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