[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/at91/at91.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.