hh.org updates
[hh.org.git] / arch / arm / mach-pxa / htcapache / htcapache-egpio.c
blob36ee214b4aaed326c734b71a7103f54a44e93aa3
1 /*
2 * Support for the EGPIO capabilities on the HTC Apache phone. This
3 * is believed to be related to the CPLD chip present on the board.
5 * (c) Copyright 2006 Kevin O'Connor <kevin@koconnor.net>
7 * This file may be distributed under the terms of the GNU GPL license.
8 */
10 #include <linux/kernel.h>
11 #include <linux/errno.h> // ENODEV
12 #include <linux/list.h> // struct list_head
13 #include <linux/spinlock.h> // spinlock_t
14 #include <linux/module.h> // EXPORT_SYMBOL
16 #include <asm/arch/pxa-regs.h> // PXA_CS2_PHYS
17 #include <asm/irq.h> // IRQ_BOARD_START, IRQT_RISING
18 #include <asm/io.h> // ioremap_nocache
19 #include <asm/mach/irq.h> // struct irqchip
21 #include <asm/arch/htcapache-gpio.h> // IRQ_EGPIO
24 enum {
25 // Location of the egpio chip in physical ram.
26 EGPIO_BASE = PXA_CS2_PHYS+0x02000000,
27 // Number of egpio irq pins
28 LAST_EGPIO = 8,
31 // Base location of egpio registers.
32 static volatile u16 *egpio;
35 /****************************************************************
36 * Input pins
37 ****************************************************************/
39 // There does not appear to be a way to mask interrupts on the egpio
40 // chip itself. It would be possible to do it in software by
41 // disabling the pxa gpio pin, however since no service currently
42 // needs enable/disable_irq there is no pressing need to implement
43 // this. It isn't necessary to worry about re-entrant irq handlers,
44 // because the egpio interrupt is checked from the pxa interrupt which
45 // is itself non re-entrant.
46 static void egpio_ack(unsigned int irq)
49 static void egpio_mask(unsigned int irq)
52 static void egpio_unmask(unsigned int irq)
56 static struct irqchip egpio_muxed_chip = {
57 .ack = egpio_ack,
58 .mask = egpio_mask,
59 .unmask = egpio_unmask,
62 static void
63 egpio_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
65 int i;
66 // Read current pins.
67 u16 readval = egpio[0];
68 // Process all set pins.
69 for (i=0; i<LAST_EGPIO; i++) {
70 int irqpin = i+8;
71 if (!(readval & (1<<irqpin)))
72 continue;
73 // Ack/unmask current pin.
74 egpio[0] = ~(1<<irqpin);
75 // Handle irq
76 irq = IRQ_EGPIO(i);
77 desc = &irq_desc[irq];
78 desc_handle_irq(irq, desc, regs);
82 // Check an input pin to see if it is active.
83 int
84 htcapache_egpio_isset(int bit)
86 u16 readval = egpio[0];
87 return readval & (1<<bit);
89 EXPORT_SYMBOL(htcapache_egpio_isset);
92 /****************************************************************
93 * Output pins
94 ****************************************************************/
96 // Local copies of what is in the egpio registers
97 static u16 cached_out_egpio[3];
98 static spinlock_t outLock;
100 static inline int u16pos(int bit) {
101 return bit/16;
103 static inline int u16bit(int bit) {
104 return 1<<(bit & (16-1));
107 void
108 htcapache_egpio_set(int bit)
110 int pos = u16pos(bit);
111 unsigned long flag;
113 spin_lock_irqsave(&outLock, flag);
114 cached_out_egpio[pos] |= u16bit(bit);
115 printk("egpio set: reg %d = 0x%04x\n", pos, cached_out_egpio[pos]);
116 egpio[pos] = cached_out_egpio[pos];
117 spin_unlock_irqrestore(&outLock, flag);
119 EXPORT_SYMBOL(htcapache_egpio_set);
121 void
122 htcapache_egpio_clear(int bit)
124 int pos = u16pos(bit);
125 unsigned long flag;
127 spin_lock_irqsave(&outLock, flag);
128 cached_out_egpio[pos] &= ~u16bit(bit);
129 printk("egpio clear: reg %d = 0x%04x\n", pos, cached_out_egpio[pos]);
130 egpio[pos] = cached_out_egpio[pos];
131 spin_unlock_irqrestore(&outLock, flag);
133 EXPORT_SYMBOL(htcapache_egpio_clear);
136 /****************************************************************
137 * Setup
138 ****************************************************************/
141 htcapache_egpio_init(void)
143 int irq;
145 spin_lock_init(&outLock);
147 // Map egpio chip into virtual address space.
148 egpio = (volatile u16 *)ioremap_nocache(EGPIO_BASE
149 , sizeof(cached_out_egpio));
150 if (!egpio)
151 return -ENODEV;
153 printk(KERN_NOTICE "EGPIO phys=%08x virt=%p\n"
154 , EGPIO_BASE, egpio);
156 // Setup irq handlers.
157 for (irq = IRQ_EGPIO(0); irq <= IRQ_EGPIO(LAST_EGPIO); irq++) {
158 set_irq_chip(irq, &egpio_muxed_chip);
159 set_irq_handler(irq, do_simple_IRQ);
160 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
162 set_irq_type(IRQ_GPIO(GPIO_NR_HTCAPACHE_EGPIO_IRQ), IRQT_RISING);
163 set_irq_chained_handler(IRQ_GPIO(GPIO_NR_HTCAPACHE_EGPIO_IRQ)
164 , egpio_handler);
166 // Setup initial output pin values.
167 cached_out_egpio[2] = (1<<8); // Disable Charger
168 egpio[1] = cached_out_egpio[1];
169 egpio[2] = cached_out_egpio[2];
171 // Unmask all current irqs.
172 egpio[0] = 0;
174 return 0;