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 43 #include <powerpc/cpu.h> 44 #include <machine/psl.h> 45 46 #if defined (PMAC_G5) 47 extern void mfhid4(volatile uint64_t * ret_hid4); 48 extern void mthid4(volatile uint64_t * hid4); 49 50 /* Local functions */ 51 static unsigned char RMCI_readb(volatile unsigned char *addr); 52 static void RMCI_writeb(unsigned char data, volatile unsigned char *addr); 53 54 #define SCC_TXRDY 4 55 #define SCC_RXRDY 1 56 #define HID4_RMCI 0x0000010000000000ULL 57 58 static volatile unsigned char *sccc = (volatile unsigned char *) 0x80013020ul; 59 static volatile unsigned char *sccd = (volatile unsigned char *) 0x80013030ul; 60 61 static unsigned char 62 RMCI_readb(volatile unsigned char *addr) 63 { 64 uint32_t omsr, rmsr; 65 uint64_t ohid, rhid; 66 uint8_t c; 67 68 /* Switch to RMCI */ 69 mfhid4(&ohid); 70 rhid = ohid | HID4_RMCI; 71 mthid4(&rhid); 72 73 /* Switch to real data accesses */ 74 asm volatile ("mfmsr %0":"=r" (omsr)); 75 rmsr = omsr & ~(PSL_DR); 76 asm volatile ("sync; mtmsr %0; sync; isync"::"r" (rmsr)); 77 78 /* Read byte */ 79 c = *addr; 80 __asm__ __volatile__("sync"); 81 82 /* Restore MSR */ 83 asm volatile ("sync; mtmsr %0; sync; isync"::"r" (omsr)); 84 85 /* Restore HID4 */ 86 mthid4(&ohid); 87 88 return c; 89 } 90 91 static void 92 RMCI_writeb(unsigned char data, volatile unsigned char *addr) 93 { 94 uint32_t omsr, rmsr; 95 uint64_t ohid, rhid; 96 97 /* Switch to RMCI */ 98 mfhid4(&ohid); 99 rhid = ohid | HID4_RMCI; 100 mthid4(&rhid); 101 102 /* Switch to real data accesses */ 103 asm volatile ("mfmsr %0":"=r" (omsr)); 104 rmsr = omsr & ~(PSL_DR); 105 asm volatile ("sync; mtmsr %0; sync; isync"::"r" (rmsr)); 106 107 /* Write data */ 108 *addr = data; 109 __asm__ __volatile__("sync"); 110 111 /* Restore MSR */ 112 asm volatile ("sync; mtmsr %0; sync; isync"::"r" (omsr)); 113 114 /* Restore HID4 */ 115 mthid4(&ohid); 116 return; 117 } 118 119 static void 120 failsafe_putc(dev_t dev, int c) 121 { 122 char ch = c; 123 124 while ((RMCI_readb(sccc) & SCC_TXRDY) == 0); 125 RMCI_writeb(ch, sccd); 126 return; 127 } 128 129 static int 130 failsafe_getc(dev_t dev) 131 { 132 char ch = '\0'; 133 while ((RMCI_readb(sccc) & SCC_RXRDY) == 0); 134 135 ch = RMCI_readb(sccd); 136 return ch; 137 } 138 139 140 static void 141 failsafe_probe(struct consdev *cd) 142 { 143 cd->cn_pri = CN_REMOTE; 144 } 145 146 static void 147 failsafe_init(struct consdev *cd) 148 { 149 } 150 151 static void 152 failsafe_pollc(dev_t dev, int on) 153 { 154 } 155 156 157 struct consdev failsafe_cons = { 158 failsafe_probe, 159 failsafe_init, 160 failsafe_getc, 161 failsafe_putc, 162 failsafe_pollc, 163 NULL, 164 }; 165 166 #endif /* PMAC_G5 */ 167