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 int h1940_bat_init(void) 301{ 302 int ret; 303 304 ret = gpio_request(H1940_LATCH_SM803_ENABLE, "h1940-charger-enable"); 305 if (ret) 306 return ret; 307 gpio_direction_output(H1940_LATCH_SM803_ENABLE, 0); 308 309 return 0; 310 311} 312 313static void h1940_bat_exit(void) 314{ 315 gpio_free(H1940_LATCH_SM803_ENABLE); 316} 317 318static void h1940_enable_charger(void) 319{ 320 gpio_set_value(H1940_LATCH_SM803_ENABLE, 1); 321} 322 323static void h1940_disable_charger(void) 324{ 325 gpio_set_value(H1940_LATCH_SM803_ENABLE, 0); 326} 327 328static struct s3c_adc_bat_pdata h1940_bat_cfg = { 329 .init = h1940_bat_init, 330 .exit = h1940_bat_exit, 331 .enable_charger = h1940_enable_charger, 332 .disable_charger = h1940_disable_charger, 333 .gpio_charge_finished = S3C2410_GPF(3), 334 .gpio_inverted = 1, 335 .lut_noac = bat_lut_noac, 336 .lut_noac_cnt = ARRAY_SIZE(bat_lut_noac), 337 .lut_acin = bat_lut_acin, 338 .lut_acin_cnt = ARRAY_SIZE(bat_lut_acin), 339 .volt_channel = 0, 340 .current_channel = 1, 341 .volt_mult = 4056, 342 .current_mult = 1893, 343 .internal_impedance = 200, 344 .backup_volt_channel = 3, 345 /* TODO Check backup volt multiplier */ 346 .backup_volt_mult = 4056, 347 .backup_volt_min = 0, 348 .backup_volt_max = 4149288 349}; 350 351static struct platform_device h1940_battery = { 352 .name = "s3c-adc-battery", 353 .id = -1, 354 .dev = { 355 .parent = &s3c_device_adc.dev, 356 .platform_data = &h1940_bat_cfg, 357 }, 358}; 359 360static DEFINE_SPINLOCK(h1940_blink_spin); 361 362int h1940_led_blink_set(struct gpio_desc *desc, int state, 363 unsigned long *delay_on, unsigned long *delay_off) 364{ 365 int blink_gpio, check_gpio1, check_gpio2; 366 int gpio = desc ? desc_to_gpio(desc) : -EINVAL; 367 368 switch (gpio) { 369 case H1940_LATCH_LED_GREEN: 370 blink_gpio = S3C2410_GPA(7); 371 check_gpio1 = S3C2410_GPA(1); 372 check_gpio2 = S3C2410_GPA(3); 373 break; 374 case H1940_LATCH_LED_RED: 375 blink_gpio = S3C2410_GPA(1); 376 check_gpio1 = S3C2410_GPA(7); 377 check_gpio2 = S3C2410_GPA(3); 378 break; 379 default: 380 blink_gpio = S3C2410_GPA(3); 381 check_gpio1 = S3C2410_GPA(1); 382 check_gpio2 = S3C2410_GPA(7); 383 break; 384 } 385 386 if (delay_on && delay_off && !*delay_on && !*delay_off) 387 *delay_on = *delay_off = 500; 388 389 spin_lock(&h1940_blink_spin); 390 391 switch (state) { 392 case GPIO_LED_NO_BLINK_LOW: 393 case GPIO_LED_NO_BLINK_HIGH: 394 if (!gpio_get_value(check_gpio1) && 395 !gpio_get_value(check_gpio2)) 396 gpio_set_value(H1940_LATCH_LED_FLASH, 0); 397 gpio_set_value(blink_gpio, 0); 398 if (gpio_is_valid(gpio)) 399 gpio_set_value(gpio, state); 400 break; 401 case GPIO_LED_BLINK: 402 if (gpio_is_valid(gpio)) 403 gpio_set_value(gpio, 0); 404 gpio_set_value(H1940_LATCH_LED_FLASH, 1); 405 gpio_set_value(blink_gpio, 1); 406 break; 407 } 408 409 spin_unlock(&h1940_blink_spin); 410 411 return 0; 412} 413EXPORT_SYMBOL(h1940_led_blink_set); 414 415static struct gpio_led h1940_leds_desc[] = { 416 { 417 .name = "Green", 418 .default_trigger = "main-battery-full", 419 .gpio = H1940_LATCH_LED_GREEN, 420 .retain_state_suspended = 1, 421 }, 422 { 423 .name = "Red", 424 .default_trigger 425 = "main-battery-charging-blink-full-solid", 426 .gpio = H1940_LATCH_LED_RED, 427 .retain_state_suspended = 1, 428 }, 429}; 430 431static struct gpio_led_platform_data h1940_leds_pdata = { 432 .num_leds = ARRAY_SIZE(h1940_leds_desc), 433 .leds = h1940_leds_desc, 434 .gpio_blink_set = h1940_led_blink_set, 435}; 436 437static struct platform_device h1940_device_leds = { 438 .name = "leds-gpio", 439 .id = -1, 440 .dev = { 441 .platform_data = &h1940_leds_pdata, 442 }, 443}; 444 445static struct platform_device h1940_device_bluetooth = { 446 .name = "h1940-bt", 447 .id = -1, 448}; 449 450static void h1940_set_mmc_power(unsigned char power_mode, unsigned short vdd) 451{ 452 s3c24xx_mci_def_set_power(power_mode, vdd); 453 454 switch (power_mode) { 455 case MMC_POWER_OFF: 456 gpio_set_value(H1940_LATCH_SD_POWER, 0); 457 break; 458 case MMC_POWER_UP: 459 case MMC_POWER_ON: 460 gpio_set_value(H1940_LATCH_SD_POWER, 1); 461 break; 462 default: 463 break; 464 } 465} 466 467static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = { 468 .set_power = h1940_set_mmc_power, 469 .ocr_avail = MMC_VDD_32_33, 470}; 471 472static struct gpiod_lookup_table h1940_mmc_gpio_table = { 473 .dev_id = "s3c2410-sdi", 474 .table = { 475 /* Card detect S3C2410_GPF(5) */ 476 GPIO_LOOKUP("GPIOF", 5, "cd", GPIO_ACTIVE_LOW), 477 /* Write protect S3C2410_GPH(8) */ 478 GPIO_LOOKUP("GPIOH", 8, "wp", GPIO_ACTIVE_LOW), 479 /* bus pins */ 480 GPIO_LOOKUP_IDX("GPIOE", 5, "bus", 0, GPIO_ACTIVE_HIGH), 481 GPIO_LOOKUP_IDX("GPIOE", 6, "bus", 1, GPIO_ACTIVE_HIGH), 482 GPIO_LOOKUP_IDX("GPIOE", 7, "bus", 2, GPIO_ACTIVE_HIGH), 483 GPIO_LOOKUP_IDX("GPIOE", 8, "bus", 3, GPIO_ACTIVE_HIGH), 484 GPIO_LOOKUP_IDX("GPIOE", 9, "bus", 4, GPIO_ACTIVE_HIGH), 485 GPIO_LOOKUP_IDX("GPIOE", 10, "bus", 5, GPIO_ACTIVE_HIGH), 486 { }, 487 }, 488}; 489 490static struct gpiod_lookup_table h1940_audio_gpio_table = { 491 .dev_id = "h1940-audio", 492 .table = { 493 GPIO_LOOKUP("H1940_LATCH", 494 H1940_LATCH_AUDIO_POWER - H1940_LATCH_GPIO(0), 495 "speaker-power", GPIO_ACTIVE_HIGH), 496 GPIO_LOOKUP("GPIOG", 4, "hp", GPIO_ACTIVE_HIGH), 497 { }, 498 }, 499}; 500 501static struct platform_device h1940_audio = { 502 .name = "h1940-audio", 503 .id = -1, 504}; 505 506static struct pwm_lookup h1940_pwm_lookup[] = { 507 PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight", NULL, 36296, 508 PWM_POLARITY_NORMAL), 509}; 510 511static int h1940_backlight_init(struct device *dev) 512{ 513 gpio_request(S3C2410_GPB(0), "Backlight"); 514 515 gpio_direction_output(S3C2410_GPB(0), 0); 516 s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE); 517 s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); 518 gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 1); 519 520 return 0; 521} 522 523static int h1940_backlight_notify(struct device *dev, int brightness) 524{ 525 if (!brightness) { 526 gpio_direction_output(S3C2410_GPB(0), 1); 527 gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 0); 528 } else { 529 gpio_direction_output(S3C2410_GPB(0), 0); 530 s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE); 531 s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); 532 gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 1); 533 } 534 return brightness; 535} 536 537static void h1940_backlight_exit(struct device *dev) 538{ 539 gpio_direction_output(S3C2410_GPB(0), 1); 540 gpio_set_value(H1940_LATCH_MAX1698_nSHUTDOWN, 0); 541} 542 543 544static struct platform_pwm_backlight_data backlight_data = { 545 .max_brightness = 100, 546 .dft_brightness = 50, 547 .init = h1940_backlight_init, 548 .notify = h1940_backlight_notify, 549 .exit = h1940_backlight_exit, 550}; 551 552static struct platform_device h1940_backlight = { 553 .name = "pwm-backlight", 554 .dev = { 555 .parent = &samsung_device_pwm.dev, 556 .platform_data = &backlight_data, 557 }, 558 .id = -1, 559}; 560 561static void h1940_lcd_power_set(struct plat_lcd_data *pd, 562 unsigned int power) 563{ 564 int value, retries = 100; 565 566 if (!power) { 567 gpio_set_value(S3C2410_GPC(0), 0); 568 /* wait for 3ac */ 569 do { 570 value = gpio_get_value(S3C2410_GPC(6)); 571 } while (value && retries--); 572 573 gpio_set_value(H1940_LATCH_LCD_P2, 0); 574 gpio_set_value(H1940_LATCH_LCD_P3, 0); 575 gpio_set_value(H1940_LATCH_LCD_P4, 0); 576 577 gpio_direction_output(S3C2410_GPC(1), 0); 578 gpio_direction_output(S3C2410_GPC(4), 0); 579 580 gpio_set_value(H1940_LATCH_LCD_P1, 0); 581 gpio_set_value(H1940_LATCH_LCD_P0, 0); 582 583 gpio_set_value(S3C2410_GPC(5), 0); 584 585 } else { 586 gpio_set_value(H1940_LATCH_LCD_P0, 1); 587 gpio_set_value(H1940_LATCH_LCD_P1, 1); 588 589 gpio_direction_input(S3C2410_GPC(1)); 590 gpio_direction_input(S3C2410_GPC(4)); 591 mdelay(10); 592 s3c_gpio_cfgpin(S3C2410_GPC(1), S3C_GPIO_SFN(2)); 593 s3c_gpio_cfgpin(S3C2410_GPC(4), S3C_GPIO_SFN(2)); 594 595 gpio_set_value(S3C2410_GPC(5), 1); 596 gpio_set_value(S3C2410_GPC(0), 1); 597 598 gpio_set_value(H1940_LATCH_LCD_P3, 1); 599 gpio_set_value(H1940_LATCH_LCD_P2, 1); 600 gpio_set_value(H1940_LATCH_LCD_P4, 1); 601 } 602} 603 604static struct plat_lcd_data h1940_lcd_power_data = { 605 .set_power = h1940_lcd_power_set, 606}; 607 608static struct platform_device h1940_lcd_powerdev = { 609 .name = "platform-lcd", 610 .dev.parent = &s3c_device_lcd.dev, 611 .dev.platform_data = &h1940_lcd_power_data, 612}; 613 614static struct uda1380_platform_data uda1380_info = { 615 .gpio_power = H1940_LATCH_UDA_POWER, 616 .gpio_reset = S3C2410_GPA(12), 617 .dac_clk = UDA1380_DAC_CLK_SYSCLK, 618}; 619 620static struct i2c_board_info h1940_i2c_devices[] = { 621 { 622 I2C_BOARD_INFO("uda1380", 0x1a), 623 .platform_data = &uda1380_info, 624 }, 625}; 626 627#define DECLARE_BUTTON(p, k, n, w) \ 628 { \ 629 .gpio = p, \ 630 .code = k, \ 631 .desc = n, \ 632 .wakeup = w, \ 633 .active_low = 1, \ 634 } 635 636static struct gpio_keys_button h1940_buttons[] = { 637 DECLARE_BUTTON(S3C2410_GPF(0), KEY_POWER, "Power", 1), 638 DECLARE_BUTTON(S3C2410_GPF(6), KEY_ENTER, "Select", 1), 639 DECLARE_BUTTON(S3C2410_GPF(7), KEY_RECORD, "Record", 0), 640 DECLARE_BUTTON(S3C2410_GPG(0), KEY_F11, "Calendar", 0), 641 DECLARE_BUTTON(S3C2410_GPG(2), KEY_F12, "Contacts", 0), 642 DECLARE_BUTTON(S3C2410_GPG(3), KEY_MAIL, "Mail", 0), 643 DECLARE_BUTTON(S3C2410_GPG(6), KEY_LEFT, "Left_arrow", 0), 644 DECLARE_BUTTON(S3C2410_GPG(7), KEY_HOMEPAGE, "Home", 0), 645 DECLARE_BUTTON(S3C2410_GPG(8), KEY_RIGHT, "Right_arrow", 0), 646 DECLARE_BUTTON(S3C2410_GPG(9), KEY_UP, "Up_arrow", 0), 647 DECLARE_BUTTON(S3C2410_GPG(10), KEY_DOWN, "Down_arrow", 0), 648}; 649 650static struct gpio_keys_platform_data h1940_buttons_data = { 651 .buttons = h1940_buttons, 652 .nbuttons = ARRAY_SIZE(h1940_buttons), 653}; 654 655static struct platform_device h1940_dev_buttons = { 656 .name = "gpio-keys", 657 .id = -1, 658 .dev = { 659 .platform_data = &h1940_buttons_data, 660 } 661}; 662 663static struct platform_device *h1940_devices[] __initdata = { 664 &h1940_dev_buttons, 665 &s3c_device_ohci, 666 &s3c_device_lcd, 667 &s3c_device_wdt, 668 &s3c_device_i2c0, 669 &s3c_device_iis, 670 &s3c_device_usbgadget, 671 &h1940_device_leds, 672 &h1940_device_bluetooth, 673 &s3c_device_sdi, 674 &s3c_device_rtc, 675 &samsung_device_pwm, 676 &h1940_backlight, 677 &h1940_lcd_powerdev, 678 &s3c_device_adc, 679 &s3c_device_ts, 680 &power_supply, 681 &h1940_battery, 682 &h1940_audio, 683}; 684 685static void __init h1940_map_io(void) 686{ 687 s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); 688 s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); 689 s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4); 690 691 /* setup PM */ 692 693#ifdef CONFIG_PM_H1940 694 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024); 695#endif 696 s3c_pm_init(); 697 698 /* Add latch gpio chip, set latch initial value */ 699 h1940_latch_control(0, 0); 700 WARN_ON(gpiochip_add_data(&h1940_latch_gpiochip, NULL)); 701} 702 703static void __init h1940_init_time(void) 704{ 705 s3c2410_init_clocks(12000000); 706 s3c24xx_timer_init(); 707} 708 709/* H1940 and RX3715 need to reserve this for suspend */ 710static void __init h1940_reserve(void) 711{ 712 memblock_reserve(0x30003000, 0x1000); 713 memblock_reserve(0x30081000, 0x1000); 714} 715 716static void __init h1940_init(void) 717{ 718 u32 tmp; 719 720 s3c24xx_fb_set_platdata(&h1940_fb_info); 721 gpiod_add_lookup_table(&h1940_mmc_gpio_table); 722 gpiod_add_lookup_table(&h1940_audio_gpio_table); 723 /* Configure the I2S pins (GPE0...GPE4) in correct mode */ 724 s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), 725 S3C_GPIO_PULL_NONE); 726 s3c24xx_mci_set_platdata(&h1940_mmc_cfg); 727 s3c24xx_udc_set_platdata(&h1940_udc_cfg); 728 s3c24xx_ts_set_platdata(&h1940_ts_cfg); 729 s3c_i2c0_set_platdata(NULL); 730 731 /* Turn off suspend on both USB ports, and switch the 732 * selectable USB port to USB device mode. */ 733 734 s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | 735 S3C2410_MISCCR_USBSUSPND0 | 736 S3C2410_MISCCR_USBSUSPND1, 0x0); 737 738 tmp = (0x78 << S3C24XX_PLL_MDIV_SHIFT) 739 | (0x02 << S3C24XX_PLL_PDIV_SHIFT) 740 | (0x03 << S3C24XX_PLL_SDIV_SHIFT); 741 writel(tmp, S3C2410_UPLLCON); 742 743 gpio_request(S3C2410_GPC(0), "LCD power"); 744 gpio_request(S3C2410_GPC(1), "LCD power"); 745 gpio_request(S3C2410_GPC(4), "LCD power"); 746 gpio_request(S3C2410_GPC(5), "LCD power"); 747 gpio_request(S3C2410_GPC(6), "LCD power"); 748 gpio_request(H1940_LATCH_LCD_P0, "LCD power"); 749 gpio_request(H1940_LATCH_LCD_P1, "LCD power"); 750 gpio_request(H1940_LATCH_LCD_P2, "LCD power"); 751 gpio_request(H1940_LATCH_LCD_P3, "LCD power"); 752 gpio_request(H1940_LATCH_LCD_P4, "LCD power"); 753 gpio_request(H1940_LATCH_MAX1698_nSHUTDOWN, "LCD power"); 754 gpio_direction_output(S3C2410_GPC(0), 0); 755 gpio_direction_output(S3C2410_GPC(1), 0); 756 gpio_direction_output(S3C2410_GPC(4), 0); 757 gpio_direction_output(S3C2410_GPC(5), 0); 758 gpio_direction_input(S3C2410_GPC(6)); 759 gpio_direction_output(H1940_LATCH_LCD_P0, 0); 760 gpio_direction_output(H1940_LATCH_LCD_P1, 0); 761 gpio_direction_output(H1940_LATCH_LCD_P2, 0); 762 gpio_direction_output(H1940_LATCH_LCD_P3, 0); 763 gpio_direction_output(H1940_LATCH_LCD_P4, 0); 764 gpio_direction_output(H1940_LATCH_MAX1698_nSHUTDOWN, 0); 765 766 gpio_request(H1940_LATCH_SD_POWER, "SD power"); 767 gpio_direction_output(H1940_LATCH_SD_POWER, 0); 768 769 pwm_add_table(h1940_pwm_lookup, ARRAY_SIZE(h1940_pwm_lookup)); 770 platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices)); 771 772 gpio_request(S3C2410_GPA(1), "Red LED blink"); 773 gpio_request(S3C2410_GPA(3), "Blue LED blink"); 774 gpio_request(S3C2410_GPA(7), "Green LED blink"); 775 gpio_request(H1940_LATCH_LED_FLASH, "LED blink"); 776 gpio_direction_output(S3C2410_GPA(1), 0); 777 gpio_direction_output(S3C2410_GPA(3), 0); 778 gpio_direction_output(S3C2410_GPA(7), 0); 779 gpio_direction_output(H1940_LATCH_LED_FLASH, 0); 780 781 i2c_register_board_info(0, h1940_i2c_devices, 782 ARRAY_SIZE(h1940_i2c_devices)); 783} 784 785MACHINE_START(H1940, "IPAQ-H1940") 786 /* Maintainer: Ben Dooks <ben-linux@fluff.org> */ 787 .atag_offset = 0x100, 788 .map_io = h1940_map_io, 789 .reserve = h1940_reserve, 790 .init_irq = s3c2410_init_irq, 791 .init_machine = h1940_init, 792 .init_time = h1940_init_time, 793MACHINE_END 794