Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
[pandora-kernel.git] / arch / arm / mach-pxa / palmt5.c
1 /*
2  * Hardware definitions for Palm Tungsten|T5
3  *
4  * Author:      Marek Vasut <marek.vasut@gmail.com>
5  *
6  * Based on work of:
7  *              Ales Snuparek <snuparek@atlas.cz>
8  *              Justin Kendrick <twilightsentry@gmail.com>
9  *              RichardT5 <richard_t5@users.sourceforge.net>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  *
15  * (find more info at www.hackndev.com)
16  *
17  */
18
19 #include <linux/platform_device.h>
20 #include <linux/delay.h>
21 #include <linux/irq.h>
22 #include <linux/gpio_keys.h>
23 #include <linux/input.h>
24 #include <linux/pda_power.h>
25 #include <linux/pwm_backlight.h>
26 #include <linux/gpio.h>
27 #include <linux/wm97xx_batt.h>
28 #include <linux/power_supply.h>
29 #include <linux/usb/gpio_vbus.h>
30
31 #include <asm/mach-types.h>
32 #include <asm/mach/arch.h>
33 #include <asm/mach/map.h>
34
35 #include <mach/pxa27x.h>
36 #include <mach/audio.h>
37 #include <mach/palmt5.h>
38 #include <mach/mmc.h>
39 #include <mach/pxafb.h>
40 #include <mach/irda.h>
41 #include <mach/pxa27x_keypad.h>
42 #include <mach/udc.h>
43 #include <mach/palmasoc.h>
44
45 #include "generic.h"
46 #include "devices.h"
47
48 /******************************************************************************
49  * Pin configuration
50  ******************************************************************************/
51 static unsigned long palmt5_pin_config[] __initdata = {
52         /* MMC */
53         GPIO32_MMC_CLK,
54         GPIO92_MMC_DAT_0,
55         GPIO109_MMC_DAT_1,
56         GPIO110_MMC_DAT_2,
57         GPIO111_MMC_DAT_3,
58         GPIO112_MMC_CMD,
59         GPIO14_GPIO,    /* SD detect */
60         GPIO114_GPIO,   /* SD power */
61         GPIO115_GPIO,   /* SD r/o switch */
62
63         /* AC97 */
64         GPIO28_AC97_BITCLK,
65         GPIO29_AC97_SDATA_IN_0,
66         GPIO30_AC97_SDATA_OUT,
67         GPIO31_AC97_SYNC,
68         GPIO89_AC97_SYSCLK,
69         GPIO95_AC97_nRESET,
70
71         /* IrDA */
72         GPIO40_GPIO,    /* ir disable */
73         GPIO46_FICP_RXD,
74         GPIO47_FICP_TXD,
75
76         /* USB */
77         GPIO15_GPIO,    /* usb detect */
78         GPIO93_GPIO,    /* usb power */
79
80         /* MATRIX KEYPAD */
81         GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
82         GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
83         GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
84         GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
85         GPIO103_KP_MKOUT_0,
86         GPIO104_KP_MKOUT_1,
87         GPIO105_KP_MKOUT_2,
88
89         /* LCD */
90         GPIO58_LCD_LDD_0,
91         GPIO59_LCD_LDD_1,
92         GPIO60_LCD_LDD_2,
93         GPIO61_LCD_LDD_3,
94         GPIO62_LCD_LDD_4,
95         GPIO63_LCD_LDD_5,
96         GPIO64_LCD_LDD_6,
97         GPIO65_LCD_LDD_7,
98         GPIO66_LCD_LDD_8,
99         GPIO67_LCD_LDD_9,
100         GPIO68_LCD_LDD_10,
101         GPIO69_LCD_LDD_11,
102         GPIO70_LCD_LDD_12,
103         GPIO71_LCD_LDD_13,
104         GPIO72_LCD_LDD_14,
105         GPIO73_LCD_LDD_15,
106         GPIO74_LCD_FCLK,
107         GPIO75_LCD_LCLK,
108         GPIO76_LCD_PCLK,
109         GPIO77_LCD_BIAS,
110
111         /* PWM */
112         GPIO16_PWM0_OUT,
113
114         /* MISC */
115         GPIO10_GPIO,    /* hotsync button */
116         GPIO90_GPIO,    /* power detect */
117         GPIO107_GPIO,   /* earphone detect */
118 };
119
120 /******************************************************************************
121  * SD/MMC card controller
122  ******************************************************************************/
123 static int palmt5_mci_init(struct device *dev, irq_handler_t palmt5_detect_int,
124                                 void *data)
125 {
126         int err = 0;
127
128         /* Setup an interrupt for detecting card insert/remove events */
129         err = gpio_request(GPIO_NR_PALMT5_SD_DETECT_N, "SD IRQ");
130         if (err)
131                 goto err;
132         err = gpio_direction_input(GPIO_NR_PALMT5_SD_DETECT_N);
133         if (err)
134                 goto err2;
135         err = request_irq(gpio_to_irq(GPIO_NR_PALMT5_SD_DETECT_N),
136                         palmt5_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
137                         IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
138                         "SD/MMC card detect", data);
139         if (err) {
140                 printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
141                                 __func__);
142                 goto err2;
143         }
144
145         err = gpio_request(GPIO_NR_PALMT5_SD_POWER, "SD_POWER");
146         if (err)
147                 goto err3;
148         err = gpio_direction_output(GPIO_NR_PALMT5_SD_POWER, 0);
149         if (err)
150                 goto err4;
151
152         err = gpio_request(GPIO_NR_PALMT5_SD_READONLY, "SD_READONLY");
153         if (err)
154                 goto err4;
155         err = gpio_direction_input(GPIO_NR_PALMT5_SD_READONLY);
156         if (err)
157                 goto err5;
158
159         printk(KERN_DEBUG "%s: irq registered\n", __func__);
160
161         return 0;
162
163 err5:
164         gpio_free(GPIO_NR_PALMT5_SD_READONLY);
165 err4:
166         gpio_free(GPIO_NR_PALMT5_SD_POWER);
167 err3:
168         free_irq(gpio_to_irq(GPIO_NR_PALMT5_SD_DETECT_N), data);
169 err2:
170         gpio_free(GPIO_NR_PALMT5_SD_DETECT_N);
171 err:
172         return err;
173 }
174
175 static void palmt5_mci_exit(struct device *dev, void *data)
176 {
177         gpio_free(GPIO_NR_PALMT5_SD_READONLY);
178         gpio_free(GPIO_NR_PALMT5_SD_POWER);
179         free_irq(IRQ_GPIO_PALMT5_SD_DETECT_N, data);
180         gpio_free(GPIO_NR_PALMT5_SD_DETECT_N);
181 }
182
183 static void palmt5_mci_power(struct device *dev, unsigned int vdd)
184 {
185         struct pxamci_platform_data *p_d = dev->platform_data;
186         gpio_set_value(GPIO_NR_PALMT5_SD_POWER, p_d->ocr_mask & (1 << vdd));
187 }
188
189 static int palmt5_mci_get_ro(struct device *dev)
190 {
191         return gpio_get_value(GPIO_NR_PALMT5_SD_READONLY);
192 }
193
194 static struct pxamci_platform_data palmt5_mci_platform_data = {
195         .ocr_mask       = MMC_VDD_32_33 | MMC_VDD_33_34,
196         .setpower       = palmt5_mci_power,
197         .get_ro         = palmt5_mci_get_ro,
198         .init           = palmt5_mci_init,
199         .exit           = palmt5_mci_exit,
200 };
201
202 /******************************************************************************
203  * GPIO keyboard
204  ******************************************************************************/
205 static unsigned int palmt5_matrix_keys[] = {
206         KEY(0, 0, KEY_POWER),
207         KEY(0, 1, KEY_F1),
208         KEY(0, 2, KEY_ENTER),
209
210         KEY(1, 0, KEY_F2),
211         KEY(1, 1, KEY_F3),
212         KEY(1, 2, KEY_F4),
213
214         KEY(2, 0, KEY_UP),
215         KEY(2, 2, KEY_DOWN),
216
217         KEY(3, 0, KEY_RIGHT),
218         KEY(3, 2, KEY_LEFT),
219 };
220
221 static struct pxa27x_keypad_platform_data palmt5_keypad_platform_data = {
222         .matrix_key_rows        = 4,
223         .matrix_key_cols        = 3,
224         .matrix_key_map         = palmt5_matrix_keys,
225         .matrix_key_map_size    = ARRAY_SIZE(palmt5_matrix_keys),
226
227         .debounce_interval      = 30,
228 };
229
230 /******************************************************************************
231  * GPIO keys
232  ******************************************************************************/
233 static struct gpio_keys_button palmt5_pxa_buttons[] = {
234         {KEY_F8, GPIO_NR_PALMT5_HOTSYNC_BUTTON_N, 1, "HotSync Button" },
235 };
236
237 static struct gpio_keys_platform_data palmt5_pxa_keys_data = {
238         .buttons        = palmt5_pxa_buttons,
239         .nbuttons       = ARRAY_SIZE(palmt5_pxa_buttons),
240 };
241
242 static struct platform_device palmt5_pxa_keys = {
243         .name   = "gpio-keys",
244         .id     = -1,
245         .dev    = {
246                 .platform_data = &palmt5_pxa_keys_data,
247         },
248 };
249
250 /******************************************************************************
251  * Backlight
252  ******************************************************************************/
253 static int palmt5_backlight_init(struct device *dev)
254 {
255         int ret;
256
257         ret = gpio_request(GPIO_NR_PALMT5_BL_POWER, "BL POWER");
258         if (ret)
259                 goto err;
260         ret = gpio_direction_output(GPIO_NR_PALMT5_BL_POWER, 0);
261         if (ret)
262                 goto err2;
263         ret = gpio_request(GPIO_NR_PALMT5_LCD_POWER, "LCD POWER");
264         if (ret)
265                 goto err2;
266         ret = gpio_direction_output(GPIO_NR_PALMT5_LCD_POWER, 0);
267         if (ret)
268                 goto err3;
269
270         return 0;
271 err3:
272         gpio_free(GPIO_NR_PALMT5_LCD_POWER);
273 err2:
274         gpio_free(GPIO_NR_PALMT5_BL_POWER);
275 err:
276         return ret;
277 }
278
279 static int palmt5_backlight_notify(int brightness)
280 {
281         gpio_set_value(GPIO_NR_PALMT5_BL_POWER, brightness);
282         gpio_set_value(GPIO_NR_PALMT5_LCD_POWER, brightness);
283         return brightness;
284 }
285
286 static void palmt5_backlight_exit(struct device *dev)
287 {
288         gpio_free(GPIO_NR_PALMT5_BL_POWER);
289         gpio_free(GPIO_NR_PALMT5_LCD_POWER);
290 }
291
292 static struct platform_pwm_backlight_data palmt5_backlight_data = {
293         .pwm_id         = 0,
294         .max_brightness = PALMT5_MAX_INTENSITY,
295         .dft_brightness = PALMT5_MAX_INTENSITY,
296         .pwm_period_ns  = PALMT5_PERIOD_NS,
297         .init           = palmt5_backlight_init,
298         .notify         = palmt5_backlight_notify,
299         .exit           = palmt5_backlight_exit,
300 };
301
302 static struct platform_device palmt5_backlight = {
303         .name   = "pwm-backlight",
304         .dev    = {
305                 .parent         = &pxa27x_device_pwm0.dev,
306                 .platform_data  = &palmt5_backlight_data,
307         },
308 };
309
310 /******************************************************************************
311  * IrDA
312  ******************************************************************************/
313 static int palmt5_irda_startup(struct device *dev)
314 {
315         int err;
316         err = gpio_request(GPIO_NR_PALMT5_IR_DISABLE, "IR DISABLE");
317         if (err)
318                 goto err;
319         err = gpio_direction_output(GPIO_NR_PALMT5_IR_DISABLE, 1);
320         if (err)
321                 gpio_free(GPIO_NR_PALMT5_IR_DISABLE);
322 err:
323         return err;
324 }
325
326 static void palmt5_irda_shutdown(struct device *dev)
327 {
328         gpio_free(GPIO_NR_PALMT5_IR_DISABLE);
329 }
330
331 static void palmt5_irda_transceiver_mode(struct device *dev, int mode)
332 {
333         gpio_set_value(GPIO_NR_PALMT5_IR_DISABLE, mode & IR_OFF);
334         pxa2xx_transceiver_mode(dev, mode);
335 }
336
337 static struct pxaficp_platform_data palmt5_ficp_platform_data = {
338         .startup                = palmt5_irda_startup,
339         .shutdown               = palmt5_irda_shutdown,
340         .transceiver_cap        = IR_SIRMODE | IR_FIRMODE | IR_OFF,
341         .transceiver_mode       = palmt5_irda_transceiver_mode,
342 };
343
344 /******************************************************************************
345  * UDC
346  ******************************************************************************/
347 static struct gpio_vbus_mach_info palmt5_udc_info = {
348         .gpio_vbus              = GPIO_NR_PALMT5_USB_DETECT_N,
349         .gpio_vbus_inverted     = 1,
350         .gpio_pullup            = GPIO_NR_PALMT5_USB_PULLUP,
351 };
352
353 static struct platform_device palmt5_gpio_vbus = {
354         .name   = "gpio-vbus",
355         .id     = -1,
356         .dev    = {
357                 .platform_data  = &palmt5_udc_info,
358         },
359 };
360
361 /******************************************************************************
362  * Power supply
363  ******************************************************************************/
364 static int power_supply_init(struct device *dev)
365 {
366         int ret;
367
368         ret = gpio_request(GPIO_NR_PALMT5_POWER_DETECT, "CABLE_STATE_AC");
369         if (ret)
370                 goto err1;
371         ret = gpio_direction_input(GPIO_NR_PALMT5_POWER_DETECT);
372         if (ret)
373                 goto err2;
374
375         return 0;
376 err2:
377         gpio_free(GPIO_NR_PALMT5_POWER_DETECT);
378 err1:
379         return ret;
380 }
381
382 static int palmt5_is_ac_online(void)
383 {
384         return gpio_get_value(GPIO_NR_PALMT5_POWER_DETECT);
385 }
386
387 static void power_supply_exit(struct device *dev)
388 {
389         gpio_free(GPIO_NR_PALMT5_POWER_DETECT);
390 }
391
392 static char *palmt5_supplicants[] = {
393         "main-battery",
394 };
395
396 static struct pda_power_pdata power_supply_info = {
397         .init            = power_supply_init,
398         .is_ac_online    = palmt5_is_ac_online,
399         .exit            = power_supply_exit,
400         .supplied_to     = palmt5_supplicants,
401         .num_supplicants = ARRAY_SIZE(palmt5_supplicants),
402 };
403
404 static struct platform_device power_supply = {
405         .name = "pda-power",
406         .id   = -1,
407         .dev  = {
408                 .platform_data = &power_supply_info,
409         },
410 };
411
412 /******************************************************************************
413  * WM97xx battery
414  ******************************************************************************/
415 static struct wm97xx_batt_info wm97xx_batt_pdata = {
416         .batt_aux       = WM97XX_AUX_ID3,
417         .temp_aux       = WM97XX_AUX_ID2,
418         .charge_gpio    = -1,
419         .max_voltage    = PALMT5_BAT_MAX_VOLTAGE,
420         .min_voltage    = PALMT5_BAT_MIN_VOLTAGE,
421         .batt_mult      = 1000,
422         .batt_div       = 414,
423         .temp_mult      = 1,
424         .temp_div       = 1,
425         .batt_tech      = POWER_SUPPLY_TECHNOLOGY_LIPO,
426         .batt_name      = "main-batt",
427 };
428
429 /******************************************************************************
430  * aSoC audio
431  ******************************************************************************/
432 static struct palm27x_asoc_info palmt5_asoc_pdata = {
433         .jack_gpio      = GPIO_NR_PALMT5_EARPHONE_DETECT,
434 };
435
436 static pxa2xx_audio_ops_t palmt5_ac97_pdata = {
437         .reset_gpio     = 95,
438 };
439
440 static struct platform_device palmt5_asoc = {
441         .name = "palm27x-asoc",
442         .id   = -1,
443         .dev  = {
444                 .platform_data = &palmt5_asoc_pdata,
445         },
446 };
447
448 /******************************************************************************
449  * Framebuffer
450  ******************************************************************************/
451 static struct pxafb_mode_info palmt5_lcd_modes[] = {
452 {
453         .pixclock       = 57692,
454         .xres           = 320,
455         .yres           = 480,
456         .bpp            = 16,
457
458         .left_margin    = 32,
459         .right_margin   = 1,
460         .upper_margin   = 7,
461         .lower_margin   = 1,
462
463         .hsync_len      = 4,
464         .vsync_len      = 1,
465 },
466 };
467
468 static struct pxafb_mach_info palmt5_lcd_screen = {
469         .modes          = palmt5_lcd_modes,
470         .num_modes      = ARRAY_SIZE(palmt5_lcd_modes),
471         .lcd_conn       = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
472 };
473
474 /******************************************************************************
475  * Power management - standby
476  ******************************************************************************/
477 static void __init palmt5_pm_init(void)
478 {
479         static u32 resume[] = {
480                 0xe3a00101,     /* mov  r0,     #0x40000000 */
481                 0xe380060f,     /* orr  r0, r0, #0x00f00000 */
482                 0xe590f008,     /* ldr  pc, [r0, #0x08] */
483         };
484
485         /* copy the bootloader */
486         memcpy(phys_to_virt(PALMT5_STR_BASE), resume, sizeof(resume));
487 }
488
489 /******************************************************************************
490  * Machine init
491  ******************************************************************************/
492 static struct platform_device *devices[] __initdata = {
493 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
494         &palmt5_pxa_keys,
495 #endif
496         &palmt5_backlight,
497         &power_supply,
498         &palmt5_asoc,
499         &palmt5_gpio_vbus,
500 };
501
502 /* setup udc GPIOs initial state */
503 static void __init palmt5_udc_init(void)
504 {
505         if (!gpio_request(GPIO_NR_PALMT5_USB_PULLUP, "UDC Vbus")) {
506                 gpio_direction_output(GPIO_NR_PALMT5_USB_PULLUP, 1);
507                 gpio_free(GPIO_NR_PALMT5_USB_PULLUP);
508         }
509 }
510
511 static void __init palmt5_init(void)
512 {
513         pxa2xx_mfp_config(ARRAY_AND_SIZE(palmt5_pin_config));
514
515         palmt5_pm_init();
516         set_pxa_fb_info(&palmt5_lcd_screen);
517         pxa_set_mci_info(&palmt5_mci_platform_data);
518         palmt5_udc_init();
519         pxa_set_ac97_info(&palmt5_ac97_pdata);
520         pxa_set_ficp_info(&palmt5_ficp_platform_data);
521         pxa_set_keypad_info(&palmt5_keypad_platform_data);
522         wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
523
524         platform_add_devices(devices, ARRAY_SIZE(devices));
525 }
526
527 MACHINE_START(PALMT5, "Palm Tungsten|T5")
528         .phys_io        = PALMT5_PHYS_IO_START,
529         .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
530         .boot_params    = 0xa0000100,
531         .map_io         = pxa_map_io,
532         .init_irq       = pxa27x_init_irq,
533         .timer          = &pxa_timer,
534         .init_machine   = palmt5_init
535 MACHINE_END