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/wii/wii_bus.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) 2012 Margarida Gouveia
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer,
   10  *    without modification, immediately at the beginning of the file.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   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, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD: releng/10.1/sys/powerpc/wii/wii_bus.c 249973 2013-04-27 06:54:49Z rpaulo $");
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/kernel.h>
   32 #include <sys/module.h>
   33 #include <sys/malloc.h>
   34 #include <sys/bus.h>
   35 #include <sys/clock.h>
   36 #include <sys/cpu.h>
   37 #include <sys/resource.h>
   38 #include <sys/rman.h>
   39 
   40 #include <vm/vm.h>
   41 #include <vm/pmap.h>
   42 
   43 #include <machine/bus.h>
   44 #include <machine/platform.h>
   45 #include <machine/pmap.h>
   46 #include <machine/resource.h>
   47 #include <machine/platformvar.h>
   48 
   49 #include <powerpc/wii/wii_picreg.h>
   50 #include <powerpc/wii/wii_fbreg.h>
   51 #include <powerpc/wii/wii_exireg.h>
   52 #include <powerpc/wii/wii_ipcreg.h>
   53 #include <powerpc/wii/wii_gpioreg.h>
   54 
   55 #define WIIBUS_CSR_ADDR         0x0d800100
   56 #define WIIBUS_CSR_LEN          0x300
   57 #define WIIBUS_CSR_RESET        0x94
   58 
   59 struct wiibus_softc {
   60         device_t                sc_dev;
   61         struct rman             sc_rman;
   62         bus_space_tag_t         sc_tag;
   63         bus_space_handle_t      sc_handle;
   64 };
   65 
   66 static struct wiibus_softc *wiibus_sc = NULL;
   67 
   68 static uint32_t wiibus_csr_read(struct wiibus_softc *, uint16_t);
   69 static void     wiibus_csr_write(struct wiibus_softc *, uint16_t, uint32_t);
   70 static void     wiibus_identify(driver_t *, device_t);
   71 static int      wiibus_probe(device_t);
   72 static int      wiibus_attach(device_t);
   73 static int      wiibus_print_child(device_t, device_t);
   74 static struct resource *
   75                 wiibus_alloc_resource(device_t, device_t, int, int *,
   76                     unsigned long, unsigned long, unsigned long,
   77                     unsigned int);
   78 static int      wiibus_activate_resource(device_t, device_t, int, int,
   79                     struct resource *);
   80        void     wiibus_reset_system(void);
   81 
   82 static device_method_t wiibus_methods[] = {
   83         /* Device interface */
   84         DEVMETHOD(device_identify,      wiibus_identify),
   85         DEVMETHOD(device_probe,         wiibus_probe),
   86         DEVMETHOD(device_attach,        wiibus_attach),
   87 
   88         /* Bus interface */
   89         DEVMETHOD(bus_add_child,        bus_generic_add_child),
   90         DEVMETHOD(bus_print_child,      wiibus_print_child),
   91         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
   92         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
   93         DEVMETHOD(bus_alloc_resource,   wiibus_alloc_resource),
   94         DEVMETHOD(bus_activate_resource,wiibus_activate_resource),
   95 
   96         DEVMETHOD_END
   97 };
   98 
   99 static MALLOC_DEFINE(M_WIIBUS, "wiibus", "Nintendo Wii system bus");
  100 
  101 struct wiibus_devinfo {
  102         struct resource_list    di_resources;
  103         uint8_t                 di_init;
  104 };
  105 
  106 static driver_t wiibus_driver = {
  107         "wiibus",
  108         wiibus_methods,
  109         sizeof(struct wiibus_softc)
  110 };
  111 
  112 static devclass_t wiibus_devclass;
  113 
  114 DRIVER_MODULE(wiibus, nexus, wiibus_driver, wiibus_devclass, 0, 0);
  115 
  116 static uint32_t
  117 wiibus_csr_read(struct wiibus_softc *sc, uint16_t reg)
  118 {
  119 
  120         return (bus_space_read_4(sc->sc_tag, sc->sc_handle, reg));
  121 }
  122 
  123 static void
  124 wiibus_csr_write(struct wiibus_softc *sc, uint16_t reg,
  125     uint32_t val)
  126 {
  127 
  128         bus_space_write_4(sc->sc_tag, sc->sc_handle, reg, val);
  129 }
  130 
  131 static void
  132 wiibus_identify(driver_t *driver, device_t parent)
  133 {
  134 
  135         if (strcmp(installed_platform(), "wii") != 0)
  136                 return;
  137 
  138         if (device_find_child(parent, "wiibus", -1) == NULL)
  139                 BUS_ADD_CHILD(parent, 0, "wiibus", 0);
  140 }
  141 
  142 
  143 static int
  144 wiibus_probe(device_t dev)
  145 {
  146 
  147         device_set_desc(dev, "Nintendo Wii System Bus");
  148 
  149         return (BUS_PROBE_NOWILDCARD);
  150 }
  151 
  152 static void
  153 wiibus_init_device_resources(struct rman *rm, struct wiibus_devinfo *dinfo,
  154     unsigned int rid, uintptr_t addr, size_t len, unsigned int irq)
  155 
  156 {
  157 
  158         if (!dinfo->di_init) {
  159                 resource_list_init(&dinfo->di_resources);
  160                 dinfo->di_init++;
  161         }
  162         if (addr) {
  163                 rman_manage_region(rm, addr, addr + len - 1);
  164                 resource_list_add(&dinfo->di_resources, SYS_RES_MEMORY, rid,
  165                     addr, addr + len, len);
  166         }
  167         if (irq)
  168                 resource_list_add(&dinfo->di_resources, SYS_RES_IRQ, rid,
  169                     irq, irq, 1);
  170 }
  171 
  172 static int
  173 wiibus_attach(device_t self)
  174 {
  175         struct wiibus_softc *sc;
  176         struct wiibus_devinfo *dinfo;
  177         device_t cdev;
  178 
  179         sc = device_get_softc(self);
  180         sc->sc_rman.rm_type = RMAN_ARRAY;
  181         sc->sc_rman.rm_descr = "Wii Bus Memory Mapped I/O";
  182         rman_init(&sc->sc_rman);
  183         KASSERT(wiibus_sc == NULL, ("wiibus_sc already initialised"));
  184         wiibus_sc = sc;
  185 
  186         /* Nintendo PIC */
  187         dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
  188         wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIPIC_REG_ADDR,
  189             WIIPIC_REG_LEN, 1);
  190         cdev = BUS_ADD_CHILD(self, 0, "wiipic", 0);
  191         device_set_ivars(cdev, dinfo);
  192 
  193         /* Framebuffer */
  194         dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
  195         wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIFB_REG_ADDR,
  196             WIIFB_REG_LEN, 8);
  197         wiibus_init_device_resources(&sc->sc_rman, dinfo, 1, WIIFB_FB_ADDR,
  198             WIIFB_FB_LEN, 0);
  199         cdev = BUS_ADD_CHILD(self, 0, "wiifb", 0);
  200         device_set_ivars(cdev, dinfo);
  201 
  202         /* External Interface Bus */
  203         dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
  204         wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIEXI_REG_ADDR,
  205             WIIEXI_REG_LEN, 4);
  206         cdev = BUS_ADD_CHILD(self, 0, "wiiexi", 0);
  207         device_set_ivars(cdev, dinfo);
  208 
  209         /* Nintendo IOS IPC */
  210         dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
  211         wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIIPC_REG_ADDR,
  212             WIIIPC_REG_LEN, 14);
  213         wiibus_init_device_resources(&sc->sc_rman, dinfo, 1, WIIIPC_IOH_ADDR,
  214             WIIIPC_IOH_LEN, 0);
  215         cdev = BUS_ADD_CHILD(self, 0, "wiiipc", 0);
  216         device_set_ivars(cdev, dinfo);
  217 
  218         /* GPIO */
  219         dinfo = malloc(sizeof(*dinfo), M_WIIBUS, M_WAITOK | M_ZERO);
  220         wiibus_init_device_resources(&sc->sc_rman, dinfo, 0, WIIGPIO_REG_ADDR,
  221             WIIGPIO_REG_LEN, 0);
  222         cdev = BUS_ADD_CHILD(self, 0, "wiigpio", 0);
  223         device_set_ivars(cdev, dinfo);
  224 
  225         /* The control registers */
  226         sc->sc_tag    = &bs_be_tag;
  227         sc->sc_handle = (bus_space_handle_t)pmap_mapdev(WIIBUS_CSR_ADDR,
  228             WIIBUS_CSR_LEN);
  229 
  230         return (bus_generic_attach(self));
  231 }
  232 
  233 static int
  234 wiibus_print_child(device_t dev, device_t child)
  235 {
  236         struct wiibus_devinfo *dinfo = device_get_ivars(child);
  237         int retval = 0;
  238 
  239         retval += bus_print_child_header(dev, child);
  240         retval += resource_list_print_type(&dinfo->di_resources, "mem",
  241             SYS_RES_MEMORY, "%#lx");
  242         retval += resource_list_print_type(&dinfo->di_resources, "irq",
  243             SYS_RES_IRQ, "%ld");
  244         retval += bus_print_child_footer(dev, child);
  245 
  246         return (retval);
  247 }
  248 
  249 static struct resource *
  250 wiibus_alloc_resource(device_t bus, device_t child, int type,
  251     int *rid, unsigned long start, unsigned long end,
  252     unsigned long count, unsigned int flags)
  253 {
  254         struct wiibus_softc *sc;
  255         struct wiibus_devinfo *dinfo;
  256         struct resource_list_entry *rle;
  257         struct resource *rv;
  258         int needactivate;
  259 
  260         sc = device_get_softc(bus);
  261         dinfo = device_get_ivars(child);
  262         needactivate = flags & RF_ACTIVE;
  263         flags &= ~RF_ACTIVE;
  264 
  265         switch (type) {
  266         case SYS_RES_MEMORY:
  267                 rle = resource_list_find(&dinfo->di_resources, SYS_RES_MEMORY,
  268                     *rid);
  269                 if (rle == NULL) {
  270                         device_printf(bus, "no res entry for %s memory 0x%x\n",
  271                             device_get_nameunit(child), *rid);
  272                         return (NULL);
  273                 }
  274                 rv = rman_reserve_resource(&sc->sc_rman, rle->start, rle->end,
  275                     rle->count, flags, child);
  276                 if (rv == NULL) {
  277                         device_printf(bus,
  278                             "failed to reserve resource for %s\n",
  279                             device_get_nameunit(child));
  280                         return (NULL);
  281                 }
  282                 rman_set_rid(rv, *rid);
  283                 break;
  284         case SYS_RES_IRQ:
  285                 return (resource_list_alloc(&dinfo->di_resources, bus, child,
  286                     type, rid, start, end, count, flags));
  287         default:
  288                 device_printf(bus, "unknown resource request from %s\n",
  289                     device_get_nameunit(child));
  290                 return (NULL);
  291         }
  292 
  293         if (needactivate) {
  294                 if (bus_activate_resource(child, type, *rid, rv) != 0) {
  295                         device_printf(bus,
  296                             "failed to activate resource for %s\n",
  297                             device_get_nameunit(child));
  298                         return (NULL);
  299                 }
  300         }
  301         
  302         return (rv);
  303 }
  304 
  305 static int
  306 wiibus_activate_resource(device_t bus, device_t child, int type, int rid,
  307     struct resource *res)
  308 {
  309         void *p;
  310 
  311         switch (type) {
  312         case SYS_RES_MEMORY:
  313                 p = pmap_mapdev(rman_get_start(res), rman_get_size(res));
  314                 if (p == NULL)
  315                         return (ENOMEM);
  316                 rman_set_virtual(res, p);
  317                 rman_set_bustag(res, &bs_be_tag);
  318                 rman_set_bushandle(res, (unsigned long)p);
  319                 break;
  320         case SYS_RES_IRQ:
  321                 return (bus_activate_resource(bus, type, rid, res));
  322         default:
  323                 device_printf(bus,
  324                     "unknown activate resource request from %s\n",
  325                     device_get_nameunit(child));
  326                 return (ENXIO);
  327         }
  328         
  329         return (rman_activate_resource(res));
  330 }
  331 
  332 void
  333 wiibus_reset_system(void)
  334 {
  335         uint32_t r;
  336 
  337         r = wiibus_csr_read(wiibus_sc, WIIBUS_CSR_RESET);
  338         r &= ~1;
  339         wiibus_csr_write(wiibus_sc, WIIBUS_CSR_RESET, r);
  340 }

Cache object: c06b539ab0f1241b89eb0408eab9c163


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