Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mach-h1940.c
Go to the documentation of this file.
1 /* linux/arch/arm/mach-s3c2410/mach-h1940.c
2  *
3  * Copyright (c) 2003-2005 Simtec Electronics
4  * Ben Dooks <[email protected]>
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/device.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/input.h>
27 #include <linux/gpio_keys.h>
28 #include <linux/pwm_backlight.h>
29 #include <linux/i2c.h>
30 #include <linux/leds.h>
31 #include <linux/pda_power.h>
32 #include <linux/s3c_adc_battery.h>
33 #include <linux/delay.h>
34 
35 #include <video/platform_lcd.h>
36 
37 #include <linux/mmc/host.h>
38 #include <linux/export.h>
39 
40 #include <asm/mach/arch.h>
41 #include <asm/mach/map.h>
42 #include <asm/mach/irq.h>
43 
44 #include <mach/hardware.h>
45 #include <asm/irq.h>
46 #include <asm/mach-types.h>
47 
48 #include <plat/regs-serial.h>
49 #include <mach/regs-lcd.h>
50 #include <mach/regs-clock.h>
51 
52 #include <mach/regs-gpio.h>
53 #include <mach/gpio-fns.h>
54 #include <mach/gpio-nrs.h>
55 
56 #include <mach/h1940.h>
57 #include <mach/h1940-latch.h>
58 #include <mach/fb.h>
61 
62 #include <plat/gpio-cfg.h>
63 #include <plat/clock.h>
64 #include <plat/devs.h>
65 #include <plat/cpu.h>
66 #include <plat/pll.h>
67 #include <plat/pm.h>
70 
71 #include <sound/uda1380.h>
72 
73 #include "common.h"
74 
75 #define H1940_LATCH ((void __force __iomem *)0xF8000000)
76 
77 #define H1940_PA_LATCH S3C2410_CS2
78 
79 #define H1940_LATCH_BIT(x) (1 << ((x) + 16 - S3C_GPIO_END))
80 
81 static struct map_desc h1940_iodesc[] __initdata = {
82  [0] = {
83  .virtual = (unsigned long)H1940_LATCH,
85  .length = SZ_16K,
86  .type = MT_DEVICE
87  },
88 };
89 
90 #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
91 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
92 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
93 
94 static struct s3c2410_uartcfg h1940_uartcfgs[] __initdata = {
95  [0] = {
96  .hwport = 0,
97  .flags = 0,
98  .ucon = 0x3c5,
99  .ulcon = 0x03,
100  .ufcon = 0x51,
101  },
102  [1] = {
103  .hwport = 1,
104  .flags = 0,
105  .ucon = 0x245,
106  .ulcon = 0x03,
107  .ufcon = 0x00,
108  },
109  /* IR port */
110  [2] = {
111  .hwport = 2,
112  .flags = 0,
113  .uart_flags = UPF_CONS_FLOW,
114  .ucon = 0x3c5,
115  .ulcon = 0x43,
116  .ufcon = 0x51,
117  }
118 };
119 
120 /* Board control latch control */
121 
122 static unsigned int latch_state;
123 
124 static void h1940_latch_control(unsigned int clear, unsigned int set)
125 {
126  unsigned long flags;
127 
128  local_irq_save(flags);
129 
130  latch_state &= ~clear;
131  latch_state |= set;
132 
133  __raw_writel(latch_state, H1940_LATCH);
134 
135  local_irq_restore(flags);
136 }
137 
138 static inline int h1940_gpiolib_to_latch(int offset)
139 {
140  return 1 << (offset + 16);
141 }
142 
143 static void h1940_gpiolib_latch_set(struct gpio_chip *chip,
144  unsigned offset, int value)
145 {
146  int latch_bit = h1940_gpiolib_to_latch(offset);
147 
148  h1940_latch_control(value ? 0 : latch_bit,
149  value ? latch_bit : 0);
150 }
151 
152 static int h1940_gpiolib_latch_output(struct gpio_chip *chip,
153  unsigned offset, int value)
154 {
155  h1940_gpiolib_latch_set(chip, offset, value);
156  return 0;
157 }
158 
159 static int h1940_gpiolib_latch_get(struct gpio_chip *chip,
160  unsigned offset)
161 {
162  return (latch_state >> (offset + 16)) & 1;
163 }
164 
165 static struct gpio_chip h1940_latch_gpiochip = {
166  .base = H1940_LATCH_GPIO(0),
167  .owner = THIS_MODULE,
168  .label = "H1940_LATCH",
169  .ngpio = 16,
170  .direction_output = h1940_gpiolib_latch_output,
171  .set = h1940_gpiolib_latch_set,
172  .get = h1940_gpiolib_latch_get,
173 };
174 
175 static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
176  .vbus_pin = S3C2410_GPG(5),
177  .vbus_pin_inverted = 1,
178  .pullup_pin = H1940_LATCH_USB_DP,
179 };
180 
181 static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
182  .delay = 10000,
183  .presc = 49,
184  .oversampling_shift = 2,
185  .cfg_gpio = s3c24xx_ts_cfg_gpio,
186 };
187 
191 static struct s3c2410fb_display h1940_lcd __initdata = {
192  .lcdcon5= S3C2410_LCDCON5_FRM565 | \
193  S3C2410_LCDCON5_INVVLINE | \
194  S3C2410_LCDCON5_HWSWP,
195 
196  .type = S3C2410_LCDCON1_TFT,
197  .width = 240,
198  .height = 320,
199  .pixclock = 260000,
200  .xres = 240,
201  .yres = 320,
202  .bpp = 16,
203  .left_margin = 8,
204  .right_margin = 20,
205  .hsync_len = 4,
206  .upper_margin = 8,
207  .lower_margin = 7,
208  .vsync_len = 1,
209 };
210 
211 static struct s3c2410fb_mach_info h1940_fb_info __initdata = {
212  .displays = &h1940_lcd,
213  .num_displays = 1,
214  .default_display = 0,
215 
216  .lpcsel = 0x02,
217  .gpccon = 0xaa940659,
218  .gpccon_mask = 0xffffc0f0,
219  .gpcup = 0x0000ffff,
220  .gpcup_mask = 0xffffffff,
221  .gpdcon = 0xaa84aaa0,
222  .gpdcon_mask = 0xffffffff,
223  .gpdup = 0x0000faff,
224  .gpdup_mask = 0xffffffff,
225 };
226 
227 static int power_supply_init(struct device *dev)
228 {
229  return gpio_request(S3C2410_GPF(2), "cable plugged");
230 }
231 
232 static int h1940_is_ac_online(void)
233 {
234  return !gpio_get_value(S3C2410_GPF(2));
235 }
236 
237 static void power_supply_exit(struct device *dev)
238 {
240 }
241 
242 static char *h1940_supplicants[] = {
243  "main-battery",
244  "backup-battery",
245 };
246 
247 static struct pda_power_pdata power_supply_info = {
248  .init = power_supply_init,
249  .is_ac_online = h1940_is_ac_online,
250  .exit = power_supply_exit,
251  .supplied_to = h1940_supplicants,
252  .num_supplicants = ARRAY_SIZE(h1940_supplicants),
253 };
254 
255 static struct resource power_supply_resources[] = {
256  [0] = DEFINE_RES_NAMED(IRQ_EINT2, 1, "ac", IORESOURCE_IRQ \
258 };
259 
260 static struct platform_device power_supply = {
261  .name = "pda-power",
262  .id = -1,
263  .dev = {
264  .platform_data =
265  &power_supply_info,
266  },
267  .resource = power_supply_resources,
268  .num_resources = ARRAY_SIZE(power_supply_resources),
269 };
270 
271 static const struct s3c_adc_bat_thresh bat_lut_noac[] = {
272  { .volt = 4070, .cur = 162, .level = 100},
273  { .volt = 4040, .cur = 165, .level = 95},
274  { .volt = 4016, .cur = 164, .level = 90},
275  { .volt = 3996, .cur = 166, .level = 85},
276  { .volt = 3971, .cur = 168, .level = 80},
277  { .volt = 3951, .cur = 168, .level = 75},
278  { .volt = 3931, .cur = 170, .level = 70},
279  { .volt = 3903, .cur = 172, .level = 65},
280  { .volt = 3886, .cur = 172, .level = 60},
281  { .volt = 3858, .cur = 176, .level = 55},
282  { .volt = 3842, .cur = 176, .level = 50},
283  { .volt = 3818, .cur = 176, .level = 45},
284  { .volt = 3789, .cur = 180, .level = 40},
285  { .volt = 3769, .cur = 180, .level = 35},
286  { .volt = 3749, .cur = 184, .level = 30},
287  { .volt = 3732, .cur = 184, .level = 25},
288  { .volt = 3716, .cur = 184, .level = 20},
289  { .volt = 3708, .cur = 184, .level = 15},
290  { .volt = 3716, .cur = 96, .level = 10},
291  { .volt = 3700, .cur = 96, .level = 5},
292  { .volt = 3684, .cur = 96, .level = 0},
293 };
294 
295 static const struct s3c_adc_bat_thresh bat_lut_acin[] = {
296  { .volt = 4130, .cur = 0, .level = 100},
297  { .volt = 3982, .cur = 0, .level = 50},
298  { .volt = 3854, .cur = 0, .level = 10},
299  { .volt = 3841, .cur = 0, .level = 0},
300 };
301 
302 static int h1940_bat_init(void)
303 {
304  int ret;
305 
306  ret = gpio_request(H1940_LATCH_SM803_ENABLE, "h1940-charger-enable");
307  if (ret)
308  return ret;
310 
311  return 0;
312 
313 }
314 
315 static void h1940_bat_exit(void)
316 {
318 }
319 
320 static void h1940_enable_charger(void)
321 {
323 }
324 
325 static void h1940_disable_charger(void)
326 {
328 }
329 
330 static struct s3c_adc_bat_pdata h1940_bat_cfg = {
331  .init = h1940_bat_init,
332  .exit = h1940_bat_exit,
333  .enable_charger = h1940_enable_charger,
334  .disable_charger = h1940_disable_charger,
335  .gpio_charge_finished = S3C2410_GPF(3),
336  .gpio_inverted = 1,
337  .lut_noac = bat_lut_noac,
338  .lut_noac_cnt = ARRAY_SIZE(bat_lut_noac),
339  .lut_acin = bat_lut_acin,
340  .lut_acin_cnt = ARRAY_SIZE(bat_lut_acin),
341  .volt_channel = 0,
342  .current_channel = 1,
343  .volt_mult = 4056,
344  .current_mult = 1893,
345  .internal_impedance = 200,
346  .backup_volt_channel = 3,
347  /* TODO Check backup volt multiplier */
348  .backup_volt_mult = 4056,
349  .backup_volt_min = 0,
350  .backup_volt_max = 4149288
351 };
352 
353 static struct platform_device h1940_battery = {
354  .name = "s3c-adc-battery",
355  .id = -1,
356  .dev = {
357  .parent = &s3c_device_adc.dev,
358  .platform_data = &h1940_bat_cfg,
359  },
360 };
361 
362 static DEFINE_SPINLOCK(h1940_blink_spin);
363 
364 int h1940_led_blink_set(unsigned gpio, int state,
365  unsigned long *delay_on, unsigned long *delay_off)
366 {
367  int blink_gpio, check_gpio1, check_gpio2;
368 
369  switch (gpio) {
371  blink_gpio = S3C2410_GPA(7);
372  check_gpio1 = S3C2410_GPA(1);
373  check_gpio2 = S3C2410_GPA(3);
374  break;
375  case H1940_LATCH_LED_RED:
376  blink_gpio = S3C2410_GPA(1);
377  check_gpio1 = S3C2410_GPA(7);
378  check_gpio2 = S3C2410_GPA(3);
379  break;
380  default:
381  blink_gpio = S3C2410_GPA(3);
382  check_gpio1 = S3C2410_GPA(1);
383  check_gpio2 = S3C2410_GPA(7);
384  break;
385  }
386 
387  if (delay_on && delay_off && !*delay_on && !*delay_off)
388  *delay_on = *delay_off = 500;
389 
390  spin_lock(&h1940_blink_spin);
391 
392  switch (state) {
395  if (!gpio_get_value(check_gpio1) &&
396  !gpio_get_value(check_gpio2))
398  gpio_set_value(blink_gpio, 0);
399  if (gpio_is_valid(gpio))
400  gpio_set_value(gpio, state);
401  break;
402  case GPIO_LED_BLINK:
403  if (gpio_is_valid(gpio))
404  gpio_set_value(gpio, 0);
406  gpio_set_value(blink_gpio, 1);
407  break;
408  }
409 
410  spin_unlock(&h1940_blink_spin);
411 
412  return 0;
413 }
415 
416 static struct gpio_led h1940_leds_desc[] = {
417  {
418  .name = "Green",
419  .default_trigger = "main-battery-full",
420  .gpio = H1940_LATCH_LED_GREEN,
421  .retain_state_suspended = 1,
422  },
423  {
424  .name = "Red",
425  .default_trigger
426  = "main-battery-charging-blink-full-solid",
427  .gpio = H1940_LATCH_LED_RED,
428  .retain_state_suspended = 1,
429  },
430 };
431 
432 static struct gpio_led_platform_data h1940_leds_pdata = {
433  .num_leds = ARRAY_SIZE(h1940_leds_desc),
434  .leds = h1940_leds_desc,
435  .gpio_blink_set = h1940_led_blink_set,
436 };
437 
438 static struct platform_device h1940_device_leds = {
439  .name = "leds-gpio",
440  .id = -1,
441  .dev = {
442  .platform_data = &h1940_leds_pdata,
443  },
444 };
445 
446 static struct platform_device h1940_device_bluetooth = {
447  .name = "h1940-bt",
448  .id = -1,
449 };
450 
451 static void h1940_set_mmc_power(unsigned char power_mode, unsigned short vdd)
452 {
453  switch (power_mode) {
454  case MMC_POWER_OFF:
456  break;
457  case MMC_POWER_UP:
458  case MMC_POWER_ON:
460  break;
461  default:
462  break;
463  }
464 }
465 
466 static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = {
467  .gpio_detect = S3C2410_GPF(5),
468  .gpio_wprotect = S3C2410_GPH(8),
469  .set_power = h1940_set_mmc_power,
470  .ocr_avail = MMC_VDD_32_33,
471 };
472 
473 static int h1940_backlight_init(struct device *dev)
474 {
475  gpio_request(S3C2410_GPB(0), "Backlight");
476 
481 
482  return 0;
483 }
484 
485 static int h1940_backlight_notify(struct device *dev, int brightness)
486 {
487  if (!brightness) {
490  } else {
495  }
496  return brightness;
497 }
498 
499 static void h1940_backlight_exit(struct device *dev)
500 {
503 }
504 
505 
506 static struct platform_pwm_backlight_data backlight_data = {
507  .pwm_id = 0,
508  .max_brightness = 100,
509  .dft_brightness = 50,
510  /* tcnt = 0x31 */
511  .pwm_period_ns = 36296,
512  .init = h1940_backlight_init,
513  .notify = h1940_backlight_notify,
514  .exit = h1940_backlight_exit,
515 };
516 
517 static struct platform_device h1940_backlight = {
518  .name = "pwm-backlight",
519  .dev = {
520  .parent = &s3c_device_timer[0].dev,
521  .platform_data = &backlight_data,
522  },
523  .id = -1,
524 };
525 
526 static void h1940_lcd_power_set(struct plat_lcd_data *pd,
527  unsigned int power)
528 {
529  int value, retries = 100;
530 
531  if (!power) {
533  /* wait for 3ac */
534  do {
535  value = gpio_get_value(S3C2410_GPC(6));
536  } while (value && retries--);
537 
541 
544 
547 
549 
550  } else {
553 
556  mdelay(10);
559 
562 
566  }
567 }
568 
569 static struct plat_lcd_data h1940_lcd_power_data = {
570  .set_power = h1940_lcd_power_set,
571 };
572 
573 static struct platform_device h1940_lcd_powerdev = {
574  .name = "platform-lcd",
575  .dev.parent = &s3c_device_lcd.dev,
576  .dev.platform_data = &h1940_lcd_power_data,
577 };
578 
579 static struct uda1380_platform_data uda1380_info = {
580  .gpio_power = H1940_LATCH_UDA_POWER,
581  .gpio_reset = S3C2410_GPA(12),
582  .dac_clk = UDA1380_DAC_CLK_SYSCLK,
583 };
584 
585 static struct i2c_board_info h1940_i2c_devices[] = {
586  {
587  I2C_BOARD_INFO("uda1380", 0x1a),
588  .platform_data = &uda1380_info,
589  },
590 };
591 
592 #define DECLARE_BUTTON(p, k, n, w) \
593  { \
594  .gpio = p, \
595  .code = k, \
596  .desc = n, \
597  .wakeup = w, \
598  .active_low = 1, \
599  }
600 
601 static struct gpio_keys_button h1940_buttons[] = {
602  DECLARE_BUTTON(S3C2410_GPF(0), KEY_POWER, "Power", 1),
603  DECLARE_BUTTON(S3C2410_GPF(6), KEY_ENTER, "Select", 1),
604  DECLARE_BUTTON(S3C2410_GPF(7), KEY_RECORD, "Record", 0),
605  DECLARE_BUTTON(S3C2410_GPG(0), KEY_F11, "Calendar", 0),
606  DECLARE_BUTTON(S3C2410_GPG(2), KEY_F12, "Contacts", 0),
607  DECLARE_BUTTON(S3C2410_GPG(3), KEY_MAIL, "Mail", 0),
608  DECLARE_BUTTON(S3C2410_GPG(6), KEY_LEFT, "Left_arrow", 0),
609  DECLARE_BUTTON(S3C2410_GPG(7), KEY_HOMEPAGE, "Home", 0),
610  DECLARE_BUTTON(S3C2410_GPG(8), KEY_RIGHT, "Right_arrow", 0),
611  DECLARE_BUTTON(S3C2410_GPG(9), KEY_UP, "Up_arrow", 0),
612  DECLARE_BUTTON(S3C2410_GPG(10), KEY_DOWN, "Down_arrow", 0),
613 };
614 
615 static struct gpio_keys_platform_data h1940_buttons_data = {
616  .buttons = h1940_buttons,
617  .nbuttons = ARRAY_SIZE(h1940_buttons),
618 };
619 
620 static struct platform_device h1940_dev_buttons = {
621  .name = "gpio-keys",
622  .id = -1,
623  .dev = {
624  .platform_data = &h1940_buttons_data,
625  }
626 };
627 
628 static struct platform_device *h1940_devices[] __initdata = {
629  &h1940_dev_buttons,
637  &h1940_device_leds,
638  &h1940_device_bluetooth,
641  &s3c_device_timer[0],
642  &h1940_backlight,
643  &h1940_lcd_powerdev,
645  &s3c_device_ts,
646  &power_supply,
647  &h1940_battery,
648 };
649 
650 static void __init h1940_map_io(void)
651 {
652  s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
654  s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
655 
656  /* setup PM */
657 
658 #ifdef CONFIG_PM_H1940
660 #endif
661  s3c_pm_init();
662 
663  /* Add latch gpio chip, set latch initial value */
664  h1940_latch_control(0, 0);
665  WARN_ON(gpiochip_add(&h1940_latch_gpiochip));
666 }
667 
668 /* H1940 and RX3715 need to reserve this for suspend */
669 static void __init h1940_reserve(void)
670 {
671  memblock_reserve(0x30003000, 0x1000);
672  memblock_reserve(0x30081000, 0x1000);
673 }
674 
675 static void __init h1940_init_irq(void)
676 {
678 }
679 
680 static void __init h1940_init(void)
681 {
682  u32 tmp;
683 
684  s3c24xx_fb_set_platdata(&h1940_fb_info);
685  s3c24xx_mci_set_platdata(&h1940_mmc_cfg);
686  s3c24xx_udc_set_platdata(&h1940_udc_cfg);
687  s3c24xx_ts_set_platdata(&h1940_ts_cfg);
689 
690  /* Turn off suspend on both USB ports, and switch the
691  * selectable USB port to USB device mode. */
692 
696 
697  tmp = (0x78 << S3C24XX_PLL_MDIV_SHIFT)
698  | (0x02 << S3C24XX_PLL_PDIV_SHIFT)
699  | (0x03 << S3C24XX_PLL_SDIV_SHIFT);
700  writel(tmp, S3C2410_UPLLCON);
701 
702  gpio_request(S3C2410_GPC(0), "LCD power");
703  gpio_request(S3C2410_GPC(1), "LCD power");
704  gpio_request(S3C2410_GPC(4), "LCD power");
705  gpio_request(S3C2410_GPC(5), "LCD power");
706  gpio_request(S3C2410_GPC(6), "LCD power");
707  gpio_request(H1940_LATCH_LCD_P0, "LCD power");
708  gpio_request(H1940_LATCH_LCD_P1, "LCD power");
709  gpio_request(H1940_LATCH_LCD_P2, "LCD power");
710  gpio_request(H1940_LATCH_LCD_P3, "LCD power");
711  gpio_request(H1940_LATCH_LCD_P4, "LCD power");
724 
725  gpio_request(H1940_LATCH_SD_POWER, "SD power");
727 
728  platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
729 
730  gpio_request(S3C2410_GPA(1), "Red LED blink");
731  gpio_request(S3C2410_GPA(3), "Blue LED blink");
732  gpio_request(S3C2410_GPA(7), "Green LED blink");
733  gpio_request(H1940_LATCH_LED_FLASH, "LED blink");
738 
739  i2c_register_board_info(0, h1940_i2c_devices,
740  ARRAY_SIZE(h1940_i2c_devices));
741 }
742 
743 MACHINE_START(H1940, "IPAQ-H1940")
744  /* Maintainer: Ben Dooks <[email protected]> */
745  .atag_offset = 0x100,
746  .map_io = h1940_map_io,
747  .reserve = h1940_reserve,
748  .init_irq = h1940_init_irq,
749  .init_machine = h1940_init,
750  .timer = &s3c24xx_timer,
751  .restart = s3c2410_restart,