blob: 99f2b43f2541bff7b4b898786ba48a2b98bebb4c [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>
Tony Lindgren3179a012005-11-10 14:26:48 +000045
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080046static void __init omap_palmte_init_irq(void)
Tony Lindgren3179a012005-11-10 14:26:48 +000047{
Tony Lindgren87bd63f2006-02-08 22:06:46 +000048 omap1_init_common_hw();
Tony Lindgren3179a012005-11-10 14:26:48 +000049 omap_init_irq();
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080050 omap_gpio_init();
Tony Lindgren3179a012005-11-10 14:26:48 +000051}
52
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080053static const int palmte_keymap[] = {
54 KEY(0, 0, KEY_F1), /* Calendar */
55 KEY(0, 1, KEY_F2), /* Contacts */
56 KEY(0, 2, KEY_F3), /* Tasks List */
57 KEY(0, 3, KEY_F4), /* Note Pad */
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080058 KEY(0, 4, KEY_POWER),
59 KEY(1, 0, KEY_LEFT),
60 KEY(1, 1, KEY_DOWN),
61 KEY(1, 2, KEY_UP),
62 KEY(1, 3, KEY_RIGHT),
Eduardo Valentinec44dfa2008-03-27 11:09:42 -040063 KEY(1, 4, KEY_ENTER),
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080064 0,
65};
66
67static struct omap_kp_platform_data palmte_kp_data = {
68 .rows = 8,
69 .cols = 8,
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -080070 .keymap = (int *) palmte_keymap,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -080071 .rep = 1,
72 .delay = 12,
73};
74
75static struct resource palmte_kp_resources[] = {
76 [0] = {
77 .start = INT_KEYBOARD,
78 .end = INT_KEYBOARD,
79 .flags = IORESOURCE_IRQ,
80 },
81};
82
83static struct platform_device palmte_kp_device = {
84 .name = "omap-keypad",
85 .id = -1,
86 .dev = {
87 .platform_data = &palmte_kp_data,
88 },
89 .num_resources = ARRAY_SIZE(palmte_kp_resources),
90 .resource = palmte_kp_resources,
91};
92
93static struct mtd_partition palmte_rom_partitions[] = {
94 /* PalmOS "Small ROM", contains the bootloader and the debugger */
95 {
96 .name = "smallrom",
97 .offset = 0,
98 .size = 0xa000,
99 .mask_flags = MTD_WRITEABLE,
100 },
101 /* PalmOS "Big ROM", a filesystem with all the OS code and data */
102 {
103 .name = "bigrom",
104 .offset = SZ_128K,
105 /*
106 * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
107 * 0x7b0000 bytes in the English-only ("enUS") version.
108 */
109 .size = 0x7b0000,
110 .mask_flags = MTD_WRITEABLE,
111 },
112};
113
114static struct flash_platform_data palmte_rom_data = {
115 .map_name = "map_rom",
116 .width = 2,
117 .parts = palmte_rom_partitions,
118 .nr_parts = ARRAY_SIZE(palmte_rom_partitions),
119};
120
121static struct resource palmte_rom_resource = {
122 .start = OMAP_CS0_PHYS,
123 .end = OMAP_CS0_PHYS + SZ_8M - 1,
124 .flags = IORESOURCE_MEM,
125};
126
127static struct platform_device palmte_rom_device = {
128 .name = "omapflash",
129 .id = -1,
130 .dev = {
131 .platform_data = &palmte_rom_data,
132 },
133 .num_resources = 1,
134 .resource = &palmte_rom_resource,
135};
136
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100137static struct platform_device palmte_lcd_device = {
138 .name = "lcd_palmte",
139 .id = -1,
140};
141
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800142static struct omap_backlight_config palmte_backlight_config = {
143 .default_intensity = 0xa0,
144};
145
146static struct platform_device palmte_backlight_device = {
147 .name = "omap-bl",
148 .id = -1,
149 .dev = {
150 .platform_data = &palmte_backlight_config,
151 },
152};
153
154static struct omap_irda_config palmte_irda_config = {
155 .transceiver_cap = IR_SIRMODE,
156 .rx_channel = OMAP_DMA_UART3_RX,
157 .tx_channel = OMAP_DMA_UART3_TX,
158 .dest_start = UART3_THR,
159 .src_start = UART3_RHR,
160 .tx_trigger = 0,
161 .rx_trigger = 0,
162};
163
164static struct resource palmte_irda_resources[] = {
165 [0] = {
166 .start = INT_UART3,
167 .end = INT_UART3,
168 .flags = IORESOURCE_IRQ,
169 },
170};
171
172static struct platform_device palmte_irda_device = {
173 .name = "omapirda",
174 .id = -1,
175 .dev = {
176 .platform_data = &palmte_irda_config,
177 },
178 .num_resources = ARRAY_SIZE(palmte_irda_resources),
179 .resource = palmte_irda_resources,
180};
181
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800182static struct platform_device *palmte_devices[] __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800183 &palmte_rom_device,
184 &palmte_kp_device,
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100185 &palmte_lcd_device,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800186 &palmte_backlight_device,
187 &palmte_irda_device,
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100188};
189
Tony Lindgren3179a012005-11-10 14:26:48 +0000190static struct omap_usb_config palmte_usb_config __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800191 .register_dev = 1, /* Mini-B only receptacle */
Tony Lindgren3179a012005-11-10 14:26:48 +0000192 .hmc_mode = 0,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800193 .pins[0] = 2,
Tony Lindgren3179a012005-11-10 14:26:48 +0000194};
195
Tony Lindgren3179a012005-11-10 14:26:48 +0000196static struct omap_lcd_config palmte_lcd_config __initdata = {
Tony Lindgren3179a012005-11-10 14:26:48 +0000197 .ctrl_name = "internal",
198};
199
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800200static struct omap_uart_config palmte_uart_config __initdata = {
201 .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
Tony Lindgren3179a012005-11-10 14:26:48 +0000202};
203
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800204#ifdef CONFIG_APM
205/*
206 * Values measured in 10 minute intervals averaged over 10 samples.
207 * May differ slightly from device to device but should be accurate
208 * enough to give basic idea of battery life left and trigger
209 * potential alerts.
210 */
211static const int palmte_battery_sample[] = {
212 2194, 2157, 2138, 2120,
213 2104, 2089, 2075, 2061,
214 2048, 2038, 2026, 2016,
215 2008, 1998, 1989, 1980,
216 1970, 1958, 1945, 1928,
217 1910, 1888, 1860, 1827,
218 1791, 1751, 1709, 1656,
219};
220
221#define INTERVAL 10
222#define BATTERY_HIGH_TRESHOLD 66
223#define BATTERY_LOW_TRESHOLD 33
224
225static void palmte_get_power_status(struct apm_power_info *info, int *battery)
226{
227 int charging, batt, hi, lo, mid;
228
David Brownell0b84b5c2008-12-10 17:35:25 -0800229 charging = !gpio_get_value(PALMTE_DC_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800230 batt = battery[0];
231 if (charging)
232 batt -= 60;
233
234 hi = ARRAY_SIZE(palmte_battery_sample);
235 lo = 0;
236
237 info->battery_flag = 0;
238 info->units = APM_UNITS_MINS;
239
240 if (batt > palmte_battery_sample[lo]) {
241 info->battery_life = 100;
242 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
243 } else if (batt <= palmte_battery_sample[hi - 1]) {
244 info->battery_life = 0;
245 info->time = 0;
246 } else {
247 while (hi > lo + 1) {
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800248 mid = (hi + lo) >> 1;
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800249 if (batt <= palmte_battery_sample[mid])
250 lo = mid;
251 else
252 hi = mid;
253 }
254
255 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
256 hi = palmte_battery_sample[lo] - batt;
257 info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
258 ARRAY_SIZE(palmte_battery_sample);
259 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
260 lo) - INTERVAL * hi / mid;
261 }
262
263 if (charging) {
264 info->ac_line_status = APM_AC_ONLINE;
265 info->battery_status = APM_BATTERY_STATUS_CHARGING;
266 info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
267 } else {
268 info->ac_line_status = APM_AC_OFFLINE;
269 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
270 info->battery_status = APM_BATTERY_STATUS_HIGH;
271 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
272 info->battery_status = APM_BATTERY_STATUS_LOW;
273 else
274 info->battery_status = APM_BATTERY_STATUS_CRITICAL;
275 }
276
277 if (info->battery_life > BATTERY_HIGH_TRESHOLD)
278 info->battery_flag |= APM_BATTERY_FLAG_HIGH;
279 else if (info->battery_life > BATTERY_LOW_TRESHOLD)
280 info->battery_flag |= APM_BATTERY_FLAG_LOW;
281 else
282 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
283}
284#else
285#define palmte_get_power_status NULL
286#endif
287
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800288static struct omap_board_config_kernel palmte_config[] __initdata = {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800289 { OMAP_TAG_USB, &palmte_usb_config },
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800290 { OMAP_TAG_LCD, &palmte_lcd_config },
291 { OMAP_TAG_UART, &palmte_uart_config },
292};
293
294static struct spi_board_info palmte_spi_info[] __initdata = {
295 {
296 .modalias = "tsc2102",
297 .bus_num = 2, /* uWire (officially) */
298 .chip_select = 0, /* As opposed to 3 */
299 .irq = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800300 .max_speed_hz = 8000000,
301 },
302};
303
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800304static void palmte_headphones_detect(void *data, int state)
305{
306 if (state) {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800307 /* Headphones connected, disable speaker */
David Brownell0b84b5c2008-12-10 17:35:25 -0800308 gpio_set_value(PALMTE_SPEAKER_GPIO, 0);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800309 printk(KERN_INFO "PM: speaker off\n");
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800310 } else {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800311 /* Headphones unplugged, re-enable speaker */
David Brownell0b84b5c2008-12-10 17:35:25 -0800312 gpio_set_value(PALMTE_SPEAKER_GPIO, 1);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800313 printk(KERN_INFO "PM: speaker on\n");
314 }
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800315}
316
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800317static void __init palmte_misc_gpio_setup(void)
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800318{
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800319 /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
Jarkko Nikulaf2d18fe2008-12-10 17:35:30 -0800320 if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800321 printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
322 return;
323 }
David Brownell40e39252008-12-10 17:35:26 -0800324 gpio_direction_input(PALMTE_PINTDAV_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800325
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800326 /* Set USB-or-DC-IN pin as input (unused) */
Jarkko Nikulaf2d18fe2008-12-10 17:35:30 -0800327 if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) {
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800328 printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
329 return;
330 }
David Brownell40e39252008-12-10 17:35:26 -0800331 gpio_direction_input(PALMTE_USB_OR_DC_GPIO);
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800332}
333
334static void __init omap_palmte_init(void)
Tony Lindgren3179a012005-11-10 14:26:48 +0000335{
336 omap_board_config = palmte_config;
337 omap_board_config_size = ARRAY_SIZE(palmte_config);
Tony Lindgren9b6553c2006-04-02 17:46:30 +0100338
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800339 platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800340
341 spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
Andrzej Zaborowskid7730cc2006-12-07 17:13:51 -0800342 palmte_misc_gpio_setup();
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800343 omap_serial_init();
Jarkko Nikula1ed16a82007-11-07 06:54:32 +0200344 omap_register_i2c_bus(1, 100, NULL, 0);
Tony Lindgren3179a012005-11-10 14:26:48 +0000345}
346
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800347static void __init omap_palmte_map_io(void)
Tony Lindgren3179a012005-11-10 14:26:48 +0000348{
Tony Lindgren87bd63f2006-02-08 22:06:46 +0000349 omap1_map_common_io();
Tony Lindgren3179a012005-11-10 14:26:48 +0000350}
351
352MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
Tony Lindgren3179a012005-11-10 14:26:48 +0000353 .phys_io = 0xfff00000,
354 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
355 .boot_params = 0x10000100,
Andrzej Zaborowskic3695012006-12-06 17:13:51 -0800356 .map_io = omap_palmte_map_io,
357 .init_irq = omap_palmte_init_irq,
358 .init_machine = omap_palmte_init,
Tony Lindgren3179a012005-11-10 14:26:48 +0000359 .timer = &omap_timer,
360MACHINE_END