blob: 61a2321b97323d200db96f1e6e8ceb73794189ed [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>
Ladislav Michl561b0362010-02-15 10:03:32 -080026#include <linux/mtd/physmap.h>
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080027#include <linux/spi/spi.h>
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080028#include <linux/interrupt.h>
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080029#include <linux/apm-emulation.h>
Tony Lindgren3179a012005-11-10 14:26:48 +000030
Russell Kinga09e64f2008-08-05 16:14:15 +010031#include <mach/hardware.h>
Tony Lindgren3179a012005-11-10 14:26:48 +000032#include <asm/mach-types.h>
33#include <asm/mach/arch.h>
34#include <asm/mach/map.h>
35
Russell Kinga09e64f2008-08-05 16:14:15 +010036#include <mach/gpio.h>
Ladislav Michl561b0362010-02-15 10:03:32 -080037#include <plat/flash.h>
Tony Lindgrence491cf2009-10-20 09:40:47 -070038#include <plat/mux.h>
39#include <plat/usb.h>
40#include <plat/tc.h>
41#include <plat/dma.h>
42#include <plat/board.h>
43#include <plat/irda.h>
44#include <plat/keypad.h>
45#include <plat/common.h>
Tony Lindgren3179a012005-11-10 14:26:48 +000046
Tony Lindgrenb2830812009-03-23 18:07:35 -070047#define PALMTE_USBDETECT_GPIO 0
48#define PALMTE_USB_OR_DC_GPIO 1
49#define PALMTE_TSC_GPIO 4
50#define PALMTE_PINTDAV_GPIO 6
51#define PALMTE_MMC_WP_GPIO 8
52#define PALMTE_MMC_POWER_GPIO 9
53#define PALMTE_HDQ_GPIO 11
54#define PALMTE_HEADPHONES_GPIO 14
55#define PALMTE_SPEAKER_GPIO 15
56#define PALMTE_DC_GPIO OMAP_MPUIO(2)
57#define PALMTE_MMC_SWITCH_GPIO OMAP_MPUIO(4)
58#define PALMTE_MMC1_GPIO OMAP_MPUIO(6)
59#define PALMTE_MMC2_GPIO OMAP_MPUIO(7)
60#define PALMTE_MMC3_GPIO OMAP_MPUIO(11)
61
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080062static void __init omap_palmte_init_irq(void)
Tony Lindgren3179a012005-11-10 14:26:48 +000063{
Tony Lindgren87bd63f2006-02-08 22:06:46 +000064 omap1_init_common_hw();
Tony Lindgren3179a012005-11-10 14:26:48 +000065 omap_init_irq();
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080066 omap_gpio_init();
Tony Lindgren3179a012005-11-10 14:26:48 +000067}
68
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080069static const int palmte_keymap[] = {
70 KEY(0, 0, KEY_F1), /* Calendar */
71 KEY(0, 1, KEY_F2), /* Contacts */
72 KEY(0, 2, KEY_F3), /* Tasks List */
73 KEY(0, 3, KEY_F4), /* Note Pad */
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080074 KEY(0, 4, KEY_POWER),
75 KEY(1, 0, KEY_LEFT),
76 KEY(1, 1, KEY_DOWN),
77 KEY(1, 2, KEY_UP),
78 KEY(1, 3, KEY_RIGHT),
Eduardo Valentinec44dfa2008-03-27 11:09:42 -040079 KEY(1, 4, KEY_ENTER),
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080080 0,
81};
82
83static struct omap_kp_platform_data palmte_kp_data = {
84 .rows = 8,
85 .cols = 8,
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080086 .keymap = (int *) palmte_keymap,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080087 .rep = 1,
88 .delay = 12,
89};
90
91static struct resource palmte_kp_resources[] = {
92 [0] = {
93 .start = INT_KEYBOARD,
94 .end = INT_KEYBOARD,
95 .flags = IORESOURCE_IRQ,
96 },
97};
98
99static struct platform_device palmte_kp_device = {
100 .name = "omap-keypad",
101 .id = -1,
102 .dev = {
103 .platform_data = &palmte_kp_data,
104 },
105 .num_resources = ARRAY_SIZE(palmte_kp_resources),
106 .resource = palmte_kp_resources,
107};
108
109static struct mtd_partition palmte_rom_partitions[] = {
110 /* PalmOS "Small ROM", contains the bootloader and the debugger */
111 {
112 .name = "smallrom",
113 .offset = 0,
114 .size = 0xa000,
115 .mask_flags = MTD_WRITEABLE,
116 },
117 /* PalmOS "Big ROM", a filesystem with all the OS code and data */
118 {
119 .name = "bigrom",
120 .offset = SZ_128K,
121 /*
122 * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
123 * 0x7b0000 bytes in the English-only ("enUS") version.
124 */
125 .size = 0x7b0000,
126 .mask_flags = MTD_WRITEABLE,
127 },
128};
129
Ladislav Michl561b0362010-02-15 10:03:32 -0800130static struct physmap_flash_data palmte_rom_data = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800131 .width = 2,
Ladislav Michl561b0362010-02-15 10:03:32 -0800132 .set_vpp = omap1_set_vpp,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800133 .parts = palmte_rom_partitions,
134 .nr_parts = ARRAY_SIZE(palmte_rom_partitions),
135};
136
137static struct resource palmte_rom_resource = {
138 .start = OMAP_CS0_PHYS,
139 .end = OMAP_CS0_PHYS + SZ_8M - 1,
140 .flags = IORESOURCE_MEM,
141};
142
143static struct platform_device palmte_rom_device = {
Ladislav Michl561b0362010-02-15 10:03:32 -0800144 .name = "physmap-flash",
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800145 .id = -1,
146 .dev = {
147 .platform_data = &palmte_rom_data,
148 },
149 .num_resources = 1,
150 .resource = &palmte_rom_resource,
151};
152
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100153static struct platform_device palmte_lcd_device = {
154 .name = "lcd_palmte",
155 .id = -1,
156};
157
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800158static struct omap_backlight_config palmte_backlight_config = {
159 .default_intensity = 0xa0,
160};
161
162static struct platform_device palmte_backlight_device = {
163 .name = "omap-bl",
164 .id = -1,
165 .dev = {
166 .platform_data = &palmte_backlight_config,
167 },
168};
169
170static struct omap_irda_config palmte_irda_config = {
171 .transceiver_cap = IR_SIRMODE,
172 .rx_channel = OMAP_DMA_UART3_RX,
173 .tx_channel = OMAP_DMA_UART3_TX,
174 .dest_start = UART3_THR,
175 .src_start = UART3_RHR,
176 .tx_trigger = 0,
177 .rx_trigger = 0,
178};
179
180static struct resource palmte_irda_resources[] = {
181 [0] = {
182 .start = INT_UART3,
183 .end = INT_UART3,
184 .flags = IORESOURCE_IRQ,
185 },
186};
187
188static struct platform_device palmte_irda_device = {
189 .name = "omapirda",
190 .id = -1,
191 .dev = {
192 .platform_data = &palmte_irda_config,
193 },
194 .num_resources = ARRAY_SIZE(palmte_irda_resources),
195 .resource = palmte_irda_resources,
196};
197
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800198static struct platform_device *palmte_devices[] __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800199 &palmte_rom_device,
200 &palmte_kp_device,
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100201 &palmte_lcd_device,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800202 &palmte_backlight_device,
203 &palmte_irda_device,
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100204};
205
Tony Lindgren3179a012005-11-10 14:26:48 +0000206static struct omap_usb_config palmte_usb_config __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800207 .register_dev = 1, /* Mini-B only receptacle */
Tony Lindgren3179a012005-11-10 14:26:48 +0000208 .hmc_mode = 0,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800209 .pins[0] = 2,
Tony Lindgren3179a012005-11-10 14:26:48 +0000210};
211
Tony Lindgren3179a012005-11-10 14:26:48 +0000212static struct omap_lcd_config palmte_lcd_config __initdata = {
Tony Lindgren3179a012005-11-10 14:26:48 +0000213 .ctrl_name = "internal",
214};
215
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800216#ifdef CONFIG_APM
217/*
218 * Values measured in 10 minute intervals averaged over 10 samples.
219 * May differ slightly from device to device but should be accurate
220 * enough to give basic idea of battery life left and trigger
221 * potential alerts.
222 */
223static const int palmte_battery_sample[] = {
224 2194, 2157, 2138, 2120,
225 2104, 2089, 2075, 2061,
226 2048, 2038, 2026, 2016,
227 2008, 1998, 1989, 1980,
228 1970, 1958, 1945, 1928,
229 1910, 1888, 1860, 1827,
230 1791, 1751, 1709, 1656,
231};
232
233#define INTERVAL 10
234#define BATTERY_HIGH_TRESHOLD 66
235#define BATTERY_LOW_TRESHOLD 33
236
237static void palmte_get_power_status(struct apm_power_info *info, int *battery)
238{
239 int charging, batt, hi, lo, mid;
240
David Brownell0b84b5c2008-12-10 17:35:25 -0800241 charging = !gpio_get_value(PALMTE_DC_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800242 batt = battery[0];
243 if (charging)
244 batt -= 60;
245
246 hi = ARRAY_SIZE(palmte_battery_sample);
247 lo = 0;
248
249 info->battery_flag = 0;
250 info->units = APM_UNITS_MINS;
251
252 if (batt > palmte_battery_sample[lo]) {
253 info->battery_life = 100;
254 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
255 } else if (batt <= palmte_battery_sample[hi - 1]) {
256 info->battery_life = 0;
257 info->time = 0;
258 } else {
259 while (hi > lo + 1) {
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800260 mid = (hi + lo) >> 1;
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800261 if (batt <= palmte_battery_sample[mid])
262 lo = mid;
263 else
264 hi = mid;
265 }
266
267 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
268 hi = palmte_battery_sample[lo] - batt;
269 info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
270 ARRAY_SIZE(palmte_battery_sample);
271 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
272 lo) - INTERVAL * hi / mid;
273 }
274
275 if (charging) {
276 info->ac_line_status = APM_AC_ONLINE;
277 info->battery_status = APM_BATTERY_STATUS_CHARGING;
278 info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
279 } else {
280 info->ac_line_status = APM_AC_OFFLINE;
281 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
282 info->battery_status = APM_BATTERY_STATUS_HIGH;
283 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
284 info->battery_status = APM_BATTERY_STATUS_LOW;
285 else
286 info->battery_status = APM_BATTERY_STATUS_CRITICAL;
287 }
288
289 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
290 info->battery_flag |= APM_BATTERY_FLAG_HIGH;
291 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
292 info->battery_flag |= APM_BATTERY_FLAG_LOW;
293 else
294 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
295}
296#else
297#define palmte_get_power_status NULL
298#endif
299
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800300static struct omap_board_config_kernel palmte_config[] __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800301 { OMAP_TAG_LCD, &palmte_lcd_config },
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800302};
303
304static struct spi_board_info palmte_spi_info[] __initdata = {
305 {
306 .modalias = "tsc2102",
307 .bus_num = 2, /* uWire (officially) */
308 .chip_select = 0, /* As opposed to 3 */
309 .irq = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800310 .max_speed_hz = 8000000,
311 },
312};
313
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800314static void palmte_headphones_detect(void *data, int state)
315{
316 if (state) {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800317 /* Headphones connected, disable speaker */
David Brownell0b84b5c2008-12-10 17:35:25 -0800318 gpio_set_value(PALMTE_SPEAKER_GPIO, 0);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800319 printk(KERN_INFO "PM: speaker off\n");
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800320 } else {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800321 /* Headphones unplugged, re-enable speaker */
David Brownell0b84b5c2008-12-10 17:35:25 -0800322 gpio_set_value(PALMTE_SPEAKER_GPIO, 1);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800323 printk(KERN_INFO "PM: speaker on\n");
324 }
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800325}
326
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800327static void __init palmte_misc_gpio_setup(void)
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800328{
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800329 /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
Jarkko Nikulaf2d18fe2008-12-10 17:35:30 -0800330 if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800331 printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
332 return;
333 }
David Brownell40e39252008-12-10 17:35:26 -0800334 gpio_direction_input(PALMTE_PINTDAV_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800335
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800336 /* Set USB-or-DC-IN pin as input (unused) */
Jarkko Nikulaf2d18fe2008-12-10 17:35:30 -0800337 if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800338 printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
339 return;
340 }
David Brownell40e39252008-12-10 17:35:26 -0800341 gpio_direction_input(PALMTE_USB_OR_DC_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800342}
343
344static void __init omap_palmte_init(void)
Tony Lindgren3179a012005-11-10 14:26:48 +0000345{
Janusz Krzysztofikc33da3a2009-10-22 14:47:42 -0700346 /* mux pins for uarts */
347 omap_cfg_reg(UART1_TX);
348 omap_cfg_reg(UART1_RTS);
349 omap_cfg_reg(UART2_TX);
350 omap_cfg_reg(UART2_RTS);
351 omap_cfg_reg(UART3_TX);
352 omap_cfg_reg(UART3_RX);
353
Tony Lindgren3179a012005-11-10 14:26:48 +0000354 omap_board_config = palmte_config;
355 omap_board_config_size = ARRAY_SIZE(palmte_config);
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100356
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800357 platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800358
359 spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800360 palmte_misc_gpio_setup();
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800361 omap_serial_init();
Felipe Balbib0b5aa32009-03-23 18:07:49 -0700362 omap_usb_init(&palmte_usb_config);
Jarkko Nikula1ed16a82007-11-07 06:54:32 +0200363 omap_register_i2c_bus(1, 100, NULL, 0);
Tony Lindgren3179a012005-11-10 14:26:48 +0000364}
365
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800366static void __init omap_palmte_map_io(void)
Tony Lindgren3179a012005-11-10 14:26:48 +0000367{
Tony Lindgren87bd63f2006-02-08 22:06:46 +0000368 omap1_map_common_io();
Tony Lindgren3179a012005-11-10 14:26:48 +0000369}
370
371MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
Tony Lindgren3179a012005-11-10 14:26:48 +0000372 .phys_io = 0xfff00000,
373 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
374 .boot_params = 0x10000100,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800375 .map_io = omap_palmte_map_io,
Russell King71ee7da2010-05-23 10:18:16 +0100376 .reserve = omap_reserve,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800377 .init_irq = omap_palmte_init_irq,
378 .init_machine = omap_palmte_init,
Tony Lindgren3179a012005-11-10 14:26:48 +0000379 .timer = &omap_timer,
380MACHINE_END