xref: /openbmc/linux/arch/alpha/kernel/smc37c93x.c (revision c39f2d9db0fd81ea20bb5cce9b3f082ca63753e2)
1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * SMC 37C93X initialization code
4   */
5  
6  #include <linux/kernel.h>
7  
8  #include <linux/mm.h>
9  #include <linux/init.h>
10  #include <linux/delay.h>
11  
12  #include <asm/hwrpb.h>
13  #include <asm/io.h>
14  
15  #define SMC_DEBUG 0
16  
17  #if SMC_DEBUG
18  # define DBG_DEVS(args)         printk args
19  #else
20  # define DBG_DEVS(args)
21  #endif
22  
23  #define KB              1024
24  #define MB              (1024*KB)
25  #define GB              (1024*MB)
26  
27  /* device "activate" register contents */
28  #define DEVICE_ON		1
29  #define DEVICE_OFF		0
30  
31  /* configuration on/off keys */
32  #define CONFIG_ON_KEY		0x55
33  #define CONFIG_OFF_KEY		0xaa
34  
35  /* configuration space device definitions */
36  #define FDC			0
37  #define IDE1			1
38  #define IDE2			2
39  #define PARP			3
40  #define SER1			4
41  #define SER2			5
42  #define RTCL			6
43  #define KYBD			7
44  #define AUXIO			8
45  
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
54  #define OSC			0x24
55  
56  #define ACTIVATE		0x30
57  #define ADDR_HI			0x60
58  #define ADDR_LO			0x61
59  #define INTERRUPT_SEL		0x70
60  #define INTERRUPT_SEL_2		0x72 /* KYBD/MOUS only */
61  #define DMA_CHANNEL_SEL		0x74 /* FDC/PARP only */
62  
63  #define FDD_MODE_REGISTER	0x90
64  #define FDD_OPTION_REGISTER	0x91
65  
66  /* values that we read back that are expected ... */
67  #define VALID_DEVICE_ID		2
68  
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
78  
SMCConfigState(unsigned long baseAddr)79  static unsigned long __init SMCConfigState(unsigned long baseAddr)
80  {
81  	unsigned char devId;
82  
83  	unsigned long configPort;
84  	unsigned long indexPort;
85  	unsigned long dataPort;
86  
87  	int i;
88  
89  	configPort = indexPort = baseAddr;
90  	dataPort = configPort + 1;
91  
92  #define NUM_RETRIES 5
93  
94  	for (i = 0; i < NUM_RETRIES; i++)
95  	{
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);
103  			break;
104  		}
105  		else
106  			udelay(100);
107  	}
108  	return (i != NUM_RETRIES) ? baseAddr : 0L;
109  }
110  
SMCRunState(unsigned long baseAddr)111  static void __init SMCRunState(unsigned long baseAddr)
112  {
113  	outb(CONFIG_OFF_KEY, baseAddr);
114  }
115  
SMCDetectUltraIO(void)116  static unsigned long __init SMCDetectUltraIO(void)
117  {
118  	unsigned long baseAddr;
119  
120  	baseAddr = 0x3F0;
121  	if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) {
122  		return( baseAddr );
123  	}
124  	baseAddr = 0x370;
125  	if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) {
126  		return( baseAddr );
127  	}
128  	return( ( unsigned long )0 );
129  }
130  
SMCEnableDevice(unsigned long baseAddr,unsigned long device,unsigned long portaddr,unsigned long interrupt)131  static void __init SMCEnableDevice(unsigned long baseAddr,
132  			    unsigned long device,
133  			    unsigned long portaddr,
134  			    unsigned long interrupt)
135  {
136  	unsigned long indexPort;
137  	unsigned long dataPort;
138  
139  	indexPort = baseAddr;
140  	dataPort = baseAddr + 1;
141  
142  	outb(LOGICAL_DEVICE_NUMBER, indexPort);
143  	outb(device, dataPort);
144  
145  	outb(ADDR_LO, indexPort);
146  	outb(( portaddr & 0xFF ), dataPort);
147  
148  	outb(ADDR_HI, indexPort);
149  	outb((portaddr >> 8) & 0xFF, dataPort);
150  
151  	outb(INTERRUPT_SEL, indexPort);
152  	outb(interrupt, dataPort);
153  
154  	outb(ACTIVATE, indexPort);
155  	outb(DEVICE_ON, dataPort);
156  }
157  
SMCEnableKYBD(unsigned long baseAddr)158  static void __init SMCEnableKYBD(unsigned long baseAddr)
159  {
160  	unsigned long indexPort;
161  	unsigned long dataPort;
162  
163  	indexPort = baseAddr;
164  	dataPort = baseAddr + 1;
165  
166  	outb(LOGICAL_DEVICE_NUMBER, indexPort);
167  	outb(KYBD, dataPort);
168  
169  	outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */
170  	outb(KYBD_INTERRUPT, dataPort);
171  
172  	outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */
173  	outb(MOUS_INTERRUPT, dataPort);
174  
175  	outb(ACTIVATE, indexPort);
176  	outb(DEVICE_ON, dataPort);
177  }
178  
SMCEnableFDC(unsigned long baseAddr)179  static void __init SMCEnableFDC(unsigned long baseAddr)
180  {
181  	unsigned long indexPort;
182  	unsigned long dataPort;
183  
184  	unsigned char oldValue;
185  
186  	indexPort = baseAddr;
187  	dataPort = baseAddr + 1;
188  
189  	outb(LOGICAL_DEVICE_NUMBER, indexPort);
190  	outb(FDC, dataPort);
191  
192  	outb(FDD_MODE_REGISTER, indexPort);
193  	oldValue = inb(dataPort);
194  
195  	oldValue |= 0x0E;                   /* Enable burst mode */
196  	outb(oldValue, dataPort);
197  
198  	outb(INTERRUPT_SEL, indexPort);	    /* Primary interrupt select */
199  	outb(0x06, dataPort );
200  
201  	outb(DMA_CHANNEL_SEL, indexPort);   /* DMA channel select */
202  	outb(0x02, dataPort);
203  
204  	outb(ACTIVATE, indexPort);
205  	outb(DEVICE_ON, dataPort);
206  }
207  
208  #if SMC_DEBUG
SMCReportDeviceStatus(unsigned long baseAddr)209  static void __init SMCReportDeviceStatus(unsigned long baseAddr)
210  {
211  	unsigned long indexPort;
212  	unsigned long dataPort;
213  	unsigned char currentControl;
214  
215  	indexPort = baseAddr;
216  	dataPort = baseAddr + 1;
217  
218  	outb(POWER_CONTROL, indexPort);
219  	currentControl = inb(dataPort);
220  
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");
233  
234  	printk( "\n" );
235  }
236  #endif
237  
SMC93x_Init(void)238  int __init SMC93x_Init(void)
239  {
240  	unsigned long SMCUltraBase;
241  	unsigned long flags;
242  
243  	local_irq_save(flags);
244  	if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) {
245  #if SMC_DEBUG
246  		SMCReportDeviceStatus(SMCUltraBase);
247  #endif
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"));
260  #if SMC_DEBUG
261  		SMCReportDeviceStatus(SMCUltraBase);
262  #endif
263  		SMCRunState(SMCUltraBase);
264  		local_irq_restore(flags);
265  		printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n",
266  		       SMCUltraBase);
267  		return 1;
268  	}
269  	else {
270  		local_irq_restore(flags);
271  		DBG_DEVS(("No SMC FDC37C93X Ultra I/O Controller found\n"));
272  		return 0;
273  	}
274  }
275