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