Page MenuHomeFreeBSD

D6250.id15986.diff
No OneTemporary

D6250.id15986.diff

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 <dev/bhnd/bhnd.h>
#include <dev/bhnd/nvram/bhnd_nvram.h>
+#include <sys/rman.h>
#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 <dev/bhnd/bhnd.h>
+#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 <mizhka@gmail.com>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+
+#include <dev/cfi/cfi_var.h>
+
+#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 <mizhka@gmail.com>
+ * 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 <sys/slicer.h>
+
+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 <mizhka@gmail.com>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/errno.h>
+#include <sys/rman.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <dev/bhnd/bhnd_debug.h>
+#include <dev/cfi/cfi_var.h>
+
+#include "chipc_spi.h"
+#include "flash_if.h"
+
+#include <sys/slicer.h>
+
+#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 <mizhka@gmail.com>
+ * 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 <mizhka@gmail.com>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/errno.h>
+#include <sys/rman.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+/*
+ * Flash slicer
+ */
+#include "chipc_slicer.h"
+
+/*
+ * SPI BUS interface
+ */
+#include <dev/spibus/spi.h>
+#include "spibus_if.h"
+#include "flash_if.h"
+
+#include <dev/bhnd/bhndvar.h>
+#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 <mizhka@gmail.com>
+ * 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 <sys/param.h>
+#include <sys/errno.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
+#include <sys/rman.h>
+#include <sys/queue.h>
+
+#include <machine/resource.h>
+#include <dev/bhnd/bhndvar.h>
+#include <dev/bhnd/bhnd_debug.h>
+
+#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 <mizhka@gmail.com>
+ * 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 <sys/queue.h>
+#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 <mizhka@gmail.com>
+ * 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 <sys/cdefs.h>
+__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 <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/bhnd/bhndvar.h>
+#include <dev/bhnd/bhnd_debug.h>
+#include "chipcbus.h"
+#include "chipcreg.h"
+
+#include <ddb/ddb.h>
+/*
+ * 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 <sys/types.h>
+#include <dev/bhnd/bhnd.h>
+#include <dev/bhnd/nvram/bhnd_nvram.h>
+#include <sys/rman.h>
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_ */

File Metadata

Mime Type
text/plain
Expires
Wed, Aug 5, 6:48 AM (2 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36008953
Default Alt Text
D6250.id15986.diff (50 KB)

Event Timeline