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