FreeBSD/Linux Kernel Cross Reference
sys/arm/at91/at91.c
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: src/sys/arm/at91/at91.c,v 1.21 2008/11/25 00:13:26 imp Exp $");
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
49 static struct at91_softc *at91_softc;
50
51 static void at91_eoi(void *);
52
53 static int
54 at91_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
73 static void
74 at91_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
85 static int
86 at91_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
94 static void
95 at91_barrier(void *t, bus_space_handle_t bsh, bus_size_t size, bus_size_t b,
96 int a)
97 {
98 }
99
100 bs_protos(generic);
101 bs_protos(generic_armv4);
102
103 struct 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
210 static int
211 at91_probe(device_t dev)
212 {
213 device_set_desc(dev, "AT91 device bus");
214 arm_post_filter = at91_eoi;
215 return (0);
216 }
217
218 static void
219 at91_identify(driver_t *drv, device_t parent)
220 {
221
222 BUS_ADD_CHILD(parent, 0, "atmelarm", 0);
223 }
224
225 struct arm32_dma_range *
226 bus_dma_get_range(void)
227 {
228
229 return (NULL);
230 }
231
232 int
233 bus_dma_get_range_nb(void)
234 {
235 return (0);
236 }
237
238 extern void irq_entry(void);
239
240 static void
241 at91_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
270 struct 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
281 struct 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
422 static void
423 at91_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 */
445 static 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
481 static int
482 at91_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
542 static struct resource *
543 at91_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
589 static struct resource_list *
590 at91_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
598 static int
599 at91_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
616 static int
617 at91_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
632 static int
633 at91_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
643 static int
644 at91_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
662 static int
663 at91_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
685 void
686 arm_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
694 int
695 arm_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
713 void
714 arm_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
724 static void
725 at91_eoi(void *unused)
726 {
727 bus_space_write_4(at91_softc->sc_st, at91_softc->sc_sys_sh,
728 IC_EOICR, 0);
729 }
730
731 static 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
750 static driver_t at91_driver = {
751 "atmelarm",
752 at91_methods,
753 sizeof(struct at91_softc),
754 };
755 static devclass_t at91_devclass;
756
757 DRIVER_MODULE(atmelarm, nexus, at91_driver, at91_devclass, 0, 0);
758 Cache object: 4d870894c7f2db6f90116afc2ed76a89
|