linux/arch/arm/mach-s3c2410/mach-h1940.c
<<
>>
Prefs
   1/* linux/arch/arm/mach-s3c2410/mach-h1940.c
   2 *
   3 * Copyright (c) 2003-2005 Simtec Electronics
   4 *   Ben Dooks <ben@simtec.co.uk>
   5 *
   6 * http://www.handhelds.org/projects/h1940.html
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  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/memblock.h>
  19#include <linux/timer.h>
  20#include <linux/init.h>
  21#include <linux/sysdev.h>
  22#include <linux/serial_core.h>
  23#include <linux/platform_device.h>
  24#include <linux/io.h>
  25#include <linux/gpio.h>
  26#include <linux/pwm_backlight.h>
  27#include <linux/i2c.h>
  28#include <video/platform_lcd.h>
  29
  30#include <linux/mmc/host.h>
  31
  32#include <asm/mach/arch.h>
  33#include <asm/mach/map.h>
  34#include <asm/mach/irq.h>
  35
  36#include <mach/hardware.h>
  37#include <asm/irq.h>
  38#include <asm/mach-types.h>
  39
  40#include <plat/regs-serial.h>
  41#include <mach/regs-lcd.h>
  42#include <mach/regs-clock.h>
  43
  44#include <mach/regs-gpio.h>
  45#include <mach/gpio-fns.h>
  46#include <mach/gpio-nrs.h>
  47
  48#include <mach/h1940.h>
  49#include <mach/h1940-latch.h>
  50#include <mach/fb.h>
  51#include <plat/udc.h>
  52#include <plat/iic.h>
  53
  54#include <plat/gpio-cfg.h>
  55#include <plat/clock.h>
  56#include <plat/devs.h>
  57#include <plat/cpu.h>
  58#include <plat/pll.h>
  59#include <plat/pm.h>
  60#include <plat/mci.h>
  61#include <plat/ts.h>
  62
  63#include <sound/uda1380.h>
  64
  65#define H1940_LATCH             ((void __force __iomem *)0xF8000000)
  66
  67#define H1940_PA_LATCH          S3C2410_CS2
  68
  69#define H1940_LATCH_BIT(x)      (1 << ((x) + 16 - S3C_GPIO_END))
  70
  71static struct map_desc h1940_iodesc[] __initdata = {
  72        [0] = {
  73                .virtual        = (unsigned long)H1940_LATCH,
  74                .pfn            = __phys_to_pfn(H1940_PA_LATCH),
  75                .length         = SZ_16K,
  76                .type           = MT_DEVICE
  77        },
  78};
  79
  80#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
  81#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
  82#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
  83
  84static struct s3c2410_uartcfg h1940_uartcfgs[] __initdata = {
  85        [0] = {
  86                .hwport      = 0,
  87                .flags       = 0,
  88                .ucon        = 0x3c5,
  89                .ulcon       = 0x03,
  90                .ufcon       = 0x51,
  91        },
  92        [1] = {
  93                .hwport      = 1,
  94                .flags       = 0,
  95                .ucon        = 0x245,
  96                .ulcon       = 0x03,
  97                .ufcon       = 0x00,
  98        },
  99        /* IR port */
 100        [2] = {
 101                .hwport      = 2,
 102                .flags       = 0,
 103                .uart_flags  = UPF_CONS_FLOW,
 104                .ucon        = 0x3c5,
 105                .ulcon       = 0x43,
 106                .ufcon       = 0x51,
 107        }
 108};
 109
 110/* Board control latch control */
 111
 112static unsigned int latch_state;
 113
 114static void h1940_latch_control(unsigned int clear, unsigned int set)
 115{
 116        unsigned long flags;
 117
 118        local_irq_save(flags);
 119
 120        latch_state &= ~clear;
 121        latch_state |= set;
 122
 123        __raw_writel(latch_state, H1940_LATCH);
 124
 125        local_irq_restore(flags);
 126}
 127
 128static inline int h1940_gpiolib_to_latch(int offset)
 129{
 130        return 1 << (offset + 16);
 131}
 132
 133static void h1940_gpiolib_latch_set(struct gpio_chip *chip,
 134                                        unsigned offset, int value)
 135{
 136        int latch_bit = h1940_gpiolib_to_latch(offset);
 137
 138        h1940_latch_control(value ? 0 : latch_bit,
 139                value ? latch_bit : 0);
 140}
 141
 142static int h1940_gpiolib_latch_output(struct gpio_chip *chip,
 143                                        unsigned offset, int value)
 144{
 145        h1940_gpiolib_latch_set(chip, offset, value);
 146        return 0;
 147}
 148
 149static int h1940_gpiolib_latch_get(struct gpio_chip *chip,
 150                                        unsigned offset)
 151{
 152        return (latch_state >> (offset + 16)) & 1;
 153}
 154
 155struct gpio_chip h1940_latch_gpiochip = {
 156        .base                   = H1940_LATCH_GPIO(0),
 157        .owner                  = THIS_MODULE,
 158        .label                  = "H1940_LATCH",
 159        .ngpio                  = 16,
 160        .direction_output       = h1940_gpiolib_latch_output,
 161        .set                    = h1940_gpiolib_latch_set,
 162        .get                    = h1940_gpiolib_latch_get,
 163};
 164
 165static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd)
 166{
 167        printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
 168
 169        switch (cmd)
 170        {
 171                case S3C2410_UDC_P_ENABLE :
 172                        gpio_set_value(H1940_LATCH_USB_DP, 1);
 173                        break;
 174                case S3C2410_UDC_P_DISABLE :
 175                        gpio_set_value(H1940_LATCH_USB_DP, 0);
 176                        break;
 177                case S3C2410_UDC_P_RESET :
 178                        break;
 179                default:
 180                        break;
 181        }
 182}
 183
 184static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
 185        .udc_command            = h1940_udc_pullup,
 186        .vbus_pin               = S3C2410_GPG(5),
 187        .vbus_pin_inverted      = 1,
 188};
 189
 190static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
 191                .delay = 10000,
 192                .presc = 49,
 193                .oversampling_shift = 2,
 194                .cfg_gpio = s3c24xx_ts_cfg_gpio,
 195};
 196
 197/**
 198 * Set lcd on or off
 199 **/
 200static struct s3c2410fb_display h1940_lcd __initdata = {
 201        .lcdcon5=       S3C2410_LCDCON5_FRM565 | \
 202                        S3C2410_LCDCON5_INVVLINE | \
 203                        S3C2410_LCDCON5_HWSWP,
 204
 205        .type =         S3C2410_LCDCON1_TFT,
 206        .width =        240,
 207        .height =       320,
 208        .pixclock =     260000,
 209        .xres =         240,
 210        .yres =         320,
 211        .bpp =          16,
 212        .left_margin =  8,
 213        .right_margin = 20,
 214        .hsync_len =    4,
 215        .upper_margin = 8,
 216        .lower_margin = 7,
 217        .vsync_len =    1,
 218};
 219
 220static struct s3c2410fb_mach_info h1940_fb_info __initdata = {
 221        .displays = &h1940_lcd,
 222        .num_displays = 1,
 223        .default_display = 0,
 224
 225        .lpcsel=        0x02,
 226        .gpccon=        0xaa940659,
 227        .gpccon_mask=   0xffffffff,
 228        .gpcup=         0x0000ffff,
 229        .gpcup_mask=    0xffffffff,
 230        .gpdcon=        0xaa84aaa0,
 231        .gpdcon_mask=   0xffffffff,
 232        .gpdup=         0x0000faff,
 233        .gpdup_mask=    0xffffffff,
 234};
 235
 236static struct platform_device h1940_device_leds = {
 237        .name             = "h1940-leds",
 238        .id               = -1,
 239};
 240
 241static struct platform_device h1940_device_bluetooth = {
 242        .name             = "h1940-bt",
 243        .id               = -1,
 244};
 245
 246static void h1940_set_mmc_power(unsigned char power_mode, unsigned short vdd)
 247{
 248        switch (power_mode) {
 249        case MMC_POWER_OFF:
 250                gpio_set_value(H1940_LATCH_SD_POWER, 0);
 251                break;
 252        case MMC_POWER_UP:
 253        case MMC_POWER_ON:
 254                gpio_set_value(H1940_LATCH_SD_POWER, 1);
 255                break;
 256        default:
 257                break;
 258        };
 259}
 260
 261static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = {
 262        .gpio_detect   = S3C2410_GPF(5),
 263        .gpio_wprotect = S3C2410_GPH(8),
 264        .set_power     = h1940_set_mmc_power,
 265        .ocr_avail     = MMC_VDD_32_33,
 266};
 267
 268static int h1940_backlight_init(struct device *dev)
 269{
 270        gpio_request(S3C2410_GPB(0), "Backlight");
 271
 272        gpio_direction_output(S3C2410_GPB(0), 0);
 273        s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE);
 274        s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
 275        gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 1);
 276
 277        return 0;
 278}
 279
 280static int h1940_backlight_notify(struct device *dev, int brightness)
 281{
 282        if (!brightness) {
 283                gpio_direction_output(S3C2410_GPB(0), 1);
 284                gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 0);
 285        } else {
 286                gpio_direction_output(S3C2410_GPB(0), 0);
 287                s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE);
 288                s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
 289                gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 1);
 290        }
 291        return brightness;
 292}
 293
 294static void h1940_backlight_exit(struct device *dev)
 295{
 296        gpio_direction_output(S3C2410_GPB(0), 1);
 297        gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 0);
 298}
 299
 300
 301static struct platform_pwm_backlight_data backlight_data = {
 302        .pwm_id         = 0,
 303        .max_brightness = 100,
 304        .dft_brightness = 50,
 305        /* tcnt = 0x31 */
 306        .pwm_period_ns  = 36296,
 307        .init           = h1940_backlight_init,
 308        .notify         = h1940_backlight_notify,
 309        .exit           = h1940_backlight_exit,
 310};
 311
 312static struct platform_device h1940_backlight = {
 313        .name = "pwm-backlight",
 314        .dev  = {
 315                .parent = &s3c_device_timer[0].dev,
 316                .platform_data = &backlight_data,
 317        },
 318        .id   = -1,
 319};
 320
 321static void h1940_lcd_power_set(struct plat_lcd_data *pd,
 322                                        unsigned int power)
 323{
 324        int value;
 325
 326        if (!power) {
 327                gpio_set_value(S3C2410_GPC(0), 0);
 328                /* wait for 3ac */
 329                do {
 330                        value = gpio_get_value(S3C2410_GPC(6));
 331                } while (value);
 332
 333                gpio_set_value(H1940_LATCH_LCD_P2, 0);
 334                gpio_set_value(H1940_LATCH_LCD_P3, 0);
 335                gpio_set_value(H1940_LATCH_LCD_P4, 0);
 336
 337                gpio_direction_output(S3C2410_GPC(1), 0);
 338                gpio_direction_output(S3C2410_GPC(4), 0);
 339
 340                gpio_set_value(H1940_LATCH_LCD_P1, 0);
 341                gpio_set_value(H1940_LATCH_LCD_P0, 0);
 342
 343                gpio_set_value(S3C2410_GPC(5), 0);
 344
 345        } else {
 346                gpio_set_value(H1940_LATCH_LCD_P0, 1);
 347                gpio_set_value(H1940_LATCH_LCD_P1, 1);
 348
 349                s3c_gpio_cfgpin(S3C2410_GPC(1), S3C_GPIO_SFN(2));
 350                s3c_gpio_cfgpin(S3C2410_GPC(4), S3C_GPIO_SFN(2));
 351
 352                gpio_set_value(S3C2410_GPC(5), 1);
 353                gpio_set_value(S3C2410_GPC(0), 1);
 354
 355                gpio_set_value(H1940_LATCH_LCD_P3, 1);
 356                gpio_set_value(H1940_LATCH_LCD_P2, 1);
 357                gpio_set_value(H1940_LATCH_LCD_P4, 1);
 358        }
 359}
 360
 361static struct plat_lcd_data h1940_lcd_power_data = {
 362        .set_power      = h1940_lcd_power_set,
 363};
 364
 365static struct platform_device h1940_lcd_powerdev = {
 366        .name                   = "platform-lcd",
 367        .dev.parent             = &s3c_device_lcd.dev,
 368        .dev.platform_data      = &h1940_lcd_power_data,
 369};
 370
 371static struct uda1380_platform_data uda1380_info = {
 372        .gpio_power     = H1940_LATCH_UDA_POWER,
 373        .gpio_reset     = S3C2410_GPA(12),
 374        .dac_clk        = UDA1380_DAC_CLK_SYSCLK,
 375};
 376
 377static struct i2c_board_info h1940_i2c_devices[] = {
 378        {
 379                I2C_BOARD_INFO("uda1380", 0x1a),
 380                .platform_data = &uda1380_info,
 381        },
 382};
 383
 384static struct platform_device *h1940_devices[] __initdata = {
 385        &s3c_device_ohci,
 386        &s3c_device_lcd,
 387        &s3c_device_wdt,
 388        &s3c_device_i2c0,
 389        &s3c_device_iis,
 390        &samsung_asoc_dma,
 391        &s3c_device_usbgadget,
 392        &h1940_device_leds,
 393        &h1940_device_bluetooth,
 394        &s3c_device_sdi,
 395        &s3c_device_rtc,
 396        &s3c_device_timer[0],
 397        &h1940_backlight,
 398        &h1940_lcd_powerdev,
 399        &s3c_device_adc,
 400        &s3c_device_ts,
 401};
 402
 403static void __init h1940_map_io(void)
 404{
 405        s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
 406        s3c24xx_init_clocks(0);
 407        s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
 408
 409        /* setup PM */
 410
 411#ifdef CONFIG_PM_H1940
 412        memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
 413#endif
 414        s3c_pm_init();
 415
 416        /* Add latch gpio chip, set latch initial value */
 417        h1940_latch_control(0, 0);
 418        WARN_ON(gpiochip_add(&h1940_latch_gpiochip));
 419}
 420
 421/* H1940 and RX3715 need to reserve this for suspend */
 422static void __init h1940_reserve(void)
 423{
 424        memblock_reserve(0x30003000, 0x1000);
 425        memblock_reserve(0x30081000, 0x1000);
 426}
 427
 428static void __init h1940_init_irq(void)
 429{
 430        s3c24xx_init_irq();
 431}
 432
 433static void __init h1940_init(void)
 434{
 435        u32 tmp;
 436
 437        s3c24xx_fb_set_platdata(&h1940_fb_info);
 438        s3c24xx_mci_set_platdata(&h1940_mmc_cfg);
 439        s3c24xx_udc_set_platdata(&h1940_udc_cfg);
 440        s3c24xx_ts_set_platdata(&h1940_ts_cfg);
 441        s3c_i2c0_set_platdata(NULL);
 442
 443        /* Turn off suspend on both USB ports, and switch the
 444         * selectable USB port to USB device mode. */
 445
 446        s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
 447                              S3C2410_MISCCR_USBSUSPND0 |
 448                              S3C2410_MISCCR_USBSUSPND1, 0x0);
 449
 450        tmp =   (0x78 << S3C24XX_PLLCON_MDIVSHIFT)
 451              | (0x02 << S3C24XX_PLLCON_PDIVSHIFT)
 452              | (0x03 << S3C24XX_PLLCON_SDIVSHIFT);
 453        writel(tmp, S3C2410_UPLLCON);
 454
 455        gpio_request(S3C2410_GPC(0), "LCD power");
 456        gpio_request(S3C2410_GPC(1), "LCD power");
 457        gpio_request(S3C2410_GPC(4), "LCD power");
 458        gpio_request(S3C2410_GPC(5), "LCD power");
 459        gpio_request(S3C2410_GPC(6), "LCD power");
 460        gpio_request(H1940_LATCH_LCD_P0, "LCD power");
 461        gpio_request(H1940_LATCH_LCD_P1, "LCD power");
 462        gpio_request(H1940_LATCH_LCD_P2, "LCD power");
 463        gpio_request(H1940_LATCH_LCD_P3, "LCD power");
 464        gpio_request(H1940_LATCH_LCD_P4, "LCD power");
 465        gpio_request(H1940_LATCH_MAX1698_nSHUTDOWN, "LCD power");
 466        gpio_direction_output(S3C2410_GPC(0), 0);
 467        gpio_direction_output(S3C2410_GPC(1), 0);
 468        gpio_direction_output(S3C2410_GPC(4), 0);
 469        gpio_direction_output(S3C2410_GPC(5), 0);
 470        gpio_direction_input(S3C2410_GPC(6));
 471        gpio_direction_output(H1940_LATCH_LCD_P0, 0);
 472        gpio_direction_output(H1940_LATCH_LCD_P1, 0);
 473        gpio_direction_output(H1940_LATCH_LCD_P2, 0);
 474        gpio_direction_output(H1940_LATCH_LCD_P3, 0);
 475        gpio_direction_output(H1940_LATCH_LCD_P4, 0);
 476        gpio_direction_output(H1940_LATCH_MAX1698_nSHUTDOWN, 0);
 477
 478        gpio_request(H1940_LATCH_USB_DP, "USB pullup");
 479        gpio_direction_output(H1940_LATCH_USB_DP, 0);
 480
 481        gpio_request(H1940_LATCH_SD_POWER, "SD power");
 482        gpio_direction_output(H1940_LATCH_SD_POWER, 0);
 483
 484        platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
 485
 486        i2c_register_board_info(0, h1940_i2c_devices,
 487                ARRAY_SIZE(h1940_i2c_devices));
 488}
 489
 490MACHINE_START(H1940, "IPAQ-H1940")
 491        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 492        .boot_params    = S3C2410_SDRAM_PA + 0x100,
 493        .map_io         = h1940_map_io,
 494        .reserve        = h1940_reserve,
 495        .init_irq       = h1940_init_irq,
 496        .init_machine   = h1940_init,
 497        .timer          = &s3c24xx_timer,
 498MACHINE_END
 499