1155324Simp/*-
2155324Simp * Copyright (c) 2005 Olivier Houchard.  All rights reserved.
3213496Scognet * Copyright (c) 2010 Greg Ansley.  All rights reserved.
4155324Simp *
5155324Simp * Redistribution and use in source and binary forms, with or without
6155324Simp * modification, are permitted provided that the following conditions
7155324Simp * are met:
8155324Simp * 1. Redistributions of source code must retain the above copyright
9155324Simp *    notice, this list of conditions and the following disclaimer.
10155324Simp * 2. Redistributions in binary form must reproduce the above copyright
11155324Simp *    notice, this list of conditions and the following disclaimer in the
12155324Simp *    documentation and/or other materials provided with the distribution.
13155324Simp *
14185265Simp * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15185265Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16185265Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17185265Simp * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18185265Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19185265Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20185265Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21185265Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22185265Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23185265Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24185265Simp * SUCH DAMAGE.
25155324Simp */
26155324Simp
27266277Sian#include "opt_platform.h"
28266277Sian
29155324Simp#include <sys/cdefs.h>
30155324Simp__FBSDID("$FreeBSD: releng/10.3/sys/arm/at91/at91.c 278727 2015-02-13 22:32:02Z ian $");
31155324Simp
32155324Simp#include <sys/param.h>
33155324Simp#include <sys/systm.h>
34155324Simp#include <sys/bus.h>
35155324Simp#include <sys/kernel.h>
36155324Simp#include <sys/malloc.h>
37155324Simp#include <sys/module.h>
38155324Simp
39155324Simp#include <vm/vm.h>
40155324Simp#include <vm/vm_kern.h>
41155324Simp#include <vm/pmap.h>
42155324Simp#include <vm/vm_page.h>
43155324Simp#include <vm/vm_extern.h>
44155324Simp
45278613Sian#include <machine/armreg.h>
46155324Simp#define	_ARM32_BUS_DMA_PRIVATE
47155324Simp#include <machine/bus.h>
48259364Sian#include <machine/devmap.h>
49155324Simp#include <machine/intr.h>
50155324Simp
51155324Simp#include <arm/at91/at91var.h>
52213496Scognet#include <arm/at91/at91_pmcvar.h>
53213496Scognet#include <arm/at91/at91_aicreg.h>
54155324Simp
55213496Scognetuint32_t at91_master_clock;
56187599Simp
57155324Simpstatic int
58278727Sianat91_bs_map(bus_space_tag_t tag, bus_addr_t bpa, bus_size_t size, int flags,
59155324Simp    bus_space_handle_t *bshp)
60155324Simp{
61155324Simp	vm_paddr_t pa, endpa;
62155324Simp
63155324Simp	pa = trunc_page(bpa);
64235718Simp	if (pa >= AT91_PA_BASE + 0xff00000) {
65266097Sian		*bshp = bpa - AT91_PA_BASE + AT91_BASE;
66155324Simp		return (0);
67161704Scognet	}
68266097Sian	if (pa >= AT91_BASE + 0xff00000) {
69266097Sian		*bshp = bpa;
70161704Scognet		return (0);
71266097Sian	}
72155324Simp	endpa = round_page(bpa + size);
73155324Simp
74266110Sian	*bshp = (vm_offset_t)pmap_mapdev(pa, endpa - pa) + (bpa - pa);
75236989Simp
76155324Simp	return (0);
77155324Simp}
78155324Simp
79155324Simpstatic void
80278727Sianat91_bs_unmap(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t size)
81155324Simp{
82278727Sian	vm_offset_t va;
83155324Simp
84278727Sian	va = (vm_offset_t)h;
85266277Sian	if (va >= AT91_BASE && va <= AT91_BASE + 0xff00000)
86266277Sian		return;
87278727Sian	pmap_unmapdev(va, size);
88155324Simp}
89155324Simp
90155324Simpstatic int
91278727Sianat91_bs_subregion(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t offset,
92155324Simp    bus_size_t size, bus_space_handle_t *nbshp)
93155324Simp{
94155324Simp
95155324Simp	*nbshp = bsh + offset;
96155324Simp	return (0);
97155324Simp}
98155324Simp
99156828Simpstatic void
100278727Sianat91_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, bus_size_t size, bus_size_t b,
101156828Simp    int a)
102156828Simp{
103156828Simp}
104156828Simp
105213496Scognetstruct arm32_dma_range *
106213496Scognetbus_dma_get_range(void)
107213496Scognet{
108213496Scognet
109213496Scognet	return (NULL);
110213496Scognet}
111213496Scognet
112213496Scognetint
113213496Scognetbus_dma_get_range_nb(void)
114213496Scognet{
115213496Scognet	return (0);
116213496Scognet}
117213496Scognet
118155324Simpbs_protos(generic);
119155324Simp
120155324Simpstruct bus_space at91_bs_tag = {
121278727Sian	/* privdata is whatever the implementer wants; unused in base tag */
122278727Sian	.bs_privdata	= NULL,
123155324Simp
124155324Simp	/* mapping/unmapping */
125278727Sian	.bs_map		= at91_bs_map,
126278727Sian	.bs_unmap	= at91_bs_unmap,
127278727Sian	.bs_subregion	= at91_bs_subregion,
128155324Simp
129155324Simp	/* allocation/deallocation */
130278727Sian	.bs_alloc	= generic_bs_alloc,
131278727Sian	.bs_free	= generic_bs_free,
132155324Simp
133155324Simp	/* barrier */
134278727Sian	.bs_barrier	= at91_barrier,
135155324Simp
136155324Simp	/* read (single) */
137278727Sian	.bs_r_1		= NULL,	/* Use inline code in bus.h */
138278727Sian	.bs_r_2		= NULL,	/* Use inline code in bus.h */
139278727Sian	.bs_r_4		= NULL,	/* Use inline code in bus.h */
140278727Sian	.bs_r_8		= NULL,	/* Use inline code in bus.h */
141155324Simp
142155324Simp	/* read multiple */
143278727Sian	.bs_rm_1	= generic_bs_rm_1,
144278727Sian	.bs_rm_2	= generic_bs_rm_2,
145278727Sian	.bs_rm_4	= generic_bs_rm_4,
146278727Sian	.bs_rm_8	= BS_UNIMPLEMENTED,
147155324Simp
148155324Simp	/* read region */
149278727Sian	.bs_rr_1	= generic_bs_rr_1,
150278727Sian	.bs_rr_2	= generic_bs_rr_2,
151278727Sian	.bs_rr_4	= generic_bs_rr_4,
152278727Sian	.bs_rr_8	= BS_UNIMPLEMENTED,
153155324Simp
154155324Simp	/* write (single) */
155278727Sian	.bs_w_1		= NULL,	/* Use inline code in bus.h */
156278727Sian	.bs_w_2		= NULL,	/* Use inline code in bus.h */
157278727Sian	.bs_w_4		= NULL,	/* Use inline code in bus.h */
158278727Sian	.bs_w_8		= NULL,	/* Use inline code in bus.h */
159155324Simp
160155324Simp	/* write multiple */
161278727Sian	.bs_wm_1	= generic_bs_wm_1,
162278727Sian	.bs_wm_2	= generic_bs_wm_2,
163278727Sian	.bs_wm_4	= generic_bs_wm_4,
164278727Sian	.bs_wm_8	= BS_UNIMPLEMENTED,
165155324Simp
166155324Simp	/* write region */
167278727Sian	.bs_wr_1	= generic_bs_wr_1,
168278727Sian	.bs_wr_2	= generic_bs_wr_2,
169278727Sian	.bs_wr_4	= generic_bs_wr_4,
170278727Sian	.bs_wr_8	= BS_UNIMPLEMENTED,
171155324Simp
172155324Simp	/* set multiple */
173278727Sian	.bs_sm_1	= BS_UNIMPLEMENTED,
174278727Sian	.bs_sm_2	= BS_UNIMPLEMENTED,
175278727Sian	.bs_sm_4	= BS_UNIMPLEMENTED,
176278727Sian	.bs_sm_8	= BS_UNIMPLEMENTED,
177155324Simp
178155324Simp	/* set region */
179278727Sian	.bs_sr_1	= generic_bs_sr_1,
180278727Sian	.bs_sr_2	= generic_bs_sr_2,
181278727Sian	.bs_sr_4	= generic_bs_sr_4,
182278727Sian	.bs_sr_8	= BS_UNIMPLEMENTED,
183155324Simp
184155324Simp	/* copy */
185278727Sian	.bs_c_1		= BS_UNIMPLEMENTED,
186278727Sian	.bs_c_2		= generic_bs_c_2,
187278727Sian	.bs_c_4		= BS_UNIMPLEMENTED,
188278727Sian	.bs_c_8		= BS_UNIMPLEMENTED,
189184310Sstas
190278727Sian	/* read stream (single) */
191278727Sian	.bs_r_1_s	= NULL,   /* Use inline code in bus.h */
192278727Sian	.bs_r_2_s	= NULL,   /* Use inline code in bus.h */
193278727Sian	.bs_r_4_s	= NULL,   /* Use inline code in bus.h */
194278727Sian	.bs_r_8_s	= NULL,   /* Use inline code in bus.h */
195184310Sstas
196184310Sstas	/* read multiple stream */
197278727Sian	.bs_rm_1_s	= generic_bs_rm_1,
198278727Sian	.bs_rm_2_s	= generic_bs_rm_2,
199278727Sian	.bs_rm_4_s	= generic_bs_rm_4,
200278727Sian	.bs_rm_8_s	= BS_UNIMPLEMENTED,
201184310Sstas
202184310Sstas	/* read region stream */
203278727Sian	.bs_rr_1_s	= generic_bs_rr_1,
204278727Sian	.bs_rr_2_s	= generic_bs_rr_2,
205278727Sian	.bs_rr_4_s	= generic_bs_rr_4,
206278727Sian	.bs_rr_8_s	= BS_UNIMPLEMENTED,
207184310Sstas
208278727Sian	/* write stream (single) */
209278727Sian	.bs_w_1_s	= NULL,   /* Use inline code in bus.h */
210278727Sian	.bs_w_2_s	= NULL,   /* Use inline code in bus.h */
211278727Sian	.bs_w_4_s	= NULL,   /* Use inline code in bus.h */
212278727Sian	.bs_w_8_s	= NULL,   /* Use inline code in bus.h */
213184310Sstas
214184310Sstas	/* write multiple stream */
215278727Sian	.bs_wm_1_s	= generic_bs_wm_1,
216278727Sian	.bs_wm_2_s	= generic_bs_wm_2,
217278727Sian	.bs_wm_4_s	= generic_bs_wm_4,
218278727Sian	.bs_wm_8_s	= BS_UNIMPLEMENTED,
219184310Sstas
220184310Sstas	/* write region stream */
221278727Sian	.bs_wr_1_s	= generic_bs_wr_1,
222278727Sian	.bs_wr_2_s	= generic_bs_wr_2,
223278727Sian	.bs_wr_4_s	= generic_bs_wr_4,
224278727Sian	.bs_wr_8_s	= BS_UNIMPLEMENTED,
225155324Simp};
226155324Simp
227266277Sian#ifndef FDT
228266277Sian
229266277Sianstatic struct at91_softc *at91_softc;
230266277Sian
231266277Sianstatic void at91_eoi(void *);
232266277Sian
233155324Simpstatic int
234155324Simpat91_probe(device_t dev)
235155324Simp{
236213496Scognet
237266065Sian	device_set_desc(dev, soc_info.name);
238265999Sian	return (BUS_PROBE_NOWILDCARD);
239155324Simp}
240155324Simp
241155324Simpstatic void
242155324Simpat91_identify(driver_t *drv, device_t parent)
243155324Simp{
244155324Simp
245155324Simp	BUS_ADD_CHILD(parent, 0, "atmelarm", 0);
246155324Simp}
247155324Simp
248238390Simpstatic void
249238390Simpat91_cpu_add_builtin_children(device_t dev, const struct cpu_devs *walker)
250238390Simp{
251238390Simp	int i;
252238390Simp
253238390Simp	for (i = 1; walker->name; i++, walker++) {
254238390Simp		at91_add_child(dev, i, walker->name, walker->unit,
255238390Simp		    walker->mem_base, walker->mem_len, walker->irq0,
256238390Simp		    walker->irq1, walker->irq2);
257238390Simp	}
258238390Simp}
259238390Simp
260155324Simpstatic int
261155324Simpat91_attach(device_t dev)
262155324Simp{
263155324Simp	struct at91_softc *sc = device_get_softc(dev);
264155324Simp
265265999Sian	arm_post_filter = at91_eoi;
266265999Sian
267155324Simp	at91_softc = sc;
268155324Simp	sc->sc_st = &at91_bs_tag;
269213496Scognet	sc->sc_sh = AT91_BASE;
270238389Simp	sc->sc_aic_sh = AT91_BASE + AT91_SYS_BASE;
271155324Simp	sc->dev = dev;
272213496Scognet
273155324Simp	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
274164432Simp	sc->sc_irq_rman.rm_descr = "AT91 IRQs";
275155324Simp	if (rman_init(&sc->sc_irq_rman) != 0 ||
276155324Simp	    rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
277155324Simp		panic("at91_attach: failed to set up IRQ rman");
278213496Scognet
279213496Scognet	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
280213496Scognet	sc->sc_mem_rman.rm_descr = "AT91 Memory";
281213496Scognet	if (rman_init(&sc->sc_mem_rman) != 0)
282155324Simp		panic("at91_attach: failed to set up memory rman");
283266110Sian	/*
284266110Sian	 * Manage the physical space, defined as being everything that isn't
285266110Sian	 * DRAM.
286266110Sian	 */
287266110Sian	if (rman_manage_region(&sc->sc_mem_rman, 0, PHYSADDR - 1) != 0)
288266110Sian		panic("at91_attach: failed to set up memory rman");
289266110Sian	if (rman_manage_region(&sc->sc_mem_rman, PHYSADDR + (256 << 20),
290266110Sian	    0xfffffffful) != 0)
291266110Sian		panic("at91_attach: failed to set up memory rman");
292155324Simp
293238390Simp        /*
294238390Simp         * Add this device's children...
295238390Simp         */
296238390Simp	at91_cpu_add_builtin_children(dev, soc_info.soc_data->soc_children);
297238398Simp	soc_info.soc_data->soc_clock_init();
298156828Simp
299155324Simp	bus_generic_probe(dev);
300155324Simp	bus_generic_attach(dev);
301278613Sian	enable_interrupts(PSR_I | PSR_F);
302155324Simp	return (0);
303155324Simp}
304155324Simp
305155324Simpstatic struct resource *
306155324Simpat91_alloc_resource(device_t dev, device_t child, int type, int *rid,
307155324Simp    u_long start, u_long end, u_long count, u_int flags)
308155324Simp{
309155324Simp	struct at91_softc *sc = device_get_softc(dev);
310155324Simp	struct resource_list_entry *rle;
311155324Simp	struct at91_ivar *ivar = device_get_ivars(child);
312155324Simp	struct resource_list *rl = &ivar->resources;
313266110Sian	bus_space_handle_t bsh;
314155324Simp
315155324Simp	if (device_get_parent(child) != dev)
316155324Simp		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
317155324Simp		    type, rid, start, end, count, flags));
318155324Simp
319155324Simp	rle = resource_list_find(rl, type, *rid);
320155324Simp	if (rle == NULL)
321155324Simp		return (NULL);
322155324Simp	if (rle->res)
323155324Simp		panic("Resource rid %d type %d already in use", *rid, type);
324155324Simp	if (start == 0UL && end == ~0UL) {
325155324Simp		start = rle->start;
326155324Simp		count = ulmax(count, rle->count);
327155324Simp		end = ulmax(rle->end, start + count - 1);
328155324Simp	}
329155324Simp	switch (type)
330155324Simp	{
331155324Simp	case SYS_RES_IRQ:
332155324Simp		rle->res = rman_reserve_resource(&sc->sc_irq_rman,
333155324Simp		    start, end, count, flags, child);
334155324Simp		break;
335155324Simp	case SYS_RES_MEMORY:
336182805Simp		rle->res = rman_reserve_resource(&sc->sc_mem_rman,
337182805Simp		    start, end, count, flags, child);
338184309Sstas		if (rle->res != NULL) {
339266110Sian			bus_space_map(&at91_bs_tag, start,
340266110Sian			    rman_get_size(rle->res), 0, &bsh);
341184309Sstas			rman_set_bustag(rle->res, &at91_bs_tag);
342266110Sian			rman_set_bushandle(rle->res, bsh);
343184309Sstas		}
344155324Simp		break;
345155324Simp	}
346155324Simp	if (rle->res) {
347155324Simp		rle->start = rman_get_start(rle->res);
348155324Simp		rle->end = rman_get_end(rle->res);
349155324Simp		rle->count = count;
350157891Simp		rman_set_rid(rle->res, *rid);
351155324Simp	}
352155324Simp	return (rle->res);
353155324Simp}
354155324Simp
355155324Simpstatic struct resource_list *
356155324Simpat91_get_resource_list(device_t dev, device_t child)
357155324Simp{
358155324Simp	struct at91_ivar *ivar;
359155324Simp
360155324Simp	ivar = device_get_ivars(child);
361155324Simp	return (&(ivar->resources));
362155324Simp}
363155324Simp
364155324Simpstatic int
365155324Simpat91_release_resource(device_t dev, device_t child, int type,
366155324Simp    int rid, struct resource *r)
367155324Simp{
368155324Simp	struct resource_list *rl;
369155324Simp	struct resource_list_entry *rle;
370155324Simp
371155324Simp	rl = at91_get_resource_list(dev, child);
372155324Simp	if (rl == NULL)
373155324Simp		return (EINVAL);
374155324Simp	rle = resource_list_find(rl, type, rid);
375155324Simp	if (rle == NULL)
376155324Simp		return (EINVAL);
377155324Simp	rman_release_resource(r);
378155324Simp	rle->res = NULL;
379155324Simp	return (0);
380155324Simp}
381155324Simp
382155324Simpstatic int
383155324Simpat91_setup_intr(device_t dev, device_t child,
384236989Simp    struct resource *ires, int flags, driver_filter_t *filt,
385236989Simp    driver_intr_t *intr, void *arg, void **cookiep)
386155324Simp{
387226832Skevlo	int error;
388161704Scognet
389238348Simp	if (rman_get_start(ires) == AT91_IRQ_SYSTEM && filt == NULL)
390167261Spiso		panic("All system interrupt ISRs must be FILTER");
391226832Skevlo	error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
392226832Skevlo	    filt, intr, arg, cookiep);
393226832Skevlo	if (error)
394226832Skevlo		return (error);
395226832Skevlo
396155324Simp	return (0);
397155324Simp}
398155324Simp
399155324Simpstatic int
400155324Simpat91_teardown_intr(device_t dev, device_t child, struct resource *res,
401155324Simp    void *cookie)
402155324Simp{
403155324Simp	struct at91_softc *sc = device_get_softc(dev);
404155324Simp
405236989Simp	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR,
406155324Simp	    1 << rman_get_start(res));
407155324Simp	return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
408155324Simp}
409155324Simp
410155324Simpstatic int
411155324Simpat91_activate_resource(device_t bus, device_t child, int type, int rid,
412155324Simp    struct resource *r)
413155324Simp{
414155324Simp#if 0
415155324Simp	u_long p;
416155324Simp	int error;
417155324Simp
418155324Simp	if (type == SYS_RES_MEMORY) {
419155324Simp		error = bus_space_map(rman_get_bustag(r),
420155324Simp		    rman_get_bushandle(r), rman_get_size(r), 0, &p);
421236989Simp		if (error)
422155324Simp			return (error);
423155324Simp		rman_set_bushandle(r, p);
424155324Simp	}
425155324Simp#endif
426155324Simp	return (rman_activate_resource(r));
427155324Simp}
428155324Simp
429155324Simpstatic int
430155324Simpat91_print_child(device_t dev, device_t child)
431155324Simp{
432155324Simp	struct at91_ivar *ivars;
433155324Simp	struct resource_list *rl;
434155324Simp	int retval = 0;
435155324Simp
436155324Simp	ivars = device_get_ivars(child);
437155324Simp	rl = &ivars->resources;
438155324Simp
439155324Simp	retval += bus_print_child_header(dev, child);
440155324Simp
441155324Simp	retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
442155324Simp	retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
443155324Simp	retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
444155324Simp	if (device_get_flags(dev))
445155324Simp		retval += printf(" flags %#x", device_get_flags(dev));
446155324Simp
447155324Simp	retval += bus_print_child_footer(dev, child);
448155324Simp
449155324Simp	return (retval);
450155324Simp}
451155324Simp
452178366Scognetstatic void
453178366Scognetat91_eoi(void *unused)
454178366Scognet{
455213496Scognet	bus_space_write_4(at91_softc->sc_st, at91_softc->sc_aic_sh,
456178366Scognet	    IC_EOICR, 0);
457178366Scognet}
458178366Scognet
459238334Simpvoid
460238334Simpat91_add_child(device_t dev, int prio, const char *name, int unit,
461238334Simp    bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2)
462238334Simp{
463238334Simp	device_t kid;
464238334Simp	struct at91_ivar *ivar;
465238334Simp
466238334Simp	kid = device_add_child_ordered(dev, prio, name, unit);
467238334Simp	if (kid == NULL) {
468238334Simp	    printf("Can't add child %s%d ordered\n", name, unit);
469238334Simp	    return;
470238334Simp	}
471238334Simp	ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
472238334Simp	if (ivar == NULL) {
473238334Simp		device_delete_child(dev, kid);
474238334Simp		printf("Can't add alloc ivar\n");
475238334Simp		return;
476238334Simp	}
477238334Simp	device_set_ivars(kid, ivar);
478238334Simp	resource_list_init(&ivar->resources);
479238334Simp	if (irq0 != -1) {
480238334Simp		bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
481238334Simp		if (irq0 != AT91_IRQ_SYSTEM)
482238334Simp			at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0);
483238334Simp	}
484238334Simp	if (irq1 != 0)
485238334Simp		bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
486238334Simp	if (irq2 != 0)
487238334Simp		bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
488266110Sian	/*
489266110Sian	 * Special case for on-board devices. These have their address
490266110Sian	 * defined relative to AT91_PA_BASE in all the register files we
491266110Sian	 * have. We could change this, but that's a lot of effort which
492266110Sian	 * will be obsoleted when FDT arrives.
493266110Sian	 */
494266110Sian	if (addr != 0 && addr < 0x10000000 && addr >= 0x0f000000)
495266110Sian		addr += AT91_PA_BASE;
496238334Simp	if (addr != 0)
497238334Simp		bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
498238334Simp}
499238334Simp
500155324Simpstatic device_method_t at91_methods[] = {
501155324Simp	DEVMETHOD(device_probe, at91_probe),
502155324Simp	DEVMETHOD(device_attach, at91_attach),
503155324Simp	DEVMETHOD(device_identify, at91_identify),
504155324Simp
505155324Simp	DEVMETHOD(bus_alloc_resource, at91_alloc_resource),
506155324Simp	DEVMETHOD(bus_setup_intr, at91_setup_intr),
507155324Simp	DEVMETHOD(bus_teardown_intr, at91_teardown_intr),
508155324Simp	DEVMETHOD(bus_activate_resource, at91_activate_resource),
509155324Simp	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
510155324Simp	DEVMETHOD(bus_get_resource_list,at91_get_resource_list),
511155324Simp	DEVMETHOD(bus_set_resource,	bus_generic_rl_set_resource),
512155324Simp	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
513155324Simp	DEVMETHOD(bus_release_resource,	at91_release_resource),
514155324Simp	DEVMETHOD(bus_print_child,	at91_print_child),
515155324Simp
516155324Simp	{0, 0},
517155324Simp};
518155324Simp
519155324Simpstatic driver_t at91_driver = {
520155324Simp	"atmelarm",
521155324Simp	at91_methods,
522155324Simp	sizeof(struct at91_softc),
523155324Simp};
524213496Scognet
525155324Simpstatic devclass_t at91_devclass;
526155324Simp
527155324SimpDRIVER_MODULE(atmelarm, nexus, at91_driver, at91_devclass, 0, 0);
528266277Sian#endif
529