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