xref: /openbmc/linux/arch/arm/mach-omap1/board-palmte.c (revision 96de0e252cedffad61b3cb5e05662c591898e69a)
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  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License version 2 as
15  * published by the Free Software Foundation.
16  */
17 
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <linux/input.h>
21 #include <linux/platform_device.h>
22 #include <linux/mtd/mtd.h>
23 #include <linux/mtd/partitions.h>
24 #include <linux/spi/spi.h>
25 #include <linux/spi/tsc2102.h>
26 #include <linux/interrupt.h>
27 
28 #include <asm/apm.h>
29 #include <asm/hardware.h>
30 #include <asm/mach-types.h>
31 #include <asm/mach/arch.h>
32 #include <asm/mach/map.h>
33 #include <asm/mach/flash.h>
34 
35 #include <asm/arch/gpio.h>
36 #include <asm/arch/mux.h>
37 #include <asm/arch/usb.h>
38 #include <asm/arch/tc.h>
39 #include <asm/arch/dma.h>
40 #include <asm/arch/board.h>
41 #include <asm/arch/irda.h>
42 #include <asm/arch/keypad.h>
43 #include <asm/arch/common.h>
44 #include <asm/arch/mcbsp.h>
45 #include <asm/arch/omap-alsa.h>
46 
47 static void __init omap_palmte_init_irq(void)
48 {
49 	omap1_init_common_hw();
50 	omap_init_irq();
51 	omap_gpio_init();
52 }
53 
54 static int palmte_keymap[] = {
55 	KEY(0, 0, KEY_F1),
56 	KEY(0, 1, KEY_F2),
57 	KEY(0, 2, KEY_F3),
58 	KEY(0, 3, KEY_F4),
59 	KEY(0, 4, KEY_POWER),
60 	KEY(1, 0, KEY_LEFT),
61 	KEY(1, 1, KEY_DOWN),
62 	KEY(1, 2, KEY_UP),
63 	KEY(1, 3, KEY_RIGHT),
64 	KEY(1, 4, KEY_CENTER),
65 	0,
66 };
67 
68 static struct omap_kp_platform_data palmte_kp_data = {
69 	.rows	= 8,
70 	.cols	= 8,
71 	.keymap = palmte_keymap,
72 	.rep	= 1,
73 	.delay	= 12,
74 };
75 
76 static struct resource palmte_kp_resources[] = {
77 	[0]	= {
78 		.start	= INT_KEYBOARD,
79 		.end	= INT_KEYBOARD,
80 		.flags	= IORESOURCE_IRQ,
81 	},
82 };
83 
84 static struct platform_device palmte_kp_device = {
85 	.name		= "omap-keypad",
86 	.id		= -1,
87 	.dev		= {
88 		.platform_data	= &palmte_kp_data,
89 	},
90 	.num_resources	= ARRAY_SIZE(palmte_kp_resources),
91 	.resource	= palmte_kp_resources,
92 };
93 
94 static struct mtd_partition palmte_rom_partitions[] = {
95 	/* PalmOS "Small ROM", contains the bootloader and the debugger */
96 	{
97 		.name		= "smallrom",
98 		.offset		= 0,
99 		.size		= 0xa000,
100 		.mask_flags	= MTD_WRITEABLE,
101 	},
102 	/* PalmOS "Big ROM", a filesystem with all the OS code and data */
103 	{
104 		.name		= "bigrom",
105 		.offset		= SZ_128K,
106 		/*
107 		 * 0x5f0000 bytes big in the multi-language ("EFIGS") version,
108 		 * 0x7b0000 bytes in the English-only ("enUS") version.
109 		 */
110 		.size		= 0x7b0000,
111 		.mask_flags	= MTD_WRITEABLE,
112 	},
113 };
114 
115 static struct flash_platform_data palmte_rom_data = {
116 	.map_name	= "map_rom",
117 	.width		= 2,
118 	.parts		= palmte_rom_partitions,
119 	.nr_parts	= ARRAY_SIZE(palmte_rom_partitions),
120 };
121 
122 static struct resource palmte_rom_resource = {
123 	.start		= OMAP_CS0_PHYS,
124 	.end		= OMAP_CS0_PHYS + SZ_8M - 1,
125 	.flags		= IORESOURCE_MEM,
126 };
127 
128 static struct platform_device palmte_rom_device = {
129 	.name		= "omapflash",
130 	.id		= -1,
131 	.dev		= {
132 		.platform_data	= &palmte_rom_data,
133 	},
134 	.num_resources	= 1,
135 	.resource	= &palmte_rom_resource,
136 };
137 
138 static struct platform_device palmte_lcd_device = {
139 	.name		= "lcd_palmte",
140 	.id		= -1,
141 };
142 
143 static struct omap_backlight_config palmte_backlight_config = {
144 	.default_intensity	= 0xa0,
145 };
146 
147 static struct platform_device palmte_backlight_device = {
148 	.name		= "omap-bl",
149 	.id		= -1,
150 	.dev		= {
151 		.platform_data	= &palmte_backlight_config,
152 	},
153 };
154 
155 static struct omap_irda_config palmte_irda_config = {
156 	.transceiver_cap	= IR_SIRMODE,
157 	.rx_channel		= OMAP_DMA_UART3_RX,
158 	.tx_channel		= OMAP_DMA_UART3_TX,
159 	.dest_start		= UART3_THR,
160 	.src_start		= UART3_RHR,
161 	.tx_trigger		= 0,
162 	.rx_trigger		= 0,
163 };
164 
165 static struct resource palmte_irda_resources[] = {
166 	[0]	= {
167 		.start	= INT_UART3,
168 		.end	= INT_UART3,
169 		.flags	= IORESOURCE_IRQ,
170 	},
171 };
172 
173 static struct platform_device palmte_irda_device = {
174 	.name		= "omapirda",
175 	.id		= -1,
176 	.dev		= {
177 		.platform_data	= &palmte_irda_config,
178 	},
179 	.num_resources	= ARRAY_SIZE(palmte_irda_resources),
180 	.resource	= palmte_irda_resources,
181 };
182 
183 static struct platform_device *devices[] __initdata = {
184 	&palmte_rom_device,
185 	&palmte_kp_device,
186 	&palmte_lcd_device,
187 	&palmte_backlight_device,
188 	&palmte_irda_device,
189 };
190 
191 static struct omap_usb_config palmte_usb_config __initdata = {
192 	.register_dev	= 1,	/* Mini-B only receptacle */
193 	.hmc_mode	= 0,
194 	.pins[0]	= 2,
195 };
196 
197 static struct omap_mmc_config palmte_mmc_config __initdata = {
198 	.mmc[0]		= {
199 		.enabled 	= 1,
200 		.wp_pin		= PALMTE_MMC_WP_GPIO,
201 		.power_pin	= PALMTE_MMC_POWER_GPIO,
202 		.switch_pin	= PALMTE_MMC_SWITCH_GPIO,
203 	},
204 };
205 
206 static struct omap_lcd_config palmte_lcd_config __initdata = {
207 	.ctrl_name	= "internal",
208 };
209 
210 static struct omap_uart_config palmte_uart_config __initdata = {
211 	.enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
212 };
213 
214 static struct omap_mcbsp_reg_cfg palmte_mcbsp1_regs = {
215 	.spcr2	= FRST | GRST | XRST | XINTM(3),
216 	.xcr2	= XDATDLY(1) | XFIG,
217 	.xcr1	= XWDLEN1(OMAP_MCBSP_WORD_32),
218 	.pcr0	= SCLKME | FSXP | CLKXP,
219 };
220 
221 static struct omap_alsa_codec_config palmte_alsa_config = {
222 	.name			= "TSC2102 audio",
223 	.mcbsp_regs_alsa	= &palmte_mcbsp1_regs,
224 	.codec_configure_dev	= NULL,	/* tsc2102_configure, */
225 	.codec_set_samplerate	= NULL,	/* tsc2102_set_samplerate, */
226 	.codec_clock_setup	= NULL,	/* tsc2102_clock_setup, */
227 	.codec_clock_on		= NULL,	/* tsc2102_clock_on, */
228 	.codec_clock_off	= NULL,	/* tsc2102_clock_off, */
229 	.get_default_samplerate	= NULL,	/* tsc2102_get_default_samplerate, */
230 };
231 
232 #ifdef CONFIG_APM
233 /*
234  * Values measured in 10 minute intervals averaged over 10 samples.
235  * May differ slightly from device to device but should be accurate
236  * enough to give basic idea of battery life left and trigger
237  * potential alerts.
238  */
239 static const int palmte_battery_sample[] = {
240 	2194, 2157, 2138, 2120,
241 	2104, 2089, 2075, 2061,
242 	2048, 2038, 2026, 2016,
243 	2008, 1998, 1989, 1980,
244 	1970, 1958, 1945, 1928,
245 	1910, 1888, 1860, 1827,
246 	1791, 1751, 1709, 1656,
247 };
248 
249 #define INTERVAL		10
250 #define BATTERY_HIGH_TRESHOLD	66
251 #define BATTERY_LOW_TRESHOLD	33
252 
253 static void palmte_get_power_status(struct apm_power_info *info, int *battery)
254 {
255 	int charging, batt, hi, lo, mid;
256 
257 	charging = !omap_get_gpio_datain(PALMTE_DC_GPIO);
258 	batt = battery[0];
259 	if (charging)
260 		batt -= 60;
261 
262 	hi = ARRAY_SIZE(palmte_battery_sample);
263 	lo = 0;
264 
265 	info->battery_flag = 0;
266 	info->units = APM_UNITS_MINS;
267 
268 	if (batt > palmte_battery_sample[lo]) {
269 		info->battery_life = 100;
270 		info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample);
271 	} else if (batt <= palmte_battery_sample[hi - 1]) {
272 		info->battery_life = 0;
273 		info->time = 0;
274 	} else {
275 		while (hi > lo + 1) {
276 			mid = (hi + lo) >> 2;
277 			if (batt <= palmte_battery_sample[mid])
278 				lo = mid;
279 			else
280 				hi = mid;
281 		}
282 
283 		mid = palmte_battery_sample[lo] - palmte_battery_sample[hi];
284 		hi = palmte_battery_sample[lo] - batt;
285 		info->battery_life = 100 - (100 * lo + 100 * hi / mid) /
286 			ARRAY_SIZE(palmte_battery_sample);
287 		info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) -
288 				lo) - INTERVAL * hi / mid;
289 	}
290 
291 	if (charging) {
292 		info->ac_line_status = APM_AC_ONLINE;
293 		info->battery_status = APM_BATTERY_STATUS_CHARGING;
294 		info->battery_flag |= APM_BATTERY_FLAG_CHARGING;
295 	} else {
296 		info->ac_line_status = APM_AC_OFFLINE;
297 		if (info->battery_life > BATTERY_HIGH_TRESHOLD)
298 			info->battery_status = APM_BATTERY_STATUS_HIGH;
299 		else if (info->battery_life > BATTERY_LOW_TRESHOLD)
300 			info->battery_status = APM_BATTERY_STATUS_LOW;
301 		else
302 			info->battery_status = APM_BATTERY_STATUS_CRITICAL;
303 	}
304 
305 	if (info->battery_life > BATTERY_HIGH_TRESHOLD)
306 		info->battery_flag |= APM_BATTERY_FLAG_HIGH;
307 	else if (info->battery_life > BATTERY_LOW_TRESHOLD)
308 		info->battery_flag |= APM_BATTERY_FLAG_LOW;
309 	else
310 		info->battery_flag |= APM_BATTERY_FLAG_CRITICAL;
311 }
312 #else
313 #define palmte_get_power_status	NULL
314 #endif
315 
316 static struct tsc2102_config palmte_tsc2102_config = {
317 	.use_internal	= 0,
318 	.monitor	= TSC_BAT1 | TSC_AUX | TSC_TEMP,
319 	.temp_at25c	= { 2200, 2615 },
320 	.apm_report	= palmte_get_power_status,
321 	.alsa_config	= &palmte_alsa_config,
322 };
323 
324 static struct omap_board_config_kernel palmte_config[] = {
325 	{ OMAP_TAG_USB,		&palmte_usb_config },
326 	{ OMAP_TAG_MMC,		&palmte_mmc_config },
327 	{ OMAP_TAG_LCD,		&palmte_lcd_config },
328 	{ OMAP_TAG_UART,	&palmte_uart_config },
329 };
330 
331 static struct spi_board_info palmte_spi_info[] __initdata = {
332 	{
333 		.modalias	= "tsc2102",
334 		.bus_num	= 2,	/* uWire (officially) */
335 		.chip_select	= 0,	/* As opposed to 3 */
336 		.irq		= OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO),
337 		.platform_data	= &palmte_tsc2102_config,
338 		.max_speed_hz	= 8000000,
339 	},
340 };
341 
342 /* Periodically check for changes on important input pins */
343 struct timer_list palmte_pin_timer;
344 int prev_power, prev_headphones;
345 
346 static void palmte_pin_handler(unsigned long data) {
347 	int power, headphones;
348 
349 	power = !omap_get_gpio_datain(PALMTE_DC_GPIO);
350 	headphones = omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO);
351 
352 	if (power && !prev_power)
353 		printk(KERN_INFO "PM: cable connected\n");
354 	else if (!power && prev_power)
355 		printk(KERN_INFO "PM: cable disconnected\n");
356 
357 	if (headphones && !prev_headphones) {
358 		/* Headphones connected, disable speaker */
359 		omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 0);
360 		printk(KERN_INFO "PM: speaker off\n");
361 	} else if (!headphones && prev_headphones) {
362 		/* Headphones unplugged, re-enable speaker */
363 		omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 1);
364 		printk(KERN_INFO "PM: speaker on\n");
365 	}
366 
367 	prev_power = power;
368 	prev_headphones = headphones;
369 	mod_timer(&palmte_pin_timer, jiffies + msecs_to_jiffies(500));
370 }
371 
372 static void __init palmte_gpio_setup(void)
373 {
374 	/* Set TSC2102 PINTDAV pin as input */
375 	if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) {
376 		printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n");
377 		return;
378 	}
379 	omap_set_gpio_direction(PALMTE_PINTDAV_GPIO, 1);
380 
381 	/* Monitor cable-connected signals */
382 	if (omap_request_gpio(PALMTE_DC_GPIO) ||
383 			omap_request_gpio(PALMTE_USB_OR_DC_GPIO) ||
384 			omap_request_gpio(PALMTE_USBDETECT_GPIO)) {
385 		printk(KERN_ERR "Could not reserve cable signal GPIO!\n");
386 		return;
387 	}
388 	omap_set_gpio_direction(PALMTE_DC_GPIO, 1);
389 	omap_set_gpio_direction(PALMTE_USB_OR_DC_GPIO, 1);
390 	omap_set_gpio_direction(PALMTE_USBDETECT_GPIO, 1);
391 
392 	/* Set speaker-enable pin as output */
393 	if (omap_request_gpio(PALMTE_SPEAKER_GPIO)) {
394 		printk(KERN_ERR "Could not reserve speaker GPIO!\n");
395 		return;
396 	}
397 	omap_set_gpio_direction(PALMTE_SPEAKER_GPIO, 0);
398 
399 	/* Monitor the headphones-connected signal */
400 	if (omap_request_gpio(PALMTE_HEADPHONES_GPIO)) {
401 		printk(KERN_ERR "Could not reserve headphones signal GPIO!\n");
402 		return;
403 	}
404 	omap_set_gpio_direction(PALMTE_HEADPHONES_GPIO, 1);
405 
406 	prev_power = omap_get_gpio_datain(PALMTE_DC_GPIO);
407 	prev_headphones = !omap_get_gpio_datain(PALMTE_HEADPHONES_GPIO);
408 	setup_timer(&palmte_pin_timer, palmte_pin_handler, 0);
409 	palmte_pin_handler(0);
410 }
411 
412 static void __init omap_palmte_init(void)
413 {
414 	omap_board_config = palmte_config;
415 	omap_board_config_size = ARRAY_SIZE(palmte_config);
416 
417 	platform_add_devices(devices, ARRAY_SIZE(devices));
418 
419 	spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info));
420 
421 	omap_serial_init();
422 	palmte_gpio_setup();
423 }
424 
425 static void __init omap_palmte_map_io(void)
426 {
427 	omap1_map_common_io();
428 }
429 
430 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
431 	.phys_io	= 0xfff00000,
432 	.io_pg_offst	= ((0xfef00000) >> 18) & 0xfffc,
433 	.boot_params	= 0x10000100,
434 	.map_io		= omap_palmte_map_io,
435 	.init_irq	= omap_palmte_init_irq,
436 	.init_machine	= omap_palmte_init,
437 	.timer		= &omap_timer,
438 MACHINE_END
439