sync hh.org
[hh.org.git] / arch / arm / mach-sa1100 / ipaq.c
blobc9ef6e89a43816cd7d2c136c656e2feea7f13234
1 /*
2 * Hardware definitions for SA1100-based HP iPAQ Handheld Computers
4 * Copyright 2000-2002 Compaq Computer Corporation.
5 * Copyright 2002-2003 Hewlett-Packard Company.
7 * Use consistent with the GNU GPL is permitted,
8 * provided that this copyright notice is
9 * preserved in its entirety in all copies and derived works.
11 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
12 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
13 * FITNESS FOR ANY PARTICULAR PURPOSE.
15 * Author: Jamey Hicks.
17 * History:
19 * 2001-10-?? Andrew Christian Added support for iPAQ H3800
20 * and abstracted EGPIO interface.
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/kernel.h>
26 #include <linux/tty.h>
27 #include <linux/sched.h>
28 #include <linux/pm.h>
29 #include <linux/irq.h>
31 #include <asm/irq.h>
32 #include <asm/hardware.h>
33 #include <asm/setup.h>
35 #include <asm/mach/arch.h>
36 #include <asm/mach/map.h>
37 #include <asm/mach/irda.h>
38 #include <asm/mach/serial_sa1100.h>
40 #include <asm/arch-sa1100/ipaqsa.h>
42 #include <linux/serial_core.h>
44 #if defined (CONFIG_SA1100_H3600) || defined (CONFIG_SA1100_H3100)
45 #include <asm/arch/h3600_gpio.h>
46 #endif
48 #include "generic.h"
49 struct ipaq_model_ops ipaq_model_ops;
50 EXPORT_SYMBOL(ipaq_model_ops);
53 * low-level UART features
56 static void ipaqsa_uart_set_mctrl(struct uart_port *port, u_int mctrl)
58 if (port->mapbase == _Ser3UTCR0) {
59 if (mctrl & TIOCM_RTS)
60 GPCR = GPIO_H3600_COM_RTS;
61 else
62 GPSR = GPIO_H3600_COM_RTS;
66 static u_int ipaqsa_uart_get_mctrl(struct uart_port *port)
68 u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
70 if (port->mapbase == _Ser3UTCR0) {
71 int gplr = GPLR;
72 /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */
73 if (gplr & GPIO_H3600_COM_DCD)
74 ret &= ~TIOCM_CD;
75 if (gplr & GPIO_H3600_COM_CTS)
76 ret &= ~TIOCM_CTS;
79 return ret;
82 static void ipaqsa_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
84 if (port->mapbase == _Ser2UTCR0) { /* TODO: REMOVE THIS */
85 assign_ipaqsa_egpio( IPAQ_EGPIO_IR_ON, !state );
86 } else if (port->mapbase == _Ser3UTCR0) {
87 assign_ipaqsa_egpio( IPAQ_EGPIO_RS232_ON, !state );
92 * Enable/Disable wake up events for this serial port.
93 * Obviously, we only support this on the normal COM port.
95 static int ipaqsa_uart_set_wake(struct uart_port *port, u_int enable)
97 int err = -EINVAL;
99 if (port->mapbase == _Ser3UTCR0) {
100 if (enable)
101 PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */
102 else
103 PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */
104 err = 0;
106 return err;
109 static struct sa1100_port_fns ipaqsa_port_fns __initdata = {
110 .set_mctrl = ipaqsa_uart_set_mctrl,
111 .get_mctrl = ipaqsa_uart_get_mctrl,
112 .pm = ipaqsa_uart_pm,
113 .set_wake = ipaqsa_uart_set_wake,
117 struct egpio_irq_info {
118 int egpio_nr;
119 int gpio; /* GPIO_GPIO(n) */
120 int irq; /* IRQ_GPIOn */
123 static struct egpio_irq_info ipaqsa_egpio_irq_info[] = {
124 { IPAQ_EGPIO_PCMCIA_CD0_N, GPIO_H3600_PCMCIA_CD0, IRQ_GPIO_H3600_PCMCIA_CD0 },
125 { IPAQ_EGPIO_PCMCIA_CD1_N, GPIO_H3600_PCMCIA_CD1, IRQ_GPIO_H3600_PCMCIA_CD1 },
126 { IPAQ_EGPIO_PCMCIA_IRQ0, GPIO_H3600_PCMCIA_IRQ0, IRQ_GPIO_H3600_PCMCIA_IRQ0 },
127 { IPAQ_EGPIO_PCMCIA_IRQ1, GPIO_H3600_PCMCIA_IRQ1, IRQ_GPIO_H3600_PCMCIA_IRQ1 },
128 { 0, 0 }
131 int ipaqsa_irq_number(int egpio_nr)
133 struct egpio_irq_info *info = ipaqsa_egpio_irq_info;
134 while (info->irq != 0) {
135 if (info->egpio_nr == egpio_nr) {
136 if (0) printk("%s: egpio_nr=%d irq=%d\n", __FUNCTION__, egpio_nr, info->irq);
137 return info->irq;
139 info++;
142 printk("%s: unhandled egpio_nr=%d\n", __FUNCTION__, egpio_nr);
143 return -EINVAL;
145 EXPORT_SYMBOL(ipaqsa_irq_number);
147 int ipaqsa_set_irq_type(enum ipaq_egpio_type egpio_nr, unsigned int type)
149 struct egpio_irq_info *info = ipaqsa_egpio_irq_info;
150 while (info->irq != 0) {
151 if (info->egpio_nr == egpio_nr) {
152 if (0) printk("%s: egpio_nr=%d gpio=%x irq=%d\n", __FUNCTION__, egpio_nr, info->gpio, info->irq);
153 set_irq_type( info->irq, type);
154 return 0;
156 info++;
158 printk("%s: unhandled egpio_nr=%d\n", __FUNCTION__, egpio_nr);
159 return -EINVAL;
161 EXPORT_SYMBOL(ipaqsa_set_irq_type);
163 int ipaqsa_request_irq(enum ipaq_egpio_type egpio_number,
164 irqreturn_t (*handler)(int, void *, struct pt_regs *),
165 unsigned long flags, const char *name, void *data)
167 int sa1100_irq = ipaqsa_irq_number(egpio_number);
168 return request_irq( sa1100_irq, handler, flags, name, data);
170 EXPORT_SYMBOL(ipaqsa_request_irq);
172 void ipaqsa_free_irq(unsigned int egpio_number, void *data)
174 int sa1100_irq = ipaqsa_irq_number(egpio_number);
175 free_irq( sa1100_irq, data );
177 EXPORT_SYMBOL(ipaqsa_free_irq);
179 void ipaqsa_set_led (enum led_color color, int duty_time, int cycle_time)
181 if (ipaq_model_ops.set_led)
182 ipaq_model_ops.set_led (color, duty_time, cycle_time);
184 EXPORT_SYMBOL(ipaqsa_set_led);
187 static struct map_desc ipaqsa_io_desc[] __initdata = {
188 { /* Flash bank 0 CS#0 */
189 .virtual = 0xe8000000,
190 .pfn = __phys_to_pfn(0x00000000),
191 .length = 0x02000000,
192 .type = MT_DEVICE
193 } , { /* EGPIO 0 CS#5 */
194 .virtual = IPAQSA_EGPIO_VIRT,
195 .pfn = __phys_to_pfn(IPAQSA_EGPIO_PHYS),
196 .length = 0x01000000,
197 .type = MT_DEVICE
198 } , { /* static memory bank 2 CS#2 */
199 .virtual = IPAQSA_BANK_2_VIRT,
200 .pfn = __phys_to_pfn(SA1100_CS2_PHYS),
201 .length = 0x02800000,
202 .type = MT_DEVICE
203 } , { /* static memory bank 4 CS#4 */
204 .virtual = IPAQSA_BANK_4_VIRT,
205 .pfn = __phys_to_pfn(SA1100_CS4_PHYS),
206 .length = 0x00800000,
207 .type = MT_DEVICE
210 /*static struct map_desc ipaqsa_io_desc[] __initdata = { */
211 /* virtual physical length type */
212 /* { 0xe8000000, 0x00000000, 0x02000000, MT_DEVICE }, *//* Flash bank 0 CS#0 */
213 /* { IPAQSA_EGPIO_VIRT, IPAQSA_EGPIO_PHYS, 0x01000000, MT_DEVICE }, *//* EGPIO 0 CS#5 */
214 /* { IPAQSA_BANK_2_VIRT, SA1100_CS2_PHYS, 0x02800000, MT_DEVICE }, *//* static memory bank 2 CS#2 */
215 /* { IPAQSA_BANK_4_VIRT, SA1100_CS4_PHYS, 0x00800000, MT_DEVICE }, *//* static memory bank 4 CS#4 */
216 /*};*/
220 * Common map_io initialization
222 void __init ipaqsa_map_io(void)
224 sa1100_map_io();
225 iotable_init(ipaqsa_io_desc, ARRAY_SIZE(ipaqsa_io_desc));
227 sa1100_register_uart_fns(&ipaqsa_port_fns);
228 sa1100_register_uart(0, 3); /* Common serial port */
230 /* Ensure those pins are outputs and driving low */
231 PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
232 PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
234 /* Configure suspend conditions */
235 PGSR = 0;
236 PWER = PWER_GPIO0 | PWER_RTC;
237 PCFR = PCFR_OPDE;
238 PSDR = 0;
244 * This turns the IRDA power on or off on the Compaq H3600
246 static int ipaqsa_irda_set_power(struct device *dev, unsigned int state)
248 assign_ipaqsa_egpio( IPAQ_EGPIO_IR_ON, state );
250 return 0;
253 static void ipaqsa_irda_set_speed(struct device *dev, unsigned int speed)
255 if (speed < 4000000) {
256 clr_ipaqsa_egpio(IPAQ_EGPIO_IR_FSEL);
257 } else {
258 set_ipaqsa_egpio(IPAQ_EGPIO_IR_FSEL);
262 static struct irda_platform_data ipaqsa_irda_data = {
263 .set_power = ipaqsa_irda_set_power,
264 .set_speed = ipaqsa_irda_set_speed,
267 void __init ipaqsa_mach_init(void)
269 sa11x0_set_irda_data(&ipaqsa_irda_data);
272 void __init ipaqsa_mtd_set_vpp(int vpp)
274 assign_ipaqsa_egpio(IPAQ_EGPIO_VPP_ON, !!vpp );
277 unsigned long ipaqsa_common_read_egpio( enum ipaq_egpio_type x)
279 switch (x) {
280 case IPAQ_EGPIO_PCMCIA_CD0_N:
281 return(GPLR & GPIO_H3600_PCMCIA_CD0);
282 case IPAQ_EGPIO_PCMCIA_CD1_N:
283 return(GPLR & GPIO_H3600_PCMCIA_CD1);
284 case IPAQ_EGPIO_PCMCIA_IRQ0:
285 return(GPLR & GPIO_H3600_PCMCIA_IRQ0);
286 case IPAQ_EGPIO_PCMCIA_IRQ1:
287 return(GPLR & GPIO_H3600_PCMCIA_IRQ1);
288 default:
289 printk("%s: unhandled egpio_nr=%d\n", __FUNCTION__, x);
290 return 0;