xref: /openbmc/linux/arch/arm/mach-sa1100/h3600.c (revision 766f0378)
1 /*
2  * Hardware definitions for Compaq iPAQ H3xxx Handheld Computers
3  *
4  * Copyright 2000,1 Compaq Computer Corporation.
5  *
6  * Use consistent with the GNU GPL is permitted,
7  * provided that this copyright notice is
8  * preserved in its entirety in all copies and derived works.
9  *
10  * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
11  * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
12  * FITNESS FOR ANY PARTICULAR PURPOSE.
13  *
14  * Author: Jamey Hicks.
15  *
16  * History:
17  *
18  * 2001-10-??	Andrew Christian   Added support for iPAQ H3800
19  *				   and abstracted EGPIO interface.
20  *
21  */
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/kernel.h>
25 #include <linux/tty.h>
26 #include <linux/pm.h>
27 #include <linux/device.h>
28 #include <linux/mfd/htc-egpio.h>
29 #include <linux/mtd/mtd.h>
30 #include <linux/mtd/partitions.h>
31 #include <linux/serial_core.h>
32 #include <linux/gpio.h>
33 #include <linux/platform_device.h>
34 
35 #include <asm/irq.h>
36 #include <mach/hardware.h>
37 #include <asm/mach-types.h>
38 #include <asm/setup.h>
39 
40 #include <asm/mach/irq.h>
41 #include <asm/mach/arch.h>
42 #include <asm/mach/flash.h>
43 #include <asm/mach/irda.h>
44 #include <asm/mach/map.h>
45 #include <asm/mach/serial_sa1100.h>
46 
47 #include <mach/h3600.h>
48 #include <mach/h3600_gpio.h>
49 
50 #include "generic.h"
51 
52 struct gpio_default_state {
53 	int gpio;
54 	int mode;
55 	const char *name;
56 };
57 
58 #define GPIO_MODE_IN	-1
59 #define GPIO_MODE_OUT0	0
60 #define GPIO_MODE_OUT1	1
61 
62 static void h3xxx_init_gpio(struct gpio_default_state *s, size_t n)
63 {
64 	while (n--) {
65 		const char *name = s->name;
66 		int err;
67 
68 		if (!name)
69 			name = "[init]";
70 		err = gpio_request(s->gpio, name);
71 		if (err) {
72 			printk(KERN_ERR "gpio%u: unable to request: %d\n",
73 				s->gpio, err);
74 			continue;
75 		}
76 		if (s->mode >= 0) {
77 			err = gpio_direction_output(s->gpio, s->mode);
78 		} else {
79 			err = gpio_direction_input(s->gpio);
80 		}
81 		if (err) {
82 			printk(KERN_ERR "gpio%u: unable to set direction: %d\n",
83 				s->gpio, err);
84 			continue;
85 		}
86 		if (!s->name)
87 			gpio_free(s->gpio);
88 		s++;
89 	}
90 }
91 
92 
93 /*
94  * H3xxx flash support
95  */
96 static struct mtd_partition h3xxx_partitions[] = {
97 	{
98 		.name		= "H3XXX boot firmware",
99 		.size		= 0x00040000,
100 		.offset		= 0,
101 		.mask_flags	= MTD_WRITEABLE,  /* force read-only */
102 	}, {
103 		.name		= "H3XXX rootfs",
104 		.size		= MTDPART_SIZ_FULL,
105 		.offset		= 0x00040000,
106 	}
107 };
108 
109 static void h3xxx_set_vpp(int vpp)
110 {
111 	gpio_set_value(H3XXX_EGPIO_VPP_ON, vpp);
112 }
113 
114 static int h3xxx_flash_init(void)
115 {
116 	int err = gpio_request(H3XXX_EGPIO_VPP_ON, "Flash Vpp");
117 	if (err)
118 		return err;
119 
120 	err = gpio_direction_output(H3XXX_EGPIO_VPP_ON, 0);
121 	if (err)
122 		gpio_free(H3XXX_EGPIO_VPP_ON);
123 
124 	return err;
125 }
126 
127 static void h3xxx_flash_exit(void)
128 {
129 	gpio_free(H3XXX_EGPIO_VPP_ON);
130 }
131 
132 static struct flash_platform_data h3xxx_flash_data = {
133 	.map_name	= "cfi_probe",
134 	.set_vpp	= h3xxx_set_vpp,
135 	.init		= h3xxx_flash_init,
136 	.exit		= h3xxx_flash_exit,
137 	.parts		= h3xxx_partitions,
138 	.nr_parts	= ARRAY_SIZE(h3xxx_partitions),
139 };
140 
141 static struct resource h3xxx_flash_resource = {
142 	.start		= SA1100_CS0_PHYS,
143 	.end		= SA1100_CS0_PHYS + SZ_32M - 1,
144 	.flags		= IORESOURCE_MEM,
145 };
146 
147 
148 /*
149  * H3xxx uart support
150  */
151 static void h3xxx_uart_set_mctrl(struct uart_port *port, u_int mctrl)
152 {
153 	if (port->mapbase == _Ser3UTCR0) {
154 		gpio_set_value(H3XXX_GPIO_COM_RTS, !(mctrl & TIOCM_RTS));
155 	}
156 }
157 
158 static u_int h3xxx_uart_get_mctrl(struct uart_port *port)
159 {
160 	u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
161 
162 	if (port->mapbase == _Ser3UTCR0) {
163 		/*
164 		 * DCD and CTS bits are inverted in GPLR by RS232 transceiver
165 		 */
166 		if (gpio_get_value(H3XXX_GPIO_COM_DCD))
167 			ret &= ~TIOCM_CD;
168 		if (gpio_get_value(H3XXX_GPIO_COM_CTS))
169 			ret &= ~TIOCM_CTS;
170 	}
171 
172 	return ret;
173 }
174 
175 static void h3xxx_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
176 {
177 	if (port->mapbase == _Ser3UTCR0)
178 		if (!gpio_request(H3XXX_EGPIO_RS232_ON, "RS232 transceiver")) {
179 			gpio_direction_output(H3XXX_EGPIO_RS232_ON, !state);
180 			gpio_free(H3XXX_EGPIO_RS232_ON);
181 		}
182 }
183 
184 /*
185  * Enable/Disable wake up events for this serial port.
186  * Obviously, we only support this on the normal COM port.
187  */
188 static int h3xxx_uart_set_wake(struct uart_port *port, u_int enable)
189 {
190 	int err = -EINVAL;
191 
192 	if (port->mapbase == _Ser3UTCR0) {
193 		if (enable)
194 			PWER |= PWER_GPIO23 | PWER_GPIO25; /* DCD and CTS */
195 		else
196 			PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
197 		err = 0;
198 	}
199 	return err;
200 }
201 
202 static struct sa1100_port_fns h3xxx_port_fns __initdata = {
203 	.set_mctrl	= h3xxx_uart_set_mctrl,
204 	.get_mctrl	= h3xxx_uart_get_mctrl,
205 	.pm		= h3xxx_uart_pm,
206 	.set_wake	= h3xxx_uart_set_wake,
207 };
208 
209 /*
210  * EGPIO
211  */
212 
213 static struct resource egpio_resources[] = {
214 	[0] = {
215 		.start	= H3600_EGPIO_PHYS,
216 		.end	= H3600_EGPIO_PHYS + 0x4 - 1,
217 		.flags	= IORESOURCE_MEM,
218 	},
219 };
220 
221 static struct htc_egpio_chip egpio_chips[] = {
222 	[0] = {
223 		.reg_start	= 0,
224 		.gpio_base	= H3XXX_EGPIO_BASE,
225 		.num_gpios	= 16,
226 		.direction	= HTC_EGPIO_OUTPUT,
227 		.initial_values	= 0x0080, /* H3XXX_EGPIO_RS232_ON */
228 	},
229 };
230 
231 static struct htc_egpio_platform_data egpio_info = {
232 	.reg_width	= 16,
233 	.bus_width	= 16,
234 	.chip		= egpio_chips,
235 	.num_chips	= ARRAY_SIZE(egpio_chips),
236 };
237 
238 static struct platform_device h3xxx_egpio = {
239 	.name		= "htc-egpio",
240 	.id		= -1,
241 	.resource	= egpio_resources,
242 	.num_resources	= ARRAY_SIZE(egpio_resources),
243 	.dev		= {
244 		.platform_data = &egpio_info,
245 	},
246 };
247 
248 static struct platform_device *h3xxx_devices[] = {
249 	&h3xxx_egpio,
250 };
251 
252 static void __init h3xxx_mach_init(void)
253 {
254 	sa1100_register_uart_fns(&h3xxx_port_fns);
255 	sa11x0_register_mtd(&h3xxx_flash_data, &h3xxx_flash_resource, 1);
256 	platform_add_devices(h3xxx_devices, ARRAY_SIZE(h3xxx_devices));
257 }
258 
259 static struct map_desc h3600_io_desc[] __initdata = {
260   	{	/* static memory bank 2  CS#2 */
261 		.virtual	=  H3600_BANK_2_VIRT,
262 		.pfn		= __phys_to_pfn(SA1100_CS2_PHYS),
263 		.length		= 0x02800000,
264 		.type		= MT_DEVICE
265 	}, {	/* static memory bank 4  CS#4 */
266 		.virtual	=  H3600_BANK_4_VIRT,
267 		.pfn		= __phys_to_pfn(SA1100_CS4_PHYS),
268 		.length		= 0x00800000,
269 		.type		= MT_DEVICE
270 	}, {	/* EGPIO 0		CS#5 */
271 		.virtual	=  H3600_EGPIO_VIRT,
272 		.pfn		= __phys_to_pfn(H3600_EGPIO_PHYS),
273 		.length		= 0x01000000,
274 		.type		= MT_DEVICE
275 	}
276 };
277 
278 /*
279  * Common map_io initialization
280  */
281 
282 static void __init h3xxx_map_io(void)
283 {
284 	sa1100_map_io();
285 	iotable_init(h3600_io_desc, ARRAY_SIZE(h3600_io_desc));
286 
287 	sa1100_register_uart(0, 3); /* Common serial port */
288 //	sa1100_register_uart(1, 1); /* Microcontroller on 3100/3600 */
289 
290 	/* Ensure those pins are outputs and driving low  */
291 	PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
292 	PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
293 
294 	/* Configure suspend conditions */
295 	PGSR = 0;
296 	PWER = PWER_GPIO0;
297 	PCFR = PCFR_OPDE;
298 	PSDR = 0;
299 
300 }
301 
302 /************************* H3100 *************************/
303 
304 #ifdef CONFIG_SA1100_H3100
305 
306 #define H3100_DIRECT_EGPIO (GPIO_H3100_BT_ON	  \
307 			  | GPIO_H3100_GPIO3	  \
308 			  | GPIO_H3100_QMUTE	  \
309 			  | GPIO_H3100_LCD_3V_ON  \
310 			  | GPIO_H3100_AUD_ON	  \
311 			  | GPIO_H3100_AUD_PWR_ON \
312 			  | GPIO_H3100_IR_ON	  \
313 			  | GPIO_H3100_IR_FSEL)
314 /*
315  * helper for sa1100fb
316  */
317 static void h3100_lcd_power(int enable)
318 {
319 	if (!gpio_request(H3XXX_EGPIO_LCD_ON, "LCD ON")) {
320 		gpio_set_value(H3100_GPIO_LCD_3V_ON, enable);
321 		gpio_direction_output(H3XXX_EGPIO_LCD_ON, enable);
322 		gpio_free(H3XXX_EGPIO_LCD_ON);
323 	}
324 }
325 
326 
327 static void __init h3100_map_io(void)
328 {
329 	h3xxx_map_io();
330 
331 	sa1100fb_lcd_power = h3100_lcd_power;
332 
333 	/* Initialize h3100-specific values here */
334 	GPCR = 0x0fffffff;	 /* All outputs are set low by default */
335 	GPDR = GPIO_H3600_L3_CLOCK |
336 	       GPIO_H3600_L3_MODE  | GPIO_H3600_L3_DATA  |
337 	       GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0 |
338 	       H3100_DIRECT_EGPIO;
339 
340 	/* Older bootldrs put GPIO2-9 in alternate mode on the
341 	   assumption that they are used for video */
342 	GAFR &= ~H3100_DIRECT_EGPIO;
343 }
344 
345 /*
346  * This turns the IRDA power on or off on the Compaq H3100
347  */
348 static int h3100_irda_set_power(struct device *dev, unsigned int state)
349 {
350 	gpio_set_value(H3100_GPIO_IR_ON, state);
351 	return 0;
352 }
353 
354 static void h3100_irda_set_speed(struct device *dev, unsigned int speed)
355 {
356 	gpio_set_value(H3100_GPIO_IR_FSEL, !(speed < 4000000));
357 }
358 
359 static struct irda_platform_data h3100_irda_data = {
360 	.set_power	= h3100_irda_set_power,
361 	.set_speed	= h3100_irda_set_speed,
362 };
363 
364 static struct gpio_default_state h3100_default_gpio[] = {
365 	{ H3100_GPIO_IR_ON,	GPIO_MODE_OUT0, "IrDA power" },
366 	{ H3100_GPIO_IR_FSEL,	GPIO_MODE_OUT0, "IrDA fsel" },
367 	{ H3XXX_GPIO_COM_DCD,	GPIO_MODE_IN,	"COM DCD" },
368 	{ H3XXX_GPIO_COM_CTS,	GPIO_MODE_IN,	"COM CTS" },
369 	{ H3XXX_GPIO_COM_RTS,	GPIO_MODE_OUT0,	"COM RTS" },
370 	{ H3100_GPIO_LCD_3V_ON,	GPIO_MODE_OUT0,	"LCD 3v" },
371 };
372 
373 static void __init h3100_mach_init(void)
374 {
375 	h3xxx_init_gpio(h3100_default_gpio, ARRAY_SIZE(h3100_default_gpio));
376 	h3xxx_mach_init();
377 	sa11x0_register_irda(&h3100_irda_data);
378 }
379 
380 MACHINE_START(H3100, "Compaq iPAQ H3100")
381 	.phys_io	= 0x80000000,
382 	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
383 	.boot_params	= 0xc0000100,
384 	.map_io		= h3100_map_io,
385 	.init_irq	= sa1100_init_irq,
386 	.timer		= &sa1100_timer,
387 	.init_machine	= h3100_mach_init,
388 MACHINE_END
389 
390 #endif /* CONFIG_SA1100_H3100 */
391 
392 /************************* H3600 *************************/
393 
394 #ifdef CONFIG_SA1100_H3600
395 
396 /*
397  * helper for sa1100fb
398  */
399 static void h3600_lcd_power(int enable)
400 {
401 	if (gpio_request(H3XXX_EGPIO_LCD_ON, "LCD power"))
402 		goto err1;
403 	if (gpio_request(H3600_EGPIO_LCD_PCI, "LCD control"))
404 		goto err2;
405 	if (gpio_request(H3600_EGPIO_LCD_5V_ON, "LCD 5v"))
406 		goto err3;
407 	if (gpio_request(H3600_EGPIO_LVDD_ON, "LCD 9v/-6.5v"))
408 		goto err4;
409 
410 	gpio_direction_output(H3XXX_EGPIO_LCD_ON, enable);
411 	gpio_direction_output(H3600_EGPIO_LCD_PCI, enable);
412 	gpio_direction_output(H3600_EGPIO_LCD_5V_ON, enable);
413 	gpio_direction_output(H3600_EGPIO_LVDD_ON, enable);
414 
415 	gpio_free(H3600_EGPIO_LVDD_ON);
416 err4:	gpio_free(H3600_EGPIO_LCD_5V_ON);
417 err3:	gpio_free(H3600_EGPIO_LCD_PCI);
418 err2:	gpio_free(H3XXX_EGPIO_LCD_ON);
419 err1:	return;
420 }
421 
422 static void __init h3600_map_io(void)
423 {
424 	h3xxx_map_io();
425 
426 	sa1100fb_lcd_power = h3600_lcd_power;
427 
428 	/* Initialize h3600-specific values here */
429 
430 	GPCR = 0x0fffffff;	 /* All outputs are set low by default */
431 	GPDR = GPIO_H3600_L3_CLOCK |
432 	       GPIO_H3600_L3_MODE  | GPIO_H3600_L3_DATA  |
433 	       GPIO_H3600_CLK_SET1 | GPIO_H3600_CLK_SET0;
434 }
435 
436 /*
437  * This turns the IRDA power on or off on the Compaq H3600
438  */
439 static int h3600_irda_set_power(struct device *dev, unsigned int state)
440 {
441 	gpio_set_value(H3600_EGPIO_IR_ON, state);
442 	return 0;
443 }
444 
445 static void h3600_irda_set_speed(struct device *dev, unsigned int speed)
446 {
447 	gpio_set_value(H3600_EGPIO_IR_FSEL, !(speed < 4000000));
448 }
449 
450 static int h3600_irda_startup(struct device *dev)
451 {
452 	int err = gpio_request(H3600_EGPIO_IR_ON, "IrDA power");
453 	if (err)
454 		goto err1;
455 	err = gpio_direction_output(H3600_EGPIO_IR_ON, 0);
456 	if (err)
457 		goto err2;
458 	err = gpio_request(H3600_EGPIO_IR_FSEL, "IrDA fsel");
459 	if (err)
460 		goto err2;
461 	err = gpio_direction_output(H3600_EGPIO_IR_FSEL, 0);
462 	if (err)
463 		goto err3;
464 	return 0;
465 
466 err3:	gpio_free(H3600_EGPIO_IR_FSEL);
467 err2:	gpio_free(H3600_EGPIO_IR_ON);
468 err1:	return err;
469 }
470 
471 static void h3600_irda_shutdown(struct device *dev)
472 {
473 	gpio_free(H3600_EGPIO_IR_ON);
474 	gpio_free(H3600_EGPIO_IR_FSEL);
475 }
476 
477 static struct irda_platform_data h3600_irda_data = {
478 	.set_power	= h3600_irda_set_power,
479 	.set_speed	= h3600_irda_set_speed,
480 	.startup	= h3600_irda_startup,
481 	.shutdown	= h3600_irda_shutdown,
482 };
483 
484 static struct gpio_default_state h3600_default_gpio[] = {
485 	{ H3XXX_GPIO_COM_DCD,	GPIO_MODE_IN,	"COM DCD" },
486 	{ H3XXX_GPIO_COM_CTS,	GPIO_MODE_IN,	"COM CTS" },
487 	{ H3XXX_GPIO_COM_RTS,	GPIO_MODE_OUT0,	"COM RTS" },
488 };
489 
490 static void __init h3600_mach_init(void)
491 {
492 	h3xxx_init_gpio(h3600_default_gpio, ARRAY_SIZE(h3600_default_gpio));
493 	h3xxx_mach_init();
494 	sa11x0_register_irda(&h3600_irda_data);
495 }
496 
497 MACHINE_START(H3600, "Compaq iPAQ H3600")
498 	.phys_io	= 0x80000000,
499 	.io_pg_offst	= ((0xf8000000) >> 18) & 0xfffc,
500 	.boot_params	= 0xc0000100,
501 	.map_io		= h3600_map_io,
502 	.init_irq	= sa1100_init_irq,
503 	.timer		= &sa1100_timer,
504 	.init_machine	= h3600_mach_init,
505 MACHINE_END
506 
507 #endif /* CONFIG_SA1100_H3600 */
508 
509