1 /* 2 * Copyright (C) 2006 Kyma Systems. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Kyma Systems. 16 * 4. The name of Kyma Systems may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY KYMA SYSTEMS ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL KYMA BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* Early serial console driver for the G5, uses the 970's Real Mode 32 * Cache Inhibited Mode (RMCI) to do cache inhibited I/O. This console 33 * is used until the real console (either ofcons or zsc) is initialized 34 * after the pmap layer is up 35 */ 36 37 #include <sys/cdefs.h> 38 #include <sys/param.h> 39 #include <sys/conf.h> 40 #include <dev/cons.h> 41 #include <sys/tty.h> 42 #include <powerpc/cpu.h> 43 44 #if defined (PMAC_G5) 45 extern void mfhid4(volatile uint64_t * ret_hid4); 46 extern void mthid4(volatile uint64_t * hid4); 47 48 /* Local functions */ 49 static unsigned char RMCI_readb(volatile unsigned char *addr); 50 static void RMCI_writeb(unsigned char data, volatile unsigned char *addr); 51 52 #define SCC_TXRDY 4 53 #define SCC_RXRDY 1 54 #define HID4_RMCI 0x0000010000000000ULL 55 56 static volatile unsigned char *sccc = (volatile unsigned char *) 0x80013020ul; 57 static volatile unsigned char *sccd = (volatile unsigned char *) 0x80013030ul; 58 59 static unsigned char 60 RMCI_readb(volatile unsigned char *addr) 61 { 62 uint32_t omsr, rmsr; 63 uint64_t ohid, rhid; 64 uint8_t c; 65 66 /* Switch to RMCI */ 67 mfhid4(&ohid); 68 rhid = ohid | HID4_RMCI; 69 mthid4(&rhid); 70 71 /* Switch to real data accesses */ 72 asm volatile ("mfmsr %0":"=r" (omsr)); 73 rmsr = omsr & ~(PSL_DR); 74 asm volatile ("sync; mtmsr %0; sync; isync"::"r" (rmsr)); 75 76 /* Read byte */ 77 c = *addr; 78 __asm__ __volatile__("sync"); 79 80 /* Restore MSR */ 81 asm volatile ("sync; mtmsr %0; sync; isync"::"r" (omsr)); 82 83 /* Restore HID4 */ 84 mthid4(&ohid); 85 86 return c; 87 } 88 89 static void 90 RMCI_writeb(unsigned char data, volatile unsigned char *addr) 91 { 92 uint32_t omsr, rmsr; 93 uint64_t ohid, rhid; 94 95 /* Switch to RMCI */ 96 mfhid4(&ohid); 97 rhid = ohid | HID4_RMCI; 98 mthid4(&rhid); 99 100 /* Switch to real data accesses */ 101 asm volatile ("mfmsr %0":"=r" (omsr)); 102 rmsr = omsr & ~(PSL_DR); 103 asm volatile ("sync; mtmsr %0; sync; isync"::"r" (rmsr)); 104 105 /* Write data */ 106 *addr = data; 107 __asm__ __volatile__("sync"); 108 109 /* Restore MSR */ 110 asm volatile ("sync; mtmsr %0; sync; isync"::"r" (omsr)); 111 112 /* Restore HID4 */ 113 mthid4(&ohid); 114 return; 115 } 116 117 static void 118 failsafe_putc(dev_t dev, int c) 119 { 120 char ch = c; 121 122 while ((RMCI_readb(sccc) & SCC_TXRDY) == 0); 123 RMCI_writeb(ch, sccd); 124 return; 125 } 126 127 static int 128 failsafe_getc(dev_t dev) 129 { 130 char ch = '\0'; 131 while ((RMCI_readb(sccc) & SCC_RXRDY) == 0); 132 133 ch = RMCI_readb(sccd); 134 return ch; 135 } 136 137 138 static void 139 failsafe_probe(struct consdev *cd) 140 { 141 cd->cn_pri = CN_REMOTE; 142 } 143 144 static void 145 failsafe_init(struct consdev *cd) 146 { 147 } 148 149 static void 150 failsafe_pollc(dev_t dev, int on) 151 { 152 } 153 154 155 struct consdev failsafe_cons = { 156 failsafe_probe, 157 failsafe_init, 158 failsafe_getc, 159 failsafe_putc, 160 failsafe_pollc, 161 NULL, 162 }; 163 164 #endif /* PMAC_G5 */ 165