10aeed3e9SJustin Hibbits /*- 20aeed3e9SJustin Hibbits * Copyright (c) 2011-2012 Semihalf. 30aeed3e9SJustin Hibbits * All rights reserved. 40aeed3e9SJustin Hibbits * 50aeed3e9SJustin Hibbits * Redistribution and use in source and binary forms, with or without 60aeed3e9SJustin Hibbits * modification, are permitted provided that the following conditions 70aeed3e9SJustin Hibbits * are met: 80aeed3e9SJustin Hibbits * 1. Redistributions of source code must retain the above copyright 90aeed3e9SJustin Hibbits * notice, this list of conditions and the following disclaimer. 100aeed3e9SJustin Hibbits * 2. Redistributions in binary form must reproduce the above copyright 110aeed3e9SJustin Hibbits * notice, this list of conditions and the following disclaimer in the 120aeed3e9SJustin Hibbits * documentation and/or other materials provided with the distribution. 130aeed3e9SJustin Hibbits * 140aeed3e9SJustin Hibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 150aeed3e9SJustin Hibbits * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 160aeed3e9SJustin Hibbits * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 170aeed3e9SJustin Hibbits * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 180aeed3e9SJustin Hibbits * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 190aeed3e9SJustin Hibbits * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 200aeed3e9SJustin Hibbits * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 210aeed3e9SJustin Hibbits * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 220aeed3e9SJustin Hibbits * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 230aeed3e9SJustin Hibbits * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 240aeed3e9SJustin Hibbits * SUCH DAMAGE. 250aeed3e9SJustin Hibbits */ 260aeed3e9SJustin Hibbits 270aeed3e9SJustin Hibbits #include <sys/param.h> 280aeed3e9SJustin Hibbits #include <sys/systm.h> 290aeed3e9SJustin Hibbits #include <sys/kernel.h> 300aeed3e9SJustin Hibbits #include <sys/module.h> 310aeed3e9SJustin Hibbits #include <sys/bus.h> 320aeed3e9SJustin Hibbits #include <sys/rman.h> 330aeed3e9SJustin Hibbits #include <sys/malloc.h> 340aeed3e9SJustin Hibbits 3547cabd04SJustin Hibbits #include <dev/fdt/simplebus.h> 360aeed3e9SJustin Hibbits #include <dev/ofw/ofw_bus.h> 370aeed3e9SJustin Hibbits #include <dev/ofw/ofw_bus_subr.h> 380aeed3e9SJustin Hibbits 39a32b5435SJustin Hibbits #include <machine/bus.h> 40a32b5435SJustin Hibbits 410aeed3e9SJustin Hibbits #include "opt_platform.h" 420aeed3e9SJustin Hibbits 430aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/Peripherals/fm_ext.h> 440aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/Peripherals/fm_muram_ext.h> 450aeed3e9SJustin Hibbits #include <contrib/ncsw/inc/ncsw_ext.h> 460aeed3e9SJustin Hibbits #include <contrib/ncsw/integrations/fman_ucode.h> 470aeed3e9SJustin Hibbits 480aeed3e9SJustin Hibbits #include "fman.h" 490aeed3e9SJustin Hibbits 500aeed3e9SJustin Hibbits 513e7ddf02SJustin Hibbits static MALLOC_DEFINE(M_FMAN, "fman", "fman devices information"); 523e7ddf02SJustin Hibbits 530aeed3e9SJustin Hibbits /** 540aeed3e9SJustin Hibbits * @group FMan private defines. 550aeed3e9SJustin Hibbits * @{ 560aeed3e9SJustin Hibbits */ 570aeed3e9SJustin Hibbits enum fman_irq_enum { 580aeed3e9SJustin Hibbits FMAN_IRQ_NUM = 0, 590aeed3e9SJustin Hibbits FMAN_ERR_IRQ_NUM = 1 600aeed3e9SJustin Hibbits }; 610aeed3e9SJustin Hibbits 620aeed3e9SJustin Hibbits enum fman_mu_ram_map { 630aeed3e9SJustin Hibbits FMAN_MURAM_OFF = 0x0, 640aeed3e9SJustin Hibbits FMAN_MURAM_SIZE = 0x28000 650aeed3e9SJustin Hibbits }; 660aeed3e9SJustin Hibbits 670aeed3e9SJustin Hibbits struct fman_config { 680aeed3e9SJustin Hibbits device_t fman_device; 690aeed3e9SJustin Hibbits uintptr_t mem_base_addr; 70f77405e3SJustin Hibbits uintptr_t irq_num; 71f77405e3SJustin Hibbits uintptr_t err_irq_num; 720aeed3e9SJustin Hibbits uint8_t fm_id; 730aeed3e9SJustin Hibbits t_FmExceptionsCallback *exception_callback; 740aeed3e9SJustin Hibbits t_FmBusErrorCallback *bus_error_callback; 750aeed3e9SJustin Hibbits }; 760aeed3e9SJustin Hibbits 770aeed3e9SJustin Hibbits /** 780aeed3e9SJustin Hibbits * @group FMan private methods/members. 790aeed3e9SJustin Hibbits * @{ 800aeed3e9SJustin Hibbits */ 810aeed3e9SJustin Hibbits /** 820aeed3e9SJustin Hibbits * Frame Manager firmware. 830aeed3e9SJustin Hibbits * We use the same firmware for both P3041 and P2041 devices. 840aeed3e9SJustin Hibbits */ 850aeed3e9SJustin Hibbits const uint32_t fman_firmware[] = FMAN_UC_IMG; 860aeed3e9SJustin Hibbits const uint32_t fman_firmware_size = sizeof(fman_firmware); 870aeed3e9SJustin Hibbits 88a32b5435SJustin Hibbits int 89a32b5435SJustin Hibbits fman_activate_resource(device_t bus, device_t child, int type, int rid, 90a32b5435SJustin Hibbits struct resource *res) 91a32b5435SJustin Hibbits { 92a32b5435SJustin Hibbits struct fman_softc *sc; 93a32b5435SJustin Hibbits bus_space_tag_t bt; 94a32b5435SJustin Hibbits bus_space_handle_t bh; 95a32b5435SJustin Hibbits int i, rv; 96a32b5435SJustin Hibbits 97a32b5435SJustin Hibbits sc = device_get_softc(bus); 98a32b5435SJustin Hibbits if (type != SYS_RES_IRQ) { 99a32b5435SJustin Hibbits for (i = 0; i < sc->sc_base.nranges; i++) { 100a32b5435SJustin Hibbits if (rman_is_region_manager(res, &sc->rman) != 0) { 101a32b5435SJustin Hibbits bt = rman_get_bustag(sc->mem_res); 102a32b5435SJustin Hibbits rv = bus_space_subregion(bt, 103a32b5435SJustin Hibbits rman_get_bushandle(sc->mem_res), 104a32b5435SJustin Hibbits rman_get_start(res) - 105a32b5435SJustin Hibbits rman_get_start(sc->mem_res), 106a32b5435SJustin Hibbits rman_get_size(res), &bh); 107a32b5435SJustin Hibbits if (rv != 0) 108a32b5435SJustin Hibbits return (rv); 109a32b5435SJustin Hibbits rman_set_bustag(res, bt); 110a32b5435SJustin Hibbits rman_set_bushandle(res, bh); 111a32b5435SJustin Hibbits return (rman_activate_resource(res)); 112a32b5435SJustin Hibbits } 113a32b5435SJustin Hibbits } 114a32b5435SJustin Hibbits return (EINVAL); 115a32b5435SJustin Hibbits } 116a32b5435SJustin Hibbits return (bus_generic_activate_resource(bus, child, type, rid, res)); 117a32b5435SJustin Hibbits } 118a32b5435SJustin Hibbits 119a32b5435SJustin Hibbits int 120a32b5435SJustin Hibbits fman_release_resource(device_t bus, device_t child, int type, int rid, 121a32b5435SJustin Hibbits struct resource *res) 122a32b5435SJustin Hibbits { 123a32b5435SJustin Hibbits struct resource_list *rl; 124a32b5435SJustin Hibbits struct resource_list_entry *rle; 125a32b5435SJustin Hibbits int passthrough, rv; 126a32b5435SJustin Hibbits 127a32b5435SJustin Hibbits passthrough = (device_get_parent(child) != bus); 128a32b5435SJustin Hibbits rl = BUS_GET_RESOURCE_LIST(bus, child); 129a32b5435SJustin Hibbits if (type != SYS_RES_IRQ) { 130a32b5435SJustin Hibbits if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){ 131a32b5435SJustin Hibbits rv = bus_deactivate_resource(child, type, rid, res); 132a32b5435SJustin Hibbits if (rv != 0) 133a32b5435SJustin Hibbits return (rv); 134a32b5435SJustin Hibbits } 135a32b5435SJustin Hibbits rv = rman_release_resource(res); 136a32b5435SJustin Hibbits if (rv != 0) 137a32b5435SJustin Hibbits return (rv); 138a32b5435SJustin Hibbits if (!passthrough) { 139a32b5435SJustin Hibbits rle = resource_list_find(rl, type, rid); 140a32b5435SJustin Hibbits KASSERT(rle != NULL, 141a32b5435SJustin Hibbits ("%s: resource entry not found!", __func__)); 142a32b5435SJustin Hibbits KASSERT(rle->res != NULL, 143a32b5435SJustin Hibbits ("%s: resource entry is not busy", __func__)); 144a32b5435SJustin Hibbits rle->res = NULL; 145a32b5435SJustin Hibbits } 146a32b5435SJustin Hibbits return (0); 147a32b5435SJustin Hibbits } 148a32b5435SJustin Hibbits return (resource_list_release(rl, bus, child, type, rid, res)); 149a32b5435SJustin Hibbits } 150a32b5435SJustin Hibbits 151a32b5435SJustin Hibbits struct resource * 152a32b5435SJustin Hibbits fman_alloc_resource(device_t bus, device_t child, int type, int *rid, 153a32b5435SJustin Hibbits rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 154a32b5435SJustin Hibbits { 155a32b5435SJustin Hibbits struct fman_softc *sc; 156a32b5435SJustin Hibbits struct resource_list *rl; 157a32b5435SJustin Hibbits struct resource_list_entry *rle = NULL; 158a32b5435SJustin Hibbits struct resource *res; 159a32b5435SJustin Hibbits int i, isdefault, passthrough; 160a32b5435SJustin Hibbits 161a32b5435SJustin Hibbits isdefault = RMAN_IS_DEFAULT_RANGE(start, end); 162a32b5435SJustin Hibbits passthrough = (device_get_parent(child) != bus); 163a32b5435SJustin Hibbits sc = device_get_softc(bus); 164a32b5435SJustin Hibbits rl = BUS_GET_RESOURCE_LIST(bus, child); 165a32b5435SJustin Hibbits switch (type) { 166a32b5435SJustin Hibbits case SYS_RES_MEMORY: 167a32b5435SJustin Hibbits KASSERT(!(isdefault && passthrough), 168a32b5435SJustin Hibbits ("%s: passthrough of default allocation", __func__)); 169a32b5435SJustin Hibbits if (!passthrough) { 170a32b5435SJustin Hibbits rle = resource_list_find(rl, type, *rid); 171a32b5435SJustin Hibbits if (rle == NULL) 172a32b5435SJustin Hibbits return (NULL); 173a32b5435SJustin Hibbits KASSERT(rle->res == NULL, 174a32b5435SJustin Hibbits ("%s: resource entry is busy", __func__)); 175a32b5435SJustin Hibbits if (isdefault) { 176a32b5435SJustin Hibbits start = rle->start; 177a32b5435SJustin Hibbits count = ulmax(count, rle->count); 178a32b5435SJustin Hibbits end = ulmax(rle->end, start + count - 1); 179a32b5435SJustin Hibbits } 180a32b5435SJustin Hibbits } 181a32b5435SJustin Hibbits 182a32b5435SJustin Hibbits res = NULL; 183a32b5435SJustin Hibbits /* Map fman ranges to nexus ranges. */ 184a32b5435SJustin Hibbits for (i = 0; i < sc->sc_base.nranges; i++) { 185a32b5435SJustin Hibbits if (start >= sc->sc_base.ranges[i].bus && end < 186a32b5435SJustin Hibbits sc->sc_base.ranges[i].bus + sc->sc_base.ranges[i].size) { 187a32b5435SJustin Hibbits start += rman_get_start(sc->mem_res); 188a32b5435SJustin Hibbits end += rman_get_start(sc->mem_res); 189a32b5435SJustin Hibbits res = rman_reserve_resource(&sc->rman, start, 190a32b5435SJustin Hibbits end, count, flags & ~RF_ACTIVE, child); 191a32b5435SJustin Hibbits if (res == NULL) 192a32b5435SJustin Hibbits return (NULL); 193a32b5435SJustin Hibbits rman_set_rid(res, *rid); 194*1b9bcfffSJohn Baldwin rman_set_type(res, type); 195a32b5435SJustin Hibbits if ((flags & RF_ACTIVE) != 0 && bus_activate_resource( 196a32b5435SJustin Hibbits child, type, *rid, res) != 0) { 197a32b5435SJustin Hibbits rman_release_resource(res); 198a32b5435SJustin Hibbits return (NULL); 199a32b5435SJustin Hibbits } 200a32b5435SJustin Hibbits break; 201a32b5435SJustin Hibbits } 202a32b5435SJustin Hibbits } 203a32b5435SJustin Hibbits if (!passthrough) 204a32b5435SJustin Hibbits rle->res = res; 205a32b5435SJustin Hibbits return (res); 206a32b5435SJustin Hibbits case SYS_RES_IRQ: 207a32b5435SJustin Hibbits return (resource_list_alloc(rl, bus, child, type, rid, start, 208a32b5435SJustin Hibbits end, count, flags)); 209a32b5435SJustin Hibbits } 210a32b5435SJustin Hibbits return (NULL); 211a32b5435SJustin Hibbits } 212a32b5435SJustin Hibbits 213a32b5435SJustin Hibbits static int 214a32b5435SJustin Hibbits fman_fill_ranges(phandle_t node, struct simplebus_softc *sc) 215a32b5435SJustin Hibbits { 216a32b5435SJustin Hibbits int host_address_cells; 217a32b5435SJustin Hibbits cell_t *base_ranges; 218a32b5435SJustin Hibbits ssize_t nbase_ranges; 219a32b5435SJustin Hibbits int err; 220a32b5435SJustin Hibbits int i, j, k; 221a32b5435SJustin Hibbits 222a32b5435SJustin Hibbits err = OF_searchencprop(OF_parent(node), "#address-cells", 223a32b5435SJustin Hibbits &host_address_cells, sizeof(host_address_cells)); 224a32b5435SJustin Hibbits if (err <= 0) 225a32b5435SJustin Hibbits return (-1); 226a32b5435SJustin Hibbits 227a32b5435SJustin Hibbits nbase_ranges = OF_getproplen(node, "ranges"); 228a32b5435SJustin Hibbits if (nbase_ranges < 0) 229a32b5435SJustin Hibbits return (-1); 230a32b5435SJustin Hibbits sc->nranges = nbase_ranges / sizeof(cell_t) / 231a32b5435SJustin Hibbits (sc->acells + host_address_cells + sc->scells); 232a32b5435SJustin Hibbits if (sc->nranges == 0) 233a32b5435SJustin Hibbits return (0); 234a32b5435SJustin Hibbits 235a32b5435SJustin Hibbits sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]), 236a32b5435SJustin Hibbits M_DEVBUF, M_WAITOK); 237a32b5435SJustin Hibbits base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK); 238a32b5435SJustin Hibbits OF_getencprop(node, "ranges", base_ranges, nbase_ranges); 239a32b5435SJustin Hibbits 240a32b5435SJustin Hibbits for (i = 0, j = 0; i < sc->nranges; i++) { 241a32b5435SJustin Hibbits sc->ranges[i].bus = 0; 242a32b5435SJustin Hibbits for (k = 0; k < sc->acells; k++) { 243a32b5435SJustin Hibbits sc->ranges[i].bus <<= 32; 244a32b5435SJustin Hibbits sc->ranges[i].bus |= base_ranges[j++]; 245a32b5435SJustin Hibbits } 246a32b5435SJustin Hibbits sc->ranges[i].host = 0; 247a32b5435SJustin Hibbits for (k = 0; k < host_address_cells; k++) { 248a32b5435SJustin Hibbits sc->ranges[i].host <<= 32; 249a32b5435SJustin Hibbits sc->ranges[i].host |= base_ranges[j++]; 250a32b5435SJustin Hibbits } 251a32b5435SJustin Hibbits sc->ranges[i].size = 0; 252a32b5435SJustin Hibbits for (k = 0; k < sc->scells; k++) { 253a32b5435SJustin Hibbits sc->ranges[i].size <<= 32; 254a32b5435SJustin Hibbits sc->ranges[i].size |= base_ranges[j++]; 255a32b5435SJustin Hibbits } 256a32b5435SJustin Hibbits } 257a32b5435SJustin Hibbits 258a32b5435SJustin Hibbits free(base_ranges, M_DEVBUF); 259a32b5435SJustin Hibbits return (sc->nranges); 260a32b5435SJustin Hibbits } 261a32b5435SJustin Hibbits 2620aeed3e9SJustin Hibbits static t_Handle 2630aeed3e9SJustin Hibbits fman_init(struct fman_softc *sc, struct fman_config *cfg) 2640aeed3e9SJustin Hibbits { 26547cabd04SJustin Hibbits phandle_t node; 2660aeed3e9SJustin Hibbits t_FmParams fm_params; 2670aeed3e9SJustin Hibbits t_Handle muram_handle, fm_handle; 2680aeed3e9SJustin Hibbits t_Error error; 2690aeed3e9SJustin Hibbits t_FmRevisionInfo revision_info; 2700aeed3e9SJustin Hibbits uint16_t clock; 2710aeed3e9SJustin Hibbits uint32_t tmp, mod; 2720aeed3e9SJustin Hibbits 2730aeed3e9SJustin Hibbits /* MURAM configuration */ 2740aeed3e9SJustin Hibbits muram_handle = FM_MURAM_ConfigAndInit(cfg->mem_base_addr + 2750aeed3e9SJustin Hibbits FMAN_MURAM_OFF, FMAN_MURAM_SIZE); 2760aeed3e9SJustin Hibbits if (muram_handle == NULL) { 2770aeed3e9SJustin Hibbits device_printf(cfg->fman_device, "couldn't init FM MURAM module" 2780aeed3e9SJustin Hibbits "\n"); 2790aeed3e9SJustin Hibbits return (NULL); 2800aeed3e9SJustin Hibbits } 2810aeed3e9SJustin Hibbits sc->muram_handle = muram_handle; 2820aeed3e9SJustin Hibbits 2830aeed3e9SJustin Hibbits /* Fill in FM configuration */ 2840aeed3e9SJustin Hibbits fm_params.fmId = cfg->fm_id; 2850aeed3e9SJustin Hibbits /* XXX we support only one partition thus each fman has master id */ 2860aeed3e9SJustin Hibbits fm_params.guestId = NCSW_MASTER_ID; 2870aeed3e9SJustin Hibbits 2880aeed3e9SJustin Hibbits fm_params.baseAddr = cfg->mem_base_addr; 2890aeed3e9SJustin Hibbits fm_params.h_FmMuram = muram_handle; 2900aeed3e9SJustin Hibbits 2910aeed3e9SJustin Hibbits /* Get FMan clock in Hz */ 2920aeed3e9SJustin Hibbits if ((tmp = fman_get_clock(sc)) == 0) 2930aeed3e9SJustin Hibbits return (NULL); 2940aeed3e9SJustin Hibbits 2950aeed3e9SJustin Hibbits /* Convert FMan clock to MHz */ 2960aeed3e9SJustin Hibbits clock = (uint16_t)(tmp / 1000000); 2970aeed3e9SJustin Hibbits mod = tmp % 1000000; 2980aeed3e9SJustin Hibbits 2990aeed3e9SJustin Hibbits if (mod >= 500000) 3000aeed3e9SJustin Hibbits ++clock; 3010aeed3e9SJustin Hibbits 3020aeed3e9SJustin Hibbits fm_params.fmClkFreq = clock; 3030aeed3e9SJustin Hibbits fm_params.f_Exception = cfg->exception_callback; 3040aeed3e9SJustin Hibbits fm_params.f_BusError = cfg->bus_error_callback; 3050aeed3e9SJustin Hibbits fm_params.h_App = cfg->fman_device; 3060aeed3e9SJustin Hibbits fm_params.irq = cfg->irq_num; 3070aeed3e9SJustin Hibbits fm_params.errIrq = cfg->err_irq_num; 3080aeed3e9SJustin Hibbits 3090aeed3e9SJustin Hibbits fm_params.firmware.size = fman_firmware_size; 3100aeed3e9SJustin Hibbits fm_params.firmware.p_Code = (uint32_t*)fman_firmware; 3110aeed3e9SJustin Hibbits 3120aeed3e9SJustin Hibbits fm_handle = FM_Config(&fm_params); 3130aeed3e9SJustin Hibbits if (fm_handle == NULL) { 3140aeed3e9SJustin Hibbits device_printf(cfg->fman_device, "couldn't configure FM " 3150aeed3e9SJustin Hibbits "module\n"); 3160aeed3e9SJustin Hibbits goto err; 3170aeed3e9SJustin Hibbits } 3180aeed3e9SJustin Hibbits 3190aeed3e9SJustin Hibbits FM_ConfigResetOnInit(fm_handle, TRUE); 3200aeed3e9SJustin Hibbits 3210aeed3e9SJustin Hibbits error = FM_Init(fm_handle); 3220aeed3e9SJustin Hibbits if (error != E_OK) { 3230aeed3e9SJustin Hibbits device_printf(cfg->fman_device, "couldn't init FM module\n"); 3240aeed3e9SJustin Hibbits goto err2; 3250aeed3e9SJustin Hibbits } 3260aeed3e9SJustin Hibbits 3270aeed3e9SJustin Hibbits error = FM_GetRevision(fm_handle, &revision_info); 3280aeed3e9SJustin Hibbits if (error != E_OK) { 3290aeed3e9SJustin Hibbits device_printf(cfg->fman_device, "couldn't get FM revision\n"); 3300aeed3e9SJustin Hibbits goto err2; 3310aeed3e9SJustin Hibbits } 3320aeed3e9SJustin Hibbits 3330aeed3e9SJustin Hibbits device_printf(cfg->fman_device, "Hardware version: %d.%d.\n", 3340aeed3e9SJustin Hibbits revision_info.majorRev, revision_info.minorRev); 3350aeed3e9SJustin Hibbits 33647cabd04SJustin Hibbits /* Initialize the simplebus part of things */ 33747cabd04SJustin Hibbits simplebus_init(sc->sc_base.dev, 0); 33847cabd04SJustin Hibbits 33947cabd04SJustin Hibbits node = ofw_bus_get_node(sc->sc_base.dev); 340a32b5435SJustin Hibbits fman_fill_ranges(node, &sc->sc_base); 341a32b5435SJustin Hibbits sc->rman.rm_type = RMAN_ARRAY; 342a32b5435SJustin Hibbits sc->rman.rm_descr = "FMan range"; 343a32b5435SJustin Hibbits rman_init_from_resource(&sc->rman, sc->mem_res); 34447cabd04SJustin Hibbits for (node = OF_child(node); node > 0; node = OF_peer(node)) { 34547cabd04SJustin Hibbits simplebus_add_device(sc->sc_base.dev, node, 0, NULL, -1, NULL); 34647cabd04SJustin Hibbits } 34747cabd04SJustin Hibbits 3480aeed3e9SJustin Hibbits return (fm_handle); 3490aeed3e9SJustin Hibbits 3500aeed3e9SJustin Hibbits err2: 3510aeed3e9SJustin Hibbits FM_Free(fm_handle); 3520aeed3e9SJustin Hibbits err: 3530aeed3e9SJustin Hibbits FM_MURAM_Free(muram_handle); 3540aeed3e9SJustin Hibbits return (NULL); 3550aeed3e9SJustin Hibbits } 3560aeed3e9SJustin Hibbits 3570aeed3e9SJustin Hibbits static void 3580aeed3e9SJustin Hibbits fman_exception_callback(t_Handle app_handle, e_FmExceptions exception) 3590aeed3e9SJustin Hibbits { 3600aeed3e9SJustin Hibbits struct fman_softc *sc; 3610aeed3e9SJustin Hibbits 3620aeed3e9SJustin Hibbits sc = app_handle; 36347cabd04SJustin Hibbits device_printf(sc->sc_base.dev, "FMan exception occurred.\n"); 3640aeed3e9SJustin Hibbits } 3650aeed3e9SJustin Hibbits 3660aeed3e9SJustin Hibbits static void 3670aeed3e9SJustin Hibbits fman_error_callback(t_Handle app_handle, e_FmPortType port_type, 3680aeed3e9SJustin Hibbits uint8_t port_id, uint64_t addr, uint8_t tnum, uint16_t liodn) 3690aeed3e9SJustin Hibbits { 3700aeed3e9SJustin Hibbits struct fman_softc *sc; 3710aeed3e9SJustin Hibbits 3720aeed3e9SJustin Hibbits sc = app_handle; 37347cabd04SJustin Hibbits device_printf(sc->sc_base.dev, "FMan error occurred.\n"); 3740aeed3e9SJustin Hibbits } 3750aeed3e9SJustin Hibbits /** @} */ 3760aeed3e9SJustin Hibbits 3770aeed3e9SJustin Hibbits 3780aeed3e9SJustin Hibbits /** 3790aeed3e9SJustin Hibbits * @group FMan driver interface. 3800aeed3e9SJustin Hibbits * @{ 3810aeed3e9SJustin Hibbits */ 3820aeed3e9SJustin Hibbits 3830aeed3e9SJustin Hibbits int 3841c41f28fSJustin Hibbits fman_get_handle(device_t dev, t_Handle *fmh) 3850aeed3e9SJustin Hibbits { 3861c41f28fSJustin Hibbits struct fman_softc *sc = device_get_softc(dev); 3870aeed3e9SJustin Hibbits 3881c41f28fSJustin Hibbits *fmh = sc->fm_handle; 3890aeed3e9SJustin Hibbits 3900aeed3e9SJustin Hibbits return (0); 3910aeed3e9SJustin Hibbits } 3920aeed3e9SJustin Hibbits 3930aeed3e9SJustin Hibbits int 3941c41f28fSJustin Hibbits fman_get_muram_handle(device_t dev, t_Handle *muramh) 3950aeed3e9SJustin Hibbits { 3961c41f28fSJustin Hibbits struct fman_softc *sc = device_get_softc(dev); 3970aeed3e9SJustin Hibbits 3981c41f28fSJustin Hibbits *muramh = sc->muram_handle; 3990aeed3e9SJustin Hibbits 4000aeed3e9SJustin Hibbits return (0); 4010aeed3e9SJustin Hibbits } 4020aeed3e9SJustin Hibbits 4030aeed3e9SJustin Hibbits int 4041c41f28fSJustin Hibbits fman_get_bushandle(device_t dev, vm_offset_t *fm_base) 4050aeed3e9SJustin Hibbits { 4061c41f28fSJustin Hibbits struct fman_softc *sc = device_get_softc(dev); 4070aeed3e9SJustin Hibbits 4081c41f28fSJustin Hibbits *fm_base = rman_get_bushandle(sc->mem_res); 40947cabd04SJustin Hibbits 41047cabd04SJustin Hibbits return (0); 41147cabd04SJustin Hibbits } 41247cabd04SJustin Hibbits 41347cabd04SJustin Hibbits int 4140aeed3e9SJustin Hibbits fman_attach(device_t dev) 4150aeed3e9SJustin Hibbits { 4160aeed3e9SJustin Hibbits struct fman_softc *sc; 4170aeed3e9SJustin Hibbits struct fman_config cfg; 4183e7ddf02SJustin Hibbits pcell_t qchan_range[2]; 4193e7ddf02SJustin Hibbits phandle_t node; 4200aeed3e9SJustin Hibbits 4210aeed3e9SJustin Hibbits sc = device_get_softc(dev); 42247cabd04SJustin Hibbits sc->sc_base.dev = dev; 4230aeed3e9SJustin Hibbits 4240aeed3e9SJustin Hibbits /* Check if MallocSmart allocator is ready */ 4250aeed3e9SJustin Hibbits if (XX_MallocSmartInit() != E_OK) { 4260aeed3e9SJustin Hibbits device_printf(dev, "could not initialize smart allocator.\n"); 4270aeed3e9SJustin Hibbits return (ENXIO); 4280aeed3e9SJustin Hibbits } 4290aeed3e9SJustin Hibbits 4303e7ddf02SJustin Hibbits node = ofw_bus_get_node(dev); 4313e7ddf02SJustin Hibbits if (OF_getencprop(node, "fsl,qman-channel-range", qchan_range, 4323e7ddf02SJustin Hibbits sizeof(qchan_range)) <= 0) { 4333e7ddf02SJustin Hibbits device_printf(dev, "Missing QMan channel range property!\n"); 4343e7ddf02SJustin Hibbits return (ENXIO); 4353e7ddf02SJustin Hibbits } 4363e7ddf02SJustin Hibbits sc->qman_chan_base = qchan_range[0]; 4373e7ddf02SJustin Hibbits sc->qman_chan_count = qchan_range[1]; 4380aeed3e9SJustin Hibbits sc->mem_rid = 0; 4390aeed3e9SJustin Hibbits sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, 44047cabd04SJustin Hibbits RF_ACTIVE | RF_SHAREABLE); 4410aeed3e9SJustin Hibbits if (!sc->mem_res) { 4420aeed3e9SJustin Hibbits device_printf(dev, "could not allocate memory.\n"); 4430aeed3e9SJustin Hibbits return (ENXIO); 4440aeed3e9SJustin Hibbits } 4450aeed3e9SJustin Hibbits 4460aeed3e9SJustin Hibbits sc->irq_rid = 0; 4470aeed3e9SJustin Hibbits sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, 4480aeed3e9SJustin Hibbits RF_ACTIVE); 4490aeed3e9SJustin Hibbits if (!sc->irq_res) { 4500aeed3e9SJustin Hibbits device_printf(dev, "could not allocate interrupt.\n"); 4510aeed3e9SJustin Hibbits goto err; 4520aeed3e9SJustin Hibbits } 4530aeed3e9SJustin Hibbits 4540aeed3e9SJustin Hibbits sc->err_irq_rid = 1; 4550aeed3e9SJustin Hibbits sc->err_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 4560aeed3e9SJustin Hibbits &sc->err_irq_rid, RF_ACTIVE | RF_SHAREABLE); 4570aeed3e9SJustin Hibbits if (!sc->err_irq_res) { 4580aeed3e9SJustin Hibbits device_printf(dev, "could not allocate error interrupt.\n"); 4590aeed3e9SJustin Hibbits goto err; 4600aeed3e9SJustin Hibbits } 4610aeed3e9SJustin Hibbits 4620aeed3e9SJustin Hibbits /* Set FMan configuration */ 4630aeed3e9SJustin Hibbits cfg.fman_device = dev; 4640aeed3e9SJustin Hibbits cfg.fm_id = device_get_unit(dev); 4650aeed3e9SJustin Hibbits cfg.mem_base_addr = rman_get_bushandle(sc->mem_res); 466f77405e3SJustin Hibbits cfg.irq_num = (uintptr_t)sc->irq_res; 467f77405e3SJustin Hibbits cfg.err_irq_num = (uintptr_t)sc->err_irq_res; 4680aeed3e9SJustin Hibbits cfg.exception_callback = fman_exception_callback; 4690aeed3e9SJustin Hibbits cfg.bus_error_callback = fman_error_callback; 4700aeed3e9SJustin Hibbits 4710aeed3e9SJustin Hibbits sc->fm_handle = fman_init(sc, &cfg); 4720aeed3e9SJustin Hibbits if (sc->fm_handle == NULL) { 4730aeed3e9SJustin Hibbits device_printf(dev, "could not be configured\n"); 474d56c7ac8SJustin Hibbits goto err; 4750aeed3e9SJustin Hibbits } 4760aeed3e9SJustin Hibbits 4770aeed3e9SJustin Hibbits return (bus_generic_attach(dev)); 4780aeed3e9SJustin Hibbits 4790aeed3e9SJustin Hibbits err: 4800aeed3e9SJustin Hibbits fman_detach(dev); 4810aeed3e9SJustin Hibbits return (ENXIO); 4820aeed3e9SJustin Hibbits } 4830aeed3e9SJustin Hibbits 4840aeed3e9SJustin Hibbits int 4850aeed3e9SJustin Hibbits fman_detach(device_t dev) 4860aeed3e9SJustin Hibbits { 4870aeed3e9SJustin Hibbits struct fman_softc *sc; 4880aeed3e9SJustin Hibbits 4890aeed3e9SJustin Hibbits sc = device_get_softc(dev); 4900aeed3e9SJustin Hibbits 4910aeed3e9SJustin Hibbits if (sc->muram_handle) { 4920aeed3e9SJustin Hibbits FM_MURAM_Free(sc->muram_handle); 4930aeed3e9SJustin Hibbits } 4940aeed3e9SJustin Hibbits 4950aeed3e9SJustin Hibbits if (sc->fm_handle) { 4960aeed3e9SJustin Hibbits FM_Free(sc->fm_handle); 4970aeed3e9SJustin Hibbits } 4980aeed3e9SJustin Hibbits 4990aeed3e9SJustin Hibbits if (sc->mem_res) { 5000aeed3e9SJustin Hibbits bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, 5010aeed3e9SJustin Hibbits sc->mem_res); 5020aeed3e9SJustin Hibbits } 5030aeed3e9SJustin Hibbits 5040aeed3e9SJustin Hibbits if (sc->irq_res) { 5050aeed3e9SJustin Hibbits bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, 5060aeed3e9SJustin Hibbits sc->irq_res); 5070aeed3e9SJustin Hibbits } 5080aeed3e9SJustin Hibbits 5090aeed3e9SJustin Hibbits if (sc->irq_res) { 5100aeed3e9SJustin Hibbits bus_release_resource(dev, SYS_RES_IRQ, sc->err_irq_rid, 5110aeed3e9SJustin Hibbits sc->err_irq_res); 5120aeed3e9SJustin Hibbits } 5130aeed3e9SJustin Hibbits 5140aeed3e9SJustin Hibbits return (0); 5150aeed3e9SJustin Hibbits } 5160aeed3e9SJustin Hibbits 5170aeed3e9SJustin Hibbits int 5180aeed3e9SJustin Hibbits fman_suspend(device_t dev) 5190aeed3e9SJustin Hibbits { 5200aeed3e9SJustin Hibbits 5210aeed3e9SJustin Hibbits return (0); 5220aeed3e9SJustin Hibbits } 5230aeed3e9SJustin Hibbits 5240aeed3e9SJustin Hibbits int 525852ba100SJustin Hibbits fman_resume_dev(device_t dev) 5260aeed3e9SJustin Hibbits { 5270aeed3e9SJustin Hibbits 5280aeed3e9SJustin Hibbits return (0); 5290aeed3e9SJustin Hibbits } 5300aeed3e9SJustin Hibbits 5310aeed3e9SJustin Hibbits int 5320aeed3e9SJustin Hibbits fman_shutdown(device_t dev) 5330aeed3e9SJustin Hibbits { 5340aeed3e9SJustin Hibbits 5350aeed3e9SJustin Hibbits return (0); 5360aeed3e9SJustin Hibbits } 5370aeed3e9SJustin Hibbits 5383e7ddf02SJustin Hibbits int 5393e7ddf02SJustin Hibbits fman_qman_channel_id(device_t dev, int port) 5403e7ddf02SJustin Hibbits { 5413e7ddf02SJustin Hibbits struct fman_softc *sc; 5423e7ddf02SJustin Hibbits int qman_port_id[] = {0x31, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 5433e7ddf02SJustin Hibbits 0x2f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; 5443e7ddf02SJustin Hibbits int i; 5453e7ddf02SJustin Hibbits 5463e7ddf02SJustin Hibbits sc = device_get_softc(dev); 5473e7ddf02SJustin Hibbits for (i = 0; i < sc->qman_chan_count; i++) { 5483e7ddf02SJustin Hibbits if (qman_port_id[i] == port) 5493e7ddf02SJustin Hibbits return (sc->qman_chan_base + i); 5503e7ddf02SJustin Hibbits } 5513e7ddf02SJustin Hibbits 5523e7ddf02SJustin Hibbits return (0); 5533e7ddf02SJustin Hibbits } 5543e7ddf02SJustin Hibbits 5550aeed3e9SJustin Hibbits /** @} */ 556