The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


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

FreeBSD/Linux Kernel Cross Reference
sys/mips/atheros/ar531x/apb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016, Hiroki Mori
    3  * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice unmodified, this list of conditions, and the following
   11  *    disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include "opt_platform.h"
   30 #include "opt_ar531x.h"
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bus.h>
   38 #include <sys/interrupt.h>
   39 #include <sys/kernel.h>
   40 #include <sys/module.h>
   41 #include <sys/rman.h>
   42 #include <sys/malloc.h>
   43 #include <sys/pcpu.h>
   44 #include <sys/proc.h>
   45 #include <sys/pmc.h>
   46 #include <sys/pmckern.h>
   47 
   48 #include <machine/bus.h>
   49 #ifdef INTRNG
   50 #include <machine/intr.h>
   51 #else
   52 #include <machine/intr_machdep.h>
   53 #endif
   54 
   55 #ifdef INTRNG
   56 #include "pic_if.h"
   57 
   58 #define PIC_INTR_ISRC(sc, irq)  (&(sc)->pic_irqs[(irq)].isrc)
   59 #endif
   60 
   61 #include <mips/atheros/ar531x/apbvar.h>
   62 #include <mips/atheros/ar531x/ar5315reg.h>
   63 #include <mips/atheros/ar531x/ar5312reg.h>
   64 #include <mips/atheros/ar531x/ar5315_setup.h>
   65 
   66 #ifdef AR531X_APB_DEBUG
   67 #define dprintf printf
   68 #else 
   69 #define dprintf(x, arg...)
   70 #endif  /* AR531X_APB_DEBUG */
   71 
   72 static int      apb_activate_resource(device_t, device_t, int, int,
   73                     struct resource *);
   74 static device_t apb_add_child(device_t, u_int, const char *, int);
   75 static struct resource *
   76                 apb_alloc_resource(device_t, device_t, int, int *, rman_res_t,
   77                     rman_res_t, rman_res_t, u_int);
   78 static int      apb_attach(device_t);
   79 static int      apb_deactivate_resource(device_t, device_t, int, int,
   80                     struct resource *);
   81 static struct resource_list *
   82                 apb_get_resource_list(device_t, device_t);
   83 static void     apb_hinted_child(device_t, const char *, int);
   84 static int      apb_filter(void *);
   85 static int      apb_probe(device_t);
   86 static int      apb_release_resource(device_t, device_t, int, int,
   87                     struct resource *);
   88 #ifndef INTRNG
   89 static int      apb_setup_intr(device_t, device_t, struct resource *, int,
   90                     driver_filter_t *, driver_intr_t *, void *, void **);
   91 static int      apb_teardown_intr(device_t, device_t, struct resource *,
   92                     void *);
   93 #endif
   94 
   95 static void 
   96 apb_mask_irq(void *source)
   97 {
   98         unsigned int irq = (unsigned int)source;
   99         uint32_t reg;
  100 
  101         if(ar531x_soc >= AR531X_SOC_AR5315) {
  102                 reg = ATH_READ_REG(AR5315_SYSREG_BASE +
  103                         AR5315_SYSREG_MISC_INTMASK);
  104                 ATH_WRITE_REG(AR5315_SYSREG_BASE
  105                         + AR5315_SYSREG_MISC_INTMASK, reg & ~(1 << irq));
  106         } else {
  107                 reg = ATH_READ_REG(AR5312_SYSREG_BASE +
  108                         AR5312_SYSREG_MISC_INTMASK);
  109                 ATH_WRITE_REG(AR5312_SYSREG_BASE
  110                         + AR5312_SYSREG_MISC_INTMASK, reg & ~(1 << irq));
  111         }
  112 }
  113 
  114 static void 
  115 apb_unmask_irq(void *source)
  116 {
  117         uint32_t reg;
  118         unsigned int irq = (unsigned int)source;
  119 
  120         if(ar531x_soc >= AR531X_SOC_AR5315) {
  121                 reg = ATH_READ_REG(AR5315_SYSREG_BASE +
  122                         AR5315_SYSREG_MISC_INTMASK);
  123                 ATH_WRITE_REG(AR5315_SYSREG_BASE +
  124                         AR5315_SYSREG_MISC_INTMASK, reg | (1 << irq));
  125         } else {
  126                 reg = ATH_READ_REG(AR5312_SYSREG_BASE +
  127                         AR5312_SYSREG_MISC_INTMASK);
  128                 ATH_WRITE_REG(AR5312_SYSREG_BASE +
  129                         AR5312_SYSREG_MISC_INTMASK, reg | (1 << irq));
  130         }
  131 }
  132 
  133 #ifdef INTRNG
  134 static int
  135 apb_pic_register_isrcs(struct apb_softc *sc)
  136 {
  137         int error;
  138         uint32_t irq;
  139         struct intr_irqsrc *isrc;
  140         const char *name;
  141 
  142         name = device_get_nameunit(sc->apb_dev);
  143         for (irq = 0; irq < APB_NIRQS; irq++) {
  144                 sc->pic_irqs[irq].irq = irq;
  145                 isrc = PIC_INTR_ISRC(sc, irq);
  146                 error = intr_isrc_register(isrc, sc->apb_dev, 0, "%s", name);
  147                 if (error != 0) {
  148                         /* XXX call intr_isrc_deregister */
  149                         device_printf(sc->apb_dev, "%s failed", __func__);
  150                         return (error);
  151                 }
  152         }
  153 
  154         return (0);
  155 }
  156 
  157 static inline intptr_t
  158 pic_xref(device_t dev)
  159 {
  160         return (0);
  161 }
  162 #endif
  163 
  164 static int
  165 apb_probe(device_t dev)
  166 {
  167 #ifdef INTRNG
  168         device_set_desc(dev, "APB Bus bridge INTRNG");
  169 #else
  170         device_set_desc(dev, "APB Bus bridge");
  171 #endif
  172 
  173         return (0);
  174 }
  175 
  176 static int
  177 apb_attach(device_t dev)
  178 {
  179         struct apb_softc *sc = device_get_softc(dev);
  180 #ifdef INTRNG
  181         intptr_t xref = pic_xref(dev);
  182         int miscirq;
  183 #else
  184         int rid = 0;
  185 #endif
  186 
  187         sc->apb_dev = dev;
  188 
  189         sc->apb_mem_rman.rm_type = RMAN_ARRAY;
  190         sc->apb_mem_rman.rm_descr = "APB memory window";
  191 
  192         if(ar531x_soc >= AR531X_SOC_AR5315) {
  193                 if (rman_init(&sc->apb_mem_rman) != 0 ||
  194                     rman_manage_region(&sc->apb_mem_rman, 
  195                         AR5315_APB_BASE, 
  196                         AR5315_APB_BASE + AR5315_APB_SIZE - 1) != 0)
  197                         panic("apb_attach: failed to set up memory rman");
  198         } else {
  199                 if (rman_init(&sc->apb_mem_rman) != 0 ||
  200                     rman_manage_region(&sc->apb_mem_rman, 
  201                         AR5312_APB_BASE, 
  202                         AR5312_APB_BASE + AR5312_APB_SIZE - 1) != 0)
  203                         panic("apb_attach: failed to set up memory rman");
  204         }
  205 
  206         sc->apb_irq_rman.rm_type = RMAN_ARRAY;
  207         sc->apb_irq_rman.rm_descr = "APB IRQ";
  208 
  209         if (rman_init(&sc->apb_irq_rman) != 0 ||
  210             rman_manage_region(&sc->apb_irq_rman, 
  211                         APB_IRQ_BASE, APB_IRQ_END) != 0)
  212                 panic("apb_attach: failed to set up IRQ rman");
  213 
  214 #ifndef INTRNG
  215         if ((sc->sc_misc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 
  216             RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  217                 device_printf(dev, "unable to allocate IRQ resource\n");
  218                 return (ENXIO);
  219         }
  220 
  221         if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC, 
  222             apb_filter, NULL, sc, &sc->sc_misc_ih))) {
  223                 device_printf(dev,
  224                     "WARNING: unable to register interrupt handler\n");
  225                 return (ENXIO);
  226         }
  227 #else
  228         /* Register the interrupts */
  229         if (apb_pic_register_isrcs(sc) != 0) {
  230                 device_printf(dev, "could not register PIC ISRCs\n");
  231                 return (ENXIO);
  232         }
  233 
  234         /*
  235          * Now, when everything is initialized, it's right time to
  236          * register interrupt controller to interrupt framefork.
  237          */
  238         if (intr_pic_register(dev, xref) == NULL) {
  239                 device_printf(dev, "could not register PIC\n");
  240                 return (ENXIO);
  241         }
  242 
  243         if(ar531x_soc >= AR531X_SOC_AR5315) {
  244                 miscirq = AR5315_CPU_IRQ_MISC;
  245         } else {
  246                 miscirq = AR5312_IRQ_MISC;
  247         }
  248         cpu_establish_hardintr("aric", apb_filter, NULL, sc, miscirq,
  249             INTR_TYPE_MISC, NULL);
  250 #endif
  251 
  252         /* mask all misc interrupt */
  253         if(ar531x_soc >= AR531X_SOC_AR5315) {
  254                 ATH_WRITE_REG(AR5315_SYSREG_BASE
  255                         + AR5315_SYSREG_MISC_INTMASK, 0);
  256         } else {
  257                 ATH_WRITE_REG(AR5312_SYSREG_BASE
  258                         + AR5312_SYSREG_MISC_INTMASK, 0);
  259         }
  260 
  261         bus_generic_probe(dev);
  262         bus_enumerate_hinted_children(dev);
  263         bus_generic_attach(dev);
  264 
  265         return (0);
  266 }
  267 
  268 static struct resource *
  269 apb_alloc_resource(device_t bus, device_t child, int type, int *rid,
  270     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
  271 {
  272         struct apb_softc                *sc = device_get_softc(bus);
  273         struct apb_ivar                 *ivar = device_get_ivars(child);
  274         struct resource                 *rv;
  275         struct resource_list_entry      *rle;
  276         struct rman                     *rm;
  277         int                              isdefault, needactivate, passthrough;
  278 
  279         isdefault = (RMAN_IS_DEFAULT_RANGE(start, end));
  280         needactivate = flags & RF_ACTIVE;
  281         /*
  282          * Pass memory requests to nexus device
  283          */
  284         passthrough = (device_get_parent(child) != bus);
  285         rle = NULL;
  286 
  287         dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %jd, %d)\n",
  288             __func__, bus, child, type, *rid, (void *)(intptr_t)start,
  289             (void *)(intptr_t)end, count, flags);
  290 
  291         if (passthrough)
  292                 return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
  293                     rid, start, end, count, flags));
  294 
  295         /*
  296          * If this is an allocation of the "default" range for a given RID,
  297          * and we know what the resources for this device are (ie. they aren't
  298          * maintained by a child bus), then work out the start/end values.
  299          */
  300 
  301         if (isdefault) {
  302                 rle = resource_list_find(&ivar->resources, type, *rid);
  303                 if (rle == NULL) {
  304                         return (NULL);
  305                 }
  306 
  307                 if (rle->res != NULL) {
  308                         panic("%s: resource entry is busy", __func__);
  309                 }
  310                 start = rle->start;
  311                 end = rle->end;
  312                 count = rle->count;
  313 
  314                 dprintf("%s: default resource (%p, %p, %jd)\n",
  315                     __func__, (void *)(intptr_t)start,
  316                     (void *)(intptr_t)end, count);
  317         }
  318 
  319         switch (type) {
  320         case SYS_RES_IRQ:
  321                 rm = &sc->apb_irq_rman;
  322                 break;
  323         case SYS_RES_MEMORY:
  324                 rm = &sc->apb_mem_rman;
  325                 break;
  326         default:
  327                 printf("%s: unknown resource type %d\n", __func__, type);
  328                 return (0);
  329         }
  330 
  331         rv = rman_reserve_resource(rm, start, end, count, flags, child);
  332         if (rv == NULL) {
  333                 printf("%s: could not reserve resource %d\n", __func__, type);
  334                 return (0);
  335         }
  336 
  337         rman_set_rid(rv, *rid);
  338 
  339         if (needactivate) {
  340                 if (bus_activate_resource(child, type, *rid, rv)) {
  341                         printf("%s: could not activate resource\n", __func__);
  342                         rman_release_resource(rv);
  343                         return (0);
  344                 }
  345         }
  346 
  347         return (rv);
  348 }
  349 
  350 static int
  351 apb_activate_resource(device_t bus, device_t child, int type, int rid,
  352     struct resource *r)
  353 {
  354 
  355         /* XXX: should we mask/unmask IRQ here? */
  356         return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
  357                 type, rid, r));
  358 }
  359 
  360 static int
  361 apb_deactivate_resource(device_t bus, device_t child, int type, int rid,
  362     struct resource *r)
  363 {
  364 
  365         /* XXX: should we mask/unmask IRQ here? */
  366         return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
  367                 type, rid, r));
  368 }
  369 
  370 static int
  371 apb_release_resource(device_t dev, device_t child, int type,
  372     int rid, struct resource *r)
  373 {
  374         struct resource_list *rl;
  375         struct resource_list_entry *rle;
  376 
  377         rl = apb_get_resource_list(dev, child);
  378         if (rl == NULL)
  379                 return (EINVAL);
  380         rle = resource_list_find(rl, type, rid);
  381         if (rle == NULL)
  382                 return (EINVAL);
  383         rman_release_resource(r);
  384         rle->res = NULL;
  385 
  386         return (0);
  387 }
  388 
  389 
  390 static int
  391 apb_setup_intr(device_t bus, device_t child, struct resource *ires,
  392                 int flags, driver_filter_t *filt, driver_intr_t *handler,
  393                 void *arg, void **cookiep)
  394 {
  395         struct apb_softc *sc = device_get_softc(bus);
  396         int error;
  397         int irq;
  398 #ifndef INTRNG
  399         struct intr_event *event;
  400 #endif
  401 
  402 #ifdef INTRNG
  403         struct intr_irqsrc *isrc;
  404         const char *name;
  405         
  406         if ((rman_get_flags(ires) & RF_SHAREABLE) == 0)
  407                 flags |= INTR_EXCL;
  408 
  409         irq = rman_get_start(ires);
  410         isrc = PIC_INTR_ISRC(sc, irq);
  411         if(isrc->isrc_event == 0) {
  412                 error = intr_event_create(&isrc->isrc_event, (void *)irq,
  413                     0, irq, apb_mask_irq, apb_unmask_irq,
  414                     NULL, NULL, "apb intr%d:", irq);
  415                 if(error != 0)
  416                         return(error);
  417         }
  418         name = device_get_nameunit(child);
  419         error = intr_event_add_handler(isrc->isrc_event, name, filt, handler,
  420             arg, intr_priority(flags), flags, cookiep);
  421         return(error);
  422 #else
  423         irq = rman_get_start(ires);
  424 
  425         if (irq > APB_IRQ_END)
  426                 panic("%s: bad irq %d", __func__, irq);
  427 
  428         event = sc->sc_eventstab[irq];
  429         if (event == NULL) {
  430                 error = intr_event_create(&event, (void *)irq, 0, irq, 
  431                     apb_mask_irq, apb_unmask_irq,
  432                     NULL, NULL,
  433                     "apb intr%d:", irq);
  434 
  435                 if (error == 0) {
  436                         sc->sc_eventstab[irq] = event;
  437                         sc->sc_intr_counter[irq] =
  438                             mips_intrcnt_create(event->ie_name);
  439                 }
  440                 else
  441                         return (error);
  442         }
  443 
  444         intr_event_add_handler(event, device_get_nameunit(child), filt,
  445             handler, arg, intr_priority(flags), flags, cookiep);
  446         mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);
  447 
  448         apb_unmask_irq((void*)irq);
  449 
  450         return (0);
  451 #endif
  452 }
  453 
  454 #ifndef INTRNG
  455 static int
  456 apb_teardown_intr(device_t dev, device_t child, struct resource *ires,
  457     void *cookie)
  458 {
  459 #ifdef INTRNG
  460          return (intr_teardown_irq(child, ires, cookie));
  461 #else
  462         struct apb_softc *sc = device_get_softc(dev);
  463         int irq, result;
  464 
  465         irq = rman_get_start(ires);
  466         if (irq > APB_IRQ_END)
  467                 panic("%s: bad irq %d", __func__, irq);
  468 
  469         if (sc->sc_eventstab[irq] == NULL)
  470                 panic("Trying to teardown unoccupied IRQ");
  471 
  472         apb_mask_irq((void*)irq);
  473 
  474         result = intr_event_remove_handler(cookie);
  475         if (!result)
  476                 sc->sc_eventstab[irq] = NULL;
  477 
  478         return (result);
  479 #endif
  480 }
  481 
  482 
  483 static int
  484 apb_filter(void *arg)
  485 {
  486         struct apb_softc *sc = arg;
  487         struct intr_event *event;
  488         uint32_t reg, irq;
  489 
  490         if(ar531x_soc >= AR531X_SOC_AR5315)
  491                 reg = ATH_READ_REG(AR5315_SYSREG_BASE +
  492                         AR5315_SYSREG_MISC_INTSTAT);
  493         else
  494                 reg = ATH_READ_REG(AR5312_SYSREG_BASE +
  495                         AR5312_SYSREG_MISC_INTSTAT);
  496 
  497         for (irq = 0; irq < APB_NIRQS; irq++) {
  498                 if (reg & (1 << irq)) {
  499 
  500                         if(ar531x_soc >= AR531X_SOC_AR5315) {
  501                                 ATH_WRITE_REG(AR5315_SYSREG_BASE +
  502                                     AR5315_SYSREG_MISC_INTSTAT,
  503                                     reg & ~(1 << irq));
  504                         } else {
  505                                 ATH_WRITE_REG(AR5312_SYSREG_BASE +
  506                                     AR5312_SYSREG_MISC_INTSTAT,
  507                                     reg & ~(1 << irq));
  508                         }
  509 
  510                         event = sc->sc_eventstab[irq];
  511                         if (!event || CK_SLIST_EMPTY(&event->ie_handlers)) {
  512                                 if(irq == 1 && ar531x_soc < AR531X_SOC_AR5315) {
  513                                         ATH_READ_REG(AR5312_SYSREG_BASE +
  514                                                 AR5312_SYSREG_AHBPERR);
  515                                         ATH_READ_REG(AR5312_SYSREG_BASE +
  516                                                 AR5312_SYSREG_AHBDMAE);
  517                                 }
  518                                 /* Ignore non handle interrupts */
  519                                 if (irq != 0 && irq != 6)
  520                                         printf("Stray APB IRQ %d\n", irq);
  521 
  522                                 continue;
  523                         }
  524 
  525                         intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame);
  526                         mips_intrcnt_inc(sc->sc_intr_counter[irq]);
  527                 }
  528         }
  529 
  530         return (FILTER_HANDLED);
  531 }
  532 #else
  533 static int
  534 apb_filter(void *arg)
  535 {
  536         struct apb_softc *sc = arg;
  537         struct thread *td;
  538         uint32_t i, intr;
  539 
  540         td = curthread;
  541         /* Workaround: do not inflate intr nesting level */
  542         td->td_intr_nesting_level--;
  543 
  544         if(ar531x_soc >= AR531X_SOC_AR5315)
  545                 intr = ATH_READ_REG(AR5315_SYSREG_BASE +
  546                         AR5315_SYSREG_MISC_INTSTAT);
  547         else
  548                 intr = ATH_READ_REG(AR5312_SYSREG_BASE +
  549                         AR5312_SYSREG_MISC_INTSTAT);
  550 
  551         while ((i = fls(intr)) != 0) {
  552                 i--;
  553                 intr &= ~(1u << i);
  554 
  555                 if(i == 1 && ar531x_soc < AR531X_SOC_AR5315) {
  556                         ATH_READ_REG(AR5312_SYSREG_BASE +
  557                             AR5312_SYSREG_AHBPERR);
  558                         ATH_READ_REG(AR5312_SYSREG_BASE +
  559                             AR5312_SYSREG_AHBDMAE);
  560                 }
  561 
  562                 if (intr_isrc_dispatch(PIC_INTR_ISRC(sc, i),
  563                     curthread->td_intr_frame) != 0) {
  564                         device_printf(sc->apb_dev,
  565                             "Stray interrupt %u detected\n", i);
  566                         apb_mask_irq((void*)i);
  567                         continue;
  568                 }
  569         }
  570 
  571         KASSERT(i == 0, ("all interrupts handled"));
  572 
  573         td->td_intr_nesting_level++;
  574 
  575         return (FILTER_HANDLED);
  576 
  577 }
  578 
  579 #endif
  580 
  581 static void
  582 apb_hinted_child(device_t bus, const char *dname, int dunit)
  583 {
  584         device_t                child;
  585         long                    maddr;
  586         int                     msize;
  587         int                     irq;
  588         int                     result;
  589         int                     mem_hints_count;
  590 
  591         child = BUS_ADD_CHILD(bus, 0, dname, dunit);
  592 
  593         /*
  594          * Set hard-wired resources for hinted child using
  595          * specific RIDs.
  596          */
  597         mem_hints_count = 0;
  598         if (resource_long_value(dname, dunit, "maddr", &maddr) == 0)
  599                 mem_hints_count++;
  600         if (resource_int_value(dname, dunit, "msize", &msize) == 0)
  601                 mem_hints_count++;
  602 
  603         /* check if all info for mem resource has been provided */
  604         if ((mem_hints_count > 0) && (mem_hints_count < 2)) {
  605                 printf("Either maddr or msize hint is missing for %s%d\n",
  606                     dname, dunit);
  607         } else if (mem_hints_count) {
  608                 result = bus_set_resource(child, SYS_RES_MEMORY, 0,
  609                     maddr, msize);
  610                 if (result != 0)
  611                         device_printf(bus, 
  612                             "warning: bus_set_resource() failed\n");
  613         }
  614 
  615         if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
  616                 result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
  617                 if (result != 0)
  618                         device_printf(bus,
  619                             "warning: bus_set_resource() failed\n");
  620         }
  621 }
  622 
  623 static device_t
  624 apb_add_child(device_t bus, u_int order, const char *name, int unit)
  625 {
  626         device_t                child;
  627         struct apb_ivar *ivar;
  628 
  629         ivar = malloc(sizeof(struct apb_ivar), M_DEVBUF, M_WAITOK | M_ZERO);
  630         if (ivar == NULL) {
  631                 printf("Failed to allocate ivar\n");
  632                 return (0);
  633         }
  634         resource_list_init(&ivar->resources);
  635 
  636         child = device_add_child_ordered(bus, order, name, unit);
  637         if (child == NULL) {
  638                 printf("Can't add child %s%d ordered\n", name, unit);
  639                 return (0);
  640         }
  641 
  642         device_set_ivars(child, ivar);
  643 
  644         return (child);
  645 }
  646 
  647 /*
  648  * Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource
  649  * Provides pointer to resource_list for these routines
  650  */
  651 static struct resource_list *
  652 apb_get_resource_list(device_t dev, device_t child)
  653 {
  654         struct apb_ivar *ivar;
  655 
  656         ivar = device_get_ivars(child);
  657         return (&(ivar->resources));
  658 }
  659 
  660 #ifdef INTRNG
  661 static void
  662 apb_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
  663 {
  664         u_int irq;
  665 
  666         irq = ((struct apb_pic_irqsrc *)isrc)->irq;
  667         apb_unmask_irq((void*)irq);
  668 }
  669 
  670 static void
  671 apb_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
  672 {
  673         u_int irq;
  674 
  675         irq = ((struct apb_pic_irqsrc *)isrc)->irq;
  676         apb_mask_irq((void*)irq);
  677 }
  678 
  679 static void
  680 apb_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
  681 {
  682         apb_pic_disable_intr(dev, isrc);
  683 }
  684 
  685 static void
  686 apb_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
  687 {
  688         apb_pic_enable_intr(dev, isrc);
  689 }
  690 
  691 static void
  692 apb_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
  693 {
  694         uint32_t reg, irq;
  695 
  696         irq = ((struct apb_pic_irqsrc *)isrc)->irq;
  697         if(ar531x_soc >= AR531X_SOC_AR5315) {
  698                 reg = ATH_READ_REG(AR5315_SYSREG_BASE +
  699                         AR5315_SYSREG_MISC_INTSTAT);
  700                 ATH_WRITE_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_MISC_INTSTAT,
  701                     reg & ~(1 << irq));
  702         } else {
  703                 reg = ATH_READ_REG(AR5312_SYSREG_BASE +
  704                         AR5312_SYSREG_MISC_INTSTAT);
  705                 ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTSTAT,
  706                     reg & ~(1 << irq));
  707         }
  708 }
  709 
  710 static int
  711 apb_pic_map_intr(device_t dev, struct intr_map_data *data,
  712     struct intr_irqsrc **isrcp)
  713 {
  714         return (ENOTSUP);
  715 }
  716 
  717 #endif
  718 
  719 static device_method_t apb_methods[] = {
  720         DEVMETHOD(bus_activate_resource,        apb_activate_resource),
  721         DEVMETHOD(bus_add_child,                apb_add_child),
  722         DEVMETHOD(bus_alloc_resource,           apb_alloc_resource),
  723         DEVMETHOD(bus_deactivate_resource,      apb_deactivate_resource),
  724         DEVMETHOD(bus_get_resource_list,        apb_get_resource_list),
  725         DEVMETHOD(bus_hinted_child,             apb_hinted_child),
  726         DEVMETHOD(bus_release_resource,         apb_release_resource),
  727         DEVMETHOD(device_attach,                apb_attach),
  728         DEVMETHOD(device_probe,                 apb_probe),
  729         DEVMETHOD(bus_get_resource,             bus_generic_rl_get_resource),
  730         DEVMETHOD(bus_set_resource,             bus_generic_rl_set_resource),
  731 #ifdef INTRNG
  732         DEVMETHOD(pic_disable_intr,             apb_pic_disable_intr),
  733         DEVMETHOD(pic_enable_intr,              apb_pic_enable_intr),
  734         DEVMETHOD(pic_map_intr,                 apb_pic_map_intr),
  735         DEVMETHOD(pic_post_filter,              apb_pic_post_filter),
  736         DEVMETHOD(pic_post_ithread,             apb_pic_post_ithread),
  737         DEVMETHOD(pic_pre_ithread,              apb_pic_pre_ithread),
  738 
  739 //      DEVMETHOD(bus_setup_intr,               bus_generic_setup_intr),
  740 #else
  741         DEVMETHOD(bus_teardown_intr,            apb_teardown_intr),
  742 #endif
  743         DEVMETHOD(bus_setup_intr,               apb_setup_intr),
  744 
  745         DEVMETHOD_END
  746 };
  747 
  748 static driver_t apb_driver = {
  749         "apb",
  750         apb_methods,
  751         sizeof(struct apb_softc),
  752 };
  753 static devclass_t apb_devclass;
  754 
  755 EARLY_DRIVER_MODULE(apb, nexus, apb_driver, apb_devclass, 0, 0,
  756     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);

Cache object: d778e6ccf53aa5117667156f6d42b1e1


[ 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.