1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 /* 2 /* 3 * SMC 37C93X initialization code 3 * SMC 37C93X initialization code 4 */ 4 */ 5 5 6 #include <linux/kernel.h> 6 #include <linux/kernel.h> 7 7 8 #include <linux/mm.h> 8 #include <linux/mm.h> 9 #include <linux/init.h> 9 #include <linux/init.h> 10 #include <linux/delay.h> 10 #include <linux/delay.h> 11 11 12 #include <asm/hwrpb.h> 12 #include <asm/hwrpb.h> 13 #include <asm/io.h> 13 #include <asm/io.h> 14 14 15 #include "proto.h" 15 #include "proto.h" 16 16 17 #define SMC_DEBUG 0 17 #define SMC_DEBUG 0 18 18 19 #if SMC_DEBUG 19 #if SMC_DEBUG 20 # define DBG_DEVS(args) printk args 20 # define DBG_DEVS(args) printk args 21 #else 21 #else 22 # define DBG_DEVS(args) 22 # define DBG_DEVS(args) 23 #endif 23 #endif 24 24 25 #define KB 1024 25 #define KB 1024 26 #define MB (1024*KB) 26 #define MB (1024*KB) 27 #define GB (1024*MB) 27 #define GB (1024*MB) 28 28 29 /* device "activate" register contents */ 29 /* device "activate" register contents */ 30 #define DEVICE_ON 1 30 #define DEVICE_ON 1 31 #define DEVICE_OFF 0 31 #define DEVICE_OFF 0 32 32 33 /* configuration on/off keys */ 33 /* configuration on/off keys */ 34 #define CONFIG_ON_KEY 0x55 34 #define CONFIG_ON_KEY 0x55 35 #define CONFIG_OFF_KEY 0xaa 35 #define CONFIG_OFF_KEY 0xaa 36 36 37 /* configuration space device definitions */ 37 /* configuration space device definitions */ 38 #define FDC 0 38 #define FDC 0 39 #define IDE1 1 39 #define IDE1 1 40 #define IDE2 2 40 #define IDE2 2 41 #define PARP 3 41 #define PARP 3 42 #define SER1 4 42 #define SER1 4 43 #define SER2 5 43 #define SER2 5 44 #define RTCL 6 44 #define RTCL 6 45 #define KYBD 7 45 #define KYBD 7 46 #define AUXIO 8 46 #define AUXIO 8 47 47 48 /* Chip register offsets from base */ 48 /* Chip register offsets from base */ 49 #define CONFIG_CONTROL 0x02 49 #define CONFIG_CONTROL 0x02 50 #define INDEX_ADDRESS 0x03 50 #define INDEX_ADDRESS 0x03 51 #define LOGICAL_DEVICE_NUMBER 0x07 51 #define LOGICAL_DEVICE_NUMBER 0x07 52 #define DEVICE_ID 0x20 52 #define DEVICE_ID 0x20 53 #define DEVICE_REV 0x21 53 #define DEVICE_REV 0x21 54 #define POWER_CONTROL 0x22 54 #define POWER_CONTROL 0x22 55 #define POWER_MGMT 0x23 55 #define POWER_MGMT 0x23 56 #define OSC 0x24 56 #define OSC 0x24 57 57 58 #define ACTIVATE 0x30 58 #define ACTIVATE 0x30 59 #define ADDR_HI 0x60 59 #define ADDR_HI 0x60 60 #define ADDR_LO 0x61 60 #define ADDR_LO 0x61 61 #define INTERRUPT_SEL 0x70 61 #define INTERRUPT_SEL 0x70 62 #define INTERRUPT_SEL_2 0x72 /* KYBD/M 62 #define INTERRUPT_SEL_2 0x72 /* KYBD/MOUS only */ 63 #define DMA_CHANNEL_SEL 0x74 /* FDC/PA 63 #define DMA_CHANNEL_SEL 0x74 /* FDC/PARP only */ 64 64 65 #define FDD_MODE_REGISTER 0x90 65 #define FDD_MODE_REGISTER 0x90 66 #define FDD_OPTION_REGISTER 0x91 66 #define FDD_OPTION_REGISTER 0x91 67 67 68 /* values that we read back that are expected 68 /* values that we read back that are expected ... */ 69 #define VALID_DEVICE_ID 2 69 #define VALID_DEVICE_ID 2 70 70 71 /* default device addresses */ 71 /* default device addresses */ 72 #define KYBD_INTERRUPT 1 72 #define KYBD_INTERRUPT 1 73 #define MOUS_INTERRUPT 12 73 #define MOUS_INTERRUPT 12 74 #define COM2_BASE 0x2f8 74 #define COM2_BASE 0x2f8 75 #define COM2_INTERRUPT 3 75 #define COM2_INTERRUPT 3 76 #define COM1_BASE 0x3f8 76 #define COM1_BASE 0x3f8 77 #define COM1_INTERRUPT 4 77 #define COM1_INTERRUPT 4 78 #define PARP_BASE 0x3bc 78 #define PARP_BASE 0x3bc 79 #define PARP_INTERRUPT 7 79 #define PARP_INTERRUPT 7 80 80 81 static unsigned long __init SMCConfigState(uns 81 static unsigned long __init SMCConfigState(unsigned long baseAddr) 82 { 82 { 83 unsigned char devId; 83 unsigned char devId; 84 84 85 unsigned long configPort; 85 unsigned long configPort; 86 unsigned long indexPort; 86 unsigned long indexPort; 87 unsigned long dataPort; 87 unsigned long dataPort; 88 88 89 int i; 89 int i; 90 90 91 configPort = indexPort = baseAddr; 91 configPort = indexPort = baseAddr; 92 dataPort = configPort + 1; 92 dataPort = configPort + 1; 93 93 94 #define NUM_RETRIES 5 94 #define NUM_RETRIES 5 95 95 96 for (i = 0; i < NUM_RETRIES; i++) 96 for (i = 0; i < NUM_RETRIES; i++) 97 { 97 { 98 outb(CONFIG_ON_KEY, configPort 98 outb(CONFIG_ON_KEY, configPort); 99 outb(CONFIG_ON_KEY, configPort 99 outb(CONFIG_ON_KEY, configPort); 100 outb(DEVICE_ID, indexPort); 100 outb(DEVICE_ID, indexPort); 101 devId = inb(dataPort); 101 devId = inb(dataPort); 102 if (devId == VALID_DEVICE_ID) 102 if (devId == VALID_DEVICE_ID) { 103 outb(DEVICE_REV, index 103 outb(DEVICE_REV, indexPort); 104 /* unsigned char devRe 104 /* unsigned char devRev = */ inb(dataPort); 105 break; 105 break; 106 } 106 } 107 else 107 else 108 udelay(100); 108 udelay(100); 109 } 109 } 110 return (i != NUM_RETRIES) ? baseAddr : 110 return (i != NUM_RETRIES) ? baseAddr : 0L; 111 } 111 } 112 112 113 static void __init SMCRunState(unsigned long b 113 static void __init SMCRunState(unsigned long baseAddr) 114 { 114 { 115 outb(CONFIG_OFF_KEY, baseAddr); 115 outb(CONFIG_OFF_KEY, baseAddr); 116 } 116 } 117 117 118 static unsigned long __init SMCDetectUltraIO(v 118 static unsigned long __init SMCDetectUltraIO(void) 119 { 119 { 120 unsigned long baseAddr; 120 unsigned long baseAddr; 121 121 122 baseAddr = 0x3F0; 122 baseAddr = 0x3F0; 123 if ( ( baseAddr = SMCConfigState( base 123 if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) { 124 return( baseAddr ); 124 return( baseAddr ); 125 } 125 } 126 baseAddr = 0x370; 126 baseAddr = 0x370; 127 if ( ( baseAddr = SMCConfigState( base 127 if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) { 128 return( baseAddr ); 128 return( baseAddr ); 129 } 129 } 130 return( ( unsigned long )0 ); 130 return( ( unsigned long )0 ); 131 } 131 } 132 132 133 static void __init SMCEnableDevice(unsigned lo 133 static void __init SMCEnableDevice(unsigned long baseAddr, 134 unsigned long devi 134 unsigned long device, 135 unsigned long port 135 unsigned long portaddr, 136 unsigned long inte 136 unsigned long interrupt) 137 { 137 { 138 unsigned long indexPort; 138 unsigned long indexPort; 139 unsigned long dataPort; 139 unsigned long dataPort; 140 140 141 indexPort = baseAddr; 141 indexPort = baseAddr; 142 dataPort = baseAddr + 1; 142 dataPort = baseAddr + 1; 143 143 144 outb(LOGICAL_DEVICE_NUMBER, indexPort) 144 outb(LOGICAL_DEVICE_NUMBER, indexPort); 145 outb(device, dataPort); 145 outb(device, dataPort); 146 146 147 outb(ADDR_LO, indexPort); 147 outb(ADDR_LO, indexPort); 148 outb(( portaddr & 0xFF ), dataPort); 148 outb(( portaddr & 0xFF ), dataPort); 149 149 150 outb(ADDR_HI, indexPort); 150 outb(ADDR_HI, indexPort); 151 outb((portaddr >> 8) & 0xFF, dataPort) 151 outb((portaddr >> 8) & 0xFF, dataPort); 152 152 153 outb(INTERRUPT_SEL, indexPort); 153 outb(INTERRUPT_SEL, indexPort); 154 outb(interrupt, dataPort); 154 outb(interrupt, dataPort); 155 155 156 outb(ACTIVATE, indexPort); 156 outb(ACTIVATE, indexPort); 157 outb(DEVICE_ON, dataPort); 157 outb(DEVICE_ON, dataPort); 158 } 158 } 159 159 160 static void __init SMCEnableKYBD(unsigned long 160 static void __init SMCEnableKYBD(unsigned long baseAddr) 161 { 161 { 162 unsigned long indexPort; 162 unsigned long indexPort; 163 unsigned long dataPort; 163 unsigned long dataPort; 164 164 165 indexPort = baseAddr; 165 indexPort = baseAddr; 166 dataPort = baseAddr + 1; 166 dataPort = baseAddr + 1; 167 167 168 outb(LOGICAL_DEVICE_NUMBER, indexPort) 168 outb(LOGICAL_DEVICE_NUMBER, indexPort); 169 outb(KYBD, dataPort); 169 outb(KYBD, dataPort); 170 170 171 outb(INTERRUPT_SEL, indexPort); /* Pri 171 outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */ 172 outb(KYBD_INTERRUPT, dataPort); 172 outb(KYBD_INTERRUPT, dataPort); 173 173 174 outb(INTERRUPT_SEL_2, indexPort); /* S 174 outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */ 175 outb(MOUS_INTERRUPT, dataPort); 175 outb(MOUS_INTERRUPT, dataPort); 176 176 177 outb(ACTIVATE, indexPort); 177 outb(ACTIVATE, indexPort); 178 outb(DEVICE_ON, dataPort); 178 outb(DEVICE_ON, dataPort); 179 } 179 } 180 180 181 static void __init SMCEnableFDC(unsigned long 181 static void __init SMCEnableFDC(unsigned long baseAddr) 182 { 182 { 183 unsigned long indexPort; 183 unsigned long indexPort; 184 unsigned long dataPort; 184 unsigned long dataPort; 185 185 186 unsigned char oldValue; 186 unsigned char oldValue; 187 187 188 indexPort = baseAddr; 188 indexPort = baseAddr; 189 dataPort = baseAddr + 1; 189 dataPort = baseAddr + 1; 190 190 191 outb(LOGICAL_DEVICE_NUMBER, indexPort) 191 outb(LOGICAL_DEVICE_NUMBER, indexPort); 192 outb(FDC, dataPort); 192 outb(FDC, dataPort); 193 193 194 outb(FDD_MODE_REGISTER, indexPort); 194 outb(FDD_MODE_REGISTER, indexPort); 195 oldValue = inb(dataPort); 195 oldValue = inb(dataPort); 196 196 197 oldValue |= 0x0E; /* 197 oldValue |= 0x0E; /* Enable burst mode */ 198 outb(oldValue, dataPort); 198 outb(oldValue, dataPort); 199 199 200 outb(INTERRUPT_SEL, indexPort); /* 200 outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */ 201 outb(0x06, dataPort ); 201 outb(0x06, dataPort ); 202 202 203 outb(DMA_CHANNEL_SEL, indexPort); /* 203 outb(DMA_CHANNEL_SEL, indexPort); /* DMA channel select */ 204 outb(0x02, dataPort); 204 outb(0x02, dataPort); 205 205 206 outb(ACTIVATE, indexPort); 206 outb(ACTIVATE, indexPort); 207 outb(DEVICE_ON, dataPort); 207 outb(DEVICE_ON, dataPort); 208 } 208 } 209 209 210 #if SMC_DEBUG 210 #if SMC_DEBUG 211 static void __init SMCReportDeviceStatus(unsig 211 static void __init SMCReportDeviceStatus(unsigned long baseAddr) 212 { 212 { 213 unsigned long indexPort; 213 unsigned long indexPort; 214 unsigned long dataPort; 214 unsigned long dataPort; 215 unsigned char currentControl; 215 unsigned char currentControl; 216 216 217 indexPort = baseAddr; 217 indexPort = baseAddr; 218 dataPort = baseAddr + 1; 218 dataPort = baseAddr + 1; 219 219 220 outb(POWER_CONTROL, indexPort); 220 outb(POWER_CONTROL, indexPort); 221 currentControl = inb(dataPort); 221 currentControl = inb(dataPort); 222 222 223 printk(currentControl & (1 << FDC) 223 printk(currentControl & (1 << FDC) 224 ? "\t+FDC Enabled\n" : "\t-FDC 224 ? "\t+FDC Enabled\n" : "\t-FDC Disabled\n"); 225 printk(currentControl & (1 << IDE1) 225 printk(currentControl & (1 << IDE1) 226 ? "\t+IDE1 Enabled\n" : "\t-IDE 226 ? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n"); 227 printk(currentControl & (1 << IDE2) 227 printk(currentControl & (1 << IDE2) 228 ? "\t+IDE2 Enabled\n" : "\t-IDE 228 ? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n"); 229 printk(currentControl & (1 << PARP) 229 printk(currentControl & (1 << PARP) 230 ? "\t+PARP Enabled\n" : "\t-PAR 230 ? "\t+PARP Enabled\n" : "\t-PARP Disabled\n"); 231 printk(currentControl & (1 << SER1) 231 printk(currentControl & (1 << SER1) 232 ? "\t+SER1 Enabled\n" : "\t-SER 232 ? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n"); 233 printk(currentControl & (1 << SER2) 233 printk(currentControl & (1 << SER2) 234 ? "\t+SER2 Enabled\n" : "\t-SER 234 ? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n"); 235 235 236 printk( "\n" ); 236 printk( "\n" ); 237 } 237 } 238 #endif 238 #endif 239 239 240 int __init SMC93x_Init(void) 240 int __init SMC93x_Init(void) 241 { 241 { 242 unsigned long SMCUltraBase; 242 unsigned long SMCUltraBase; 243 unsigned long flags; 243 unsigned long flags; 244 244 245 local_irq_save(flags); 245 local_irq_save(flags); 246 if ((SMCUltraBase = SMCDetectUltraIO() 246 if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) { 247 #if SMC_DEBUG 247 #if SMC_DEBUG 248 SMCReportDeviceStatus(SMCUltra 248 SMCReportDeviceStatus(SMCUltraBase); 249 #endif 249 #endif 250 SMCEnableDevice(SMCUltraBase, 250 SMCEnableDevice(SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT); 251 DBG_DEVS(("SMC FDC37C93X: SER1 251 DBG_DEVS(("SMC FDC37C93X: SER1 done\n")); 252 SMCEnableDevice(SMCUltraBase, 252 SMCEnableDevice(SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT); 253 DBG_DEVS(("SMC FDC37C93X: SER2 253 DBG_DEVS(("SMC FDC37C93X: SER2 done\n")); 254 SMCEnableDevice(SMCUltraBase, 254 SMCEnableDevice(SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT); 255 DBG_DEVS(("SMC FDC37C93X: PARP 255 DBG_DEVS(("SMC FDC37C93X: PARP done\n")); 256 /* On PC164, IDE on the SMC is 256 /* On PC164, IDE on the SMC is not enabled; 257 CMD646 (PCI) on MB */ 257 CMD646 (PCI) on MB */ 258 SMCEnableKYBD(SMCUltraBase); 258 SMCEnableKYBD(SMCUltraBase); 259 DBG_DEVS(("SMC FDC37C93X: KYB 259 DBG_DEVS(("SMC FDC37C93X: KYB done\n")); 260 SMCEnableFDC(SMCUltraBase); 260 SMCEnableFDC(SMCUltraBase); 261 DBG_DEVS(("SMC FDC37C93X: FDC 261 DBG_DEVS(("SMC FDC37C93X: FDC done\n")); 262 #if SMC_DEBUG 262 #if SMC_DEBUG 263 SMCReportDeviceStatus(SMCUltra 263 SMCReportDeviceStatus(SMCUltraBase); 264 #endif 264 #endif 265 SMCRunState(SMCUltraBase); 265 SMCRunState(SMCUltraBase); 266 local_irq_restore(flags); 266 local_irq_restore(flags); 267 printk("SMC FDC37C93X Ultra I/ 267 printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n", 268 SMCUltraBase); 268 SMCUltraBase); 269 return 1; 269 return 1; 270 } 270 } 271 else { 271 else { 272 local_irq_restore(flags); 272 local_irq_restore(flags); 273 DBG_DEVS(("No SMC FDC37C93X Ul 273 DBG_DEVS(("No SMC FDC37C93X Ultra I/O Controller found\n")); 274 return 0; 274 return 0; 275 } 275 } 276 } 276 } 277 277
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.