linux/arch/arm/mach-s3c24xx/mach-rx1950.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006-2009 Victor Chukhantsev, Denis Grigoriev,
   3 * Copyright (c) 2007-2010 Vasily Khoruzhick
   4 *
   5 * based on smdk2440 written by Ben Dooks
   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
  13#include <linux/kernel.h>
  14#include <linux/types.h>
  15#include <linux/interrupt.h>
  16#include <linux/list.h>
  17#include <linux/memblock.h>
  18#include <linux/delay.h>
  19#include <linux/timer.h>
  20#include <linux/init.h>
  21#include <linux/gpio.h>
  22#include <linux/platform_device.h>
  23#include <linux/serial_core.h>
  24#include <linux/serial_s3c.h>
  25#include <linux/input.h>
  26#include <linux/gpio_keys.h>
  27#include <linux/device.h>
  28#include <linux/pda_power.h>
  29#include <linux/pwm_backlight.h>
  30#include <linux/pwm.h>
  31#include <linux/s3c_adc_battery.h>
  32#include <linux/leds.h>
  33#include <linux/i2c.h>
  34
  35#include <linux/mtd/mtd.h>
  36#include <linux/mtd/partitions.h>
  37
  38#include <linux/mmc/host.h>
  39
  40#include <asm/mach-types.h>
  41#include <asm/mach/arch.h>
  42#include <asm/mach/map.h>
  43
  44#include <linux/platform_data/i2c-s3c2410.h>
  45#include <linux/platform_data/mmc-s3cmci.h>
  46#include <linux/platform_data/mtd-nand-s3c2410.h>
  47#include <linux/platform_data/touchscreen-s3c2410.h>
  48#include <linux/platform_data/usb-s3c2410_udc.h>
  49
  50#include <sound/uda1380.h>
  51
  52#include <mach/fb.h>
  53#include <mach/regs-gpio.h>
  54#include <mach/regs-lcd.h>
  55#include <mach/gpio-samsung.h>
  56
  57#include <plat/cpu.h>
  58#include <plat/devs.h>
  59#include <plat/pm.h>
  60#include <plat/samsung-time.h>
  61#include <plat/gpio-cfg.h>
  62
  63#include "common.h"
  64#include "h1940.h"
  65
  66#define LCD_PWM_PERIOD 192960
  67#define LCD_PWM_DUTY 127353
  68
  69static struct map_desc rx1950_iodesc[] __initdata = {
  70};
  71
  72static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
  73        [0] = {
  74               .hwport = 0,
  75               .flags = 0,
  76               .ucon = 0x3c5,
  77               .ulcon = 0x03,
  78               .ufcon = 0x51,
  79                .clk_sel = S3C2410_UCON_CLKSEL3,
  80        },
  81        [1] = {
  82               .hwport = 1,
  83               .flags = 0,
  84               .ucon = 0x3c5,
  85               .ulcon = 0x03,
  86               .ufcon = 0x51,
  87                .clk_sel = S3C2410_UCON_CLKSEL3,
  88        },
  89        /* IR port */
  90        [2] = {
  91               .hwport = 2,
  92               .flags = 0,
  93               .ucon = 0x3c5,
  94               .ulcon = 0x43,
  95               .ufcon = 0xf1,
  96                .clk_sel = S3C2410_UCON_CLKSEL3,
  97        },
  98};
  99
 100static struct s3c2410fb_display rx1950_display = {
 101        .type = S3C2410_LCDCON1_TFT,
 102        .width = 240,
 103        .height = 320,
 104        .xres = 240,
 105        .yres = 320,
 106        .bpp = 16,
 107
 108        .pixclock = 260000,
 109        .left_margin = 10,
 110        .right_margin = 20,
 111        .hsync_len = 10,
 112        .upper_margin = 2,
 113        .lower_margin = 2,
 114        .vsync_len = 2,
 115
 116        .lcdcon5 = S3C2410_LCDCON5_FRM565 |
 117                           S3C2410_LCDCON5_INVVCLK |
 118                           S3C2410_LCDCON5_INVVLINE |
 119                           S3C2410_LCDCON5_INVVFRAME |
 120                           S3C2410_LCDCON5_HWSWP |
 121                           (0x02 << 13) |
 122                           (0x02 << 15),
 123
 124};
 125
 126static int power_supply_init(struct device *dev)
 127{
 128        return gpio_request(S3C2410_GPF(2), "cable plugged");
 129}
 130
 131static int rx1950_is_ac_online(void)
 132{
 133        return !gpio_get_value(S3C2410_GPF(2));
 134}
 135
 136static void power_supply_exit(struct device *dev)
 137{
 138        gpio_free(S3C2410_GPF(2));
 139}
 140
 141static char *rx1950_supplicants[] = {
 142        "main-battery"
 143};
 144
 145static struct pda_power_pdata power_supply_info = {
 146        .init                   = power_supply_init,
 147        .is_ac_online           = rx1950_is_ac_online,
 148        .exit                   = power_supply_exit,
 149        .supplied_to            = rx1950_supplicants,
 150        .num_supplicants        = ARRAY_SIZE(rx1950_supplicants),
 151};
 152
 153static struct resource power_supply_resources[] = {
 154        [0] = DEFINE_RES_NAMED(IRQ_EINT2, 1, "ac", IORESOURCE_IRQ \
 155                        | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE),
 156};
 157
 158static struct platform_device power_supply = {
 159        .name                   = "pda-power",
 160        .id                     = -1,
 161        .dev                    = {
 162                                        .platform_data =
 163                                                &power_supply_info,
 164        },
 165        .resource               = power_supply_resources,
 166        .num_resources          = ARRAY_SIZE(power_supply_resources),
 167};
 168
 169static const struct s3c_adc_bat_thresh bat_lut_noac[] = {
 170        { .volt = 4100, .cur = 156, .level = 100},
 171        { .volt = 4050, .cur = 156, .level = 95},
 172        { .volt = 4025, .cur = 141, .level = 90},
 173        { .volt = 3995, .cur = 144, .level = 85},
 174        { .volt = 3957, .cur = 162, .level = 80},
 175        { .volt = 3931, .cur = 147, .level = 75},
 176        { .volt = 3902, .cur = 147, .level = 70},
 177        { .volt = 3863, .cur = 153, .level = 65},
 178        { .volt = 3838, .cur = 150, .level = 60},
 179        { .volt = 3800, .cur = 153, .level = 55},
 180        { .volt = 3765, .cur = 153, .level = 50},
 181        { .volt = 3748, .cur = 172, .level = 45},
 182        { .volt = 3740, .cur = 153, .level = 40},
 183        { .volt = 3714, .cur = 175, .level = 35},
 184        { .volt = 3710, .cur = 156, .level = 30},
 185        { .volt = 3963, .cur = 156, .level = 25},
 186        { .volt = 3672, .cur = 178, .level = 20},
 187        { .volt = 3651, .cur = 178, .level = 15},
 188        { .volt = 3629, .cur = 178, .level = 10},
 189        { .volt = 3612, .cur = 162, .level = 5},
 190        { .volt = 3605, .cur = 162, .level = 0},
 191};
 192
 193static const struct s3c_adc_bat_thresh bat_lut_acin[] = {
 194        { .volt = 4200, .cur = 0, .level = 100},
 195        { .volt = 4190, .cur = 0, .level = 99},
 196        { .volt = 4178, .cur = 0, .level = 95},
 197        { .volt = 4110, .cur = 0, .level = 70},
 198        { .volt = 4076, .cur = 0, .level = 65},
 199        { .volt = 4046, .cur = 0, .level = 60},
 200        { .volt = 4021, .cur = 0, .level = 55},
 201        { .volt = 3999, .cur = 0, .level = 50},
 202        { .volt = 3982, .cur = 0, .level = 45},
 203        { .volt = 3965, .cur = 0, .level = 40},
 204        { .volt = 3957, .cur = 0, .level = 35},
 205        { .volt = 3948, .cur = 0, .level = 30},
 206        { .volt = 3936, .cur = 0, .level = 25},
 207        { .volt = 3927, .cur = 0, .level = 20},
 208        { .volt = 3906, .cur = 0, .level = 15},
 209        { .volt = 3880, .cur = 0, .level = 10},
 210        { .volt = 3829, .cur = 0, .level = 5},
 211        { .volt = 3820, .cur = 0, .level = 0},
 212};
 213
 214static int rx1950_bat_init(void)
 215{
 216        int ret;
 217
 218        ret = gpio_request(S3C2410_GPJ(2), "rx1950-charger-enable-1");
 219        if (ret)
 220                goto err_gpio1;
 221        ret = gpio_request(S3C2410_GPJ(3), "rx1950-charger-enable-2");
 222        if (ret)
 223                goto err_gpio2;
 224
 225        return 0;
 226
 227err_gpio2:
 228        gpio_free(S3C2410_GPJ(2));
 229err_gpio1:
 230        return ret;
 231}
 232
 233static void rx1950_bat_exit(void)
 234{
 235        gpio_free(S3C2410_GPJ(2));
 236        gpio_free(S3C2410_GPJ(3));
 237}
 238
 239static void rx1950_enable_charger(void)
 240{
 241        gpio_direction_output(S3C2410_GPJ(2), 1);
 242        gpio_direction_output(S3C2410_GPJ(3), 1);
 243}
 244
 245static void rx1950_disable_charger(void)
 246{
 247        gpio_direction_output(S3C2410_GPJ(2), 0);
 248        gpio_direction_output(S3C2410_GPJ(3), 0);
 249}
 250
 251static DEFINE_SPINLOCK(rx1950_blink_spin);
 252
 253static int rx1950_led_blink_set(struct gpio_desc *desc, int state,
 254        unsigned long *delay_on, unsigned long *delay_off)
 255{
 256        int gpio = desc_to_gpio(desc);
 257        int blink_gpio, check_gpio;
 258
 259        switch (gpio) {
 260        case S3C2410_GPA(6):
 261                blink_gpio = S3C2410_GPA(4);
 262                check_gpio = S3C2410_GPA(3);
 263                break;
 264        case S3C2410_GPA(7):
 265                blink_gpio = S3C2410_GPA(3);
 266                check_gpio = S3C2410_GPA(4);
 267                break;
 268        default:
 269                return -EINVAL;
 270                break;
 271        }
 272
 273        if (delay_on && delay_off && !*delay_on && !*delay_off)
 274                *delay_on = *delay_off = 500;
 275
 276        spin_lock(&rx1950_blink_spin);
 277
 278        switch (state) {
 279        case GPIO_LED_NO_BLINK_LOW:
 280        case GPIO_LED_NO_BLINK_HIGH:
 281                if (!gpio_get_value(check_gpio))
 282                        gpio_set_value(S3C2410_GPJ(6), 0);
 283                gpio_set_value(blink_gpio, 0);
 284                gpio_set_value(gpio, state);
 285                break;
 286        case GPIO_LED_BLINK:
 287                gpio_set_value(gpio, 0);
 288                gpio_set_value(S3C2410_GPJ(6), 1);
 289                gpio_set_value(blink_gpio, 1);
 290                break;
 291        }
 292
 293        spin_unlock(&rx1950_blink_spin);
 294
 295        return 0;
 296}
 297
 298static struct gpio_led rx1950_leds_desc[] = {
 299        {
 300                .name                   = "Green",
 301                .default_trigger        = "main-battery-full",
 302                .gpio                   = S3C2410_GPA(6),
 303                .retain_state_suspended = 1,
 304        },
 305        {
 306                .name                   = "Red",
 307                .default_trigger
 308                        = "main-battery-charging-blink-full-solid",
 309                .gpio                   = S3C2410_GPA(7),
 310                .retain_state_suspended = 1,
 311        },
 312        {
 313                .name                   = "Blue",
 314                .default_trigger        = "rx1950-acx-mem",
 315                .gpio                   = S3C2410_GPA(11),
 316                .retain_state_suspended = 1,
 317        },
 318};
 319
 320static struct gpio_led_platform_data rx1950_leds_pdata = {
 321        .num_leds       = ARRAY_SIZE(rx1950_leds_desc),
 322        .leds           = rx1950_leds_desc,
 323        .gpio_blink_set = rx1950_led_blink_set,
 324};
 325
 326static struct platform_device rx1950_leds = {
 327        .name   = "leds-gpio",
 328        .id             = -1,
 329        .dev    = {
 330                                .platform_data = &rx1950_leds_pdata,
 331        },
 332};
 333
 334static struct s3c_adc_bat_pdata rx1950_bat_cfg = {
 335        .init = rx1950_bat_init,
 336        .exit = rx1950_bat_exit,
 337        .enable_charger = rx1950_enable_charger,
 338        .disable_charger = rx1950_disable_charger,
 339        .gpio_charge_finished = S3C2410_GPF(3),
 340        .lut_noac = bat_lut_noac,
 341        .lut_noac_cnt = ARRAY_SIZE(bat_lut_noac),
 342        .lut_acin = bat_lut_acin,
 343        .lut_acin_cnt = ARRAY_SIZE(bat_lut_acin),
 344        .volt_channel = 0,
 345        .current_channel = 1,
 346        .volt_mult = 4235,
 347        .current_mult = 2900,
 348        .internal_impedance = 200,
 349};
 350
 351static struct platform_device rx1950_battery = {
 352        .name             = "s3c-adc-battery",
 353        .id               = -1,
 354        .dev = {
 355                .parent = &s3c_device_adc.dev,
 356                .platform_data = &rx1950_bat_cfg,
 357        },
 358};
 359
 360static struct s3c2410fb_mach_info rx1950_lcd_cfg = {
 361        .displays = &rx1950_display,
 362        .num_displays = 1,
 363        .default_display = 0,
 364
 365        .lpcsel = 0x02,
 366        .gpccon = 0xaa9556a9,
 367        .gpccon_mask = 0xffc003fc,
 368        .gpcup = 0x0000ffff,
 369        .gpcup_mask = 0xffffffff,
 370
 371        .gpdcon = 0xaa90aaa1,
 372        .gpdcon_mask = 0xffc0fff0,
 373        .gpdup = 0x0000fcfd,
 374        .gpdup_mask = 0xffffffff,
 375
 376};
 377
 378static struct pwm_lookup rx1950_pwm_lookup[] = {
 379        PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight.0", NULL, 48000,
 380                   PWM_POLARITY_NORMAL),
 381};
 382
 383static struct pwm_device *lcd_pwm;
 384
 385static void rx1950_lcd_power(int enable)
 386{
 387        int i;
 388        static int enabled;
 389        if (enabled == enable)
 390                return;
 391        if (!enable) {
 392
 393                /* GPC11-GPC15->OUTPUT */
 394                for (i = 11; i < 16; i++)
 395                        gpio_direction_output(S3C2410_GPC(i), 1);
 396
 397                /* Wait a bit here... */
 398                mdelay(100);
 399
 400                /* GPD2-GPD7->OUTPUT */
 401                /* GPD11-GPD15->OUTPUT */
 402                /* GPD2-GPD7->1, GPD11-GPD15->1 */
 403                for (i = 2; i < 8; i++)
 404                        gpio_direction_output(S3C2410_GPD(i), 1);
 405                for (i = 11; i < 16; i++)
 406                        gpio_direction_output(S3C2410_GPD(i), 1);
 407
 408                /* Wait a bit here...*/
 409                mdelay(100);
 410
 411                /* GPB0->OUTPUT, GPB0->0 */
 412                gpio_direction_output(S3C2410_GPB(0), 0);
 413
 414                /* GPC1-GPC4->OUTPUT, GPC1-4->0 */
 415                for (i = 1; i < 5; i++)
 416                        gpio_direction_output(S3C2410_GPC(i), 0);
 417
 418                /* GPC15-GPC11->0 */
 419                for (i = 11; i < 16; i++)
 420                        gpio_direction_output(S3C2410_GPC(i), 0);
 421
 422                /* GPD15-GPD11->0, GPD2->GPD7->0 */
 423                for (i = 11; i < 16; i++)
 424                        gpio_direction_output(S3C2410_GPD(i), 0);
 425
 426                for (i = 2; i < 8; i++)
 427                        gpio_direction_output(S3C2410_GPD(i), 0);
 428
 429                /* GPC6->0, GPC7->0, GPC5->0 */
 430                gpio_direction_output(S3C2410_GPC(6), 0);
 431                gpio_direction_output(S3C2410_GPC(7), 0);
 432                gpio_direction_output(S3C2410_GPC(5), 0);
 433
 434                /* GPB1->OUTPUT, GPB1->0 */
 435                gpio_direction_output(S3C2410_GPB(1), 0);
 436                pwm_config(lcd_pwm, 0, LCD_PWM_PERIOD);
 437                pwm_disable(lcd_pwm);
 438
 439                /* GPC0->0, GPC10->0 */
 440                gpio_direction_output(S3C2410_GPC(0), 0);
 441                gpio_direction_output(S3C2410_GPC(10), 0);
 442        } else {
 443                pwm_config(lcd_pwm, LCD_PWM_DUTY, LCD_PWM_PERIOD);
 444                pwm_enable(lcd_pwm);
 445
 446                gpio_direction_output(S3C2410_GPC(0), 1);
 447                gpio_direction_output(S3C2410_GPC(5), 1);
 448
 449                s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPB1_TOUT1);
 450                gpio_direction_output(S3C2410_GPC(7), 1);
 451
 452                for (i = 1; i < 5; i++)
 453                        s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));
 454
 455                for (i = 11; i < 16; i++)
 456                        s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));
 457
 458                for (i = 2; i < 8; i++)
 459                        s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));
 460
 461                for (i = 11; i < 16; i++)
 462                        s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));
 463
 464                gpio_direction_output(S3C2410_GPC(10), 1);
 465                gpio_direction_output(S3C2410_GPC(6), 1);
 466        }
 467        enabled = enable;
 468}
 469
 470static void rx1950_bl_power(int enable)
 471{
 472        static int enabled;
 473        if (enabled == enable)
 474                return;
 475        if (!enable) {
 476                        gpio_direction_output(S3C2410_GPB(0), 0);
 477        } else {
 478                        /* LED driver need a "push" to power on */
 479                        gpio_direction_output(S3C2410_GPB(0), 1);
 480                        /* Warm up backlight for one period of PWM.
 481                         * Without this trick its almost impossible to
 482                         * enable backlight with low brightness value
 483                         */
 484                        ndelay(48000);
 485                        s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
 486        }
 487        enabled = enable;
 488}
 489
 490static int rx1950_backlight_init(struct device *dev)
 491{
 492        WARN_ON(gpio_request(S3C2410_GPB(0), "Backlight"));
 493        lcd_pwm = pwm_request(1, "RX1950 LCD");
 494        if (IS_ERR(lcd_pwm)) {
 495                dev_err(dev, "Unable to request PWM for LCD power!\n");
 496                return PTR_ERR(lcd_pwm);
 497        }
 498
 499        /*
 500         * FIXME: pwm_apply_args() should be removed when switching to
 501         * the atomic PWM API.
 502         */
 503        pwm_apply_args(lcd_pwm);
 504
 505        rx1950_lcd_power(1);
 506        rx1950_bl_power(1);
 507
 508        return 0;
 509}
 510
 511static void rx1950_backlight_exit(struct device *dev)
 512{
 513        rx1950_bl_power(0);
 514        rx1950_lcd_power(0);
 515
 516        pwm_free(lcd_pwm);
 517        gpio_free(S3C2410_GPB(0));
 518}
 519
 520
 521static int rx1950_backlight_notify(struct device *dev, int brightness)
 522{
 523        if (!brightness) {
 524                rx1950_bl_power(0);
 525                rx1950_lcd_power(0);
 526        } else {
 527                rx1950_lcd_power(1);
 528                rx1950_bl_power(1);
 529        }
 530        return brightness;
 531}
 532
 533static struct platform_pwm_backlight_data rx1950_backlight_data = {
 534        .max_brightness = 24,
 535        .dft_brightness = 4,
 536        .enable_gpio = -1,
 537        .init = rx1950_backlight_init,
 538        .notify = rx1950_backlight_notify,
 539        .exit = rx1950_backlight_exit,
 540};
 541
 542static struct platform_device rx1950_backlight = {
 543        .name = "pwm-backlight",
 544        .dev = {
 545                .parent = &samsung_device_pwm.dev,
 546                .platform_data = &rx1950_backlight_data,
 547        },
 548};
 549
 550static void rx1950_set_mmc_power(unsigned char power_mode, unsigned short vdd)
 551{
 552        switch (power_mode) {
 553        case MMC_POWER_OFF:
 554                gpio_direction_output(S3C2410_GPJ(1), 0);
 555                break;
 556        case MMC_POWER_UP:
 557        case MMC_POWER_ON:
 558                gpio_direction_output(S3C2410_GPJ(1), 1);
 559                break;
 560        default:
 561                break;
 562        }
 563}
 564
 565static struct s3c24xx_mci_pdata rx1950_mmc_cfg __initdata = {
 566        .gpio_detect = S3C2410_GPF(5),
 567        .gpio_wprotect = S3C2410_GPH(8),
 568        .set_power = rx1950_set_mmc_power,
 569        .ocr_avail = MMC_VDD_32_33,
 570};
 571
 572static struct mtd_partition rx1950_nand_part[] = {
 573        [0] = {
 574                        .name = "Boot0",
 575                        .offset = 0,
 576                        .size = 0x4000,
 577                        .mask_flags = MTD_WRITEABLE,
 578        },
 579        [1] = {
 580                        .name = "Boot1",
 581                        .offset = MTDPART_OFS_APPEND,
 582                        .size = 0x40000,
 583                        .mask_flags = MTD_WRITEABLE,
 584        },
 585        [2] = {
 586                        .name = "Kernel",
 587                        .offset = MTDPART_OFS_APPEND,
 588                        .size = 0x300000,
 589                        .mask_flags = 0,
 590        },
 591        [3] = {
 592                        .name = "Filesystem",
 593                        .offset = MTDPART_OFS_APPEND,
 594                        .size = MTDPART_SIZ_FULL,
 595                        .mask_flags = 0,
 596        },
 597};
 598
 599static struct s3c2410_nand_set rx1950_nand_sets[] = {
 600        [0] = {
 601                        .name = "Internal",
 602                        .nr_chips = 1,
 603                        .nr_partitions = ARRAY_SIZE(rx1950_nand_part),
 604                        .partitions = rx1950_nand_part,
 605        },
 606};
 607
 608static struct s3c2410_platform_nand rx1950_nand_info = {
 609        .tacls = 25,
 610        .twrph0 = 50,
 611        .twrph1 = 15,
 612        .nr_sets = ARRAY_SIZE(rx1950_nand_sets),
 613        .sets = rx1950_nand_sets,
 614        .ecc_mode = NAND_ECC_SOFT,
 615};
 616
 617static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
 618        .vbus_pin = S3C2410_GPG(5),
 619        .vbus_pin_inverted = 1,
 620        .pullup_pin = S3C2410_GPJ(5),
 621};
 622
 623static struct s3c2410_ts_mach_info rx1950_ts_cfg __initdata = {
 624        .delay = 10000,
 625        .presc = 49,
 626        .oversampling_shift = 3,
 627};
 628
 629static struct gpio_keys_button rx1950_gpio_keys_table[] = {
 630        {
 631                .code           = KEY_POWER,
 632                .gpio           = S3C2410_GPF(0),
 633                .active_low     = 1,
 634                .desc           = "Power button",
 635                .wakeup         = 1,
 636        },
 637        {
 638                .code           = KEY_F5,
 639                .gpio           = S3C2410_GPF(7),
 640                .active_low     = 1,
 641                .desc           = "Record button",
 642        },
 643        {
 644                .code           = KEY_F1,
 645                .gpio           = S3C2410_GPG(0),
 646                .active_low     = 1,
 647                .desc           = "Calendar button",
 648        },
 649        {
 650                .code           = KEY_F2,
 651                .gpio           = S3C2410_GPG(2),
 652                .active_low     = 1,
 653                .desc           = "Contacts button",
 654        },
 655        {
 656                .code           = KEY_F3,
 657                .gpio           = S3C2410_GPG(3),
 658                .active_low     = 1,
 659                .desc           = "Mail button",
 660        },
 661        {
 662                .code           = KEY_F4,
 663                .gpio           = S3C2410_GPG(7),
 664                .active_low     = 1,
 665                .desc           = "WLAN button",
 666        },
 667        {
 668                .code           = KEY_LEFT,
 669                .gpio           = S3C2410_GPG(10),
 670                .active_low     = 1,
 671                .desc           = "Left button",
 672        },
 673        {
 674                .code           = KEY_RIGHT,
 675                .gpio           = S3C2410_GPG(11),
 676                .active_low     = 1,
 677                .desc           = "Right button",
 678        },
 679        {
 680                .code           = KEY_UP,
 681                .gpio           = S3C2410_GPG(4),
 682                .active_low     = 1,
 683                .desc           = "Up button",
 684        },
 685        {
 686                .code           = KEY_DOWN,
 687                .gpio           = S3C2410_GPG(6),
 688                .active_low     = 1,
 689                .desc           = "Down button",
 690        },
 691        {
 692                .code           = KEY_ENTER,
 693                .gpio           = S3C2410_GPG(9),
 694                .active_low     = 1,
 695                .desc           = "Ok button"
 696        },
 697};
 698
 699static struct gpio_keys_platform_data rx1950_gpio_keys_data = {
 700        .buttons = rx1950_gpio_keys_table,
 701        .nbuttons = ARRAY_SIZE(rx1950_gpio_keys_table),
 702};
 703
 704static struct platform_device rx1950_device_gpiokeys = {
 705        .name = "gpio-keys",
 706        .dev.platform_data = &rx1950_gpio_keys_data,
 707};
 708
 709static struct uda1380_platform_data uda1380_info = {
 710        .gpio_power     = S3C2410_GPJ(0),
 711        .gpio_reset     = S3C2410_GPD(0),
 712        .dac_clk        = UDA1380_DAC_CLK_SYSCLK,
 713};
 714
 715static struct i2c_board_info rx1950_i2c_devices[] = {
 716        {
 717                I2C_BOARD_INFO("uda1380", 0x1a),
 718                .platform_data = &uda1380_info,
 719        },
 720};
 721
 722static struct platform_device *rx1950_devices[] __initdata = {
 723        &s3c2410_device_dclk,
 724        &s3c_device_lcd,
 725        &s3c_device_wdt,
 726        &s3c_device_i2c0,
 727        &s3c_device_iis,
 728        &s3c_device_usbgadget,
 729        &s3c_device_rtc,
 730        &s3c_device_nand,
 731        &s3c_device_sdi,
 732        &s3c_device_adc,
 733        &s3c_device_ts,
 734        &samsung_device_pwm,
 735        &rx1950_backlight,
 736        &rx1950_device_gpiokeys,
 737        &power_supply,
 738        &rx1950_battery,
 739        &rx1950_leds,
 740};
 741
 742static void __init rx1950_map_io(void)
 743{
 744        s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc));
 745        s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs));
 746        samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 747
 748        /* setup PM */
 749
 750#ifdef CONFIG_PM_H1940
 751        memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 8);
 752#endif
 753
 754        s3c_pm_init();
 755}
 756
 757static void __init rx1950_init_time(void)
 758{
 759        s3c2442_init_clocks(16934000);
 760        samsung_timer_init();
 761}
 762
 763static void __init rx1950_init_machine(void)
 764{
 765        int i;
 766
 767        s3c24xx_fb_set_platdata(&rx1950_lcd_cfg);
 768        s3c24xx_udc_set_platdata(&rx1950_udc_cfg);
 769        s3c24xx_ts_set_platdata(&rx1950_ts_cfg);
 770        s3c24xx_mci_set_platdata(&rx1950_mmc_cfg);
 771        s3c_i2c0_set_platdata(NULL);
 772        s3c_nand_set_platdata(&rx1950_nand_info);
 773
 774        /* Turn off suspend on both USB ports, and switch the
 775         * selectable USB port to USB device mode. */
 776        s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
 777                                                S3C2410_MISCCR_USBSUSPND0 |
 778                                                S3C2410_MISCCR_USBSUSPND1, 0x0);
 779
 780        /* mmc power is disabled by default */
 781        WARN_ON(gpio_request(S3C2410_GPJ(1), "MMC power"));
 782        gpio_direction_output(S3C2410_GPJ(1), 0);
 783
 784        for (i = 0; i < 8; i++)
 785                WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));
 786
 787        for (i = 10; i < 16; i++)
 788                WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));
 789
 790        for (i = 2; i < 8; i++)
 791                WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));
 792
 793        for (i = 11; i < 16; i++)
 794                WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));
 795
 796        WARN_ON(gpio_request(S3C2410_GPB(1), "LCD power"));
 797
 798        WARN_ON(gpio_request(S3C2410_GPA(3), "Red blink"));
 799        WARN_ON(gpio_request(S3C2410_GPA(4), "Green blink"));
 800        WARN_ON(gpio_request(S3C2410_GPJ(6), "LED blink"));
 801        gpio_direction_output(S3C2410_GPA(3), 0);
 802        gpio_direction_output(S3C2410_GPA(4), 0);
 803        gpio_direction_output(S3C2410_GPJ(6), 0);
 804
 805        pwm_add_table(rx1950_pwm_lookup, ARRAY_SIZE(rx1950_pwm_lookup));
 806        platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));
 807
 808        i2c_register_board_info(0, rx1950_i2c_devices,
 809                ARRAY_SIZE(rx1950_i2c_devices));
 810}
 811
 812/* H1940 and RX3715 need to reserve this for suspend */
 813static void __init rx1950_reserve(void)
 814{
 815        memblock_reserve(0x30003000, 0x1000);
 816        memblock_reserve(0x30081000, 0x1000);
 817}
 818
 819MACHINE_START(RX1950, "HP iPAQ RX1950")
 820    /* Maintainers: Vasily Khoruzhick */
 821        .atag_offset = 0x100,
 822        .map_io = rx1950_map_io,
 823        .reserve        = rx1950_reserve,
 824        .init_irq       = s3c2442_init_irq,
 825        .init_machine = rx1950_init_machine,
 826        .init_time      = rx1950_init_time,
 827MACHINE_END
 828