1/* 2 * linux/arch/arm/mach-pxa/cm-x2xx.c 3 * 4 * Copyright (C) 2008 CompuLab, Ltd. 5 * Mike Rapoport <mike@compulab.co.il> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12#include <linux/platform_device.h> 13#include <linux/syscore_ops.h> 14#include <linux/irq.h> 15#include <linux/gpio.h> 16#include <linux/regulator/machine.h> 17 18#include <linux/dm9000.h> 19#include <linux/leds.h> 20 21#include <asm/mach/arch.h> 22#include <asm/mach-types.h> 23#include <asm/mach/map.h> 24 25#include <mach/pxa25x.h> 26#undef GPIO24_SSP1_SFRM 27#include <mach/pxa27x.h> 28#include <mach/audio.h> 29#include <linux/platform_data/video-pxafb.h> 30#include <mach/smemc.h> 31 32#include <asm/hardware/it8152.h> 33 34#include "generic.h" 35#include "cm-x2xx-pci.h" 36 37extern void cmx255_init(void); 38extern void cmx270_init(void); 39 40/* reserve IRQs for IT8152 */ 41#define CMX2XX_NR_IRQS (IRQ_BOARD_START + 40) 42 43/* virtual addresses for statically mapped regions */ 44#define CMX2XX_VIRT_BASE (void __iomem *)(0xe8000000) 45#define CMX2XX_IT8152_VIRT (CMX2XX_VIRT_BASE) 46 47/* physical address if local-bus attached devices */ 48#define CMX255_DM9000_PHYS_BASE (PXA_CS1_PHYS + (8 << 22)) 49#define CMX270_DM9000_PHYS_BASE (PXA_CS1_PHYS + (6 << 22)) 50 51/* leds */ 52#define CMX255_GPIO_RED (27) 53#define CMX255_GPIO_GREEN (32) 54#define CMX270_GPIO_RED (93) 55#define CMX270_GPIO_GREEN (94) 56 57/* GPIO IRQ usage */ 58#define GPIO22_ETHIRQ (22) 59#define GPIO10_ETHIRQ (10) 60#define CMX255_GPIO_IT8152_IRQ (0) 61#define CMX270_GPIO_IT8152_IRQ (22) 62 63#define CMX255_ETHIRQ PXA_GPIO_TO_IRQ(GPIO22_ETHIRQ) 64#define CMX270_ETHIRQ PXA_GPIO_TO_IRQ(GPIO10_ETHIRQ) 65 66#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) 67static struct resource cmx255_dm9000_resource[] = { 68 [0] = { 69 .start = CMX255_DM9000_PHYS_BASE, 70 .end = CMX255_DM9000_PHYS_BASE + 3, 71 .flags = IORESOURCE_MEM, 72 }, 73 [1] = { 74 .start = CMX255_DM9000_PHYS_BASE + 4, 75 .end = CMX255_DM9000_PHYS_BASE + 4 + 500, 76 .flags = IORESOURCE_MEM, 77 }, 78 [2] = { 79 .start = CMX255_ETHIRQ, 80 .end = CMX255_ETHIRQ, 81 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, 82 } 83}; 84 85static struct resource cmx270_dm9000_resource[] = { 86 [0] = { 87 .start = CMX270_DM9000_PHYS_BASE, 88 .end = CMX270_DM9000_PHYS_BASE + 3, 89 .flags = IORESOURCE_MEM, 90 }, 91 [1] = { 92 .start = CMX270_DM9000_PHYS_BASE + 8, 93 .end = CMX270_DM9000_PHYS_BASE + 8 + 500, 94 .flags = IORESOURCE_MEM, 95 }, 96 [2] = { 97 .start = CMX270_ETHIRQ, 98 .end = CMX270_ETHIRQ, 99 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, 100 } 101}; 102 103static struct dm9000_plat_data cmx270_dm9000_platdata = { 104 .flags = DM9000_PLATF_32BITONLY | DM9000_PLATF_NO_EEPROM, 105}; 106 107static struct platform_device cmx2xx_dm9000_device = { 108 .name = "dm9000", 109 .id = 0, 110 .num_resources = ARRAY_SIZE(cmx270_dm9000_resource), 111 .dev = { 112 .platform_data = &cmx270_dm9000_platdata, 113 } 114}; 115 116static void __init cmx2xx_init_dm9000(void) 117{ 118 if (cpu_is_pxa25x()) 119 cmx2xx_dm9000_device.resource = cmx255_dm9000_resource; 120 else 121 cmx2xx_dm9000_device.resource = cmx270_dm9000_resource; 122 platform_device_register(&cmx2xx_dm9000_device); 123} 124#else 125static inline void cmx2xx_init_dm9000(void) {} 126#endif 127 128/* UCB1400 touchscreen controller */ 129#if defined(CONFIG_TOUCHSCREEN_UCB1400) || defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE) 130static struct platform_device cmx2xx_ts_device = { 131 .name = "ucb1400_core", 132 .id = -1, 133}; 134 135static void __init cmx2xx_init_touchscreen(void) 136{ 137 platform_device_register(&cmx2xx_ts_device); 138} 139#else 140static inline void cmx2xx_init_touchscreen(void) {} 141#endif 142 143/* CM-X270 LEDs */ 144#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) 145static struct gpio_led cmx2xx_leds[] = { 146 [0] = { 147 .name = "cm-x2xx:red", 148 .default_trigger = "nand-disk", 149 .active_low = 1, 150 }, 151 [1] = { 152 .name = "cm-x2xx:green", 153 .default_trigger = "heartbeat", 154 .active_low = 1, 155 }, 156}; 157 158static struct gpio_led_platform_data cmx2xx_gpio_led_pdata = { 159 .num_leds = ARRAY_SIZE(cmx2xx_leds), 160 .leds = cmx2xx_leds, 161}; 162 163static struct platform_device cmx2xx_led_device = { 164 .name = "leds-gpio", 165 .id = -1, 166 .dev = { 167 .platform_data = &cmx2xx_gpio_led_pdata, 168 }, 169}; 170 171static void __init cmx2xx_init_leds(void) 172{ 173 if (cpu_is_pxa25x()) { 174 cmx2xx_leds[0].gpio = CMX255_GPIO_RED; 175 cmx2xx_leds[1].gpio = CMX255_GPIO_GREEN; 176 } else { 177 cmx2xx_leds[0].gpio = CMX270_GPIO_RED; 178 cmx2xx_leds[1].gpio = CMX270_GPIO_GREEN; 179 } 180 platform_device_register(&cmx2xx_led_device); 181} 182#else 183static inline void cmx2xx_init_leds(void) {} 184#endif 185 186#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) 187/* 188 Display definitions 189 keep these for backwards compatibility, although symbolic names (as 190 e.g. in lpd270.c) looks better 191*/ 192#define MTYPE_STN320x240 0 193#define MTYPE_TFT640x480 1 194#define MTYPE_CRT640x480 2 195#define MTYPE_CRT800x600 3 196#define MTYPE_TFT320x240 6 197#define MTYPE_STN640x480 7 198 199static struct pxafb_mode_info generic_stn_320x240_mode = { 200 .pixclock = 76923, 201 .bpp = 8, 202 .xres = 320, 203 .yres = 240, 204 .hsync_len = 3, 205 .vsync_len = 2, 206 .left_margin = 3, 207 .upper_margin = 0, 208 .right_margin = 3, 209 .lower_margin = 0, 210 .sync = (FB_SYNC_HOR_HIGH_ACT | 211 FB_SYNC_VERT_HIGH_ACT), 212 .cmap_greyscale = 0, 213}; 214 215static struct pxafb_mach_info generic_stn_320x240 = { 216 .modes = &generic_stn_320x240_mode, 217 .num_modes = 1, 218 .lcd_conn = LCD_COLOR_STN_8BPP | LCD_PCLK_EDGE_FALL |\ 219 LCD_AC_BIAS_FREQ(0xff), 220 .cmap_inverse = 0, 221 .cmap_static = 0, 222}; 223 224static struct pxafb_mode_info generic_tft_640x480_mode = { 225 .pixclock = 38461, 226 .bpp = 8, 227 .xres = 640, 228 .yres = 480, 229 .hsync_len = 60, 230 .vsync_len = 2, 231 .left_margin = 70, 232 .upper_margin = 10, 233 .right_margin = 70, 234 .lower_margin = 5, 235 .sync = 0, 236 .cmap_greyscale = 0, 237}; 238 239static struct pxafb_mach_info generic_tft_640x480 = { 240 .modes = &generic_tft_640x480_mode, 241 .num_modes = 1, 242 .lcd_conn = LCD_COLOR_TFT_8BPP | LCD_PCLK_EDGE_FALL |\ 243 LCD_AC_BIAS_FREQ(0xff), 244 .cmap_inverse = 0, 245 .cmap_static = 0, 246}; 247 248static struct pxafb_mode_info generic_crt_640x480_mode = { 249 .pixclock = 38461, 250 .bpp = 8, 251 .xres = 640, 252 .yres = 480, 253 .hsync_len = 63, 254 .vsync_len = 2, 255 .left_margin = 81, 256 .upper_margin = 33, 257 .right_margin = 16, 258 .lower_margin = 10, 259 .sync = (FB_SYNC_HOR_HIGH_ACT | 260 FB_SYNC_VERT_HIGH_ACT), 261 .cmap_greyscale = 0, 262}; 263 264static struct pxafb_mach_info generic_crt_640x480 = { 265 .modes = &generic_crt_640x480_mode, 266 .num_modes = 1, 267 .lcd_conn = LCD_COLOR_TFT_8BPP | LCD_AC_BIAS_FREQ(0xff), 268 .cmap_inverse = 0, 269 .cmap_static = 0, 270}; 271 272static struct pxafb_mode_info generic_crt_800x600_mode = { 273 .pixclock = 28846, 274 .bpp = 8, 275 .xres = 800, 276 .yres = 600, 277 .hsync_len = 63, 278 .vsync_len = 2, 279 .left_margin = 26, 280 .upper_margin = 21, 281 .right_margin = 26, 282 .lower_margin = 11, 283 .sync = (FB_SYNC_HOR_HIGH_ACT | 284 FB_SYNC_VERT_HIGH_ACT), 285 .cmap_greyscale = 0, 286}; 287 288static struct pxafb_mach_info generic_crt_800x600 = { 289 .modes = &generic_crt_800x600_mode, 290 .num_modes = 1, 291 .lcd_conn = LCD_COLOR_TFT_8BPP | LCD_AC_BIAS_FREQ(0xff), 292 .cmap_inverse = 0, 293 .cmap_static = 0, 294}; 295 296static struct pxafb_mode_info generic_tft_320x240_mode = { 297 .pixclock = 134615, 298 .bpp = 16, 299 .xres = 320, 300 .yres = 240, 301 .hsync_len = 63, 302 .vsync_len = 7, 303 .left_margin = 75, 304 .upper_margin = 0, 305 .right_margin = 15, 306 .lower_margin = 15, 307 .sync = 0, 308 .cmap_greyscale = 0, 309}; 310 311static struct pxafb_mach_info generic_tft_320x240 = { 312 .modes = &generic_tft_320x240_mode, 313 .num_modes = 1, 314 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_AC_BIAS_FREQ(0xff), 315 .cmap_inverse = 0, 316 .cmap_static = 0, 317}; 318 319static struct pxafb_mode_info generic_stn_640x480_mode = { 320 .pixclock = 57692, 321 .bpp = 8, 322 .xres = 640, 323 .yres = 480, 324 .hsync_len = 4, 325 .vsync_len = 2, 326 .left_margin = 10, 327 .upper_margin = 5, 328 .right_margin = 10, 329 .lower_margin = 5, 330 .sync = (FB_SYNC_HOR_HIGH_ACT | 331 FB_SYNC_VERT_HIGH_ACT), 332 .cmap_greyscale = 0, 333}; 334 335static struct pxafb_mach_info generic_stn_640x480 = { 336 .modes = &generic_stn_640x480_mode, 337 .num_modes = 1, 338 .lcd_conn = LCD_COLOR_STN_8BPP | LCD_AC_BIAS_FREQ(0xff), 339 .cmap_inverse = 0, 340 .cmap_static = 0, 341}; 342 343static struct pxafb_mach_info *cmx2xx_display = &generic_crt_640x480; 344 345static int __init cmx2xx_set_display(char *str) 346{ 347 int disp_type = simple_strtol(str, NULL, 0); 348 switch (disp_type) { 349 case MTYPE_STN320x240: 350 cmx2xx_display = &generic_stn_320x240; 351 break; 352 case MTYPE_TFT640x480: 353 cmx2xx_display = &generic_tft_640x480; 354 break; 355 case MTYPE_CRT640x480: 356 cmx2xx_display = &generic_crt_640x480; 357 break; 358 case MTYPE_CRT800x600: 359 cmx2xx_display = &generic_crt_800x600; 360 break; 361 case MTYPE_TFT320x240: 362 cmx2xx_display = &generic_tft_320x240; 363 break; 364 case MTYPE_STN640x480: 365 cmx2xx_display = &generic_stn_640x480; 366 break; 367 default: /* fallback to CRT 640x480 */ 368 cmx2xx_display = &generic_crt_640x480; 369 break; 370 } 371 return 1; 372} 373 374/* 375 This should be done really early to get proper configuration for 376 frame buffer. 377 Indeed, pxafb parameters can be used istead, but CM-X2XX bootloader 378 has limitied line length for kernel command line, and also it will 379 break compatibitlty with proprietary releases already in field. 380*/ 381__setup("monitor=", cmx2xx_set_display); 382 383static void __init cmx2xx_init_display(void) 384{ 385 pxa_set_fb_info(NULL, cmx2xx_display); 386} 387#else 388static inline void cmx2xx_init_display(void) {} 389#endif 390 391#ifdef CONFIG_PM 392static unsigned long sleep_save_msc[10]; 393 394static int cmx2xx_suspend(void) 395{ 396 cmx2xx_pci_suspend(); 397 398 /* save MSC registers */ 399 sleep_save_msc[0] = __raw_readl(MSC0); 400 sleep_save_msc[1] = __raw_readl(MSC1); 401 sleep_save_msc[2] = __raw_readl(MSC2); 402 403 /* setup power saving mode registers */ 404 PCFR = 0x0; 405 PSLR = 0xff400000; 406 PMCR = 0x00000005; 407 PWER = 0x80000000; 408 PFER = 0x00000000; 409 PRER = 0x00000000; 410 PGSR0 = 0xC0018800; 411 PGSR1 = 0x004F0002; 412 PGSR2 = 0x6021C000; 413 PGSR3 = 0x00020000; 414 415 return 0; 416} 417 418static void cmx2xx_resume(void) 419{ 420 cmx2xx_pci_resume(); 421 422 /* restore MSC registers */ 423 __raw_writel(sleep_save_msc[0], MSC0); 424 __raw_writel(sleep_save_msc[1], MSC1); 425 __raw_writel(sleep_save_msc[2], MSC2); 426} 427 428static struct syscore_ops cmx2xx_pm_syscore_ops = { 429 .resume = cmx2xx_resume, 430 .suspend = cmx2xx_suspend, 431}; 432 433static int __init cmx2xx_pm_init(void) 434{ 435 register_syscore_ops(&cmx2xx_pm_syscore_ops); 436 437 return 0; 438} 439#else 440static int __init cmx2xx_pm_init(void) { return 0; } 441#endif 442 443#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE) 444static void __init cmx2xx_init_ac97(void) 445{ 446 pxa_set_ac97_info(NULL); 447} 448#else 449static inline void cmx2xx_init_ac97(void) {} 450#endif 451 452static void __init cmx2xx_init(void) 453{ 454 pxa_set_ffuart_info(NULL); 455 pxa_set_btuart_info(NULL); 456 pxa_set_stuart_info(NULL); 457 458 cmx2xx_pm_init(); 459 460 if (cpu_is_pxa25x()) 461 cmx255_init(); 462 else 463 cmx270_init(); 464 465 cmx2xx_init_dm9000(); 466 cmx2xx_init_display(); 467 cmx2xx_init_ac97(); 468 cmx2xx_init_touchscreen(); 469 cmx2xx_init_leds(); 470 471 regulator_has_full_constraints(); 472} 473 474static void __init cmx2xx_init_irq(void) 475{ 476 if (cpu_is_pxa25x()) { 477 pxa25x_init_irq(); 478 cmx2xx_pci_init_irq(CMX255_GPIO_IT8152_IRQ); 479 } else { 480 pxa27x_init_irq(); 481 cmx2xx_pci_init_irq(CMX270_GPIO_IT8152_IRQ); 482 } 483} 484 485#ifdef CONFIG_PCI 486/* Map PCI companion statically */ 487static struct map_desc cmx2xx_io_desc[] __initdata = { 488 [0] = { /* PCI bridge */ 489 .virtual = (unsigned long)CMX2XX_IT8152_VIRT, 490 .pfn = __phys_to_pfn(PXA_CS4_PHYS), 491 .length = SZ_64M, 492 .type = MT_DEVICE 493 }, 494}; 495 496static void __init cmx2xx_map_io(void) 497{ 498 if (cpu_is_pxa25x()) 499 pxa25x_map_io(); 500 501 if (cpu_is_pxa27x()) 502 pxa27x_map_io(); 503 504 iotable_init(cmx2xx_io_desc, ARRAY_SIZE(cmx2xx_io_desc)); 505 506 it8152_base_address = CMX2XX_IT8152_VIRT; 507} 508#else 509static void __init cmx2xx_map_io(void) 510{ 511 if (cpu_is_pxa25x()) 512 pxa25x_map_io(); 513 514 if (cpu_is_pxa27x()) 515 pxa27x_map_io(); 516} 517#endif 518 519MACHINE_START(ARMCORE, "Compulab CM-X2XX") 520 .atag_offset = 0x100, 521 .map_io = cmx2xx_map_io, 522 .nr_irqs = CMX2XX_NR_IRQS, 523 .init_irq = cmx2xx_init_irq, 524 /* NOTE: pxa25x_handle_irq() works on PXA27x w/o camera support */ 525 .handle_irq = pxa25x_handle_irq, 526 .init_time = pxa_timer_init, 527 .init_machine = cmx2xx_init, 528#ifdef CONFIG_PCI 529 .dma_zone_size = SZ_64M, 530#endif 531 .restart = pxa_restart, 532MACHINE_END 533