blob: 0995a0fc1dd0002496af4718c4ee356c82c9fd24 [file] [log] [blame]
Tony Lindgren3179a012005-11-10 14:26:48 +00001/*
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 *
Simon Arlott6cbdc8c2007-05-11 20:40:30 +010010 * Maintainers : http://palmtelinux.sf.net
Tony Lindgren3179a012005-11-10 14:26:48 +000011 * palmtelinux-developpers@lists.sf.net
12 *
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080013 * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
14 *
Tony Lindgren3179a012005-11-10 14:26:48 +000015 * 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>
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080022#include <linux/input.h>
Tony Lindgren3179a012005-11-10 14:26:48 +000023#include <linux/platform_device.h>
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080024#include <linux/mtd/mtd.h>
25#include <linux/mtd/partitions.h>
26#include <linux/spi/spi.h>
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080027#include <linux/interrupt.h>
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080028#include <linux/apm-emulation.h>
Tony Lindgren3179a012005-11-10 14:26:48 +000029
Russell Kinga09e64f2008-08-05 16:14:15 +010030#include <mach/hardware.h>
Tony Lindgren3179a012005-11-10 14:26:48 +000031#include <asm/mach-types.h>
32#include <asm/mach/arch.h>
33#include <asm/mach/map.h>
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080034#include <asm/mach/flash.h>
Tony Lindgren3179a012005-11-10 14:26:48 +000035
Russell Kinga09e64f2008-08-05 16:14:15 +010036#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/mcbsp.h>
46#include <mach/omap-alsa.h>
Tony Lindgren3179a012005-11-10 14:26:48 +000047
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080048static void __init omap_palmte_init_irq(void)
Tony Lindgren3179a012005-11-10 14:26:48 +000049{
Tony Lindgren87bd63f2006-02-08 22:06:46 +000050 omap1_init_common_hw();
Tony Lindgren3179a012005-11-10 14:26:48 +000051 omap_init_irq();
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080052 omap_gpio_init();
Tony Lindgren3179a012005-11-10 14:26:48 +000053}
54
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080055static const int palmte_keymap[] = {
56 KEY(0, 0, KEY_F1), /* Calendar */
57 KEY(0, 1, KEY_F2), /* Contacts */
58 KEY(0, 2, KEY_F3), /* Tasks List */
59 KEY(0, 3, KEY_F4), /* Note Pad */
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080060 KEY(0, 4, KEY_POWER),
61 KEY(1, 0, KEY_LEFT),
62 KEY(1, 1, KEY_DOWN),
63 KEY(1, 2, KEY_UP),
64 KEY(1, 3, KEY_RIGHT),
Eduardo Valentinec44dfa2008-03-27 11:09:42 -040065 KEY(1, 4, KEY_ENTER),
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080066 0,
67};
68
69static struct omap_kp_platform_data palmte_kp_data = {
70 .rows = 8,
71 .cols = 8,
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080072 .keymap = (int *) palmte_keymap,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080073 .rep = 1,
74 .delay = 12,
75};
76
77static struct resource palmte_kp_resources[] = {
78 [0] = {
79 .start = INT_KEYBOARD,
80 .end = INT_KEYBOARD,
81 .flags = IORESOURCE_IRQ,
82 },
83};
84
85static struct platform_device palmte_kp_device = {
86 .name = "omap-keypad",
87 .id = -1,
88 .dev = {
89 .platform_data = &palmte_kp_data,
90 },
91 .num_resources = ARRAY_SIZE(palmte_kp_resources),
92 .resource = palmte_kp_resources,
93};
94
95static struct mtd_partition palmte_rom_partitions[] = {
96 /* PalmOS "Small ROM", contains the bootloader and the debugger */
97 {
98 .name = "smallrom",
99 .offset = 0,
100 .size = 0xa000,
101 .mask_flags = MTD_WRITEABLE,
102 },
103 /* PalmOS "Big ROM", a filesystem with all the OS code and data */
104 {
105 .name = "bigrom",
106 .offset = SZ_128K,
107 /*
108 * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
109 * 0x7b0000 bytes in the English-only ("enUS") version.
110 */
111 .size = 0x7b0000,
112 .mask_flags = MTD_WRITEABLE,
113 },
114};
115
116static struct flash_platform_data palmte_rom_data = {
117 .map_name = "map_rom",
118 .width = 2,
119 .parts = palmte_rom_partitions,
120 .nr_parts = ARRAY_SIZE(palmte_rom_partitions),
121};
122
123static struct resource palmte_rom_resource = {
124 .start = OMAP_CS0_PHYS,
125 .end = OMAP_CS0_PHYS + SZ_8M - 1,
126 .flags = IORESOURCE_MEM,
127};
128
129static struct platform_device palmte_rom_device = {
130 .name = "omapflash",
131 .id = -1,
132 .dev = {
133 .platform_data = &palmte_rom_data,
134 },
135 .num_resources = 1,
136 .resource = &palmte_rom_resource,
137};
138
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100139static struct platform_device palmte_lcd_device = {
140 .name = "lcd_palmte",
141 .id = -1,
142};
143
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800144static struct omap_backlight_config palmte_backlight_config = {
145 .default_intensity = 0xa0,
146};
147
148static struct platform_device palmte_backlight_device = {
149 .name = "omap-bl",
150 .id = -1,
151 .dev = {
152 .platform_data = &palmte_backlight_config,
153 },
154};
155
156static struct omap_irda_config palmte_irda_config = {
157 .transceiver_cap = IR_SIRMODE,
158 .rx_channel = OMAP_DMA_UART3_RX,
159 .tx_channel = OMAP_DMA_UART3_TX,
160 .dest_start = UART3_THR,
161 .src_start = UART3_RHR,
162 .tx_trigger = 0,
163 .rx_trigger = 0,
164};
165
166static struct resource palmte_irda_resources[] = {
167 [0] = {
168 .start = INT_UART3,
169 .end = INT_UART3,
170 .flags = IORESOURCE_IRQ,
171 },
172};
173
174static struct platform_device palmte_irda_device = {
175 .name = "omapirda",
176 .id = -1,
177 .dev = {
178 .platform_data = &palmte_irda_config,
179 },
180 .num_resources = ARRAY_SIZE(palmte_irda_resources),
181 .resource = palmte_irda_resources,
182};
183
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800184static struct platform_device *palmte_devices[] __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800185 &palmte_rom_device,
186 &palmte_kp_device,
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100187 &palmte_lcd_device,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800188 &palmte_backlight_device,
189 &palmte_irda_device,
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100190};
191
Tony Lindgren3179a012005-11-10 14:26:48 +0000192static struct omap_usb_config palmte_usb_config __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800193 .register_dev = 1, /* Mini-B only receptacle */
Tony Lindgren3179a012005-11-10 14:26:48 +0000194 .hmc_mode = 0,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800195 .pins[0] = 2,
Tony Lindgren3179a012005-11-10 14:26:48 +0000196};
197
198static struct omap_mmc_config palmte_mmc_config __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800199 .mmc[0] = {
Tony Lindgren3179a012005-11-10 14:26:48 +0000200 .enabled = 1,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800201 .wp_pin = PALMTE_MMC_WP_GPIO,
202 .power_pin = PALMTE_MMC_POWER_GPIO,
203 .switch_pin = PALMTE_MMC_SWITCH_GPIO,
Tony Lindgren3179a012005-11-10 14:26:48 +0000204 },
205};
206
207static struct omap_lcd_config palmte_lcd_config __initdata = {
Tony Lindgren3179a012005-11-10 14:26:48 +0000208 .ctrl_name = "internal",
209};
210
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800211static struct omap_uart_config palmte_uart_config __initdata = {
212 .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
Tony Lindgren3179a012005-11-10 14:26:48 +0000213};
214
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800215static struct omap_mcbsp_reg_cfg palmte_mcbsp1_regs = {
216 .spcr2 = FRST | GRST | XRST | XINTM(3),
217 .xcr2 = XDATDLY(1) | XFIG,
218 .xcr1 = XWDLEN1(OMAP_MCBSP_WORD_32),
219 .pcr0 = SCLKME | FSXP | CLKXP,
220};
221
222static struct omap_alsa_codec_config palmte_alsa_config = {
223 .name = "TSC2102 audio",
224 .mcbsp_regs_alsa = &palmte_mcbsp1_regs,
225 .codec_configure_dev = NULL, /* tsc2102_configure, */
226 .codec_set_samplerate = NULL, /* tsc2102_set_samplerate, */
227 .codec_clock_setup = NULL, /* tsc2102_clock_setup, */
228 .codec_clock_on = NULL, /* tsc2102_clock_on, */
229 .codec_clock_off = NULL, /* tsc2102_clock_off, */
230 .get_default_samplerate = NULL, /* tsc2102_get_default_samplerate, */
231};
232
233#ifdef CONFIG_APM
234/*
235 * Values measured in 10 minute intervals averaged over 10 samples.
236 * May differ slightly from device to device but should be accurate
237 * enough to give basic idea of battery life left and trigger
238 * potential alerts.
239 */
240static const int palmte_battery_sample[] = {
241 2194, 2157, 2138, 2120,
242 2104, 2089, 2075, 2061,
243 2048, 2038, 2026, 2016,
244 2008, 1998, 1989, 1980,
245 1970, 1958, 1945, 1928,
246 1910, 1888, 1860, 1827,
247 1791, 1751, 1709, 1656,
248};
249
250#define INTERVAL 10
251#define BATTERY_HIGH_TRESHOLD 66
252#define BATTERY_LOW_TRESHOLD 33
253
254static void palmte_get_power_status(struct apm_power_info *info, int *battery)
255{
256 int charging, batt, hi, lo, mid;
257
David Brownell0b84b5c2008-12-10 17:35:25 -0800258 charging = !gpio_get_value(PALMTE_DC_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800259 batt = battery[0];
260 if (charging)
261 batt -= 60;
262
263 hi = ARRAY_SIZE(palmte_battery_sample);
264 lo = 0;
265
266 info->battery_flag = 0;
267 info->units = APM_UNITS_MINS;
268
269 if (batt > palmte_battery_sample[lo]) {
270 info->battery_life = 100;
271 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
272 } else if (batt <= palmte_battery_sample[hi - 1]) {
273 info->battery_life = 0;
274 info->time = 0;
275 } else {
276 while (hi > lo + 1) {
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800277 mid = (hi + lo) >> 1;
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800278 if (batt <= palmte_battery_sample[mid])
279 lo = mid;
280 else
281 hi = mid;
282 }
283
284 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
285 hi = palmte_battery_sample[lo] - batt;
286 info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
287 ARRAY_SIZE(palmte_battery_sample);
288 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
289 lo) - INTERVAL * hi / mid;
290 }
291
292 if (charging) {
293 info->ac_line_status = APM_AC_ONLINE;
294 info->battery_status = APM_BATTERY_STATUS_CHARGING;
295 info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
296 } else {
297 info->ac_line_status = APM_AC_OFFLINE;
298 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
299 info->battery_status = APM_BATTERY_STATUS_HIGH;
300 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
301 info->battery_status = APM_BATTERY_STATUS_LOW;
302 else
303 info->battery_status = APM_BATTERY_STATUS_CRITICAL;
304 }
305
306 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
307 info->battery_flag |= APM_BATTERY_FLAG_HIGH;
308 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
309 info->battery_flag |= APM_BATTERY_FLAG_LOW;
310 else
311 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
312}
313#else
314#define palmte_get_power_status NULL
315#endif
316
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800317static struct omap_board_config_kernel palmte_config[] __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800318 { OMAP_TAG_USB, &palmte_usb_config },
319 { OMAP_TAG_MMC, &palmte_mmc_config },
320 { OMAP_TAG_LCD, &palmte_lcd_config },
321 { OMAP_TAG_UART, &palmte_uart_config },
322};
323
324static struct spi_board_info palmte_spi_info[] __initdata = {
325 {
326 .modalias = "tsc2102",
327 .bus_num = 2, /* uWire (officially) */
328 .chip_select = 0, /* As opposed to 3 */
329 .irq = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800330 .max_speed_hz = 8000000,
331 },
332};
333
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800334static void palmte_headphones_detect(void *data, int state)
335{
336 if (state) {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800337 /* Headphones connected, disable speaker */
David Brownell0b84b5c2008-12-10 17:35:25 -0800338 gpio_set_value(PALMTE_SPEAKER_GPIO, 0);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800339 printk(KERN_INFO "PM: speaker off\n");
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800340 } else {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800341 /* Headphones unplugged, re-enable speaker */
David Brownell0b84b5c2008-12-10 17:35:25 -0800342 gpio_set_value(PALMTE_SPEAKER_GPIO, 1);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800343 printk(KERN_INFO "PM: speaker on\n");
344 }
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800345}
346
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800347static void __init palmte_misc_gpio_setup(void)
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800348{
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800349 /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800350 if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) {
351 printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
352 return;
353 }
David Brownell40e39252008-12-10 17:35:26 -0800354 gpio_direction_input(PALMTE_PINTDAV_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800355
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800356 /* Set USB-or-DC-IN pin as input (unused) */
357 if (omap_request_gpio(PALMTE_USB_OR_DC_GPIO)) {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800358 printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
359 return;
360 }
David Brownell40e39252008-12-10 17:35:26 -0800361 gpio_direction_input(PALMTE_USB_OR_DC_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800362}
363
364static void __init omap_palmte_init(void)
Tony Lindgren3179a012005-11-10 14:26:48 +0000365{
366 omap_board_config = palmte_config;
367 omap_board_config_size = ARRAY_SIZE(palmte_config);
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100368
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800369 platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800370
371 spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800372 palmte_misc_gpio_setup();
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800373 omap_serial_init();
Jarkko Nikula1ed16a82007-11-07 06:54:32 +0200374 omap_register_i2c_bus(1, 100, NULL, 0);
Tony Lindgren3179a012005-11-10 14:26:48 +0000375}
376
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800377static void __init omap_palmte_map_io(void)
Tony Lindgren3179a012005-11-10 14:26:48 +0000378{
Tony Lindgren87bd63f2006-02-08 22:06:46 +0000379 omap1_map_common_io();
Tony Lindgren3179a012005-11-10 14:26:48 +0000380}
381
382MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
Tony Lindgren3179a012005-11-10 14:26:48 +0000383 .phys_io = 0xfff00000,
384 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
385 .boot_params = 0x10000100,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800386 .map_io = omap_palmte_map_io,
387 .init_irq = omap_palmte_init_irq,
388 .init_machine = omap_palmte_init,
Tony Lindgren3179a012005-11-10 14:26:48 +0000389 .timer = &omap_timer,
390MACHINE_END