xref: /openbmc/linux/arch/sh/boards/mach-microdev/setup.c (revision 8fa5723aa7e053d498336b48448b292fc2e0458b)
1 /*
2  * arch/sh/boards/superh/microdev/setup.c
3  *
4  * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com)
5  * Copyright (C) 2003, 2004 SuperH, Inc.
6  * Copyright (C) 2004, 2005 Paul Mundt
7  *
8  * SuperH SH4-202 MicroDev board support.
9  *
10  * May be copied or modified under the terms of the GNU General Public
11  * License.  See linux/COPYING for more information.
12  */
13 #include <linux/init.h>
14 #include <linux/platform_device.h>
15 #include <linux/ioport.h>
16 #include <video/s1d13xxxfb.h>
17 #include <mach/microdev.h>
18 #include <asm/io.h>
19 #include <asm/machvec.h>
20 
21 extern void microdev_heartbeat(void);
22 
23 
24 /****************************************************************************/
25 
26 
27 	/*
28 	 * Setup for the SMSC FDC37C93xAPM
29 	 */
30 #define SMSC_CONFIG_PORT_ADDR	 (0x3F0)
31 #define SMSC_INDEX_PORT_ADDR	 SMSC_CONFIG_PORT_ADDR
32 #define SMSC_DATA_PORT_ADDR	 (SMSC_INDEX_PORT_ADDR + 1)
33 
34 #define SMSC_ENTER_CONFIG_KEY	 0x55
35 #define SMSC_EXIT_CONFIG_KEY	 0xaa
36 
37 #define SMCS_LOGICAL_DEV_INDEX 	 0x07	/* Logical Device Number */
38 #define SMSC_DEVICE_ID_INDEX	 0x20	/* Device ID */
39 #define SMSC_DEVICE_REV_INDEX	 0x21	/* Device Revision */
40 #define SMSC_ACTIVATE_INDEX	 0x30	/* Activate */
41 #define SMSC_PRIMARY_BASE_INDEX	 0x60	/* Primary Base Address */
42 #define SMSC_SECONDARY_BASE_INDEX 0x62	/* Secondary Base Address */
43 #define SMSC_PRIMARY_INT_INDEX	 0x70	/* Primary Interrupt Select */
44 #define SMSC_SECONDARY_INT_INDEX 0x72	/* Secondary Interrupt Select */
45 #define SMSC_HDCS0_INDEX	 0xf0	/* HDCS0 Address Decoder */
46 #define SMSC_HDCS1_INDEX	 0xf1	/* HDCS1 Address Decoder */
47 
48 #define SMSC_IDE1_DEVICE	1	/* IDE #1 logical device */
49 #define SMSC_IDE2_DEVICE	2	/* IDE #2 logical device */
50 #define SMSC_PARALLEL_DEVICE	3	/* Parallel Port logical device */
51 #define SMSC_SERIAL1_DEVICE	4	/* Serial #1 logical device */
52 #define SMSC_SERIAL2_DEVICE	5	/* Serial #2 logical device */
53 #define SMSC_KEYBOARD_DEVICE	7	/* Keyboard logical device */
54 #define SMSC_CONFIG_REGISTERS	8	/* Configuration Registers (Aux I/O) */
55 
56 #define SMSC_READ_INDEXED(index) ({ \
57 	outb((index), SMSC_INDEX_PORT_ADDR); \
58 	inb(SMSC_DATA_PORT_ADDR); })
59 #define SMSC_WRITE_INDEXED(val, index) ({ \
60 	outb((index), SMSC_INDEX_PORT_ADDR); \
61 	outb((val),   SMSC_DATA_PORT_ADDR); })
62 
63 #define	IDE1_PRIMARY_BASE	0x01f0	/* Task File Registe base for IDE #1 */
64 #define	IDE1_SECONDARY_BASE	0x03f6	/* Miscellaneous AT registers for IDE #1 */
65 #define	IDE2_PRIMARY_BASE	0x0170	/* Task File Registe base for IDE #2 */
66 #define	IDE2_SECONDARY_BASE	0x0376	/* Miscellaneous AT registers for IDE #2 */
67 
68 #define SERIAL1_PRIMARY_BASE	0x03f8
69 #define SERIAL2_PRIMARY_BASE	0x02f8
70 
71 #define	MSB(x)		( (x) >> 8 )
72 #define	LSB(x)		( (x) & 0xff )
73 
74 	/* General-Purpose base address on CPU-board FPGA */
75 #define	MICRODEV_FPGA_GP_BASE		0xa6100000ul
76 
77 	/* assume a Keyboard Controller is present */
78 int microdev_kbd_controller_present = 1;
79 
80 static struct resource smc91x_resources[] = {
81 	[0] = {
82 		.start		= 0x300,
83 		.end		= 0x300 + 0x0001000 - 1,
84 		.flags		= IORESOURCE_MEM,
85 	},
86 	[1] = {
87 		.start		= MICRODEV_LINUX_IRQ_ETHERNET,
88 		.end		= MICRODEV_LINUX_IRQ_ETHERNET,
89 		.flags		= IORESOURCE_IRQ,
90 	},
91 };
92 
93 static struct platform_device smc91x_device = {
94 	.name		= "smc91x",
95 	.id		= -1,
96 	.num_resources	= ARRAY_SIZE(smc91x_resources),
97 	.resource	= smc91x_resources,
98 };
99 
100 #ifdef CONFIG_FB_S1D13XXX
101 static struct s1d13xxxfb_regval s1d13806_initregs[] = {
102 	{ S1DREG_MISC,			0x00 },
103 	{ S1DREG_COM_DISP_MODE,		0x00 },
104 	{ S1DREG_GPIO_CNF0,		0x00 },
105 	{ S1DREG_GPIO_CNF1,		0x00 },
106 	{ S1DREG_GPIO_CTL0,		0x00 },
107 	{ S1DREG_GPIO_CTL1,		0x00 },
108 	{ S1DREG_CLK_CNF,		0x02 },
109 	{ S1DREG_LCD_CLK_CNF,		0x01 },
110 	{ S1DREG_CRT_CLK_CNF,		0x03 },
111 	{ S1DREG_MPLUG_CLK_CNF,		0x03 },
112 	{ S1DREG_CPU2MEM_WST_SEL,	0x02 },
113 	{ S1DREG_SDRAM_REF_RATE,	0x03 },
114 	{ S1DREG_SDRAM_TC0,		0x00 },
115 	{ S1DREG_SDRAM_TC1,		0x01 },
116 	{ S1DREG_MEM_CNF,		0x80 },
117 	{ S1DREG_PANEL_TYPE,		0x25 },
118 	{ S1DREG_MOD_RATE,		0x00 },
119 	{ S1DREG_LCD_DISP_HWIDTH,	0x63 },
120 	{ S1DREG_LCD_NDISP_HPER,	0x1e },
121 	{ S1DREG_TFT_FPLINE_START,	0x06 },
122 	{ S1DREG_TFT_FPLINE_PWIDTH,	0x03 },
123 	{ S1DREG_LCD_DISP_VHEIGHT0,	0x57 },
124 	{ S1DREG_LCD_DISP_VHEIGHT1,	0x02 },
125 	{ S1DREG_LCD_NDISP_VPER,	0x00 },
126 	{ S1DREG_TFT_FPFRAME_START,	0x0a },
127 	{ S1DREG_TFT_FPFRAME_PWIDTH,	0x81 },
128 	{ S1DREG_LCD_DISP_MODE,		0x03 },
129 	{ S1DREG_LCD_MISC,		0x00 },
130 	{ S1DREG_LCD_DISP_START0,	0x00 },
131 	{ S1DREG_LCD_DISP_START1,	0x00 },
132 	{ S1DREG_LCD_DISP_START2,	0x00 },
133 	{ S1DREG_LCD_MEM_OFF0,		0x90 },
134 	{ S1DREG_LCD_MEM_OFF1,		0x01 },
135 	{ S1DREG_LCD_PIX_PAN,		0x00 },
136 	{ S1DREG_LCD_DISP_FIFO_HTC,	0x00 },
137 	{ S1DREG_LCD_DISP_FIFO_LTC,	0x00 },
138 	{ S1DREG_CRT_DISP_HWIDTH,	0x63 },
139 	{ S1DREG_CRT_NDISP_HPER,	0x1f },
140 	{ S1DREG_CRT_HRTC_START,	0x04 },
141 	{ S1DREG_CRT_HRTC_PWIDTH,	0x8f },
142 	{ S1DREG_CRT_DISP_VHEIGHT0,	0x57 },
143 	{ S1DREG_CRT_DISP_VHEIGHT1,	0x02 },
144 	{ S1DREG_CRT_NDISP_VPER,	0x1b },
145 	{ S1DREG_CRT_VRTC_START,	0x00 },
146 	{ S1DREG_CRT_VRTC_PWIDTH,	0x83 },
147 	{ S1DREG_TV_OUT_CTL,		0x10 },
148 	{ S1DREG_CRT_DISP_MODE,		0x05 },
149 	{ S1DREG_CRT_DISP_START0,	0x00 },
150 	{ S1DREG_CRT_DISP_START1,	0x00 },
151 	{ S1DREG_CRT_DISP_START2,	0x00 },
152 	{ S1DREG_CRT_MEM_OFF0,		0x20 },
153 	{ S1DREG_CRT_MEM_OFF1,		0x03 },
154 	{ S1DREG_CRT_PIX_PAN,		0x00 },
155 	{ S1DREG_CRT_DISP_FIFO_HTC,	0x00 },
156 	{ S1DREG_CRT_DISP_FIFO_LTC,	0x00 },
157 	{ S1DREG_LCD_CUR_CTL,		0x00 },
158 	{ S1DREG_LCD_CUR_START,		0x01 },
159 	{ S1DREG_LCD_CUR_XPOS0,		0x00 },
160 	{ S1DREG_LCD_CUR_XPOS1,		0x00 },
161 	{ S1DREG_LCD_CUR_YPOS0,		0x00 },
162 	{ S1DREG_LCD_CUR_YPOS1,		0x00 },
163 	{ S1DREG_LCD_CUR_BCTL0,		0x00 },
164 	{ S1DREG_LCD_CUR_GCTL0,		0x00 },
165 	{ S1DREG_LCD_CUR_RCTL0,		0x00 },
166 	{ S1DREG_LCD_CUR_BCTL1,		0x1f },
167 	{ S1DREG_LCD_CUR_GCTL1,		0x3f },
168 	{ S1DREG_LCD_CUR_RCTL1,		0x1f },
169 	{ S1DREG_LCD_CUR_FIFO_HTC,	0x00 },
170 	{ S1DREG_CRT_CUR_CTL,		0x00 },
171 	{ S1DREG_CRT_CUR_START,		0x01 },
172 	{ S1DREG_CRT_CUR_XPOS0,		0x00 },
173 	{ S1DREG_CRT_CUR_XPOS1,		0x00 },
174 	{ S1DREG_CRT_CUR_YPOS0,		0x00 },
175 	{ S1DREG_CRT_CUR_YPOS1,		0x00 },
176 	{ S1DREG_CRT_CUR_BCTL0,		0x00 },
177 	{ S1DREG_CRT_CUR_GCTL0,		0x00 },
178 	{ S1DREG_CRT_CUR_RCTL0,		0x00 },
179 	{ S1DREG_CRT_CUR_BCTL1,		0x1f },
180 	{ S1DREG_CRT_CUR_GCTL1,		0x3f },
181 	{ S1DREG_CRT_CUR_RCTL1,		0x1f },
182 	{ S1DREG_CRT_CUR_FIFO_HTC,	0x00 },
183 	{ S1DREG_BBLT_CTL0,		0x00 },
184 	{ S1DREG_BBLT_CTL1,		0x00 },
185 	{ S1DREG_BBLT_CC_EXP,		0x00 },
186 	{ S1DREG_BBLT_OP,		0x00 },
187 	{ S1DREG_BBLT_SRC_START0,	0x00 },
188 	{ S1DREG_BBLT_SRC_START1,	0x00 },
189 	{ S1DREG_BBLT_SRC_START2,	0x00 },
190 	{ S1DREG_BBLT_DST_START0,	0x00 },
191 	{ S1DREG_BBLT_DST_START1,	0x00 },
192 	{ S1DREG_BBLT_DST_START2,	0x00 },
193 	{ S1DREG_BBLT_MEM_OFF0,		0x00 },
194 	{ S1DREG_BBLT_MEM_OFF1,		0x00 },
195 	{ S1DREG_BBLT_WIDTH0,		0x00 },
196 	{ S1DREG_BBLT_WIDTH1,		0x00 },
197 	{ S1DREG_BBLT_HEIGHT0,		0x00 },
198 	{ S1DREG_BBLT_HEIGHT1,		0x00 },
199 	{ S1DREG_BBLT_BGC0,		0x00 },
200 	{ S1DREG_BBLT_BGC1,		0x00 },
201 	{ S1DREG_BBLT_FGC0,		0x00 },
202 	{ S1DREG_BBLT_FGC1,		0x00 },
203 	{ S1DREG_LKUP_MODE,		0x00 },
204 	{ S1DREG_LKUP_ADDR,		0x00 },
205 	{ S1DREG_PS_CNF,		0x10 },
206 	{ S1DREG_PS_STATUS,		0x00 },
207 	{ S1DREG_CPU2MEM_WDOGT,		0x00 },
208 	{ S1DREG_COM_DISP_MODE,		0x02 },
209 };
210 
211 static struct s1d13xxxfb_pdata s1d13806_platform_data = {
212 	.initregs	= s1d13806_initregs,
213 	.initregssize	= ARRAY_SIZE(s1d13806_initregs),
214 };
215 
216 static struct resource s1d13806_resources[] = {
217 	[0] = {
218 		.start		= 0x07200000,
219 		.end		= 0x07200000 + 0x00200000 - 1,
220 		.flags		= IORESOURCE_MEM,
221 	},
222 	[1] = {
223 		.start		= 0x07000000,
224 		.end		= 0x07000000 + 0x00200000 - 1,
225 		.flags		= IORESOURCE_MEM,
226 	},
227 };
228 
229 static struct platform_device s1d13806_device = {
230 	.name		= "s1d13806fb",
231 	.id		= -1,
232 	.num_resources	= ARRAY_SIZE(s1d13806_resources),
233 	.resource	= s1d13806_resources,
234 
235 	.dev = {
236 		.platform_data	= &s1d13806_platform_data,
237 	},
238 };
239 #endif
240 
241 static struct platform_device *microdev_devices[] __initdata = {
242 	&smc91x_device,
243 #ifdef CONFIG_FB_S1D13XXX
244 	&s1d13806_device,
245 #endif
246 };
247 
248 static int __init microdev_devices_setup(void)
249 {
250 	return platform_add_devices(microdev_devices, ARRAY_SIZE(microdev_devices));
251 }
252 
253 /*
254  * Setup for the SMSC FDC37C93xAPM
255  */
256 static int __init smsc_superio_setup(void)
257 {
258 
259 	unsigned char devid, devrev;
260 
261 		/* Initially the chip is in run state */
262 		/* Put it into configuration state */
263 	outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
264 
265 		/* Read device ID info */
266 	devid  = SMSC_READ_INDEXED(SMSC_DEVICE_ID_INDEX);
267 	devrev = SMSC_READ_INDEXED(SMSC_DEVICE_REV_INDEX);
268 	if ( (devid==0x30) && (devrev==0x01) )
269 	{
270   		printk("SMSC FDC37C93xAPM SuperIO device detected\n");
271 	}
272 	else
273 	{		/* not the device identity we expected */
274 		printk("Not detected a SMSC FDC37C93xAPM SuperIO device (devid=0x%02x, rev=0x%02x)\n",
275 			devid, devrev);
276 			/* inform the keyboard driver that we have no keyboard controller */
277 		microdev_kbd_controller_present = 0;
278 			/* little point in doing anything else in this functon */
279 		return 0;
280 	}
281 
282 		/* Select the keyboard device */
283 	SMSC_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX);
284 		/* enable it */
285 	SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
286 		/* enable the interrupts */
287 	SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_KEYBOARD, SMSC_PRIMARY_INT_INDEX);
288 	SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_MOUSE, SMSC_SECONDARY_INT_INDEX);
289 
290 		/* Select the Serial #1 device */
291 	SMSC_WRITE_INDEXED(SMSC_SERIAL1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
292 		/* enable it */
293 	SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
294 		/* program with port addresses */
295 	SMSC_WRITE_INDEXED(MSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
296 	SMSC_WRITE_INDEXED(LSB(SERIAL1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
297 	SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
298 		/* enable the interrupts */
299 	SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL1, SMSC_PRIMARY_INT_INDEX);
300 
301 		/* Select the Serial #2 device */
302 	SMSC_WRITE_INDEXED(SMSC_SERIAL2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
303 		/* enable it */
304 	SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
305 		/* program with port addresses */
306 	SMSC_WRITE_INDEXED(MSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
307 	SMSC_WRITE_INDEXED(LSB(SERIAL2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
308 	SMSC_WRITE_INDEXED(0x00, SMSC_HDCS0_INDEX);
309 		/* enable the interrupts */
310 	SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_SERIAL2, SMSC_PRIMARY_INT_INDEX);
311 
312 		/* Select the IDE#1 device */
313 	SMSC_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
314 		/* enable it */
315 	SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
316 		/* program with port addresses */
317 	SMSC_WRITE_INDEXED(MSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
318 	SMSC_WRITE_INDEXED(LSB(IDE1_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
319 	SMSC_WRITE_INDEXED(MSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
320 	SMSC_WRITE_INDEXED(LSB(IDE1_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
321 	SMSC_WRITE_INDEXED(0x0c, SMSC_HDCS0_INDEX);
322 	SMSC_WRITE_INDEXED(0x00, SMSC_HDCS1_INDEX);
323 		/* select the interrupt */
324 	SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE1, SMSC_PRIMARY_INT_INDEX);
325 
326 		/* Select the IDE#2 device */
327 	SMSC_WRITE_INDEXED(SMSC_IDE2_DEVICE, SMCS_LOGICAL_DEV_INDEX);
328 		/* enable it */
329 	SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
330 		/* program with port addresses */
331 	SMSC_WRITE_INDEXED(MSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+0);
332 	SMSC_WRITE_INDEXED(LSB(IDE2_PRIMARY_BASE), SMSC_PRIMARY_BASE_INDEX+1);
333 	SMSC_WRITE_INDEXED(MSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+0);
334 	SMSC_WRITE_INDEXED(LSB(IDE2_SECONDARY_BASE), SMSC_SECONDARY_BASE_INDEX+1);
335 		/* select the interrupt */
336 	SMSC_WRITE_INDEXED(MICRODEV_FPGA_IRQ_IDE2, SMSC_PRIMARY_INT_INDEX);
337 
338 		/* Select the configuration registers */
339 	SMSC_WRITE_INDEXED(SMSC_CONFIG_REGISTERS, SMCS_LOGICAL_DEV_INDEX);
340 		/* enable the appropriate GPIO pins for IDE functionality:
341 		 * bit[0]   In/Out		1==input;  0==output
342 		 * bit[1]   Polarity		1==invert; 0==no invert
343 		 * bit[2]   Int Enb #1		1==Enable Combined IRQ #1; 0==disable
344 		 * bit[3:4] Function Select	00==original; 01==Alternate Function #1
345 		 */
346 	SMSC_WRITE_INDEXED(0x00, 0xc2);	/* GP42 = nIDE1_OE */
347 	SMSC_WRITE_INDEXED(0x01, 0xc5);	/* GP45 = IDE1_IRQ */
348 	SMSC_WRITE_INDEXED(0x00, 0xc6);	/* GP46 = nIOROP */
349 	SMSC_WRITE_INDEXED(0x00, 0xc7);	/* GP47 = nIOWOP */
350 	SMSC_WRITE_INDEXED(0x08, 0xe8);	/* GP20 = nIDE2_OE */
351 
352 		/* Exit the configuration state */
353 	outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
354 
355 	return 0;
356 }
357 
358 static void __init microdev_setup(char **cmdline_p)
359 {
360 	int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
361 	const int fpgaRevision = *fpgaRevisionRegister;
362 	int * const CacheControlRegister = (int*)CCR;
363 
364 	device_initcall(microdev_devices_setup);
365 	device_initcall(smsc_superio_setup);
366 
367 	printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
368 		get_system_type(), fpgaRevision, *CacheControlRegister);
369 }
370 
371 /*
372  * The Machine Vector
373  */
374 static struct sh_machine_vector mv_sh4202_microdev __initmv = {
375 	.mv_name		= "SH4-202 MicroDev",
376 	.mv_setup		= microdev_setup,
377 	.mv_nr_irqs		= 72,		/* QQQ need to check this - use the MACRO */
378 
379 	.mv_inb			= microdev_inb,
380 	.mv_inw			= microdev_inw,
381 	.mv_inl			= microdev_inl,
382 	.mv_outb		= microdev_outb,
383 	.mv_outw		= microdev_outw,
384 	.mv_outl		= microdev_outl,
385 
386 	.mv_inb_p		= microdev_inb_p,
387 	.mv_inw_p		= microdev_inw_p,
388 	.mv_inl_p		= microdev_inl_p,
389 	.mv_outb_p		= microdev_outb_p,
390 	.mv_outw_p		= microdev_outw_p,
391 	.mv_outl_p		= microdev_outl_p,
392 
393 	.mv_insb		= microdev_insb,
394 	.mv_insw		= microdev_insw,
395 	.mv_insl		= microdev_insl,
396 	.mv_outsb		= microdev_outsb,
397 	.mv_outsw		= microdev_outsw,
398 	.mv_outsl		= microdev_outsl,
399 
400 	.mv_init_irq		= init_microdev_irq,
401 
402 #ifdef CONFIG_HEARTBEAT
403 	.mv_heartbeat		= microdev_heartbeat,
404 #endif
405 };
406