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