Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6
[linux-2.6] / arch / arm / mach-omap1 / board-palmte.c
1 /*
2  * linux/arch/arm/mach-omap1/board-palmte.c
3  *
4  * Modified from board-generic.c
5  *
6  * Support for the Palm Tungsten E PDA.
7  *
8  * Original version : Laurent Gonzalez
9  *
10  * Maintainers : http://palmtelinux.sf.net
11  *                palmtelinux-developpers@lists.sf.net
12  *
13  * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License version 2 as
17  * published by the Free Software Foundation.
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/input.h>
23 #include <linux/platform_device.h>
24 #include <linux/mtd/mtd.h>
25 #include <linux/mtd/partitions.h>
26 #include <linux/spi/spi.h>
27 #include <linux/interrupt.h>
28 #include <linux/apm-emulation.h>
29
30 #include <mach/hardware.h>
31 #include <asm/mach-types.h>
32 #include <asm/mach/arch.h>
33 #include <asm/mach/map.h>
34 #include <asm/mach/flash.h>
35
36 #include <mach/gpio.h>
37 #include <mach/mux.h>
38 #include <mach/usb.h>
39 #include <mach/tc.h>
40 #include <mach/dma.h>
41 #include <mach/board.h>
42 #include <mach/irda.h>
43 #include <mach/keypad.h>
44 #include <mach/common.h>
45
46 #define PALMTE_USBDETECT_GPIO   0
47 #define PALMTE_USB_OR_DC_GPIO   1
48 #define PALMTE_TSC_GPIO         4
49 #define PALMTE_PINTDAV_GPIO     6
50 #define PALMTE_MMC_WP_GPIO      8
51 #define PALMTE_MMC_POWER_GPIO   9
52 #define PALMTE_HDQ_GPIO         11
53 #define PALMTE_HEADPHONES_GPIO  14
54 #define PALMTE_SPEAKER_GPIO     15
55 #define PALMTE_DC_GPIO          OMAP_MPUIO(2)
56 #define PALMTE_MMC_SWITCH_GPIO  OMAP_MPUIO(4)
57 #define PALMTE_MMC1_GPIO        OMAP_MPUIO(6)
58 #define PALMTE_MMC2_GPIO        OMAP_MPUIO(7)
59 #define PALMTE_MMC3_GPIO        OMAP_MPUIO(11)
60
61 static void __init omap_palmte_init_irq(void)
62 {
63         omap1_init_common_hw();
64         omap_init_irq();
65         omap_gpio_init();
66 }
67
68 static const int palmte_keymap[] = {
69         KEY(0, 0, KEY_F1),              /* Calendar */
70         KEY(0, 1, KEY_F2),              /* Contacts */
71         KEY(0, 2, KEY_F3),              /* Tasks List */
72         KEY(0, 3, KEY_F4),              /* Note Pad */
73         KEY(0, 4, KEY_POWER),
74         KEY(1, 0, KEY_LEFT),
75         KEY(1, 1, KEY_DOWN),
76         KEY(1, 2, KEY_UP),
77         KEY(1, 3, KEY_RIGHT),
78         KEY(1, 4, KEY_ENTER),
79         0,
80 };
81
82 static struct omap_kp_platform_data palmte_kp_data = {
83         .rows   = 8,
84         .cols   = 8,
85         .keymap = (int *) palmte_keymap,
86         .rep    = 1,
87         .delay  = 12,
88 };
89
90 static struct resource palmte_kp_resources[] = {
91         [0]     = {
92                 .start  = INT_KEYBOARD,
93                 .end    = INT_KEYBOARD,
94                 .flags  = IORESOURCE_IRQ,
95         },
96 };
97
98 static struct platform_device palmte_kp_device = {
99         .name           = "omap-keypad",
100         .id             = -1,
101         .dev            = {
102                 .platform_data  = &palmte_kp_data,
103         },
104         .num_resources  = ARRAY_SIZE(palmte_kp_resources),
105         .resource       = palmte_kp_resources,
106 };
107
108 static struct mtd_partition palmte_rom_partitions[] = {
109         /* PalmOS "Small ROM", contains the bootloader and the debugger */
110         {
111                 .name           = "smallrom",
112                 .offset         = 0,
113                 .size           = 0xa000,
114                 .mask_flags     = MTD_WRITEABLE,
115         },
116         /* PalmOS "Big ROM", a filesystem with all the OS code and data */
117         {
118                 .name           = "bigrom",
119                 .offset         = SZ_128K,
120                 /*
121                  * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
122                  * 0x7b0000 bytes in the English-only ("enUS") version.
123                  */
124                 .size           = 0x7b0000,
125                 .mask_flags     = MTD_WRITEABLE,
126         },
127 };
128
129 static struct flash_platform_data palmte_rom_data = {
130         .map_name       = "map_rom",
131         .width          = 2,
132         .parts          = palmte_rom_partitions,
133         .nr_parts       = ARRAY_SIZE(palmte_rom_partitions),
134 };
135
136 static struct resource palmte_rom_resource = {
137         .start          = OMAP_CS0_PHYS,
138         .end            = OMAP_CS0_PHYS + SZ_8M - 1,
139         .flags          = IORESOURCE_MEM,
140 };
141
142 static struct platform_device palmte_rom_device = {
143         .name           = "omapflash",
144         .id             = -1,
145         .dev            = {
146                 .platform_data  = &palmte_rom_data,
147         },
148         .num_resources  = 1,
149         .resource       = &palmte_rom_resource,
150 };
151
152 static struct platform_device palmte_lcd_device = {
153         .name           = "lcd_palmte",
154         .id             = -1,
155 };
156
157 static struct omap_backlight_config palmte_backlight_config = {
158         .default_intensity      = 0xa0,
159 };
160
161 static struct platform_device palmte_backlight_device = {
162         .name           = "omap-bl",
163         .id             = -1,
164         .dev            = {
165                 .platform_data  = &palmte_backlight_config,
166         },
167 };
168
169 static struct omap_irda_config palmte_irda_config = {
170         .transceiver_cap        = IR_SIRMODE,
171         .rx_channel             = OMAP_DMA_UART3_RX,
172         .tx_channel             = OMAP_DMA_UART3_TX,
173         .dest_start             = UART3_THR,
174         .src_start              = UART3_RHR,
175         .tx_trigger             = 0,
176         .rx_trigger             = 0,
177 };
178
179 static struct resource palmte_irda_resources[] = {
180         [0]     = {
181                 .start  = INT_UART3,
182                 .end    = INT_UART3,
183                 .flags  = IORESOURCE_IRQ,
184         },
185 };
186
187 static struct platform_device palmte_irda_device = {
188         .name           = "omapirda",
189         .id             = -1,
190         .dev            = {
191                 .platform_data  = &palmte_irda_config,
192         },
193         .num_resources  = ARRAY_SIZE(palmte_irda_resources),
194         .resource       = palmte_irda_resources,
195 };
196
197 static struct platform_device *palmte_devices[] __initdata = {
198         &palmte_rom_device,
199         &palmte_kp_device,
200         &palmte_lcd_device,
201         &palmte_backlight_device,
202         &palmte_irda_device,
203 };
204
205 static struct omap_usb_config palmte_usb_config __initdata = {
206         .register_dev   = 1,    /* Mini-B only receptacle */
207         .hmc_mode       = 0,
208         .pins[0]        = 2,
209 };
210
211 static struct omap_lcd_config palmte_lcd_config __initdata = {
212         .ctrl_name      = "internal",
213 };
214
215 static struct omap_uart_config palmte_uart_config __initdata = {
216         .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
217 };
218
219 #ifdef CONFIG_APM
220 /*
221  * Values measured in 10 minute intervals averaged over 10 samples.
222  * May differ slightly from device to device but should be accurate
223  * enough to give basic idea of battery life left and trigger
224  * potential alerts.
225  */
226 static const int palmte_battery_sample[] = {
227         2194, 2157, 2138, 2120,
228         2104, 2089, 2075, 2061,
229         2048, 2038, 2026, 2016,
230         2008, 1998, 1989, 1980,
231         1970, 1958, 1945, 1928,
232         1910, 1888, 1860, 1827,
233         1791, 1751, 1709, 1656,
234 };
235
236 #define INTERVAL                10
237 #define BATTERY_HIGH_TRESHOLD   66
238 #define BATTERY_LOW_TRESHOLD    33
239
240 static void palmte_get_power_status(struct apm_power_info *info, int *battery)
241 {
242         int charging, batt, hi, lo, mid;
243
244         charging = !gpio_get_value(PALMTE_DC_GPIO);
245         batt = battery[0];
246         if (charging)
247                 batt -= 60;
248
249         hi = ARRAY_SIZE(palmte_battery_sample);
250         lo = 0;
251
252         info->battery_flag = 0;
253         info->units = APM_UNITS_MINS;
254
255         if (batt > palmte_battery_sample[lo]) {
256                 info->battery_life = 100;
257                 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
258         } else if (batt <= palmte_battery_sample[hi - 1]) {
259                 info->battery_life = 0;
260                 info->time = 0;
261         } else {
262                 while (hi > lo + 1) {
263                         mid = (hi + lo) >> 1;
264                         if (batt <= palmte_battery_sample[mid])
265                                 lo = mid;
266                         else
267                                 hi = mid;
268                 }
269
270                 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
271                 hi = palmte_battery_sample[lo] - batt;
272                 info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
273                         ARRAY_SIZE(palmte_battery_sample);
274                 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
275                                 lo) - INTERVAL * hi / mid;
276         }
277
278         if (charging) {
279                 info->ac_line_status = APM_AC_ONLINE;
280                 info->battery_status = APM_BATTERY_STATUS_CHARGING;
281                 info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
282         } else {
283                 info->ac_line_status = APM_AC_OFFLINE;
284                 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
285                         info->battery_status = APM_BATTERY_STATUS_HIGH;
286                 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
287                         info->battery_status = APM_BATTERY_STATUS_LOW;
288                 else
289                         info->battery_status = APM_BATTERY_STATUS_CRITICAL;
290         }
291
292         if (info->battery_life > BATTERY_HIGH_TRESHOLD)
293                 info->battery_flag |= APM_BATTERY_FLAG_HIGH;
294         else if (info->battery_life > BATTERY_LOW_TRESHOLD)
295                 info->battery_flag |= APM_BATTERY_FLAG_LOW;
296         else
297                 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
298 }
299 #else
300 #define palmte_get_power_status NULL
301 #endif
302
303 static struct omap_board_config_kernel palmte_config[] __initdata = {
304         { OMAP_TAG_LCD,         &palmte_lcd_config },
305         { OMAP_TAG_UART,        &palmte_uart_config },
306 };
307
308 static struct spi_board_info palmte_spi_info[] __initdata = {
309         {
310                 .modalias       = "tsc2102",
311                 .bus_num        = 2,    /* uWire (officially) */
312                 .chip_select    = 0,    /* As opposed to 3 */
313                 .irq            = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
314                 .max_speed_hz   = 8000000,
315         },
316 };
317
318 static void palmte_headphones_detect(void *data, int state)
319 {
320         if (state) {
321                 /* Headphones connected, disable speaker */
322                 gpio_set_value(PALMTE_SPEAKER_GPIO, 0);
323                 printk(KERN_INFO "PM: speaker off\n");
324         } else {
325                 /* Headphones unplugged, re-enable speaker */
326                 gpio_set_value(PALMTE_SPEAKER_GPIO, 1);
327                 printk(KERN_INFO "PM: speaker on\n");
328         }
329 }
330
331 static void __init palmte_misc_gpio_setup(void)
332 {
333         /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
334         if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) {
335                 printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
336                 return;
337         }
338         gpio_direction_input(PALMTE_PINTDAV_GPIO);
339
340         /* Set USB-or-DC-IN pin as input (unused) */
341         if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) {
342                 printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
343                 return;
344         }
345         gpio_direction_input(PALMTE_USB_OR_DC_GPIO);
346 }
347
348 static void __init omap_palmte_init(void)
349 {
350         omap_board_config = palmte_config;
351         omap_board_config_size = ARRAY_SIZE(palmte_config);
352
353         platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
354
355         spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
356         palmte_misc_gpio_setup();
357         omap_serial_init();
358         omap_usb_init(&palmte_usb_config);
359         omap_register_i2c_bus(1, 100, NULL, 0);
360 }
361
362 static void __init omap_palmte_map_io(void)
363 {
364         omap1_map_common_io();
365 }
366
367 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
368         .phys_io        = 0xfff00000,
369         .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
370         .boot_params    = 0x10000100,
371         .map_io         = omap_palmte_map_io,
372         .init_irq       = omap_palmte_init_irq,
373         .init_machine   = omap_palmte_init,
374         .timer          = &omap_timer,
375 MACHINE_END