Merge branch 'r6040' of git://git.kernel.org/pub/scm/linux/kernel/git/romieu/netdev...
[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/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
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_CENTER),
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_mmc_config palmte_mmc_config __initdata = {
200         .mmc[0]         = {
201                 .enabled        = 1,
202                 .wp_pin         = PALMTE_MMC_WP_GPIO,
203                 .power_pin      = PALMTE_MMC_POWER_GPIO,
204                 .switch_pin     = PALMTE_MMC_SWITCH_GPIO,
205         },
206 };
207
208 static struct omap_lcd_config palmte_lcd_config __initdata = {
209         .ctrl_name      = "internal",
210 };
211
212 static struct omap_uart_config palmte_uart_config __initdata = {
213         .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
214 };
215
216 static struct omap_mcbsp_reg_cfg palmte_mcbsp1_regs = {
217         .spcr2  = FRST | GRST | XRST | XINTM(3),
218         .xcr2   = XDATDLY(1) | XFIG,
219         .xcr1   = XWDLEN1(OMAP_MCBSP_WORD_32),
220         .pcr0   = SCLKME | FSXP | CLKXP,
221 };
222
223 static struct omap_alsa_codec_config palmte_alsa_config = {
224         .name                   = "TSC2102 audio",
225         .mcbsp_regs_alsa        = &palmte_mcbsp1_regs,
226         .codec_configure_dev    = NULL, /* tsc2102_configure, */
227         .codec_set_samplerate   = NULL, /* tsc2102_set_samplerate, */
228         .codec_clock_setup      = NULL, /* tsc2102_clock_setup, */
229         .codec_clock_on         = NULL, /* tsc2102_clock_on, */
230         .codec_clock_off        = NULL, /* tsc2102_clock_off, */
231         .get_default_samplerate = NULL, /* tsc2102_get_default_samplerate, */
232 };
233
234 #ifdef CONFIG_APM
235 /*
236  * Values measured in 10 minute intervals averaged over 10 samples.
237  * May differ slightly from device to device but should be accurate
238  * enough to give basic idea of battery life left and trigger
239  * potential alerts.
240  */
241 static const int palmte_battery_sample[] = {
242         2194, 2157, 2138, 2120,
243         2104, 2089, 2075, 2061,
244         2048, 2038, 2026, 2016,
245         2008, 1998, 1989, 1980,
246         1970, 1958, 1945, 1928,
247         1910, 1888, 1860, 1827,
248         1791, 1751, 1709, 1656,
249 };
250
251 #define INTERVAL                10
252 #define BATTERY_HIGH_TRESHOLD   66
253 #define BATTERY_LOW_TRESHOLD    33
254
255 static void palmte_get_power_status(struct apm_power_info *info, int *battery)
256 {
257         int charging, batt, hi, lo, mid;
258
259         charging = !omap_get_gpio_datain(PALMTE_DC_GPIO);
260         batt = battery[0];
261         if (charging)
262                 batt -= 60;
263
264         hi = ARRAY_SIZE(palmte_battery_sample);
265         lo = 0;
266
267         info->battery_flag = 0;
268         info->units = APM_UNITS_MINS;
269
270         if (batt > palmte_battery_sample[lo]) {
271                 info->battery_life = 100;
272                 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
273         } else if (batt <= palmte_battery_sample[hi - 1]) {
274                 info->battery_life = 0;
275                 info->time = 0;
276         } else {
277                 while (hi > lo + 1) {
278                         mid = (hi + lo) >> 1;
279                         if (batt <= palmte_battery_sample[mid])
280                                 lo = mid;
281                         else
282                                 hi = mid;
283                 }
284
285                 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
286                 hi = palmte_battery_sample[lo] - batt;
287                 info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
288                         ARRAY_SIZE(palmte_battery_sample);
289                 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
290                                 lo) - INTERVAL * hi / mid;
291         }
292
293         if (charging) {
294                 info->ac_line_status = APM_AC_ONLINE;
295                 info->battery_status = APM_BATTERY_STATUS_CHARGING;
296                 info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
297         } else {
298                 info->ac_line_status = APM_AC_OFFLINE;
299                 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
300                         info->battery_status = APM_BATTERY_STATUS_HIGH;
301                 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
302                         info->battery_status = APM_BATTERY_STATUS_LOW;
303                 else
304                         info->battery_status = APM_BATTERY_STATUS_CRITICAL;
305         }
306
307         if (info->battery_life > BATTERY_HIGH_TRESHOLD)
308                 info->battery_flag |= APM_BATTERY_FLAG_HIGH;
309         else if (info->battery_life > BATTERY_LOW_TRESHOLD)
310                 info->battery_flag |= APM_BATTERY_FLAG_LOW;
311         else
312                 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
313 }
314 #else
315 #define palmte_get_power_status NULL
316 #endif
317
318 static struct tsc2102_config palmte_tsc2102_config = {
319         .use_internal   = 0,
320         .monitor        = TSC_BAT1 | TSC_AUX | TSC_TEMP,
321         .temp_at25c     = { 2200, 2615 },
322         .apm_report     = palmte_get_power_status,
323         .alsa_config    = &palmte_alsa_config,
324 };
325
326 static struct omap_board_config_kernel palmte_config[] __initdata = {
327         { OMAP_TAG_USB,         &palmte_usb_config },
328         { OMAP_TAG_MMC,         &palmte_mmc_config },
329         { OMAP_TAG_LCD,         &palmte_lcd_config },
330         { OMAP_TAG_UART,        &palmte_uart_config },
331 };
332
333 static struct spi_board_info palmte_spi_info[] __initdata = {
334         {
335                 .modalias       = "tsc2102",
336                 .bus_num        = 2,    /* uWire (officially) */
337                 .chip_select    = 0,    /* As opposed to 3 */
338                 .irq            = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
339                 .platform_data  = &palmte_tsc2102_config,
340                 .max_speed_hz   = 8000000,
341         },
342 };
343
344 static void palmte_headphones_detect(void *data, int state)
345 {
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 void __init palmte_misc_gpio_setup(void)
358 {
359         /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
360         if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) {
361                 printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
362                 return;
363         }
364         omap_set_gpio_direction(PALMTE_PINTDAV_GPIO, 1);
365
366         /* Set USB-or-DC-IN pin as input (unused) */
367         if (omap_request_gpio(PALMTE_USB_OR_DC_GPIO)) {
368                 printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
369                 return;
370         }
371         omap_set_gpio_direction(PALMTE_USB_OR_DC_GPIO, 1);
372 }
373
374 static void __init omap_palmte_init(void)
375 {
376         omap_board_config = palmte_config;
377         omap_board_config_size = ARRAY_SIZE(palmte_config);
378
379         platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
380
381         spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
382         palmte_misc_gpio_setup();
383         omap_serial_init();
384         omap_register_i2c_bus(1, 100, NULL, 0);
385 }
386
387 static void __init omap_palmte_map_io(void)
388 {
389         omap1_map_common_io();
390 }
391
392 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
393         .phys_io        = 0xfff00000,
394         .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
395         .boot_params    = 0x10000100,
396         .map_io         = omap_palmte_map_io,
397         .init_irq       = omap_palmte_init_irq,
398         .init_machine   = omap_palmte_init,
399         .timer          = &omap_timer,
400 MACHINE_END