2 * SMC 37C93X initialization code
5 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/delay.h>
11 #include <asm/hwrpb.h>
13 #include <asm/segment.h>
18 # define DBG_DEVS(args) printk args
20 # define DBG_DEVS(args)
27 /* device "activate" register contents */
31 /* configuration on/off keys */
32 #define CONFIG_ON_KEY 0x55
33 #define CONFIG_OFF_KEY 0xaa
35 /* configuration space device definitions */
46 /* Chip register offsets from base */
47 #define CONFIG_CONTROL 0x02
48 #define INDEX_ADDRESS 0x03
49 #define LOGICAL_DEVICE_NUMBER 0x07
50 #define DEVICE_ID 0x20
51 #define DEVICE_REV 0x21
52 #define POWER_CONTROL 0x22
53 #define POWER_MGMT 0x23
59 #define INTERRUPT_SEL 0x70
60 #define INTERRUPT_SEL_2 0x72 /* KYBD/MOUS only */
61 #define DMA_CHANNEL_SEL 0x74 /* FDC/PARP only */
63 #define FDD_MODE_REGISTER 0x90
64 #define FDD_OPTION_REGISTER 0x91
66 /* values that we read back that are expected ... */
67 #define VALID_DEVICE_ID 2
69 /* default device addresses */
70 #define KYBD_INTERRUPT 1
71 #define MOUS_INTERRUPT 12
72 #define COM2_BASE 0x2f8
73 #define COM2_INTERRUPT 3
74 #define COM1_BASE 0x3f8
75 #define COM1_INTERRUPT 4
76 #define PARP_BASE 0x3bc
77 #define PARP_INTERRUPT 7
79 static unsigned long __init
SMCConfigState(unsigned long baseAddr
)
83 unsigned long configPort
;
84 unsigned long indexPort
;
85 unsigned long dataPort
;
89 configPort
= indexPort
= baseAddr
;
90 dataPort
= configPort
+ 1;
94 for (i
= 0; i
< NUM_RETRIES
; i
++)
96 outb(CONFIG_ON_KEY
, configPort
);
97 outb(CONFIG_ON_KEY
, configPort
);
98 outb(DEVICE_ID
, indexPort
);
99 devId
= inb(dataPort
);
100 if (devId
== VALID_DEVICE_ID
) {
101 outb(DEVICE_REV
, indexPort
);
102 /* unsigned char devRev = */ inb(dataPort
);
108 return (i
!= NUM_RETRIES
) ? baseAddr
: 0L;
111 static void __init
SMCRunState(unsigned long baseAddr
)
113 outb(CONFIG_OFF_KEY
, baseAddr
);
116 static unsigned long __init
SMCDetectUltraIO(void)
118 unsigned long baseAddr
;
121 if ( ( baseAddr
= SMCConfigState( baseAddr
) ) == 0x3F0 ) {
125 if ( ( baseAddr
= SMCConfigState( baseAddr
) ) == 0x370 ) {
128 return( ( unsigned long )0 );
131 static void __init
SMCEnableDevice(unsigned long baseAddr
,
132 unsigned long device
,
133 unsigned long portaddr
,
134 unsigned long interrupt
)
136 unsigned long indexPort
;
137 unsigned long dataPort
;
139 indexPort
= baseAddr
;
140 dataPort
= baseAddr
+ 1;
142 outb(LOGICAL_DEVICE_NUMBER
, indexPort
);
143 outb(device
, dataPort
);
145 outb(ADDR_LO
, indexPort
);
146 outb(( portaddr
& 0xFF ), dataPort
);
148 outb(ADDR_HI
, indexPort
);
149 outb((portaddr
>> 8) & 0xFF, dataPort
);
151 outb(INTERRUPT_SEL
, indexPort
);
152 outb(interrupt
, dataPort
);
154 outb(ACTIVATE
, indexPort
);
155 outb(DEVICE_ON
, dataPort
);
158 static void __init
SMCEnableKYBD(unsigned long baseAddr
)
160 unsigned long indexPort
;
161 unsigned long dataPort
;
163 indexPort
= baseAddr
;
164 dataPort
= baseAddr
+ 1;
166 outb(LOGICAL_DEVICE_NUMBER
, indexPort
);
167 outb(KYBD
, dataPort
);
169 outb(INTERRUPT_SEL
, indexPort
); /* Primary interrupt select */
170 outb(KYBD_INTERRUPT
, dataPort
);
172 outb(INTERRUPT_SEL_2
, indexPort
); /* Secondary interrupt select */
173 outb(MOUS_INTERRUPT
, dataPort
);
175 outb(ACTIVATE
, indexPort
);
176 outb(DEVICE_ON
, dataPort
);
179 static void __init
SMCEnableFDC(unsigned long baseAddr
)
181 unsigned long indexPort
;
182 unsigned long dataPort
;
184 unsigned char oldValue
;
186 indexPort
= baseAddr
;
187 dataPort
= baseAddr
+ 1;
189 outb(LOGICAL_DEVICE_NUMBER
, indexPort
);
192 outb(FDD_MODE_REGISTER
, indexPort
);
193 oldValue
= inb(dataPort
);
195 oldValue
|= 0x0E; /* Enable burst mode */
196 outb(oldValue
, dataPort
);
198 outb(INTERRUPT_SEL
, indexPort
); /* Primary interrupt select */
199 outb(0x06, dataPort
);
201 outb(DMA_CHANNEL_SEL
, indexPort
); /* DMA channel select */
202 outb(0x02, dataPort
);
204 outb(ACTIVATE
, indexPort
);
205 outb(DEVICE_ON
, dataPort
);
209 static void __init
SMCReportDeviceStatus(unsigned long baseAddr
)
211 unsigned long indexPort
;
212 unsigned long dataPort
;
213 unsigned char currentControl
;
215 indexPort
= baseAddr
;
216 dataPort
= baseAddr
+ 1;
218 outb(POWER_CONTROL
, indexPort
);
219 currentControl
= inb(dataPort
);
221 printk(currentControl
& (1 << FDC
)
222 ? "\t+FDC Enabled\n" : "\t-FDC Disabled\n");
223 printk(currentControl
& (1 << IDE1
)
224 ? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n");
225 printk(currentControl
& (1 << IDE2
)
226 ? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n");
227 printk(currentControl
& (1 << PARP
)
228 ? "\t+PARP Enabled\n" : "\t-PARP Disabled\n");
229 printk(currentControl
& (1 << SER1
)
230 ? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n");
231 printk(currentControl
& (1 << SER2
)
232 ? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n");
238 int __init
SMC93x_Init(void)
240 unsigned long SMCUltraBase
;
243 local_irq_save(flags
);
244 if ((SMCUltraBase
= SMCDetectUltraIO()) != 0UL) {
246 SMCReportDeviceStatus(SMCUltraBase
);
248 SMCEnableDevice(SMCUltraBase
, SER1
, COM1_BASE
, COM1_INTERRUPT
);
249 DBG_DEVS(("SMC FDC37C93X: SER1 done\n"));
250 SMCEnableDevice(SMCUltraBase
, SER2
, COM2_BASE
, COM2_INTERRUPT
);
251 DBG_DEVS(("SMC FDC37C93X: SER2 done\n"));
252 SMCEnableDevice(SMCUltraBase
, PARP
, PARP_BASE
, PARP_INTERRUPT
);
253 DBG_DEVS(("SMC FDC37C93X: PARP done\n"));
254 /* On PC164, IDE on the SMC is not enabled;
255 CMD646 (PCI) on MB */
256 SMCEnableKYBD(SMCUltraBase
);
257 DBG_DEVS(("SMC FDC37C93X: KYB done\n"));
258 SMCEnableFDC(SMCUltraBase
);
259 DBG_DEVS(("SMC FDC37C93X: FDC done\n"));
261 SMCReportDeviceStatus(SMCUltraBase
);
263 SMCRunState(SMCUltraBase
);
264 local_irq_restore(flags
);
265 printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n",
270 local_irq_restore(flags
);
271 DBG_DEVS(("No SMC FDC37C93X Ultra I/O Controller found\n"));