at91.c revision 178366
1/*-
2 * Copyright (c) 2005 Olivier Houchard.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include <sys/cdefs.h>
26__FBSDID("$FreeBSD: head/sys/arm/at91/at91.c 178366 2008-04-20 23:29:06Z cognet $");
27
28#include <sys/param.h>
29#include <sys/systm.h>
30#include <sys/bus.h>
31#include <sys/kernel.h>
32#include <sys/malloc.h>
33#include <sys/module.h>
34
35#include <vm/vm.h>
36#include <vm/vm_kern.h>
37#include <vm/pmap.h>
38#include <vm/vm_page.h>
39#include <vm/vm_extern.h>
40
41#define	_ARM32_BUS_DMA_PRIVATE
42#include <machine/bus.h>
43#include <machine/intr.h>
44
45#include <arm/at91/at91rm92reg.h>
46#include <arm/at91/at91var.h>
47
48static struct at91_softc *at91_softc;
49
50static void at91_eoi(void *);
51
52static int
53at91_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flags,
54    bus_space_handle_t *bshp)
55{
56	vm_paddr_t pa, endpa;
57
58	pa = trunc_page(bpa);
59	if (pa >= 0xfff00000) {
60		*bshp = pa - 0xf0000000 + 0xd0000000;
61		return (0);
62	}
63	if (pa >= 0xdff00000)
64		return (0);
65	endpa = round_page(bpa + size);
66
67	*bshp = (vm_offset_t)pmap_mapdev(pa, endpa - pa);
68
69	return (0);
70}
71
72static void
73at91_bs_unmap(void *t, bus_space_handle_t h, bus_size_t size)
74{
75	vm_offset_t va, endva;
76
77	va = trunc_page((vm_offset_t)t);
78	endva = va + round_page(size);
79
80	/* Free the kernel virtual mapping. */
81	kmem_free(kernel_map, va, endva - va);
82}
83
84static int
85at91_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset,
86    bus_size_t size, bus_space_handle_t *nbshp)
87{
88
89	*nbshp = bsh + offset;
90	return (0);
91}
92
93static void
94at91_barrier(void *t, bus_space_handle_t bsh, bus_size_t size, bus_size_t b,
95    int a)
96{
97}
98
99bs_protos(generic);
100bs_protos(generic_armv4);
101
102struct bus_space at91_bs_tag = {
103	/* cookie */
104	(void *) 0,
105
106	/* mapping/unmapping */
107	at91_bs_map,
108	at91_bs_unmap,
109	at91_bs_subregion,
110
111	/* allocation/deallocation */
112	NULL,
113	NULL,
114
115	/* barrier */
116	at91_barrier,
117
118	/* read (single) */
119	generic_bs_r_1,
120	generic_armv4_bs_r_2,
121	generic_bs_r_4,
122	NULL,
123
124	/* read multiple */
125	generic_bs_rm_1,
126	generic_armv4_bs_rm_2,
127	generic_bs_rm_4,
128	NULL,
129
130	/* read region */
131	generic_bs_rr_1,
132	generic_armv4_bs_rr_2,
133	generic_bs_rr_4,
134	NULL,
135
136	/* write (single) */
137	generic_bs_w_1,
138	generic_armv4_bs_w_2,
139	generic_bs_w_4,
140	NULL,
141
142	/* write multiple */
143	generic_bs_wm_1,
144	generic_armv4_bs_wm_2,
145	generic_bs_wm_4,
146	NULL,
147
148	/* write region */
149	NULL,
150	generic_armv4_bs_wr_2,
151	generic_bs_wr_4,
152	NULL,
153
154	/* set multiple */
155	NULL,
156	NULL,
157	NULL,
158	NULL,
159
160	/* set region */
161	NULL,
162	generic_armv4_bs_sr_2,
163	generic_bs_sr_4,
164	NULL,
165
166	/* copy */
167	NULL,
168	generic_armv4_bs_c_2,
169	NULL,
170	NULL,
171};
172
173static int
174at91_probe(device_t dev)
175{
176	device_set_desc(dev, "AT91 device bus");
177	arm_post_filter = at91_eoi;
178	return (0);
179}
180
181static void
182at91_identify(driver_t *drv, device_t parent)
183{
184
185	BUS_ADD_CHILD(parent, 0, "atmelarm", 0);
186}
187
188struct arm32_dma_range *
189bus_dma_get_range(void)
190{
191
192	return (NULL);
193}
194
195int
196bus_dma_get_range_nb(void)
197{
198	return (0);
199}
200
201extern void irq_entry(void);
202
203static void
204at91_add_child(device_t dev, int prio, const char *name, int unit,
205    bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2)
206{
207	device_t kid;
208	struct at91_ivar *ivar;
209
210	kid = device_add_child_ordered(dev, prio, name, unit);
211	if (kid == NULL) {
212	    printf("Can't add child %s%d ordered\n", name, unit);
213	    return;
214	}
215	ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
216	if (ivar == NULL) {
217		device_delete_child(dev, kid);
218		printf("Can't add alloc ivar\n");
219		return;
220	}
221	device_set_ivars(kid, ivar);
222	resource_list_init(&ivar->resources);
223	if (irq0 != -1)
224		bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
225	if (irq1 != 0)
226		bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
227	if (irq2 != 0)
228		bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
229	if (addr != 0)
230		bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
231}
232
233struct cpu_devs
234{
235	const char *name;
236	int unit;
237	bus_addr_t mem_base;
238	bus_size_t mem_len;
239	int irq0;
240	int irq1;
241	int irq2;
242};
243
244struct cpu_devs at91rm9200_devs[] =
245{
246	// All the "system" devices
247	{
248		"at91_st", 0,
249		AT91RM92_BASE + AT91RM92_ST_BASE, AT91RM92_ST_SIZE,
250		AT91RM92_IRQ_SYSTEM
251	},
252	{
253		"at91_pio", 0,
254		AT91RM92_BASE + AT91RM92_PIOA_BASE, AT91RM92_PIO_SIZE,
255		AT91RM92_IRQ_SYSTEM
256	},
257	{
258		"at91_pio", 1,
259		AT91RM92_BASE + AT91RM92_PIOB_BASE, AT91RM92_PIO_SIZE,
260		AT91RM92_IRQ_SYSTEM
261	},
262	{
263		"at91_pio", 2,
264		AT91RM92_BASE + AT91RM92_PIOC_BASE, AT91RM92_PIO_SIZE,
265		AT91RM92_IRQ_SYSTEM
266	},
267	{
268		"at91_pio", 3,
269		AT91RM92_BASE + AT91RM92_PIOD_BASE, AT91RM92_PIO_SIZE,
270		AT91RM92_IRQ_SYSTEM
271	},
272	{
273		"at91_pmc", 0,
274		AT91RM92_BASE + AT91RM92_PMC_BASE, AT91RM92_PMC_SIZE,
275		AT91RM92_IRQ_SYSTEM
276	},
277	{
278		"at91_aic", 0,
279		AT91RM92_BASE + AT91RM92_AIC_BASE, AT91RM92_AIC_SIZE,
280		0	// Interrupt controller has no interrupts!
281	},
282	{
283		"at91_rtc", 0,
284		AT91RM92_BASE + AT91RM92_RTC_BASE, AT91RM92_RTC_SIZE,
285		AT91RM92_IRQ_SYSTEM
286	},
287	{
288		"at91_mc", 0,
289		AT91RM92_BASE + AT91RM92_MC_BASE, AT91RM92_MC_SIZE,
290		AT91RM92_IRQ_SYSTEM
291	},
292
293	// All other devices
294	{
295		"at91_tc", 0,
296		AT91RM92_BASE + AT91RM92_TC0_BASE, AT91RM92_TC_SIZE,
297		AT91RM92_IRQ_TC0, AT91RM92_IRQ_TC1, AT91RM92_IRQ_TC2
298	},
299	{
300		"at91_tc", 1,
301		AT91RM92_BASE + AT91RM92_TC1_BASE, AT91RM92_TC_SIZE,
302		AT91RM92_IRQ_TC3, AT91RM92_IRQ_TC4, AT91RM92_IRQ_TC5
303	},
304	{
305		"at91_udp", 0,
306		AT91RM92_BASE + AT91RM92_UDP_BASE, AT91RM92_UDP_SIZE,
307		AT91RM92_IRQ_UDP
308	},
309	{
310		"at91_mci", 0,
311		AT91RM92_BASE + AT91RM92_MCI_BASE, AT91RM92_MCI_SIZE,
312		AT91RM92_IRQ_MCI
313	},
314	{
315		"at91_twi", 0,
316		AT91RM92_BASE + AT91RM92_TWI_BASE, AT91RM92_TWI_SIZE,
317		AT91RM92_IRQ_TWI
318	},
319	{
320		"ate", 0,
321		AT91RM92_BASE + AT91RM92_EMAC_BASE, AT91RM92_EMAC_SIZE,
322		AT91RM92_IRQ_EMAC
323	},
324#ifndef SKYEYE_WORKAROUNDS
325	{
326		"uart", 0,
327		AT91RM92_BASE + AT91RM92_DBGU_BASE, AT91RM92_DBGU_SIZE,
328		AT91RM92_IRQ_SYSTEM
329	},
330	{
331		"uart", 1,
332		AT91RM92_BASE + AT91RM92_USART0_BASE, AT91RM92_USART_SIZE,
333		AT91RM92_IRQ_USART0
334	},
335	{
336		"uart", 2,
337		AT91RM92_BASE + AT91RM92_USART1_BASE, AT91RM92_USART_SIZE,
338		AT91RM92_IRQ_USART1
339	},
340	{
341		"uart", 3,
342		AT91RM92_BASE + AT91RM92_USART2_BASE, AT91RM92_USART_SIZE,
343		AT91RM92_IRQ_USART2
344	},
345	{
346		"uart", 4,
347		AT91RM92_BASE + AT91RM92_USART3_BASE, AT91RM92_USART_SIZE,
348		AT91RM92_IRQ_USART3
349	},
350#else
351	{
352		"uart", 0,
353		AT91RM92_BASE + AT91RM92_USART0_BASE, AT91RM92_USART_SIZE,
354		AT91RM92_IRQ_USART0
355	},
356#endif
357	{
358		"at91_ssc", 0,
359		AT91RM92_BASE + AT91RM92_SSC0_BASE, AT91RM92_SSC_SIZE,
360		AT91RM92_IRQ_SSC0
361	},
362	{
363		"at91_ssc", 1,
364		AT91RM92_BASE + AT91RM92_SSC1_BASE, AT91RM92_SSC_SIZE,
365		AT91RM92_IRQ_SSC1
366	},
367	{
368		"at91_ssc", 2,
369		AT91RM92_BASE + AT91RM92_SSC2_BASE, AT91RM92_SSC_SIZE,
370		AT91RM92_IRQ_SSC2
371	},
372	{
373		"at91_spi", 0,
374		AT91RM92_BASE + AT91RM92_SPI_BASE, AT91RM92_SPI_SIZE,
375		AT91RM92_IRQ_SPI
376	},
377	{
378		"ohci", 0,
379		AT91RM92_OHCI_BASE, AT91RM92_OHCI_SIZE,
380		AT91RM92_IRQ_UHP
381	},
382	{	0, 0, 0, 0, 0 }
383};
384
385static void
386at91_cpu_add_builtin_children(device_t dev, struct at91_softc *sc)
387{
388	int i;
389	struct cpu_devs *walker;
390
391	// XXX should look at the device id in the DBGU register and
392	// XXX based on the CPU load in these devices
393	for (i = 0, walker = at91rm9200_devs; walker->name; i++, walker++) {
394		at91_add_child(dev, i, walker->name, walker->unit,
395		    walker->mem_base, walker->mem_len, walker->irq0,
396		    walker->irq1, walker->irq2);
397	}
398}
399
400#define NORMDEV 50
401
402/*
403 * Standard priority levels for the system.  0 is lowest and 7 is highest.
404 * These values are the ones Atmel uses for its Linux port, which differ
405 * a little form the ones that are in the standard distribution.  Also,
406 * the ones marked with 'TWEEK' are different based on experience.
407 */
408static int irq_prio[32] =
409{
410	7,	/* Advanced Interrupt Controller (FIQ) */
411	7,	/* System Peripherals */
412	1,	/* Parallel IO Controller A */
413	1,	/* Parallel IO Controller B */
414	1,	/* Parallel IO Controller C */
415	1,	/* Parallel IO Controller D */
416	5,	/* USART 0 */
417	5,	/* USART 1 */
418	5,	/* USART 2 */
419	5,	/* USART 3 */
420	0,	/* Multimedia Card Interface */
421	2,	/* USB Device Port */
422	4,	/* Two-Wire Interface */		/* TWEEK */
423	5,	/* Serial Peripheral Interface */
424	4,	/* Serial Synchronous Controller 0 */
425	6,	/* Serial Synchronous Controller 1 */	/* TWEEK */
426	4,	/* Serial Synchronous Controller 2 */
427	0,	/* Timer Counter 0 */
428	6,	/* Timer Counter 1 */			/* TWEEK */
429	0,	/* Timer Counter 2 */
430	0,	/* Timer Counter 3 */
431	0,	/* Timer Counter 4 */
432	0,	/* Timer Counter 5 */
433	2,	/* USB Host port */
434	3,	/* Ethernet MAC */
435	0,	/* Advanced Interrupt Controller (IRQ0) */
436	0,	/* Advanced Interrupt Controller (IRQ1) */
437	0,	/* Advanced Interrupt Controller (IRQ2) */
438	0,	/* Advanced Interrupt Controller (IRQ3) */
439	0,	/* Advanced Interrupt Controller (IRQ4) */
440	0,	/* Advanced Interrupt Controller (IRQ5) */
441 	0	/* Advanced Interrupt Controller (IRQ6) */
442};
443
444static int
445at91_attach(device_t dev)
446{
447	struct at91_softc *sc = device_get_softc(dev);
448	int i;
449
450	at91_softc = sc;
451	sc->sc_st = &at91_bs_tag;
452	sc->sc_sh = AT91RM92_BASE;
453	sc->dev = dev;
454	if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_SYS_BASE,
455	    AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0)
456		panic("Enable to map IRQ registers");
457	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
458	sc->sc_irq_rman.rm_descr = "AT91 IRQs";
459	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
460	sc->sc_mem_rman.rm_descr = "AT91 Memory";
461#if 0
462	sc->sc_usbmem_rman.rm_type = RMAN_ARRAY;
463	sc->sc_usbmem_rman.rm_descr = "AT91RM9200 USB Memory-mapped regs";
464#endif
465	if (rman_init(&sc->sc_irq_rman) != 0 ||
466	    rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
467		panic("at91_attach: failed to set up IRQ rman");
468	if (rman_init(&sc->sc_mem_rman) != 0 ||
469	    rman_manage_region(&sc->sc_mem_rman, 0xdff00000ul,
470	    0xdffffffful) != 0)
471		panic("at91_attach: failed to set up memory rman");
472	if (rman_manage_region(&sc->sc_mem_rman, AT91RM92_OHCI_BASE,
473	    AT91RM92_OHCI_BASE + AT91RM92_OHCI_SIZE - 1) != 0)
474		panic("at91_attach: failed to set up ohci memory");
475
476	for (i = 0; i < 32; i++) {
477		bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_SVR +
478		    i * 4, i);
479		/* Priority. */
480		bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_SMR + i * 4,
481		    irq_prio[i]);
482		if (i < 8)
483			bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_EOICR,
484			    1);
485	}
486	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_SPU, 32);
487	/* No debug. */
488	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_DCR, 0);
489	/* Disable and clear all interrupts. */
490	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IDCR, 0xffffffff);
491	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_ICCR, 0xffffffff);
492
493	/* XXX */
494	/* Disable all interrupts for RTC (0xe24 == RTC_IDR) */
495	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff);
496	/* DIsable all interrupts for DBGU */
497	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0x20c, 0xffffffff);
498	/* Disable all interrupts for the SDRAM controller */
499	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff);
500
501	at91_cpu_add_builtin_children(dev, sc);
502
503	bus_generic_probe(dev);
504	bus_generic_attach(dev);
505	enable_interrupts(I32_bit | F32_bit);
506	return (0);
507}
508
509static struct resource *
510at91_alloc_resource(device_t dev, device_t child, int type, int *rid,
511    u_long start, u_long end, u_long count, u_int flags)
512{
513	struct at91_softc *sc = device_get_softc(dev);
514	struct resource_list_entry *rle;
515	struct at91_ivar *ivar = device_get_ivars(child);
516	struct resource_list *rl = &ivar->resources;
517
518	if (device_get_parent(child) != dev)
519		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
520		    type, rid, start, end, count, flags));
521
522	rle = resource_list_find(rl, type, *rid);
523	if (rle == NULL)
524		return (NULL);
525	if (rle->res)
526		panic("Resource rid %d type %d already in use", *rid, type);
527	if (start == 0UL && end == ~0UL) {
528		start = rle->start;
529		count = ulmax(count, rle->count);
530		end = ulmax(rle->end, start + count - 1);
531	}
532	switch (type)
533	{
534	case SYS_RES_IRQ:
535		rle->res = rman_reserve_resource(&sc->sc_irq_rman,
536		    start, end, count, flags, child);
537		break;
538	case SYS_RES_MEMORY:
539#if 0
540		if (start >= 0x00300000 && start <= 0x003fffff)
541			rle->res = rman_reserve_resource(&sc->sc_usbmem_rman,
542			    start, end, count, flags, child);
543		else
544#endif
545			rle->res = rman_reserve_resource(&sc->sc_mem_rman,
546			    start, end, count, flags, child);
547		rman_set_bustag(rle->res, &at91_bs_tag);
548		rman_set_bushandle(rle->res, start);
549		break;
550	}
551	if (rle->res) {
552		rle->start = rman_get_start(rle->res);
553		rle->end = rman_get_end(rle->res);
554		rle->count = count;
555		rman_set_rid(rle->res, *rid);
556	}
557	return (rle->res);
558}
559
560static struct resource_list *
561at91_get_resource_list(device_t dev, device_t child)
562{
563	struct at91_ivar *ivar;
564
565	ivar = device_get_ivars(child);
566	return (&(ivar->resources));
567}
568
569static int
570at91_release_resource(device_t dev, device_t child, int type,
571    int rid, struct resource *r)
572{
573	struct resource_list *rl;
574	struct resource_list_entry *rle;
575
576	rl = at91_get_resource_list(dev, child);
577	if (rl == NULL)
578		return (EINVAL);
579	rle = resource_list_find(rl, type, rid);
580	if (rle == NULL)
581		return (EINVAL);
582	rman_release_resource(r);
583	rle->res = NULL;
584	return (0);
585}
586
587static int
588at91_setup_intr(device_t dev, device_t child,
589    struct resource *ires, int flags, driver_filter_t *filt,
590    driver_intr_t *intr, void *arg, void **cookiep)
591{
592	struct at91_softc *sc = device_get_softc(dev);
593
594	if (rman_get_start(ires) == AT91RM92_IRQ_SYSTEM && filt == NULL)
595		panic("All system interrupt ISRs must be FILTER");
596	BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt,
597	    intr, arg, cookiep);
598	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IECR,
599	    1 << rman_get_start(ires));
600	return (0);
601}
602
603static int
604at91_teardown_intr(device_t dev, device_t child, struct resource *res,
605    void *cookie)
606{
607	struct at91_softc *sc = device_get_softc(dev);
608
609	bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IDCR,
610	    1 << rman_get_start(res));
611	return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
612}
613
614static int
615at91_activate_resource(device_t bus, device_t child, int type, int rid,
616    struct resource *r)
617{
618#if 0
619	u_long p;
620	int error;
621
622	if (type == SYS_RES_MEMORY) {
623		error = bus_space_map(rman_get_bustag(r),
624		    rman_get_bushandle(r), rman_get_size(r), 0, &p);
625		if (error)
626			return (error);
627		rman_set_bushandle(r, p);
628	}
629#endif
630	return (rman_activate_resource(r));
631}
632
633static int
634at91_print_child(device_t dev, device_t child)
635{
636	struct at91_ivar *ivars;
637	struct resource_list *rl;
638	int retval = 0;
639
640	ivars = device_get_ivars(child);
641	rl = &ivars->resources;
642
643	retval += bus_print_child_header(dev, child);
644
645	retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
646	retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
647	retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
648	if (device_get_flags(dev))
649		retval += printf(" flags %#x", device_get_flags(dev));
650
651	retval += bus_print_child_footer(dev, child);
652
653	return (retval);
654}
655
656void
657arm_mask_irq(uintptr_t nb)
658{
659
660	bus_space_write_4(at91_softc->sc_st,
661	    at91_softc->sc_sys_sh, IC_IDCR, 1 << nb);
662
663}
664
665int
666arm_get_next_irq()
667{
668
669	int status;
670	int irq;
671
672	irq = bus_space_read_4(at91_softc->sc_st,
673	    at91_softc->sc_sys_sh, IC_IVR);
674	status = bus_space_read_4(at91_softc->sc_st,
675	    at91_softc->sc_sys_sh, IC_ISR);
676	if (status == 0) {
677		bus_space_write_4(at91_softc->sc_st,
678		    at91_softc->sc_sys_sh, IC_EOICR, 1);
679		return (-1);
680	}
681	return (irq);
682}
683
684void
685arm_unmask_irq(uintptr_t nb)
686{
687
688	bus_space_write_4(at91_softc->sc_st,
689	at91_softc->sc_sys_sh, IC_IECR, 1 << nb);
690	bus_space_write_4(at91_softc->sc_st, at91_softc->sc_sys_sh,
691	    IC_EOICR, 0);
692
693}
694
695static void
696at91_eoi(void *unused)
697{
698	bus_space_write_4(at91_softc->sc_st, at91_softc->sc_sys_sh,
699	    IC_EOICR, 0);
700}
701
702static device_method_t at91_methods[] = {
703	DEVMETHOD(device_probe, at91_probe),
704	DEVMETHOD(device_attach, at91_attach),
705	DEVMETHOD(device_identify, at91_identify),
706
707	DEVMETHOD(bus_alloc_resource, at91_alloc_resource),
708	DEVMETHOD(bus_setup_intr, at91_setup_intr),
709	DEVMETHOD(bus_teardown_intr, at91_teardown_intr),
710	DEVMETHOD(bus_activate_resource, at91_activate_resource),
711	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
712	DEVMETHOD(bus_get_resource_list,at91_get_resource_list),
713	DEVMETHOD(bus_set_resource,	bus_generic_rl_set_resource),
714	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
715	DEVMETHOD(bus_release_resource,	at91_release_resource),
716	DEVMETHOD(bus_print_child,	at91_print_child),
717
718	{0, 0},
719};
720
721static driver_t at91_driver = {
722	"atmelarm",
723	at91_methods,
724	sizeof(struct at91_softc),
725};
726static devclass_t at91_devclass;
727
728DRIVER_MODULE(atmelarm, nexus, at91_driver, at91_devclass, 0, 0);
729