• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/alpha/kernel/
1/*
2 * SMC 37C93X initialization code
3 */
4
5#include <linux/kernel.h>
6
7#include <linux/mm.h>
8#include <linux/init.h>
9#include <linux/delay.h>
10
11#include <asm/hwrpb.h>
12#include <asm/io.h>
13#include <asm/segment.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
79static unsigned long __init SMCConfigState(unsigned long baseAddr)
80{
81	unsigned char devId;
82	unsigned char devRev;
83
84	unsigned long configPort;
85	unsigned long indexPort;
86	unsigned long dataPort;
87
88	int i;
89
90	configPort = indexPort = baseAddr;
91	dataPort = configPort + 1;
92
93#define NUM_RETRIES 5
94
95	for (i = 0; i < NUM_RETRIES; i++)
96	{
97		outb(CONFIG_ON_KEY, configPort);
98		outb(CONFIG_ON_KEY, configPort);
99		outb(DEVICE_ID, indexPort);
100		devId = inb(dataPort);
101		if (devId == VALID_DEVICE_ID) {
102			outb(DEVICE_REV, indexPort);
103			devRev = inb(dataPort);
104			break;
105		}
106		else
107			udelay(100);
108	}
109	return (i != NUM_RETRIES) ? baseAddr : 0L;
110}
111
112static void __init SMCRunState(unsigned long baseAddr)
113{
114	outb(CONFIG_OFF_KEY, baseAddr);
115}
116
117static unsigned long __init SMCDetectUltraIO(void)
118{
119	unsigned long baseAddr;
120
121	baseAddr = 0x3F0;
122	if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) {
123		return( baseAddr );
124	}
125	baseAddr = 0x370;
126	if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) {
127		return( baseAddr );
128	}
129	return( ( unsigned long )0 );
130}
131
132static void __init SMCEnableDevice(unsigned long baseAddr,
133			    unsigned long device,
134			    unsigned long portaddr,
135			    unsigned long interrupt)
136{
137	unsigned long indexPort;
138	unsigned long dataPort;
139
140	indexPort = baseAddr;
141	dataPort = baseAddr + 1;
142
143	outb(LOGICAL_DEVICE_NUMBER, indexPort);
144	outb(device, dataPort);
145
146	outb(ADDR_LO, indexPort);
147	outb(( portaddr & 0xFF ), dataPort);
148
149	outb(ADDR_HI, indexPort);
150	outb((portaddr >> 8) & 0xFF, dataPort);
151
152	outb(INTERRUPT_SEL, indexPort);
153	outb(interrupt, dataPort);
154
155	outb(ACTIVATE, indexPort);
156	outb(DEVICE_ON, dataPort);
157}
158
159static void __init SMCEnableKYBD(unsigned long baseAddr)
160{
161	unsigned long indexPort;
162	unsigned long dataPort;
163
164	indexPort = baseAddr;
165	dataPort = baseAddr + 1;
166
167	outb(LOGICAL_DEVICE_NUMBER, indexPort);
168	outb(KYBD, dataPort);
169
170	outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */
171	outb(KYBD_INTERRUPT, dataPort);
172
173	outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */
174	outb(MOUS_INTERRUPT, dataPort);
175
176	outb(ACTIVATE, indexPort);
177	outb(DEVICE_ON, dataPort);
178}
179
180static void __init SMCEnableFDC(unsigned long baseAddr)
181{
182	unsigned long indexPort;
183	unsigned long dataPort;
184
185	unsigned char oldValue;
186
187	indexPort = baseAddr;
188	dataPort = baseAddr + 1;
189
190	outb(LOGICAL_DEVICE_NUMBER, indexPort);
191	outb(FDC, dataPort);
192
193	outb(FDD_MODE_REGISTER, indexPort);
194	oldValue = inb(dataPort);
195
196	oldValue |= 0x0E;                   /* Enable burst mode */
197	outb(oldValue, dataPort);
198
199	outb(INTERRUPT_SEL, indexPort);	    /* Primary interrupt select */
200	outb(0x06, dataPort );
201
202	outb(DMA_CHANNEL_SEL, indexPort);   /* DMA channel select */
203	outb(0x02, dataPort);
204
205	outb(ACTIVATE, indexPort);
206	outb(DEVICE_ON, dataPort);
207}
208
209#if SMC_DEBUG
210static void __init SMCReportDeviceStatus(unsigned long baseAddr)
211{
212	unsigned long indexPort;
213	unsigned long dataPort;
214	unsigned char currentControl;
215
216	indexPort = baseAddr;
217	dataPort = baseAddr + 1;
218
219	outb(POWER_CONTROL, indexPort);
220	currentControl = inb(dataPort);
221
222	printk(currentControl & (1 << FDC)
223	       ? "\t+FDC Enabled\n" : "\t-FDC Disabled\n");
224	printk(currentControl & (1 << IDE1)
225	       ? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n");
226	printk(currentControl & (1 << IDE2)
227	       ? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n");
228	printk(currentControl & (1 << PARP)
229	       ? "\t+PARP Enabled\n" : "\t-PARP Disabled\n");
230	printk(currentControl & (1 << SER1)
231	       ? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n");
232	printk(currentControl & (1 << SER2)
233	       ? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n");
234
235	printk( "\n" );
236}
237#endif
238
239int __init SMC93x_Init(void)
240{
241	unsigned long SMCUltraBase;
242	unsigned long flags;
243
244	local_irq_save(flags);
245	if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) {
246#if SMC_DEBUG
247		SMCReportDeviceStatus(SMCUltraBase);
248#endif
249		SMCEnableDevice(SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT);
250		DBG_DEVS(("SMC FDC37C93X: SER1 done\n"));
251		SMCEnableDevice(SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT);
252		DBG_DEVS(("SMC FDC37C93X: SER2 done\n"));
253		SMCEnableDevice(SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT);
254		DBG_DEVS(("SMC FDC37C93X: PARP done\n"));
255		/* On PC164, IDE on the SMC is not enabled;
256		   CMD646 (PCI) on MB */
257		SMCEnableKYBD(SMCUltraBase);
258		DBG_DEVS(("SMC FDC37C93X: KYB done\n"));
259		SMCEnableFDC(SMCUltraBase);
260		DBG_DEVS(("SMC FDC37C93X: FDC done\n"));
261#if SMC_DEBUG
262		SMCReportDeviceStatus(SMCUltraBase);
263#endif
264		SMCRunState(SMCUltraBase);
265		local_irq_restore(flags);
266		printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n",
267		       SMCUltraBase);
268		return 1;
269	}
270	else {
271		local_irq_restore(flags);
272		DBG_DEVS(("No SMC FDC37C93X Ultra I/O Controller found\n"));
273		return 0;
274	}
275}
276