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