diff --git a/sys/dev/bhnd/cores/chipc/chipc_slicer.c b/sys/dev/bhnd/cores/chipc/chipc_slicer.c index 45cac4d3794c..4c6969d7ff2f 100644 --- a/sys/dev/bhnd/cores/chipc/chipc_slicer.c +++ b/sys/dev/bhnd/cores/chipc/chipc_slicer.c @@ -1,202 +1,206 @@ /*- * Copyright (c) 2016 Michael Zhilin * 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 __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 #include #include #include #include #include #include #include #include #include #include "chipc_slicer.h" #include #include "chipc_spi.h" static int chipc_slicer_walk(device_t dev, struct resource *res, struct flash_slice *slices, int *nslices); void chipc_register_slicer(chipc_flash flash_type) { switch (flash_type) { case CHIPC_SFLASH_AT: case CHIPC_SFLASH_ST: - flash_register_slicer(chipc_slicer_spi); + flash_register_slicer(chipc_slicer_spi, FLASH_SLICES_TYPE_SPI, + TRUE); break; case CHIPC_PFLASH_CFI: - flash_register_slicer(chipc_slicer_cfi); + flash_register_slicer(chipc_slicer_cfi, FLASH_SLICES_TYPE_CFI, + TRUE); break; default: /* Unsupported */ break; } } int -chipc_slicer_cfi(device_t dev, struct flash_slice *slices, int *nslices) +chipc_slicer_cfi(device_t dev, const char *provider __unused, + struct flash_slice *slices, int *nslices) { struct cfi_softc *sc; device_t parent; /* must be CFI flash */ if (device_get_devclass(dev) != devclass_find("cfi")) return (ENXIO); /* must be attached to chipc */ if ((parent = device_get_parent(dev)) == NULL) { BHND_ERROR_DEV(dev, "no found ChipCommon device"); return (ENXIO); } if (device_get_devclass(parent) != devclass_find("bhnd_chipc")) { BHND_ERROR_DEV(dev, "no found ChipCommon device"); return (ENXIO); } 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) +chipc_slicer_spi(device_t dev, const char *provider __unused, + struct flash_slice *slices, int *nslices) { struct chipc_spi_softc *sc; device_t chipc, spi, spibus; BHND_DEBUG_DEV(dev, "initting SPI slicer: %s", device_get_name(dev)); /* must be SPI-attached flash */ spibus = device_get_parent(dev); if (spibus == NULL) { BHND_ERROR_DEV(dev, "no found ChipCommon SPI BUS device"); return (ENXIO); } spi = device_get_parent(spibus); if (spi == NULL) { BHND_ERROR_DEV(dev, "no found ChipCommon SPI device"); return (ENXIO); } chipc = device_get_parent(spi); if (device_get_devclass(chipc) != devclass_find("bhnd_chipc")) { BHND_ERROR_DEV(dev, "no found ChipCommon device"); return (ENXIO); } sc = device_get_softc(spi); return (chipc_slicer_walk(dev, sc->sc_flash_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); } diff --git a/sys/dev/bhnd/cores/chipc/chipc_slicer.h b/sys/dev/bhnd/cores/chipc/chipc_slicer.h index 4c35caa1af25..6f296262891a 100644 --- a/sys/dev/bhnd/cores/chipc/chipc_slicer.h +++ b/sys/dev/bhnd/cores/chipc/chipc_slicer.h @@ -1,49 +1,49 @@ /*- * Copyright (c) 2016 Michael Zhilin * 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 #include "chipcvar.h" #define TRX_MAGIC 0x30524448 #define CFE_MAGIC 0x43464531 #define NVRAM_MAGIC 0x48534C46 void chipc_register_slicer(chipc_flash flash_type); -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); +int chipc_slicer_spi(device_t dev, const char *provider, + struct flash_slice *slices, int *nslices); +int chipc_slicer_cfi(device_t dev, const char *provider, + struct flash_slice *slices, int *nslices); #endif /* _BHND_CORES_CHIPC_CHIPC_SLICER_H_ */ diff --git a/sys/dev/fdt/fdt_slicer.c b/sys/dev/fdt/fdt_slicer.c index 7e385c15c5d3..2765f53aa1ba 100644 --- a/sys/dev/fdt/fdt_slicer.c +++ b/sys/dev/fdt/fdt_slicer.c @@ -1,112 +1,138 @@ /*- * Copyright (c) 2012 Semihalf. * 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. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include +#include +#include #ifdef DEBUG #define debugf(fmt, args...) do { printf("%s(): ", __func__); \ printf(fmt,##args); } while (0) #else #define debugf(fmt, args...) #endif -int -fdt_flash_fill_slices(device_t dev, struct flash_slice *slices, int *slices_num) +static int fdt_flash_fill_slices(device_t dev, const char *provider, + struct flash_slice *slices, int *slices_num); +static void fdt_slicer_init(void); + +static int +fdt_flash_fill_slices(device_t dev, const char *provider __unused, + struct flash_slice *slices, int *slices_num) { char *slice_name; phandle_t dt_node, dt_child; u_long base, size; int i; ssize_t name_len; /* * We assume the caller provides buffer for FLASH_SLICES_MAX_NUM * flash_slice structures. */ if (slices == NULL) { *slices_num = 0; return (ENOMEM); } dt_node = ofw_bus_get_node(dev); for (dt_child = OF_child(dt_node), i = 0; dt_child != 0; dt_child = OF_peer(dt_child)) { if (i == FLASH_SLICES_MAX_NUM) { debugf("not enough buffer for slice i=%d\n", i); break; } /* * Retrieve start and size of the slice. */ if (fdt_regsize(dt_child, &base, &size) != 0) { debugf("error during processing reg property, i=%d\n", i); continue; } if (size == 0) { debugf("slice i=%d with no size\n", i); continue; } /* * Retrieve label. */ name_len = OF_getprop_alloc(dt_child, "label", sizeof(char), (void **)&slice_name); if (name_len <= 0) { /* Use node name if no label defined */ - name_len = OF_getprop_alloc(dt_child, "name", sizeof(char), - (void **)&slice_name); + name_len = OF_getprop_alloc(dt_child, "name", + sizeof(char), (void **)&slice_name); if (name_len <= 0) { debugf("slice i=%d with no name\n", i); slice_name = NULL; } } /* * Fill slice entry data. */ slices[i].base = base; slices[i].size = size; slices[i].label = slice_name; i++; } *slices_num = i; return (0); } + +static void +fdt_slicer_init(void) +{ + + flash_register_slicer(fdt_flash_fill_slices, FLASH_SLICES_TYPE_NAND, + FALSE); + flash_register_slicer(fdt_flash_fill_slices, FLASH_SLICES_TYPE_CFI, + FALSE); + flash_register_slicer(fdt_flash_fill_slices, FLASH_SLICES_TYPE_SPI, + FALSE); +} + +/* + * Must be initialized after GEOM classes (SI_SUB_DRIVERS/SI_ORDER_FIRST), + * i. e. after g_init() is called, due to the use of the GEOM topology_lock + * in flash_register_slicer(). However, must be before SI_SUB_CONFIGURE. + */ +SYSINIT(fdt_slicer_rootconf, SI_SUB_DRIVERS, SI_ORDER_SECOND, fdt_slicer_init, + NULL); diff --git a/sys/dev/nand/nfc_rb.c b/sys/dev/nand/nfc_rb.c index 38b28445add1..1102b3abb9c4 100644 --- a/sys/dev/nand/nfc_rb.c +++ b/sys/dev/nand/nfc_rb.c @@ -1,282 +1,321 @@ /*- * Copyright (C) 2015 Justin Hibbits * 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. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. */ /* RouterBoard 600/800 NAND controller driver. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include +#include + +#include #include #include #include #include #include #include #include "nfc_if.h" #include "gpio_if.h" #define RB_NAND_DATA (0x00) struct rb_nand_softc { struct nand_softc nand_dev; struct resource *sc_mem; int rid; device_t sc_gpio; uint32_t sc_rdy_pin; uint32_t sc_nce_pin; uint32_t sc_cle_pin; uint32_t sc_ale_pin; }; static int rb_nand_attach(device_t); static int rb_nand_probe(device_t); static int rb_nand_send_command(device_t, uint8_t); static int rb_nand_send_address(device_t, uint8_t); static uint8_t rb_nand_read_byte(device_t); static void rb_nand_read_buf(device_t, void *, uint32_t); static void rb_nand_write_buf(device_t, void *, uint32_t); static int rb_nand_select_cs(device_t, uint8_t); static int rb_nand_read_rnb(device_t); static device_method_t rb_nand_methods[] = { DEVMETHOD(device_probe, rb_nand_probe), DEVMETHOD(device_attach, rb_nand_attach), DEVMETHOD(nfc_send_command, rb_nand_send_command), DEVMETHOD(nfc_send_address, rb_nand_send_address), DEVMETHOD(nfc_read_byte, rb_nand_read_byte), DEVMETHOD(nfc_read_buf, rb_nand_read_buf), DEVMETHOD(nfc_write_buf, rb_nand_write_buf), DEVMETHOD(nfc_select_cs, rb_nand_select_cs), DEVMETHOD(nfc_read_rnb, rb_nand_read_rnb), { 0, 0 }, }; static driver_t rb_nand_driver = { "nand", rb_nand_methods, sizeof(struct rb_nand_softc), }; static devclass_t rb_nand_devclass; DRIVER_MODULE(rb_nand, ofwbus, rb_nand_driver, rb_nand_devclass, 0, 0); #if 0 static const struct nand_ecc_data rb_ecc = { .eccsize = 6, .eccmode = NAND_ECC_SOFT, .eccbytes = 6, .eccpositions = { 8, 9, 10, 13, 14, 15 }, }; #endif +/* Slicer operates on the NAND controller, so we have to find the chip. */ +static int +rb_nand_slicer(device_t dev, const char *provider __unused, + struct flash_slice *slices, int *nslices) +{ + struct nand_chip *chip; + device_t *children; + int n; + + if (device_get_children(dev, &children, &n) != 0) { + panic("Slicer called on controller with no child!"); + } + dev = children[0]; + free(children, M_TEMP); + + if (device_get_children(dev, &children, &n) != 0) { + panic("Slicer called on controller with nandbus but no child!"); + } + dev = children[0]; + free(children, M_TEMP); + + chip = device_get_softc(dev); + *nslices = 2; + slices[0].base = 0; + slices[0].size = 4 * 1024 * 1024; + slices[0].label = "boot"; + + slices[1].base = 4 * 1024 * 1024; + slices[1].size = chip->ndisk->d_mediasize - slices[0].size; + slices[1].label = "rootfs"; + + return (0); +} + static int rb_nand_probe(device_t dev) { const char *device_type; device_type = ofw_bus_get_type(dev); if (!device_type || strcmp(device_type, "rb,nand")) return (ENXIO); device_set_desc(dev, "RouterBoard 333/600/800 NAND controller"); return (BUS_PROBE_DEFAULT); } static int rb_nand_attach(device_t dev) { struct rb_nand_softc *sc; phandle_t node; uint32_t ale[2],cle[2],nce[2],rdy[2]; u_long size,start; int err; sc = device_get_softc(dev); node = ofw_bus_get_node(dev); if (OF_getprop(node, "ale", ale, sizeof(ale)) <= 0) { return (ENXIO); } if (OF_getprop(node, "cle", cle, sizeof(cle)) <= 0) { return (ENXIO); } if (OF_getprop(node, "nce", nce, sizeof(nce)) <= 0) { return (ENXIO); } if (OF_getprop(node, "rdy", rdy, sizeof(rdy)) <= 0) { return (ENXIO); } if (ale[0] != cle[0] || ale[0] != nce[0] || ale[0] != rdy[0]) { device_printf(dev, "GPIO handles for signals must match.\n"); return (ENXIO); } sc->sc_ale_pin = ale[1]; sc->sc_cle_pin = cle[1]; sc->sc_nce_pin = nce[1]; sc->sc_rdy_pin = rdy[1]; sc->sc_gpio = OF_device_from_xref(ale[0]); if (sc->sc_gpio == NULL) { device_printf(dev, "No GPIO resource found!\n"); return (ENXIO); } sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, RF_ACTIVE); if (sc->sc_mem == NULL) { device_printf(dev, "could not allocate resources!\n"); return (ENXIO); } start = rman_get_start(sc->sc_mem); size = rman_get_size(sc->sc_mem); if (law_enable(OCP85XX_TGTIF_LBC, start, size) != 0) { bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->sc_mem); device_printf(dev, "could not allocate local address window.\n"); return (ENXIO); } + flash_register_slicer(rb_nand_slicer, FLASH_SLICES_TYPE_NAND, TRUE); + nand_init(&sc->nand_dev, dev, NAND_ECC_SOFT, 0, 0, NULL, NULL); err = nandbus_create(dev); return (err); } static int rb_nand_send_command(device_t dev, uint8_t command) { struct rb_nand_softc *sc; nand_debug(NDBG_DRV,"rb_nand: send command %x", command); sc = device_get_softc(dev); GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 1); GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0); GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0); bus_write_1(sc->sc_mem, RB_NAND_DATA, command); GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0); return (0); } static int rb_nand_send_address(device_t dev, uint8_t addr) { struct rb_nand_softc *sc; nand_debug(NDBG_DRV,"rb_nand: send address %x", addr); sc = device_get_softc(dev); GPIO_PIN_SET(sc->sc_gpio, sc->sc_cle_pin, 0); GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 1); GPIO_PIN_SET(sc->sc_gpio, sc->sc_nce_pin, 0); bus_write_1(sc->sc_mem, RB_NAND_DATA, addr); GPIO_PIN_SET(sc->sc_gpio, sc->sc_ale_pin, 0); return (0); } static uint8_t rb_nand_read_byte(device_t dev) { struct rb_nand_softc *sc; uint8_t data; sc = device_get_softc(dev); data = bus_read_1(sc->sc_mem, RB_NAND_DATA); nand_debug(NDBG_DRV,"rb_nand: read %x", data); return (data); } static void rb_nand_read_buf(device_t dev, void* buf, uint32_t len) { struct rb_nand_softc *sc; sc = device_get_softc(dev); bus_read_region_1(sc->sc_mem, RB_NAND_DATA, buf, len); } static void rb_nand_write_buf(device_t dev, void* buf, uint32_t len) { struct rb_nand_softc *sc; int i; uint8_t *b = (uint8_t*)buf; sc = device_get_softc(dev); for (i = 0; i < len; i++) { #ifdef NAND_DEBUG if (!(i % 16)) printf("%s", i == 0 ? "rb_nand:\n" : "\n"); printf(" %x", b[i]); if (i == len - 1) printf("\n"); #endif bus_write_1(sc->sc_mem, RB_NAND_DATA, b[i]); } } static int rb_nand_select_cs(device_t dev, uint8_t cs) { if (cs > 0) return (ENODEV); return (0); } static int rb_nand_read_rnb(device_t dev) { struct rb_nand_softc *sc; uint32_t rdy_bit; sc = device_get_softc(dev); GPIO_PIN_GET(sc->sc_gpio, sc->sc_rdy_pin, &rdy_bit); return (rdy_bit); /* ready */ } diff --git a/sys/geom/geom_flashmap.c b/sys/geom/geom_flashmap.c index 76dd1fadd57b..b7737b5c9a14 100644 --- a/sys/geom/geom_flashmap.c +++ b/sys/geom/geom_flashmap.c @@ -1,272 +1,247 @@ /*- * Copyright (c) 2012 Semihalf * Copyright (c) 2009 Jakub Klama * 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. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include -#include #include #include -#include #include -#include -#include #include #include #include #include #include #include + #include -#define FLASHMAP_CLASS_NAME "Flashmap" +#define FLASHMAP_CLASS_NAME "Flashmap" struct g_flashmap_slice { off_t sl_start; off_t sl_end; const char *sl_name; STAILQ_ENTRY(g_flashmap_slice) sl_link; }; STAILQ_HEAD(g_flashmap_head, g_flashmap_slice); -static void g_flashmap_print(struct g_flashmap_slice *); -static int g_flashmap_modify(struct g_geom *, const char *, - int, struct g_flashmap_head *); -static int g_flashmap_start(struct bio *); -static int g_flashmap_ioctl(struct g_provider *, u_long, void *, - int, struct thread *); -static void g_flashmap_dumpconf(struct sbuf *, const char *, - struct g_geom *, struct g_consumer *, struct g_provider *); -static struct g_geom *g_flashmap_taste(struct g_class *, - struct g_provider *, int); -static void g_flashmap_config(struct gctl_req *, struct g_class *, - const char *); -static int g_flashmap_load(device_t, struct g_flashmap_head *); -static int (*flash_fill_slices)(device_t, struct flash_slice *, int *) = - fdt_flash_fill_slices; +static struct { + const char *type; + flash_slicer_t slicer; +} g_flashmap_slicers[] = { + { "NAND::device", NULL }, + { "CFI::device", NULL }, + { "SPI::device", NULL }, + { "MMC::device", NULL } +}; + +static g_ioctl_t g_flashmap_ioctl; +static g_taste_t g_flashmap_taste; + +static int g_flashmap_load(device_t dev, struct g_provider *pp, + flash_slicer_t slicer, struct g_flashmap_head *head); +static int g_flashmap_modify(struct g_geom *gp, const char *devname, + int secsize, struct g_flashmap_head *slices); +static void g_flashmap_print(struct g_flashmap_slice *slice); MALLOC_DECLARE(M_FLASHMAP); MALLOC_DEFINE(M_FLASHMAP, "geom_flashmap", "GEOM flash memory slicer class"); static void g_flashmap_print(struct g_flashmap_slice *slice) { printf("%08jx-%08jx: %s (%juKB)\n", (uintmax_t)slice->sl_start, (uintmax_t)slice->sl_end, slice->sl_name, (uintmax_t)(slice->sl_end - slice->sl_start) / 1024); } static int g_flashmap_modify(struct g_geom *gp, const char *devname, int secsize, struct g_flashmap_head *slices) { struct g_flashmap_slice *slice; int i, error; g_topology_assert(); i = 0; STAILQ_FOREACH(slice, slices, sl_link) { if (bootverbose) { printf("%s: slice ", devname); g_flashmap_print(slice); } error = g_slice_config(gp, i++, G_SLICE_CONFIG_CHECK, slice->sl_start, slice->sl_end - slice->sl_start + 1, - secsize, "%ss.%s", gp->name, slice->sl_name); + secsize, FLASH_SLICES_FMT, gp->name, slice->sl_name); if (error) return (error); } i = 0; STAILQ_FOREACH(slice, slices, sl_link) { error = g_slice_config(gp, i++, G_SLICE_CONFIG_SET, slice->sl_start, slice->sl_end - slice->sl_start + 1, secsize, "%ss.%s", gp->name, slice->sl_name); if (error) return (error); } return (0); } -static int -g_flashmap_start(struct bio *bp) -{ - - return (0); -} - -static void -g_flashmap_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, - struct g_consumer *cp __unused, struct g_provider *pp) -{ - struct g_slicer *gsp; - - gsp = gp->softc; - g_slice_dumpconf(sb, indent, gp, cp, pp); -} - static int g_flashmap_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td) { struct g_consumer *cp; struct g_geom *gp; if (cmd != NAND_IO_GET_CHIP_PARAM) return (ENOIOCTL); cp = LIST_FIRST(&pp->geom->consumer); if (cp == NULL) return (ENOIOCTL); gp = cp->provider->geom; if (gp->ioctl == NULL) return (ENOIOCTL); return (gp->ioctl(cp->provider, cmd, data, fflag, td)); } - static struct g_geom * g_flashmap_taste(struct g_class *mp, struct g_provider *pp, int flags) { - struct g_geom *gp = NULL; + struct g_geom *gp; struct g_consumer *cp; struct g_flashmap_head head; struct g_flashmap_slice *slice, *slice_temp; + flash_slicer_t slicer; device_t dev; - int nslices, size; + int i, size; g_trace(G_T_TOPOLOGY, "flashmap_taste(%s,%s)", mp->name, pp->name); g_topology_assert(); if (flags == G_TF_NORMAL && strcmp(pp->geom->class->name, G_DISK_CLASS_NAME) != 0) return (NULL); - gp = g_slice_new(mp, FLASH_SLICES_MAX_NUM, pp, &cp, NULL, 0, - g_flashmap_start); + gp = g_slice_new(mp, FLASH_SLICES_MAX_NUM, pp, &cp, NULL, 0, NULL); if (gp == NULL) return (NULL); STAILQ_INIT(&head); do { - size = sizeof(device_t); - if (g_io_getattr("NAND::device", cp, &size, &dev)) { + slicer = NULL; + for (i = 0; i < nitems(g_flashmap_slicers); i++) { size = sizeof(device_t); - if (g_io_getattr("CFI::device", cp, &size, &dev)) { - size = sizeof(device_t); - if (g_io_getattr("SPI::device", cp, &size, - &dev)) - break; + if (g_io_getattr(g_flashmap_slicers[i].type, cp, + &size, &dev) == 0) { + slicer = g_flashmap_slicers[i].slicer; + break; } } + if (slicer == NULL) + break; - nslices = g_flashmap_load(dev, &head); - if (nslices == 0) + if (g_flashmap_load(dev, pp, slicer, &head) == 0) break; g_flashmap_modify(gp, cp->provider->name, cp->provider->sectorsize, &head); } while (0); g_access(cp, -1, 0, 0); - STAILQ_FOREACH_SAFE(slice, &head, sl_link, slice_temp) { + STAILQ_FOREACH_SAFE(slice, &head, sl_link, slice_temp) free(slice, M_FLASHMAP); - } if (LIST_EMPTY(&gp->provider)) { g_slice_spoiled(cp); return (NULL); } return (gp); } -static void -g_flashmap_config(struct gctl_req *req, struct g_class *mp, const char *verb) -{ - - gctl_error(req, "unknown config verb"); -} - static int -g_flashmap_load(device_t dev, struct g_flashmap_head *head) +g_flashmap_load(device_t dev, struct g_provider *pp, flash_slicer_t slicer, + struct g_flashmap_head *head) { struct flash_slice *slices; struct g_flashmap_slice *slice; - uint32_t i, buf_size; - int nslices = 0; + int i, nslices = 0; - buf_size = sizeof(struct flash_slice) * FLASH_SLICES_MAX_NUM; - slices = malloc(buf_size, M_FLASHMAP, M_WAITOK | M_ZERO); - if (flash_fill_slices && - flash_fill_slices(dev, slices, &nslices) == 0) { + slices = malloc(sizeof(struct flash_slice) * FLASH_SLICES_MAX_NUM, + M_FLASHMAP, M_WAITOK | M_ZERO); + if (slicer(dev, pp->name, slices, &nslices) == 0) { for (i = 0; i < nslices; i++) { slice = malloc(sizeof(struct g_flashmap_slice), M_FLASHMAP, M_WAITOK); slice->sl_name = slices[i].label; slice->sl_start = slices[i].base; slice->sl_end = slices[i].base + slices[i].size - 1; STAILQ_INSERT_TAIL(head, slice, sl_link); } } free(slices, M_FLASHMAP); return (nslices); } -void flash_register_slicer(int (*slicer)(device_t, struct flash_slice *, int *)) +void flash_register_slicer(flash_slicer_t slicer, u_int type, bool force) { - flash_fill_slices = slicer; + g_topology_lock(); + if (g_flashmap_slicers[type].slicer == NULL || force == TRUE) + g_flashmap_slicers[type].slicer = slicer; + g_topology_unlock(); } static struct g_class g_flashmap_class = { .name = FLASHMAP_CLASS_NAME, .version = G_VERSION, .taste = g_flashmap_taste, - .dumpconf = g_flashmap_dumpconf, .ioctl = g_flashmap_ioctl, - .ctlreq = g_flashmap_config, }; DECLARE_GEOM_CLASS(g_flashmap_class, g_flashmap); +MODULE_VERSION(g_flashmap, 0); diff --git a/sys/modules/geom/Makefile b/sys/modules/geom/Makefile index 8d7e3c6deb3f..7b79f53a13af 100644 --- a/sys/modules/geom/Makefile +++ b/sys/modules/geom/Makefile @@ -1,33 +1,34 @@ # $FreeBSD$ SYSDIR?=${.CURDIR}/../.. .include "${SYSDIR}/conf/kern.opts.mk" SUBDIR= geom_bde \ geom_cache \ geom_concat \ geom_eli \ + geom_flashmap \ geom_gate \ geom_journal \ geom_label \ geom_linux_lvm \ geom_mirror \ geom_mountver \ geom_multipath \ geom_nop \ geom_part \ geom_raid \ geom_raid3 \ geom_sched \ geom_shsec \ geom_stripe \ geom_uzip \ geom_vinum \ geom_virstor \ geom_zero .if ${MK_CCD} != "no" || defined(ALL_MODULES) SUBDIR+= geom_ccd .endif .include diff --git a/sys/modules/geom/geom_flashmap/Makefile b/sys/modules/geom/geom_flashmap/Makefile new file mode 100644 index 000000000000..d475860fefe6 --- /dev/null +++ b/sys/modules/geom/geom_flashmap/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../geom + +KMOD= geom_flashmap +SRCS= geom_flashmap.c + +.include diff --git a/sys/powerpc/mikrotik/platform_rb.c b/sys/powerpc/mikrotik/platform_rb.c index 39de29e8d618..e05c59b37636 100644 --- a/sys/powerpc/mikrotik/platform_rb.c +++ b/sys/powerpc/mikrotik/platform_rb.c @@ -1,123 +1,85 @@ /*- * Copyright (c) 2015 Justin Hibbits * 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. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, 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 DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include -#include #include #include #include -#include #include -#include #include #include "platform_if.h" static int rb_probe(platform_t); static int rb_attach(platform_t); static platform_method_t rb_methods[] = { PLATFORMMETHOD(platform_probe, rb_probe), PLATFORMMETHOD(platform_attach, rb_attach), PLATFORMMETHOD_END }; DEFINE_CLASS_1(rb, rb_platform, rb_methods, 0, mpc85xx_platform); PLATFORM_DEF(rb_platform); -/* Slicer operates on the NAND controller, so we have to find the chip. */ -static int -rb_nand_slicer(device_t dev, struct flash_slice *slices, int *nslices) -{ - struct nand_chip *chip; - device_t *children; - int n; - - if (device_get_children(dev, &children, &n) != 0) { - panic("Slicer called on controller with no child!"); - } - dev = children[0]; - free(children, M_TEMP); - - if (device_get_children(dev, &children, &n) != 0) { - panic("Slicer called on controller with nandbus but no child!"); - } - dev = children[0]; - free(children, M_TEMP); - - chip = device_get_softc(dev); - *nslices = 2; - slices[0].base = 0; - slices[0].size = 4 * 1024 * 1024; - slices[0].label = "boot"; - - slices[1].base = 4 * 1024 * 1024; - slices[1].size = chip->ndisk->d_mediasize - slices[0].size; - slices[1].label = "rootfs"; - - return (0); -} - static int rb_probe(platform_t plat) { phandle_t rootnode; char model[32]; rootnode = OF_finddevice("/"); if (OF_getprop(rootnode, "model", model, sizeof(model)) > 0) { if (strcmp(model, "RB800") == 0) return (BUS_PROBE_SPECIFIC); } return (ENXIO); } static int rb_attach(platform_t plat) { int error; error = mpc85xx_attach(plat); if (error) return (error); - flash_register_slicer(rb_nand_slicer); - return (0); } diff --git a/sys/sys/slicer.h b/sys/sys/slicer.h index 9bf8748f2de0..53f680d84ced 100644 --- a/sys/sys/slicer.h +++ b/sys/sys/slicer.h @@ -1,52 +1,64 @@ /*- * Copyright (c) 2012 Semihalf. * 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. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE. * * $FreeBSD$ */ #ifndef _FLASH_SLICER_H_ -#define _FLASH_SLICER_H_ +#define _FLASH_SLICER_H_ #include -#define FLASH_SLICES_MAX_NUM 8 -#define FLASH_SLICES_MAX_NAME_LEN (32 + 1) +#define FLASH_SLICES_MAX_NUM 8 +#define FLASH_SLICES_MAX_NAME_LEN (32 + 1) #define FLASH_SLICES_FLAG_NONE 0 #define FLASH_SLICES_FLAG_RO 1 /* Read only */ +#define FLASH_SLICES_FMT "%ss.%s" + struct flash_slice { off_t base; off_t size; - char *label; + const char *label; unsigned int flags; }; #ifdef _KERNEL -int fdt_flash_fill_slices(device_t, struct flash_slice *, int *) __weak_symbol; -void flash_register_slicer(int (*)(device_t, struct flash_slice *, int *)); + +typedef int (*flash_slicer_t)(device_t dev, const char *provider, + struct flash_slice *slices, int *slices_num); + +#define FLASH_SLICES_TYPE_NAND 0 +#define FLASH_SLICES_TYPE_CFI 1 +#define FLASH_SLICES_TYPE_SPI 2 +#define FLASH_SLICES_TYPE_MMC 3 + +/* Use NULL for deregistering a slicer */ +void flash_register_slicer(flash_slicer_t slicer, u_int type, bool force); + #endif /* _KERNEL */ #endif /* _FLASH_SLICER_H_ */