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