Merge branch 'acpi-pad' into release
[sfrench/cifs-2.6.git] / 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 <plat/mux.h>
38 #include <plat/usb.h>
39 #include <plat/tc.h>
40 #include <plat/dma.h>
41 #include <plat/board.h>
42 #include <plat/irda.h>
43 #include <plat/keypad.h>
44 #include <plat/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 #ifdef CONFIG_APM
216 /*
217  * Values measured in 10 minute intervals averaged over 10 samples.
218  * May differ slightly from device to device but should be accurate
219  * enough to give basic idea of battery life left and trigger
220  * potential alerts.
221  */
222 static const int palmte_battery_sample[] = {
223         2194, 2157, 2138, 2120,
224         2104, 2089, 2075, 2061,
225         2048, 2038, 2026, 2016,
226         2008, 1998, 1989, 1980,
227         1970, 1958, 1945, 1928,
228         1910, 1888, 1860, 1827,
229         1791, 1751, 1709, 1656,
230 };
231
232 #define INTERVAL                10
233 #define BATTERY_HIGH_TRESHOLD   66
234 #define BATTERY_LOW_TRESHOLD    33
235
236 static void palmte_get_power_status(struct apm_power_info *info, int *battery)
237 {
238         int charging, batt, hi, lo, mid;
239
240         charging = !gpio_get_value(PALMTE_DC_GPIO);
241         batt = battery[0];
242         if (charging)
243                 batt -= 60;
244
245         hi = ARRAY_SIZE(palmte_battery_sample);
246         lo = 0;
247
248         info->battery_flag = 0;
249         info->units = APM_UNITS_MINS;
250
251         if (batt > palmte_battery_sample[lo]) {
252                 info->battery_life = 100;
253                 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
254         } else if (batt <= palmte_battery_sample[hi - 1]) {
255                 info->battery_life = 0;
256                 info->time = 0;
257         } else {
258                 while (hi > lo + 1) {
259                         mid = (hi + lo) >> 1;
260                         if (batt <= palmte_battery_sample[mid])
261                                 lo = mid;
262                         else
263                                 hi = mid;
264                 }
265
266                 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
267                 hi = palmte_battery_sample[lo] - batt;
268                 info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
269                         ARRAY_SIZE(palmte_battery_sample);
270                 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
271                                 lo) - INTERVAL * hi / mid;
272         }
273
274         if (charging) {
275                 info->ac_line_status = APM_AC_ONLINE;
276                 info->battery_status = APM_BATTERY_STATUS_CHARGING;
277                 info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
278         } else {
279                 info->ac_line_status = APM_AC_OFFLINE;
280                 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
281                         info->battery_status = APM_BATTERY_STATUS_HIGH;
282                 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
283                         info->battery_status = APM_BATTERY_STATUS_LOW;
284                 else
285                         info->battery_status = APM_BATTERY_STATUS_CRITICAL;
286         }
287
288         if (info->battery_life > BATTERY_HIGH_TRESHOLD)
289                 info->battery_flag |= APM_BATTERY_FLAG_HIGH;
290         else if (info->battery_life > BATTERY_LOW_TRESHOLD)
291                 info->battery_flag |= APM_BATTERY_FLAG_LOW;
292         else
293                 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
294 }
295 #else
296 #define palmte_get_power_status NULL
297 #endif
298
299 static struct omap_board_config_kernel palmte_config[] __initdata = {
300         { OMAP_TAG_LCD,         &palmte_lcd_config },
301 };
302
303 static struct spi_board_info palmte_spi_info[] __initdata = {
304         {
305                 .modalias       = "tsc2102",
306                 .bus_num        = 2,    /* uWire (officially) */
307                 .chip_select    = 0,    /* As opposed to 3 */
308                 .irq            = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
309                 .max_speed_hz   = 8000000,
310         },
311 };
312
313 static void palmte_headphones_detect(void *data, int state)
314 {
315         if (state) {
316                 /* Headphones connected, disable speaker */
317                 gpio_set_value(PALMTE_SPEAKER_GPIO, 0);
318                 printk(KERN_INFO "PM: speaker off\n");
319         } else {
320                 /* Headphones unplugged, re-enable speaker */
321                 gpio_set_value(PALMTE_SPEAKER_GPIO, 1);
322                 printk(KERN_INFO "PM: speaker on\n");
323         }
324 }
325
326 static void __init palmte_misc_gpio_setup(void)
327 {
328         /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
329         if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) {
330                 printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
331                 return;
332         }
333         gpio_direction_input(PALMTE_PINTDAV_GPIO);
334
335         /* Set USB-or-DC-IN pin as input (unused) */
336         if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) {
337                 printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
338                 return;
339         }
340         gpio_direction_input(PALMTE_USB_OR_DC_GPIO);
341 }
342
343 static void __init omap_palmte_init(void)
344 {
345         /* mux pins for uarts */
346         omap_cfg_reg(UART1_TX);
347         omap_cfg_reg(UART1_RTS);
348         omap_cfg_reg(UART2_TX);
349         omap_cfg_reg(UART2_RTS);
350         omap_cfg_reg(UART3_TX);
351         omap_cfg_reg(UART3_RX);
352
353         omap_board_config = palmte_config;
354         omap_board_config_size = ARRAY_SIZE(palmte_config);
355
356         platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
357
358         spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
359         palmte_misc_gpio_setup();
360         omap_serial_init();
361         omap_usb_init(&palmte_usb_config);
362         omap_register_i2c_bus(1, 100, NULL, 0);
363 }
364
365 static void __init omap_palmte_map_io(void)
366 {
367         omap1_map_common_io();
368 }
369
370 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
371         .phys_io        = 0xfff00000,
372         .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
373         .boot_params    = 0x10000100,
374         .map_io         = omap_palmte_map_io,
375         .init_irq       = omap_palmte_init_irq,
376         .init_machine   = omap_palmte_init,
377         .timer          = &omap_timer,
378 MACHINE_END