Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164838146
D6250.id15986.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
50 KB
Referenced Files
None
Subscribers
None
D6250.id15986.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D6250: [BHND] ChipCommon: Resource managers, Serial & Parallel Flash support,
Attached
Detach File
Event Timeline
Log In to Comment