hh.org updates
[hh.org.git] / arch / arm / mach-pxa / aximx30 / aximx30_core.c
blobe92365568cca04b7ac768f4f374970b8e8fa8188
1 /* Core Hardware driver for x30 (ASIC3, EGPIOs)
3 * Authors: Giuseppe Zompatori <giuseppe_zompatori@yahoo.it>
5 * based on previews work, see below:
7 * Copyright (c) 2005 SDG Systems, LLC
9 * 2005-03-29 Todd Blumer Converted basic structure to support hx4700
12 #include <linux/module.h>
13 #include <linux/version.h>
14 #include <linux/config.h>
15 #include <linux/interrupt.h>
16 #include <linux/device.h>
18 #include <asm/irq.h>
19 #include <asm/io.h>
20 #include <asm/mach/irq.h>
21 #include <asm/arch/pxa-regs.h>
22 #include <asm/arch/aximx30-gpio.h>
23 #include <asm/arch/aximx30-asic.h>
25 #include <linux/soc/asic3_base.h>
26 #include <asm/hardware/ipaq-asic3.h>
28 #include "aximx30_core.h"
30 #define EGPIO_OFFSET 0
31 #define EGPIO_BASE (PXA_CS5_PHYS+EGPIO_OFFSET)
32 #define WLAN_OFFSET 0x800000
33 #define WLAN_BASE (PXA_CS5_PHYS+WLAN_OFFSET)
34 #define PPSH_OFFSET 0x1000000
36 volatile u_int16_t *egpios;
37 u_int16_t egpio_reg;
40 * may make sense to put egpios elsewhere, but they're here now
41 * since they share some of the same address space with the TI WLAN
43 * EGPIO register is write-only
46 void
47 x30_egpio_enable( unsigned long bits )
49 egpio_reg |= bits;
50 *egpios = egpio_reg;
52 EXPORT_SYMBOL(x30_egpio_enable);
54 void
55 x30_egpio_disable( unsigned long bits )
57 egpio_reg &= ~bits;
58 *egpios = egpio_reg;
60 EXPORT_SYMBOL(x30_egpio_disable);
62 int
63 x30_udc_detect( void )
65 return (asic3_get_gpio_status_d(&x30_asic3.dev)
66 & (1 << GPIOD_USBC_DETECT_N)) ? 0 : 1;
69 static unsigned int serial_irq = 0xffffffff;
70 static unsigned int ac_irq = 0xffffffff;
72 static int
73 serial_isr(int irq, void *dev_id, struct pt_regs *regs)
75 unsigned int statusd;
76 int connected;
78 if (irq != serial_irq)
79 return IRQ_NONE;
81 statusd = asic3_get_gpio_status_d( &x30_asic3.dev );
82 connected = (statusd & (1<<GPIOD_COM_DCD)) != 0;
83 printk( KERN_INFO "serial_isr: com_dcd=%d\n", connected );
84 SET_X30_GPIO( RS232_ON, connected );
85 return IRQ_HANDLED;
88 static int
89 ac_isr(int irq, void *dev_id, struct pt_regs *regs)
91 unsigned int statusd;
92 int connected;
94 if (irq != ac_irq)
95 return IRQ_NONE;
97 statusd = asic3_get_gpio_status_d( &x30_asic3.dev );
98 connected = (statusd & (1<<GPIOD_AC_IN_N)) == 0;
99 printk( KERN_INFO "ac_isr: connected=%d\n", connected );
100 if (connected)
101 set_irq_type( ac_irq, IRQT_RISING );
102 else
103 set_irq_type( ac_irq, IRQT_FALLING );
104 SET_X30_GPIO_N( CHARGE_EN, connected );
105 return IRQ_HANDLED;
108 static int
109 x30_core_probe( struct device *dev )
111 unsigned int statusd;
112 int connected;
113 struct x30_core_funcs *funcs = (struct x30_core_funcs *) dev->platform_data;
114 printk( KERN_NOTICE "X30 Core Hardware Driver\n" );
116 funcs->udc_detect = x30_udc_detect;
118 /* UART IRQ */
119 egpios = (volatile u_int16_t *)ioremap_nocache( EGPIO_BASE, sizeof *egpios );
120 if (!egpios)
121 return -ENODEV;
123 serial_irq = asic3_irq_base( &x30_asic3.dev ) + ASIC3_GPIOD_IRQ_BASE
124 + GPIOD_COM_DCD;
125 if (request_irq( serial_irq, serial_isr, SA_INTERRUPT,
126 "X30 Serial", NULL ) != 0) {
127 printk( KERN_ERR "Unable to configure serial port interrupt.\n" );
128 return -ENODEV;
130 set_irq_type( serial_irq, IRQT_RISING );
132 ac_irq = asic3_irq_base( &x30_asic3.dev ) + ASIC3_GPIOD_IRQ_BASE
133 + GPIOD_AC_IN_N;
135 statusd = asic3_get_gpio_status_d( &x30_asic3.dev );
136 connected = (statusd & (1<<GPIOD_AC_IN_N)) == 0;
137 printk( KERN_INFO "AC: connected=%d\n", connected );
138 if (connected)
139 set_irq_type( ac_irq, IRQT_RISING );
140 else
141 set_irq_type( ac_irq, IRQT_FALLING );
143 if (request_irq( ac_irq, ac_isr, SA_INTERRUPT,
144 "X30 AC Detect", NULL ) != 0) {
145 printk( KERN_ERR "Unable to configure AC detect interrupt.\n" );
146 free_irq( serial_irq, NULL );
147 return -ENODEV;
149 SET_X30_GPIO_N( CHARGE_EN, connected );
150 return 0;
153 static int
154 x30_core_remove( struct device *dev )
156 int irq;
158 irq = asic3_irq_base( &x30_asic3.dev ) + ASIC3_GPIOD_IRQ_BASE
159 + GPIOD_COM_DCD;
160 if (egpios != NULL)
161 iounmap( (void *)egpios );
162 if (serial_irq != 0xffffffff)
163 free_irq( serial_irq, NULL );
164 if (ac_irq != 0xffffffff)
165 free_irq( ac_irq, NULL );
166 return 0;
169 struct device_driver x30_core_driver = {
170 .name = "X30-core",
171 .bus = &platform_bus_type,
172 .probe = x30_core_probe,
173 .remove = x30_core_remove,
176 static int __init
177 x30_core_init( void )
179 return driver_register( &x30_core_driver );
183 static void __exit
184 x30_core_exit( void )
186 driver_unregister( &x30_core_driver );
189 module_init( x30_core_init );
190 module_exit( x30_core_exit );
192 MODULE_AUTHOR("Giuseppe Zompatori <giuseppe_zompatori@yahoo.it>");
193 MODULE_DESCRIPTION("Dell Axim X30 Core Hardware Driver");
194 MODULE_LICENSE("GPL");