blob: d8fa53c19178147ff229adf79a1324c19460887e [file] [log] [blame]
Sergey Lapinc49e1e62008-08-29 15:47:52 +01001/*
2 * Hardware definitions for Palm Zire72
3 *
4 * Authors:
5 * Vladimir "Farcaller" Pouzanov <farcaller@gmail.com>
6 * Sergey Lapin <slapin@ossfans.org>
7 * Alex Osborne <bobofdoom@gmail.com>
8 * Jan Herman <2hp@seznam.cz>
9 *
10 * Rewrite for mainline:
11 * Marek Vasut <marek.vasut@gmail.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 *
17 * (find more info at www.hackndev.com)
18 *
19 */
20
21#include <linux/platform_device.h>
22#include <linux/sysdev.h>
23#include <linux/delay.h>
24#include <linux/irq.h>
25#include <linux/gpio_keys.h>
26#include <linux/input.h>
27#include <linux/pda_power.h>
28#include <linux/pwm_backlight.h>
29#include <linux/gpio.h>
Marek Vasuteb73e622009-06-01 22:34:14 +020030#include <linux/wm97xx_batt.h>
Sergey Lapinc49e1e62008-08-29 15:47:52 +010031#include <linux/power_supply.h>
Marek Vasuteb73e622009-06-01 22:34:14 +020032#include <linux/usb/gpio_vbus.h>
Sergey Lapinc49e1e62008-08-29 15:47:52 +010033
34#include <asm/mach-types.h>
35#include <asm/mach/arch.h>
36#include <asm/mach/map.h>
37
Eric Miao51c62982009-01-02 23:17:22 +080038#include <mach/pxa27x.h>
Sergey Lapinc49e1e62008-08-29 15:47:52 +010039#include <mach/audio.h>
40#include <mach/palmz72.h>
41#include <mach/mmc.h>
42#include <mach/pxafb.h>
Sergey Lapinc49e1e62008-08-29 15:47:52 +010043#include <mach/irda.h>
44#include <mach/pxa27x_keypad.h>
45#include <mach/udc.h>
Marek Vasuteb73e622009-06-01 22:34:14 +020046#include <mach/palmasoc.h>
47
Sergey Lapinc49e1e62008-08-29 15:47:52 +010048#include <mach/pm.h>
49
50#include "generic.h"
51#include "devices.h"
52
53/******************************************************************************
54 * Pin configuration
55 ******************************************************************************/
56static unsigned long palmz72_pin_config[] __initdata = {
57 /* MMC */
58 GPIO32_MMC_CLK,
59 GPIO92_MMC_DAT_0,
60 GPIO109_MMC_DAT_1,
61 GPIO110_MMC_DAT_2,
62 GPIO111_MMC_DAT_3,
63 GPIO112_MMC_CMD,
64 GPIO14_GPIO, /* SD detect */
65 GPIO115_GPIO, /* SD RO */
66 GPIO98_GPIO, /* SD power */
67
68 /* AC97 */
69 GPIO28_AC97_BITCLK,
70 GPIO29_AC97_SDATA_IN_0,
71 GPIO30_AC97_SDATA_OUT,
72 GPIO31_AC97_SYNC,
Marek Vasuteb73e622009-06-01 22:34:14 +020073 GPIO89_AC97_SYSCLK,
74 GPIO113_AC97_nRESET,
Sergey Lapinc49e1e62008-08-29 15:47:52 +010075
76 /* IrDA */
77 GPIO49_GPIO, /* ir disable */
78 GPIO46_FICP_RXD,
79 GPIO47_FICP_TXD,
80
81 /* PWM */
82 GPIO16_PWM0_OUT,
83
84 /* USB */
85 GPIO15_GPIO, /* usb detect */
Marek Vasuteb73e622009-06-01 22:34:14 +020086 GPIO95_GPIO, /* usb pullup */
Sergey Lapinc49e1e62008-08-29 15:47:52 +010087
88 /* Matrix keypad */
89 GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
90 GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
91 GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
92 GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
93 GPIO103_KP_MKOUT_0,
94 GPIO104_KP_MKOUT_1,
95 GPIO105_KP_MKOUT_2,
96
97 /* LCD */
98 GPIO58_LCD_LDD_0,
99 GPIO59_LCD_LDD_1,
100 GPIO60_LCD_LDD_2,
101 GPIO61_LCD_LDD_3,
102 GPIO62_LCD_LDD_4,
103 GPIO63_LCD_LDD_5,
104 GPIO64_LCD_LDD_6,
105 GPIO65_LCD_LDD_7,
106 GPIO66_LCD_LDD_8,
107 GPIO67_LCD_LDD_9,
108 GPIO68_LCD_LDD_10,
109 GPIO69_LCD_LDD_11,
110 GPIO70_LCD_LDD_12,
111 GPIO71_LCD_LDD_13,
112 GPIO72_LCD_LDD_14,
113 GPIO73_LCD_LDD_15,
114 GPIO74_LCD_FCLK,
115 GPIO75_LCD_LCLK,
116 GPIO76_LCD_PCLK,
117 GPIO77_LCD_BIAS,
118 GPIO20_GPIO, /* bl power */
119 GPIO21_GPIO, /* LCD border switch */
120 GPIO22_GPIO, /* LCD border color */
121 GPIO96_GPIO, /* lcd power */
122
123 /* Misc. */
124 GPIO0_GPIO | WAKEUP_ON_LEVEL_HIGH, /* power detect */
125 GPIO88_GPIO, /* green led */
126 GPIO27_GPIO, /* WM9712 IRQ */
127};
128
129/******************************************************************************
130 * SD/MMC card controller
131 ******************************************************************************/
Robert Jarzmik7a648252009-07-06 22:16:42 +0200132/* SD_POWER is not actually power, but it is more like chip
133 * select, i.e. it is inverted */
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100134static struct pxamci_platform_data palmz72_mci_platform_data = {
Robert Jarzmik7a648252009-07-06 22:16:42 +0200135 .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
136 .gpio_card_detect = GPIO_NR_PALMZ72_SD_DETECT_N,
137 .gpio_card_ro = GPIO_NR_PALMZ72_SD_RO,
138 .gpio_power = GPIO_NR_PALMZ72_SD_POWER_N,
139 .gpio_power_invert = 1,
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100140};
141
142/******************************************************************************
143 * GPIO keyboard
144 ******************************************************************************/
145static unsigned int palmz72_matrix_keys[] = {
146 KEY(0, 0, KEY_POWER),
147 KEY(0, 1, KEY_F1),
148 KEY(0, 2, KEY_ENTER),
149
150 KEY(1, 0, KEY_F2),
151 KEY(1, 1, KEY_F3),
152 KEY(1, 2, KEY_F4),
153
154 KEY(2, 0, KEY_UP),
155 KEY(2, 2, KEY_DOWN),
156
157 KEY(3, 0, KEY_RIGHT),
158 KEY(3, 2, KEY_LEFT),
159};
160
161static struct pxa27x_keypad_platform_data palmz72_keypad_platform_data = {
162 .matrix_key_rows = 4,
163 .matrix_key_cols = 3,
164 .matrix_key_map = palmz72_matrix_keys,
165 .matrix_key_map_size = ARRAY_SIZE(palmz72_matrix_keys),
166
167 .debounce_interval = 30,
168};
169
170/******************************************************************************
171 * Backlight
172 ******************************************************************************/
173static int palmz72_backlight_init(struct device *dev)
174{
175 int ret;
176
177 ret = gpio_request(GPIO_NR_PALMZ72_BL_POWER, "BL POWER");
178 if (ret)
179 goto err;
180 ret = gpio_direction_output(GPIO_NR_PALMZ72_BL_POWER, 0);
181 if (ret)
182 goto err2;
183 ret = gpio_request(GPIO_NR_PALMZ72_LCD_POWER, "LCD POWER");
184 if (ret)
185 goto err2;
186 ret = gpio_direction_output(GPIO_NR_PALMZ72_LCD_POWER, 0);
187 if (ret)
188 goto err3;
189
190 return 0;
191err3:
192 gpio_free(GPIO_NR_PALMZ72_LCD_POWER);
193err2:
194 gpio_free(GPIO_NR_PALMZ72_BL_POWER);
195err:
196 return ret;
197}
198
199static int palmz72_backlight_notify(int brightness)
200{
201 gpio_set_value(GPIO_NR_PALMZ72_BL_POWER, brightness);
202 gpio_set_value(GPIO_NR_PALMZ72_LCD_POWER, brightness);
203 return brightness;
204}
205
206static void palmz72_backlight_exit(struct device *dev)
207{
208 gpio_free(GPIO_NR_PALMZ72_BL_POWER);
209 gpio_free(GPIO_NR_PALMZ72_LCD_POWER);
210}
211
212static struct platform_pwm_backlight_data palmz72_backlight_data = {
213 .pwm_id = 0,
214 .max_brightness = PALMZ72_MAX_INTENSITY,
215 .dft_brightness = PALMZ72_MAX_INTENSITY,
216 .pwm_period_ns = PALMZ72_PERIOD_NS,
217 .init = palmz72_backlight_init,
218 .notify = palmz72_backlight_notify,
219 .exit = palmz72_backlight_exit,
220};
221
222static struct platform_device palmz72_backlight = {
223 .name = "pwm-backlight",
224 .dev = {
225 .parent = &pxa27x_device_pwm0.dev,
226 .platform_data = &palmz72_backlight_data,
227 },
228};
229
230/******************************************************************************
231 * IrDA
232 ******************************************************************************/
233static int palmz72_irda_startup(struct device *dev)
234{
235 int err;
236 err = gpio_request(GPIO_NR_PALMZ72_IR_DISABLE, "IR DISABLE");
237 if (err)
238 goto err;
239 err = gpio_direction_output(GPIO_NR_PALMZ72_IR_DISABLE, 1);
240 if (err)
241 gpio_free(GPIO_NR_PALMZ72_IR_DISABLE);
242err:
243 return err;
244}
245
246static void palmz72_irda_shutdown(struct device *dev)
247{
248 gpio_free(GPIO_NR_PALMZ72_IR_DISABLE);
249}
250
251static void palmz72_irda_transceiver_mode(struct device *dev, int mode)
252{
253 gpio_set_value(GPIO_NR_PALMZ72_IR_DISABLE, mode & IR_OFF);
254 pxa2xx_transceiver_mode(dev, mode);
255}
256
257static struct pxaficp_platform_data palmz72_ficp_platform_data = {
258 .startup = palmz72_irda_startup,
259 .shutdown = palmz72_irda_shutdown,
260 .transceiver_cap = IR_SIRMODE | IR_OFF,
261 .transceiver_mode = palmz72_irda_transceiver_mode,
262};
263
264/******************************************************************************
265 * LEDs
266 ******************************************************************************/
267static struct gpio_led gpio_leds[] = {
268 {
269 .name = "palmz72:green:led",
270 .default_trigger = "none",
271 .gpio = GPIO_NR_PALMZ72_LED_GREEN,
272 },
273};
274
275static struct gpio_led_platform_data gpio_led_info = {
276 .leds = gpio_leds,
277 .num_leds = ARRAY_SIZE(gpio_leds),
278};
279
280static struct platform_device palmz72_leds = {
281 .name = "leds-gpio",
282 .id = -1,
283 .dev = {
284 .platform_data = &gpio_led_info,
285 }
286};
287
288/******************************************************************************
Marek Vasuteb73e622009-06-01 22:34:14 +0200289 * UDC
290 ******************************************************************************/
291static struct gpio_vbus_mach_info palmz72_udc_info = {
292 .gpio_vbus = GPIO_NR_PALMZ72_USB_DETECT_N,
293 .gpio_pullup = GPIO_NR_PALMZ72_USB_PULLUP,
294};
295
296static struct platform_device palmz72_gpio_vbus = {
297 .name = "gpio-vbus",
298 .id = -1,
299 .dev = {
300 .platform_data = &palmz72_udc_info,
301 },
302};
303
304/******************************************************************************
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100305 * Power supply
306 ******************************************************************************/
307static int power_supply_init(struct device *dev)
308{
309 int ret;
310
311 ret = gpio_request(GPIO_NR_PALMZ72_POWER_DETECT, "CABLE_STATE_AC");
312 if (ret)
313 goto err1;
314 ret = gpio_direction_input(GPIO_NR_PALMZ72_POWER_DETECT);
315 if (ret)
316 goto err2;
317
318 ret = gpio_request(GPIO_NR_PALMZ72_USB_DETECT_N, "CABLE_STATE_USB");
319 if (ret)
320 goto err2;
321 ret = gpio_direction_input(GPIO_NR_PALMZ72_USB_DETECT_N);
322 if (ret)
323 goto err3;
324
325 return 0;
326err3:
327 gpio_free(GPIO_NR_PALMZ72_USB_DETECT_N);
328err2:
329 gpio_free(GPIO_NR_PALMZ72_POWER_DETECT);
330err1:
331 return ret;
332}
333
334static int palmz72_is_ac_online(void)
335{
336 return gpio_get_value(GPIO_NR_PALMZ72_POWER_DETECT);
337}
338
339static int palmz72_is_usb_online(void)
340{
341 return !gpio_get_value(GPIO_NR_PALMZ72_USB_DETECT_N);
342}
343
344static void power_supply_exit(struct device *dev)
345{
346 gpio_free(GPIO_NR_PALMZ72_USB_DETECT_N);
347 gpio_free(GPIO_NR_PALMZ72_POWER_DETECT);
348}
349
350static char *palmz72_supplicants[] = {
351 "main-battery",
352};
353
354static struct pda_power_pdata power_supply_info = {
355 .init = power_supply_init,
356 .is_ac_online = palmz72_is_ac_online,
357 .is_usb_online = palmz72_is_usb_online,
358 .exit = power_supply_exit,
359 .supplied_to = palmz72_supplicants,
360 .num_supplicants = ARRAY_SIZE(palmz72_supplicants),
361};
362
363static struct platform_device power_supply = {
364 .name = "pda-power",
365 .id = -1,
366 .dev = {
367 .platform_data = &power_supply_info,
368 },
369};
370
371/******************************************************************************
Marek Vasuteb73e622009-06-01 22:34:14 +0200372 * WM97xx battery
373 ******************************************************************************/
374static struct wm97xx_batt_info wm97xx_batt_pdata = {
375 .batt_aux = WM97XX_AUX_ID3,
376 .temp_aux = WM97XX_AUX_ID2,
377 .charge_gpio = -1,
378 .max_voltage = PALMZ72_BAT_MAX_VOLTAGE,
379 .min_voltage = PALMZ72_BAT_MIN_VOLTAGE,
380 .batt_mult = 1000,
381 .batt_div = 414,
382 .temp_mult = 1,
383 .temp_div = 1,
384 .batt_tech = POWER_SUPPLY_TECHNOLOGY_LIPO,
385 .batt_name = "main-batt",
386};
387
388/******************************************************************************
389 * aSoC audio
390 ******************************************************************************/
391static struct platform_device palmz72_asoc = {
392 .name = "palm27x-asoc",
393 .id = -1,
394};
395
396/******************************************************************************
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100397 * Framebuffer
398 ******************************************************************************/
399static struct pxafb_mode_info palmz72_lcd_modes[] = {
400{
401 .pixclock = 115384,
402 .xres = 320,
403 .yres = 320,
404 .bpp = 16,
405
406 .left_margin = 27,
407 .right_margin = 7,
408 .upper_margin = 7,
409 .lower_margin = 8,
410
411 .hsync_len = 6,
412 .vsync_len = 1,
413},
414};
415
416static struct pxafb_mach_info palmz72_lcd_screen = {
417 .modes = palmz72_lcd_modes,
418 .num_modes = ARRAY_SIZE(palmz72_lcd_modes),
419 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
420};
421
Sergey Lapinfda50a12008-08-29 15:53:24 +0100422#ifdef CONFIG_PM
423
424/* We have some black magic here
425 * PalmOS ROM on recover expects special struct physical address
426 * to be transferred via PSPR. Using this struct PalmOS restores
427 * its state after sleep. As for Linux, we need to setup it the
428 * same way. More than that, PalmOS ROM changes some values in memory.
429 * For now only one location is found, which needs special treatment.
430 * Thanks to Alex Osborne, Andrzej Zaborowski, and lots of other people
431 * for reading backtraces for me :)
432 */
433
434#define PALMZ72_SAVE_DWORD ((unsigned long *)0xc0000050)
435
436static struct palmz72_resume_info palmz72_resume_info = {
437 .magic0 = 0xb4e6,
438 .magic1 = 1,
439
440 /* reset state, MMU off etc */
441 .arm_control = 0,
442 .aux_control = 0,
443 .ttb = 0,
444 .domain_access = 0,
445 .process_id = 0,
446};
447
448static unsigned long store_ptr;
449
450/* sys_device for Palm Zire 72 PM */
451
452static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
453{
454 /* setup the resume_info struct for the original bootloader */
455 palmz72_resume_info.resume_addr = (u32) pxa_cpu_resume;
456
457 /* Storing memory touched by ROM */
458 store_ptr = *PALMZ72_SAVE_DWORD;
459
460 /* Setting PSPR to a proper value */
461 PSPR = virt_to_phys(&palmz72_resume_info);
462
463 return 0;
464}
465
466static int palmz72_pm_resume(struct sys_device *dev)
467{
468 *PALMZ72_SAVE_DWORD = store_ptr;
469 return 0;
470}
471
472static struct sysdev_class palmz72_pm_sysclass = {
473 .name = "palmz72_pm",
474 .suspend = palmz72_pm_suspend,
475 .resume = palmz72_pm_resume,
476};
477
478static struct sys_device palmz72_pm_device = {
479 .cls = &palmz72_pm_sysclass,
480};
481
482static int __init palmz72_pm_init(void)
483{
484 int ret = -ENODEV;
485 if (machine_is_palmz72()) {
486 ret = sysdev_class_register(&palmz72_pm_sysclass);
487 if (ret == 0)
488 ret = sysdev_register(&palmz72_pm_device);
489 }
490 return ret;
491}
492
493device_initcall(palmz72_pm_init);
494#endif
495
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100496/******************************************************************************
497 * Machine init
498 ******************************************************************************/
499static struct platform_device *devices[] __initdata = {
500 &palmz72_backlight,
501 &palmz72_leds,
Marek Vasuteb73e622009-06-01 22:34:14 +0200502 &palmz72_asoc,
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100503 &power_supply,
Marek Vasuteb73e622009-06-01 22:34:14 +0200504 &palmz72_gpio_vbus,
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100505};
506
Marek Vasuteb73e622009-06-01 22:34:14 +0200507/* setup udc GPIOs initial state */
508static void __init palmz72_udc_init(void)
509{
510 if (!gpio_request(GPIO_NR_PALMZ72_USB_PULLUP, "USB Pullup")) {
511 gpio_direction_output(GPIO_NR_PALMZ72_USB_PULLUP, 0);
512 gpio_free(GPIO_NR_PALMZ72_USB_PULLUP);
513 }
514}
515
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100516static void __init palmz72_init(void)
517{
518 pxa2xx_mfp_config(ARRAY_AND_SIZE(palmz72_pin_config));
Marek Vasuteb73e622009-06-01 22:34:14 +0200519
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100520 set_pxa_fb_info(&palmz72_lcd_screen);
521 pxa_set_mci_info(&palmz72_mci_platform_data);
Marek Vasuteb73e622009-06-01 22:34:14 +0200522 palmz72_udc_init();
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100523 pxa_set_ac97_info(NULL);
524 pxa_set_ficp_info(&palmz72_ficp_platform_data);
525 pxa_set_keypad_info(&palmz72_keypad_platform_data);
Marek Vasuteb73e622009-06-01 22:34:14 +0200526 wm97xx_bat_set_pdata(&wm97xx_batt_pdata);
527
Sergey Lapinc49e1e62008-08-29 15:47:52 +0100528 platform_add_devices(devices, ARRAY_SIZE(devices));
529}
530
531MACHINE_START(PALMZ72, "Palm Zire72")
532 .phys_io = 0x40000000,
533 .io_pg_offst = io_p2v(0x40000000),
534 .boot_params = 0xa0000100,
535 .map_io = pxa_map_io,
536 .init_irq = pxa27x_init_irq,
537 .timer = &pxa_timer,
538 .init_machine = palmz72_init
539MACHINE_END