2 * linux/arch/arm/mach-omap1/board-palmte.c
4 * Modified from board-generic.c
6 * Support for the Palm Tungsten E PDA.
8 * Original version : Laurent Gonzalez
10 * Maintainers : http://palmtelinux.sf.net
11 * palmtelinux-developpers@lists.sf.net
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.
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>
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>
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>
47 static void __init
omap_palmte_init_irq(void)
49 omap1_init_common_hw();
54 static int palmte_keymap
[] = {
64 KEY(1, 4, KEY_CENTER
),
68 static struct omap_kp_platform_data palmte_kp_data
= {
71 .keymap
= palmte_keymap
,
76 static struct resource palmte_kp_resources
[] = {
78 .start
= INT_KEYBOARD
,
80 .flags
= IORESOURCE_IRQ
,
84 static struct platform_device palmte_kp_device
= {
85 .name
= "omap-keypad",
88 .platform_data
= &palmte_kp_data
,
90 .num_resources
= ARRAY_SIZE(palmte_kp_resources
),
91 .resource
= palmte_kp_resources
,
94 static struct mtd_partition palmte_rom_partitions
[] = {
95 /* PalmOS "Small ROM", contains the bootloader and the debugger */
100 .mask_flags
= MTD_WRITEABLE
,
102 /* PalmOS "Big ROM", a filesystem with all the OS code and data */
107 * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
108 * 0x7b0000 bytes in the English-only ("enUS") version.
111 .mask_flags
= MTD_WRITEABLE
,
115 static struct flash_platform_data palmte_rom_data
= {
116 .map_name
= "map_rom",
118 .parts
= palmte_rom_partitions
,
119 .nr_parts
= ARRAY_SIZE(palmte_rom_partitions
),
122 static struct resource palmte_rom_resource
= {
123 .start
= OMAP_CS0_PHYS
,
124 .end
= OMAP_CS0_PHYS
+ SZ_8M
- 1,
125 .flags
= IORESOURCE_MEM
,
128 static struct platform_device palmte_rom_device
= {
132 .platform_data
= &palmte_rom_data
,
135 .resource
= &palmte_rom_resource
,
138 static struct platform_device palmte_lcd_device
= {
139 .name
= "lcd_palmte",
143 static struct omap_backlight_config palmte_backlight_config
= {
144 .default_intensity
= 0xa0,
147 static struct platform_device palmte_backlight_device
= {
151 .platform_data
= &palmte_backlight_config
,
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
,
165 static struct resource palmte_irda_resources
[] = {
169 .flags
= IORESOURCE_IRQ
,
173 static struct platform_device palmte_irda_device
= {
177 .platform_data
= &palmte_irda_config
,
179 .num_resources
= ARRAY_SIZE(palmte_irda_resources
),
180 .resource
= palmte_irda_resources
,
183 static struct platform_device
*devices
[] __initdata
= {
187 &palmte_backlight_device
,
191 static struct omap_usb_config palmte_usb_config __initdata
= {
192 .register_dev
= 1, /* Mini-B only receptacle */
197 static struct omap_mmc_config palmte_mmc_config __initdata
= {
200 .wp_pin
= PALMTE_MMC_WP_GPIO
,
201 .power_pin
= PALMTE_MMC_POWER_GPIO
,
202 .switch_pin
= PALMTE_MMC_SWITCH_GPIO
,
206 static struct omap_lcd_config palmte_lcd_config __initdata
= {
207 .ctrl_name
= "internal",
210 static struct omap_uart_config palmte_uart_config __initdata
= {
211 .enabled_uarts
= (1 << 0) | (1 << 1) | (0 << 2),
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
,
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, */
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
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,
250 #define BATTERY_HIGH_TRESHOLD 66
251 #define BATTERY_LOW_TRESHOLD 33
253 static void palmte_get_power_status(struct apm_power_info
*info
, int *battery
)
255 int charging
, batt
, hi
, lo
, mid
;
257 charging
= !omap_get_gpio_datain(PALMTE_DC_GPIO
);
262 hi
= ARRAY_SIZE(palmte_battery_sample
);
265 info
->battery_flag
= 0;
266 info
->units
= APM_UNITS_MINS
;
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;
275 while (hi
> lo
+ 1) {
276 mid
= (hi
+ lo
) >> 2;
277 if (batt
<= palmte_battery_sample
[mid
])
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
;
292 info
->ac_line_status
= APM_AC_ONLINE
;
293 info
->battery_status
= APM_BATTERY_STATUS_CHARGING
;
294 info
->battery_flag
|= APM_BATTERY_FLAG_CHARGING
;
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
;
302 info
->battery_status
= APM_BATTERY_STATUS_CRITICAL
;
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
;
310 info
->battery_flag
|= APM_BATTERY_FLAG_CRITICAL
;
313 #define palmte_get_power_status NULL
316 static struct tsc2102_config palmte_tsc2102_config
= {
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
,
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
,
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, */
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
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,
360 #define BATTERY_HIGH_TRESHOLD 66
361 #define BATTERY_LOW_TRESHOLD 33
363 static void palmte_get_power_status(struct apm_power_info
*info
, int *battery
)
365 int charging
, batt
, hi
, lo
, mid
;
367 charging
= !omap_get_gpio_datain(PALMTE_DC_GPIO
);
372 hi
= ARRAY_SIZE(palmte_battery_sample
);
375 info
->battery_flag
= 0;
376 info
->units
= APM_UNITS_MINS
;
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;
385 while (hi
> lo
+ 1) {
386 mid
= (hi
+ lo
) >> 2;
387 if (batt
<= palmte_battery_sample
[mid
])
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
;
402 info
->ac_line_status
= APM_AC_ONLINE
;
403 info
->battery_status
= APM_BATTERY_STATUS_CHARGING
;
404 info
->battery_flag
|= APM_BATTERY_FLAG_CHARGING
;
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
;
412 info
->battery_status
= APM_BATTERY_STATUS_CRITICAL
;
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
;
420 info
->battery_flag
|= APM_BATTERY_FLAG_CRITICAL
;
423 #define palmte_get_power_status NULL
426 static struct tsc2102_config palmte_tsc2102_config
= {
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
,
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
},
441 static struct spi_board_info palmte_spi_info
[] __initdata
= {
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,
452 static struct spi_board_info palmte_spi_info
[] __initdata
= {
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,
463 /* Periodically check for changes on important input pins */
464 struct timer_list palmte_pin_timer
;
465 int prev_power
, prev_headphones
;
467 static void palmte_pin_handler(unsigned long data
) {
468 int power
, headphones
;
470 power
= !omap_get_gpio_datain(PALMTE_DC_GPIO
);
471 headphones
= omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO
);
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");
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");
489 prev_headphones
= headphones
;
490 mod_timer(&palmte_pin_timer
, jiffies
+ msecs_to_jiffies(500));
493 static void __init
palmte_gpio_setup(void)
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");
500 omap_set_gpio_direction(PALMTE_PINTDAV_GPIO
, 1);
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");
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);
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");
518 omap_set_gpio_direction(PALMTE_SPEAKER_GPIO
, 0);
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");
525 omap_set_gpio_direction(PALMTE_HEADPHONES_GPIO
, 1);
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);
533 static void __init
omap_palmte_init(void)
535 omap_board_config
= palmte_config
;
536 omap_board_config_size
= ARRAY_SIZE(palmte_config
);
538 platform_add_devices(devices
, ARRAY_SIZE(devices
));
540 spi_register_board_info(palmte_spi_info
, ARRAY_SIZE(palmte_spi_info
));
542 spi_register_board_info(palmte_spi_info
, ARRAY_SIZE(palmte_spi_info
));
548 static void __init
omap_palmte_map_io(void)
550 omap1_map_common_io();
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
,