1 /* $NetBSD: imx31_gpio.c,v 1.3 2008/04/28 20:23:14 martin Exp $ */
3 * Copyright (c) 2007 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: imx31_gpio.c,v 1.3 2008/04/28 20:23:14 martin Exp $");
38 #include <sys/param.h>
39 #include <sys/evcnt.h>
40 #include <sys/atomic.h>
42 #include <uvm/uvm_extern.h>
44 #include <machine/intr.h>
47 #include <arm/armreg.h>
48 #include <arm/cpufunc.h>
50 #include <machine/bus.h>
52 #include <arm/imx/imx31reg.h>
53 #include <arm/imx/imx31var.h>
54 #include <arm/pic/picvar.h>
58 #include <dev/gpio/gpiovar.h>
61 static void gpio_pic_block_irqs(struct pic_softc
*, size_t, uint32_t);
62 static void gpio_pic_unblock_irqs(struct pic_softc
*, size_t, uint32_t);
63 static int gpio_pic_find_pending_irqs(struct pic_softc
*);
64 static void gpio_pic_establish_irq(struct pic_softc
*, struct intrsource
*);
66 const struct pic_ops gpio_pic_ops
= {
67 .pic_block_irqs
= gpio_pic_block_irqs
,
68 .pic_unblock_irqs
= gpio_pic_unblock_irqs
,
69 .pic_find_pending_irqs
= gpio_pic_find_pending_irqs
,
70 .pic_establish_irq
= gpio_pic_establish_irq
,
74 struct device gpio_dev
;
75 struct pic_softc gpio_pic
;
76 bus_space_tag_t gpio_memt
;
77 bus_space_handle_t gpio_memh
;
78 uint32_t gpio_enable_mask
;
79 uint32_t gpio_edge_mask
;
80 uint32_t gpio_level_mask
;
82 struct gpio_chipset_tag gpio_chipset
;
83 gpio_pin_t gpio_pins
[32];
87 #define PIC_TO_SOFTC(pic) \
88 ((struct gpio_softc *)((char *)(pic) - \
89 offsetof(struct gpio_softc, gpio_pic)))
91 #define GPIO_READ(gpio, reg) \
92 bus_space_read_4((gpio)->gpio_memt, (gpio)->gpio_memh, (reg))
93 #define GPIO_WRITE(gpio, reg, val) \
94 bus_space_write_4((gpio)->gpio_memt, (gpio)->gpio_memh, (reg), (val))
97 gpio_pic_unblock_irqs(struct pic_softc
*pic
, size_t irq_base
, uint32_t irq_mask
)
99 struct gpio_softc
* const gpio
= PIC_TO_SOFTC(pic
);
100 KASSERT(irq_base
== 0);
102 gpio
->gpio_enable_mask
|= irq_mask
;
104 * If this a level source, ack it now. If it's still asserted
107 if (irq_mask
& gpio
->gpio_level_mask
)
108 GPIO_WRITE(gpio
, GPIO_ISR
, irq_mask
);
109 GPIO_WRITE(gpio
, GPIO_IMR
, gpio
->gpio_enable_mask
);
113 gpio_pic_block_irqs(struct pic_softc
*pic
, size_t irq_base
, uint32_t irq_mask
)
115 struct gpio_softc
* const gpio
= PIC_TO_SOFTC(pic
);
116 KASSERT(irq_base
== 0);
118 gpio
->gpio_enable_mask
&= ~irq_mask
;
119 GPIO_WRITE(gpio
, GPIO_IMR
, gpio
->gpio_enable_mask
);
123 gpio_pic_find_pending_irqs(struct pic_softc
*pic
)
125 struct gpio_softc
* const gpio
= PIC_TO_SOFTC(pic
);
129 v
= GPIO_READ(gpio
, GPIO_ISR
);
130 pending
= (v
& gpio
->gpio_enable_mask
);
135 * Disable the pending interrupts.
137 gpio
->gpio_enable_mask
&= ~pending
;
138 GPIO_WRITE(gpio
, GPIO_IMR
, gpio
->gpio_enable_mask
);
141 * If any of the sources are edge triggered, ack them now so
142 * we won't lose them.
144 if (v
& gpio
->gpio_edge_mask
)
145 GPIO_WRITE(gpio
, GPIO_ISR
, v
& gpio
->gpio_edge_mask
);
148 * Now find all the pending bits and mark them as pending.
152 KASSERT(pending
!= 0);
153 irq
= 31 - __builtin_clz(pending
);
154 pending
&= ~__BIT(irq
);
155 pic_mark_pending(&gpio
->gpio_pic
, irq
);
156 } while (pending
!= 0);
161 #define GPIO_TYPEMAP \
162 ((GPIO_ICR_LEVEL_LOW << (2*IST_LEVEL_LOW)) | \
163 (GPIO_ICR_LEVEL_HIGH << (2*IST_LEVEL_HIGH)) | \
164 (GPIO_ICR_EDGE_RISING << (2*IST_EDGE_RISING)) | \
165 (GPIO_ICR_EDGE_FALLING << (2*IST_EDGE_FALLING)))
168 gpio_pic_establish_irq(struct pic_softc
*pic
, struct intrsource
*is
)
170 struct gpio_softc
* const gpio
= PIC_TO_SOFTC(pic
);
171 KASSERT(is
->is_irq
< 32);
172 uint32_t irq_mask
= __BIT(is
->is_irq
);
174 unsigned int icr_shift
, icr_reg
;
178 * Make sure the irq isn't enabled and not asserting.
180 gpio
->gpio_enable_mask
&= ~irq_mask
;
181 GPIO_WRITE(gpio
, GPIO_IMR
, gpio
->gpio_enable_mask
);
182 GPIO_WRITE(gpio
, GPIO_ISR
, irq_mask
);
185 * Convert the type to a gpio type and figure out which bits in what
186 * register we have to tweak.
188 gtype
= (GPIO_TYPEMAP
>> (2 * is
->is_type
)) & 3;
189 icr_shift
= (is
->is_irq
& 0x0f) << 1;
190 icr_reg
= GPIO_ICR1
+ ((is
->is_irq
& 0x10) >> 2);
193 * Set the interrupt type.
195 v
= GPIO_READ(gpio
, icr_reg
);
196 v
&= ~(3 << icr_shift
);
197 v
|= gtype
<< icr_shift
;
198 GPIO_WRITE(gpio
, icr_reg
, v
);
203 v
= GPIO_READ(gpio
, GPIO_DIR
);
205 GPIO_WRITE(gpio
, GPIO_DIR
, v
);
208 * Now record the type of interrupt.
210 if (gtype
== GPIO_ICR_EDGE_RISING
|| gtype
== GPIO_ICR_EDGE_FALLING
) {
211 gpio
->gpio_edge_mask
|= irq_mask
;
212 gpio
->gpio_level_mask
&= ~irq_mask
;
214 gpio
->gpio_edge_mask
&= ~irq_mask
;
215 gpio
->gpio_level_mask
|= irq_mask
;
219 static int gpio_match(device_t
, cfdata_t
, void *);
220 static void gpio_attach(device_t
, device_t
, void *);
222 CFATTACH_DECL(imxgpio
,
223 sizeof(struct gpio_softc
),
224 gpio_match
, gpio_attach
,
230 imxgpio_pin_read(void *arg
, int pin
)
232 struct gpio_softc
* const gpio
= arg
;
234 return (GPIO_READ(gpio
, GPIO_DR
) >> pin
) & 1;
238 imxgpio_pin_write(void *arg
, int pin
, int value
)
240 struct gpio_softc
* const gpio
= arg
;
241 uint32_t mask
= 1 << pin
;
244 old
= GPIO_READ(gpio
, GPIO_DR
);
251 GPIO_WRITE(gpio
, GPIO_DR
, new);
255 imxgpio_pin_ctl(void *arg
, int pin
, int flags
)
257 struct gpio_softc
* const gpio
= arg
;
258 uint32_t mask
= 1 << pin
;
261 old
= GPIO_READ(gpio
, GPIO_DIR
);
263 switch (flags
& (GPIO_PIN_INPUT
|GPIO_PIN_OUTPUT
)) {
264 case GPIO_PIN_INPUT
: new |= mask
; break;
265 case GPIO_PIN_OUTPUT
: new &= ~mask
; break;
269 GPIO_WRITE(gpio
, GPIO_DIR
, new);
273 gpio_defer(device_t self
)
275 struct gpio_softc
* const gpio
= (void *) self
;
276 struct gpio_chipset_tag
* const gp
= &gpio
->gpio_chipset
;
277 struct gpiobus_attach_args gba
;
279 uint32_t mask
, dir
, value
;
282 gp
->gp_cookie
= gpio
;
283 gp
->gp_pin_read
= imxgpio_pin_read
;
284 gp
->gp_pin_write
= imxgpio_pin_write
;
285 gp
->gp_pin_ctl
= imxgpio_pin_ctl
;
288 gba
.gba_pins
= gpio
->gpio_pins
;
289 gba
.gba_npins
= __arraycount(gpio
->gpio_pins
);
291 dir
= GPIO_READ(gpio
, GPIO_DIR
);
292 value
= GPIO_READ(gpio
, GPIO_DR
);
293 for (pin
= 0, mask
= 1, pins
= gpio
->gpio_pins
;
294 pin
< 32; pin
++, mask
<<= 1, pins
++) {
296 if ((gpio
->gpio_edge_mask
|gpio
->gpio_level_mask
) & mask
)
297 pins
->pin_caps
= GPIO_PIN_INPUT
;
299 pins
->pin_caps
= GPIO_PIN_INPUT
|GPIO_PIN_OUTPUT
;
301 (dir
& mask
) ? GPIO_PIN_OUTPUT
: GPIO_PIN_INPUT
;
303 (value
& mask
) ? GPIO_PIN_HIGH
: GPIO_PIN_LOW
;
306 config_found_ia(self
, "gpiobus", &gba
, gpiobus_print
);
308 #endif /* NGPIO > 0 */
311 gpio_match(device_t parent
, cfdata_t cfdata
, void *aux
)
313 struct ahb_attach_args
*ahba
= aux
;
314 bus_space_handle_t memh
;
318 if (ahba
->ahba_addr
!= GPIO1_BASE
319 && ahba
->ahba_addr
!= GPIO2_BASE
320 && ahba
->ahba_addr
!= GPIO3_BASE
)
323 size
= (ahba
->ahba_size
== AHBCF_SIZE_DEFAULT
) ? GPIO_SIZE
: ahba
->ahba_size
;
325 error
= bus_space_map(ahba
->ahba_memt
, ahba
->ahba_addr
, size
, 0, &memh
);
329 bus_space_unmap(ahba
->ahba_memt
, memh
, size
);
334 gpio_attach(device_t parent
, device_t self
, void *aux
)
336 struct ahb_attach_args
* const ahba
= aux
;
337 struct gpio_softc
* const gpio
= (void *) self
;
340 if (ahba
->ahba_size
== AHBCF_SIZE_DEFAULT
)
341 ahba
->ahba_size
= GPIO_SIZE
;
343 gpio
->gpio_memt
= ahba
->ahba_memt
;
344 error
= bus_space_map(ahba
->ahba_memt
, ahba
->ahba_addr
, ahba
->ahba_size
,
345 0, &gpio
->gpio_memh
);
348 aprint_error(": failed to map register %#lx@%#lx: %d\n",
349 ahba
->ahba_size
, ahba
->ahba_addr
, error
);
353 if (ahba
->ahba_irqbase
!= AHBCF_IRQBASE_DEFAULT
) {
354 gpio
->gpio_pic
.pic_ops
= &gpio_pic_ops
;
355 strlcpy(gpio
->gpio_pic
.pic_name
, self
->dv_xname
,
356 sizeof(gpio
->gpio_pic
.pic_name
));
357 gpio
->gpio_pic
.pic_maxsources
= 32;
358 pic_add(&gpio
->gpio_pic
, ahba
->ahba_irqbase
);
359 aprint_normal(": interrupts %d..%d",
360 ahba
->ahba_irqbase
, ahba
->ahba_irqbase
+ 31);
364 config_interrupts(self
, gpio_defer
);