]> err.no Git - linux-2.6/blob - arch/arm/mach-pxa/magician.c
[ARM] 4965/1: magician: use htc-pasic3,leds-pasic3,ds1wm,leds-gpio
[linux-2.6] / arch / arm / mach-pxa / magician.c
1 /*
2  * Support for HTC Magician PDA phones:
3  * i-mate JAM, O2 Xda mini, Orange SPV M500, Qtek s100, Qtek s110
4  * and T-Mobile MDA Compact.
5  *
6  * Copyright (c) 2006-2007 Philipp Zabel
7  *
8  * Based on hx4700.c, spitz.c and others.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/platform_device.h>
19 #include <linux/delay.h>
20 #include <linux/gpio_keys.h>
21 #include <linux/input.h>
22 #include <linux/mfd/htc-egpio.h>
23 #include <linux/mfd/htc-pasic3.h>
24 #include <linux/mtd/mtd.h>
25 #include <linux/mtd/map.h>
26 #include <linux/mtd/physmap.h>
27 #include <linux/pda_power.h>
28
29 #include <asm/gpio.h>
30 #include <asm/hardware.h>
31 #include <asm/mach-types.h>
32 #include <asm/mach/arch.h>
33 #include <asm/arch/magician.h>
34 #include <asm/arch/pxa-regs.h>
35 #include <asm/arch/pxafb.h>
36 #include <asm/arch/i2c.h>
37 #include <asm/arch/mmc.h>
38 #include <asm/arch/irda.h>
39 #include <asm/arch/ohci.h>
40
41 #include "generic.h"
42
43 /*
44  * IRDA
45  */
46
47 static void magician_irda_transceiver_mode(struct device *dev, int mode)
48 {
49         gpio_set_value(GPIO83_MAGICIAN_nIR_EN, mode & IR_OFF);
50 }
51
52 static struct pxaficp_platform_data magician_ficp_info = {
53         .transceiver_cap  = IR_SIRMODE | IR_OFF,
54         .transceiver_mode = magician_irda_transceiver_mode,
55 };
56
57 /*
58  * GPIO Keys
59  */
60
61 static struct gpio_keys_button magician_button_table[] = {
62         {KEY_POWER,      GPIO0_MAGICIAN_KEY_POWER,      0, "Power button"},
63         {KEY_ESC,        GPIO37_MAGICIAN_KEY_HANGUP,    0, "Hangup button"},
64         {KEY_F10,        GPIO38_MAGICIAN_KEY_CONTACTS,  0, "Contacts button"},
65         {KEY_CALENDAR,   GPIO90_MAGICIAN_KEY_CALENDAR,  0, "Calendar button"},
66         {KEY_CAMERA,     GPIO91_MAGICIAN_KEY_CAMERA,    0, "Camera button"},
67         {KEY_UP,         GPIO93_MAGICIAN_KEY_UP,        0, "Up button"},
68         {KEY_DOWN,       GPIO94_MAGICIAN_KEY_DOWN,      0, "Down button"},
69         {KEY_LEFT,       GPIO95_MAGICIAN_KEY_LEFT,      0, "Left button"},
70         {KEY_RIGHT,      GPIO96_MAGICIAN_KEY_RIGHT,     0, "Right button"},
71         {KEY_KPENTER,    GPIO97_MAGICIAN_KEY_ENTER,     0, "Action button"},
72         {KEY_RECORD,     GPIO98_MAGICIAN_KEY_RECORD,    0, "Record button"},
73         {KEY_VOLUMEUP,   GPIO100_MAGICIAN_KEY_VOL_UP,   0, "Volume up"},
74         {KEY_VOLUMEDOWN, GPIO101_MAGICIAN_KEY_VOL_DOWN, 0, "Volume down"},
75         {KEY_PHONE,      GPIO102_MAGICIAN_KEY_PHONE,    0, "Phone button"},
76         {KEY_PLAY,       GPIO99_MAGICIAN_HEADPHONE_IN,  0, "Headset button"},
77 };
78
79 static struct gpio_keys_platform_data gpio_keys_data = {
80         .buttons  = magician_button_table,
81         .nbuttons = ARRAY_SIZE(magician_button_table),
82 };
83
84 static struct platform_device gpio_keys = {
85         .name = "gpio-keys",
86         .dev  = {
87                 .platform_data = &gpio_keys_data,
88         },
89         .id   = -1,
90 };
91
92
93 /*
94  * EGPIO (Xilinx CPLD)
95  *
96  * 7 32-bit aligned 8-bit registers: 3x output, 1x irq, 3x input
97  */
98
99 static struct resource egpio_resources[] = {
100         [0] = {
101                 .start = PXA_CS3_PHYS,
102                 .end   = PXA_CS3_PHYS + 0x20,
103                 .flags = IORESOURCE_MEM,
104         },
105         [1] = {
106                 .start = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ),
107                 .end   = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ),
108                 .flags = IORESOURCE_IRQ,
109         },
110 };
111
112 static struct htc_egpio_chip egpio_chips[] = {
113         [0] = {
114                 .reg_start = 0,
115                 .gpio_base = MAGICIAN_EGPIO(0, 0),
116                 .num_gpios = 24,
117                 .direction = HTC_EGPIO_OUTPUT,
118                 .initial_values = 0x40, /* EGPIO_MAGICIAN_GSM_RESET */
119         },
120         [1] = {
121                 .reg_start = 4,
122                 .gpio_base = MAGICIAN_EGPIO(4, 0),
123                 .num_gpios = 24,
124                 .direction = HTC_EGPIO_INPUT,
125         },
126 };
127
128 static struct htc_egpio_platform_data egpio_info = {
129         .reg_width    = 8,
130         .bus_width    = 32,
131         .irq_base     = IRQ_BOARD_START,
132         .num_irqs     = 4,
133         .ack_register = 3,
134         .chip         = egpio_chips,
135         .num_chips    = ARRAY_SIZE(egpio_chips),
136 };
137
138 static struct platform_device egpio = {
139         .name          = "htc-egpio",
140         .id            = -1,
141         .resource      = egpio_resources,
142         .num_resources = ARRAY_SIZE(egpio_resources),
143         .dev = {
144                 .platform_data = &egpio_info,
145         },
146 };
147
148 /*
149  * LCD - Toppoly TD028STEB1 or Samsung LTP280QV
150  */
151
152 static struct pxafb_mode_info toppoly_modes[] = {
153         {
154                 .pixclock     = 96153,
155                 .bpp          = 16,
156                 .xres         = 240,
157                 .yres         = 320,
158                 .hsync_len    = 11,
159                 .vsync_len    = 3,
160                 .left_margin  = 19,
161                 .upper_margin = 2,
162                 .right_margin = 10,
163                 .lower_margin = 2,
164                 .sync         = 0,
165         },
166 };
167
168 static struct pxafb_mode_info samsung_modes[] = {
169         {
170                 .pixclock     = 96153,
171                 .bpp          = 16,
172                 .xres         = 240,
173                 .yres         = 320,
174                 .hsync_len    = 8,
175                 .vsync_len    = 4,
176                 .left_margin  = 9,
177                 .upper_margin = 4,
178                 .right_margin = 9,
179                 .lower_margin = 4,
180                 .sync         = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
181         },
182 };
183
184 static void toppoly_lcd_power(int on, struct fb_var_screeninfo *si)
185 {
186         pr_debug("Toppoly LCD power\n");
187
188         if (on) {
189                 pr_debug("on\n");
190                 gpio_set_value(EGPIO_MAGICIAN_TOPPOLY_POWER, 1);
191                 gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1);
192                 udelay(2000);
193                 gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);
194                 udelay(2000);
195                 /* FIXME: enable LCDC here */
196                 udelay(2000);
197                 gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1);
198                 udelay(2000);
199                 gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1);
200         } else {
201                 pr_debug("off\n");
202                 msleep(15);
203                 gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0);
204                 udelay(500);
205                 gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0);
206                 udelay(1000);
207                 gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0);
208                 gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);
209         }
210 }
211
212 static void samsung_lcd_power(int on, struct fb_var_screeninfo *si)
213 {
214         pr_debug("Samsung LCD power\n");
215
216         if (on) {
217                 pr_debug("on\n");
218                 if (system_rev < 3)
219                         gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 1);
220                 else
221                         gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);
222                 mdelay(10);
223                 gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1);
224                 mdelay(10);
225                 gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1);
226                 mdelay(30);
227                 gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1);
228                 mdelay(10);
229         } else {
230                 pr_debug("off\n");
231                 mdelay(10);
232                 gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0);
233                 mdelay(30);
234                 gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0);
235                 mdelay(10);
236                 gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0);
237                 mdelay(10);
238                 if (system_rev < 3)
239                         gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
240                 else
241                         gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);
242         }
243 }
244
245 static struct pxafb_mach_info toppoly_info = {
246         .modes           = toppoly_modes,
247         .num_modes       = 1,
248         .fixed_modes     = 1,
249         .lccr0           = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
250         .lccr3           = LCCR3_PixRsEdg,
251         .pxafb_lcd_power = toppoly_lcd_power,
252 };
253
254 static struct pxafb_mach_info samsung_info = {
255         .modes           = samsung_modes,
256         .num_modes       = 1,
257         .fixed_modes     = 1,
258         .lccr0           = LCCR0_LDDALT | LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
259         .lccr3           = LCCR3_PixFlEdg,
260         .pxafb_lcd_power = samsung_lcd_power,
261 };
262
263 /*
264  * Backlight
265  */
266
267 static void magician_set_bl_intensity(int intensity)
268 {
269         if (intensity) {
270                 PWM_CTRL0 = 1;
271                 PWM_PERVAL0 = 0xc8;
272                 if (intensity > 0xc7) {
273                         PWM_PWDUTY0 = intensity - 0x48;
274                         gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 1);
275                 } else {
276                         PWM_PWDUTY0 = intensity;
277                         gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 0);
278                 }
279                 gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 1);
280                 pxa_set_cken(CKEN_PWM0, 1);
281         } else {
282                 /* PWM_PWDUTY0 = intensity; */
283                 gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 0);
284                 pxa_set_cken(CKEN_PWM0, 0);
285         }
286 }
287
288 static struct generic_bl_info backlight_info = {
289         .default_intensity = 0x64,
290         .limit_mask        = 0x0b,
291         .max_intensity     = 0xc7+0x48,
292         .set_bl_intensity  = magician_set_bl_intensity,
293 };
294
295 static struct platform_device backlight = {
296         .name = "generic-bl",
297         .dev  = {
298                 .platform_data = &backlight_info,
299         },
300         .id   = -1,
301 };
302
303 /*
304  * LEDs
305  */
306
307 struct gpio_led gpio_leds[] = {
308         {
309                 .name = "magician::vibra",
310                 .default_trigger = "none",
311                 .gpio = GPIO22_MAGICIAN_VIBRA_EN,
312         },
313         {
314                 .name = "magician::phone_bl",
315                 .default_trigger = "none",
316                 .gpio = GPIO103_MAGICIAN_LED_KP,
317         },
318 };
319
320 static struct gpio_led_platform_data gpio_led_info = {
321         .leds = gpio_leds,
322         .num_leds = ARRAY_SIZE(gpio_leds),
323 };
324
325 static struct platform_device leds_gpio = {
326         .name = "leds-gpio",
327         .id   = -1,
328         .dev  = {
329                 .platform_data = &gpio_led_info,
330         },
331 };
332
333 static struct pasic3_led pasic3_leds[] = {
334         {
335                 .led = {
336                         .name            = "magician:red",
337                         .default_trigger = "ds2760-battery.0-charging",
338                 },
339                 .hw_num = 0,
340                 .bit2   = PASIC3_BIT2_LED0,
341                 .mask   = PASIC3_MASK_LED0,
342         },
343         {
344                 .led = {
345                         .name            = "magician:green",
346                         .default_trigger = "ds2760-battery.0-charging-or-full",
347                 },
348                 .hw_num = 1,
349                 .bit2   = PASIC3_BIT2_LED1,
350                 .mask   = PASIC3_MASK_LED1,
351         },
352         {
353                 .led = {
354                         .name            = "magician:blue",
355                         .default_trigger = "bluetooth",
356                 },
357                 .hw_num = 2,
358                 .bit2   = PASIC3_BIT2_LED2,
359                 .mask   = PASIC3_MASK_LED2,
360         },
361 };
362
363 static struct platform_device pasic3;
364
365 static struct pasic3_leds_machinfo __devinit pasic3_leds_info = {
366         .num_leds   = ARRAY_SIZE(pasic3_leds),
367         .power_gpio = EGPIO_MAGICIAN_LED_POWER,
368         .leds       = pasic3_leds,
369 };
370
371 /*
372  * PASIC3 with DS1WM
373  */
374
375 static struct resource pasic3_resources[] = {
376         [0] = {
377                 .start  = PXA_CS2_PHYS,
378                 .end    = PXA_CS2_PHYS + 0x1b,
379                 .flags  = IORESOURCE_MEM,
380         },
381         /* No IRQ handler in the PASIC3, DS1WM needs an external IRQ */
382         [1] = {
383                 .start  = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ),
384                 .end    = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ),
385                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
386         }
387 };
388
389 static struct pasic3_platform_data pasic3_platform_data = {
390         .bus_shift  = 2,
391         .led_pdata  = &pasic3_leds_info,
392         .clock_rate = 4000000,
393 };
394
395 static struct platform_device pasic3 = {
396         .name           = "pasic3",
397         .id             = -1,
398         .num_resources  = ARRAY_SIZE(pasic3_resources),
399         .resource       = pasic3_resources,
400         .dev = {
401                 .platform_data = &pasic3_platform_data,
402         },
403 };
404
405 /*
406  * External power
407  */
408
409 static int magician_is_ac_online(void)
410 {
411         return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC);
412 }
413
414 static int magician_is_usb_online(void)
415 {
416         return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_USB);
417 }
418
419 static void magician_set_charge(int flags)
420 {
421         gpio_set_value(GPIO30_MAGICIAN_nCHARGE_EN, !flags);
422         gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags);
423 }
424
425 static char *magician_supplicants[] = {
426         "ds2760-battery.0", "backup-battery"
427 };
428
429 static struct pda_power_pdata power_supply_info = {
430         .is_ac_online    = magician_is_ac_online,
431         .is_usb_online   = magician_is_usb_online,
432         .set_charge      = magician_set_charge,
433         .supplied_to     = magician_supplicants,
434         .num_supplicants = ARRAY_SIZE(magician_supplicants),
435 };
436
437 static struct resource power_supply_resources[] = {
438         [0] = {
439                 .name  = "ac",
440                 .flags = IORESOURCE_IRQ,
441                 .start = IRQ_MAGICIAN_AC,
442                 .end   = IRQ_MAGICIAN_AC,
443         },
444         [1] = {
445                 .name  = "usb",
446                 .flags = IORESOURCE_IRQ,
447                 .start = IRQ_MAGICIAN_AC,
448                 .end   = IRQ_MAGICIAN_AC,
449         },
450 };
451
452 static struct platform_device power_supply = {
453         .name = "pda-power",
454         .id   = -1,
455         .dev  = {
456                 .platform_data = &power_supply_info,
457         },
458         .resource      = power_supply_resources,
459         .num_resources = ARRAY_SIZE(power_supply_resources),
460 };
461
462
463 /*
464  * MMC/SD
465  */
466
467 static int magician_mci_init(struct device *dev,
468                                 irq_handler_t detect_irq, void *data)
469 {
470         return request_irq(IRQ_MAGICIAN_SD, detect_irq,
471                                 IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
472                                 "MMC card detect", data);
473 }
474
475 static void magician_mci_setpower(struct device *dev, unsigned int vdd)
476 {
477         struct pxamci_platform_data *pdata = dev->platform_data;
478
479         gpio_set_value(EGPIO_MAGICIAN_SD_POWER, (1 << vdd) & pdata->ocr_mask);
480 }
481
482 static int magician_mci_get_ro(struct device *dev)
483 {
484         return (!gpio_get_value(EGPIO_MAGICIAN_nSD_READONLY));
485 }
486
487 static void magician_mci_exit(struct device *dev, void *data)
488 {
489         free_irq(IRQ_MAGICIAN_SD, data);
490 }
491
492 static struct pxamci_platform_data magician_mci_info = {
493         .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
494         .init     = magician_mci_init,
495         .get_ro   = magician_mci_get_ro,
496         .setpower = magician_mci_setpower,
497         .exit     = magician_mci_exit,
498 };
499
500
501 /*
502  * USB OHCI
503  */
504
505 static int magician_ohci_init(struct device *dev)
506 {
507         UHCHR = (UHCHR | UHCHR_SSEP2 | UHCHR_PCPL | UHCHR_CGR) &
508             ~(UHCHR_SSEP1 | UHCHR_SSEP3 | UHCHR_SSE);
509
510         return 0;
511 }
512
513 static struct pxaohci_platform_data magician_ohci_info = {
514         .port_mode    = PMM_PERPORT_MODE,
515         .init         = magician_ohci_init,
516         .power_budget = 0,
517 };
518
519
520 /*
521  * StrataFlash
522  */
523
524 static void magician_set_vpp(struct map_info *map, int vpp)
525 {
526         gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp);
527 }
528
529 #define PXA_CS_SIZE             0x04000000
530
531 static struct resource strataflash_resource = {
532         .start = PXA_CS0_PHYS,
533         .end   = PXA_CS0_PHYS + PXA_CS_SIZE - 1,
534         .flags = IORESOURCE_MEM,
535 };
536
537 static struct physmap_flash_data strataflash_data = {
538         .width = 4,
539         .set_vpp = magician_set_vpp,
540 };
541
542 static struct platform_device strataflash = {
543         .name          = "physmap-flash",
544         .id            = -1,
545         .resource      = &strataflash_resource,
546         .num_resources = 1,
547         .dev = {
548                 .platform_data = &strataflash_data,
549         },
550 };
551
552 /*
553  * Platform devices
554  */
555
556 static struct platform_device *devices[] __initdata = {
557         &gpio_keys,
558         &egpio,
559         &backlight,
560         &pasic3,
561         &power_supply,
562         &strataflash,
563         &leds_gpio,
564 };
565
566 static void __init magician_init(void)
567 {
568         void __iomem *cpld;
569         int lcd_select;
570
571         platform_add_devices(devices, ARRAY_SIZE(devices));
572         pxa_set_i2c_info(NULL);
573         pxa_set_mci_info(&magician_mci_info);
574         pxa_set_ohci_info(&magician_ohci_info);
575         pxa_set_ficp_info(&magician_ficp_info);
576
577         /* Check LCD type we have */
578         cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000);
579         if (cpld) {
580                 u8 board_id = __raw_readb(cpld+0x14);
581                 system_rev = board_id & 0x7;
582                 lcd_select = board_id & 0x8;
583                 iounmap(cpld);
584                 pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
585                 if (lcd_select && (system_rev < 3))
586                         pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD);
587                 pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD);
588                 pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD);
589                 pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD);
590                 set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
591         } else
592                 pr_err("LCD detection: CPLD mapping failed\n");
593 }
594
595
596 MACHINE_START(MAGICIAN, "HTC Magician")
597         .phys_io = 0x40000000,
598         .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
599         .boot_params = 0xa0000100,
600         .map_io = pxa_map_io,
601         .init_irq = pxa27x_init_irq,
602         .init_machine = magician_init,
603         .timer = &pxa_timer,
604 MACHINE_END