]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap1/board-palmte.c
ARM: OMAP: Palm Tungsten|T support
[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  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License version 2 as
15  * published by the Free Software Foundation.
16  */
17
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <linux/input.h>
21 #include <linux/platform_device.h>
22 #include <linux/mtd/mtd.h>
23 #include <linux/mtd/partitions.h>
24 #include <linux/spi/spi.h>
25 #include <linux/spi/tsc2102.h>
26 #include <linux/interrupt.h>
27
28 #include <asm/apm.h>
29 #include <asm/hardware.h>
30 #include <asm/mach-types.h>
31 #include <asm/mach/arch.h>
32 #include <asm/mach/map.h>
33 #include <asm/mach/flash.h>
34
35 #include <asm/arch/gpio.h>
36 #include <asm/arch/mux.h>
37 #include <asm/arch/usb.h>
38 #include <asm/arch/tc.h>
39 #include <asm/arch/dma.h>
40 #include <asm/arch/board.h>
41 #include <asm/arch/irda.h>
42 #include <asm/arch/keypad.h>
43 #include <asm/arch/common.h>
44 #include <asm/arch/mcbsp.h>
45 #include <asm/arch/omap-alsa.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 int palmte_keymap[] = {
55         KEY(0, 0, KEY_F1),
56         KEY(0, 1, KEY_F2),
57         KEY(0, 2, KEY_F3),
58         KEY(0, 3, KEY_F4),
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_CENTER),
65         0,
66 };
67
68 static struct omap_kp_platform_data palmte_kp_data = {
69         .rows   = 8,
70         .cols   = 8,
71         .keymap = 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 *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_mmc_config palmte_mmc_config __initdata = {
198         .mmc[0]         = {
199                 .enabled        = 1,
200                 .wp_pin         = PALMTE_MMC_WP_GPIO,
201                 .power_pin      = PALMTE_MMC_POWER_GPIO,
202                 .switch_pin     = PALMTE_MMC_SWITCH_GPIO,
203         },
204 };
205
206 static struct omap_lcd_config palmte_lcd_config __initdata = {
207         .ctrl_name      = "internal",
208 };
209
210 static struct omap_uart_config palmte_uart_config __initdata = {
211         .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
212 };
213
214 static struct omap_mcbsp_reg_cfg palmte_mcbsp1_regs = {
215         .spcr2  = FRST | GRST | XRST | XINTM(3),
216         .xcr2   = XDATDLY(1) | XFIG,
217         .xcr1   = XWDLEN1(OMAP_MCBSP_WORD_32),
218         .pcr0   = SCLKME | FSXP | CLKXP,
219 };
220
221 static struct omap_alsa_codec_config palmte_alsa_config = {
222         .name                   = "TSC2102 audio",
223         .mcbsp_regs_alsa        = &palmte_mcbsp1_regs,
224         .codec_configure_dev    = NULL, /* tsc2102_configure, */
225         .codec_set_samplerate   = NULL, /* tsc2102_set_samplerate, */
226         .codec_clock_setup      = NULL, /* tsc2102_clock_setup, */
227         .codec_clock_on         = NULL, /* tsc2102_clock_on, */
228         .codec_clock_off        = NULL, /* tsc2102_clock_off, */
229         .get_default_samplerate = NULL, /* tsc2102_get_default_samplerate, */
230 };
231
232 #ifdef CONFIG_APM
233 /*
234  * Values measured in 10 minute intervals averaged over 10 samples.
235  * May differ slightly from device to device but should be accurate
236  * enough to give basic idea of battery life left and trigger
237  * potential alerts.
238  */
239 static const int palmte_battery_sample[] = {
240         2194, 2157, 2138, 2120,
241         2104, 2089, 2075, 2061,
242         2048, 2038, 2026, 2016,
243         2008, 1998, 1989, 1980,
244         1970, 1958, 1945, 1928,
245         1910, 1888, 1860, 1827,
246         1791, 1751, 1709, 1656,
247 };
248
249 #define INTERVAL                10
250 #define BATTERY_HIGH_TRESHOLD   66
251 #define BATTERY_LOW_TRESHOLD    33
252
253 static void palmte_get_power_status(struct apm_power_info *info, int *battery)
254 {
255         int charging, batt, hi, lo, mid;
256
257         charging = !omap_get_gpio_datain(PALMTE_DC_GPIO);
258         batt = battery[0];
259         if (charging)
260                 batt -= 60;
261
262         hi = ARRAY_SIZE(palmte_battery_sample);
263         lo = 0;
264
265         info->battery_flag = 0;
266         info->units = APM_UNITS_MINS;
267
268         if (batt > palmte_battery_sample[lo]) {
269                 info->battery_life = 100;
270                 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
271         } else if (batt <= palmte_battery_sample[hi - 1]) {
272                 info->battery_life = 0;
273                 info->time = 0;
274         } else {
275                 while (hi > lo + 1) {
276                         mid = (hi + lo) >> 2;
277                         if (batt <= palmte_battery_sample[mid])
278                                 lo = mid;
279                         else
280                                 hi = mid;
281                 }
282
283                 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
284                 hi = palmte_battery_sample[lo] - batt;
285                 info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
286                         ARRAY_SIZE(palmte_battery_sample);
287                 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
288                                 lo) - INTERVAL * hi / mid;
289         }
290
291         if (charging) {
292                 info->ac_line_status = APM_AC_ONLINE;
293                 info->battery_status = APM_BATTERY_STATUS_CHARGING;
294                 info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
295         } else {
296                 info->ac_line_status = APM_AC_OFFLINE;
297                 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
298                         info->battery_status = APM_BATTERY_STATUS_HIGH;
299                 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
300                         info->battery_status = APM_BATTERY_STATUS_LOW;
301                 else
302                         info->battery_status = APM_BATTERY_STATUS_CRITICAL;
303         }
304
305         if (info->battery_life > BATTERY_HIGH_TRESHOLD)
306                 info->battery_flag |= APM_BATTERY_FLAG_HIGH;
307         else if (info->battery_life > BATTERY_LOW_TRESHOLD)
308                 info->battery_flag |= APM_BATTERY_FLAG_LOW;
309         else
310                 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
311 }
312 #else
313 #define palmte_get_power_status NULL
314 #endif
315
316 static struct tsc2102_config palmte_tsc2102_config = {
317         .use_internal   = 0,
318         .monitor        = TSC_BAT1 | TSC_AUX | TSC_TEMP,
319         .temp_at25c     = { 2200, 2615 },
320         .apm_report     = palmte_get_power_status,
321         .alsa_config    = &palmte_alsa_config,
322 };
323
324 static struct omap_mcbsp_reg_cfg palmte_mcbsp1_regs = {
325         .spcr2  = FRST | GRST | XRST | XINTM(3),
326         .xcr2   = XDATDLY(1) | XFIG,
327         .xcr1   = XWDLEN1(OMAP_MCBSP_WORD_32),
328         .pcr0   = SCLKME | FSXP | CLKXP,
329 };
330
331 static struct omap_alsa_codec_config palmte_alsa_config = {
332         .name                   = "TSC2102 audio",
333         .mcbsp_regs_alsa        = &palmte_mcbsp1_regs,
334         .codec_configure_dev    = NULL, /* tsc2102_configure, */
335         .codec_set_samplerate   = NULL, /* tsc2102_set_samplerate, */
336         .codec_clock_setup      = NULL, /* tsc2102_clock_setup, */
337         .codec_clock_on         = NULL, /* tsc2102_clock_on, */
338         .codec_clock_off        = NULL, /* tsc2102_clock_off, */
339         .get_default_samplerate = NULL, /* tsc2102_get_default_samplerate, */
340 };
341
342 #ifdef CONFIG_APM
343 /*
344  * Values measured in 10 minute intervals averaged over 10 samples.
345  * May differ slightly from device to device but should be accurate
346  * enough to give basic idea of battery life left and trigger
347  * potential alerts.
348  */
349 static const int palmte_battery_sample[] = {
350         2194, 2157, 2138, 2120,
351         2104, 2089, 2075, 2061,
352         2048, 2038, 2026, 2016,
353         2008, 1998, 1989, 1980,
354         1970, 1958, 1945, 1928,
355         1910, 1888, 1860, 1827,
356         1791, 1751, 1709, 1656,
357 };
358
359 #define INTERVAL                10
360 #define BATTERY_HIGH_TRESHOLD   66
361 #define BATTERY_LOW_TRESHOLD    33
362
363 static void palmte_get_power_status(struct apm_power_info *info, int *battery)
364 {
365         int charging, batt, hi, lo, mid;
366
367         charging = !omap_get_gpio_datain(PALMTE_DC_GPIO);
368         batt = battery[0];
369         if (charging)
370                 batt -= 60;
371
372         hi = ARRAY_SIZE(palmte_battery_sample);
373         lo = 0;
374
375         info->battery_flag = 0;
376         info->units = APM_UNITS_MINS;
377
378         if (batt > palmte_battery_sample[lo]) {
379                 info->battery_life = 100;
380                 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
381         } else if (batt <= palmte_battery_sample[hi - 1]) {
382                 info->battery_life = 0;
383                 info->time = 0;
384         } else {
385                 while (hi > lo + 1) {
386                         mid = (hi + lo) >> 2;
387                         if (batt <= palmte_battery_sample[mid])
388                                 lo = mid;
389                         else
390                                 hi = mid;
391                 }
392
393                 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
394                 hi = palmte_battery_sample[lo] - batt;
395                 info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
396                         ARRAY_SIZE(palmte_battery_sample);
397                 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
398                                 lo) - INTERVAL * hi / mid;
399         }
400
401         if (charging) {
402                 info->ac_line_status = APM_AC_ONLINE;
403                 info->battery_status = APM_BATTERY_STATUS_CHARGING;
404                 info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
405         } else {
406                 info->ac_line_status = APM_AC_OFFLINE;
407                 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
408                         info->battery_status = APM_BATTERY_STATUS_HIGH;
409                 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
410                         info->battery_status = APM_BATTERY_STATUS_LOW;
411                 else
412                         info->battery_status = APM_BATTERY_STATUS_CRITICAL;
413         }
414
415         if (info->battery_life > BATTERY_HIGH_TRESHOLD)
416                 info->battery_flag |= APM_BATTERY_FLAG_HIGH;
417         else if (info->battery_life > BATTERY_LOW_TRESHOLD)
418                 info->battery_flag |= APM_BATTERY_FLAG_LOW;
419         else
420                 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
421 }
422 #else
423 #define palmte_get_power_status NULL
424 #endif
425
426 static struct tsc2102_config palmte_tsc2102_config = {
427         .use_internal   = 0,
428         .monitor        = TSC_BAT1 | TSC_AUX | TSC_TEMP,
429         .temp_at25c     = { 2200, 2615 },
430         .apm_report     = palmte_get_power_status,
431         .alsa_config    = &palmte_alsa_config,
432 };
433
434 static struct omap_board_config_kernel palmte_config[] = {
435         { OMAP_TAG_USB,         &palmte_usb_config },
436         { OMAP_TAG_MMC,         &palmte_mmc_config },
437         { OMAP_TAG_LCD,         &palmte_lcd_config },
438         { OMAP_TAG_UART,        &palmte_uart_config },
439 };
440
441 static struct spi_board_info palmte_spi_info[] __initdata = {
442         {
443                 .modalias       = "tsc2102",
444                 .bus_num        = 2,    /* uWire (officially) */
445                 .chip_select    = 0,    /* As opposed to 3 */
446                 .irq            = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
447                 .platform_data  = &palmte_tsc2102_config,
448                 .max_speed_hz   = 8000000,
449         },
450 };
451
452 static struct spi_board_info palmte_spi_info[] __initdata = {
453         {
454                 .modalias       = "tsc2102",
455                 .bus_num        = 2,    /* uWire (officially) */
456                 .chip_select    = 0,    /* As opposed to 3 */
457                 .irq            = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
458                 .platform_data  = &palmte_tsc2102_config,
459                 .max_speed_hz   = 8000000,
460         },
461 };
462
463 /* Periodically check for changes on important input pins */
464 struct timer_list palmte_pin_timer;
465 int prev_power, prev_headphones;
466
467 static void palmte_pin_handler(unsigned long data) {
468         int power, headphones;
469
470         power = !omap_get_gpio_datain(PALMTE_DC_GPIO);
471         headphones = omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO);
472
473         if (power && !prev_power)
474                 printk(KERN_INFO "PM: cable connected\n");
475         else if (!power && prev_power)
476                 printk(KERN_INFO "PM: cable disconnected\n");
477
478         if (headphones && !prev_headphones) {
479                 /* Headphones connected, disable speaker */
480                 omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 0);
481                 printk(KERN_INFO "PM: speaker off\n");
482         } else if (!headphones && prev_headphones) {
483                 /* Headphones unplugged, re-enable speaker */
484                 omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 1);
485                 printk(KERN_INFO "PM: speaker on\n");
486         }
487
488         prev_power = power;
489         prev_headphones = headphones;
490         mod_timer(&palmte_pin_timer, jiffies + msecs_to_jiffies(500));
491 }
492
493 static void __init palmte_gpio_setup(void)
494 {
495         /* Set TSC2102 PINTDAV pin as input */
496         if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) {
497                 printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
498                 return;
499         }
500         omap_set_gpio_direction(PALMTE_PINTDAV_GPIO, 1);
501
502         /* Monitor cable-connected signals */
503         if (omap_request_gpio(PALMTE_DC_GPIO) ||
504                         omap_request_gpio(PALMTE_USB_OR_DC_GPIO) ||
505                         omap_request_gpio(PALMTE_USBDETECT_GPIO)) {
506                 printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
507                 return;
508         }
509         omap_set_gpio_direction(PALMTE_DC_GPIO, 1);
510         omap_set_gpio_direction(PALMTE_USB_OR_DC_GPIO, 1);
511         omap_set_gpio_direction(PALMTE_USBDETECT_GPIO, 1);
512
513         /* Set speaker-enable pin as output */
514         if (omap_request_gpio(PALMTE_SPEAKER_GPIO)) {
515                 printk(KERN_ERR "Could not reserve speaker GPIO!\n");
516                 return;
517         }
518         omap_set_gpio_direction(PALMTE_SPEAKER_GPIO, 0);
519
520         /* Monitor the headphones-connected signal */
521         if (omap_request_gpio(PALMTE_HEADPHONES_GPIO)) {
522                 printk(KERN_ERR "Could not reserve headphones signal GPIO!\n");
523                 return;
524         }
525         omap_set_gpio_direction(PALMTE_HEADPHONES_GPIO, 1);
526
527         prev_power = omap_get_gpio_datain(PALMTE_DC_GPIO);
528         prev_headphones = !omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO);
529         setup_timer(&palmte_pin_timer, palmte_pin_handler, 0);
530         palmte_pin_handler(0);
531 }
532
533 static void __init omap_palmte_init(void)
534 {
535         omap_board_config = palmte_config;
536         omap_board_config_size = ARRAY_SIZE(palmte_config);
537
538         platform_add_devices(devices, ARRAY_SIZE(devices));
539
540         spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
541
542         spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
543
544         omap_serial_init();
545         palmte_gpio_setup();
546 }
547
548 static void __init omap_palmte_map_io(void)
549 {
550         omap1_map_common_io();
551 }
552
553 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
554         .phys_io        = 0xfff00000,
555         .io_pg_offst    = ((0xfef00000) >> 18) & 0xfffc,
556         .boot_params    = 0x10000100,
557         .map_io         = omap_palmte_map_io,
558         .init_irq       = omap_palmte_init_irq,
559         .init_machine   = omap_palmte_init,
560         .timer          = &omap_timer,
561 MACHINE_END