Index: sys/dev/bhnd/cores/chipc/chipc.h =================================================================== --- sys/dev/bhnd/cores/chipc/chipc.h +++ sys/dev/bhnd/cores/chipc/chipc.h @@ -34,8 +34,10 @@ #include #include +#include #include "bhnd_chipc_if.h" +#include "chipcvar.h" /** * Query a ChipCommon device and return the preferred NVRAM data source. @@ -48,4 +50,11 @@ return (BHND_CHIPC_NVRAM_SRC(dev)); } -#endif /* _BHND_CORES_CHIPC_CHIPC_H_ */ \ No newline at end of file +int chipc_init_pflash(device_t dev, uint32_t flash_config); +int chipc_init_sflash(device_t dev, char* flash_name); +int chipc_init_uarts(struct chipc_softc* sc, int num_uarts); +int chipc_init_bus(device_t dev); +void chipc_parse_capabilities(struct chipc_capabilities* capabilities, u_int32_t caps); +void chipc_print_capacilities(struct chipc_capabilities* capabilities); + +#endif /* _BHND_CORES_CHIPC_CHIPC_H_ */ Index: sys/dev/bhnd/cores/chipc/chipc.c =================================================================== --- sys/dev/bhnd/cores/chipc/chipc.c +++ sys/dev/bhnd/cores/chipc/chipc.c @@ -52,6 +52,7 @@ #include +#include "chipc.h" #include "chipcreg.h" #include "chipcvar.h" @@ -152,6 +153,10 @@ sc->caps = bhnd_bus_read_4(sc->core, CHIPC_CAPABILITIES); sc->cst = bhnd_bus_read_4(sc->core, CHIPC_CHIPST); + chipc_parse_capabilities(&sc->capabilities, sc->caps); + if(bootverbose) + chipc_print_capacilities(&sc->capabilities); + // TODO switch (bhnd_chipc_nvram_src(dev)) { case BHND_NVRAM_SRC_CIS: @@ -171,6 +176,48 @@ break; } + error = chipc_init_bus(dev); + if(error > 0){ + device_printf(dev,"init_bus with: %d\n", error); + goto cleanup; + } + + int flash_type = sc->capabilities.flash_type; + //Parallel Flash + switch(flash_type){ + case CHIPC_PFLASH: + sc->flash_cfg = bhnd_bus_read_4(sc->core, CHIPC_FLASH_CFG); + error = chipc_init_pflash(sc->bus, sc->flash_cfg); + break; + case CHIPC_SFLASH_AT: + error = chipc_init_sflash(sc->bus, "at45d"); //not tested yet + break; + case CHIPC_SFLASH_ST: + error = chipc_init_sflash(sc->bus, "mx25l"); + break; + default: + if(bootverbose){ + device_printf(dev, "no flash found\n"); + } + } + + if(error > 0){ + device_printf(dev,"init_flash_failed with: %d\n", error); + goto cleanup; + } + + int uarts = sc->capabilities.num_uarts; + if (uarts > 0 && (error = chipc_init_uarts(sc, uarts)) > 0){ + device_printf(dev,"init_uarts failed with: %d\n", error); + goto cleanup; + } + + error = bus_generic_attach(dev); + if(error > 0){ + device_printf(dev, "bus_gener_attach failed: %d\n", error); + goto cleanup; + } + return (0); cleanup: @@ -297,7 +344,17 @@ DEVMETHOD(device_detach, chipc_detach), DEVMETHOD(device_suspend, chipc_suspend), DEVMETHOD(device_resume, chipc_resume), - + + /* Bus interface */ + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_config_intr, bus_generic_config_intr), + DEVMETHOD(bus_bind_intr, bus_generic_bind_intr), + DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), + /* ChipCommon interface */ DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src), Index: sys/dev/bhnd/cores/chipc/chipc_cfi.c =================================================================== --- /dev/null +++ sys/dev/bhnd/cores/chipc/chipc_cfi.c @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "chipc_slicer.h" + +static int +chipc_cfi_probe(device_t dev) +{ + struct cfi_softc *sc = device_get_softc(dev); + sc->sc_width = 2; + int error = cfi_probe(dev); + if (!error) + device_set_desc(dev, "ChipCommon CFI"); + return (error); +} + +static int +chipc_cfi_attach(device_t dev) +{ + int error = cfi_attach(dev); + if(error) + return error; + + flash_register_slicer(chipc_slicer_flash); + return 0; +} + +static device_method_t chipc_cfi_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, chipc_cfi_probe), + DEVMETHOD(device_attach, chipc_cfi_attach), + DEVMETHOD(device_detach, cfi_detach), + + {0, 0} +}; + +static driver_t chipc_cfi_driver = { + cfi_driver_name, + chipc_cfi_methods, + sizeof(struct cfi_softc), +}; + +DRIVER_MODULE(cfi, bhnd_chipcbus, chipc_cfi_driver, cfi_devclass, 0, 0); + Index: sys/dev/bhnd/cores/chipc/chipc_slicer.h =================================================================== --- /dev/null +++ sys/dev/bhnd/cores/chipc/chipc_slicer.h @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#pragma once + +#include + +int chipc_slicer_flash(device_t dev, struct flash_slice *slices, int *nslices); Index: sys/dev/bhnd/cores/chipc/chipc_slicer.c =================================================================== --- /dev/null +++ sys/dev/bhnd/cores/chipc/chipc_slicer.c @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "chipc_spi.h" +#include "flash_if.h" + +#include + +#define TRX_MAGIC 0x30524448 +#define CFE_MAGIC 0x43464531 +#define NVRAM_MAGIC 0x48534C46 + + +int chipc_slicer_walk(struct resource* res, int flash_size, struct flash_slice *slices, int *nslices); +int chipc_slicer_flash(device_t dev, struct flash_slice *slices, int *nslices); + +/* + * Slicer is required to split firmware images into pieces. + * The first supported FW is TRX-based used by Asus routers + * TODO: add NetGear FW (CHK) + */ +int chipc_slicer_flash(device_t dev, struct flash_slice *slices, int *nslices){ + struct resource* res; + int flash_size; + const char* devclazz = device_get_name(dev); + + BHND_INFO_DEV(dev, ("start flash slicer for class %s", + device_get_name(dev))); + + if (strcmp(devclazz, "mx25l") == 0) { //SPI + //flash(mx25l) <- spibus <- chipc_spi + device_t spibus = device_get_parent(dev); + device_t chipc_spi = device_get_parent(spibus); + struct chipc_spi_softc *sc = device_get_softc(chipc_spi); + + flash_size = FLASH_GET_SIZE(dev); + res = sc->sc_res; + + }else if(strcmp(devclazz, "cfi") == 0){ //CFI + struct cfi_softc *sc = device_get_softc(dev); + + flash_size = sc->sc_size; + res = sc->sc_res; + }else { + //Unsupported case + BHND_ERROR_DEV(dev, ("unsupported flash device class: %s", device_get_name(dev))) + return (0); + } + + /* + * Main processing part + */ + return chipc_slicer_walk(res,flash_size,slices,nslices); +} + +int chipc_slicer_walk(struct resource* res, int flash_size, struct flash_slice *slices, int *nslices){ + bus_space_tag_t mem_tag = rman_get_bustag(res); + bus_space_handle_t mem_hndl = rman_get_bushandle(res); + + *nslices = 0; + BHND_TRACE(("slicer: scanning memory for headers...\n")); + + /* Find FW header in flash memory with step = 0x1000 (or block size (128Kb)? */ + for(uint32_t ofs = 0; ofs < flash_size; ofs+= 0x1000){ + uint32_t val = bus_space_read_4(mem_tag, mem_hndl, ofs); + switch(val){ + case TRX_MAGIC: + BHND_DEBUG(("TRX found: %x\n", ofs)); + //read last offset of TRX header + uint32_t fs_ofs = bus_space_read_4(mem_tag, mem_hndl, ofs + 24); + BHND_DEBUG(("FS offset: %x\n", fs_ofs)); + + /* + * GEOM IO will panic if offset is not aligned on sector size, i.e. 512 bytes + */ + if(fs_ofs % 0x200 != 0){ + BHND_ERROR(("WARNING! filesystem offset should be aligned on sector size (%d bytes)\n", 0x200)); + break; + } + + slices[*nslices].base = ofs + fs_ofs; + //XXX: fully sized? any other partition? + uint32_t fw_len = bus_space_read_4(mem_tag, mem_hndl, ofs + 4); + slices[*nslices].size = fw_len - fs_ofs; + slices[*nslices].label = "rootfs"; + *nslices += 1; + break; + case CFE_MAGIC: + BHND_DEBUG(( "CFE found: %x\n", ofs )); + break; + case NVRAM_MAGIC: + BHND_DEBUG(( "NVRAM found: %x\n", ofs )); + break; + default: + break; + } + } + + BHND_TRACE(("slicer: done\n")); + return (0); +} + Index: sys/dev/bhnd/cores/chipc/chipc_spi.h =================================================================== --- /dev/null +++ sys/dev/bhnd/cores/chipc/chipc_spi.h @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#pragma once + +#define CHIPC_SPI_MAXRES 2 +#define CHIPC_SPI_MAXTRIES 1000 + +#define CHIPC_SPI_ACTION_INPUT 1 +#define CHIPC_SPI_ACTION_OUTPUT 2 + +#define CHIPC_SPI_FLASHCTL 0x00 +#define CHIPC_SPI_FLASHCTL_OPCODE 0x000000ff +#define CHIPC_SPI_FLASHCTL_ACTION 0x00000700 // +/* + * We don't use action at all. Experimentaly found, that + * action 0 - read current MISO byte to data register (interactive mode) + * action 1 = read 2nd byte to data register + * action 2 = read 4th byte to data register (surprise! see action 6) + * action 3 = read 5th byte to data register + * action 4 = read bytes 5-8 to data register in swapped order + * action 5 = read bytes 9-12 to data register in swapped order + * action 6 = read 3rd byte to data register + * action 7 = read bytes 6-9 to data register in swapped order + * It may be wrong if CS bit is 1. + * If CS bit is 1, you should write cmd / data to opcode byte-to-byte. + */ +#define CHIPC_SPI_FLASHCTL_CSACTIVE 0x00001000 +#define CHIPC_SPI_FLASHCTL_START 0x80000000 //same as BUSY +#define CHIPC_SPI_FLASHCTL_BUSY 0x80000000 //same as BUSY +#define CHIPC_SPI_FLASHADDR 0x04 +#define CHIPC_SPI_FLASHDATA 0x08 + + +struct chipc_spi_softc{ + device_t dev; + struct bhnd_resource* bhnd_res[CHIPC_SPI_MAXRES]; + // SPI registers + int sc_mem_rid; + struct resource* sc_mem_res; + + // MMIO flash + struct resource *sc_res; + bus_space_handle_t sc_handle; + bus_space_tag_t sc_tag; + int sc_rid; +}; + +/* + * register space access macros + */ + +#define SPI_BARRIER_WRITE(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \ + BUS_SPACE_BARRIER_WRITE) +#define SPI_BARRIER_READ(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \ + BUS_SPACE_BARRIER_READ) +#define SPI_BARRIER_RW(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \ + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) + +#define SPI_WRITE(sc, reg, val) do { \ + bus_write_4(sc->sc_mem_res, (reg), (val)); \ + } while (0) + +#define SPI_READ(sc, reg) bus_read_4(sc->sc_mem_res, (reg)) + +#define SPI_SET_BITS(sc, reg, bits) \ + SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) | (bits)) + +#define SPI_CLEAR_BITS(sc, reg, bits) \ + SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) & ~(bits)) + + Index: sys/dev/bhnd/cores/chipc/chipc_spi.c =================================================================== --- /dev/null +++ sys/dev/bhnd/cores/chipc/chipc_spi.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Flash slicer + */ +#include "chipc_slicer.h" + +/* + * SPI BUS interface + */ +#include +#include "spibus_if.h" +#include "flash_if.h" + +#include +#include "chipcreg.h" +#include "chipcvar.h" +#include "chipc_spi.h" + +/* + * **************************** VARIABLES **************************** + */ + +//static struct resource_spec chipc_spi_resource_specs[] = { +// {SYS_RES_MEMORY, 0, RF_ACTIVE}, +// {-1, -1, -1} +//}; + +/* + * **************************** PROTOTYPES **************************** + */ + +static int chipc_spi_probe(device_t dev); +static int chipc_spi_attach(device_t dev); +static int chipc_spi_transfer(device_t dev, device_t child, struct spi_command *cmd); +static int chipc_spi_txrx(struct chipc_spi_softc *sc, uint8_t in, uint8_t* out); +static int chipc_spi_wait(struct chipc_spi_softc *sc); + +/* + * **************************** IMPLEMENTATION ************************ + */ + +#define TRX_MAGIC 0x30524448 +#define CFE_MAGIC 0x43464531 +#define NVRAM_MAGIC 0x48534C46 + +static int chipc_spi_probe(device_t dev){ + device_set_desc(dev, "ChipCommon SPI"); + return (BUS_PROBE_DEFAULT); //??? BUS_PROBE_NOWILDCARD +} + +static int chipc_spi_attach(device_t dev){ + struct chipc_spi_softc* sc = device_get_softc(dev); + + sc->sc_rid = 0; + sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, + RF_ACTIVE); + if (sc->sc_res == NULL) + return (ENXIO); + + sc->sc_mem_rid = 1; + sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mem_rid, + RF_ACTIVE); + if (sc->sc_mem_res == NULL) + return (ENXIO); + + sc->sc_tag = rman_get_bustag(sc->sc_res); + sc->sc_handle = rman_get_bushandle(sc->sc_res); + + flash_register_slicer(chipc_slicer_flash); + + device_add_child(dev, "spibus", 0); + return (bus_generic_attach(dev)); +} + +static int chipc_spi_wait(struct chipc_spi_softc *sc) { + int i = CHIPC_SPI_MAXTRIES; + + while (i--) + if (!(SPI_READ(sc, CHIPC_SPI_FLASHCTL) & CHIPC_SPI_FLASHCTL_START)) + break; + + if (i != 0) + return (0); + + BHND_DEBUG_DEV(sc->dev, ("busy")); + return (-1); +} + +static int chipc_spi_txrx(struct chipc_spi_softc *sc, uint8_t out, uint8_t* in) { + uint32_t ctl = CHIPC_SPI_FLASHCTL_START | CHIPC_SPI_FLASHCTL_CSACTIVE | out; + SPI_BARRIER_WRITE(sc); + SPI_WRITE(sc, CHIPC_SPI_FLASHCTL, ctl); + SPI_BARRIER_WRITE(sc); + + if (chipc_spi_wait(sc)) + return (-1); + + *in = SPI_READ(sc, CHIPC_SPI_FLASHDATA) & 0xff; + return (0); +} + +static int chipc_spi_transfer(device_t dev, device_t child, struct spi_command *cmd) { + struct chipc_spi_softc *sc = device_get_softc(dev); + uint8_t *buf_in, *buf_out; + int i; + + KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, + ("TX/RX command sizes should be equal")); + KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, + ("TX/RX data sizes should be equal")); + + if(cmd->tx_cmd_sz == 0){ + BHND_DEBUG_DEV(child, ("size of command is ZERO")); + return (EIO); + } + + SPI_BARRIER_WRITE(sc); + SPI_WRITE(sc, CHIPC_SPI_FLASHADDR, 0); + SPI_BARRIER_WRITE(sc); + + /* + * Transfer command + */ + buf_out = (uint8_t *)cmd->tx_cmd; + buf_in = (uint8_t *)cmd->rx_cmd; + for (i = 0; i < cmd->tx_cmd_sz; i++) + if (chipc_spi_txrx(sc, buf_out[i], &(buf_in[i]))) + return (EIO); + + /* + * Receive/transmit data + */ + buf_out = (uint8_t *)cmd->tx_data; + buf_in = (uint8_t *)cmd->rx_data; + for (i = 0; i < cmd->tx_data_sz; i++) + if (chipc_spi_txrx(sc, buf_out[i], &(buf_in[i]))) + return (EIO); + + /* + * Clear CS bit and whole control register + */ + SPI_BARRIER_WRITE(sc); + SPI_WRITE(sc, CHIPC_SPI_FLASHCTL, 0); + SPI_BARRIER_WRITE(sc); + + return (0); +} + +/* + * **************************** METADATA ************************ + */ + +static device_method_t chipc_spi_methods[] = { + DEVMETHOD(device_probe, chipc_spi_probe), + DEVMETHOD(device_attach, chipc_spi_attach), + /* SPI */ + DEVMETHOD(spibus_transfer, chipc_spi_transfer), + DEVMETHOD_END +}; + + +static driver_t chipc_spi_driver = { + "spi", + chipc_spi_methods, + sizeof(struct chipc_spi_softc), +}; + +static devclass_t chipc_spi_devclass; + + +DRIVER_MODULE(chipc_spi, bhnd_chipcbus, chipc_spi_driver, chipc_spi_devclass, 0, 0); Index: sys/dev/bhnd/cores/chipc/chipc_subr.c =================================================================== --- /dev/null +++ sys/dev/bhnd/cores/chipc/chipc_subr.c @@ -0,0 +1,216 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "bus_if.h" +#include "chipc.h" +#include "chipcvar.h" +#include "chipcreg.h" +#include "chipcbus.h" + +int chipc_init_bus(device_t dev){ + struct chipc_softc* sc = device_get_softc(dev); + device_t bus = device_add_child(dev,"bhnd_chipcbus",-1); + if(bus == NULL){ + BHND_ERROR_DEV(dev, ("error occurred during adding BUS")); + return ENXIO; + } + + struct chipcbus_ivar* ivar = malloc(sizeof(struct chipcbus_ivar), M_BHND, M_NOWAIT); + if (ivar == NULL){ + BHND_ERROR_DEV(dev, ("can't allocate memory for chipcbus_ivar")); + return ENOMEM; + } + + device_set_ivars(bus, ivar); + sc->bus = bus; + SLIST_INIT(&ivar->mems); + SLIST_INIT(&ivar->irqs); + + /* + * Iterate over device ports & regions and fill instance variable + */ + bhnd_addr_t rg_start; + bhnd_size_t rg_size; + int ret; + + for(int i = 0; i < bhnd_get_port_count(dev, BHND_PORT_DEVICE); i++){ + int rgcnt = bhnd_get_region_count(dev, BHND_PORT_DEVICE, i); + BHND_DEBUG_DEV(dev, ("[%d] region count = %d", i, rgcnt)); + for (int j = 0; j < rgcnt; j++){ + ret = bhnd_get_region_addr(dev, BHND_PORT_DEVICE, i, j, &rg_start, &rg_size); + BHND_DEBUG_DEV(dev, ("[%d.%d] region addr = 0x%jx (%d)", i, j, rg_start, ret)); + if(!ret){ + struct chipcbus_reg* reg = malloc(sizeof(struct chipcbus_reg), M_BHND, M_NOWAIT); + reg->start = rg_start; + reg->end = rg_start + rg_size - 1; + reg->port = i; + reg->reg = j; + SLIST_INSERT_HEAD(&ivar->mems, reg, entries); + } + } + } + + int err = device_probe_and_attach(bus); + if(err) + BHND_ERROR_DEV(bus,("probe_and_attach failed with error:%d", err)); + + return err; +} + +int chipc_init_pflash(device_t dev, uint32_t flash_config){ + //TODO: pass parameters to CFI + int width = (flash_config & CHIPC_CF_DS) ? 2 : 1; + int enabled = (flash_config & CHIPC_CF_EN); + int byteswap = (flash_config & CHIPC_CF_BS); + + BHND_DEBUG_DEV(dev,("trying attach flash width=%d enabled=%d swapbytes=%d", width, enabled, byteswap)); + device_t flashdev = device_add_child(dev, "cfi", -1); + if(flashdev == NULL){ + BHND_ERROR_DEV(dev, ("can't add ChipCommon Parallel Flash to bus")); + return ENXIO; + } + + return 0; +} + +int chipc_init_sflash(device_t dev, char* flash_name){ + device_t chipc_spi = device_add_child(dev, "spi", -1); + if(!chipc_spi){ + BHND_ERROR_DEV(dev, ("can't add chipc_spi to ChipCommon ")); + return ENXIO; + } + + int err = device_probe_and_attach(chipc_spi); + if(err){ + BHND_ERROR_DEV(dev, ("failed attach chipc_spi: %d", err)); + return err; + } + + device_t* children; + int cnt_children; + err = device_get_children(chipc_spi, &children, &cnt_children); + + if(err){ + BHND_ERROR_DEV(chipc_spi, ("can't get list of children: %d", err)); + return err; + } + + if(!cnt_children){ + BHND_ERROR_DEV(chipc_spi, ("no found children")); + return ENXIO; + } + + device_t flash = BUS_ADD_CHILD(children[0], 0, flash_name, -1); + + if(children) + free(children, M_TEMP); + + if (!flash){ + BHND_ERROR_DEV(chipc_spi, ("can't add %s to spibus", flash_name)); + } + + err = device_probe_and_attach(flash); + if(err) + BHND_ERROR_DEV(dev, ("failed attach flash %s: %d", flash_name, err)); + + return err; +} + +int chipc_init_uarts(struct chipc_softc* sc, int num_uarts){ + if (num_uarts < 0) + return EINVAL; + else if (num_uarts == 0) + return 0; + + device_t child = device_add_child(sc->bus, "uart", 0); + if(!child){ + BHND_ERROR_DEV(sc->bus, ("can'd add UART to bus")); + return ENXIO; + } + + int err = device_probe_and_attach(child); + if(err) + BHND_ERROR_DEV(child, ("error occuried on probe_and_attach: %d", err)); + + return err; +} + +void chipc_print_capacilities(struct chipc_capabilities* capabilities){ + BHND_DEBUG(("UARTs: 0x%01x", capabilities->num_uarts)) + BHND_DEBUG(("BigEngian: 0x%01x", capabilities->is_bigend)) + BHND_DEBUG(("UART-GPIO: 0x%01x", capabilities->uart_gpio)) + BHND_DEBUG(("UART Clock: 0x%01x", capabilities->uart_clock)) + BHND_DEBUG(("Flash type: 0x%x", capabilities->flash_type)) + + BHND_DEBUG(("External buses: 0x%x", capabilities->external_buses)) + BHND_DEBUG(("Power control: 0x%01x", capabilities->power_control)) + BHND_DEBUG(("JTAG master: 0x%01x", capabilities->jtag_master)) + + BHND_DEBUG(("PLL Type: 0x%x", capabilities->pll_type)) + BHND_DEBUG(("OTP size: 0x%01x", capabilities->otp_size)) + BHND_DEBUG(("Is 64bit? 0x%01x", capabilities->is_64bit)) + BHND_DEBUG(("Boot ROM: 0x%01x", capabilities->boot_rom)) + BHND_DEBUG(("PMU: 0x%01x", capabilities->pmu)) + BHND_DEBUG(("ECI: 0x%01x", capabilities->eci)) + BHND_DEBUG(("SPROM: 0x%01x", capabilities->sprom)) + return; +} + +void chipc_parse_capabilities(struct chipc_capabilities* capabilities, u_int32_t caps){ + capabilities->num_uarts = GET_BITS(caps, CHIPC_CAP_UARTS); + capabilities->is_bigend = GET_BITS(caps, CHIPC_CAP_MIPSEB); + capabilities->uart_gpio = GET_BITS(caps, CHIPC_CAP_UARTGPIO); + capabilities->uart_clock= GET_BITS(caps, CHIPC_CAP_UCLKSEL); + capabilities->flash_type= GET_BITS(caps, CHIPC_CAP_FLASH); + + capabilities->external_buses = GET_BITS(caps, CHIPC_CAP_EXTBUS); + capabilities->power_control = GET_BITS(caps, CHIPC_CAP_PWR_CTL); + capabilities->jtag_master = GET_BITS(caps, CHIPC_CAP_JTAGP); + + capabilities->pll_type = GET_BITS(caps, CHIPC_CAP_PLL); + capabilities->otp_size = GET_BITS(caps, CHIPC_CAP_OTP_SIZE); + capabilities->is_64bit = GET_BITS(caps, CHIPC_CAP_BKPLN64); + capabilities->boot_rom = GET_BITS(caps, CHIPC_CAP_ROM); + capabilities->pmu = GET_BITS(caps, CHIPC_CAP_PMU); + capabilities->eci = GET_BITS(caps, CHIPC_CAP_ECI); + capabilities->sprom = GET_BITS(caps, CHIPC_CAP_SPROM); + return; +} Index: sys/dev/bhnd/cores/chipc/chipcbus.h =================================================================== --- /dev/null +++ sys/dev/bhnd/cores/chipc/chipcbus.h @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ +#pragma once + +#include +#define NUM_IRQS 6 + +struct chipcbus_spec { + char* name; + int type, rid; + int port, reg; + rman_res_t start; + rman_res_t size; + +}; + +struct chipcbus_softc { + device_t dev; + struct rman chipc_mem; + struct rman chipc_irq; +}; + +struct chipcbus_reg{ + SLIST_ENTRY(chipcbus_reg) entries; + rman_res_t start, end; + int port, reg; +}; + +struct chipcbus_ivar { + SLIST_HEAD(mem_list, chipcbus_reg) mems; + int irq_cnt; + SLIST_HEAD(irq_list, chipcbus_reg) irqs; +}; + +struct chipcbus_devinfo { + struct resource_list resources; +}; + +/* + * Prototypes + */ +void chipcbus_cleanup(device_t dev); Index: sys/dev/bhnd/cores/chipc/chipcbus.c =================================================================== --- /dev/null +++ sys/dev/bhnd/cores/chipc/chipcbus.c @@ -0,0 +1,330 @@ +/*- + * Copyright (c) 2016 Michael Zhilin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * The purpose of ChipCommon BUS is resource management for sub-ChipCommon drivers like UART, PMU, flash. + * ChipCommon core was a lot of resource: several memory regions, one or more IRQ lines. To manage / split + * these resources into resources of sub-drivers, this bus is introduced. + * + * The bus has 2 resource managers + * TODO: decide how to split resources + * + * Port.Region - purpose + * 0.0 - main registers (0x40 - SPI, 0x300 - UART) + * 1.0 - ? + * 1.1 - MMIO flash (SPI & CFI) + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include "chipcbus.h" +#include "chipcreg.h" + +#include +/* + * There are 2 flash resources: + * - resource ID (rid) = 0. This is memory-mapped flash memory + * - resource ID (rid) = 1. This is memory-mapped flash registers (for instance for SPI) + */ +struct chipcbus_spec mem_specs[] = { + {"uart", SYS_RES_MEMORY, 0, 0, 0, CHIPC_UART_BASE, CHIPC_UART_SIZE}, + {"uart", SYS_RES_IRQ, 0,-1,-1, 0, 1 }, + {"spi", SYS_RES_MEMORY, 0, 1, 1, 0, ~0}, + {"spi", SYS_RES_MEMORY, 1, 0, 0, CHIPC_FLASHBASE, CHIPC_FLASHREGSZ}, + {"cfi", SYS_RES_MEMORY, 0, 1, 1, 0, ~0}, + {"cfi", SYS_RES_MEMORY, 1, 0, 0, CHIPC_FLASHBASE, CHIPC_FLASHREGSZ}, + {0, 0, 0, 0, 0, 0, 0} +}; + +/* + * FIXME: HACK + */ +struct chipcbus_reg static_irq = { {NULL}, 2, 2, 0, 0 }; + +static struct chipcbus_reg* chipcbus_get_region(device_t bus, int port, int regid){ + struct chipcbus_ivar* ivar = device_get_ivars(bus); + struct chipcbus_reg* reg; + SLIST_FOREACH(reg, &ivar->mems, entries){ + if(reg->port == port && reg->reg == regid){ + return reg; + } + } + return NULL; +} + +static void chipcbus_set_resources(device_t bus, device_t dev, struct resource_list* rl){ + BHND_DEBUG_DEV(dev,("first time to init resources...")); + const char* devname = device_get_name(dev); + struct chipcbus_spec* spec = mem_specs; + while(spec->name){ + if(strcmp(spec->name, devname) == 0){ + int type = spec->type; + int rid = spec->rid; + struct chipcbus_reg* reg; + if(type == SYS_RES_MEMORY){ + reg = chipcbus_get_region(bus, spec->port, spec->reg); + }else if(type == SYS_RES_IRQ){ + reg = &static_irq; + } + if(reg != NULL){ + rman_res_t offset = reg->start; + rman_res_t start = MIN(offset + spec->start, reg->end); + rman_res_t end = MIN(offset + spec->start + MIN(spec->size, reg->end - reg->start + 1) - 1, reg->end); + rman_res_t count = end - start + 1; + resource_list_add(rl,type, rid, start, end, count); + }else{ + BHND_WARN_DEV(dev,("region is not found [type %d, rid %d, port.region %d.%d]", spec->type, spec->rid, spec->port, spec->reg)); + } + } + spec++; + } + return; +} + +void chipcbus_cleanup(device_t dev){ + struct chipcbus_softc* sc = device_get_softc(dev); + rman_fini(&sc->chipc_irq); + rman_fini(&sc->chipc_mem); + return; +} + +static int chipcbus_probe(device_t dev){ + device_set_desc(dev, "ChipCommon BUS"); + return BUS_PROBE_GENERIC; +} + +static int chipcbus_attach(device_t dev){ + int err; + struct chipcbus_softc* sc = device_get_softc(dev); + BHND_DEBUG_DEV(dev, ("start attaching")); + sc->chipc_irq.rm_start = 0; + sc->chipc_irq.rm_end = NUM_IRQS - 1; + sc->chipc_irq.rm_type = RMAN_ARRAY; + sc->chipc_irq.rm_descr = "ChipCommon IRQs"; + err = rman_init(&sc->chipc_irq); + if(err){ + BHND_ERROR_DEV(dev, ("error occurred during init of IRQ rman")); + return err; + } + sc->chipc_mem.rm_start = 0; + sc->chipc_mem.rm_end = BUS_SPACE_MAXADDR; + sc->chipc_mem.rm_type = RMAN_ARRAY; + sc->chipc_mem.rm_descr = "ChipCommon Memory"; + err = rman_init(&sc->chipc_mem); + if(err){ + BHND_ERROR_DEV(dev, ("error occurred during init of MEMORY rman")); + goto error; + } + + struct chipcbus_ivar* ivar = device_get_ivars(dev); + if(ivar != NULL){ + struct chipcbus_reg* reg; + SLIST_FOREACH(reg, &ivar->mems, entries){ + err = rman_manage_region(&sc->chipc_mem, reg->start, reg->end); + if(err){ + BHND_ERROR_DEV(dev, ("error occurred during rman_manage_region of MEMORY rman with params: 0x%jx - 0x%jx" + ,reg->start, reg->end)); + goto error; + } + } +//TODO: IRQ +//FIXME: HACK + err = rman_manage_region(&sc->chipc_irq, 0, NUM_IRQS - 1); + if(err){ + BHND_ERROR_DEV(dev, ("error occurred during rman_manage_region of IRQ rman with params: 0x%d - 0x%d" + , 0, NUM_IRQS)); + goto error; + } +// for(int i = 0; i < ivar->irq_cnt; i++){ +// err = rman_manage_region(&sc->chipc_mem, ivar->irqs[i].start, ivar->irqs[i].end); +// if(err){ +// BHND_ERROR_DEV(dev, ("error occurred during rman_manage_region of IRQ rman with params: %jd - %jd" +// ,ivar->mems[i].start, ivar->mems[i].end)); +// goto error; +// } +// } + }else + BHND_INFO_DEV(dev, ("no instance variables for chipcommon bus")); + + BHND_DEBUG_DEV(dev, ("attached successfully")); + return 0; +error: + BHND_DEBUG_DEV(dev, ("attaching finished with error: %d", err)); + chipcbus_cleanup(dev); + return err; +} + +static int chipcbus_detach(device_t dev){ + chipcbus_cleanup(dev); + return 0; +} + +static struct resource_list * +chipcbus_get_resource_list(device_t dev, device_t child){ + struct chipcbus_devinfo *dinfo = device_get_ivars(child); + + /* + * Lazy way of resource assignment + */ + if(dinfo == NULL){ + dinfo = malloc(sizeof(struct chipcbus_devinfo*), M_BHND, M_NOWAIT); + + if (!dinfo){ + BHND_ERROR_DEV(dev, ("can't allocate memory for chipcbus_devinfo of %s", device_get_nameunit(child))); + return NULL; + } + + resource_list_init(&(dinfo->resources)); + chipcbus_set_resources(dev, child, &(dinfo->resources)); + device_set_ivars(child, dinfo); + } + + return (&dinfo->resources); +} + +static struct resource * +chipcbus_alloc_resource(device_t bus, device_t child, int type, int *rid, + rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) +{ + struct chipcbus_softc* sc = device_get_softc(bus); + BHND_DEBUG_DEV(child,("looking for allocation resource [%d]: %d, 0x%jx, 0x%jx, 0x%jx", type, *rid, start, end, count)); + + if(RMAN_IS_DEFAULT_RANGE(start, end) && count == 1){ + struct resource_list* rl = chipcbus_get_resource_list(bus, child); + struct resource_list_entry* rle = resource_list_find(rl, type, *rid); + if(rle == NULL){ + BHND_DEBUG_DEV(child, ("there is no resource in resource list: type %d rid %d",type, *rid)); + return NULL; + } + start = rle->start; + end = rle->end; + count = rle->count; + } + + struct rman* rm; + switch (type) { + case SYS_RES_IRQ: + rm = &sc->chipc_irq; + break; + case SYS_RES_MEMORY: + rm = &sc->chipc_mem; + break; + default: + BHND_ERROR_DEV(child,("unknown resource type %d", type)); + return NULL; + } + + BHND_DEBUG_DEV(child,("ready for rman_reserve [%d]: %d, 0x%jx, 0x%jx, 0x%jx", type, *rid, start, end, count)); + + struct resource* r = rman_reserve_resource(rm, start, end, count, flags, child); + if (r == NULL) { + BHND_ERROR_DEV(child, ("could not reserve resource %d: 0x%jx-0x%jx", *rid, start, end)); + return NULL; + } + + rman_set_rid(r, *rid); + + if (flags & RF_ACTIVE) + if (bus_activate_resource(child, type, *rid, r)) { + BHND_ERROR_DEV(child, ("could not activate resource %d: 0x%jx-0x%jx", *rid, start, end)); + rman_release_resource(r); + return NULL; + } + + return r; +} + +static int chipcbus_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + if (rman_get_flags(r) & RF_ACTIVE) { + int error = bus_deactivate_resource(child, type, rid, r); + if (error) + return error; + } + + return (rman_release_resource(r)); +} + +static void chipcbus_probe_nomatch(device_t dev, device_t child){ + device_printf(dev, "no found driver for %s\n", device_get_name(child)); +}; + +static device_method_t chipcbus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, chipcbus_probe), + DEVMETHOD(device_attach, chipcbus_attach), + DEVMETHOD(device_detach, chipcbus_detach), + + /* Bus interface */ + DEVMETHOD(bus_get_resource_list, chipcbus_get_resource_list), + DEVMETHOD(bus_alloc_resource, chipcbus_alloc_resource), + DEVMETHOD(bus_release_resource, chipcbus_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_config_intr, bus_generic_config_intr), + DEVMETHOD(bus_bind_intr, bus_generic_bind_intr), + DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), + + DEVMETHOD(bus_probe_nomatch, chipcbus_probe_nomatch), + +// DEVMETHOD(bus_delete_resource, nexus_delete_resource), +// DEVMETHOD(bus_get_resource, nexus_get_resource), +// DEVMETHOD(bus_print_child, nexus_print_child), +// DEVMETHOD(bus_set_resource, nexus_set_resource), +// DEVMETHOD(bus_hinted_child, nexus_hinted_child), + + DEVMETHOD_END +}; + +devclass_t bhnd_chipcbus_devclass; /**< bhnd(4) chipcommon bus device class */ + +DEFINE_CLASS_0(bhnd_chipcbus, chipcbus_driver, chipcbus_methods, sizeof(struct chipcbus_softc)); + +DRIVER_MODULE(bhnd_chipcbus, bhnd_chipc, chipcbus_driver, bhnd_chipcbus_devclass, 0, 0); +MODULE_DEPEND(bhnd_chipcbus, bhnd_chipc, 1, 1, 1); +MODULE_VERSION(bhnd_chipcbus, 1); Index: sys/dev/bhnd/cores/chipc/chipcreg.h =================================================================== --- sys/dev/bhnd/cores/chipc/chipcreg.h +++ sys/dev/bhnd/cores/chipc/chipcreg.h @@ -25,6 +25,8 @@ #ifndef _BHND_CORES_CHIPC_CHIPCREG_H_ #define _BHND_CORES_CHIPC_CHIPCREG_H_ +#define GET_BITS(value,field) (value & field) >> field##_SHIFT; + #define CHIPC_CHIPID_SIZE 0x100 /**< size of the register block containing the chip identification registers. */ @@ -60,6 +62,8 @@ #define CHIPC_JTAGIR 0x34 #define CHIPC_JTAGDR 0x38 #define CHIPC_JTAGCTRL 0x3c +#define CHIPC_FLASHBASE 0x40 +#define CHIPC_FLASHREGSZ 12 #define CHIPC_GPIOPU 0x58 #define CHIPC_GPIOPD 0x5c #define CHIPC_GPIOIN 0x60 @@ -76,10 +80,14 @@ #define CHIPC_CLKC_M3 0xa0 #define CHIPC_CLKDIV 0xa4 #define CHIPC_SYS_CLK_CTL 0xc0 +#define CHIPC_FLASH_CFG 0x128 +#define CHIPC_FLASH_WAIT_CNT 0x12C #define CHIPC_SPROM_CTRL 0x190 /**< SPROM interface (rev >= 32) */ #define CHIPC_SPROM_ADDR 0x194 #define CHIPC_SPROM_DATA 0x198 #define CHIPC_CLK_CTL_ST SI_CLK_CTL_ST +#define CHIPC_UART_BASE 0x300 +#define CHIPC_UART_SIZE 0x100 #define CHIPC_PMU_CTL 0x600 #define CHIPC_PMU_CAP 0x604 #define CHIPC_PMU_ST 0x608 @@ -96,27 +104,43 @@ #define CHIPC_SPROM_OTP 0x800 /* SPROM/OTP address space */ /* capabilities */ -#define CHIPC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ -#define CHIPC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ -#define CHIPC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ -#define CHIPC_CAP_UINTCLK 0x00000008 /* UARTs are driven by internal divided clock */ -#define CHIPC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ -#define CHIPC_CAP_EXTBUS_MASK 0x000000c0 /* External bus mask */ -#define CHIPC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ -#define CHIPC_CAP_EXTBUS_FULL 0x00000040 /* ExtBus: PCMCIA, IDE & Prog */ -#define CHIPC_CAP_EXTBUS_PROG 0x00000080 /* ExtBus: ProgIf only */ -#define CHIPC_CAP_FLASH_MASK 0x00000700 /* Type of flash */ -#define CHIPC_CAP_PLL_MASK 0x00038000 /* Type of PLL */ -#define CHIPC_CAP_PWR_CTL 0x00040000 /* Power control */ -#define CHIPC_CAP_OTP_SIZE 0x00380000 /* OTP Size (0 = none) */ -#define CHIPC_CAP_OTP_SIZE_SHIFT 19 /* OTP Size shift */ -#define CHIPC_CAP_OTP_SIZE_BASE 5 /* OTP Size base */ -#define CHIPC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ -#define CHIPC_CAP_ROM 0x00800000 /* Internal boot rom active */ -#define CHIPC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ -#define CHIPC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ -#define CHIPC_CAP_SPROM 0x40000000 /* SPROM Present, rev >= 32 */ -#define CHIPC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */ +#define CHIPC_CAP_UARTS 0x00000003 /* Number of UARTs */ +#define CHIPC_CAP_UARTS_SHIFT 0 +#define CHIPC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ +#define CHIPC_CAP_MIPSEB_SHIFT 2 +#define CHIPC_CAP_UCLKSEL 0x00000018 /* UARTs clock select */ +#define CHIPC_CAP_UCLKSEL_SHIFT 3 +#define CHIPC_CAP_UCLKSEL_UINTCLK 0x00000001 /* UARTs are driven by internal divided clock */ +#define CHIPC_CAP_UARTGPIO 0x00000020 /* UARTs own GPIOs 15:12 */ +#define CHIPC_CAP_UARTGPIO_SHIFT 5 +#define CHIPC_CAP_EXTBUS 0x000000c0 /* External bus mask */ +#define CHIPC_CAP_EXTBUS_SHIFT 6 +#define CHIPC_CAP_EXTBUS_NONE 0x00000000 /* No ExtBus present */ +#define CHIPC_CAP_EXTBUS_FULL 0x00000001 /* ExtBus: PCMCIA, IDE & Prog */ +#define CHIPC_CAP_EXTBUS_PROG 0x00000002 /* ExtBus: ProgIf only */ +#define CHIPC_CAP_FLASH 0x00000700 /* Type of flash */ +#define CHIPC_CAP_FLASH_SHIFT 8 +#define CHIPC_CAP_PLL 0x00038000 /* Type of PLL */ +#define CHIPC_CAP_PLL_SHIFT 15 +#define CHIPC_CAP_PWR_CTL 0x00040000 /* Power control */ +#define CHIPC_CAP_PWR_CTL_SHIFT 18 +#define CHIPC_CAP_OTP_SIZE 0x00380000 /* OTP Size (0 = none) */ +#define CHIPC_CAP_OTP_SIZE_SHIFT 19 /* OTP Size shift */ +#define CHIPC_CAP_OTP_SIZE_BASE 5 /* OTP Size base */ +#define CHIPC_CAP_JTAGP 0x00400000 /* JTAG Master Present */ +#define CHIPC_CAP_JTAGP_SHIFT 22 +#define CHIPC_CAP_ROM 0x00800000 /* Internal boot rom active */ +#define CHIPC_CAP_ROM_SHIFT 23 +#define CHIPC_CAP_BKPLN64 0x08000000 /* 64-bit backplane */ +#define CHIPC_CAP_BKPLN64_SHIFT 27 +#define CHIPC_CAP_PMU 0x10000000 /* PMU Present, rev >= 20 */ +#define CHIPC_CAP_PMU_SHIFT 28 +#define CHIPC_CAP_ECI 0x20000000 /*Enhanced Coexistence Interface */ +#define CHIPC_CAP_ECI_SHIFT 29 +#define CHIPC_CAP_SPROM 0x40000000 /* SPROM Present, rev >= 32 */ +#define CHIPC_CAP_SPROM_SHIFT 30 +#define CHIPC_CAP_NFLASH 0x80000000 /* Nand flash present, rev >= 35 */ +#define CHIPC_CAP_NFLASH_SHIFT 31 #define CHIPC_CAP2_SECI 0x00000001 /* SECI Present, rev >= 36 */ #define CHIPC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */ @@ -488,10 +512,10 @@ #define CHIPC_CLKC_5350_M 0x04020009 /* Flash types in the chipcommon capabilities register */ -#define CHIPC_FLASH_NONE 0x000 /* No flash */ -#define CHIPC_SFLASH_ST 0x100 /* ST serial flash */ -#define CHIPC_SFLASH_AT 0x200 /* Atmel serial flash */ -#define CHIPC_PFLASH 0x700 /* Parallel flash */ +#define CHIPC_FLASH_NONE 0x0 /* No flash */ +#define CHIPC_SFLASH_ST 0x1 /* ST serial flash */ +#define CHIPC_SFLASH_AT 0x2 /* Atmel serial flash */ +#define CHIPC_PFLASH 0x7 /* Parallel flash */ /* Bits in the ExtBus config registers */ #define CHIPC_CFG_EN 0x0001 /* Enable */ Index: sys/dev/bhnd/cores/chipc/chipcvar.h =================================================================== --- sys/dev/bhnd/cores/chipc/chipcvar.h +++ sys/dev/bhnd/cores/chipc/chipcvar.h @@ -32,7 +32,10 @@ #ifndef _BHND_CORES_CHIPC_CHIPCVAR_H_ #define _BHND_CORES_CHIPC_CHIPCVAR_H_ -#include "chipc.h" +#include +#include +#include +#include DECLARE_CLASS(bhnd_chipc); extern devclass_t bhnd_chipc_devclass; @@ -78,8 +81,27 @@ CHIPC_QUIRK_SUPPORTS_NFLASH = (1<<6), }; +struct chipc_capabilities{ + u_int8_t num_uarts; + u_int8_t is_bigend; + u_int8_t uart_clock; + u_int8_t uart_gpio; + u_int8_t external_buses; + u_int8_t flash_type; + u_int8_t pll_type; + u_int8_t power_control; + u_int8_t otp_size; + u_int8_t jtag_master; + u_int8_t boot_rom; + u_int8_t is_64bit; + u_int8_t pmu; + u_int8_t eci; + u_int8_t sprom; +}; + struct chipc_softc { device_t dev; + device_t bus; struct resource_spec rspec[CHIPC_MAX_RSPEC]; struct bhnd_resource *res[CHIPC_MAX_RES]; @@ -89,6 +111,8 @@ uint32_t quirks; /**< CHIPC_QUIRK_* quirk flags */ uint32_t caps; /**< CHIPC_CAP_* capability register flags */ uint32_t cst; /**< CHIPC_CST* status register flags */ + uint32_t flash_cfg; /**< CHIPC_FLASH_CFG register data */ + struct chipc_capabilities capabilities; }; -#endif /* _BHND_CORES_CHIPC_CHIPCVAR_H_ */ \ No newline at end of file +#endif /* _BHND_CORES_CHIPC_CHIPCVAR_H_ */