1 /*
2  * linux/arch/arm/mach-w90x900/dev.c
3  *
4  * Copyright (C) 2009 Nuvoton corporation.
5  *
6  * Wan ZongShun <mcuos.com@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation;version 2 of the License.
11  *
12  */
13 
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/interrupt.h>
17 #include <linux/list.h>
18 #include <linux/timer.h>
19 #include <linux/init.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
22 
23 #include <linux/mtd/physmap.h>
24 #include <linux/mtd/mtd.h>
25 #include <linux/mtd/partitions.h>
26 
27 #include <linux/spi/spi.h>
28 #include <linux/spi/flash.h>
29 
30 #include <asm/system_misc.h>
31 #include <asm/mach/arch.h>
32 #include <asm/mach/map.h>
33 #include <asm/mach/irq.h>
34 #include <asm/mach-types.h>
35 
36 #include <mach/regs-serial.h>
37 #include <mach/nuc900_spi.h>
38 #include <mach/map.h>
39 #include <mach/fb.h>
40 #include <mach/regs-ldm.h>
41 #include <mach/w90p910_keypad.h>
42 
43 #include "cpu.h"
44 
45 /*NUC900 evb norflash driver data */
46 
47 #define NUC900_FLASH_BASE	0xA0000000
48 #define NUC900_FLASH_SIZE	0x400000
49 #define SPIOFFSET		0x200
50 #define SPIOREG_SIZE		0x100
51 
52 static struct mtd_partition nuc900_flash_partitions[] = {
53 	{
54 		.name	=	"NOR Partition 1 for kernel (960K)",
55 		.size	=	0xF0000,
56 		.offset	=	0x10000,
57 	},
58 	{
59 		.name	=	"NOR Partition 2 for image (1M)",
60 		.size	=	0x100000,
61 		.offset	=	0x100000,
62 	},
63 	{
64 		.name	=	"NOR Partition 3 for user (2M)",
65 		.size	=	0x200000,
66 		.offset	=	0x00200000,
67 	}
68 };
69 
70 static struct physmap_flash_data nuc900_flash_data = {
71 	.width		=	2,
72 	.parts		=	nuc900_flash_partitions,
73 	.nr_parts	=	ARRAY_SIZE(nuc900_flash_partitions),
74 };
75 
76 static struct resource nuc900_flash_resources[] = {
77 	{
78 		.start	=	NUC900_FLASH_BASE,
79 		.end	=	NUC900_FLASH_BASE + NUC900_FLASH_SIZE - 1,
80 		.flags	=	IORESOURCE_MEM,
81 	}
82 };
83 
84 static struct platform_device nuc900_flash_device = {
85 	.name		=	"physmap-flash",
86 	.id		=	0,
87 	.dev		= {
88 				.platform_data = &nuc900_flash_data,
89 			},
90 	.resource	=	nuc900_flash_resources,
91 	.num_resources	=	ARRAY_SIZE(nuc900_flash_resources),
92 };
93 
94 /* USB EHCI Host Controller */
95 
96 static struct resource nuc900_usb_ehci_resource[] = {
97 	[0] = {
98 		.start = W90X900_PA_USBEHCIHOST,
99 		.end   = W90X900_PA_USBEHCIHOST + W90X900_SZ_USBEHCIHOST - 1,
100 		.flags = IORESOURCE_MEM,
101 	},
102 	[1] = {
103 		.start = IRQ_USBH,
104 		.end   = IRQ_USBH,
105 		.flags = IORESOURCE_IRQ,
106 	}
107 };
108 
109 static u64 nuc900_device_usb_ehci_dmamask = 0xffffffffUL;
110 
111 static struct platform_device nuc900_device_usb_ehci = {
112 	.name		  = "nuc900-ehci",
113 	.id		  = -1,
114 	.num_resources	  = ARRAY_SIZE(nuc900_usb_ehci_resource),
115 	.resource	  = nuc900_usb_ehci_resource,
116 	.dev              = {
117 		.dma_mask = &nuc900_device_usb_ehci_dmamask,
118 		.coherent_dma_mask = 0xffffffffUL
119 	}
120 };
121 
122 /* USB OHCI Host Controller */
123 
124 static struct resource nuc900_usb_ohci_resource[] = {
125 	[0] = {
126 		.start = W90X900_PA_USBOHCIHOST,
127 		.end   = W90X900_PA_USBOHCIHOST + W90X900_SZ_USBOHCIHOST - 1,
128 		.flags = IORESOURCE_MEM,
129 	},
130 	[1] = {
131 		.start = IRQ_USBH,
132 		.end   = IRQ_USBH,
133 		.flags = IORESOURCE_IRQ,
134 	}
135 };
136 
137 static u64 nuc900_device_usb_ohci_dmamask = 0xffffffffUL;
138 static struct platform_device nuc900_device_usb_ohci = {
139 	.name		  = "nuc900-ohci",
140 	.id		  = -1,
141 	.num_resources	  = ARRAY_SIZE(nuc900_usb_ohci_resource),
142 	.resource	  = nuc900_usb_ohci_resource,
143 	.dev              = {
144 		.dma_mask = &nuc900_device_usb_ohci_dmamask,
145 		.coherent_dma_mask = 0xffffffffUL
146 	}
147 };
148 
149 /* USB Device (Gadget)*/
150 
151 static struct resource nuc900_usbgadget_resource[] = {
152 	[0] = {
153 		.start = W90X900_PA_USBDEV,
154 		.end   = W90X900_PA_USBDEV + W90X900_SZ_USBDEV - 1,
155 		.flags = IORESOURCE_MEM,
156 	},
157 	[1] = {
158 		.start = IRQ_USBD,
159 		.end   = IRQ_USBD,
160 		.flags = IORESOURCE_IRQ,
161 	}
162 };
163 
164 static struct platform_device nuc900_device_usbgadget = {
165 	.name		= "nuc900-usbgadget",
166 	.id		= -1,
167 	.num_resources	= ARRAY_SIZE(nuc900_usbgadget_resource),
168 	.resource	= nuc900_usbgadget_resource,
169 };
170 
171 /* MAC device */
172 
173 static struct resource nuc900_emc_resource[] = {
174 	[0] = {
175 		.start = W90X900_PA_EMC,
176 		.end   = W90X900_PA_EMC + W90X900_SZ_EMC - 1,
177 		.flags = IORESOURCE_MEM,
178 	},
179 	[1] = {
180 		.start = IRQ_EMCTX,
181 		.end   = IRQ_EMCTX,
182 		.flags = IORESOURCE_IRQ,
183 	},
184 	[2] = {
185 		.start = IRQ_EMCRX,
186 		.end   = IRQ_EMCRX,
187 		.flags = IORESOURCE_IRQ,
188 	}
189 };
190 
191 static u64 nuc900_device_emc_dmamask = 0xffffffffUL;
192 static struct platform_device nuc900_device_emc = {
193 	.name		= "nuc900-emc",
194 	.id		= -1,
195 	.num_resources	= ARRAY_SIZE(nuc900_emc_resource),
196 	.resource	= nuc900_emc_resource,
197 	.dev              = {
198 		.dma_mask = &nuc900_device_emc_dmamask,
199 		.coherent_dma_mask = 0xffffffffUL
200 	}
201 };
202 
203 /* SPI device */
204 
205 static struct nuc900_spi_info nuc900_spiflash_data = {
206 	.num_cs		= 1,
207 	.lsb		= 0,
208 	.txneg		= 1,
209 	.rxneg		= 0,
210 	.divider	= 24,
211 	.sleep		= 0,
212 	.txnum		= 0,
213 	.txbitlen	= 8,
214 	.bus_num	= 0,
215 };
216 
217 static struct resource nuc900_spi_resource[] = {
218 	[0] = {
219 		.start = W90X900_PA_I2C + SPIOFFSET,
220 		.end   = W90X900_PA_I2C + SPIOFFSET + SPIOREG_SIZE - 1,
221 		.flags = IORESOURCE_MEM,
222 	},
223 	[1] = {
224 		.start = IRQ_SSP,
225 		.end   = IRQ_SSP,
226 		.flags = IORESOURCE_IRQ,
227 	}
228 };
229 
230 static struct platform_device nuc900_device_spi = {
231 	.name		= "nuc900-spi",
232 	.id		= -1,
233 	.num_resources	= ARRAY_SIZE(nuc900_spi_resource),
234 	.resource	= nuc900_spi_resource,
235 	.dev		= {
236 				.platform_data = &nuc900_spiflash_data,
237 			}
238 };
239 
240 /* spi device, spi flash info */
241 
242 static struct mtd_partition nuc900_spi_flash_partitions[] = {
243 	{
244 		.name = "bootloader(spi)",
245 		.size = 0x0100000,
246 		.offset = 0,
247 	},
248 };
249 
250 static struct flash_platform_data nuc900_spi_flash_data = {
251 	.name = "m25p80",
252 	.parts =  nuc900_spi_flash_partitions,
253 	.nr_parts = ARRAY_SIZE(nuc900_spi_flash_partitions),
254 	.type = "w25x16",
255 };
256 
257 static struct spi_board_info nuc900_spi_board_info[] __initdata = {
258 	{
259 		.modalias = "m25p80",
260 		.max_speed_hz = 20000000,
261 		.bus_num = 0,
262 		.chip_select = 0,
263 		.platform_data = &nuc900_spi_flash_data,
264 		.mode = SPI_MODE_0,
265 	},
266 };
267 
268 /* WDT Device */
269 
270 static struct resource nuc900_wdt_resource[] = {
271 	[0] = {
272 		.start = W90X900_PA_TIMER,
273 		.end   = W90X900_PA_TIMER + W90X900_SZ_TIMER - 1,
274 		.flags = IORESOURCE_MEM,
275 	},
276 	[1] = {
277 		.start = IRQ_WDT,
278 		.end   = IRQ_WDT,
279 		.flags = IORESOURCE_IRQ,
280 	}
281 };
282 
283 static struct platform_device nuc900_device_wdt = {
284 	.name		= "nuc900-wdt",
285 	.id		= -1,
286 	.num_resources	= ARRAY_SIZE(nuc900_wdt_resource),
287 	.resource	= nuc900_wdt_resource,
288 };
289 
290 /*
291  * public device definition between 910 and 920, or 910
292  * and 950 or 950 and 960...,their dev platform register
293  * should be in specific file such as nuc950, nuc960 c
294  * files rather than the public dev.c file here. so the
295  * corresponding platform_device definition should not be
296  * static.
297 */
298 
299 /* RTC controller*/
300 
301 static struct resource nuc900_rtc_resource[] = {
302 	[0] = {
303 		.start = W90X900_PA_RTC,
304 		.end   = W90X900_PA_RTC + 0xff,
305 		.flags = IORESOURCE_MEM,
306 	},
307 	[1] = {
308 		.start = IRQ_RTC,
309 		.end   = IRQ_RTC,
310 		.flags = IORESOURCE_IRQ,
311 	},
312 };
313 
314 struct platform_device nuc900_device_rtc = {
315 	.name		= "nuc900-rtc",
316 	.id		= -1,
317 	.num_resources	= ARRAY_SIZE(nuc900_rtc_resource),
318 	.resource	= nuc900_rtc_resource,
319 };
320 
321 /*TouchScreen controller*/
322 
323 static struct resource nuc900_ts_resource[] = {
324 	[0] = {
325 		.start = W90X900_PA_ADC,
326 		.end   = W90X900_PA_ADC + W90X900_SZ_ADC-1,
327 		.flags = IORESOURCE_MEM,
328 	},
329 	[1] = {
330 		.start = IRQ_ADC,
331 		.end   = IRQ_ADC,
332 		.flags = IORESOURCE_IRQ,
333 	},
334 };
335 
336 struct platform_device nuc900_device_ts = {
337 	.name		= "nuc900-ts",
338 	.id		= -1,
339 	.resource	= nuc900_ts_resource,
340 	.num_resources	= ARRAY_SIZE(nuc900_ts_resource),
341 };
342 
343 /* FMI Device */
344 
345 static struct resource nuc900_fmi_resource[] = {
346 	[0] = {
347 		.start = W90X900_PA_FMI,
348 		.end   = W90X900_PA_FMI + W90X900_SZ_FMI - 1,
349 		.flags = IORESOURCE_MEM,
350 	},
351 	[1] = {
352 		.start = IRQ_FMI,
353 		.end   = IRQ_FMI,
354 		.flags = IORESOURCE_IRQ,
355 	}
356 };
357 
358 struct platform_device nuc900_device_fmi = {
359 	.name		= "nuc900-fmi",
360 	.id		= -1,
361 	.num_resources	= ARRAY_SIZE(nuc900_fmi_resource),
362 	.resource	= nuc900_fmi_resource,
363 };
364 
365 /* KPI controller*/
366 
367 static int nuc900_keymap[] = {
368 	KEY(0, 0, KEY_A),
369 	KEY(0, 1, KEY_B),
370 	KEY(0, 2, KEY_C),
371 	KEY(0, 3, KEY_D),
372 
373 	KEY(1, 0, KEY_E),
374 	KEY(1, 1, KEY_F),
375 	KEY(1, 2, KEY_G),
376 	KEY(1, 3, KEY_H),
377 
378 	KEY(2, 0, KEY_I),
379 	KEY(2, 1, KEY_J),
380 	KEY(2, 2, KEY_K),
381 	KEY(2, 3, KEY_L),
382 
383 	KEY(3, 0, KEY_M),
384 	KEY(3, 1, KEY_N),
385 	KEY(3, 2, KEY_O),
386 	KEY(3, 3, KEY_P),
387 };
388 
389 static struct matrix_keymap_data nuc900_map_data = {
390 	.keymap			= nuc900_keymap,
391 	.keymap_size		= ARRAY_SIZE(nuc900_keymap),
392 };
393 
394 struct w90p910_keypad_platform_data nuc900_keypad_info = {
395 	.keymap_data	= &nuc900_map_data,
396 	.prescale	= 0xfa,
397 	.debounce	= 0x50,
398 };
399 
400 static struct resource nuc900_kpi_resource[] = {
401 	[0] = {
402 		.start = W90X900_PA_KPI,
403 		.end   = W90X900_PA_KPI + W90X900_SZ_KPI - 1,
404 		.flags = IORESOURCE_MEM,
405 	},
406 	[1] = {
407 		.start = IRQ_KPI,
408 		.end   = IRQ_KPI,
409 		.flags = IORESOURCE_IRQ,
410 	}
411 
412 };
413 
414 struct platform_device nuc900_device_kpi = {
415 	.name		= "nuc900-kpi",
416 	.id		= -1,
417 	.num_resources	= ARRAY_SIZE(nuc900_kpi_resource),
418 	.resource	= nuc900_kpi_resource,
419 	.dev		= {
420 				.platform_data = &nuc900_keypad_info,
421 			}
422 };
423 
424 /* LCD controller*/
425 
426 static struct nuc900fb_display nuc900_lcd_info[] = {
427 	/* Giantplus Technology GPM1040A0 320x240 Color TFT LCD */
428 	[0] = {
429 		.type		= LCM_DCCS_VA_SRC_RGB565,
430 		.width		= 320,
431 		.height		= 240,
432 		.xres		= 320,
433 		.yres		= 240,
434 		.bpp		= 16,
435 		.pixclock	= 200000,
436 		.left_margin	= 34,
437 		.right_margin   = 54,
438 		.hsync_len	= 10,
439 		.upper_margin	= 18,
440 		.lower_margin	= 4,
441 		.vsync_len	= 1,
442 		.dccs		= 0x8e00041a,
443 		.devctl		= 0x060800c0,
444 		.fbctrl		= 0x00a000a0,
445 		.scale		= 0x04000400,
446 	},
447 };
448 
449 static struct nuc900fb_mach_info nuc900_fb_info = {
450 #if defined(CONFIG_GPM1040A0_320X240)
451 	.displays		= &nuc900_lcd_info[0],
452 #else
453 	.displays		= nuc900_lcd_info,
454 #endif
455 	.num_displays		= ARRAY_SIZE(nuc900_lcd_info),
456 	.default_display	= 0,
457 	.gpio_dir		= 0x00000004,
458 	.gpio_dir_mask		= 0xFFFFFFFD,
459 	.gpio_data		= 0x00000004,
460 	.gpio_data_mask		= 0xFFFFFFFD,
461 };
462 
463 static struct resource nuc900_lcd_resource[] = {
464 	[0] = {
465 		.start = W90X900_PA_LCD,
466 		.end   = W90X900_PA_LCD + W90X900_SZ_LCD - 1,
467 		.flags = IORESOURCE_MEM,
468 	},
469 	[1] = {
470 		.start = IRQ_LCD,
471 		.end   = IRQ_LCD,
472 		.flags = IORESOURCE_IRQ,
473 	}
474 };
475 
476 static u64 nuc900_device_lcd_dmamask = -1;
477 struct platform_device nuc900_device_lcd = {
478 	.name             = "nuc900-lcd",
479 	.id               = -1,
480 	.num_resources    = ARRAY_SIZE(nuc900_lcd_resource),
481 	.resource         = nuc900_lcd_resource,
482 	.dev              = {
483 		.dma_mask               = &nuc900_device_lcd_dmamask,
484 		.coherent_dma_mask      = -1,
485 		.platform_data = &nuc900_fb_info,
486 	}
487 };
488 
489 /* AUDIO controller*/
490 static u64 nuc900_device_audio_dmamask = -1;
491 static struct resource nuc900_ac97_resource[] = {
492 	[0] = {
493 		.start = W90X900_PA_ACTL,
494 		.end   = W90X900_PA_ACTL + W90X900_SZ_ACTL - 1,
495 		.flags = IORESOURCE_MEM,
496 	},
497 	[1] = {
498 		.start = IRQ_ACTL,
499 		.end   = IRQ_ACTL,
500 		.flags = IORESOURCE_IRQ,
501 	}
502 
503 };
504 
505 struct platform_device nuc900_device_ac97 = {
506 	.name		= "nuc900-ac97",
507 	.id		= -1,
508 	.num_resources	= ARRAY_SIZE(nuc900_ac97_resource),
509 	.resource	= nuc900_ac97_resource,
510 	.dev              = {
511 		.dma_mask               = &nuc900_device_audio_dmamask,
512 		.coherent_dma_mask      = -1,
513 	}
514 };
515 
516 /*Here should be your evb resourse,such as LCD*/
517 
518 static struct platform_device *nuc900_public_dev[] __initdata = {
519 	&nuc900_serial_device,
520 	&nuc900_flash_device,
521 	&nuc900_device_usb_ehci,
522 	&nuc900_device_usb_ohci,
523 	&nuc900_device_usbgadget,
524 	&nuc900_device_emc,
525 	&nuc900_device_spi,
526 	&nuc900_device_wdt,
527 	&nuc900_device_ac97,
528 };
529 
530 /* Provide adding specific CPU platform devices API */
531 
nuc900_board_init(struct platform_device ** device,int size)532 void __init nuc900_board_init(struct platform_device **device, int size)
533 {
534 	disable_hlt();
535 	platform_add_devices(device, size);
536 	platform_add_devices(nuc900_public_dev, ARRAY_SIZE(nuc900_public_dev));
537 	spi_register_board_info(nuc900_spi_board_info,
538 					ARRAY_SIZE(nuc900_spi_board_info));
539 }
540 
541