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