Page MenuHomeFreeBSD

D6250.id16046.diff
No OneTemporary

D6250.id16046.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, uint8_t num_uarts);
+int chipc_init_bus(device_t dev);
+void chipc_parse_capabilities(struct chipc_capabilities* capabilities,
+ u_int32_t caps);
+
+#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"
@@ -114,6 +115,7 @@
uint32_t ccid_reg;
uint8_t chip_type;
int error;
+ uint8_t uart_cnt;
sc = device_get_softc(dev);
sc->dev = dev;
@@ -152,6 +154,8 @@
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);
+
// TODO
switch (bhnd_chipc_nvram_src(dev)) {
case BHND_NVRAM_SRC_CIS:
@@ -171,6 +175,48 @@
break;
}
+ error = chipc_init_bus(dev);
+ if (error != 0) {
+ device_printf(dev,"init_bus with: %d\n", error);
+ goto cleanup;
+ }
+
+ switch(sc->capabilities.flash_type){
+ case CHIPC_PFLASH:
+ /* Parallel flash */
+ 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:
+ /* Serial flash at45d */
+ error = chipc_init_sflash(sc->bus, "at45d"); //not tested yet
+ break;
+ case CHIPC_SFLASH_ST:
+ /* Serial flash mx25l */
+ 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;
+ }
+
+ uart_cnt = sc->capabilities.num_uarts;
+ if (uart_cnt > 0 && (error = chipc_init_uarts(sc, uart_cnt)) > 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_generic_attach failed: %d\n", error);
+ goto cleanup;
+ }
+
return (0);
cleanup:
@@ -297,7 +343,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,88 @@
+/*-
+ * 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)
+{
+ int error;
+ struct cfi_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_width = 2;
+ error = cfi_probe(dev);
+ if (!error)
+ device_set_desc(dev, "ChipCommon CFI");
+ return (error);
+}
+
+static int
+chipc_cfi_attach(device_t dev)
+{
+ int error;
+ 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,38 @@
+/*-
+ * 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.
+ */
+
+#ifndef _BHND_CORES_CHIPC_CHIPC_SLICER_H_
+#define _BHND_CORES_CHIPC_CHIPC_SLICER_H_
+
+#include <sys/slicer.h>
+
+int chipc_slicer_flash(device_t dev, struct flash_slice *slices,
+ int *nslices);
+
+#endif /* _BHND_CORES_CHIPC_CHIPC_SLICER_H_ */
Index: sys/dev/bhnd/cores/chipc/chipc_slicer.c
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/chipc/chipc_slicer.c
@@ -0,0 +1,159 @@
+/*-
+ * 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 <sys/slicer.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"
+
+#define TRX_MAGIC 0x30524448
+#define CFE_MAGIC 0x43464531
+#define NVRAM_MAGIC 0x48534C46
+
+
+static 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;
+
+ devclazz = device_get_name(dev);
+ BHND_INFO_DEV(dev, "start flash slicer for class %s", devclazz);
+ if (strcmp(devclazz, "mx25l") == 0) { //SPI
+ /* flash(mx25l) <- spibus <- chipc_spi */
+ device_t spibus;
+ device_t chipc_spi;
+ struct chipc_spi_softc *sc;
+
+ spibus = device_get_parent(dev);
+ chipc_spi = device_get_parent(spibus);
+ 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, "ChipCommon Flash slicer: "
+ "unsupported flash device class: %s", devclazz);
+ return (0);
+ }
+
+ /*
+ * Main processing part
+ */
+ return (chipc_slicer_walk(res,flash_size,slices,nslices));
+}
+
+static int
+chipc_slicer_walk(struct resource* res, int flash_size,
+ struct flash_slice *slices, int *nslices)
+{
+ uint32_t fw_len;
+ uint32_t fs_ofs;
+ uint32_t val;
+
+ *nslices = 0;
+ BHND_TRACE("slicer: scanning memory for headers...");
+
+ /*
+ * Find FW header in flash memory with step = 0x1000
+ * (or block size (128Kb)?
+ */
+ for(uint32_t ofs = 0; ofs < flash_size; ofs+= 0x1000){
+ val = bus_read_4(res, ofs);
+ switch (val) {
+ case TRX_MAGIC:
+ BHND_DEBUG("TRX found: %x", ofs);
+ /* read last offset of TRX header */
+ fs_ofs = bus_read_4(res, ofs + 24);
+ BHND_DEBUG("FS offset: %x", fs_ofs);
+
+ /*
+ * GEOM IO will panic if offset is not aligned
+ * on sector size, i.e. 512 bytes
+ */
+ if (fs_ofs % 0x200 != 0) {
+ BHND_WARN("WARNING! filesystem offset should be"
+ " aligned on sector size (%d bytes)", 0x200);
+ BHND_WARN("ignoring firmware image");
+ break;
+ }
+
+ slices[*nslices].base = ofs + fs_ofs;
+ //XXX: fully sized? any other partition?
+ fw_len = bus_read_4(res, ofs + 4);
+ slices[*nslices].size = fw_len - fs_ofs;
+ slices[*nslices].label = "rootfs";
+ *nslices += 1;
+ break;
+ case CFE_MAGIC:
+ BHND_DEBUG("CFE found: %x", ofs);
+ break;
+ case NVRAM_MAGIC:
+ BHND_DEBUG("NVRAM found: %x", ofs);
+ break;
+ default:
+ break;
+ }
+ }
+
+ BHND_TRACE("slicer: done");
+ return (0);
+}
Index: sys/dev/bhnd/cores/chipc/chipc_spi.h
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/chipc/chipc_spi.h
@@ -0,0 +1,100 @@
+/*-
+ * 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.
+ */
+
+/*
+ * $FreeBSD$
+ */
+
+#ifndef _BHND_CORES_CHIPC_CHIPC_SPI_H_
+#define _BHND_CORES_CHIPC_CHIPC_SPI_H_
+
+#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))
+
+#endif /* _BHND_CORES_CHIPC_CHIPC_SPI_H_ */
Index: sys/dev/bhnd/cores/chipc/chipc_spi.c
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/chipc/chipc_spi.c
@@ -0,0 +1,214 @@
+/*-
+ * 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/bhndvar.h>
+/*
+ * SPI BUS interface
+ */
+#include <dev/spibus/spi.h>
+
+#include "spibus_if.h"
+#include "flash_if.h"
+
+#include "chipcreg.h"
+#include "chipcvar.h"
+#include "chipc_spi.h"
+
+/*
+ * Flash slicer
+ */
+#include "chipc_slicer.h"
+
+/*
+ * **************************** 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 ************************
+ */
+
+static int
+chipc_spi_probe(device_t dev)
+{
+ device_set_desc(dev, "ChipCommon SPI");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+chipc_spi_attach(device_t dev)
+{
+ struct chipc_spi_softc* sc;
+
+ 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;
+
+ for (i = CHIPC_SPI_MAXTRIES; i > 0; 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;
+
+ 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;
+ uint8_t *buf_in;
+ uint8_t *buf_out;
+ int i;
+
+ sc = device_get_softc(dev);
+ 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,271 @@
+/*-
+ * 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/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"
+
+static void chipc_print_capabilities(struct chipc_capabilities* capabilities);
+
+int
+chipc_init_bus(device_t dev)
+{
+ int err;
+ int ret;
+ struct chipcbus_ivar *ivar;
+ struct chipcbus_reg *reg;
+ struct chipc_softc *sc;
+ bhnd_addr_t rg_start;
+ bhnd_size_t rg_size;
+ device_t bus;
+
+ bus = device_add_child(dev,"bhnd_chipcbus",-1);
+ if (bus == NULL) {
+ BHND_ERROR_DEV(dev, "error occurred during adding "
+ "ChipCommon bus");
+ return (ENXIO);
+ }
+
+ 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 = device_get_softc(dev);
+ sc->bus = bus;
+
+ SLIST_INIT(&ivar->mems);
+ SLIST_INIT(&ivar->irqs);
+
+ /* Iterate over device ports & regions and fill instance variable */
+ 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 == 0) {
+ reg = malloc(sizeof(struct chipcbus_reg),
+ M_BHND, M_NOWAIT);
+ if (reg == NULL) {
+ return (ENOMEM);
+ }
+ reg->start = rg_start;
+ reg->end = rg_start + rg_size - 1;
+ reg->port = i;
+ reg->reg = j;
+ SLIST_INSERT_HEAD(&ivar->mems, reg, entries);
+ }
+ }
+ }
+
+ err = device_probe_and_attach(bus);
+ if (err)
+ BHND_ERROR_DEV(bus, "ChipCommon bus probing and attaching "
+ " 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;
+ int enabled;
+ int byteswap;
+ int err;
+ device_t flashdev;
+
+ width = (flash_config & CHIPC_CF_DS) ? 2 : 1;
+ enabled = (flash_config & CHIPC_CF_EN);
+ byteswap = (flash_config & CHIPC_CF_BS);
+
+ BHND_DEBUG_DEV(dev, "trying attach flash "
+ "width=%d enabled=%d swapbytes=%d",
+ width, enabled, byteswap);
+ flashdev = device_add_child(dev, "cfi", -1);
+ if (flashdev == NULL) {
+ BHND_ERROR_DEV(dev, "can't add Parallel Flash to "
+ "ChipCommon bus");
+ return (ENXIO);
+ }
+
+ err = device_probe_and_attach(flashdev);
+ if (err)
+ BHND_ERROR_DEV(dev, "failed attach parallel flash: %d", err);
+
+ return (err);
+}
+
+int
+chipc_init_sflash(device_t dev, char* flash_name)
+{
+ device_t chipc_spi;
+ device_t *children;
+ device_t flash;
+ int cnt_children;
+ int err;
+
+ chipc_spi = device_add_child(dev, "spi", -1);
+ if (chipc_spi == NULL) {
+ BHND_ERROR_DEV(dev, "can't add chipc_spi to ChipCommon");
+ return (ENXIO);
+ }
+
+ err = device_probe_and_attach(chipc_spi);
+ if (err) {
+ BHND_ERROR_DEV(dev, "failed attach chipc_spi: %d", err);
+ return (err);
+ }
+
+ 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 == 0) {
+ BHND_ERROR_DEV(chipc_spi, "no found children");
+ return (ENXIO);
+ }
+
+ flash = BUS_ADD_CHILD(children[0], 0, flash_name, -1);
+ if (children)
+ free(children, M_TEMP);
+
+ if (flash == NULL) {
+ BHND_ERROR_DEV(chipc_spi, "can't add %s to spibus", flash_name);
+ return (ENXIO);
+ }
+
+ 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, uint8_t num_uarts)
+{
+ device_t child;
+ int err;
+
+ if (num_uarts < 0)
+ return (EINVAL);
+ else if (num_uarts == 0)
+ return (0);
+
+ child = device_add_child(sc->bus, "uart", 0);
+ if (child == NULL) {
+ BHND_ERROR_DEV(sc->bus, "can'd add UART to bus");
+ return (ENXIO);
+ }
+
+ err = device_probe_and_attach(child);
+ if (err)
+ BHND_ERROR_DEV(child, "error occurred on probe_and_attach: %d",
+ err);
+
+ return (err);
+}
+
+static void
+chipc_print_capabilities(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);
+}
+
+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);
+
+ if(bootverbose)
+ chipc_print_capabilities(capabilities);
+}
Index: sys/dev/bhnd/cores/chipc/chipcbus.h
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/chipc/chipcbus.h
@@ -0,0 +1,65 @@
+/*-
+ * 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.
+ */
+
+#ifndef _BHND_CORES_CHIPC_CHIPCBUS_H_
+#define _BHND_CORES_CHIPC_CHIPCBUS_H_
+
+#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;
+ SLIST_HEAD(irq_list, chipcbus_reg) irqs;
+};
+
+struct chipcbus_devinfo {
+ struct resource_list resources;
+};
+
+#endif /* _BHND_CORES_CHIPC_CHIPCBUS_H_ */
Index: sys/dev/bhnd/cores/chipc/chipcbus.c
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/chipc/chipcbus.c
@@ -0,0 +1,431 @@
+/*-
+ * 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 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 drivers this bus
+ * is introduced. The bus has 2 resource managers. Driver gets information
+ * about BHND ports/regions and map it into resources for drivers.
+ *
+ * Here is overview of mapping:
+ *
+ * ------------------------------------------------------
+ * | Port.Region| Purpose |
+ * ------------------------------------------------------
+ * | 0.0 | main registers: SPI(0x40), UART(0x300)|
+ * | 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"
+
+static struct chipcbus_reg* chipcbus_get_region(device_t bus,
+ int port,
+ int regid);
+static struct resource_list* chipcbus_get_resource_list(device_t dev,
+ device_t child);
+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);
+static int chipcbus_probe(device_t dev);
+static int chipcbus_attach(device_t dev);
+static int chipcbus_detach(device_t dev);
+static void chipcbus_probe_nomatch(device_t dev, device_t child);
+static void chipcbus_set_resources(device_t bus, device_t dev,
+ struct resource_list* rl);
+static int chipcbus_release_resource(device_t bus, device_t child,
+ int type, int rid, struct resource *r);
+void chipcbus_cleanup(device_t dev);
+
+/*
+ * 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 (i.e 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},
+ {NULL, 0, 0, 0, 0, 0, 0}
+};
+
+/*
+ * We're creating resource manager for all MIPS IRQs,
+ * but it's MIPS-ifed code and it's better to get IRQ number from core info.
+ * TODO: fetch IRQ number from core info to demipsify code
+ */
+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;
+ struct chipcbus_reg *reg;
+
+ ivar = device_get_ivars(bus);
+ 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)
+{
+ const char *devname;
+ struct chipcbus_spec *spec;
+ struct chipcbus_reg *reg;
+
+ int rid;
+ int type;
+ rman_res_t offset;
+ rman_res_t start;
+ rman_res_t end;
+ rman_res_t count;
+
+ BHND_DEBUG_DEV(dev, "first time to init resources...");
+
+ devname = device_get_name(dev);
+ spec = mem_specs;
+ for (;spec->name != NULL; spec++) {
+ if (strcmp(spec->name, devname) != 0)
+ continue;
+
+ /* name is matched */
+ reg = NULL;
+ type = spec->type;
+ rid = spec->rid;
+
+ switch (type){
+ case SYS_RES_MEMORY:
+ reg = chipcbus_get_region(bus, spec->port, spec->reg);
+ break;
+ case SYS_RES_IRQ:
+ reg = &static_irq;
+ break;
+ default:
+ break;
+ }
+
+ if (reg == NULL) {
+ BHND_WARN_DEV(dev, "region is not found "
+ "[type %d, rid %d, port.region %d.%d]",
+ spec->type, spec->rid, spec->port, spec->reg);
+ continue;
+ }
+
+ offset = reg->start;
+ start = MIN(offset + spec->start, reg->end);
+ end = MIN(offset + spec->start +
+ MIN(spec->size, reg->end - reg->start + 1) - 1,
+ reg->end);
+ count = end - start + 1;
+ resource_list_add(rl,type, rid, start, end, count);
+ }
+}
+
+void
+chipcbus_cleanup(device_t dev)
+{
+ struct chipcbus_softc *sc;
+ sc = device_get_softc(dev);
+ rman_fini(&sc->chipc_irq);
+ rman_fini(&sc->chipc_mem);
+}
+
+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;
+ struct chipcbus_ivar *ivar;
+ struct chipcbus_reg *reg;
+
+ BHND_DEBUG_DEV(dev, "start attaching");
+
+ sc = device_get_softc(dev);
+ 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 rman_init of "
+ "IRQ rman: %d", err);
+ goto error;
+ }
+ 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: %d", err);
+ goto error;
+ }
+
+ ivar = device_get_ivars(dev);
+ if (ivar == NULL) {
+ BHND_INFO_DEV(dev, "no instance variables for chipcommon bus");
+ goto out;
+ }
+
+ 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 : err = %d"
+ ,reg->start, reg->end, err);
+ goto error;
+ }
+ }
+/*
+ * We're creating resource manager for all MIPS IRQs, but it's MIPS-ifed code
+ * and it's better to get IRQ number from core info.
+ * TODO: fetch IRQ number from core info to demipsify code
+ */
+ 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 : err = %d"
+ , 0, NUM_IRQS, err);
+ goto error;
+ }
+
+out:
+ 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;
+
+ 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 == NULL) {
+ 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;
+ struct rman *rm;
+ struct resource *r;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+
+ 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) {
+ rl = chipcbus_get_resource_list(bus, child);
+ if (rl == NULL) {
+ BHND_ERROR_DEV(bus, "there is no resource list for: %s",
+ device_get_nameunit(child));
+ return (NULL);
+ }
+ 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;
+ }
+
+ sc = device_get_softc(bus);
+ 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);
+ 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)
+{
+ int error;
+
+ if (rman_get_flags(r) & RF_ACTIVE) {
+ 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),
+
+ /*
+ * TODO: Add
+ * - bus_print_child,
+ * - bus_{get,set,delete}_resource,
+ * - bus_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 {
+ uint8_t num_uarts;
+ uint8_t is_bigend;
+ uint8_t uart_clock;
+ uint8_t uart_gpio;
+ uint8_t external_buses;
+ uint8_t flash_type;
+ uint8_t pll_type;
+ uint8_t power_control;
+ uint8_t otp_size;
+ uint8_t jtag_master;
+ uint8_t boot_rom;
+ uint8_t is_64bit;
+ uint8_t pmu;
+ uint8_t eci;
+ uint8_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, Nov 26, 6:09 PM (4 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26221681
Default Alt Text
D6250.id16046.diff (52 KB)

Event Timeline