1296177Sjhibbits/*- 2296177Sjhibbits * Copyright (c) 2011-2012 Semihalf. 3296177Sjhibbits * All rights reserved. 4296177Sjhibbits * 5296177Sjhibbits * Redistribution and use in source and binary forms, with or without 6296177Sjhibbits * modification, are permitted provided that the following conditions 7296177Sjhibbits * are met: 8296177Sjhibbits * 1. Redistributions of source code must retain the above copyright 9296177Sjhibbits * notice, this list of conditions and the following disclaimer. 10296177Sjhibbits * 2. Redistributions in binary form must reproduce the above copyright 11296177Sjhibbits * notice, this list of conditions and the following disclaimer in the 12296177Sjhibbits * documentation and/or other materials provided with the distribution. 13296177Sjhibbits * 14296177Sjhibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15296177Sjhibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16296177Sjhibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17296177Sjhibbits * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18296177Sjhibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19296177Sjhibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20296177Sjhibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21296177Sjhibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22296177Sjhibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23296177Sjhibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24296177Sjhibbits * SUCH DAMAGE. 25296177Sjhibbits */ 26296177Sjhibbits 27296177Sjhibbits#include "opt_platform.h" 28296177Sjhibbits#include <sys/cdefs.h> 29296177Sjhibbits__FBSDID("$FreeBSD$"); 30296177Sjhibbits 31296177Sjhibbits#include <sys/param.h> 32296177Sjhibbits#include <sys/systm.h> 33296177Sjhibbits#include <sys/kernel.h> 34296177Sjhibbits#include <sys/bus.h> 35296177Sjhibbits#include <sys/module.h> 36296177Sjhibbits 37296177Sjhibbits#include <machine/bus.h> 38296177Sjhibbits 39296177Sjhibbits#include <dev/fdt/fdt_common.h> 40296177Sjhibbits 41296177Sjhibbits#include <dev/ofw/ofw_bus.h> 42296177Sjhibbits#include <dev/ofw/ofw_bus_subr.h> 43296177Sjhibbits#include <dev/ofw/ofw_subr.h> 44296177Sjhibbits 45296177Sjhibbits#include "bman.h" 46296177Sjhibbits#include "portals.h" 47296177Sjhibbits 48296177Sjhibbits#define FBMAN_DEVSTR "Freescale Buffer Manager" 49296177Sjhibbits 50296177Sjhibbitsstatic int bman_fdt_probe(device_t); 51296177Sjhibbits 52296177Sjhibbitsstatic device_method_t bman_methods[] = { 53296177Sjhibbits /* Device interface */ 54296177Sjhibbits DEVMETHOD(device_probe, bman_fdt_probe), 55296177Sjhibbits DEVMETHOD(device_attach, bman_attach), 56296177Sjhibbits DEVMETHOD(device_detach, bman_detach), 57296177Sjhibbits 58296177Sjhibbits DEVMETHOD(device_suspend, bman_suspend), 59296177Sjhibbits DEVMETHOD(device_resume, bman_resume), 60296177Sjhibbits DEVMETHOD(device_shutdown, bman_shutdown), 61296177Sjhibbits 62296177Sjhibbits { 0, 0 } 63296177Sjhibbits}; 64296177Sjhibbits 65296177Sjhibbitsstatic driver_t bman_driver = { 66296177Sjhibbits "bman", 67296177Sjhibbits bman_methods, 68296177Sjhibbits sizeof(struct bman_softc), 69296177Sjhibbits}; 70296177Sjhibbits 71296177Sjhibbitsstatic devclass_t bman_devclass; 72296177SjhibbitsDRIVER_MODULE(bman, simplebus, bman_driver, bman_devclass, 0, 0); 73296177Sjhibbits 74296177Sjhibbitsstatic int 75296177Sjhibbitsbman_fdt_probe(device_t dev) 76296177Sjhibbits{ 77296177Sjhibbits 78296177Sjhibbits if (!ofw_bus_is_compatible(dev, "fsl,bman")) 79296177Sjhibbits return (ENXIO); 80296177Sjhibbits 81296177Sjhibbits device_set_desc(dev, FBMAN_DEVSTR); 82296177Sjhibbits 83296177Sjhibbits return (BUS_PROBE_DEFAULT); 84296177Sjhibbits} 85296177Sjhibbits 86296177Sjhibbits/* 87296177Sjhibbits * BMAN Portals 88296177Sjhibbits */ 89296177Sjhibbits#define BMAN_PORT_DEVSTR "Freescale Buffer Manager - Portals" 90296177Sjhibbits 91296177Sjhibbitsstatic device_probe_t bman_portals_fdt_probe; 92296177Sjhibbitsstatic device_attach_t bman_portals_fdt_attach; 93296177Sjhibbits 94296177Sjhibbitsstatic device_method_t bm_portals_methods[] = { 95296177Sjhibbits /* Device interface */ 96296177Sjhibbits DEVMETHOD(device_probe, bman_portals_fdt_probe), 97296177Sjhibbits DEVMETHOD(device_attach, bman_portals_fdt_attach), 98296177Sjhibbits DEVMETHOD(device_detach, bman_portals_detach), 99296177Sjhibbits 100296177Sjhibbits { 0, 0 } 101296177Sjhibbits}; 102296177Sjhibbits 103296177Sjhibbitsstatic driver_t bm_portals_driver = { 104296177Sjhibbits "bman-portals", 105296177Sjhibbits bm_portals_methods, 106296177Sjhibbits sizeof(struct dpaa_portals_softc), 107296177Sjhibbits}; 108296177Sjhibbits 109296177Sjhibbitsstatic devclass_t bm_portals_devclass; 110296177SjhibbitsDRIVER_MODULE(bman_portals, ofwbus, bm_portals_driver, bm_portals_devclass, 0, 0); 111296177Sjhibbits 112296177Sjhibbitsstatic void 113296177Sjhibbitsget_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep) 114296177Sjhibbits{ 115296177Sjhibbits 116296177Sjhibbits *addrp = 2; 117296177Sjhibbits *sizep = 1; 118296177Sjhibbits OF_getencprop(node, "#address-cells", addrp, sizeof(*addrp)); 119296177Sjhibbits OF_getencprop(node, "#size-cells", sizep, sizeof(*sizep)); 120296177Sjhibbits} 121296177Sjhibbits 122296177Sjhibbitsstatic int 123296177Sjhibbitsbman_portals_fdt_probe(device_t dev) 124296177Sjhibbits{ 125296177Sjhibbits 126296177Sjhibbits if (!ofw_bus_is_compatible(dev, "bman-portals")) 127296177Sjhibbits return (ENXIO); 128296177Sjhibbits 129296177Sjhibbits device_set_desc(dev, BMAN_PORT_DEVSTR); 130296177Sjhibbits 131296177Sjhibbits return (BUS_PROBE_DEFAULT); 132296177Sjhibbits} 133296177Sjhibbits 134296177Sjhibbitsstatic int 135296177Sjhibbitsbman_portals_fdt_attach(device_t dev) 136296177Sjhibbits{ 137296177Sjhibbits struct dpaa_portals_softc *sc; 138296177Sjhibbits struct resource_list_entry *rle; 139296177Sjhibbits phandle_t node, child, cpu_node; 140296177Sjhibbits vm_paddr_t portal_pa; 141296177Sjhibbits vm_size_t portal_size; 142296177Sjhibbits uint32_t addr, size; 143296177Sjhibbits ihandle_t cpu; 144296177Sjhibbits int cpu_num, cpus, intr_rid; 145296177Sjhibbits struct dpaa_portals_devinfo di; 146296177Sjhibbits struct ofw_bus_devinfo ofw_di; 147296177Sjhibbits 148296177Sjhibbits cpus = 0; 149296177Sjhibbits sc = device_get_softc(dev); 150296177Sjhibbits sc->sc_dev = dev; 151296177Sjhibbits 152296177Sjhibbits node = ofw_bus_get_node(dev); 153296177Sjhibbits get_addr_props(node, &addr, &size); 154296177Sjhibbits 155296177Sjhibbits /* Find portals tied to CPUs */ 156296177Sjhibbits for (child = OF_child(node); child != 0; child = OF_peer(child)) { 157296177Sjhibbits if (!fdt_is_compatible(child, "fsl,bman-portal")) { 158296177Sjhibbits continue; 159296177Sjhibbits } 160296177Sjhibbits /* Checkout related cpu */ 161296177Sjhibbits if (OF_getprop(child, "cpu-handle", (void *)&cpu, 162296177Sjhibbits sizeof(cpu)) <= 0) { 163296177Sjhibbits continue; 164296177Sjhibbits } 165296177Sjhibbits /* Acquire cpu number */ 166296177Sjhibbits cpu_node = OF_instance_to_package(cpu); 167296177Sjhibbits if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) { 168296177Sjhibbits device_printf(dev, "Could not retrieve CPU number.\n"); 169296177Sjhibbits return (ENXIO); 170296177Sjhibbits } 171296177Sjhibbits 172296177Sjhibbits cpus++; 173296177Sjhibbits 174296177Sjhibbits if (cpus > MAXCPU) 175296177Sjhibbits break; 176296177Sjhibbits 177296177Sjhibbits if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) { 178296177Sjhibbits device_printf(dev, "could not set up devinfo\n"); 179296177Sjhibbits continue; 180296177Sjhibbits } 181296177Sjhibbits 182296177Sjhibbits resource_list_init(&di.di_res); 183296177Sjhibbits if (ofw_bus_reg_to_rl(dev, child, addr, size, &di.di_res)) { 184296177Sjhibbits device_printf(dev, "%s: could not process 'reg' " 185296177Sjhibbits "property\n", ofw_di.obd_name); 186296177Sjhibbits ofw_bus_gen_destroy_devinfo(&ofw_di); 187296177Sjhibbits continue; 188296177Sjhibbits } 189296177Sjhibbits if (ofw_bus_intr_to_rl(dev, child, &di.di_res, &intr_rid)) { 190296177Sjhibbits device_printf(dev, "%s: could not process " 191296177Sjhibbits "'interrupts' property\n", ofw_di.obd_name); 192296177Sjhibbits resource_list_free(&di.di_res); 193296177Sjhibbits ofw_bus_gen_destroy_devinfo(&ofw_di); 194296177Sjhibbits continue; 195296177Sjhibbits } 196296177Sjhibbits di.di_intr_rid = intr_rid; 197296177Sjhibbits 198296177Sjhibbits ofw_reg_to_paddr(child, 0, &portal_pa, &portal_size, NULL); 199296177Sjhibbits rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 0); 200296177Sjhibbits 201296177Sjhibbits if (sc->sc_dp_pa == 0) 202296177Sjhibbits sc->sc_dp_pa = portal_pa - rle->start; 203296177Sjhibbits 204296177Sjhibbits portal_size = rle->end + 1; 205296177Sjhibbits rle = resource_list_find(&di.di_res, SYS_RES_MEMORY, 1); 206296177Sjhibbits portal_size = ulmax(rle->end + 1, portal_size); 207296177Sjhibbits sc->sc_dp_size = ulmax(sc->sc_dp_size, portal_size); 208296177Sjhibbits 209296177Sjhibbits if (dpaa_portal_alloc_res(dev, &di, cpu_num)) 210296177Sjhibbits goto err; 211296177Sjhibbits } 212296177Sjhibbits 213296177Sjhibbits ofw_bus_gen_destroy_devinfo(&ofw_di); 214296177Sjhibbits 215296177Sjhibbits return (bman_portals_attach(dev)); 216296177Sjhibbitserr: 217296177Sjhibbits resource_list_free(&di.di_res); 218296177Sjhibbits ofw_bus_gen_destroy_devinfo(&ofw_di); 219296177Sjhibbits bman_portals_detach(dev); 220296177Sjhibbits return (ENXIO); 221296177Sjhibbits} 222