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