Index: sys/arm64/rockchip/rk3399_efuse.c =================================================================== --- sys/arm64/rockchip/rk3399_efuse.c +++ sys/arm64/rockchip/rk3399_efuse.c @@ -0,0 +1,224 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 BusyTech + * + * 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. + */ + +/* + * RK3399 non-secure efuse driver (read-only). Based on u-boot implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +/* Registers & bits in registers. */ +#define EFUSE_CTRL 0x0000 +#define EFUSE_CTRL_CSB (1 << 0) +#define EFUSE_CTRL_STROBE (1 << 1) +#define EFUSE_CTRL_LOAD (1 << 2) +#define EFUSE_CTRL_PGENB (1 << 3) +#define EFUSE_CTRL_PS (1 << 4) +#define EFUSE_CTRL_PD (1 << 5) +#define EFUSE_CTRL_MR (1 << 6) +#define EFUSE_CTRL_RSB (1 << 7) +#define EFUSE_CTRL_RWI (1 << 8) +#define EFUSE_CTRL_STROBE_SFT_SEL (1 << 9) +#define EFUSE_CTRL_ADDR_SHIFT 16 +#define EFUSE_CTRL_ADDR_MASK (0x3ff << EFUSE_CTRL_ADDR_SHIFT) +#define EFUSE_DOUT 0x0004 +#define EFUSE_RF 0x0008 +#define EFUSE_JTAG_PASS 0x0010 +#define EFUSE_STROBE_FINISH_CTRL 0x0014 + +#define EFUSE_NUM 32 +#define EFUSE_SIZE 4 + +#define READ4(sc, reg) bus_read_4((sc)->sc_mem_res, (reg)) +#define WRITE4(sc, reg, val) bus_write_4((sc)->sc_mem_res, (reg), (val)) + +struct rk3399_efuse_softc { + device_t sc_dev; + struct resource *sc_mem_res; + struct cdev *sc_cdev; + struct mtx sc_lock; + int sc_mem_rid; +}; + +static devclass_t rk3399_efuse_devclass; + +static int rk3399_efuse_probe(device_t); +static int rk3399_efuse_attach(device_t); +static int rk3399_efuse_detach(device_t); + +static d_read_t rk3399_efuse_read; + +static struct cdevsw rk3399_efuse_cdevsw = { + .d_version = D_VERSION, + .d_read = rk3399_efuse_read, + .d_name = "rk3399_efuse", +}; + + +static int +rk3399_efuse_read(struct cdev *dev, struct uio *uio, int ioflag) +{ + uint32_t buf[EFUSE_NUM]; + struct rk3399_efuse_softc *sc = dev->si_drv1; + uint32_t val; + uint32_t ii; + int len; + + len = uio->uio_resid; + if (len > EFUSE_NUM * EFUSE_SIZE || len < 0) + return (EIO); + + if (len == 0) + return (0); + + mtx_lock(&sc->sc_lock); + WRITE4(sc, EFUSE_CTRL, EFUSE_CTRL_LOAD | EFUSE_CTRL_PGENB | + EFUSE_CTRL_STROBE_SFT_SEL | EFUSE_CTRL_RSB); + DELAY(1); + for (ii = 0; ii < EFUSE_NUM; ii++) { + val = READ4(sc, EFUSE_CTRL); + val |= EFUSE_CTRL_STROBE | (ii << EFUSE_CTRL_ADDR_SHIFT); + WRITE4(sc, EFUSE_CTRL, val); + DELAY(1); + + buf[ii] = READ4(sc, EFUSE_DOUT); + } + WRITE4(sc, EFUSE_CTRL, EFUSE_CTRL_CSB | EFUSE_CTRL_PD); + mtx_unlock(&sc->sc_lock); + + return (uiomove(buf, uio->uio_resid, uio)); +} + +static int +rk3399_efuse_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "rockchip,rk3399-efuse")) + return (ENXIO); + + device_set_desc(dev, "Rockchip RK3399 fuse (non-secure)"); + return (BUS_PROBE_DEFAULT); +} + +static int +rk3399_efuse_attach(device_t dev) +{ + struct rk3399_efuse_softc *sc; + struct make_dev_args args; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + + sc->sc_mem_rid = 0; + sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->sc_mem_rid, RF_ACTIVE); + if (sc->sc_mem_res == NULL) { + device_printf(dev, "cannot allocate memory resource\n"); + goto err_alloc_mem; + } + + mtx_init(&sc->sc_lock, device_get_nameunit(dev), "rk3399_efuse", + MTX_DEF); + make_dev_args_init(&args); + args.mda_devsw = &rk3399_efuse_cdevsw; + args.mda_uid = UID_ROOT; + args.mda_gid = GID_WHEEL; + args.mda_mode = S_IRUSR | S_IRGRP; + args.mda_si_drv1 = sc; + + if (make_dev_s(&args, &sc->sc_cdev, "efuse") != 0) { + device_printf(dev, "cannot create efuse device\n"); + goto err_make_dev; + } + return (bus_generic_attach(dev)); + +err_make_dev: + mtx_destroy(&sc->sc_lock); + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, + sc->sc_mem_res); +err_alloc_mem: + return (ENXIO); +} + +static int +rk3399_efuse_detach(device_t dev) +{ + struct rk3399_efuse_softc *sc; + + sc = device_get_softc(dev); + + if (sc->sc_cdev != NULL) + destroy_dev(sc->sc_cdev); + + mtx_destroy(&sc->sc_lock); + if (sc->sc_mem_res) { + bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, + sc->sc_mem_res); + } + + return (bus_generic_detach(dev)); +} + +static device_method_t rk3399_efuse_methods[] = { + DEVMETHOD(device_probe, rk3399_efuse_probe), + DEVMETHOD(device_attach, rk3399_efuse_attach), + DEVMETHOD(device_detach, rk3399_efuse_detach), + + {0, 0}, +}; + +static driver_t rk3399_efuse_driver = { + "rk3399_efuse", + rk3399_efuse_methods, + sizeof(struct rk3399_efuse_softc), +}; + +DRIVER_MODULE(rk3399_efuse, simplebus, rk3399_efuse_driver, + rk3399_efuse_devclass, NULL, NULL); +MODULE_VERSION(rk3399_efuse, 1); Index: sys/conf/files.arm64 =================================================================== --- sys/conf/files.arm64 +++ sys/conf/files.arm64 @@ -378,6 +378,7 @@ # RockChip Drivers arm64/rockchip/rk3399_emmcphy.c optional fdt rk_emmcphy soc_rockchip_rk3399 +arm64/rockchip/rk3399_efuse.c optional fdt soc_rockchip_rk3399 arm64/rockchip/rk_dwc3.c optional fdt rk_dwc3 soc_rockchip_rk3399 arm64/rockchip/rk_i2c.c optional fdt rk_i2c soc_rockchip_rk3328 | fdt rk_i2c soc_rockchip_rk3399 arm64/rockchip/rk805.c optional fdt rk805 soc_rockchip_rk3328 | fdt rk805 soc_rockchip_rk3399