mach-h1940.c (20846B)
1// SPDX-License-Identifier: GPL-2.0 2// 3// Copyright (c) 2003-2005 Simtec Electronics 4// Ben Dooks <ben@simtec.co.uk> 5// 6// https://www.handhelds.org/projects/h1940.html 7 8#include <linux/kernel.h> 9#include <linux/types.h> 10#include <linux/interrupt.h> 11#include <linux/list.h> 12#include <linux/memblock.h> 13#include <linux/timer.h> 14#include <linux/init.h> 15#include <linux/device.h> 16#include <linux/serial_core.h> 17#include <linux/serial_s3c.h> 18#include <linux/platform_device.h> 19#include <linux/io.h> 20#include <linux/gpio.h> 21#include <linux/gpio/machine.h> 22#include <linux/input.h> 23#include <linux/gpio_keys.h> 24#include <linux/pwm.h> 25#include <linux/pwm_backlight.h> 26#include <linux/i2c.h> 27#include <linux/leds.h> 28#include <linux/pda_power.h> 29#include <linux/s3c_adc_battery.h> 30#include <linux/delay.h> 31 32#include <video/platform_lcd.h> 33 34#include <linux/mmc/host.h> 35#include <linux/export.h> 36 37#include <asm/irq.h> 38#include <asm/mach-types.h> 39#include <asm/mach/arch.h> 40#include <asm/mach/map.h> 41#include <asm/mach/irq.h> 42 43#include <linux/platform_data/i2c-s3c2410.h> 44#include <linux/platform_data/mmc-s3cmci.h> 45#include <linux/platform_data/touchscreen-s3c2410.h> 46#include <linux/platform_data/usb-s3c2410_udc.h> 47 48#include <sound/uda1380.h> 49 50#include <linux/platform_data/fb-s3c2410.h> 51#include "map.h" 52#include "hardware-s3c24xx.h" 53#include "regs-clock.h" 54#include "regs-gpio.h" 55#include "gpio-samsung.h" 56 57#include "cpu.h" 58#include "devs.h" 59#include "gpio-cfg.h" 60#include "pm.h" 61 62#include "s3c24xx.h" 63#include "h1940.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 71#define S3C24XX_PLL_MDIV_SHIFT (12) 72#define S3C24XX_PLL_PDIV_SHIFT (4) 73#define S3C24XX_PLL_SDIV_SHIFT (0) 74 75static struct map_desc h1940_iodesc[] __initdata = { 76 [0] = { 77 .virtual = (unsigned long)H1940_LATCH, 78 .pfn = __phys_to_pfn(H1940_PA_LATCH), 79 .length = SZ_16K, 80 .type = MT_DEVICE 81 }, 82}; 83 84#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK 85#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB 86#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE 87 88static struct s3c2410_uartcfg h1940_uartcfgs[] __initdata = { 89 [0] = { 90 .hwport = 0, 91 .flags = 0, 92 .ucon = 0x3c5, 93 .ulcon = 0x03, 94 .ufcon = 0x51, 95 }, 96 [1] = { 97 .hwport = 1, 98 .flags = 0, 99 .ucon = 0x245, 100 .ulcon = 0x03, 101 .ufcon = 0x00, 102 }, 103 /* IR port */ 104 [2] = { 105 .hwport = 2, 106 .flags = 0, 107 .uart_flags = UPF_CONS_FLOW, 108 .ucon = 0x3c5, 109 .ulcon = 0x43, 110 .ufcon = 0x51, 111 } 112}; 113 114/* Board control latch control */ 115 116static unsigned int latch_state; 117 118static void h1940_latch_control(unsigned int clear, unsigned int set) 119{ 120 unsigned long flags; 121 122 local_irq_save(flags); 123 124 latch_state &= ~clear; 125 latch_state |= set; 126 127 __raw_writel(latch_state, H1940_LATCH); 128 129 local_irq_restore(flags); 130} 131 132static inline int h1940_gpiolib_to_latch(int offset) 133{ 134 return 1 << (offset + 16); 135} 136 137static void h1940_gpiolib_latch_set(struct gpio_chip *chip, 138 unsigned offset, int value) 139{ 140 int latch_bit = h1940_gpiolib_to_latch(offset); 141 142 h1940_latch_control(value ? 0 : latch_bit, 143 value ? latch_bit : 0); 144} 145 146static int h1940_gpiolib_latch_output(struct gpio_chip *chip, 147 unsigned offset, int value) 148{ 149 h1940_gpiolib_latch_set(chip, offset, value); 150 return 0; 151} 152 153static int h1940_gpiolib_latch_get(struct gpio_chip *chip, 154 unsigned offset) 155{ 156 return (latch_state >> (offset + 16)) & 1; 157} 158 159static struct gpio_chip h1940_latch_gpiochip = { 160 .base = H1940_LATCH_GPIO(0), 161 .owner = THIS_MODULE, 162 .label = "H1940_LATCH", 163 .ngpio = 16, 164 .direction_output = h1940_gpiolib_latch_output, 165 .set = h1940_gpiolib_latch_set, 166 .get = h1940_gpiolib_latch_get, 167}; 168 169static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = { 170 .vbus_pin = S3C2410_GPG(5), 171 .vbus_pin_inverted = 1, 172 .pullup_pin = H1940_LATCH_USB_DP, 173}; 174 175static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = { 176 .delay = 10000, 177 .presc = 49, 178 .oversampling_shift = 2, 179 .cfg_gpio = s3c24xx_ts_cfg_gpio, 180}; 181 182/* 183 * Set lcd on or off 184 */ 185static struct s3c2410fb_display h1940_lcd __initdata = { 186 .lcdcon5= S3C2410_LCDCON5_FRM565 | \ 187 S3C2410_LCDCON5_INVVLINE | \ 188 S3C2410_LCDCON5_HWSWP, 189 190 .type = S3C2410_LCDCON1_TFT, 191 .width = 240, 192 .height = 320, 193 .pixclock = 260000, 194 .xres = 240, 195 .yres = 320, 196 .bpp = 16, 197 .left_margin = 8, 198 .right_margin = 20, 199 .hsync_len = 4, 200 .upper_margin = 8, 201 .lower_margin = 7, 202 .vsync_len = 1, 203}; 204 205static struct s3c2410fb_mach_info h1940_fb_info __initdata = { 206 .displays = &h1940_lcd, 207 .num_displays = 1, 208 .default_display = 0, 209 210 .lpcsel = 0x02, 211 .gpccon = 0xaa940659, 212 .gpccon_mask = 0xffffc0f0, 213 .gpccon_reg = S3C2410_GPCCON, 214 .gpcup = 0x0000ffff, 215 .gpcup_mask = 0xffffffff, 216 .gpcup_reg = S3C2410_GPCUP, 217 .gpdcon = 0xaa84aaa0, 218 .gpdcon_mask = 0xffffffff, 219 .gpdcon_reg = S3C2410_GPDCON, 220 .gpdup = 0x0000faff, 221 .gpdup_mask = 0xffffffff, 222 .gpdup_reg = S3C2410_GPDUP, 223}; 224 225static int power_supply_init(struct device *dev) 226{ 227 return gpio_request(S3C2410_GPF(2), "cable plugged"); 228} 229 230static int h1940_is_ac_online(void) 231{ 232 return !gpio_get_value(S3C2410_GPF(2)); 233} 234 235static void power_supply_exit(struct device *dev) 236{ 237 gpio_free(S3C2410_GPF(2)); 238} 239 240static char *h1940_supplicants[] = { 241 "main-battery", 242 "backup-battery", 243}; 244 245static struct pda_power_pdata power_supply_info = { 246 .init = power_supply_init, 247 .is_ac_online = h1940_is_ac_online, 248 .exit = power_supply_exit, 249 .supplied_to = h1940_supplicants, 250 .num_supplicants = ARRAY_SIZE(h1940_supplicants), 251}; 252 253static struct resource power_supply_resources[] = { 254 [0] = DEFINE_RES_NAMED(IRQ_EINT2, 1, "ac", IORESOURCE_IRQ \ 255 | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE), 256}; 257 258static struct platform_device power_supply = { 259 .name = "pda-power", 260 .id = -1, 261 .dev = { 262 .platform_data = 263 &power_supply_info, 264 }, 265 .resource = power_supply_resources, 266 .num_resources = ARRAY_SIZE(power_supply_resources), 267}; 268 269static const struct s3c_adc_bat_thresh bat_lut_noac[] = { 270 { .volt = 4070, .cur = 162, .level = 100}, 271 { .volt = 4040, .cur = 165, .level = 95}, 272 { .volt = 4016, .cur = 164, .level = 90}, 273 { .volt = 3996, .cur = 166, .level = 85}, 274 { .volt = 3971, .cur = 168, .level = 80}, 275 { .volt = 3951, .cur = 168, .level = 75}, 276 { .volt = 3931, .cur = 170, .level = 70}, 277 { .volt = 3903, .cur = 172, .level = 65}, 278 { .volt = 3886, .cur = 172, .level = 60}, 279 { .volt = 3858, .cur = 176, .level = 55}, 280 { .volt = 3842, .cur = 176, .level = 50}, 281 { .volt = 3818, .cur = 176, .level = 45}, 282 { .volt = 3789, .cur = 180, .level = 40}, 283 { .volt = 3769, .cur = 180, .level = 35}, 284 { .volt = 3749, .cur = 184, .level = 30}, 285 { .volt = 3732, .cur = 184, .level = 25}, 286 { .volt = 3716, .cur = 184, .level = 20}, 287 { .volt = 3708, .cur = 184, .level = 15}, 288 { .volt = 3716, .cur = 96, .level = 10}, 289 { .volt = 3700, .cur = 96, .level = 5}, 290 { .volt = 3684, .cur = 96, .level = 0}, 291}; 292 293static const struct s3c_adc_bat_thresh bat_lut_acin[] = { 294 { .volt = 4130, .cur = 0, .level = 100}, 295 { .volt = 3982, .cur = 0, .level = 50}, 296 { .volt = 3854, .cur = 0, .level = 10}, 297 { .volt = 3841, .cur = 0, .level = 0}, 298}; 299 300static struct gpiod_lookup_table h1940_bat_gpio_table = { 301 .dev_id = "s3c-adc-battery", 302 .table = { 303 /* Charge status S3C2410_GPF(3) */ 304 GPIO_LOOKUP("GPIOF", 3, "charge-status", GPIO_ACTIVE_LOW), 305 { }, 306 }, 307}; 308 309static int h1940_bat_init(void) 310{ 311 int ret; 312 313 ret = gpio_request(H1940_LATCH_SM803_ENABLE, "h1940-charger-enable"); 314 if (ret) 315 return ret; 316 gpio_direction_output(H1940_LATCH_SM803_ENABLE, 0); 317 318 return 0; 319 320} 321 322static void h1940_bat_exit(void) 323{ 324 gpio_free(H1940_LATCH_SM803_ENABLE); 325} 326 327static void h1940_enable_charger(void) 328{ 329 gpio_set_value(H1940_LATCH_SM803_ENABLE, 1); 330} 331 332static void h1940_disable_charger(void) 333{ 334 gpio_set_value(H1940_LATCH_SM803_ENABLE, 0); 335} 336 337static struct s3c_adc_bat_pdata h1940_bat_cfg = { 338 .init = h1940_bat_init, 339 .exit = h1940_bat_exit, 340 .enable_charger = h1940_enable_charger, 341 .disable_charger = h1940_disable_charger, 342 .lut_noac = bat_lut_noac, 343 .lut_noac_cnt = ARRAY_SIZE(bat_lut_noac), 344 .lut_acin = bat_lut_acin, 345 .lut_acin_cnt = ARRAY_SIZE(bat_lut_acin), 346 .volt_channel = 0, 347 .current_channel = 1, 348 .volt_mult = 4056, 349 .current_mult = 1893, 350 .internal_impedance = 200, 351 .backup_volt_channel = 3, 352 /* TODO Check backup volt multiplier */ 353 .backup_volt_mult = 4056, 354 .backup_volt_min = 0, 355 .backup_volt_max = 4149288 356}; 357 358static struct platform_device h1940_battery = { 359 .name = "s3c-adc-battery", 360 .id = -1, 361 .dev = { 362 .parent = &s3c_device_adc.dev, 363 .platform_data = &h1940_bat_cfg, 364 }, 365}; 366 367static DEFINE_SPINLOCK(h1940_blink_spin); 368 369int h1940_led_blink_set(struct gpio_desc *desc, int state, 370 unsigned long *delay_on, unsigned long *delay_off) 371{ 372 int blink_gpio, check_gpio1, check_gpio2; 373 int gpio = desc ? desc_to_gpio(desc) : -EINVAL; 374 375 switch (gpio) { 376 case H1940_LATCH_LED_GREEN: 377 blink_gpio = S3C2410_GPA(7); 378 check_gpio1 = S3C2410_GPA(1); 379 check_gpio2 = S3C2410_GPA(3); 380 break; 381 case H1940_LATCH_LED_RED: 382 blink_gpio = S3C2410_GPA(1); 383 check_gpio1 = S3C2410_GPA(7); 384 check_gpio2 = S3C2410_GPA(3); 385 break; 386 default: 387 blink_gpio = S3C2410_GPA(3); 388 check_gpio1 = S3C2410_GPA(1); 389 check_gpio2 = S3C2410_GPA(7); 390 break; 391 } 392 393 if (delay_on && delay_off && !*delay_on && !*delay_off) 394 *delay_on = *delay_off = 500; 395 396 spin_lock(&h1940_blink_spin); 397 398 switch (state) { 399 case GPIO_LED_NO_BLINK_LOW: 400 case GPIO_LED_NO_BLINK_HIGH: 401 if (!gpio_get_value(check_gpio1) && 402 !gpio_get_value(check_gpio2)) 403 gpio_set_value(H1940_LATCH_LED_FLASH, 0); 404 gpio_set_value(blink_gpio, 0); 405 if (gpio_is_valid(gpio)) 406 gpio_set_value(gpio, state); 407 break; 408 case GPIO_LED_BLINK: 409 if (gpio_is_valid(gpio)) 410 gpio_set_value(gpio, 0); 411 gpio_set_value(H1940_LATCH_LED_FLASH, 1); 412 gpio_set_value(blink_gpio, 1); 413 break; 414 } 415 416 spin_unlock(&h1940_blink_spin); 417 418 return 0; 419} 420EXPORT_SYMBOL(h1940_led_blink_set); 421 422static struct gpio_led h1940_leds_desc[] = { 423 { 424 .name = "Green", 425 .default_trigger = "main-battery-full", 426 .gpio = H1940_LATCH_LED_GREEN, 427 .retain_state_suspended = 1, 428 }, 429 { 430 .name = "Red", 431 .default_trigger 432 = "main-battery-charging-blink-full-solid", 433 .gpio = H1940_LATCH_LED_RED, 434 .retain_state_suspended = 1, 435 }, 436}; 437 438static struct gpio_led_platform_data h1940_leds_pdata = { 439 .num_leds = ARRAY_SIZE(h1940_leds_desc), 440 .leds = h1940_leds_desc, 441 .gpio_blink_set = h1940_led_blink_set, 442}; 443 444static struct platform_device h1940_device_leds = { 445 .name = "leds-gpio", 446 .id = -1, 447 .dev = { 448 .platform_data = &h1940_leds_pdata, 449 }, 450}; 451 452static struct platform_device h1940_device_bluetooth = { 453 .name = "h1940-bt", 454 .id = -1, 455}; 456 457static void h1940_set_mmc_power(unsigned char power_mode, unsigned short vdd) 458{ 459 s3c24xx_mci_def_set_power(power_mode, vdd); 460 461 switch (power_mode) { 462 case MMC_POWER_OFF: 463 gpio_set_value(H1940_LATCH_SD_POWER, 0); 464 break; 465 case MMC_POWER_UP: 466 case MMC_POWER_ON: 467 gpio_set_value(H1940_LATCH_SD_POWER, 1); 468 break; 469 default: 470 break; 471 } 472} 473 474static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = { 475 .set_power = h1940_set_mmc_power, 476 .ocr_avail = MMC_VDD_32_33, 477}; 478 479static struct gpiod_lookup_table h1940_mmc_gpio_table = { 480 .dev_id = "s3c2410-sdi", 481 .table = { 482 /* Card detect S3C2410_GPF(5) */ 483 GPIO_LOOKUP("GPIOF", 5, "cd", GPIO_ACTIVE_LOW), 484 /* Write protect S3C2410_GPH(8) */ 485 GPIO_LOOKUP("GPIOH", 8, "wp", GPIO_ACTIVE_LOW), 486 /* bus pins */ 487 GPIO_LOOKUP_IDX("GPIOE", 5, "bus", 0, GPIO_ACTIVE_HIGH), 488 GPIO_LOOKUP_IDX("GPIOE", 6, "bus", 1, GPIO_ACTIVE_HIGH), 489 GPIO_LOOKUP_IDX("GPIOE", 7, "bus", 2, GPIO_ACTIVE_HIGH), 490 GPIO_LOOKUP_IDX("GPIOE", 8, "bus", 3, GPIO_ACTIVE_HIGH), 491 GPIO_LOOKUP_IDX("GPIOE", 9, "bus", 4, GPIO_ACTIVE_HIGH), 492 GPIO_LOOKUP_IDX("GPIOE", 10, "bus", 5, GPIO_ACTIVE_HIGH), 493 { }, 494 }, 495}; 496 497static struct gpiod_lookup_table h1940_audio_gpio_table = { 498 .dev_id = "h1940-audio", 499 .table = { 500 GPIO_LOOKUP("H1940_LATCH", 501 H1940_LATCH_AUDIO_POWER - H1940_LATCH_GPIO(0), 502 "speaker-power", GPIO_ACTIVE_HIGH), 503 GPIO_LOOKUP("GPIOG", 4, "hp", GPIO_ACTIVE_HIGH), 504 { }, 505 }, 506}; 507 508static struct platform_device h1940_audio = { 509 .name = "h1940-audio", 510 .id = -1, 511}; 512 513static struct pwm_lookup h1940_pwm_lookup[] = { 514 PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight", NULL, 36296, 515 PWM_POLARITY_NORMAL), 516}; 517 518static int h1940_backlight_init(struct device *dev) 519{ 520 gpio_request(S3C2410_GPB(0), "Backlight"); 521 522 gpio_direction_output(S3C2410_GPB(0), 0); 523 s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE); 524 s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); 525 gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 1); 526 527 return 0; 528} 529 530static int h1940_backlight_notify(struct device *dev, int brightness) 531{ 532 if (!brightness) { 533 gpio_direction_output(S3C2410_GPB(0), 1); 534 gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 0); 535 } else { 536 gpio_direction_output(S3C2410_GPB(0), 0); 537 s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE); 538 s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); 539 gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 1); 540 } 541 return brightness; 542} 543 544static void h1940_backlight_exit(struct device *dev) 545{ 546 gpio_direction_output(S3C2410_GPB(0), 1); 547 gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 0); 548} 549 550 551static struct platform_pwm_backlight_data backlight_data = { 552 .max_brightness = 100, 553 .dft_brightness = 50, 554 .init = h1940_backlight_init, 555 .notify = h1940_backlight_notify, 556 .exit = h1940_backlight_exit, 557}; 558 559static struct platform_device h1940_backlight = { 560 .name = "pwm-backlight", 561 .dev = { 562 .parent = &samsung_device_pwm.dev, 563 .platform_data = &backlight_data, 564 }, 565 .id = -1, 566}; 567 568static void h1940_lcd_power_set(struct plat_lcd_data *pd, 569 unsigned int power) 570{ 571 int value, retries = 100; 572 573 if (!power) { 574 gpio_set_value(S3C2410_GPC(0), 0); 575 /* wait for 3ac */ 576 do { 577 value = gpio_get_value(S3C2410_GPC(6)); 578 } while (value && retries--); 579 580 gpio_set_value(H1940_LATCH_LCD_P2, 0); 581 gpio_set_value(H1940_LATCH_LCD_P3, 0); 582 gpio_set_value(H1940_LATCH_LCD_P4, 0); 583 584 gpio_direction_output(S3C2410_GPC(1), 0); 585 gpio_direction_output(S3C2410_GPC(4), 0); 586 587 gpio_set_value(H1940_LATCH_LCD_P1, 0); 588 gpio_set_value(H1940_LATCH_LCD_P0, 0); 589 590 gpio_set_value(S3C2410_GPC(5), 0); 591 592 } else { 593 gpio_set_value(H1940_LATCH_LCD_P0, 1); 594 gpio_set_value(H1940_LATCH_LCD_P1, 1); 595 596 gpio_direction_input(S3C2410_GPC(1)); 597 gpio_direction_input(S3C2410_GPC(4)); 598 mdelay(10); 599 s3c_gpio_cfgpin(S3C2410_GPC(1), S3C_GPIO_SFN(2)); 600 s3c_gpio_cfgpin(S3C2410_GPC(4), S3C_GPIO_SFN(2)); 601 602 gpio_set_value(S3C2410_GPC(5), 1); 603 gpio_set_value(S3C2410_GPC(0), 1); 604 605 gpio_set_value(H1940_LATCH_LCD_P3, 1); 606 gpio_set_value(H1940_LATCH_LCD_P2, 1); 607 gpio_set_value(H1940_LATCH_LCD_P4, 1); 608 } 609} 610 611static struct plat_lcd_data h1940_lcd_power_data = { 612 .set_power = h1940_lcd_power_set, 613}; 614 615static struct platform_device h1940_lcd_powerdev = { 616 .name = "platform-lcd", 617 .dev.parent = &s3c_device_lcd.dev, 618 .dev.platform_data = &h1940_lcd_power_data, 619}; 620 621static struct uda1380_platform_data uda1380_info = { 622 .gpio_power = H1940_LATCH_UDA_POWER, 623 .gpio_reset = S3C2410_GPA(12), 624 .dac_clk = UDA1380_DAC_CLK_SYSCLK, 625}; 626 627static struct i2c_board_info h1940_i2c_devices[] = { 628 { 629 I2C_BOARD_INFO("uda1380", 0x1a), 630 .platform_data = &uda1380_info, 631 }, 632}; 633 634#define DECLARE_BUTTON(p, k, n, w) \ 635 { \ 636 .gpio = p, \ 637 .code = k, \ 638 .desc = n, \ 639 .wakeup = w, \ 640 .active_low = 1, \ 641 } 642 643static struct gpio_keys_button h1940_buttons[] = { 644 DECLARE_BUTTON(S3C2410_GPF(0), KEY_POWER, "Power", 1), 645 DECLARE_BUTTON(S3C2410_GPF(6), KEY_ENTER, "Select", 1), 646 DECLARE_BUTTON(S3C2410_GPF(7), KEY_RECORD, "Record", 0), 647 DECLARE_BUTTON(S3C2410_GPG(0), KEY_F11, "Calendar", 0), 648 DECLARE_BUTTON(S3C2410_GPG(2), KEY_F12, "Contacts", 0), 649 DECLARE_BUTTON(S3C2410_GPG(3), KEY_MAIL, "Mail", 0), 650 DECLARE_BUTTON(S3C2410_GPG(6), KEY_LEFT, "Left_arrow", 0), 651 DECLARE_BUTTON(S3C2410_GPG(7), KEY_HOMEPAGE, "Home", 0), 652 DECLARE_BUTTON(S3C2410_GPG(8), KEY_RIGHT, "Right_arrow", 0), 653 DECLARE_BUTTON(S3C2410_GPG(9), KEY_UP, "Up_arrow", 0), 654 DECLARE_BUTTON(S3C2410_GPG(10), KEY_DOWN, "Down_arrow", 0), 655}; 656 657static struct gpio_keys_platform_data h1940_buttons_data = { 658 .buttons = h1940_buttons, 659 .nbuttons = ARRAY_SIZE(h1940_buttons), 660}; 661 662static struct platform_device h1940_dev_buttons = { 663 .name = "gpio-keys", 664 .id = -1, 665 .dev = { 666 .platform_data = &h1940_buttons_data, 667 } 668}; 669 670static struct platform_device *h1940_devices[] __initdata = { 671 &h1940_dev_buttons, 672 &s3c_device_ohci, 673 &s3c_device_lcd, 674 &s3c_device_wdt, 675 &s3c_device_i2c0, 676 &s3c_device_iis, 677 &s3c_device_usbgadget, 678 &h1940_device_leds, 679 &h1940_device_bluetooth, 680 &s3c_device_sdi, 681 &s3c_device_rtc, 682 &samsung_device_pwm, 683 &h1940_backlight, 684 &h1940_lcd_powerdev, 685 &s3c_device_adc, 686 &s3c_device_ts, 687 &power_supply, 688 &h1940_battery, 689 &h1940_audio, 690}; 691 692static void __init h1940_map_io(void) 693{ 694 s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); 695 s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); 696 s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4); 697 698 /* setup PM */ 699 700#ifdef CONFIG_PM_H1940 701 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024); 702#endif 703 s3c_pm_init(); 704 705 /* Add latch gpio chip, set latch initial value */ 706 h1940_latch_control(0, 0); 707 WARN_ON(gpiochip_add_data(&h1940_latch_gpiochip, NULL)); 708} 709 710static void __init h1940_init_time(void) 711{ 712 s3c2410_init_clocks(12000000); 713 s3c24xx_timer_init(); 714} 715 716/* H1940 and RX3715 need to reserve this for suspend */ 717static void __init h1940_reserve(void) 718{ 719 memblock_reserve(0x30003000, 0x1000); 720 memblock_reserve(0x30081000, 0x1000); 721} 722 723static void __init h1940_init(void) 724{ 725 u32 tmp; 726 727 s3c24xx_fb_set_platdata(&h1940_fb_info); 728 gpiod_add_lookup_table(&h1940_mmc_gpio_table); 729 gpiod_add_lookup_table(&h1940_audio_gpio_table); 730 gpiod_add_lookup_table(&h1940_bat_gpio_table); 731 /* Configure the I2S pins (GPE0...GPE4) in correct mode */ 732 s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), 733 S3C_GPIO_PULL_NONE); 734 s3c24xx_mci_set_platdata(&h1940_mmc_cfg); 735 s3c24xx_udc_set_platdata(&h1940_udc_cfg); 736 s3c24xx_ts_set_platdata(&h1940_ts_cfg); 737 s3c_i2c0_set_platdata(NULL); 738 739 /* Turn off suspend on both USB ports, and switch the 740 * selectable USB port to USB device mode. */ 741 742 s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | 743 S3C2410_MISCCR_USBSUSPND0 | 744 S3C2410_MISCCR_USBSUSPND1, 0x0); 745 746 tmp = (0x78 << S3C24XX_PLL_MDIV_SHIFT) 747 | (0x02 << S3C24XX_PLL_PDIV_SHIFT) 748 | (0x03 << S3C24XX_PLL_SDIV_SHIFT); 749 writel(tmp, S3C2410_UPLLCON); 750 751 gpio_request(S3C2410_GPC(0), "LCD power"); 752 gpio_request(S3C2410_GPC(1), "LCD power"); 753 gpio_request(S3C2410_GPC(4), "LCD power"); 754 gpio_request(S3C2410_GPC(5), "LCD power"); 755 gpio_request(S3C2410_GPC(6), "LCD power"); 756 gpio_request(H1940_LATCH_LCD_P0, "LCD power"); 757 gpio_request(H1940_LATCH_LCD_P1, "LCD power"); 758 gpio_request(H1940_LATCH_LCD_P2, "LCD power"); 759 gpio_request(H1940_LATCH_LCD_P3, "LCD power"); 760 gpio_request(H1940_LATCH_LCD_P4, "LCD power"); 761 gpio_request(H1940_LATCH_MAX1698_nSHUTDOWN, "LCD power"); 762 gpio_direction_output(S3C2410_GPC(0), 0); 763 gpio_direction_output(S3C2410_GPC(1), 0); 764 gpio_direction_output(S3C2410_GPC(4), 0); 765 gpio_direction_output(S3C2410_GPC(5), 0); 766 gpio_direction_input(S3C2410_GPC(6)); 767 gpio_direction_output(H1940_LATCH_LCD_P0, 0); 768 gpio_direction_output(H1940_LATCH_LCD_P1, 0); 769 gpio_direction_output(H1940_LATCH_LCD_P2, 0); 770 gpio_direction_output(H1940_LATCH_LCD_P3, 0); 771 gpio_direction_output(H1940_LATCH_LCD_P4, 0); 772 gpio_direction_output(H1940_LATCH_MAX1698_nSHUTDOWN, 0); 773 774 gpio_request(H1940_LATCH_SD_POWER, "SD power"); 775 gpio_direction_output(H1940_LATCH_SD_POWER, 0); 776 777 pwm_add_table(h1940_pwm_lookup, ARRAY_SIZE(h1940_pwm_lookup)); 778 platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices)); 779 780 gpio_request(S3C2410_GPA(1), "Red LED blink"); 781 gpio_request(S3C2410_GPA(3), "Blue LED blink"); 782 gpio_request(S3C2410_GPA(7), "Green LED blink"); 783 gpio_request(H1940_LATCH_LED_FLASH, "LED blink"); 784 gpio_direction_output(S3C2410_GPA(1), 0); 785 gpio_direction_output(S3C2410_GPA(3), 0); 786 gpio_direction_output(S3C2410_GPA(7), 0); 787 gpio_direction_output(H1940_LATCH_LED_FLASH, 0); 788 789 i2c_register_board_info(0, h1940_i2c_devices, 790 ARRAY_SIZE(h1940_i2c_devices)); 791} 792 793MACHINE_START(H1940, "IPAQ-H1940") 794 /* Maintainer: Ben Dooks <ben-linux@fluff.org> */ 795 .atag_offset = 0x100, 796 .nr_irqs = NR_IRQS_S3C2410, 797 .map_io = h1940_map_io, 798 .reserve = h1940_reserve, 799 .init_irq = s3c2410_init_irq, 800 .init_machine = h1940_init, 801 .init_time = h1940_init_time, 802MACHINE_END