Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145387273
D6250.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
27 KB
Referenced Files
None
Subscribers
None
D6250.diff
View Options
Index: head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
===================================================================
--- head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
+++ head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
@@ -28,7 +28,6 @@
#include <sys/bus.h>
#include <dev/bhnd/bhnd.h>
-#include <dev/bhnd/nvram/bhnd_nvram.h>
INTERFACE bhnd_chipc;
@@ -37,6 +36,7 @@
#
HEADER {
+ #include <dev/bhnd/nvram/bhnd_nvram.h>
/* forward declarations */
struct chipc_caps;
struct chipc_caps *bhnd_chipc_generic_get_caps(device_t dev);
@@ -123,3 +123,12 @@
METHOD void disable_sprom {
device_t dev;
}
+
+/**
+ * Return the flash configuration register value
+ *
+ * @param dev A bhnd(4) ChipCommon device
+ */
+METHOD uint32_t get_flash_cfg {
+ device_t dev;
+}
Index: head/sys/dev/bhnd/cores/chipc/chipc.c
===================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc.c
+++ head/sys/dev/bhnd/cores/chipc/chipc.c
@@ -39,19 +39,36 @@
* and bcma(4) interconnects, providing a common interface to chipset
* identification, bus enumeration, UARTs, clocks, watchdog interrupts, GPIO,
* flash, etc.
+ *
+ * The purpose of this driver is memory resource management for ChipCommon drivers
+ * like UART, PMU, flash. ChipCommon core has several memory regions.
+ *
+ * ChipCommon driver has memory resource manager. Driver
+ * gets information about BHND core ports/regions and map them
+ * into drivers' resources.
+ *
+ * Here is overview of mapping:
+ *
+ * ------------------------------------------------------
+ * | Port.Region| Purpose |
+ * ------------------------------------------------------
+ * | 0.0 | PMU, SPI(0x40), UART(0x300) |
+ * | 1.0 | ? |
+ * | 1.1 | MMIO flash (SPI & CFI) |
+ * ------------------------------------------------------
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/bus.h>
+#include <sys/rman.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <machine/bus.h>
-#include <sys/rman.h>
#include <machine/resource.h>
#include <dev/bhnd/bhnd.h>
@@ -99,6 +116,18 @@
};
+/*
+ * Here is resource configuration hints for child devices
+ *
+ * [Flash] There are 2 flash resources:
+ * - resource ID (rid) = 0: memory-mapped flash memory
+ * - resource ID (rid) = 1: memory-mapped flash registers (i.e for SPI)
+ *
+ * [UART] Uses IRQ and memory resources:
+ * - resource ID (rid) = 0: memory-mapped registers
+ * - IRQ resource ID (rid) = 0: shared IRQ line for Tx/Rx.
+ */
+
static const struct chipc_hint {
const char *name;
int unit;
@@ -1288,6 +1317,15 @@
return (&sc->caps);
}
+static uint32_t
+chipc_get_flash_cfg(device_t dev)
+{
+ struct chipc_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (bhnd_bus_read_4(sc->core, CHIPC_FLASH_CFG));
+}
+
static device_method_t chipc_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, chipc_probe),
@@ -1330,11 +1368,13 @@
DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom_pins),
DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom_pins),
DEVMETHOD(bhnd_chipc_get_caps, chipc_get_caps),
+ DEVMETHOD(bhnd_chipc_get_flash_cfg, chipc_get_flash_cfg),
DEVMETHOD_END
};
DEFINE_CLASS_0(bhnd_chipc, chipc_driver, chipc_methods, sizeof(struct chipc_softc));
-DRIVER_MODULE(bhnd_chipc, bhnd, chipc_driver, bhnd_chipc_devclass, 0, 0);
+EARLY_DRIVER_MODULE(bhnd_chipc, bhnd, chipc_driver, bhnd_chipc_devclass, 0, 0,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
MODULE_DEPEND(bhnd_chipc, bhnd, 1, 1, 1);
MODULE_VERSION(bhnd_chipc, 1);
Index: head/sys/dev/bhnd/cores/chipc/chipc_cfi.c
===================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc_cfi.c
+++ head/sys/dev/bhnd/cores/chipc/chipc_cfi.c
@@ -0,0 +1,141 @@
+/*-
+ * 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/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/conf.h>
+
+#include <machine/bus.h>
+
+#include <dev/bhnd/bhnd_debug.h>
+#include <dev/cfi/cfi_var.h>
+
+#include "bhnd_chipc_if.h"
+#include "chipc_slicer.h"
+#include "chipcreg.h"
+#include "chipcvar.h"
+
+/*
+ * **************************** PROTOTYPES ****************************
+ */
+
+static void chipc_cfi_identify(driver_t *driver, device_t parent);
+static int chipc_cfi_probe(device_t dev);
+static int chipc_cfi_attach(device_t dev);
+
+/*
+ * **************************** IMPLEMENTATION ************************
+ */
+
+static void
+chipc_cfi_identify(driver_t *driver, device_t parent)
+{
+ struct chipc_caps *caps;
+
+ if (device_find_child(parent, cfi_driver_name, -1) != NULL)
+ return;
+
+ caps = BHND_CHIPC_GET_CAPS(parent);
+ if (caps == NULL)
+ return;
+
+ if (caps->flash_type != CHIPC_PFLASH_CFI)
+ return;
+
+ BUS_ADD_CHILD(parent, 0, cfi_driver_name, -1);
+ return;
+}
+
+static int
+chipc_cfi_probe(device_t dev)
+{
+ int error;
+ int enabled;
+ int byteswap;
+ uint32_t flash_config;
+ struct cfi_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ flash_config = BHND_CHIPC_GET_FLASH_CFG(device_get_parent(dev));
+
+ enabled = (flash_config & CHIPC_CF_EN);
+ byteswap = (flash_config & CHIPC_CF_BS);
+
+ if (enabled == 0)
+ device_disable(dev);
+
+ BHND_DEBUG_DEV(dev, "trying attach flash enabled=%d swapbytes=%d",
+ enabled, byteswap);
+
+ sc->sc_width = 0;
+ error = cfi_probe(dev);
+ if (error == 0)
+ 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_cfi);
+ return (0);
+}
+
+static device_method_t chipc_cfi_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_identify, chipc_cfi_identify),
+ 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_chipc, chipc_cfi_driver, cfi_devclass, 0, 0);
+
Index: head/sys/dev/bhnd/cores/chipc/chipc_slicer.h
===================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc_slicer.h
+++ head/sys/dev/bhnd/cores/chipc/chipc_slicer.h
@@ -0,0 +1,46 @@
+/*-
+ * 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_SLICER_H_
+#define _BHND_CORES_CHIPC_CHIPC_SLICER_H_
+
+#include <sys/slicer.h>
+
+#define TRX_MAGIC 0x30524448
+#define CFE_MAGIC 0x43464531
+#define NVRAM_MAGIC 0x48534C46
+
+int chipc_slicer_spi(device_t dev, struct flash_slice *slices,
+ int *nslices);
+int chipc_slicer_cfi(device_t dev, struct flash_slice *slices,
+ int *nslices);
+
+#endif /* _BHND_CORES_CHIPC_CHIPC_SLICER_H_ */
Index: head/sys/dev/bhnd/cores/chipc/chipc_slicer.c
===================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc_slicer.c
+++ head/sys/dev/bhnd/cores/chipc/chipc_slicer.c
@@ -0,0 +1,172 @@
+/*-
+ * 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$");
+
+/*
+ * 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)
+ */
+
+#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 "chipc_slicer.h"
+
+#include <dev/cfi/cfi_var.h>
+#include "chipc_spi.h"
+
+static int chipc_slicer_walk(device_t dev, struct resource* res,
+ struct flash_slice *slices, int *nslices);
+
+int
+chipc_slicer_cfi(device_t dev, struct flash_slice *slices, int *nslices)
+{
+ struct cfi_softc *sc;
+
+ if (strcmp("cfi", device_get_name(dev)) != 0)
+ return (0);
+
+ sc = device_get_softc(dev);
+
+ return (chipc_slicer_walk(dev, sc->sc_res, slices, nslices));
+}
+
+int
+chipc_slicer_spi(device_t dev, struct flash_slice *slices, int *nslices)
+{
+ /* flash(mx25l) <- spibus <- chipc_spi */
+ device_t spibus;
+ device_t chipc_spi;
+ struct chipc_spi_softc *sc;
+
+ BHND_DEBUG_DEV(dev, "initting SPI slicer: %s", device_get_name(dev));
+
+ if (strcmp("mx25l", device_get_name(dev)) != 0)
+ return (EINVAL);
+
+ spibus = device_get_parent(dev);
+ if (spibus == NULL) {
+ BHND_ERROR_DEV(dev, "no found ChipCommon SPI BUS device");
+ return (EINVAL);
+ }
+
+ chipc_spi = device_get_parent(spibus);
+ if (chipc_spi == NULL) {
+ BHND_ERROR_DEV(spibus, "no found ChipCommon SPI device");
+ return (EINVAL);
+ }
+
+ sc = device_get_softc(chipc_spi);
+
+ return (chipc_slicer_walk(dev, sc->sc_res, slices, nslices));
+}
+
+/*
+ * Main processing part
+ */
+static int
+chipc_slicer_walk(device_t dev, struct resource* res,
+ struct flash_slice *slices, int *nslices)
+{
+ uint32_t fw_len;
+ uint32_t fs_ofs;
+ uint32_t val;
+ uint32_t ofs_trx;
+ int flash_size;
+
+ *nslices = 0;
+
+ flash_size = rman_get_size(res);
+ ofs_trx = flash_size;
+
+ BHND_TRACE_DEV(dev, "slicer: scanning memory [%x bytes] for headers...",
+ flash_size);
+
+ /* Find FW header in flash memory with step=128Kb (0x1000) */
+ for(uint32_t ofs = 0; ofs < flash_size; ofs+= 0x1000){
+ val = bus_read_4(res, ofs);
+ switch (val) {
+ case TRX_MAGIC:
+ /* check for second TRX */
+ if (ofs_trx < ofs) {
+ BHND_TRACE_DEV(dev, "stop on 2nd TRX: %x", ofs);
+ break;
+ }
+
+ BHND_TRACE("TRX found: %x", ofs);
+ ofs_trx = ofs;
+ /* read last offset of TRX header */
+ fs_ofs = bus_read_4(res, ofs + 24);
+ BHND_TRACE("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 TRX 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_TRACE("CFE found: %x", ofs);
+ break;
+ case NVRAM_MAGIC:
+ BHND_TRACE("NVRAM found: %x", ofs);
+ break;
+ default:
+ break;
+ }
+ }
+
+ BHND_TRACE("slicer: done");
+ return (0);
+}
Index: head/sys/dev/bhnd/cores/chipc/chipc_spi.h
===================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc_spi.h
+++ head/sys/dev/bhnd/cores/chipc/chipc_spi.h
@@ -0,0 +1,94 @@
+/*-
+ * 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_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;
+
+ /* SPI registers */
+ struct resource *sc_mem_res;
+
+ /* MMIO flash */
+ struct resource *sc_res;
+};
+
+/* 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: head/sys/dev/bhnd/cores/chipc/chipc_spi.c
===================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc_spi.c
+++ head/sys/dev/bhnd/cores/chipc/chipc_spi.c
@@ -0,0 +1,280 @@
+/*-
+ * 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/kernel.h>
+#include <sys/module.h>
+#include <sys/errno.h>
+#include <sys/rman.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+
+#include <dev/bhnd/bhndvar.h>
+/*
+ * SPI BUS interface
+ */
+#include <dev/spibus/spi.h>
+
+#include "spibus_if.h"
+
+#include "chipcreg.h"
+#include "chipcvar.h"
+#include "chipc_spi.h"
+#include "bhnd_chipc_if.h"
+
+/*
+ * Flash slicer
+ */
+#include "chipc_slicer.h"
+
+/*
+ * **************************** PROTOTYPES ****************************
+ */
+
+static void chipc_spi_identify(driver_t *driver, device_t parent);
+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 void
+chipc_spi_identify(driver_t *driver, device_t parent)
+{
+ struct chipc_caps *caps;
+ device_t spidev;
+ device_t spibus;
+ device_t flash;
+ char* flash_name;
+ int err;
+
+ flash_name = NULL;
+
+ if (device_find_child(parent, "spi", -1) != NULL)
+ return;
+
+ caps = BHND_CHIPC_GET_CAPS(parent);
+ if (caps == NULL) {
+ BHND_ERROR_DEV(parent, "can't retrieve ChipCommon capabilities");
+ return;
+ }
+
+ switch (caps->flash_type) {
+ case CHIPC_SFLASH_AT:
+ flash_name = "at45d";
+ break;
+ case CHIPC_SFLASH_ST:
+ flash_name = "mx25l";
+ break;
+ default:
+ return;
+ }
+
+ spidev = BUS_ADD_CHILD(parent, 0, "spi", -1);
+ if (spidev == NULL) {
+ BHND_ERROR_DEV(parent, "can't add chipc_spi to ChipCommon");
+ return;
+ }
+
+ err = device_probe_and_attach(spidev);
+ if (err) {
+ BHND_ERROR_DEV(spidev, "failed attach chipc_spi: %d", err);
+ return;
+ }
+
+ spibus = device_find_child(spidev, "spibus", -1);
+ if (spibus == NULL) {
+ BHND_ERROR_DEV(spidev, "can't find spibus under chipc_spi");
+ return;
+ }
+
+ flash = BUS_ADD_CHILD(spibus, 0, flash_name, -1);
+ if (flash == NULL) {
+ BHND_ERROR_DEV(spibus, "can't add %s to spibus", flash_name);
+ return;
+ }
+
+ err = device_probe_and_attach(flash);
+ if (err)
+ BHND_ERROR_DEV(flash, "failed attach flash %s: %d", flash_name,
+ err);
+
+ return;
+}
+
+static int
+chipc_spi_probe(device_t dev)
+{
+ device_set_desc(dev, "ChipCommon SPI");
+ return (BUS_PROBE_DEFAULT);
+}
+
+struct resource_spec spec_mem[] = {
+ {SYS_RES_MEMORY, 0, RF_ACTIVE},
+ {SYS_RES_MEMORY, 1, RF_ACTIVE},
+ { -1, -1, 0 }
+ };
+
+static int
+chipc_spi_attach(device_t dev)
+{
+ int err;
+ struct chipc_spi_softc *sc;
+ struct resource *mem[2];
+
+ sc = device_get_softc(dev);
+ err = bus_alloc_resources(dev, spec_mem, mem);
+ if (err != 0)
+ return (ENXIO);
+
+ sc->sc_res = mem[0];
+ sc->sc_mem_res = mem[1];
+
+ flash_register_slicer(chipc_slicer_spi);
+ 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_identify, chipc_spi_identify),
+ 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_chipc, chipc_spi_driver, chipc_spi_devclass,
+ 0, 0);
Index: head/sys/mips/broadcom/uart_bus_chipc.c
===================================================================
--- head/sys/mips/broadcom/uart_bus_chipc.c
+++ head/sys/mips/broadcom/uart_bus_chipc.c
@@ -45,9 +45,12 @@
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/bhnd/cores/chipc/chipcvar.h>
+
#include "uart_if.h"
#include "bhnd_chipc_if.h"
+
static int uart_chipc_probe(device_t dev);
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
@@ -55,9 +58,18 @@
static void
uart_chipc_identify(driver_t *driver, device_t parent)
{
- struct chipc_capabilities *caps;
+ struct chipc_caps *caps;
- caps = BHND_CHIPC_GET_CAPABILITIES(parent);
+ if (device_find_child(parent, "uart", -1) != NULL)
+ return;
+
+ caps = BHND_CHIPC_GET_CAPS(parent);
+
+ if (caps == NULL) {
+ device_printf(parent, "error: can't retrieve ChipCommon "
+ "capabilities\n");
+ return;
+ }
if (caps->num_uarts == 0)
return;
@@ -74,6 +86,7 @@
struct uart_softc *sc;
struct resource *res;
int rid;
+ int err;
rid = 0;
res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
@@ -97,7 +110,11 @@
sc->sc_bas.bst = sc->sc_sysdev->bas.bst;
sc->sc_bas.bsh = sc->sc_sysdev->bas.bsh;
- bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
+ err = bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
+ if (err) {
+ device_printf(dev, "can't release resource [%d]\n", rid);
+ return (ENXIO);
+ }
/* We use internal SoC clock generator with non-standart freq MHz */
return (uart_bus_probe(dev, 0, sc->sc_sysdev->bas.rclk, 0, 0));
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Feb 20, 4:17 AM (12 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28894685
Default Alt Text
D6250.diff (27 KB)
Attached To
Mode
D6250: [BHND] ChipCommon: Resource managers, Serial & Parallel Flash support,
Attached
Detach File
Event Timeline
Log In to Comment