From 16809202f9cfab139457e0f67b3ab387e00f84ba Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 17 Dec 2022 11:56:45 +0000 Subject: Add aplefuse(4), a driver for the eFuses on Apple Silicon SoCs. ok patrick@ --- sys/arch/arm64/conf/GENERIC | 3 +- sys/arch/arm64/conf/files.arm64 | 6 ++- sys/arch/arm64/dev/aplefuse.c | 112 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 sys/arch/arm64/dev/aplefuse.c (limited to 'sys') diff --git a/sys/arch/arm64/conf/GENERIC b/sys/arch/arm64/conf/GENERIC index d6608a85bdd..9788fcf7269 100644 --- a/sys/arch/arm64/conf/GENERIC +++ b/sys/arch/arm64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.250 2022/12/12 19:18:25 kettenis Exp $ +# $OpenBSD: GENERIC,v 1.251 2022/12/17 11:56:44 kettenis Exp $ # # GENERIC machine description file # @@ -157,6 +157,7 @@ apldcms* at apldchidev? wsmouse* at apldcms? mux 0 apldma* at fdt? apldog* at fdt? early 1 +aplefuse* at fdt? early 1 apliic* at fdt? iic* at apliic? aplintc* at fdt? early 1 diff --git a/sys/arch/arm64/conf/files.arm64 b/sys/arch/arm64/conf/files.arm64 index f5e39dfb2b5..b30947a9e61 100644 --- a/sys/arch/arm64/conf/files.arm64 +++ b/sys/arch/arm64/conf/files.arm64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.arm64,v 1.64 2022/11/21 21:48:06 kettenis Exp $ +# $OpenBSD: files.arm64,v 1.65 2022/12/17 11:56:44 kettenis Exp $ maxpartitions 16 maxusers 2 8 128 @@ -169,6 +169,10 @@ device apldog attach apldog at fdt file arch/arm64/dev/apldog.c apldog +device aplefuse +attach aplefuse at fdt +file arch/arm64/dev/aplefuse.c aplefuse + device apliic: i2cbus attach apliic at fdt file arch/arm64/dev/apliic.c apliic diff --git a/sys/arch/arm64/dev/aplefuse.c b/sys/arch/arm64/dev/aplefuse.c new file mode 100644 index 00000000000..53eb1e4e329 --- /dev/null +++ b/sys/arch/arm64/dev/aplefuse.c @@ -0,0 +1,112 @@ +/* $OpenBSD: aplefuse.c,v 1.1 2022/12/17 11:56:44 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +struct aplefuse_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_size_t sc_ios; + + struct nvmem_device sc_nd; +}; + +int aplefuse_match(struct device *, void *, void *); +void aplefuse_attach(struct device *, struct device *, void *); + +const struct cfattach aplefuse_ca = { + sizeof (struct aplefuse_softc), aplefuse_match, aplefuse_attach +}; + +struct cfdriver aplefuse_cd = { + NULL, "aplefuse", DV_DULL +}; + +int aplefuse_nvmem_read(void *, bus_addr_t, void *, bus_size_t); +int aplefuse_nvmem_write(void *, bus_addr_t, const void *, bus_size_t); + +int +aplefuse_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + return OF_is_compatible(faa->fa_node, "apple,efuses"); +} + +void +aplefuse_attach(struct device *parent, struct device *self, void *aux) +{ + struct aplefuse_softc *sc = (struct aplefuse_softc *)self; + struct fdt_attach_args *faa = aux; + + if (faa->fa_nreg < 1) { + printf(": no registers\n"); + return; + } + + sc->sc_iot = faa->fa_iot; + if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, + faa->fa_reg[0].size, 0, &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } + sc->sc_ios = faa->fa_reg[0].size; + + printf("\n"); + + sc->sc_nd.nd_node = faa->fa_node; + sc->sc_nd.nd_cookie = sc; + sc->sc_nd.nd_read = aplefuse_nvmem_read; + nvmem_register(&sc->sc_nd); +} + +int +aplefuse_nvmem_read(void *cookie, bus_addr_t addr, void *data, bus_size_t size) +{ + struct aplefuse_softc *sc = cookie; + uint8_t *p = data; + uint32_t value; + uint8_t buf[4]; + int offset; + + if (addr > sc->sc_ios || size > sc->sc_ios - addr) + return EINVAL; + + offset = addr & 0x3; + addr &= ~0x3; + while (size > 0) { + value = bus_space_read_4(sc->sc_iot, sc->sc_ioh, addr); + htolem32(buf, value); + memcpy(p, &buf[offset], MIN(size, 4 - offset)); + size -= MIN(size, 4 - offset); + p += MIN(size, 4 - offset); + addr += 4; + offset = 0; + } + + return 0; +} -- cgit v1.2.3