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.
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>
29 #include <linux/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>
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
;
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
) {
72 /* DCD and CTS bits are inverted in GPLR by RS232 transceiver */
73 if (gplr
& GPIO_H3600_COM_DCD
)
75 if (gplr
& GPIO_H3600_COM_CTS
)
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
)
99 if (port
->mapbase
== _Ser3UTCR0
) {
101 PWER
|= PWER_GPIO23
| PWER_GPIO25
; /* DCD and CTS */
103 PWER
&= ~(PWER_GPIO23
| PWER_GPIO25
); /* DCD and CTS */
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
{
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
},
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
);
142 printk("%s: unhandled egpio_nr=%d\n", __FUNCTION__
, egpio_nr
);
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
);
158 printk("%s: unhandled egpio_nr=%d\n", __FUNCTION__
, egpio_nr
);
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,
193 } , { /* EGPIO 0 CS#5 */
194 .virtual = IPAQSA_EGPIO_VIRT
,
195 .pfn
= __phys_to_pfn(IPAQSA_EGPIO_PHYS
),
196 .length
= 0x01000000,
198 } , { /* static memory bank 2 CS#2 */
199 .virtual = IPAQSA_BANK_2_VIRT
,
200 .pfn
= __phys_to_pfn(SA1100_CS2_PHYS
),
201 .length
= 0x02800000,
203 } , { /* static memory bank 4 CS#4 */
204 .virtual = IPAQSA_BANK_4_VIRT
,
205 .pfn
= __phys_to_pfn(SA1100_CS4_PHYS
),
206 .length
= 0x00800000,
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 */
220 * Common map_io initialization
222 void __init
ipaqsa_map_io(void)
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 */
236 PWER
= PWER_GPIO0
| PWER_RTC
;
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
);
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
);
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
)
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
);
289 printk("%s: unhandled egpio_nr=%d\n", __FUNCTION__
, x
);