1/* 2 * linux/arch/arm/mach-pxa/lpd270.c 3 * 4 * Support for the LogicPD PXA270 Card Engine. 5 * Derived from the mainstone code, which carries these notices: 6 * 7 * Author: Nicolas Pitre 8 * Created: Nov 05, 2002 9 * Copyright: MontaVista Software Inc. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15#include <linux/gpio.h> 16#include <linux/init.h> 17#include <linux/platform_device.h> 18#include <linux/syscore_ops.h> 19#include <linux/interrupt.h> 20#include <linux/sched.h> 21#include <linux/bitops.h> 22#include <linux/fb.h> 23#include <linux/ioport.h> 24#include <linux/mtd/mtd.h> 25#include <linux/mtd/partitions.h> 26#include <linux/pwm_backlight.h> 27#include <linux/smc91x.h> 28 29#include <asm/types.h> 30#include <asm/setup.h> 31#include <asm/memory.h> 32#include <asm/mach-types.h> 33#include <mach/hardware.h> 34#include <asm/irq.h> 35#include <asm/sizes.h> 36 37#include <asm/mach/arch.h> 38#include <asm/mach/map.h> 39#include <asm/mach/irq.h> 40#include <asm/mach/flash.h> 41 42#include <mach/pxa27x.h> 43#include <mach/lpd270.h> 44#include <mach/audio.h> 45#include <linux/platform_data/video-pxafb.h> 46#include <linux/platform_data/mmc-pxamci.h> 47#include <linux/platform_data/irda-pxaficp.h> 48#include <linux/platform_data/usb-ohci-pxa27x.h> 49#include <mach/smemc.h> 50 51#include "generic.h" 52#include "devices.h" 53 54static unsigned long lpd270_pin_config[] __initdata = { 55 /* Chip Selects */ 56 GPIO15_nCS_1, /* Mainboard Flash */ 57 GPIO78_nCS_2, /* CPLD + Ethernet */ 58 59 /* LCD - 16bpp Active TFT */ 60 GPIO58_LCD_LDD_0, 61 GPIO59_LCD_LDD_1, 62 GPIO60_LCD_LDD_2, 63 GPIO61_LCD_LDD_3, 64 GPIO62_LCD_LDD_4, 65 GPIO63_LCD_LDD_5, 66 GPIO64_LCD_LDD_6, 67 GPIO65_LCD_LDD_7, 68 GPIO66_LCD_LDD_8, 69 GPIO67_LCD_LDD_9, 70 GPIO68_LCD_LDD_10, 71 GPIO69_LCD_LDD_11, 72 GPIO70_LCD_LDD_12, 73 GPIO71_LCD_LDD_13, 74 GPIO72_LCD_LDD_14, 75 GPIO73_LCD_LDD_15, 76 GPIO74_LCD_FCLK, 77 GPIO75_LCD_LCLK, 78 GPIO76_LCD_PCLK, 79 GPIO77_LCD_BIAS, 80 GPIO16_PWM0_OUT, /* Backlight */ 81 82 /* USB Host */ 83 GPIO88_USBH1_PWR, 84 GPIO89_USBH1_PEN, 85 86 /* AC97 */ 87 GPIO28_AC97_BITCLK, 88 GPIO29_AC97_SDATA_IN_0, 89 GPIO30_AC97_SDATA_OUT, 90 GPIO31_AC97_SYNC, 91 GPIO45_AC97_SYSCLK, 92 93 GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, 94}; 95 96static unsigned int lpd270_irq_enabled; 97 98static void lpd270_mask_irq(struct irq_data *d) 99{ 100 int lpd270_irq = d->irq - LPD270_IRQ(0); 101 102 __raw_writew(~(1 << lpd270_irq), LPD270_INT_STATUS); 103 104 lpd270_irq_enabled &= ~(1 << lpd270_irq); 105 __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK); 106} 107 108static void lpd270_unmask_irq(struct irq_data *d) 109{ 110 int lpd270_irq = d->irq - LPD270_IRQ(0); 111 112 lpd270_irq_enabled |= 1 << lpd270_irq; 113 __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK); 114} 115 116static struct irq_chip lpd270_irq_chip = { 117 .name = "CPLD", 118 .irq_ack = lpd270_mask_irq, 119 .irq_mask = lpd270_mask_irq, 120 .irq_unmask = lpd270_unmask_irq, 121}; 122 123static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc) 124{ 125 unsigned long pending; 126 127 pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled; 128 do { 129 /* clear useless edge notification */ 130 desc->irq_data.chip->irq_ack(&desc->irq_data); 131 if (likely(pending)) { 132 irq = LPD270_IRQ(0) + __ffs(pending); 133 generic_handle_irq(irq); 134 135 pending = __raw_readw(LPD270_INT_STATUS) & 136 lpd270_irq_enabled; 137 } 138 } while (pending); 139} 140 141static void __init lpd270_init_irq(void) 142{ 143 int irq; 144 145 pxa27x_init_irq(); 146 147 __raw_writew(0, LPD270_INT_MASK); 148 __raw_writew(0, LPD270_INT_STATUS); 149 150 /* setup extra LogicPD PXA270 irqs */ 151 for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) { 152 irq_set_chip_and_handler(irq, &lpd270_irq_chip, 153 handle_level_irq); 154 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 155 } 156 irq_set_chained_handler(PXA_GPIO_TO_IRQ(0), lpd270_irq_handler); 157 irq_set_irq_type(PXA_GPIO_TO_IRQ(0), IRQ_TYPE_EDGE_FALLING); 158} 159 160 161#ifdef CONFIG_PM 162static void lpd270_irq_resume(void) 163{ 164 __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK); 165} 166 167static struct syscore_ops lpd270_irq_syscore_ops = { 168 .resume = lpd270_irq_resume, 169}; 170 171static int __init lpd270_irq_device_init(void) 172{ 173 if (machine_is_logicpd_pxa270()) { 174 register_syscore_ops(&lpd270_irq_syscore_ops); 175 return 0; 176 } 177 return -ENODEV; 178} 179 180device_initcall(lpd270_irq_device_init); 181#endif 182 183 184static struct resource smc91x_resources[] = { 185 [0] = { 186 .start = LPD270_ETH_PHYS, 187 .end = (LPD270_ETH_PHYS + 0xfffff), 188 .flags = IORESOURCE_MEM, 189 }, 190 [1] = { 191 .start = LPD270_ETHERNET_IRQ, 192 .end = LPD270_ETHERNET_IRQ, 193 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, 194 }, 195}; 196 197struct smc91x_platdata smc91x_platdata = { 198 .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, 199}; 200 201static struct platform_device smc91x_device = { 202 .name = "smc91x", 203 .id = 0, 204 .num_resources = ARRAY_SIZE(smc91x_resources), 205 .resource = smc91x_resources, 206 .dev.platform_data = &smc91x_platdata, 207}; 208 209static struct resource lpd270_flash_resources[] = { 210 [0] = { 211 .start = PXA_CS0_PHYS, 212 .end = PXA_CS0_PHYS + SZ_64M - 1, 213 .flags = IORESOURCE_MEM, 214 }, 215 [1] = { 216 .start = PXA_CS1_PHYS, 217 .end = PXA_CS1_PHYS + SZ_64M - 1, 218 .flags = IORESOURCE_MEM, 219 }, 220}; 221 222static struct mtd_partition lpd270_flash0_partitions[] = { 223 { 224 .name = "Bootloader", 225 .size = 0x00040000, 226 .offset = 0, 227 .mask_flags = MTD_WRITEABLE /* force read-only */ 228 }, { 229 .name = "Kernel", 230 .size = 0x00400000, 231 .offset = 0x00040000, 232 }, { 233 .name = "Filesystem", 234 .size = MTDPART_SIZ_FULL, 235 .offset = 0x00440000 236 }, 237}; 238 239static struct flash_platform_data lpd270_flash_data[2] = { 240 { 241 .name = "processor-flash", 242 .map_name = "cfi_probe", 243 .parts = lpd270_flash0_partitions, 244 .nr_parts = ARRAY_SIZE(lpd270_flash0_partitions), 245 }, { 246 .name = "mainboard-flash", 247 .map_name = "cfi_probe", 248 .parts = NULL, 249 .nr_parts = 0, 250 } 251}; 252 253static struct platform_device lpd270_flash_device[2] = { 254 { 255 .name = "pxa2xx-flash", 256 .id = 0, 257 .dev = { 258 .platform_data = &lpd270_flash_data[0], 259 }, 260 .resource = &lpd270_flash_resources[0], 261 .num_resources = 1, 262 }, { 263 .name = "pxa2xx-flash", 264 .id = 1, 265 .dev = { 266 .platform_data = &lpd270_flash_data[1], 267 }, 268 .resource = &lpd270_flash_resources[1], 269 .num_resources = 1, 270 }, 271}; 272 273static struct platform_pwm_backlight_data lpd270_backlight_data = { 274 .pwm_id = 0, 275 .max_brightness = 1, 276 .dft_brightness = 1, 277 .pwm_period_ns = 78770, 278 .enable_gpio = -1, 279}; 280 281static struct platform_device lpd270_backlight_device = { 282 .name = "pwm-backlight", 283 .dev = { 284 .parent = &pxa27x_device_pwm0.dev, 285 .platform_data = &lpd270_backlight_data, 286 }, 287}; 288 289/* 5.7" TFT QVGA (LoLo display number 1) */ 290static struct pxafb_mode_info sharp_lq057q3dc02_mode = { 291 .pixclock = 150000, 292 .xres = 320, 293 .yres = 240, 294 .bpp = 16, 295 .hsync_len = 0x14, 296 .left_margin = 0x28, 297 .right_margin = 0x0a, 298 .vsync_len = 0x02, 299 .upper_margin = 0x08, 300 .lower_margin = 0x14, 301 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 302}; 303 304static struct pxafb_mach_info sharp_lq057q3dc02 = { 305 .modes = &sharp_lq057q3dc02_mode, 306 .num_modes = 1, 307 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL | 308 LCD_ALTERNATE_MAPPING, 309}; 310 311/* 12.1" TFT SVGA (LoLo display number 2) */ 312static struct pxafb_mode_info sharp_lq121s1dg31_mode = { 313 .pixclock = 50000, 314 .xres = 800, 315 .yres = 600, 316 .bpp = 16, 317 .hsync_len = 0x05, 318 .left_margin = 0x52, 319 .right_margin = 0x05, 320 .vsync_len = 0x04, 321 .upper_margin = 0x14, 322 .lower_margin = 0x0a, 323 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 324}; 325 326static struct pxafb_mach_info sharp_lq121s1dg31 = { 327 .modes = &sharp_lq121s1dg31_mode, 328 .num_modes = 1, 329 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL | 330 LCD_ALTERNATE_MAPPING, 331}; 332 333/* 3.6" TFT QVGA (LoLo display number 3) */ 334static struct pxafb_mode_info sharp_lq036q1da01_mode = { 335 .pixclock = 150000, 336 .xres = 320, 337 .yres = 240, 338 .bpp = 16, 339 .hsync_len = 0x0e, 340 .left_margin = 0x04, 341 .right_margin = 0x0a, 342 .vsync_len = 0x03, 343 .upper_margin = 0x03, 344 .lower_margin = 0x03, 345 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 346}; 347 348static struct pxafb_mach_info sharp_lq036q1da01 = { 349 .modes = &sharp_lq036q1da01_mode, 350 .num_modes = 1, 351 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL | 352 LCD_ALTERNATE_MAPPING, 353}; 354 355/* 6.4" TFT VGA (LoLo display number 5) */ 356static struct pxafb_mode_info sharp_lq64d343_mode = { 357 .pixclock = 25000, 358 .xres = 640, 359 .yres = 480, 360 .bpp = 16, 361 .hsync_len = 0x31, 362 .left_margin = 0x89, 363 .right_margin = 0x19, 364 .vsync_len = 0x12, 365 .upper_margin = 0x22, 366 .lower_margin = 0x00, 367 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 368}; 369 370static struct pxafb_mach_info sharp_lq64d343 = { 371 .modes = &sharp_lq64d343_mode, 372 .num_modes = 1, 373 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL | 374 LCD_ALTERNATE_MAPPING, 375}; 376 377/* 10.4" TFT VGA (LoLo display number 7) */ 378static struct pxafb_mode_info sharp_lq10d368_mode = { 379 .pixclock = 25000, 380 .xres = 640, 381 .yres = 480, 382 .bpp = 16, 383 .hsync_len = 0x31, 384 .left_margin = 0x89, 385 .right_margin = 0x19, 386 .vsync_len = 0x12, 387 .upper_margin = 0x22, 388 .lower_margin = 0x00, 389 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 390}; 391 392static struct pxafb_mach_info sharp_lq10d368 = { 393 .modes = &sharp_lq10d368_mode, 394 .num_modes = 1, 395 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL | 396 LCD_ALTERNATE_MAPPING, 397}; 398 399/* 3.5" TFT QVGA (LoLo display number 8) */ 400static struct pxafb_mode_info sharp_lq035q7db02_20_mode = { 401 .pixclock = 150000, 402 .xres = 240, 403 .yres = 320, 404 .bpp = 16, 405 .hsync_len = 0x0e, 406 .left_margin = 0x0a, 407 .right_margin = 0x0a, 408 .vsync_len = 0x03, 409 .upper_margin = 0x05, 410 .lower_margin = 0x14, 411 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 412}; 413 414static struct pxafb_mach_info sharp_lq035q7db02_20 = { 415 .modes = &sharp_lq035q7db02_20_mode, 416 .num_modes = 1, 417 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL | 418 LCD_ALTERNATE_MAPPING, 419}; 420 421static struct pxafb_mach_info *lpd270_lcd_to_use; 422 423static int __init lpd270_set_lcd(char *str) 424{ 425 if (!strncasecmp(str, "lq057q3dc02", 11)) { 426 lpd270_lcd_to_use = &sharp_lq057q3dc02; 427 } else if (!strncasecmp(str, "lq121s1dg31", 11)) { 428 lpd270_lcd_to_use = &sharp_lq121s1dg31; 429 } else if (!strncasecmp(str, "lq036q1da01", 11)) { 430 lpd270_lcd_to_use = &sharp_lq036q1da01; 431 } else if (!strncasecmp(str, "lq64d343", 8)) { 432 lpd270_lcd_to_use = &sharp_lq64d343; 433 } else if (!strncasecmp(str, "lq10d368", 8)) { 434 lpd270_lcd_to_use = &sharp_lq10d368; 435 } else if (!strncasecmp(str, "lq035q7db02-20", 14)) { 436 lpd270_lcd_to_use = &sharp_lq035q7db02_20; 437 } else { 438 printk(KERN_INFO "lpd270: unknown lcd panel [%s]\n", str); 439 } 440 441 return 1; 442} 443 444__setup("lcd=", lpd270_set_lcd); 445 446static struct platform_device *platform_devices[] __initdata = { 447 &smc91x_device, 448 &lpd270_backlight_device, 449 &lpd270_flash_device[0], 450 &lpd270_flash_device[1], 451}; 452 453static struct pxaohci_platform_data lpd270_ohci_platform_data = { 454 .port_mode = PMM_PERPORT_MODE, 455 .flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW, 456}; 457 458static void __init lpd270_init(void) 459{ 460 pxa2xx_mfp_config(ARRAY_AND_SIZE(lpd270_pin_config)); 461 462 pxa_set_ffuart_info(NULL); 463 pxa_set_btuart_info(NULL); 464 pxa_set_stuart_info(NULL); 465 466 lpd270_flash_data[0].width = (__raw_readl(BOOT_DEF) & 1) ? 2 : 4; 467 lpd270_flash_data[1].width = 4; 468 469 /* 470 * System bus arbiter setting: 471 * - Core_Park 472 * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4 473 */ 474 ARB_CNTRL = ARB_CORE_PARK | 0x234; 475 476 platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); 477 478 pxa_set_ac97_info(NULL); 479 480 if (lpd270_lcd_to_use != NULL) 481 pxa_set_fb_info(NULL, lpd270_lcd_to_use); 482 483 pxa_set_ohci_info(&lpd270_ohci_platform_data); 484} 485 486 487static struct map_desc lpd270_io_desc[] __initdata = { 488 { 489 .virtual = (unsigned long)LPD270_CPLD_VIRT, 490 .pfn = __phys_to_pfn(LPD270_CPLD_PHYS), 491 .length = LPD270_CPLD_SIZE, 492 .type = MT_DEVICE, 493 }, 494}; 495 496static void __init lpd270_map_io(void) 497{ 498 pxa27x_map_io(); 499 iotable_init(lpd270_io_desc, ARRAY_SIZE(lpd270_io_desc)); 500 501 /* for use I SRAM as framebuffer. */ 502 PSLR |= 0x00000F04; 503 PCFR = 0x00000066; 504} 505 506MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine") 507 /* Maintainer: Peter Barada */ 508 .atag_offset = 0x100, 509 .map_io = lpd270_map_io, 510 .nr_irqs = LPD270_NR_IRQS, 511 .init_irq = lpd270_init_irq, 512 .handle_irq = pxa27x_handle_irq, 513 .init_time = pxa_timer_init, 514 .init_machine = lpd270_init, 515 .restart = pxa_restart, 516MACHINE_END 517