xref: /openbmc/linux/arch/arm/mach-omap1/board-palmte.c (revision f15cbe6f1a4b4d9df59142fc8e4abb973302cf44)
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 <asm/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 <asm/arch/gpio.h>
37 #include <asm/arch/mux.h>
38 #include <asm/arch/usb.h>
39 #include <asm/arch/tc.h>
40 #include <asm/arch/dma.h>
41 #include <asm/arch/board.h>
42 #include <asm/arch/irda.h>
43 #include <asm/arch/keypad.h>
44 #include <asm/arch/common.h>
45 #include <asm/arch/mcbsp.h>
46 #include <asm/arch/omap-alsa.h>
47 
48 static void __init omap_palmte_init_irq(void)
49 {
50 	omap1_init_common_hw();
51 	omap_init_irq();
52 	omap_gpio_init();
53 }
54 
55 static 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 */
60 	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),
65 	KEY(1, 4, KEY_ENTER),
66 	0,
67 };
68 
69 static struct omap_kp_platform_data palmte_kp_data = {
70 	.rows	= 8,
71 	.cols	= 8,
72 	.keymap = (int *) palmte_keymap,
73 	.rep	= 1,
74 	.delay	= 12,
75 };
76 
77 static struct resource palmte_kp_resources[] = {
78 	[0]	= {
79 		.start	= INT_KEYBOARD,
80 		.end	= INT_KEYBOARD,
81 		.flags	= IORESOURCE_IRQ,
82 	},
83 };
84 
85 static 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 
95 static 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 
116 static 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 
123 static struct resource palmte_rom_resource = {
124 	.start		= OMAP_CS0_PHYS,
125 	.end		= OMAP_CS0_PHYS + SZ_8M - 1,
126 	.flags		= IORESOURCE_MEM,
127 };
128 
129 static 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 
139 static struct platform_device palmte_lcd_device = {
140 	.name		= "lcd_palmte",
141 	.id		= -1,
142 };
143 
144 static struct omap_backlight_config palmte_backlight_config = {
145 	.default_intensity	= 0xa0,
146 };
147 
148 static struct platform_device palmte_backlight_device = {
149 	.name		= "omap-bl",
150 	.id		= -1,
151 	.dev		= {
152 		.platform_data	= &palmte_backlight_config,
153 	},
154 };
155 
156 static 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 
166 static struct resource palmte_irda_resources[] = {
167 	[0]	= {
168 		.start	= INT_UART3,
169 		.end	= INT_UART3,
170 		.flags	= IORESOURCE_IRQ,
171 	},
172 };
173 
174 static 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 
184 static struct platform_device *palmte_devices[] __initdata = {
185 	&palmte_rom_device,
186 	&palmte_kp_device,
187 	&palmte_lcd_device,
188 	&palmte_backlight_device,
189 	&palmte_irda_device,
190 };
191 
192 static struct omap_usb_config palmte_usb_config __initdata = {
193 	.register_dev	= 1,	/* Mini-B only receptacle */
194 	.hmc_mode	= 0,
195 	.pins[0]	= 2,
196 };
197 
198 static struct omap_mmc_config palmte_mmc_config __initdata = {
199 	.mmc[0]		= {
200 		.enabled 	= 1,
201 		.wp_pin		= PALMTE_MMC_WP_GPIO,
202 		.power_pin	= PALMTE_MMC_POWER_GPIO,
203 		.switch_pin	= PALMTE_MMC_SWITCH_GPIO,
204 	},
205 };
206 
207 static struct omap_lcd_config palmte_lcd_config __initdata = {
208 	.ctrl_name	= "internal",
209 };
210 
211 static struct omap_uart_config palmte_uart_config __initdata = {
212 	.enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
213 };
214 
215 static 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 
222 static 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  */
240 static 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 
254 static void palmte_get_power_status(struct apm_power_info *info, int *battery)
255 {
256 	int charging, batt, hi, lo, mid;
257 
258 	charging = !omap_get_gpio_datain(PALMTE_DC_GPIO);
259 	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) {
277 			mid = (hi + lo) >> 1;
278 			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 
317 static struct omap_board_config_kernel palmte_config[] __initdata = {
318 	{ 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 
324 static 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),
330 		.max_speed_hz	= 8000000,
331 	},
332 };
333 
334 static void palmte_headphones_detect(void *data, int state)
335 {
336 	if (state) {
337 		/* Headphones connected, disable speaker */
338 		omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 0);
339 		printk(KERN_INFO "PM: speaker off\n");
340 	} else {
341 		/* Headphones unplugged, re-enable speaker */
342 		omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 1);
343 		printk(KERN_INFO "PM: speaker on\n");
344 	}
345 }
346 
347 static void __init palmte_misc_gpio_setup(void)
348 {
349 	/* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
350 	if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) {
351 		printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
352 		return;
353 	}
354 	omap_set_gpio_direction(PALMTE_PINTDAV_GPIO, 1);
355 
356 	/* Set USB-or-DC-IN pin as input (unused) */
357 	if (omap_request_gpio(PALMTE_USB_OR_DC_GPIO)) {
358 		printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
359 		return;
360 	}
361 	omap_set_gpio_direction(PALMTE_USB_OR_DC_GPIO, 1);
362 }
363 
364 static void __init omap_palmte_init(void)
365 {
366 	omap_board_config = palmte_config;
367 	omap_board_config_size = ARRAY_SIZE(palmte_config);
368 
369 	platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices));
370 
371 	spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
372 	palmte_misc_gpio_setup();
373 	omap_serial_init();
374 	omap_register_i2c_bus(1, 100, NULL, 0);
375 }
376 
377 static void __init omap_palmte_map_io(void)
378 {
379 	omap1_map_common_io();
380 }
381 
382 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
383 	.phys_io	= 0xfff00000,
384 	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
385 	.boot_params	= 0x10000100,
386 	.map_io		= omap_palmte_map_io,
387 	.init_irq	= omap_palmte_init_irq,
388 	.init_machine	= omap_palmte_init,
389 	.timer		= &omap_timer,
390 MACHINE_END
391