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/powerpc/mpc85xx/ocpbus.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 2006 by Juniper Networks. 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  * 3. The name of the author may not be used to endorse or promote products
   13  *    derived from this software without specific prior written permission.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/ktr.h>
   35 #include <sys/kernel.h>
   36 #include <sys/module.h>
   37 #include <sys/bus.h>
   38 #include <sys/rman.h>
   39 #include <sys/malloc.h>
   40 
   41 #include <machine/spr.h>
   42 #include <machine/ocpbus.h>
   43 #include <machine/intr_machdep.h>
   44 #include <machine/md_var.h>
   45 #include <machine/vmparam.h>
   46 #include <machine/bootinfo.h>
   47 
   48 #include <powerpc/mpc85xx/ocpbus.h>
   49 #include <powerpc/mpc85xx/mpc85xx.h>
   50 
   51 #include "pic_if.h"
   52 
   53 extern struct bus_space bs_be_tag;
   54 
   55 struct ocpbus_softc {
   56         struct rman     sc_mem;
   57         struct rman     sc_irq;
   58 };
   59 
   60 struct ocp_devinfo {
   61         int             ocp_devtype;
   62         int             ocp_unit;
   63 };
   64 
   65 static int ocpbus_probe(device_t);
   66 static int ocpbus_attach(device_t);
   67 static int ocpbus_shutdown(device_t);
   68 static int ocpbus_get_resource(device_t, device_t, int, int, u_long *,
   69     u_long *);
   70 static struct resource *ocpbus_alloc_resource(device_t, device_t, int, int *,
   71     u_long, u_long, u_long, u_int);
   72 static int ocpbus_print_child(device_t, device_t);
   73 static int ocpbus_release_resource(device_t, device_t, int, int,
   74     struct resource *);
   75 static int ocpbus_read_ivar(device_t, device_t, int, uintptr_t *);
   76 static int ocpbus_setup_intr(device_t, device_t, struct resource *, int,
   77     driver_filter_t *, driver_intr_t *, void *, void **);
   78 static int ocpbus_teardown_intr(device_t, device_t, struct resource *, void *);
   79 static int ocpbus_config_intr(device_t, int, enum intr_trigger,
   80     enum intr_polarity);
   81 
   82 /*
   83  * Bus interface definition
   84  */
   85 static device_method_t ocpbus_methods[] = {
   86         /* Device interface */
   87         DEVMETHOD(device_probe,         ocpbus_probe),
   88         DEVMETHOD(device_attach,        ocpbus_attach),
   89         DEVMETHOD(device_shutdown,      ocpbus_shutdown),
   90 
   91         /* Bus interface */
   92         DEVMETHOD(bus_print_child,      ocpbus_print_child),
   93         DEVMETHOD(bus_read_ivar,        ocpbus_read_ivar),
   94         DEVMETHOD(bus_setup_intr,       ocpbus_setup_intr),
   95         DEVMETHOD(bus_teardown_intr,    ocpbus_teardown_intr),
   96         DEVMETHOD(bus_config_intr,      ocpbus_config_intr),
   97 
   98         DEVMETHOD(bus_get_resource,     ocpbus_get_resource),
   99         DEVMETHOD(bus_alloc_resource,   ocpbus_alloc_resource),
  100         DEVMETHOD(bus_release_resource, ocpbus_release_resource),
  101         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
  102         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
  103 
  104         { 0, 0 }
  105 };
  106 
  107 static driver_t ocpbus_driver = {
  108         "ocpbus",
  109         ocpbus_methods,
  110         sizeof(struct ocpbus_softc)
  111 };
  112 
  113 devclass_t ocpbus_devclass;
  114 
  115 DRIVER_MODULE(ocpbus, nexus, ocpbus_driver, ocpbus_devclass, 0, 0);
  116 
  117 static device_t
  118 ocpbus_mk_child(device_t dev, int type, int unit)
  119 {
  120         struct ocp_devinfo *dinfo;
  121         device_t child;
  122 
  123         child = device_add_child(dev, NULL, -1);
  124         if (child == NULL) {
  125                 device_printf(dev, "could not add child device\n");
  126                 return (NULL);
  127         }
  128         dinfo = malloc(sizeof(struct ocp_devinfo), M_DEVBUF, M_WAITOK|M_ZERO);
  129         dinfo->ocp_devtype = type;
  130         dinfo->ocp_unit = unit;
  131         device_set_ivars(child, dinfo);
  132         return (child);
  133 }
  134 
  135 static int
  136 ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
  137 {
  138         u_long addr, size;
  139 
  140         switch (type) {
  141         case SYS_RES_MEMORY:
  142                 switch (trgt) {
  143                 case OCP85XX_TGTIF_PCI0:
  144                         addr = 0x80000000;
  145                         size = 0x10000000;
  146                         break;
  147                 case OCP85XX_TGTIF_PCI1:
  148                         addr = 0x90000000;
  149                         size = 0x10000000;
  150                         break;
  151                 case OCP85XX_TGTIF_PCI2:
  152                         addr = 0xA0000000;
  153                         size = 0x10000000;
  154                         break;
  155                 case OCP85XX_TGTIF_PCI3:
  156                         addr = 0xB0000000;
  157                         size = 0x10000000;
  158                         break;
  159                 default:
  160                         return (EINVAL);
  161                 }
  162                 break;
  163         case SYS_RES_IOPORT:
  164                 switch (trgt) {
  165                 case OCP85XX_TGTIF_PCI0:
  166                         addr = 0xfee00000;
  167                         size = 0x00010000;
  168                         break;
  169                 case OCP85XX_TGTIF_PCI1:
  170                         addr = 0xfee10000;
  171                         size = 0x00010000;
  172                         break;
  173                 case OCP85XX_TGTIF_PCI2:
  174                         addr = 0xfee20000;
  175                         size = 0x00010000;
  176                         break;
  177                 case OCP85XX_TGTIF_PCI3:
  178                         addr = 0xfee30000;
  179                         size = 0x00010000;
  180                         break;
  181                 default:
  182                         return (EINVAL);
  183                 }
  184                 break;
  185         default:
  186                 return (EINVAL);
  187         }
  188 
  189         *startp = addr;
  190         *countp = size;
  191 
  192         return (law_enable(trgt, *startp, *countp));
  193 }
  194 
  195 static int
  196 ocpbus_probe(device_t dev)
  197 {
  198 
  199         device_set_desc(dev, "Freescale on-chip peripherals bus");
  200         return (BUS_PROBE_DEFAULT);
  201 }
  202 
  203 static int
  204 ocpbus_attach(device_t dev)
  205 {
  206         struct ocpbus_softc *sc;
  207         int error, i, tgt, law_max;
  208         uint32_t sr;
  209         u_long start, end;
  210 
  211         sc = device_get_softc(dev);
  212 
  213         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_I2C, 0);
  214         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_I2C, 1);
  215         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_UART, 0);
  216         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_UART, 1);
  217         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_LBC, 0);
  218         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 0);
  219         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 1);
  220         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 2);
  221         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PCIB, 3);
  222         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 0);
  223         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 1);
  224         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 2);
  225         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_TSEC, 3);
  226         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_PIC, 0);
  227         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_QUICC, 0);
  228         ocpbus_mk_child(dev, OCPBUS_DEVTYPE_SEC, 0);
  229 
  230         /* Set up IRQ rman */
  231         start = 0;
  232         end = INTR_VECTORS - 1;
  233         sc->sc_irq.rm_start = start;
  234         sc->sc_irq.rm_end = end;
  235         sc->sc_irq.rm_type = RMAN_ARRAY;
  236         sc->sc_irq.rm_descr = "Interrupt request lines";
  237         if (rman_init(&sc->sc_irq) ||
  238             rman_manage_region(&sc->sc_irq, start, end))
  239                 panic("ocpbus_attach IRQ rman");
  240 
  241         /* Set up I/O mem rman */
  242         sc->sc_mem.rm_type = RMAN_ARRAY;
  243         sc->sc_mem.rm_descr = "OCPBus Device Memory";
  244         error = rman_init(&sc->sc_mem);
  245         if (error) {
  246                 device_printf(dev, "rman_init() failed. error = %d\n", error);
  247                 return (error);
  248         }
  249 
  250         error = rman_manage_region(&sc->sc_mem, CCSRBAR_VA,
  251             CCSRBAR_VA + CCSRBAR_SIZE - 1);
  252         if (error) {
  253                 device_printf(dev, "rman_manage_region() failed. error = %d\n",
  254                     error);
  255                 return (error);
  256         }
  257 
  258         /*
  259          * Clear local access windows. Skip DRAM entries, so we don't shoot
  260          * ourselves in the foot.
  261          */
  262         law_max = law_getmax();
  263         for (i = 0; i < law_max; i++) {
  264                 sr = ccsr_read4(OCP85XX_LAWSR(i));
  265                 if ((sr & 0x80000000) == 0)
  266                         continue;
  267                 tgt = (sr & 0x01f00000) >> 20;
  268                 if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 ||
  269                     tgt == OCP85XX_TGTIF_RAM_INTL)
  270                         continue;
  271 
  272                 ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff);
  273         }
  274 
  275         if (bootverbose)
  276                 device_printf(dev, "PORDEVSR=%08x, PORDEVSR2=%08x\n",
  277                     ccsr_read4(OCP85XX_PORDEVSR),
  278                     ccsr_read4(OCP85XX_PORDEVSR2));
  279 
  280         for (i = PIC_IRQ_START; i < PIC_IRQ_START + 4; i++)
  281                 powerpc_config_intr(i, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
  282 
  283         return (bus_generic_attach(dev));
  284 }
  285 
  286 static int
  287 ocpbus_shutdown(device_t dev)
  288 {
  289 
  290         return(0);
  291 }
  292 
  293 struct ocp_resource {
  294         int     sr_devtype;
  295         int     sr_unit;
  296         int     sr_resource;
  297         int     sr_rid;
  298         int     sr_offset;
  299         int     sr_size;
  300 };
  301 
  302 const struct ocp_resource mpc8555_resources[] = {
  303         {OCPBUS_DEVTYPE_PIC, 0, SYS_RES_MEMORY, 0, OCP85XX_OPENPIC_OFF,
  304             OCP85XX_OPENPIC_SIZE},
  305 
  306         {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_MEMORY, 0, OCP85XX_QUICC_OFF,
  307             OCP85XX_QUICC_SIZE},
  308         {OCPBUS_DEVTYPE_QUICC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(30), 1},
  309 
  310         {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_MEMORY, 0, OCP85XX_TSEC0_OFF,
  311             OCP85XX_TSEC_SIZE},
  312         {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(13), 1},
  313         {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 1, PIC_IRQ_INT(14), 1},
  314         {OCPBUS_DEVTYPE_TSEC, 0, SYS_RES_IRQ, 2, PIC_IRQ_INT(18), 1},
  315         {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_MEMORY, 0, OCP85XX_TSEC1_OFF,
  316             OCP85XX_TSEC_SIZE},
  317         {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(19), 1},
  318         {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 1, PIC_IRQ_INT(20), 1},
  319         {OCPBUS_DEVTYPE_TSEC, 1, SYS_RES_IRQ, 2, PIC_IRQ_INT(24), 1},
  320         {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_MEMORY, 0, OCP85XX_TSEC2_OFF,
  321             OCP85XX_TSEC_SIZE},
  322         {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 0, PIC_IRQ_INT(15), 1},
  323         {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 1, PIC_IRQ_INT(16), 1},
  324         {OCPBUS_DEVTYPE_TSEC, 2, SYS_RES_IRQ, 2, PIC_IRQ_INT(17), 1},
  325         {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_MEMORY, 0, OCP85XX_TSEC3_OFF,
  326             OCP85XX_TSEC_SIZE},
  327         {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 0, PIC_IRQ_INT(21), 1},
  328         {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 1, PIC_IRQ_INT(22), 1},
  329         {OCPBUS_DEVTYPE_TSEC, 3, SYS_RES_IRQ, 2, PIC_IRQ_INT(23), 1},
  330 
  331         {OCPBUS_DEVTYPE_UART, 0, SYS_RES_MEMORY, 0, OCP85XX_UART0_OFF,
  332             OCP85XX_UART_SIZE},
  333         {OCPBUS_DEVTYPE_UART, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(26), 1},
  334         {OCPBUS_DEVTYPE_UART, 1, SYS_RES_MEMORY, 0, OCP85XX_UART1_OFF,
  335             OCP85XX_UART_SIZE},
  336         {OCPBUS_DEVTYPE_UART, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(26), 1},
  337 
  338         {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_MEMORY, 0, OCP85XX_PCI0_OFF,
  339             OCP85XX_PCI_SIZE},
  340         {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI0},
  341         {OCPBUS_DEVTYPE_PCIB, 0, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI0},
  342         {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_MEMORY, 0, OCP85XX_PCI1_OFF,
  343             OCP85XX_PCI_SIZE},
  344         {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI1},
  345         {OCPBUS_DEVTYPE_PCIB, 1, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI1},
  346         {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_MEMORY, 0, OCP85XX_PCI2_OFF,
  347             OCP85XX_PCI_SIZE},
  348         {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI2},
  349         {OCPBUS_DEVTYPE_PCIB, 2, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI2},
  350         {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_MEMORY, 0, OCP85XX_PCI3_OFF,
  351             OCP85XX_PCI_SIZE},
  352         {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_PCI3},
  353         {OCPBUS_DEVTYPE_PCIB, 3, SYS_RES_IOPORT, 1, 0, OCP85XX_TGTIF_PCI3},
  354 
  355         {OCPBUS_DEVTYPE_LBC, 0, SYS_RES_MEMORY, 0, OCP85XX_LBC_OFF,
  356             OCP85XX_LBC_SIZE},
  357 
  358         {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_MEMORY, 0, OCP85XX_I2C0_OFF,
  359             OCP85XX_I2C_SIZE},
  360         {OCPBUS_DEVTYPE_I2C, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(27), 1},
  361         {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_MEMORY, 0, OCP85XX_I2C1_OFF,
  362             OCP85XX_I2C_SIZE},
  363         {OCPBUS_DEVTYPE_I2C, 1, SYS_RES_IRQ, 0, PIC_IRQ_INT(27), 1},
  364 
  365         {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_MEMORY, 0, OCP85XX_SEC_OFF,
  366             OCP85XX_SEC_SIZE},
  367         {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 0, PIC_IRQ_INT(29), 1},
  368         {OCPBUS_DEVTYPE_SEC, 0, SYS_RES_IRQ, 1, PIC_IRQ_INT(42), 1},
  369 
  370         {0}
  371 };
  372 
  373 static int
  374 ocpbus_get_resource(device_t dev, device_t child, int type, int rid,
  375     u_long *startp, u_long *countp)
  376 {
  377         const struct ocp_resource *res;
  378         struct ocp_devinfo *dinfo;
  379         u_long start = 0, count = 0;
  380         int error;
  381 
  382         dinfo = device_get_ivars(child);
  383 
  384         /*
  385          * Lookup the correct values.
  386          */
  387         res = mpc8555_resources;
  388         for (; res->sr_devtype; res++) {
  389                 if (res->sr_devtype != dinfo->ocp_devtype)
  390                         continue;
  391                 if (res->sr_unit != dinfo->ocp_unit)
  392                         continue;
  393                 if (res->sr_rid != rid)
  394                         continue;
  395                 if (res->sr_resource != type)
  396                         continue;
  397 
  398                 if (res->sr_offset != 0) {
  399                         error = 0;
  400                         switch (type) {
  401                         case SYS_RES_MEMORY:
  402                                 start = res->sr_offset + CCSRBAR_VA;
  403                                 break;
  404                         case SYS_RES_IRQ:
  405                                 start = res->sr_offset;
  406                                 break;
  407                         default:
  408                                 error = EINVAL;
  409                                 break;
  410                         }
  411                         count = res->sr_size;
  412                 } else
  413                         error = ocpbus_write_law(res->sr_size, type, &start,
  414                             &count);
  415 
  416                 if (!error) {
  417                         if (startp != NULL)
  418                                 *startp = start;
  419                         if (countp != NULL)
  420                                 *countp = count;
  421                 }
  422                 return (error);
  423         }
  424 
  425         return (ENOENT);
  426 }
  427 
  428 static struct resource *
  429 ocpbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
  430     u_long start, u_long end, u_long count, u_int flags)
  431 {
  432         struct ocpbus_softc *sc;
  433         struct resource *rv;
  434         int error;
  435 
  436         sc = device_get_softc(dev);
  437 
  438         switch (type) {
  439         case SYS_RES_IRQ:
  440                 if (start == 0ul && end == ~0ul) {
  441                         error = ocpbus_get_resource(dev, child, type, *rid,
  442                             &start, &count);
  443                         if (error)
  444                                 return (NULL);
  445                 }
  446 
  447                 rv = rman_reserve_resource(&sc->sc_irq, start,
  448                     start + count - 1, count, flags, child);
  449                 if (rv == NULL)
  450                         return (NULL);
  451                 break;
  452 
  453         case SYS_RES_MEMORY:
  454                 if (start != 0ul || end != ~0ul)
  455                         return (NULL);
  456 
  457                 error = ocpbus_get_resource(dev, child, type, *rid, &start,
  458                     &count);
  459                 if (error)
  460                         return (NULL);
  461 
  462                 rv = rman_reserve_resource(&sc->sc_mem, start,
  463                     start + count - 1, count, flags, child);
  464                 if (rv == NULL)
  465                         return (NULL);
  466 
  467                 rman_set_bustag(rv, &bs_be_tag);
  468                 rman_set_bushandle(rv, rman_get_start(rv));
  469                 break;
  470 
  471         default:
  472                 return (NULL);
  473         }
  474 
  475         rman_set_rid(rv, *rid);
  476         return (rv);
  477 }
  478 
  479 static int
  480 ocpbus_print_child(device_t dev, device_t child)
  481 {
  482         u_long size, start;
  483         int error, retval, rid;
  484 
  485         retval = bus_print_child_header(dev, child);
  486 
  487         rid = 0;
  488         while (1) {
  489                 error = ocpbus_get_resource(dev, child, SYS_RES_MEMORY, rid,
  490                     &start, &size);
  491                 if (error)
  492                         break;
  493                 retval += (rid == 0) ? printf(" iomem ") : printf(",");
  494                 retval += printf("%#lx", start);
  495                 if (size > 1)
  496                         retval += printf("-%#lx", start + size - 1);
  497                 rid++;
  498         }
  499 
  500         /*
  501          * The SYS_RES_IOPORT resource of the PCIB has rid 1 because the
  502          * the SYS_RES_MEMORY resource related to the decoding window also
  503          * has rid 1. This is friendlier for the PCIB child...
  504          */
  505         rid = 1;
  506         while (1) {
  507                 error = ocpbus_get_resource(dev, child, SYS_RES_IOPORT, rid,
  508                     &start, &size);
  509                 if (error)
  510                         break;
  511                 retval += (rid == 1) ? printf(" ioport ") : printf(",");
  512                 retval += printf("%#lx", start);
  513                 if (size > 1)
  514                         retval += printf("-%#lx", start + size - 1);
  515                 rid++;
  516         }
  517 
  518         rid = 0;
  519         while (1) {
  520                 error = ocpbus_get_resource(dev, child, SYS_RES_IRQ, rid,
  521                     &start, &size);
  522                 if (error)
  523                         break;
  524                 retval += (rid == 0) ? printf(" irq ") : printf(",");
  525                 retval += printf("%ld", start);
  526                 rid++;
  527         }
  528 
  529         retval += bus_print_child_footer(dev, child);
  530         return (retval);
  531 }
  532 
  533 static int
  534 ocpbus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
  535 {
  536         struct ocp_devinfo *dinfo;
  537         struct bi_eth_addr *eth;
  538         int unit;
  539 
  540         if (device_get_parent(child) != dev)
  541                 return (EINVAL);
  542 
  543         dinfo = device_get_ivars(child);
  544 
  545         switch (index) {
  546         case OCPBUS_IVAR_CLOCK:
  547                 *result = bootinfo->bi_bus_clk;
  548                 return (0);
  549         case OCPBUS_IVAR_DEVTYPE:
  550                 *result = dinfo->ocp_devtype;
  551                 return (0);
  552         case OCPBUS_IVAR_HWUNIT:
  553                 *result = dinfo->ocp_unit;
  554                 return (0);
  555         case OCPBUS_IVAR_MACADDR:
  556                 unit = device_get_unit(child);
  557                 if (unit > bootinfo->bi_eth_addr_no - 1)
  558                         return (EINVAL);
  559                 eth = bootinfo_eth() + unit;
  560                 *result = (uintptr_t)eth;
  561                 return (0);
  562         }
  563 
  564         return (EINVAL);
  565 }
  566 
  567 static int
  568 ocpbus_release_resource(device_t dev, device_t child, int type, int rid,
  569     struct resource *res)
  570 {
  571 
  572         return (rman_release_resource(res));
  573 }
  574 
  575 static int
  576 ocpbus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
  577     driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep)
  578 {
  579         int error;
  580 
  581         if (res == NULL)
  582                 panic("ocpbus_setup_intr: NULL irq resource!");
  583 
  584         *cookiep = 0;
  585         if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
  586                 flags |= INTR_EXCL;
  587 
  588         /*
  589          * We depend here on rman_activate_resource() being idempotent.
  590          */
  591         error = rman_activate_resource(res);
  592         if (error)
  593                 return (error);
  594 
  595         error = powerpc_setup_intr(device_get_nameunit(child),
  596             rman_get_start(res), filter, ihand, arg, flags, cookiep);
  597 
  598         return (error);
  599 }
  600 
  601 static int
  602 ocpbus_teardown_intr(device_t dev, device_t child, struct resource *res,
  603     void *cookie)
  604 {
  605 
  606         return (powerpc_teardown_intr(cookie));
  607 }
  608 
  609 static int
  610 ocpbus_config_intr(device_t dev, int irq, enum intr_trigger trig, 
  611     enum intr_polarity pol)
  612 {
  613 
  614         return (powerpc_config_intr(irq, trig, pol));
  615 }

Cache object: b6b90c38a150737cd85558cc061fef32


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