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/armreg.h>
47 #include <machine/cpu.h>
48 #include <machine/bus.h>
50 #include <machine/cpufunc.h>
51 #include <machine/intr.h>
52 #include <arm/samsung/s3c2xx0/s3c2410reg.h>
53 #include <arm/samsung/s3c2xx0/s3c2440reg.h>
54 #include <arm/samsung/s3c2xx0/s3c24x0var.h>
57 #define S3C2XX0_XTAL_CLK 12000000
59 bus_space_tag_t s3c2xx0_bs_tag;
62 u_int irqmasks[IPL_LEVELS];
69 { CHIPID_S3C2410A, "S3C2410A", CPU_S3C2410 },
70 { CHIPID_S3C2440A, "S3C2440A", CPU_S3C2440 },
71 { CHIPID_S3C2442B, "S3C2442B", CPU_S3C2440 },
85 } s3c24x0_children[] = {
87 { SYS_RES_IOPORT, S3C24X0_RTC_PA_BASE, S3C24X0_RTC_SIZE },
90 { "timer", 0, -1, { { 0 }, } },
92 { SYS_RES_IRQ, S3C24X0_INT_UART0, 1 },
93 { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(0),
94 S3C24X0_UART_BASE(1) - S3C24X0_UART_BASE(0) },
97 { SYS_RES_IRQ, S3C24X0_INT_UART1, 1 },
98 { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(1),
99 S3C24X0_UART_BASE(2) - S3C24X0_UART_BASE(1) },
102 { SYS_RES_IRQ, S3C24X0_INT_UART2, 1 },
103 { SYS_RES_IOPORT, S3C24X0_UART_PA_BASE(2),
104 S3C24X0_UART_BASE(3) - S3C24X0_UART_BASE(2) },
107 { SYS_RES_IRQ, S3C24X0_INT_USBH, 0 },
108 { SYS_RES_IOPORT, S3C24X0_USBHC_PA_BASE, S3C24X0_USBHC_SIZE },
115 static device_t s3c24x0_add_child(device_t, int, const char *, int);
117 static int s3c24x0_probe(device_t);
118 static int s3c24x0_attach(device_t);
119 static void s3c24x0_identify(driver_t *, device_t);
120 static int s3c24x0_setup_intr(device_t, device_t, struct resource *, int,
121 driver_filter_t *, driver_intr_t *, void *, void **);
122 static int s3c24x0_teardown_intr(device_t, device_t, struct resource *,
124 static int s3c24x0_config_intr(device_t, int, enum intr_trigger,
126 static struct resource *s3c24x0_alloc_resource(device_t, device_t, int, int *,
127 u_long, u_long, u_long, u_int);
128 static int s3c24x0_activate_resource(device_t, device_t, int, int,
130 static int s3c24x0_release_resource(device_t, device_t, int, int,
132 static struct resource_list *s3c24x0_get_resource_list(device_t, device_t);
134 static void s3c24x0_identify_cpu(device_t);
136 static device_method_t s3c24x0_methods[] = {
137 DEVMETHOD(device_probe, s3c24x0_probe),
138 DEVMETHOD(device_attach, s3c24x0_attach),
139 DEVMETHOD(device_identify, s3c24x0_identify),
140 DEVMETHOD(bus_setup_intr, s3c24x0_setup_intr),
141 DEVMETHOD(bus_teardown_intr, s3c24x0_teardown_intr),
142 DEVMETHOD(bus_config_intr, s3c24x0_config_intr),
143 DEVMETHOD(bus_alloc_resource, s3c24x0_alloc_resource),
144 DEVMETHOD(bus_activate_resource, s3c24x0_activate_resource),
145 DEVMETHOD(bus_release_resource, s3c24x0_release_resource),
146 DEVMETHOD(bus_get_resource_list,s3c24x0_get_resource_list),
147 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
148 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
152 static driver_t s3c24x0_driver = {
155 sizeof(struct s3c24x0_softc),
157 static devclass_t s3c24x0_devclass;
159 DRIVER_MODULE(s3c24x0, nexus, s3c24x0_driver, s3c24x0_devclass, 0, 0);
161 struct s3c2xx0_softc *s3c2xx0_softc = NULL;
164 s3c24x0_add_child(device_t bus, int prio, const char *name, int unit)
167 struct s3c2xx0_ivar *ivar;
169 child = device_add_child_ordered(bus, prio, name, unit);
173 ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
175 device_delete_child(bus, child);
176 printf("Can't add alloc ivar\n");
179 device_set_ivars(child, ivar);
180 resource_list_init(&ivar->resources);
186 s3c24x0_enable_ext_intr(unsigned int irq)
194 } else if (irq <= 23) {
196 offset = (irq - 8) * 2;
200 /* Make the pin an interrupt source */
201 value = bus_space_read_4(s3c2xx0_softc->sc_iot,
202 s3c2xx0_softc->sc_gpio_ioh, reg);
203 value &= ~(3 << offset);
204 value |= 2 << offset;
205 bus_space_write_4(s3c2xx0_softc->sc_iot, s3c2xx0_softc->sc_gpio_ioh,
210 s3c24x0_setup_intr(device_t dev, device_t child,
211 struct resource *ires, int flags, driver_filter_t *filt,
212 driver_intr_t *intr, void *arg, void **cookiep)
216 error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt,
221 for (irq = rman_get_start(ires); irq <= rman_get_end(ires); irq++) {
222 if (irq >= S3C24X0_EXTIRQ_MIN && irq <= S3C24X0_EXTIRQ_MAX) {
223 /* Enable the external interrupt pin */
224 s3c24x0_enable_ext_intr(irq - S3C24X0_EXTIRQ_MIN);
231 s3c24x0_teardown_intr(device_t dev, device_t child, struct resource *res,
234 return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
238 s3c24x0_config_intr(device_t dev, int irq, enum intr_trigger trig,
239 enum intr_polarity pol)
241 uint32_t mask, reg, value;
244 /* Only external interrupts can be configured */
245 if (irq < S3C24X0_EXTIRQ_MIN || irq > S3C24X0_EXTIRQ_MAX)
248 /* There is no standard trigger or polarity for the bus */
249 if (trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM)
252 irq -= S3C24X0_EXTIRQ_MIN;
254 /* Get the bits to set */
256 if (pol == INTR_POLARITY_LOW) {
258 } else if (pol == INTR_POLARITY_HIGH) {
261 if (trig == INTR_TRIGGER_LEVEL) {
265 /* Get the register to set */
267 reg = GPIO_EXTINT(0);
269 } else if (irq <= 15) {
270 reg = GPIO_EXTINT(1);
271 offset = (irq - 8) * 4;
272 } else if (irq <= 23) {
273 reg = GPIO_EXTINT(2);
274 offset = (irq - 16) * 4;
279 /* Set the new signaling method */
280 value = bus_space_read_4(s3c2xx0_softc->sc_iot,
281 s3c2xx0_softc->sc_gpio_ioh, reg);
282 value &= ~(7 << offset);
283 value |= mask << offset;
284 bus_space_write_4(s3c2xx0_softc->sc_iot,
285 s3c2xx0_softc->sc_gpio_ioh, reg, value);
290 static struct resource *
291 s3c24x0_alloc_resource(device_t bus, device_t child, int type, int *rid,
292 u_long start, u_long end, u_long count, u_int flags)
294 struct resource_list_entry *rle;
295 struct s3c2xx0_ivar *ivar = device_get_ivars(child);
296 struct resource_list *rl = &ivar->resources;
297 struct resource *res = NULL;
299 if (device_get_parent(child) != bus)
300 return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
301 type, rid, start, end, count, flags));
303 rle = resource_list_find(rl, type, *rid);
305 /* There is a resource list. Use it */
307 panic("Resource rid %d type %d already in use", *rid,
309 if (start == 0UL && end == ~0UL) {
311 count = ulmax(count, rle->count);
312 end = ulmax(rle->end, start + count - 1);
315 * When allocating an irq with children irq's really
316 * allocate the children as it is those we are interested
317 * in receiving, not the parent.
319 if (type == SYS_RES_IRQ && start == end) {
321 case S3C24X0_INT_ADCTC:
322 start = S3C24X0_INT_TC;
323 end = S3C24X0_INT_ADC;
325 #ifdef S3C2440_INT_CAM
326 case S3C2440_INT_CAM:
327 start = S3C2440_INT_CAM_C;
328 end = S3C2440_INT_CAM_P;
334 count = end - start + 1;
340 res = rman_reserve_resource(
341 &s3c2xx0_softc->s3c2xx0_irq_rman, start, end,
342 count, flags, child);
347 res = rman_reserve_resource(
348 &s3c2xx0_softc->s3c2xx0_mem_rman,
349 start, end, count, flags, child);
351 panic("Unable to map address space %#lX-%#lX", start,
354 rman_set_bustag(res, s3c2xx0_bs_tag);
355 rman_set_bushandle(res, start);
356 if (flags & RF_ACTIVE) {
357 if (bus_activate_resource(child, type, *rid, res)) {
358 rman_release_resource(res);
366 rman_set_rid(res, *rid);
369 rle->start = rman_get_start(res);
370 rle->end = rman_get_end(res);
379 s3c24x0_activate_resource(device_t bus, device_t child, int type, int rid,
382 bus_space_handle_t p;
385 if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
386 error = bus_space_map(rman_get_bustag(r),
387 rman_get_bushandle(r), rman_get_size(r), 0, &p);
390 rman_set_bushandle(r, p);
392 return (rman_activate_resource(r));
396 s3c24x0_release_resource(device_t bus, device_t child, int type, int rid,
399 struct s3c2xx0_ivar *ivar = device_get_ivars(child);
400 struct resource_list *rl = &ivar->resources;
401 struct resource_list_entry *rle;
406 rle = resource_list_find(rl, type, rid);
410 rman_release_resource(r);
416 static struct resource_list *
417 s3c24x0_get_resource_list(device_t dev, device_t child)
419 struct s3c2xx0_ivar *ivar;
421 ivar = device_get_ivars(child);
422 return (&(ivar->resources));
426 s3c24x0_identify(driver_t *driver, device_t parent)
429 BUS_ADD_CHILD(parent, 0, "s3c24x0", 0);
433 s3c24x0_probe(device_t dev)
435 return (BUS_PROBE_NOWILDCARD);
439 s3c24x0_attach(device_t dev)
441 struct s3c24x0_softc *sc = device_get_softc(dev);
447 s3c2xx0_bs_tag = arm_base_bs_tag;
448 s3c2xx0_softc = &(sc->sc_sx);
449 sc->sc_sx.sc_iot = iot = s3c2xx0_bs_tag;
450 s3c2xx0_softc->s3c2xx0_irq_rman.rm_type = RMAN_ARRAY;
451 s3c2xx0_softc->s3c2xx0_irq_rman.rm_descr = "S3C24X0 IRQs";
452 s3c2xx0_softc->s3c2xx0_mem_rman.rm_type = RMAN_ARRAY;
453 s3c2xx0_softc->s3c2xx0_mem_rman.rm_descr = "S3C24X0 Device Registers";
454 /* Manage the registor memory space */
455 if ((rman_init(&s3c2xx0_softc->s3c2xx0_mem_rman) != 0) ||
456 (rman_manage_region(&s3c2xx0_softc->s3c2xx0_mem_rman,
457 S3C24X0_DEV_VA_OFFSET,
458 S3C24X0_DEV_VA_OFFSET + S3C24X0_DEV_VA_SIZE) != 0) ||
459 (rman_manage_region(&s3c2xx0_softc->s3c2xx0_mem_rman,
460 S3C24X0_DEV_START, S3C24X0_DEV_STOP) != 0))
461 panic("s3c24x0_attach: failed to set up register rman");
463 /* These are needed for things without a proper device to attach to */
464 sc->sc_sx.sc_intctl_ioh = S3C24X0_INTCTL_BASE;
465 sc->sc_sx.sc_gpio_ioh = S3C24X0_GPIO_BASE;
466 sc->sc_sx.sc_clkman_ioh = S3C24X0_CLKMAN_BASE;
467 sc->sc_sx.sc_wdt_ioh = S3C24X0_WDT_BASE;
468 sc->sc_timer_ioh = S3C24X0_TIMER_BASE;
473 s3c24x0_identify_cpu(dev);
476 * Manage the interrupt space.
477 * We need to put this after s3c24x0_identify_cpu as the avaliable
478 * interrupts change depending on which CPU we have.
480 if (sc->sc_sx.sc_cpu == CPU_S3C2410)
481 irqmax = S3C2410_SUBIRQ_MAX;
483 irqmax = S3C2440_SUBIRQ_MAX;
484 if (rman_init(&s3c2xx0_softc->s3c2xx0_irq_rman) != 0 ||
485 rman_manage_region(&s3c2xx0_softc->s3c2xx0_irq_rman, 0,
487 rman_manage_region(&s3c2xx0_softc->s3c2xx0_irq_rman,
488 S3C24X0_EXTIRQ_MIN, S3C24X0_EXTIRQ_MAX))
489 panic("s3c24x0_attach: failed to set up IRQ rman");
491 /* calculate current clock frequency */
492 s3c24x0_clock_freq(&sc->sc_sx);
493 device_printf(dev, "fclk %d MHz hclk %d MHz pclk %d MHz\n",
494 sc->sc_sx.sc_fclk / 1000000, sc->sc_sx.sc_hclk / 1000000,
495 sc->sc_sx.sc_pclk / 1000000);
498 * Attach children devices
501 for (i = 0; s3c24x0_children[i].name != NULL; i++) {
502 child = s3c24x0_add_child(dev, s3c24x0_children[i].prio,
503 s3c24x0_children[i].name, s3c24x0_children[i].unit);
504 for (j = 0; j < sizeof(s3c24x0_children[i].res) /
505 sizeof(s3c24x0_children[i].res[0]) &&
506 s3c24x0_children[i].res[j].type != 0; j++) {
507 bus_set_resource(child,
508 s3c24x0_children[i].res[j].type, 0,
509 s3c24x0_children[i].res[j].start,
510 s3c24x0_children[i].res[j].count);
514 bus_generic_probe(dev);
515 bus_generic_attach(dev);
521 s3c24x0_identify_cpu(device_t dev)
523 struct s3c24x0_softc *sc = device_get_softc(dev);
527 idcode = bus_space_read_4(sc->sc_sx.sc_iot, sc->sc_sx.sc_gpio_ioh,
530 for (i = 0; s3c2x0_cpu_id[i].name != NULL; i++) {
531 if (s3c2x0_cpu_id[i].idcode == idcode)
534 if (s3c2x0_cpu_id[i].name == NULL)
535 panic("Unknown CPU detected ((Chip ID: %#X)", idcode);
536 device_printf(dev, "Found %s CPU (Chip ID: %#X)\n",
537 s3c2x0_cpu_id[i].name, idcode);
538 sc->sc_sx.sc_cpu = s3c2x0_cpu_id[i].cpu;
542 * fill sc_pclk, sc_hclk, sc_fclk from values of clock controller register.
544 * s3c24{1,4}0_clock_freq2() is meant to be called from kernel startup routines.
545 * s3c24x0_clock_freq() is for after kernel initialization is done.
547 * Because they can be called before bus_space is available we need to use
548 * volatile pointers rather than bus_space_read.
551 s3c2410_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
553 uint32_t pllcon, divn;
554 unsigned int mdiv, pdiv, sdiv;
555 unsigned int f, h, p;
557 pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
558 divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
560 mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
561 pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
562 sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
564 f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
566 if (divn & S3C2410_CLKDIVN_HDIVN)
569 if (divn & CLKDIVN_PDIVN)
578 s3c2440_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk)
580 uint32_t pllcon, divn, camdivn;
581 unsigned int mdiv, pdiv, sdiv;
582 unsigned int f, h, p;
584 pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON);
585 divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN);
586 camdivn = *(volatile uint32_t *)(clkman_base + S3C2440_CLKMAN_CAMDIVN);
588 mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
589 pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
590 sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
592 f = (2 * (mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
594 switch((divn >> 1) & 3) {
601 if ((camdivn & S3C2440_CAMDIVN_HCLK4_HALF) ==
602 S3C2440_CAMDIVN_HCLK4_HALF)
608 if ((camdivn & S3C2440_CAMDIVN_HCLK3_HALF) ==
609 S3C2440_CAMDIVN_HCLK3_HALF)
616 if (divn & CLKDIVN_PDIVN)
625 s3c24x0_clock_freq(struct s3c2xx0_softc *sc)
629 va = sc->sc_clkman_ioh;
632 s3c2410_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk,
636 s3c2440_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk,
645 (void) disable_interrupts(PSR_I|PSR_F);
647 bus_space_write_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_wdt_ioh, WDT_WTCON,
648 WTCON_ENABLE | WTCON_CLKSEL_16 | WTCON_ENRST);
653 s3c24x0_sleep(int mode __unused)
657 reg = bus_space_read_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_clkman_ioh,
659 bus_space_write_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_clkman_ioh,
660 CLKMAN_CLKCON, reg | CLKCON_IDLE);
665 arm_get_next_irq(int last __unused)
670 if ((irq = bus_space_read_4(s3c2xx0_bs_tag,
671 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTOFFSET)) != 0) {
673 /* Clear the pending bit */
674 intpnd = bus_space_read_4(s3c2xx0_bs_tag,
675 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTPND);
676 bus_space_write_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
677 INTCTL_SRCPND, intpnd);
678 bus_space_write_4(s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh,
679 INTCTL_INTPND, intpnd);
682 case S3C24X0_INT_ADCTC:
683 case S3C24X0_INT_UART0:
684 case S3C24X0_INT_UART1:
685 case S3C24X0_INT_UART2:
686 /* Find the sub IRQ */
688 subirq &= bus_space_read_4(s3c2xx0_bs_tag,
689 s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND);
690 subirq &= ~(bus_space_read_4(s3c2xx0_bs_tag,
691 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK));
695 subirq = ffs(subirq) - 1;
697 /* Clear the sub irq pending bit */
698 bus_space_write_4(s3c2xx0_bs_tag,
699 s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND,
703 * Return the parent IRQ for UART
704 * as it is all we ever need
709 return (S3C24X0_SUBIRQ_MIN + subirq);
715 /* There is a 1:1 mapping to the IRQ we are handling */
716 return S3C24X0_INT_EXT(irq);
718 case S3C24X0_INT_4_7:
719 case S3C24X0_INT_8_23:
720 /* Find the external interrupt being called */
722 subirq &= bus_space_read_4(s3c2xx0_bs_tag,
723 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTPEND);
724 subirq &= ~bus_space_read_4(s3c2xx0_bs_tag,
725 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
729 subirq = ffs(subirq) - 1;
731 /* Clear the external irq pending bit */
732 bus_space_write_4(s3c2xx0_bs_tag,
733 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTPEND,
736 return S3C24X0_INT_EXT(subirq);
745 arm_mask_irq(uintptr_t irq)
749 if (irq >= S3C24X0_INT_EXT(0) && irq <= S3C24X0_INT_EXT(3)) {
750 /* External interrupt 0..3 are directly mapped to irq 0..3 */
751 irq -= S3C24X0_EXTIRQ_MIN;
753 if (irq < S3C24X0_SUBIRQ_MIN) {
754 mask = bus_space_read_4(s3c2xx0_bs_tag,
755 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK);
757 bus_space_write_4(s3c2xx0_bs_tag,
758 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK, mask);
759 } else if (irq < S3C24X0_EXTIRQ_MIN) {
760 mask = bus_space_read_4(s3c2xx0_bs_tag,
761 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK);
762 mask |= (1 << (irq - S3C24X0_SUBIRQ_MIN));
763 bus_space_write_4(s3c2xx0_bs_tag,
764 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask);
766 mask = bus_space_read_4(s3c2xx0_bs_tag,
767 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
768 mask |= (1 << (irq - S3C24X0_EXTIRQ_MIN));
769 bus_space_write_4(s3c2xx0_bs_tag,
770 s3c2xx0_softc->sc_intctl_ioh, GPIO_EINTMASK, mask);
775 arm_unmask_irq(uintptr_t irq)
779 if (irq >= S3C24X0_INT_EXT(0) && irq <= S3C24X0_INT_EXT(3)) {
780 /* External interrupt 0..3 are directly mapped to irq 0..3 */
781 irq -= S3C24X0_EXTIRQ_MIN;
783 if (irq < S3C24X0_SUBIRQ_MIN) {
784 mask = bus_space_read_4(s3c2xx0_bs_tag,
785 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK);
787 bus_space_write_4(s3c2xx0_bs_tag,
788 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK, mask);
789 } else if (irq < S3C24X0_EXTIRQ_MIN) {
790 mask = bus_space_read_4(s3c2xx0_bs_tag,
791 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK);
792 mask &= ~(1 << (irq - S3C24X0_SUBIRQ_MIN));
793 bus_space_write_4(s3c2xx0_bs_tag,
794 s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask);
796 mask = bus_space_read_4(s3c2xx0_bs_tag,
797 s3c2xx0_softc->sc_gpio_ioh, GPIO_EINTMASK);
798 mask &= ~(1 << (irq - S3C24X0_EXTIRQ_MIN));
799 bus_space_write_4(s3c2xx0_bs_tag,
800 s3c2xx0_softc->sc_intctl_ioh, GPIO_EINTMASK, mask);