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