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