commit d1b648325a28bc903dc7c8171365a37353143f2e Author: Brandon Bergren Date: Thu Sep 12 11:14:59 2019 -0500 jhibbits opal nvram diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 5383595b141..b5ceba0bbd4 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -192,6 +192,7 @@ powerpc/powernv/opal_flash.c optional powernv opalflash powerpc/powernv/opal_hmi.c optional powernv powerpc/powernv/opal_i2c.c optional iicbus fdt powernv powerpc/powernv/opal_i2cm.c optional iicbus fdt powernv +powerpc/powernv/opal_nvram.c optional powernv nvram powerpc/powernv/opal_pci.c optional powernv pci powerpc/powernv/opal_sensor.c optional powernv powerpc/powernv/opalcall.S optional powernv diff --git a/sys/modules/Makefile b/sys/modules/Makefile index f5c0995af6a..b1a9efba04f 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -756,10 +756,11 @@ _wi= wi .if ${MACHINE_ARCH} == "powerpc64" _ipmi= ipmi +_nvram= opal_nvram .endif .if ${MACHINE_ARCH} == "powerpc64" || ${MACHINE_ARCH} == "powerpc" # Don't build powermac_nvram for powerpcspe, it's never supported. -_nvram= powermac_nvram +_nvram+= powermac_nvram .endif .if ${MACHINE_CPUARCH} == "sparc64" diff --git a/sys/modules/opal_nvram/Makefile b/sys/modules/opal_nvram/Makefile new file mode 100644 index 00000000000..aca711070fc --- /dev/null +++ b/sys/modules/opal_nvram/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/powerpc/powernv + +KMOD= opal_nvram +SRCS= opal_nvram.c +SRCS+= bus_if.h device_if.h +SRCS+= ofw_bus_if.h + +.include diff --git a/sys/modules/opal_nvram/Makefile.orig b/sys/modules/opal_nvram/Makefile.orig new file mode 100644 index 00000000000..e69de29bb2d diff --git a/sys/powerpc/powernv/opal.h b/sys/powerpc/powernv/opal.h index a8f55f34133..ecf22e39a7f 100644 --- a/sys/powerpc/powernv/opal.h +++ b/sys/powerpc/powernv/opal.h @@ -45,6 +45,8 @@ int opal_call(uint64_t token, ...); #define OPAL_RTC_WRITE 4 #define OPAL_CEC_POWER_DOWN 5 #define OPAL_CEC_REBOOT 6 +#define OPAL_READ_NVRAM 7 +#define OPAL_WRITE_NVRAM 8 #define OPAL_HANDLE_INTERRUPT 9 #define OPAL_POLL_EVENTS 10 #define OPAL_PCI_CONFIG_READ_BYTE 13 diff --git a/sys/powerpc/powernv/opal_nvram.c b/sys/powerpc/powernv/opal_nvram.c new file mode 100644 index 00000000000..615acfdaf7d --- /dev/null +++ b/sys/powerpc/powernv/opal_nvram.c @@ -0,0 +1,273 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2006 Maxim Sobolev + * 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "opal.h" + +#include + +#include +#include + +struct chrp_header { + uint8_t sig; + uint8_t csum; + uint16_t len; + char name[12]; +}; + +struct opal_nvram_softc { + device_t sc_dev; + phandle_t sc_node; + uint32_t sc_size; + uint8_t *sc_buf; + vm_paddr_t sc_buf_phys; + + struct cdev *sc_cdev; + int sc_isopen; +}; + +/* + * Device interface. + */ +static int opal_nvram_probe(device_t); +static int opal_nvram_attach(device_t); +static int opal_nvram_detach(device_t); + +/* + * Driver methods. + */ +static device_method_t opal_nvram_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, opal_nvram_probe), + DEVMETHOD(device_attach, opal_nvram_attach), + DEVMETHOD(device_detach, opal_nvram_detach), + + { 0, 0 } +}; + +static driver_t opal_nvram_driver = { + "opal_nvram", + opal_nvram_methods, + sizeof(struct opal_nvram_softc) +}; + +static devclass_t opal_nvram_devclass; + +DRIVER_MODULE(opal_nvram, opal, opal_nvram_driver, opal_nvram_devclass, 0, 0); + +/* + * Cdev methods. + */ + +static d_open_t opal_nvram_open; +static d_close_t opal_nvram_close; +static d_read_t opal_nvram_read; +static d_write_t opal_nvram_write; +static d_ioctl_t opal_nvram_ioctl; + +static struct cdevsw opal_nvram_cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDGIANT, + .d_open = opal_nvram_open, + .d_close = opal_nvram_close, + .d_read = opal_nvram_read, + .d_write = opal_nvram_write, + .d_ioctl = opal_nvram_ioctl, + .d_name = "nvram", +}; + +static int +opal_nvram_probe(device_t dev) +{ + + if (!ofw_bus_is_compatible(dev, "ibm,opal-nvram")) + return (ENXIO); + + device_set_desc(dev, "OPAL NVRAM"); + return (0); +} + +static int +opal_nvram_attach(device_t dev) +{ + struct opal_nvram_softc *sc; + phandle_t node; + int err; + + node = ofw_bus_get_node(dev); + sc = device_get_softc(dev); + + sc->sc_dev = dev; + sc->sc_node = node; + + err = OF_getencprop(node, "#bytes", &sc->sc_size, + sizeof(sc->sc_size)); + + if (err < 0) + return (ENXIO); + + sc->sc_buf = contigmalloc(2 * PAGE_SIZE, M_DEVBUF, M_WAITOK, + 0, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); + sc->sc_buf_phys = pmap_kextract((vm_offset_t)sc->sc_buf); + sc->sc_cdev = make_dev(&opal_nvram_cdevsw, 0, 0, 0, 0600, + "nvram"); + sc->sc_cdev->si_drv1 = sc; + + return 0; +} + +static int +opal_nvram_detach(device_t dev) +{ + struct opal_nvram_softc *sc; + + sc = device_get_softc(dev); + + if (sc->sc_cdev != NULL) + destroy_dev(sc->sc_cdev); + + return 0; +} + +static int +opal_nvram_open(struct cdev *dev, int flags, int fmt, struct thread *td) +{ + struct opal_nvram_softc *sc = dev->si_drv1; + + if (sc->sc_isopen) + return EBUSY; + sc->sc_isopen = 1; + return 0; +} + +static int +opal_nvram_close(struct cdev *dev, int fflag, int devtype, struct thread *td) +{ + struct opal_nvram_softc *sc = dev->si_drv1; + + sc->sc_isopen = 0; + return 0; +} + +static int +opal_nvram_read(struct cdev *dev, struct uio *uio, int ioflag) +{ + int rv, amnt; + struct opal_nvram_softc *sc = dev->si_drv1; + + rv = 0; + while (uio->uio_resid > 0) { + amnt = MIN(uio->uio_resid, sc->sc_size - uio->uio_offset); + if (amnt == 0) + break; + + rv = opal_call(OPAL_READ_NVRAM, sc->sc_buf_phys, + amnt, uio->uio_offset); + if (rv != OPAL_SUCCESS) { + switch (rv) { + case OPAL_HARDWARE: + rv = EIO; + break; + case OPAL_PARAMETER: + rv = EINVAL; + break; + } + break; + } + rv = uiomove(sc->sc_buf, amnt, uio); + if (rv != 0) + break; + } + return rv; +} + +static int +opal_nvram_write(struct cdev *dev, struct uio *uio, int ioflag) +{ + int rv, amnt; + struct opal_nvram_softc *sc = dev->si_drv1; + + rv = 0; + while (uio->uio_resid > 0) { + amnt = MIN(uio->uio_resid, sc->sc_size - uio->uio_offset); + if (amnt == 0) { + rv = ENOSPC; + break; + } + rv = uiomove(sc->sc_buf, amnt, uio); + if (rv != 0) + break; + rv = opal_call(OPAL_WRITE_NVRAM, sc->sc_buf_phys, amnt, + uio->uio_offset); + if (rv != OPAL_SUCCESS) { + switch (rv) { + case OPAL_HARDWARE: + rv = EIO; + break; + case OPAL_PARAMETER: + rv = EINVAL; + break; + } + break; + } + } + return rv; +} + +static int +opal_nvram_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, + struct thread *td) +{ + struct opal_nvram_softc *sc = dev->si_drv1; + + switch (cmd) { + case DIOCGMEDIASIZE: + return (sc->sc_size); + } + return (EINVAL); +} \ No newline at end of file