1/* $OpenBSD: qcsdam.c,v 1.1 2023/07/22 22:43:53 patrick Exp $ */ 2/* 3 * Copyright (c) 2023 Patrick Wildt <patrick@blueri.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <sys/param.h> 19#include <sys/systm.h> 20#include <sys/device.h> 21 22#include <machine/bus.h> 23#include <machine/fdt.h> 24 25#include <dev/fdt/spmivar.h> 26 27#include <dev/ofw/openfirm.h> 28#include <dev/ofw/ofw_misc.h> 29#include <dev/ofw/fdt.h> 30 31struct qcsdam_softc { 32 struct device sc_dev; 33 spmi_tag_t sc_tag; 34 int8_t sc_sid; 35 uint16_t sc_addr; 36 37 struct nvmem_device sc_nd; 38}; 39 40int qcsdam_match(struct device *, void *, void *); 41void qcsdam_attach(struct device *, struct device *, void *); 42 43const struct cfattach qcsdam_ca = { 44 sizeof (struct qcsdam_softc), qcsdam_match, qcsdam_attach 45}; 46 47struct cfdriver qcsdam_cd = { 48 NULL, "qcsdam", DV_DULL 49}; 50 51int qcsdam_nvmem_read(void *, bus_addr_t, void *, bus_size_t); 52int qcsdam_nvmem_write(void *, bus_addr_t, const void *, bus_size_t); 53 54int 55qcsdam_match(struct device *parent, void *match, void *aux) 56{ 57 struct spmi_attach_args *saa = aux; 58 59 return OF_is_compatible(saa->sa_node, "qcom,spmi-sdam"); 60} 61 62void 63qcsdam_attach(struct device *parent, struct device *self, void *aux) 64{ 65 struct qcsdam_softc *sc = (struct qcsdam_softc *)self; 66 struct spmi_attach_args *saa = aux; 67 uint32_t reg; 68 69 if (OF_getpropintarray(saa->sa_node, "reg", 70 ®, sizeof(reg)) != sizeof(reg)) { 71 printf(": can't find registers\n"); 72 return; 73 } 74 75 sc->sc_tag = saa->sa_tag; 76 sc->sc_sid = saa->sa_sid; 77 sc->sc_addr = reg; 78 79 printf("\n"); 80 81 sc->sc_nd.nd_node = saa->sa_node; 82 sc->sc_nd.nd_cookie = sc; 83 sc->sc_nd.nd_read = qcsdam_nvmem_read; 84 sc->sc_nd.nd_write = qcsdam_nvmem_write; 85 nvmem_register(&sc->sc_nd); 86} 87 88int 89qcsdam_nvmem_read(void *cookie, bus_addr_t addr, void *data, bus_size_t size) 90{ 91 struct qcsdam_softc *sc = cookie; 92 int error; 93 94 error = spmi_cmd_read(sc->sc_tag, sc->sc_sid, SPMI_CMD_EXT_READL, 95 sc->sc_addr + addr, data, size); 96 if (error) { 97 printf("%s: error reading NVMEM\n", sc->sc_dev.dv_xname); 98 return error; 99 } 100 101 return 0; 102} 103 104int 105qcsdam_nvmem_write(void *cookie, bus_addr_t addr, const void *data, 106 bus_size_t size) 107{ 108 struct qcsdam_softc *sc = cookie; 109 int error; 110 111 error = spmi_cmd_write(sc->sc_tag, sc->sc_sid, SPMI_CMD_EXT_WRITEL, 112 sc->sc_addr + addr, data, size); 113 if (error) { 114 printf("%s: error reading NVMEM\n", sc->sc_dev.dv_xname); 115 return error; 116 } 117 118 return 0; 119} 120