1 /* $OpenBSD: qcaoss.c,v 1.1 2023/05/23 14:10:27 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 #include <sys/malloc.h>
22 #include <sys/atomic.h>
23
24 #include <machine/bus.h>
25 #include <machine/fdt.h>
26
27 #include <dev/ofw/openfirm.h>
28 #include <dev/ofw/ofw_misc.h>
29 #include <dev/ofw/fdt.h>
30
31 #define AOSS_DESC_MAGIC 0x0
32 #define AOSS_DESC_VERSION 0x4
33 #define AOSS_DESC_FEATURES 0x8
34 #define AOSS_DESC_UCORE_LINK_STATE 0xc
35 #define AOSS_DESC_UCORE_LINK_STATE_ACK 0x10
36 #define AOSS_DESC_UCORE_CH_STATE 0x14
37 #define AOSS_DESC_UCORE_CH_STATE_ACK 0x18
38 #define AOSS_DESC_UCORE_MBOX_SIZE 0x1c
39 #define AOSS_DESC_UCORE_MBOX_OFFSET 0x20
40 #define AOSS_DESC_MCORE_LINK_STATE 0x24
41 #define AOSS_DESC_MCORE_LINK_STATE_ACK 0x28
42 #define AOSS_DESC_MCORE_CH_STATE 0x2c
43 #define AOSS_DESC_MCORE_CH_STATE_ACK 0x30
44 #define AOSS_DESC_MCORE_MBOX_SIZE 0x34
45 #define AOSS_DESC_MCORE_MBOX_OFFSET 0x38
46
47 #define AOSS_MAGIC 0x4d41494c
48 #define AOSS_VERSION 1
49
50 #define AOSS_STATE_UP (0xffffU << 0)
51 #define AOSS_STATE_DOWN (0xffffU << 16)
52
53 #define HREAD4(sc, reg) \
54 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
55 #define HWRITE4(sc, reg, val) \
56 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
57
58 struct qcaoss_softc {
59 struct device sc_dev;
60 bus_space_tag_t sc_iot;
61 bus_space_handle_t sc_ioh;
62
63 size_t sc_offset;
64 size_t sc_size;
65
66 struct mbox_channel *sc_mc;
67 };
68
69 struct qcaoss_softc *qcaoss_sc;
70
71 int qcaoss_match(struct device *, void *, void *);
72 void qcaoss_attach(struct device *, struct device *, void *);
73
74 const struct cfattach qcaoss_ca = {
75 sizeof (struct qcaoss_softc), qcaoss_match, qcaoss_attach
76 };
77
78 struct cfdriver qcaoss_cd = {
79 NULL, "qcaoss", DV_DULL
80 };
81
82 int
qcaoss_match(struct device * parent,void * match,void * aux)83 qcaoss_match(struct device *parent, void *match, void *aux)
84 {
85 struct fdt_attach_args *faa = aux;
86
87 return OF_is_compatible(faa->fa_node, "qcom,aoss-qmp");
88 }
89
90 void
qcaoss_attach(struct device * parent,struct device * self,void * aux)91 qcaoss_attach(struct device *parent, struct device *self, void *aux)
92 {
93 struct qcaoss_softc *sc = (struct qcaoss_softc *)self;
94 struct fdt_attach_args *faa = aux;
95 int i;
96
97 if (faa->fa_nreg < 1) {
98 printf(": no registers\n");
99 return;
100 }
101
102 sc->sc_iot = faa->fa_iot;
103 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
104 faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
105 printf(": can't map registers\n");
106 return;
107 }
108
109 sc->sc_mc = mbox_channel_idx(faa->fa_node, 0, NULL);
110 if (sc->sc_mc == NULL) {
111 bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
112 printf(": can't find mbox\n");
113 return;
114 }
115
116 if (HREAD4(sc, AOSS_DESC_MAGIC) != AOSS_MAGIC ||
117 HREAD4(sc, AOSS_DESC_VERSION) != AOSS_VERSION) {
118 printf(": invalid QMP info\n");
119 return;
120 }
121
122 sc->sc_offset = HREAD4(sc, AOSS_DESC_MCORE_MBOX_OFFSET);
123 sc->sc_size = HREAD4(sc, AOSS_DESC_MCORE_MBOX_SIZE);
124 if (sc->sc_size == 0) {
125 printf(": invalid mailbox size\n");
126 return;
127 }
128
129 HWRITE4(sc, AOSS_DESC_UCORE_LINK_STATE_ACK,
130 HREAD4(sc, AOSS_DESC_UCORE_LINK_STATE));
131
132 HWRITE4(sc, AOSS_DESC_MCORE_LINK_STATE, AOSS_STATE_UP);
133 mbox_send(sc->sc_mc, NULL, 0);
134
135 for (i = 1000; i > 0; i--) {
136 if (HREAD4(sc, AOSS_DESC_MCORE_LINK_STATE_ACK) == AOSS_STATE_UP)
137 break;
138 delay(1000);
139 }
140 if (i == 0) {
141 printf(": didn't get link state ack\n");
142 return;
143 }
144
145 HWRITE4(sc, AOSS_DESC_MCORE_CH_STATE, AOSS_STATE_UP);
146 mbox_send(sc->sc_mc, NULL, 0);
147
148 for (i = 1000; i > 0; i--) {
149 if (HREAD4(sc, AOSS_DESC_UCORE_CH_STATE) == AOSS_STATE_UP)
150 break;
151 delay(1000);
152 }
153 if (i == 0) {
154 printf(": didn't get open channel\n");
155 return;
156 }
157
158 HWRITE4(sc, AOSS_DESC_UCORE_CH_STATE_ACK, AOSS_STATE_UP);
159 mbox_send(sc->sc_mc, NULL, 0);
160
161 for (i = 1000; i > 0; i--) {
162 if (HREAD4(sc, AOSS_DESC_MCORE_CH_STATE_ACK) == AOSS_STATE_UP)
163 break;
164 delay(1000);
165 }
166 if (i == 0) {
167 printf(": didn't get channel ack\n");
168 return;
169 }
170
171 printf("\n");
172
173 qcaoss_sc = sc;
174 }
175
176 int
qcaoss_send(char * data,size_t len)177 qcaoss_send(char *data, size_t len)
178 {
179 struct qcaoss_softc *sc = qcaoss_sc;
180 uint32_t reg;
181 int i;
182
183 if (sc == NULL)
184 return ENXIO;
185
186 if (data == NULL || sizeof(uint32_t) + len > sc->sc_size ||
187 (len % sizeof(uint32_t)) != 0)
188 return EINVAL;
189
190 /* Write data first, needs to be 32-bit access. */
191 for (i = 0; i < len; i += 4) {
192 memcpy(®, data + i, sizeof(reg));
193 HWRITE4(sc, sc->sc_offset + sizeof(uint32_t) + i, reg);
194 }
195
196 /* Commit transaction by writing length. */
197 HWRITE4(sc, sc->sc_offset, len);
198
199 /* Assert it's stored and inform peer. */
200 KASSERT(HREAD4(sc, sc->sc_offset) == len);
201 mbox_send(sc->sc_mc, NULL, 0);
202
203 for (i = 1000; i > 0; i--) {
204 if (HREAD4(sc, sc->sc_offset) == 0)
205 break;
206 delay(1000);
207 }
208 if (i == 0) {
209 printf("%s: timeout sending message\n", sc->sc_dev.dv_xname);
210 HWRITE4(sc, sc->sc_offset, 0);
211 return ETIMEDOUT;
212 }
213
214 return 0;
215 }
216