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  * Copyright (c) 2006 Andrzej Zaborowski  <balrog@zabor.org>
14  *
15  * 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>
22 #include <linux/input.h>
23 #include <linux/platform_device.h>
24 #include <linux/mtd/mtd.h>
25 #include <linux/mtd/partitions.h>
26 #include <linux/spi/spi.h>
27 #include <linux/interrupt.h>
28 #include <linux/apm-emulation.h>
29 
30 #include <mach/hardware.h>
31 #include <asm/mach-types.h>
32 #include <asm/mach/arch.h>
33 #include <asm/mach/map.h>
34 #include <asm/mach/flash.h>
35 
36 #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 
46 #define PALMTE_USBDETECT_GPIO	0
47 #define PALMTE_USB_OR_DC_GPIO	1
48 #define PALMTE_TSC_GPIO		4
49 #define PALMTE_PINTDAV_GPIO	6
50 #define PALMTE_MMC_WP_GPIO	8
51 #define PALMTE_MMC_POWER_GPIO	9
52 #define PALMTE_HDQ_GPIO		11
53 #define PALMTE_HEADPHONES_GPIO	14
54 #define PALMTE_SPEAKER_GPIO	15
55 #define PALMTE_DC_GPIO		OMAP_MPUIO(2)
56 #define PALMTE_MMC_SWITCH_GPIO	OMAP_MPUIO(4)
57 #define PALMTE_MMC1_GPIO	OMAP_MPUIO(6)
58 #define PALMTE_MMC2_GPIO	OMAP_MPUIO(7)
59 #define PALMTE_MMC3_GPIO	OMAP_MPUIO(11)
60 
61 static void __init omap_palmte_init_irq(void)
62 {
63 	omap1_init_common_hw();
64 	omap_init_irq();
65 	omap_gpio_init();
66 }
67 
68 static const int palmte_keymap[] = {
69 	KEY(0, 0, KEY_F1),		/* Calendar */
70 	KEY(0, 1, KEY_F2),		/* Contacts */
71 	KEY(0, 2, KEY_F3),		/* Tasks List */
72 	KEY(0, 3, KEY_F4),		/* Note Pad */
73 	KEY(0, 4, KEY_POWER),
74 	KEY(1, 0, KEY_LEFT),
75 	KEY(1, 1, KEY_DOWN),
76 	KEY(1, 2, KEY_UP),
77 	KEY(1, 3, KEY_RIGHT),
78 	KEY(1, 4, KEY_ENTER),
79 	0,
80 };
81 
82 static struct omap_kp_platform_data palmte_kp_data = {
83 	.rows	= 8,
84 	.cols	= 8,
85 	.keymap = (int *) palmte_keymap,
86 	.rep	= 1,
87 	.delay	= 12,
88 };
89 
90 static struct resource palmte_kp_resources[] = {
91 	[0]	= {
92 		.start	= INT_KEYBOARD,
93 		.end	= INT_KEYBOARD,
94 		.flags	= IORESOURCE_IRQ,
95 	},
96 };
97 
98 static struct platform_device palmte_kp_device = {
99 	.name		= "omap-keypad",
100 	.id		= -1,
101 	.dev		= {
102 		.platform_data	= &palmte_kp_data,
103 	},
104 	.num_resources	= ARRAY_SIZE(palmte_kp_resources),
105 	.resource	= palmte_kp_resources,
106 };
107 
108 static struct mtd_partition palmte_rom_partitions[] = {
109 	/* PalmOS "Small ROM", contains the bootloader and the debugger */
110 	{
111 		.name		= "smallrom",
112 		.offset		= 0,
113 		.size		= 0xa000,
114 		.mask_flags	= MTD_WRITEABLE,
115 	},
116 	/* PalmOS "Big ROM", a filesystem with all the OS code and data */
117 	{
118 		.name		= "bigrom",
119 		.offset		= SZ_128K,
120 		/*
121 		 * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
122 		 * 0x7b0000 bytes in the English-only ("enUS") version.
123 		 */
124 		.size		= 0x7b0000,
125 		.mask_flags	= MTD_WRITEABLE,
126 	},
127 };
128 
129 static struct flash_platform_data palmte_rom_data = {
130 	.map_name	= "map_rom",
131 	.width		= 2,
132 	.parts		= palmte_rom_partitions,
133 	.nr_parts	= ARRAY_SIZE(palmte_rom_partitions),
134 };
135 
136 static struct resource palmte_rom_resource = {
137 	.start		= OMAP_CS0_PHYS,
138 	.end		= OMAP_CS0_PHYS + SZ_8M - 1,
139 	.flags		= IORESOURCE_MEM,
140 };
141 
142 static struct platform_device palmte_rom_device = {
143 	.name		= "omapflash",
144 	.id		= -1,
145 	.dev		= {
146 		.platform_data	= &palmte_rom_data,
147 	},
148 	.num_resources	= 1,
149 	.resource	= &palmte_rom_resource,
150 };
151 
152 static struct platform_device palmte_lcd_device = {
153 	.name		= "lcd_palmte",
154 	.id		= -1,
155 };
156 
157 static struct omap_backlight_config palmte_backlight_config = {
158 	.default_intensity	= 0xa0,
159 };
160 
161 static struct platform_device palmte_backlight_device = {
162 	.name		= "omap-bl",
163 	.id		= -1,
164 	.dev		= {
165 		.platform_data	= &palmte_backlight_config,
166 	},
167 };
168 
169 static struct omap_irda_config palmte_irda_config = {
170 	.transceiver_cap	= IR_SIRMODE,
171 	.rx_channel		= OMAP_DMA_UART3_RX,
172 	.tx_channel		= OMAP_DMA_UART3_TX,
173 	.dest_start		= UART3_THR,
174 	.src_start		= UART3_RHR,
175 	.tx_trigger		= 0,
176 	.rx_trigger		= 0,
177 };
178 
179 static struct resource palmte_irda_resources[] = {
180 	[0]	= {
181 		.start	= INT_UART3,
182 		.end	= INT_UART3,
183 		.flags	= IORESOURCE_IRQ,
184 	},
185 };
186 
187 static struct platform_device palmte_irda_device = {
188 	.name		= "omapirda",
189 	.id		= -1,
190 	.dev		= {
191 		.platform_data	= &palmte_irda_config,
192 	},
193 	.num_resources	= ARRAY_SIZE(palmte_irda_resources),
194 	.resource	= palmte_irda_resources,
195 };
196 
197 static struct platform_device *palmte_devices[] __initdata = {
198 	&palmte_rom_device,
199 	&palmte_kp_device,
200 	&palmte_lcd_device,
201 	&palmte_backlight_device,
202 	&palmte_irda_device,
203 };
204 
205 static struct omap_usb_config palmte_usb_config __initdata = {
206 	.register_dev	= 1,	/* Mini-B only receptacle */
207 	.hmc_mode	= 0,
208 	.pins[0]	= 2,
209 };
210 
211 static struct omap_lcd_config palmte_lcd_config __initdata = {
212 	.ctrl_name	= "internal",
213 };
214 
215 static struct omap_uart_config palmte_uart_config __initdata = {
216 	.enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
217 };
218 
219 #ifdef CONFIG_APM
220 /*
221  * Values measured in 10 minute intervals averaged over 10 samples.
222  * May differ slightly from device to device but should be accurate
223  * enough to give basic idea of battery life left and trigger
224  * potential alerts.
225  */
226 static const int palmte_battery_sample[] = {
227 	2194, 2157, 2138, 2120,
228 	2104, 2089, 2075, 2061,
229 	2048, 2038, 2026, 2016,
230 	2008, 1998, 1989, 1980,
231 	1970, 1958, 1945, 1928,
232 	1910, 1888, 1860, 1827,
233 	1791, 1751, 1709, 1656,
234 };
235 
236 #define INTERVAL		10
237 #define BATTERY_HIGH_TRESHOLD	66
238 #define BATTERY_LOW_TRESHOLD	33
239 
240 static void palmte_get_power_status(struct apm_power_info *info, int *battery)
241 {
242 	int charging, batt, hi, lo, mid;
243 
244 	charging = !gpio_get_value(PALMTE_DC_GPIO);
245 	batt = battery[0];
246 	if (charging)
247 		batt -= 60;
248 
249 	hi = ARRAY_SIZE(palmte_battery_sample);
250 	lo = 0;
251 
252 	info->battery_flag = 0;
253 	info->units = APM_UNITS_MINS;
254 
255 	if (batt > palmte_battery_sample[lo]) {
256 		info->battery_life = 100;
257 		info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
258 	} else if (batt <= palmte_battery_sample[hi - 1]) {
259 		info->battery_life = 0;
260 		info->time = 0;
261 	} else {
262 		while (hi > lo + 1) {
263 			mid = (hi + lo) >> 1;
264 			if (batt <= palmte_battery_sample[mid])
265 				lo = mid;
266 			else
267 				hi = mid;
268 		}
269 
270 		mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
271 		hi = palmte_battery_sample[lo] - batt;
272 		info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
273 			ARRAY_SIZE(palmte_battery_sample);
274 		info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
275 				lo) - INTERVAL * hi / mid;
276 	}
277 
278 	if (charging) {
279 		info->ac_line_status = APM_AC_ONLINE;
280 		info->battery_status = APM_BATTERY_STATUS_CHARGING;
281 		info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
282 	} else {
283 		info->ac_line_status = APM_AC_OFFLINE;
284 		if (info->battery_life > BATTERY_HIGH_TRESHOLD)
285 			info->battery_status = APM_BATTERY_STATUS_HIGH;
286 		else if (info->battery_life > BATTERY_LOW_TRESHOLD)
287 			info->battery_status = APM_BATTERY_STATUS_LOW;
288 		else
289 			info->battery_status = APM_BATTERY_STATUS_CRITICAL;
290 	}
291 
292 	if (info->battery_life > BATTERY_HIGH_TRESHOLD)
293 		info->battery_flag |= APM_BATTERY_FLAG_HIGH;
294 	else if (info->battery_life > BATTERY_LOW_TRESHOLD)
295 		info->battery_flag |= APM_BATTERY_FLAG_LOW;
296 	else
297 		info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
298 }
299 #else
300 #define palmte_get_power_status	NULL
301 #endif
302 
303 static struct omap_board_config_kernel palmte_config[] __initdata = {
304 	{ OMAP_TAG_LCD,		&palmte_lcd_config },
305 	{ OMAP_TAG_UART,	&palmte_uart_config },
306 };
307 
308 static struct spi_board_info palmte_spi_info[] __initdata = {
309 	{
310 		.modalias	= "tsc2102",
311 		.bus_num	= 2,	/* uWire (officially) */
312 		.chip_select	= 0,	/* As opposed to 3 */
313 		.irq		= OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
314 		.max_speed_hz	= 8000000,
315 	},
316 };
317 
318 static void palmte_headphones_detect(void *data, int state)
319 {
320 	if (state) {
321 		/* Headphones connected, disable speaker */
322 		gpio_set_value(PALMTE_SPEAKER_GPIO, 0);
323 		printk(KERN_INFO "PM: speaker off\n");
324 	} else {
325 		/* Headphones unplugged, re-enable speaker */
326 		gpio_set_value(PALMTE_SPEAKER_GPIO, 1);
327 		printk(KERN_INFO "PM: speaker on\n");
328 	}
329 }
330 
331 static void __init palmte_misc_gpio_setup(void)
332 {
333 	/* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
334 	if (gpio_request(PALMTE_PINTDAV_GPIO, "TSC2102 PINTDAV") < 0) {
335 		printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
336 		return;
337 	}
338 	gpio_direction_input(PALMTE_PINTDAV_GPIO);
339 
340 	/* Set USB-or-DC-IN pin as input (unused) */
341 	if (gpio_request(PALMTE_USB_OR_DC_GPIO, "USB/DC-IN") < 0) {
342 		printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
343 		return;
344 	}
345 	gpio_direction_input(PALMTE_USB_OR_DC_GPIO);
346 }
347 
348 static void __init omap_palmte_init(void)
349 {
350 	omap_board_config = palmte_config;
351 	omap_board_config_size = ARRAY_SIZE(palmte_config);
352 
353 	platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
354 
355 	spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
356 	palmte_misc_gpio_setup();
357 	omap_serial_init();
358 	omap_usb_init(&palmte_usb_config);
359 	omap_register_i2c_bus(1, 100, NULL, 0);
360 }
361 
362 static void __init omap_palmte_map_io(void)
363 {
364 	omap1_map_common_io();
365 }
366 
367 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
368 	.phys_io	= 0xfff00000,
369 	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
370 	.boot_params	= 0x10000100,
371 	.map_io		= omap_palmte_map_io,
372 	.init_irq	= omap_palmte_init_irq,
373 	.init_machine	= omap_palmte_init,
374 	.timer		= &omap_timer,
375 MACHINE_END
376