1 /* $NetBSD: s3c2410.c,v 1.4 2003/08/27 03:46:05 bsh Exp $ */
4 * Copyright (c) 2003 Genetec corporation. All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of Genetec corporation may not be used to endorse
16 * or promote products derived from this software without specific prior
19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/reboot.h>
39 #include <sys/malloc.h>
40 #include <sys/module.h>
46 #include <machine/cpu.h>
47 #include <machine/bus.h>
49 #include <machine/cpufunc.h>
50 #include <machine/intr.h>
51 #include <arm/s3c2xx0/s3c2410reg.h>
52 #include <arm/s3c2xx0/s3c2440reg.h>
53 #include <arm/s3c2xx0/s3c24x0var.h>
56 #define S3C2XX0_XTAL_CLK 12000000
59 u_int irqmasks[IPL_LEVELS];
66 { CHIPID_S3C2410A, "S3C2410A", CPU_S3C2410 },
67 { CHIPID_S3C2440A, "S3C2440A", CPU_S3C2440 },
68 { CHIPID_S3C2442B, "S3C2442B", CPU_S3C2440 },
82 } s3c24x0_children[] = {
84 { SYS_RES_IOPORT, S3C24X0_RTC_PA_BASE, S3C24X0_RTC_SIZE },
87 { "timer", 0, -1, { { 0 }, } },
89 { SYS_RES_IRQ, S3C24X0_INT_UART0, 1 },
90 { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(0),
91 S3C24X0_UART_BASE(1) - S3C24X0_UART_BASE(0) },
94 { SYS_RES_IRQ, S3C24X0_INT_UART1, 1 },
95 { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(1),
96 S3C24X0_UART_BASE(2) - S3C24X0_UART_BASE(1) },
99 { SYS_RES_IRQ, S3C24X0_INT_UART2, 1 },
100 { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(2),
101 S3C24X0_UART_BASE(3) - S3C24X0_UART_BASE(2) },
104 { SYS_RES_IRQ, S3C24X0_INT_USBH, 0 },
105 { SYS_RES_IOPORT, S3C24X0_USBHC_PA_BASE, S3C24X0_USBHC_SIZE },
112 static device_t s3c24x0_add_child(device_t, int, const char *, int);
114 static int s3c24x0_probe(device_t);
115 static int s3c24x0_attach(device_t);
116 static void s3c24x0_identify(driver_t *, device_t);
117 static int s3c24x0_setup_intr(device_t, device_t, struct resource *, int,
118 driver_filter_t *, driver_intr_t *, void *, void **);
119 static int s3c24x0_teardown_intr(device_t, device_t, struct resource *,
121 static int s3c24x0_config_intr(device_t, int, enum intr_trigger,
123 static struct resource *s3c24x0_alloc_resource(device_t, device_t, int, int *,
124 u_long, u_long, u_long, u_int);
125 static int s3c24x0_activate_resource(device_t, device_t, int, int,
127 static int s3c24x0_release_resource(device_t, device_t, int, int,
129 static struct resource_list *s3c24x0_get_resource_list(device_t, device_t);
131 static void s3c24x0_identify_cpu(device_t);
133 static device_method_t s3c24x0_methods[] = {
134 DEVMETHOD(device_probe, s3c24x0_probe),
135 DEVMETHOD(device_attach, s3c24x0_attach),
136 DEVMETHOD(device_identify, s3c24x0_identify),
137 DEVMETHOD(bus_setup_intr, s3c24x0_setup_intr),
138 DEVMETHOD(bus_teardown_intr, s3c24x0_teardown_intr),
139 DEVMETHOD(bus_config_intr, s3c24x0_config_intr),
140 DEVMETHOD(bus_alloc_resource, s3c24x0_alloc_resource),
141 DEVMETHOD(bus_activate_resource, s3c24x0_activate_resource),
142 DEVMETHOD(bus_release_resource, s3c24x0_release_resource),
143 DEVMETHOD(bus_get_resource_list,s3c24x0_get_resource_list),
144 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
145 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
149 static driver_t s3c24x0_driver = {
152 sizeof(struct s3c24x0_softc),
154 static devclass_t s3c24x0_devclass;
156 DRIVER_MODULE(s3c24x0, nexus, s3c24x0_driver, s3c24x0_devclass, 0, 0);
158 struct s3c2xx0_softc *s3c2xx0_softc = NULL;
161 s3c24x0_add_child(device_t bus, int prio, const char *name, int unit)
164 struct s3c2xx0_ivar *ivar;
166 child = device_add_child_ordered(bus, prio, name, unit);
170 ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
172 device_delete_child(bus, child);
173 printf("Can't add alloc ivar\n");
176 device_set_ivars(child, ivar);
177 resource_list_init(&ivar->resources);
183 s3c24x0_enable_ext_intr(unsigned int irq)
191 } else if (irq <= 23) {
193 offset = (irq - 8) * 2;
197 /* Make the pin an interrupt source */
198 value = bus_space_read_4(s3c2xx0_softc->sc_iot,
199 s3c2xx0_softc->sc_gpio_ioh, reg);
200 value &= ~(3 << offset);
201 value |= 2 << offset;
202 bus_space_write_4(s3c2xx0_softc->sc_iot, s3c2xx0_softc->sc_gpio_ioh,
207 s3c24x0_setup_intr(device_t dev, device_t child,
208 struct resource *ires, int flags, driver_filter_t *filt,
209 driver_intr_t *intr, void *arg, void **cookiep)
213 error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt,
218 for (irq = rman_get_start(ires); irq <= rman_get_end(ires); irq++) {
219 if (irq >= S3C24X0_EXTIRQ_MIN && irq <= S3C24X0_EXTIRQ_MAX) {
220 /* Enable the external interrupt pin */
221 s3c24x0_enable_ext_intr(irq - S3C24X0_EXTIRQ_MIN);
229 s3c24x0_teardown_intr(device_t dev, device_t child, struct resource *res,
232 return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
236 s3c24x0_config_intr(device_t dev, int irq, enum intr_trigger trig,
237 enum intr_polarity pol)
239 uint32_t mask, reg, value;
242 /* Only external interrupts can be configured */
243 if (irq < S3C24X0_EXTIRQ_MIN || irq > S3C24X0_EXTIRQ_MAX)
246 /* There is no standard trigger or polarity for the bus */
247 if (trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM)
250 irq -= S3C24X0_EXTIRQ_MIN;
252 /* Get the bits to set */
254 if (pol == INTR_POLARITY_LOW) {
256 } else if (pol == INTR_POLARITY_HIGH) {
259 if (trig == INTR_TRIGGER_LEVEL) {
263 /* Get the register to set */
265 reg = GPIO_EXTINT(0);
267 } else if (irq <= 15) {
268 reg = GPIO_EXTINT(1);
269 offset = (irq - 8) * 4;
270 } else if (irq <= 23) {
271 reg = GPIO_EXTINT(2);
272 offset = (irq - 16) * 4;
277 /* Set the new signaling method */
278 value = bus_space_read_4(s3c2xx0_softc->sc_iot,
279 s3c2xx0_softc->sc_gpio_ioh, reg);
280 value &= ~(7 << offset);
281 value |= mask << offset;
282 bus_space_write_4(s3c2xx0_softc->sc_iot,
283 s3c2xx0_softc->sc_gpio_ioh, reg, value);
288 static struct resource *
289 s3c24x0_alloc_resource(device_t bus, device_t child, int type, int *rid,
290 u_long start, u_long end, u_long count, u_int flags)
292 struct resource_list_entry *rle;
293 struct s3c2xx0_ivar *ivar = device_get_ivars(child);
294 struct resource_list *rl = &ivar->resources;
295 struct resource *res = NULL;
297 if (device_get_parent(child) != bus)
298 return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
299 type, rid, start, end, count, flags));
301 rle = resource_list_find(rl, type, *rid);
303 /* There is a resource list. Use it */
305 panic("Resource rid %d type %d already in use", *rid,
307 if (start == 0UL && end == ~0UL) {
309 count = ulmax(count, rle->count);
310 end = ulmax(rle->end, start + count - 1);
313 * When allocating an irq with children irq's really
314 * allocate the children as it is those we are interested
315 * in receiving, not the parent.
317 if (type == SYS_RES_IRQ && start == end) {
319 case S3C24X0_INT_ADCTC:
320 start = S3C24X0_INT_TC;
321 end = S3C24X0_INT_ADC;
323 #ifdef S3C2440_INT_CAM
324 case S3C2440_INT_CAM:
325 start = S3C2440_INT_CAM_C;
326 end = S3C2440_INT_CAM_P;
332 count = end - start + 1;
338 res = rman_reserve_resource(
339 &s3c2xx0_softc->s3c2xx0_irq_rman, start, end,
340 count, flags, child);
345 res = rman_reserve_resource(
346 &s3c2xx0_softc->s3c2xx0_mem_rman,
347 start, end, count, flags, child);
349 panic("Unable to map address space %#lX-%#lX", start,
352 rman_set_bustag(res, &s3c2xx0_bs_tag);
353 rman_set_bushandle(res, start);
354 if (flags & RF_ACTIVE) {
355 if (bus_activate_resource(child, type, *rid, res)) {
356 rman_release_resource(res);
364 rman_set_rid(res, *rid);
367 rle->start = rman_get_start(res);
368 rle->end = rman_get_end(res);
377 s3c24x0_activate_resource(device_t bus, device_t child, int type, int rid,
380 bus_space_handle_t p;
383 if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
384 error = bus_space_map(rman_get_bustag(r),
385 rman_get_bushandle(r), rman_get_size(r), 0, &p);
388 rman_set_bushandle(r, p);
390 return (rman_activate_resource(r));
394 s3c24x0_release_resource(device_t bus, device_t child, int type, int rid,
397 struct s3c2xx0_ivar *ivar = device_get_ivars(child);
398 struct resource_list *rl = &ivar->resources;
399 struct resource_list_entry *rle;
404 rle = resource_list_find(rl, type, rid);
408 rman_release_resource(r);
414 static struct resource_list *
415 s3c24x0_get_resource_list(device_t dev, device_t child)
417 struct s3c2xx0_ivar *ivar;
419 ivar = device_get_ivars(child);
420 return (&(ivar->resources));
424 s3c24x0_identify(driver_t *driver, device_t parent)
427 BUS_ADD_CHILD(parent, 0, "s3c24x0", 0);
431 s3c24x0_probe(device_t dev)
437 s3c24x0_attach(device_t dev)
439 struct s3c24x0_softc *sc = device_get_softc(dev);
445 s3c2xx0_softc = &(sc->sc_sx);
446 sc->sc_sx.sc_iot = iot = &s3c2xx0_bs_tag;
447 s3c2xx0_softc->s3c2xx0_irq_rman.rm_type = RMAN_ARRAY;
448 s3c2xx0_softc->s3c2xx0_irq_rman.rm_descr = "S3C24X0 IRQs";
449 s3c2xx0_softc->s3c2xx0_mem_rman.rm_type = RMAN_ARRAY;
450 s3c2xx0_softc->s3c2xx0_mem_rman.rm_descr = "S3C24X0 Device Registers";
451 /* Manage the registor memory space */
452 if ((rman_init(&s3c2xx0_softc->s3c2xx0_mem_rman) != 0) ||
453 (rman_manage_region(&s3c2xx0_softc->s3c2xx0_mem_rman,
454 S3C24X0_DEV_VA_OFFSET,
455 S3C24X0_DEV_VA_OFFSET + S3C24X0_DEV_VA_SIZE) != 0) ||
456 (rman_manage_region(&s3c2xx0_softc->s3c2xx0_mem_rman,
457 S3C24X0_DEV_START, S3C24X0_DEV_STOP) != 0))
458 panic("s3c24x0_attach: failed to set up register rman");
460 /* These are needed for things without a proper device to attach to */
461 sc->sc_sx.sc_intctl_ioh = S3C24X0_INTCTL_BASE;
462 sc->sc_sx.sc_gpio_ioh = S3C24X0_GPIO_BASE;
463 sc->sc_sx.sc_clkman_ioh = S3C24X0_CLKMAN_BASE;
464 sc->sc_sx.sc_wdt_ioh = S3C24X0_WDT_BASE;
465 sc->sc_timer_ioh = S3C24X0_TIMER_BASE;
470 s3c24x0_identify_cpu(dev);
473 * Manage the interrupt space.
474 * We need to put this after s3c24x0_identify_cpu as the avaliable
475 * interrupts change depending on which CPU we have.
477 if (sc->sc_sx.sc_cpu == CPU_S3C2410)
478 irqmax = S3C2410_SUBIRQ_MAX;
480 irqmax = S3C2440_SUBIRQ_MAX;
481 if (rman_init(&s3c2xx0_softc->s3c2xx0_irq_rman) != 0 ||
482 rman_manage_region(&s3c2xx0_softc->s3c2xx0_irq_rman, 0,
484 rman_manage_region(&s3c2xx0_softc->s3c2xx0_irq_rman,
485 S3C24X0_EXTIRQ_MIN, S3C24X0_EXTIRQ_MAX))
486 panic("s3c24x0_attach: failed to set up IRQ rman");
488 /* calculate current clock frequency */
489 s3c24x0_clock_freq(&sc->sc_sx);
490 device_printf(dev, "fclk %d MHz hclk %d MHz pclk %d MHz\n",
491 sc->sc_sx.sc_fclk / 1000000, sc->sc_sx.sc_hclk / 1000000,
492 sc->sc_sx.sc_pclk / 1000000);
495 * Attach children devices
498 for (i = 0; s3c24x0_children[i].name != NULL; i++) {
499 child = s3c24x0_add_child(dev, s3c24x0_children[i].prio,
500 s3c24x0_children[i].name, s3c24x0_children[i].unit);
501 for (j = 0; j < sizeof(s3c24x0_children[i].res) /
502 sizeof(s3c24x0_children[i].res[0]) &&
503 s3c24x0_children[i].res[j].type != 0; j++) {
504 bus_set_resource(child,
505 s3c24x0_children[i].res[j].type, 0,
506 s3c24x0_children[i].res[j].start,
507 s3c24x0_children[i].res[j].count);
511 bus_generic_probe(dev);
512 bus_generic_attach(dev);
518 s3c24x0_identify_cpu(device_t dev)
520 struct s3c24x0_softc *sc = device_get_softc(dev);
524 idcode = bus_space_read_4(sc->sc_sx.sc_iot, sc->sc_sx.sc_gpio_ioh,
527 for (i = 0; s3c2x0_cpu_id[i].name != NULL; i++) {
528 if (s3c2x0_cpu_id[i].idcode == idcode)
531 if (s3c2x0_cpu_id[i].name == NULL)
532 panic("Unknown CPU detected ((Chip ID: %#X)", idcode);
533 device_printf(dev, "Found %s CPU (Chip ID: %#X)\n",
534 s3c2x0_cpu_id[i].name, idcode);
535 sc->sc_sx.sc_cpu = s3c2x0_cpu_id[i].cpu;
539 * fill sc_pclk, sc_hclk, sc_fclk from values of clock controller register.
541 * s3c24{1,4}0_clock_freq2() is meant to be called from kernel startup routines.
542 * s3c24x0_clock_freq() is for after kernel initialization is done.
544 * Because they can be called before bus_space is available we need to use
545 * volatile pointers rather than bus_space_read.
548 s3c2410_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
550 uint32_t pllcon, divn;
551 unsigned int mdiv, pdiv, sdiv;
552 unsigned int f, h, p;
554 pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
555 divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
557 mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
558 pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
559 sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
561 f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
563 if (divn & S3C2410_CLKDIVN_HDIVN)
566 if (divn & CLKDIVN_PDIVN)
575 s3c2440_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
577 uint32_t pllcon, divn, camdivn;
578 unsigned int mdiv, pdiv, sdiv;
579 unsigned int f, h, p;
581 pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
582 divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
583 camdivn = *(volatile uint32_t *)(clkman_base + S3C2440_CLKMAN_CAMDIVN);
585 mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
586 pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
587 sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
589 f = (2 * (mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
591 switch((divn >> 1) & 3) {
598 if ((camdivn & S3C2440_CAMDIVN_HCLK4_HALF) ==
599 S3C2440_CAMDIVN_HCLK4_HALF)
605 if ((camdivn & S3C2440_CAMDIVN_HCLK3_HALF) ==
606 S3C2440_CAMDIVN_HCLK3_HALF)
613 if (divn & CLKDIVN_PDIVN)
622 s3c24x0_clock_freq(struct s3c2xx0_softc *sc)
626 va = sc->sc_clkman_ioh;
629 s3c2410_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk,
633 s3c2440_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk,
642 (void) disable_interrupts(I32_bit|F32_bit);
644 bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_wdt_ioh, WDT_WTCON,
645 WTCON_ENABLE | WTCON_CLKSEL_16 | WTCON_ENRST);
650 s3c24x0_sleep(int mode __unused)
654 reg = bus_space_read_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_clkman_ioh,
656 bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_clkman_ioh,
657 CLKMAN_CLKCON, reg | CLKCON_IDLE);
662 arm_get_next_irq(int last __unused)
667 if ((irq = bus_space_read_4(&s3c2xx0_bs_tag,
668 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTOFFSET)) != 0) {
670 /* Clear the pending bit */
671 intpnd = bus_space_read_4(&s3c2xx0_bs_tag,
672 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTPND);
673 bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
674 INTCTL_SRCPND, intpnd);
675 bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
676 INTCTL_INTPND, intpnd);
679 case S3C24X0_INT_ADCTC:
680 case S3C24X0_INT_UART0:
681 case S3C24X0_INT_UART1:
682 case S3C24X0_INT_UART2:
683 /* Find the sub IRQ */
685 subirq &= bus_space_read_4(&s3c2xx0_bs_tag,
686 s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND);
687 subirq &= ~(bus_space_read_4(&s3c2xx0_bs_tag,
688 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK));
692 subirq = ffs(subirq) - 1;
694 /* Clear the sub irq pending bit */
695 bus_space_write_4(&s3c2xx0_bs_tag,
696 s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND,
700 * Return the parent IRQ for UART
701 * as it is all we ever need
706 return (S3C24X0_SUBIRQ_MIN + subirq);
712 /* There is a 1:1 mapping to the IRQ we are handling */
713 return S3C24X0_INT_EXT(irq);
715 case S3C24X0_INT_4_7:
716 case S3C24X0_INT_8_23:
717 /* Find the external interrupt being called */
719 subirq &= bus_space_read_4(&s3c2xx0_bs_tag,
720 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTPEND);
721 subirq &= ~bus_space_read_4(&s3c2xx0_bs_tag,
722 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
726 subirq = ffs(subirq) - 1;
728 /* Clear the external irq pending bit */
729 bus_space_write_4(&s3c2xx0_bs_tag,
730 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTPEND,
733 return S3C24X0_INT_EXT(subirq);
742 arm_mask_irq(uintptr_t irq)
746 if (irq >= S3C24X0_INT_EXT(0) && irq <= S3C24X0_INT_EXT(3)) {
747 /* External interrupt 0..3 are directly mapped to irq 0..3 */
748 irq -= S3C24X0_EXTIRQ_MIN;
750 if (irq < S3C24X0_SUBIRQ_MIN) {
751 mask = bus_space_read_4(&s3c2xx0_bs_tag,
752 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK);
754 bus_space_write_4(&s3c2xx0_bs_tag,
755 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK, mask);
756 } else if (irq < S3C24X0_EXTIRQ_MIN) {
757 mask = bus_space_read_4(&s3c2xx0_bs_tag,
758 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK);
759 mask |= (1 << (irq - S3C24X0_SUBIRQ_MIN));
760 bus_space_write_4(&s3c2xx0_bs_tag,
761 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask);
763 mask = bus_space_read_4(&s3c2xx0_bs_tag,
764 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
765 mask |= (1 << (irq - S3C24X0_EXTIRQ_MIN));
766 bus_space_write_4(&s3c2xx0_bs_tag,
767 s3c2xx0_softc->sc_intctl_ioh, GPIO_EINTMASK, mask);
772 arm_unmask_irq(uintptr_t irq)
776 if (irq >= S3C24X0_INT_EXT(0) && irq <= S3C24X0_INT_EXT(3)) {
777 /* External interrupt 0..3 are directly mapped to irq 0..3 */
778 irq -= S3C24X0_EXTIRQ_MIN;
780 if (irq < S3C24X0_SUBIRQ_MIN) {
781 mask = bus_space_read_4(&s3c2xx0_bs_tag,
782 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK);
784 bus_space_write_4(&s3c2xx0_bs_tag,
785 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK, mask);
786 } else if (irq < S3C24X0_EXTIRQ_MIN) {
787 mask = bus_space_read_4(&s3c2xx0_bs_tag,
788 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK);
789 mask &= ~(1 << (irq - S3C24X0_SUBIRQ_MIN));
790 bus_space_write_4(&s3c2xx0_bs_tag,
791 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask);
793 mask = bus_space_read_4(&s3c2xx0_bs_tag,
794 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
795 mask &= ~(1 << (irq - S3C24X0_EXTIRQ_MIN));
796 bus_space_write_4(&s3c2xx0_bs_tag,
797 s3c2xx0_softc->sc_intctl_ioh, GPIO_EINTMASK, mask);