xref: /openbsd-src/sys/dev/fdt/qcpas.c (revision a419c0167f5658b19fc3f503d295a4cf70b6b8d7)
1 /*	$OpenBSD: qcpas.c,v 1.8 2024/11/08 21:13:34 landry 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 #include <sys/exec_elf.h>
24 #include <sys/sensors.h>
25 #include <sys/task.h>
26 
27 #include <machine/apmvar.h>
28 #include <machine/bus.h>
29 #include <machine/fdt.h>
30 #include <uvm/uvm_extern.h>
31 
32 #include <dev/ofw/openfirm.h>
33 #include <dev/ofw/ofw_clock.h>
34 #include <dev/ofw/ofw_misc.h>
35 #include <dev/ofw/ofw_power.h>
36 #include <dev/ofw/fdt.h>
37 
38 #include "apm.h"
39 
40 extern int qcscm_pas_init_image(uint32_t, paddr_t);
41 extern int qcscm_pas_mem_setup(uint32_t, paddr_t, size_t);
42 extern int qcscm_pas_auth_and_reset(uint32_t);
43 extern int qcscm_pas_shutdown(uint32_t);
44 
45 #define MDT_TYPE_MASK				(7 << 24)
46 #define MDT_TYPE_HASH				(2 << 24)
47 #define MDT_RELOCATABLE				(1 << 27)
48 
49 #define HREAD4(sc, reg)							\
50 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
51 #define HWRITE4(sc, reg, val)						\
52 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
53 
54 struct qcpas_dmamem {
55 	bus_dmamap_t		tdm_map;
56 	bus_dma_segment_t	tdm_seg;
57 	size_t			tdm_size;
58 	caddr_t			tdm_kva;
59 };
60 #define QCPAS_DMA_MAP(_tdm)	((_tdm)->tdm_map)
61 #define QCPAS_DMA_LEN(_tdm)	((_tdm)->tdm_size)
62 #define QCPAS_DMA_DVA(_tdm)	((_tdm)->tdm_map->dm_segs[0].ds_addr)
63 #define QCPAS_DMA_KVA(_tdm)	((void *)(_tdm)->tdm_kva)
64 
65 struct qcpas_softc {
66 	struct device		sc_dev;
67 	bus_space_tag_t		sc_iot;
68 	bus_space_handle_t	sc_ioh;
69 	bus_dma_tag_t		sc_dmat;
70 	int			sc_node;
71 
72 	void			*sc_ih[6];
73 
74 	paddr_t			sc_mem_phys[2];
75 	size_t			sc_mem_size[2];
76 	void			*sc_mem_region[2];
77 	vaddr_t			sc_mem_reloc[2];
78 
79 	uint32_t		sc_pas_id;
80 	uint32_t		sc_dtb_pas_id;
81 	uint32_t		sc_lite_pas_id;
82 	char			*sc_load_state;
83 
84 	struct qcpas_dmamem	*sc_metadata[2];
85 
86 	/* GLINK */
87 	volatile uint32_t	*sc_tx_tail;
88 	volatile uint32_t	*sc_tx_head;
89 	volatile uint32_t	*sc_rx_tail;
90 	volatile uint32_t	*sc_rx_head;
91 
92 	uint32_t		sc_tx_off;
93 	uint32_t		sc_rx_off;
94 
95 	uint8_t			*sc_tx_fifo;
96 	int			sc_tx_fifolen;
97 	uint8_t			*sc_rx_fifo;
98 	int			sc_rx_fifolen;
99 	void			*sc_glink_ih;
100 
101 	struct mbox_channel	*sc_mc;
102 
103 	struct task		sc_glink_rx;
104 	uint32_t		sc_glink_max_channel;
105 	TAILQ_HEAD(,qcpas_glink_channel) sc_glink_channels;
106 
107 #ifndef SMALL_KERNEL
108 	uint32_t		sc_last_full_capacity;
109 	uint32_t		sc_warning_capacity;
110 	uint32_t		sc_low_capacity;
111 	struct ksensor		sc_sens[11];
112 	struct ksensordev	sc_sensdev;
113 #endif
114 };
115 
116 int	qcpas_match(struct device *, void *, void *);
117 void	qcpas_attach(struct device *, struct device *, void *);
118 
119 const struct cfattach qcpas_ca = {
120 	sizeof (struct qcpas_softc), qcpas_match, qcpas_attach
121 };
122 
123 struct cfdriver qcpas_cd = {
124 	NULL, "qcpas", DV_DULL
125 };
126 
127 void	qcpas_mountroot(struct device *);
128 int	qcpas_map_memory(struct qcpas_softc *);
129 int	qcpas_mdt_init(struct qcpas_softc *, int, u_char *, size_t);
130 void	qcpas_glink_attach(struct qcpas_softc *, int);
131 
132 struct qcpas_dmamem *
133 	qcpas_dmamem_alloc(struct qcpas_softc *, bus_size_t, bus_size_t);
134 void	qcpas_dmamem_free(struct qcpas_softc *, struct qcpas_dmamem *);
135 
136 void	qcpas_intr_establish(struct qcpas_softc *, int, char *, void *);
137 int	qcpas_intr_wdog(void *);
138 int	qcpas_intr_fatal(void *);
139 int	qcpas_intr_ready(void *);
140 int	qcpas_intr_handover(void *);
141 int	qcpas_intr_stop_ack(void *);
142 int	qcpas_intr_shutdown_ack(void *);
143 
144 int
145 qcpas_match(struct device *parent, void *match, void *aux)
146 {
147 	struct fdt_attach_args *faa = aux;
148 
149 	return OF_is_compatible(faa->fa_node, "qcom,sc8280xp-adsp-pas") ||
150 	    OF_is_compatible(faa->fa_node, "qcom,x1e80100-adsp-pas");
151 }
152 
153 void
154 qcpas_attach(struct device *parent, struct device *self, void *aux)
155 {
156 	struct qcpas_softc *sc = (struct qcpas_softc *)self;
157 	struct fdt_attach_args *faa = aux;
158 
159 	if (faa->fa_nreg < 1) {
160 		printf(": no registers\n");
161 		return;
162 	}
163 
164 	sc->sc_iot = faa->fa_iot;
165 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
166 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
167 		printf(": can't map registers\n");
168 		return;
169 	}
170 	sc->sc_dmat = faa->fa_dmat;
171 	sc->sc_node = faa->fa_node;
172 
173 	if (OF_is_compatible(faa->fa_node, "qcom,sc8280xp-adsp-pas")) {
174 		sc->sc_pas_id = 1;
175 		sc->sc_load_state = "adsp";
176 	}
177 	if (OF_is_compatible(faa->fa_node, "qcom,sc8280xp-nsp0-pas")) {
178 		sc->sc_pas_id = 18;
179 	}
180 	if (OF_is_compatible(faa->fa_node, "qcom,sc8280xp-nsp1-pas")) {
181 		sc->sc_pas_id = 30;
182 	}
183 
184 	if (OF_is_compatible(faa->fa_node, "qcom,x1e80100-adsp-pas")) {
185 		sc->sc_pas_id = 1;
186 		sc->sc_dtb_pas_id = 36;
187 		sc->sc_lite_pas_id = 31;
188 		sc->sc_load_state = "adsp";
189 	}
190 
191 	qcpas_intr_establish(sc, 0, "wdog", qcpas_intr_wdog);
192 	qcpas_intr_establish(sc, 1, "fatal", qcpas_intr_fatal);
193 	qcpas_intr_establish(sc, 2, "ready", qcpas_intr_ready);
194 	qcpas_intr_establish(sc, 3, "handover", qcpas_intr_handover);
195 	qcpas_intr_establish(sc, 4, "stop-ack", qcpas_intr_stop_ack);
196 	qcpas_intr_establish(sc, 5, "shutdown-ack", qcpas_intr_shutdown_ack);
197 
198 	printf("\n");
199 
200 	config_mountroot(self, qcpas_mountroot);
201 }
202 
203 extern int qcaoss_send(char *, size_t);
204 
205 void
206 qcpas_mountroot(struct device *self)
207 {
208 	struct qcpas_softc *sc = (struct qcpas_softc *)self;
209 	char fwname[128];
210 	size_t fwlen, dtb_fwlen;
211 	u_char *fw, *dtb_fw;
212 	int node, ret;
213 	int error;
214 
215 	if (qcpas_map_memory(sc) != 0)
216 		return;
217 
218 	if (OF_getproplen(sc->sc_node, "firmware-name") <= 0)
219 		return;
220 	OF_getprop(sc->sc_node, "firmware-name", fwname, sizeof(fwname));
221 	fwname[sizeof(fwname) - 1] = '\0';
222 
223 	/* If we need a second firmware, make sure we have a name for it. */
224 	if (sc->sc_dtb_pas_id && strlen(fwname) == sizeof(fwname) - 1)
225 		return;
226 
227 	error = loadfirmware(fwname, &fw, &fwlen);
228 	if (error) {
229 		printf("%s: failed to load %s: %d\n",
230 		    sc->sc_dev.dv_xname, fwname, error);
231 		return;
232 	}
233 
234 	if (sc->sc_lite_pas_id) {
235 		if (qcscm_pas_shutdown(sc->sc_lite_pas_id)) {
236 			printf("%s: failed to shutdown lite firmware\n",
237 			    sc->sc_dev.dv_xname);
238 		}
239 	}
240 
241 	if (sc->sc_dtb_pas_id) {
242 		error = loadfirmware(fwname + strlen(fwname) + 1,
243 		    &dtb_fw, &dtb_fwlen);
244 		if (error) {
245 			printf("%s: failed to load %s: %d\n",
246 			    sc->sc_dev.dv_xname, fwname, error);
247 			return;
248 		}
249 	}
250 
251 	if (sc->sc_load_state) {
252 		char buf[64];
253 		snprintf(buf, sizeof(buf),
254 		    "{class: image, res: load_state, name: %s, val: on}",
255 		    sc->sc_load_state);
256 		ret = qcaoss_send(buf, sizeof(buf));
257 		if (ret != 0) {
258 			printf("%s: failed to toggle load state\n",
259 			    sc->sc_dev.dv_xname);
260 			return;
261 		}
262 	}
263 
264 	power_domain_enable_all(sc->sc_node);
265 	clock_enable(sc->sc_node, "xo");
266 
267 	if (sc->sc_dtb_pas_id) {
268 		qcpas_mdt_init(sc, sc->sc_dtb_pas_id, dtb_fw, dtb_fwlen);
269 		free(dtb_fw, M_DEVBUF, dtb_fwlen);
270 	}
271 
272 	ret = qcpas_mdt_init(sc, sc->sc_pas_id, fw, fwlen);
273 	free(fw, M_DEVBUF, fwlen);
274 	if (ret != 0) {
275 		printf("%s: failed to boot coprocessor\n",
276 		    sc->sc_dev.dv_xname);
277 		return;
278 	}
279 
280 	node = OF_getnodebyname(sc->sc_node, "glink-edge");
281 	if (node)
282 		qcpas_glink_attach(sc, node);
283 
284 #ifndef SMALL_KERNEL
285 	strlcpy(sc->sc_sensdev.xname, sc->sc_dev.dv_xname,
286 	    sizeof(sc->sc_sensdev.xname));
287 
288 	strlcpy(sc->sc_sens[0].desc, "last full capacity",
289 	    sizeof(sc->sc_sens[0].desc));
290 	sc->sc_sens[0].type = SENSOR_WATTHOUR;
291 	sc->sc_sens[0].flags = SENSOR_FUNKNOWN;
292 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[0]);
293 
294 	strlcpy(sc->sc_sens[1].desc, "warning capacity",
295 	    sizeof(sc->sc_sens[1].desc));
296 	sc->sc_sens[1].type = SENSOR_WATTHOUR;
297 	sc->sc_sens[1].flags = SENSOR_FUNKNOWN;
298 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[1]);
299 
300 	strlcpy(sc->sc_sens[2].desc, "low capacity",
301 	    sizeof(sc->sc_sens[2].desc));
302 	sc->sc_sens[2].type = SENSOR_WATTHOUR;
303 	sc->sc_sens[2].flags = SENSOR_FUNKNOWN;
304 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[2]);
305 
306 	strlcpy(sc->sc_sens[3].desc, "voltage", sizeof(sc->sc_sens[3].desc));
307 	sc->sc_sens[3].type = SENSOR_VOLTS_DC;
308 	sc->sc_sens[3].flags = SENSOR_FUNKNOWN;
309 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[3]);
310 
311 	strlcpy(sc->sc_sens[4].desc, "battery unknown",
312 	    sizeof(sc->sc_sens[4].desc));
313 	sc->sc_sens[4].type = SENSOR_INTEGER;
314 	sc->sc_sens[4].flags = SENSOR_FUNKNOWN;
315 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[4]);
316 
317 	strlcpy(sc->sc_sens[5].desc, "rate", sizeof(sc->sc_sens[5].desc));
318 	sc->sc_sens[5].type =SENSOR_WATTS;
319 	sc->sc_sens[5].flags = SENSOR_FUNKNOWN;
320 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[5]);
321 
322 	strlcpy(sc->sc_sens[6].desc, "remaining capacity",
323 	    sizeof(sc->sc_sens[6].desc));
324 	sc->sc_sens[6].type = SENSOR_WATTHOUR;
325 	sc->sc_sens[6].flags = SENSOR_FUNKNOWN;
326 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[6]);
327 
328 	strlcpy(sc->sc_sens[7].desc, "current voltage",
329 	    sizeof(sc->sc_sens[7].desc));
330 	sc->sc_sens[7].type = SENSOR_VOLTS_DC;
331 	sc->sc_sens[7].flags = SENSOR_FUNKNOWN;
332 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[7]);
333 
334 	strlcpy(sc->sc_sens[8].desc, "design capacity",
335 	    sizeof(sc->sc_sens[8].desc));
336 	sc->sc_sens[8].type = SENSOR_WATTHOUR;
337 	sc->sc_sens[8].flags = SENSOR_FUNKNOWN;
338 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[8]);
339 
340 	strlcpy(sc->sc_sens[9].desc, "discharge cycles",
341 	    sizeof(sc->sc_sens[9].desc));
342 	sc->sc_sens[9].type = SENSOR_INTEGER;
343 	sc->sc_sens[9].flags = SENSOR_FUNKNOWN;
344 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[9]);
345 
346 	strlcpy(sc->sc_sens[10].desc, "temperature",
347 	    sizeof(sc->sc_sens[10].desc));
348 	sc->sc_sens[10].type = SENSOR_TEMP;
349 	sc->sc_sens[10].flags = SENSOR_FUNKNOWN;
350 	sensor_attach(&sc->sc_sensdev, &sc->sc_sens[10]);
351 
352 	sensordev_install(&sc->sc_sensdev);
353 #endif
354 }
355 
356 int
357 qcpas_map_memory(struct qcpas_softc *sc)
358 {
359 	uint32_t memreg[2] = {};
360 	uint32_t reg[4];
361 	size_t off;
362 	int node;
363 	int i;
364 
365 	OF_getpropintarray(sc->sc_node, "memory-region",
366 	    memreg, sizeof(memreg));
367 	if (memreg[0] == 0)
368 		return EINVAL;
369 
370 	for (i = 0; i < nitems(memreg); i++) {
371 		if (memreg[i] == 0)
372 			break;
373 		node = OF_getnodebyphandle(memreg[i]);
374 		if (node == 0)
375 			return EINVAL;
376 		if (OF_getpropintarray(node, "reg", reg,
377 		    sizeof(reg)) != sizeof(reg))
378 			return EINVAL;
379 
380 		sc->sc_mem_phys[i] = (uint64_t)reg[0] << 32 | reg[1];
381 		KASSERT((sc->sc_mem_phys[i] & PAGE_MASK) == 0);
382 		sc->sc_mem_size[i] = (uint64_t)reg[2] << 32 | reg[3];
383 		KASSERT((sc->sc_mem_size[i] & PAGE_MASK) == 0);
384 
385 		sc->sc_mem_region[i] = km_alloc(sc->sc_mem_size[i],
386 		    &kv_any, &kp_none, &kd_nowait);
387 		if (!sc->sc_mem_region[i])
388 			return ENOMEM;
389 
390 		for (off = 0; off < sc->sc_mem_size[i]; off += PAGE_SIZE) {
391 			pmap_kenter_cache((vaddr_t)sc->sc_mem_region[i] + off,
392 			    sc->sc_mem_phys[i] + off, PROT_READ | PROT_WRITE,
393 			    PMAP_CACHE_DEV_NGNRNE);
394 		}
395 	}
396 
397 	return 0;
398 }
399 
400 int
401 qcpas_mdt_init(struct qcpas_softc *sc, int pas_id, u_char *fw, size_t fwlen)
402 {
403 	Elf32_Ehdr *ehdr;
404 	Elf32_Phdr *phdr;
405 	paddr_t minpa = -1, maxpa = 0;
406 	int i, hashseg = 0, relocate = 0;
407 	int error;
408 	ssize_t off;
409 	int idx;
410 
411 	if (pas_id == sc->sc_dtb_pas_id)
412 		idx = 1;
413 	else
414 		idx = 0;
415 
416 	ehdr = (Elf32_Ehdr *)fw;
417 	phdr = (Elf32_Phdr *)&ehdr[1];
418 
419 	if (ehdr->e_phnum < 2 || phdr[0].p_type == PT_LOAD)
420 		return EINVAL;
421 
422 	for (i = 0; i < ehdr->e_phnum; i++) {
423 		if ((phdr[i].p_flags & MDT_TYPE_MASK) == MDT_TYPE_HASH) {
424 			if (i > 0 && !hashseg)
425 				hashseg = i;
426 			continue;
427 		}
428 		if (phdr[i].p_type != PT_LOAD || phdr[i].p_memsz == 0)
429 			continue;
430 		if (phdr[i].p_flags & MDT_RELOCATABLE)
431 			relocate = 1;
432 		if (phdr[i].p_paddr < minpa)
433 			minpa = phdr[i].p_paddr;
434 		if (phdr[i].p_paddr + phdr[i].p_memsz > maxpa)
435 			maxpa =
436 			    roundup(phdr[i].p_paddr + phdr[i].p_memsz,
437 			    PAGE_SIZE);
438 	}
439 
440 	if (!hashseg)
441 		return EINVAL;
442 
443 	sc->sc_metadata[idx] = qcpas_dmamem_alloc(sc, phdr[0].p_filesz +
444 	    phdr[hashseg].p_filesz, PAGE_SIZE);
445 	if (sc->sc_metadata[idx] == NULL)
446 		return EINVAL;
447 
448 	memcpy(QCPAS_DMA_KVA(sc->sc_metadata[idx]), fw, phdr[0].p_filesz);
449 	if (phdr[0].p_filesz + phdr[hashseg].p_filesz == fwlen) {
450 		memcpy(QCPAS_DMA_KVA(sc->sc_metadata[idx]) + phdr[0].p_filesz,
451 		    fw + phdr[0].p_filesz, phdr[hashseg].p_filesz);
452 	} else if (phdr[hashseg].p_offset + phdr[hashseg].p_filesz <= fwlen) {
453 		memcpy(QCPAS_DMA_KVA(sc->sc_metadata[idx]) + phdr[0].p_filesz,
454 		    fw + phdr[hashseg].p_offset, phdr[hashseg].p_filesz);
455 	} else {
456 		printf("%s: metadata split segment not supported\n",
457 		    sc->sc_dev.dv_xname);
458 		return EINVAL;
459 	}
460 
461 	membar_producer();
462 
463 	if (qcscm_pas_init_image(pas_id,
464 	    QCPAS_DMA_DVA(sc->sc_metadata[idx])) != 0) {
465 		printf("%s: init image failed\n", sc->sc_dev.dv_xname);
466 		qcpas_dmamem_free(sc, sc->sc_metadata[idx]);
467 		return EINVAL;
468 	}
469 
470 	if (qcscm_pas_mem_setup(pas_id,
471 	    sc->sc_mem_phys[idx], maxpa - minpa) != 0) {
472 		printf("%s: mem setup failed\n", sc->sc_dev.dv_xname);
473 		qcpas_dmamem_free(sc, sc->sc_metadata[idx]);
474 		return EINVAL;
475 	}
476 
477 	sc->sc_mem_reloc[idx] = relocate ? minpa : sc->sc_mem_phys[idx];
478 
479 	for (i = 0; i < ehdr->e_phnum; i++) {
480 		if ((phdr[i].p_flags & MDT_TYPE_MASK) == MDT_TYPE_HASH ||
481 		    phdr[i].p_type != PT_LOAD || phdr[i].p_memsz == 0)
482 			continue;
483 		off = phdr[i].p_paddr - sc->sc_mem_reloc[idx];
484 		if (off < 0 || off + phdr[i].p_memsz > sc->sc_mem_size[0])
485 			return EINVAL;
486 		if (phdr[i].p_filesz > phdr[i].p_memsz)
487 			return EINVAL;
488 
489 		if (phdr[i].p_filesz && phdr[i].p_offset < fwlen &&
490 		    phdr[i].p_offset + phdr[i].p_filesz <= fwlen) {
491 			memcpy(sc->sc_mem_region[idx] + off,
492 			    fw + phdr[i].p_offset, phdr[i].p_filesz);
493 		} else if (phdr[i].p_filesz) {
494 			printf("%s: firmware split segment not supported\n",
495 			    sc->sc_dev.dv_xname);
496 			return EINVAL;
497 		}
498 
499 		if (phdr[i].p_memsz > phdr[i].p_filesz)
500 			memset(sc->sc_mem_region[idx] + off + phdr[i].p_filesz,
501 			    0, phdr[i].p_memsz - phdr[i].p_filesz);
502 	}
503 
504 	membar_producer();
505 
506 	if (qcscm_pas_auth_and_reset(pas_id) != 0) {
507 		printf("%s: auth and reset failed\n", sc->sc_dev.dv_xname);
508 		qcpas_dmamem_free(sc, sc->sc_metadata[idx]);
509 		return EINVAL;
510 	}
511 
512 	if (pas_id == sc->sc_dtb_pas_id)
513 		return 0;
514 
515 	error = tsleep_nsec(sc, PWAIT, "qcpas", SEC_TO_NSEC(5));
516 	if (error) {
517 		printf("%s: failed to receive ready signal\n",
518 		    sc->sc_dev.dv_xname);
519 		return error;
520 	}
521 
522 	/* XXX: free metadata ? */
523 
524 	return 0;
525 }
526 
527 struct qcpas_dmamem *
528 qcpas_dmamem_alloc(struct qcpas_softc *sc, bus_size_t size, bus_size_t align)
529 {
530 	struct qcpas_dmamem *tdm;
531 	int nsegs;
532 
533 	tdm = malloc(sizeof(*tdm), M_DEVBUF, M_WAITOK | M_ZERO);
534 	tdm->tdm_size = size;
535 
536 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
537 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &tdm->tdm_map) != 0)
538 		goto tdmfree;
539 
540 	if (bus_dmamem_alloc_range(sc->sc_dmat, size, align, 0,
541 	    &tdm->tdm_seg, 1, &nsegs, BUS_DMA_WAITOK, 0, 0xffffffff) != 0)
542 		goto destroy;
543 
544 	if (bus_dmamem_map(sc->sc_dmat, &tdm->tdm_seg, nsegs, size,
545 	    &tdm->tdm_kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0)
546 		goto free;
547 
548 	if (bus_dmamap_load(sc->sc_dmat, tdm->tdm_map, tdm->tdm_kva, size,
549 	    NULL, BUS_DMA_WAITOK) != 0)
550 		goto unmap;
551 
552 	bzero(tdm->tdm_kva, size);
553 
554 	return (tdm);
555 
556 unmap:
557 	bus_dmamem_unmap(sc->sc_dmat, tdm->tdm_kva, size);
558 free:
559 	bus_dmamem_free(sc->sc_dmat, &tdm->tdm_seg, 1);
560 destroy:
561 	bus_dmamap_destroy(sc->sc_dmat, tdm->tdm_map);
562 tdmfree:
563 	free(tdm, M_DEVBUF, 0);
564 
565 	return (NULL);
566 }
567 
568 void
569 qcpas_dmamem_free(struct qcpas_softc *sc, struct qcpas_dmamem *tdm)
570 {
571 	bus_dmamem_unmap(sc->sc_dmat, tdm->tdm_kva, tdm->tdm_size);
572 	bus_dmamem_free(sc->sc_dmat, &tdm->tdm_seg, 1);
573 	bus_dmamap_destroy(sc->sc_dmat, tdm->tdm_map);
574 	free(tdm, M_DEVBUF, 0);
575 }
576 
577 void
578 qcpas_intr_establish(struct qcpas_softc *sc, int i, char *name, void *handler)
579 {
580 	int idx;
581 
582 	idx = OF_getindex(sc->sc_node, name, "interrupt-names");
583 	if (idx >= 0)
584 		sc->sc_ih[i] =
585 		    fdt_intr_establish_idx(sc->sc_node, idx, IPL_BIO,
586 		    handler, sc, sc->sc_dev.dv_xname);
587 }
588 
589 int
590 qcpas_intr_wdog(void *cookie)
591 {
592 	return 0;
593 }
594 
595 int
596 qcpas_intr_fatal(void *cookie)
597 {
598 	return 0;
599 }
600 
601 int
602 qcpas_intr_ready(void *cookie)
603 {
604 	struct qcpas_softc *sc = cookie;
605 
606 	wakeup(sc);
607 	return 0;
608 }
609 
610 int
611 qcpas_intr_handover(void *cookie)
612 {
613 	return 0;
614 }
615 
616 int
617 qcpas_intr_stop_ack(void *cookie)
618 {
619 	return 0;
620 }
621 
622 int
623 qcpas_intr_shutdown_ack(void *cookie)
624 {
625 	return 0;
626 }
627 
628 /* GLINK */
629 
630 #define SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR	478
631 #define SMEM_GLINK_NATIVE_XPRT_FIFO_0		479
632 #define SMEM_GLINK_NATIVE_XPRT_FIFO_1		480
633 
634 struct glink_msg {
635 	uint16_t cmd;
636 	uint16_t param1;
637 	uint32_t param2;
638 	uint8_t data[];
639 } __packed;
640 
641 struct qcpas_glink_intent_pair {
642 	uint32_t size;
643 	uint32_t iid;
644 } __packed;
645 
646 struct qcpas_glink_intent {
647 	TAILQ_ENTRY(qcpas_glink_intent) it_q;
648 	uint32_t it_id;
649 	uint32_t it_size;
650 	int it_inuse;
651 };
652 
653 struct qcpas_glink_channel {
654 	TAILQ_ENTRY(qcpas_glink_channel) ch_q;
655 	struct qcpas_softc *ch_sc;
656 	struct qcpas_glink_protocol *ch_proto;
657 	uint32_t ch_rcid;
658 	uint32_t ch_lcid;
659 	uint32_t ch_max_intent;
660 	TAILQ_HEAD(,qcpas_glink_intent) ch_l_intents;
661 	TAILQ_HEAD(,qcpas_glink_intent) ch_r_intents;
662 };
663 
664 #define GLINK_CMD_VERSION		0
665 #define GLINK_CMD_VERSION_ACK		1
666 #define  GLINK_VERSION				1
667 #define  GLINK_FEATURE_INTENT_REUSE		(1 << 0)
668 #define GLINK_CMD_OPEN			2
669 #define GLINK_CMD_CLOSE			3
670 #define GLINK_CMD_OPEN_ACK		4
671 #define GLINK_CMD_INTENT		5
672 #define GLINK_CMD_RX_DONE		6
673 #define GLINK_CMD_RX_INTENT_REQ		7
674 #define GLINK_CMD_RX_INTENT_REQ_ACK	8
675 #define GLINK_CMD_TX_DATA		9
676 #define GLINK_CMD_CLOSE_ACK		11
677 #define GLINK_CMD_TX_DATA_CONT		12
678 #define GLINK_CMD_READ_NOTIF		13
679 #define GLINK_CMD_RX_DONE_W_REUSE	14
680 
681 void	qcpas_glink_recv(void *);
682 int	qcpas_glink_intr(void *);
683 
684 void	qcpas_glink_tx(struct qcpas_softc *, uint8_t *, int);
685 void	qcpas_glink_tx_commit(struct qcpas_softc *);
686 void	qcpas_glink_rx(struct qcpas_softc *, uint8_t *, int);
687 void	qcpas_glink_rx_commit(struct qcpas_softc *);
688 
689 void	qcpas_glink_send(void *, void *, int);
690 
691 extern int qcsmem_alloc(int, int, int);
692 extern void *qcsmem_get(int, int, int *);
693 
694 int	qcpas_pmic_rtr_init(void *);
695 int	qcpas_pmic_rtr_recv(void *, uint8_t *, int);
696 int	qcpas_pmic_rtr_apminfo(struct apm_power_info *);
697 
698 struct qcpas_glink_protocol {
699 	char *name;
700 	int (*init)(void *cookie);
701 	int (*recv)(void *cookie, uint8_t *buf, int len);
702 } qcpas_glink_protocols[] = {
703 	{ "PMIC_RTR_ADSP_APPS", qcpas_pmic_rtr_init , qcpas_pmic_rtr_recv },
704 };
705 
706 void
707 qcpas_glink_attach(struct qcpas_softc *sc, int node)
708 {
709 	uint32_t remote;
710 	uint32_t *descs;
711 	int size;
712 
713 	remote = OF_getpropint(node, "qcom,remote-pid", -1);
714 	if (remote == -1)
715 		return;
716 
717 	if (qcsmem_alloc(remote, SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR, 32) != 0 ||
718 	    qcsmem_alloc(remote, SMEM_GLINK_NATIVE_XPRT_FIFO_0, 16384) != 0)
719 		return;
720 
721 	descs = qcsmem_get(remote, SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR, &size);
722 	if (descs == NULL || size != 32)
723 		return;
724 
725 	sc->sc_tx_tail = &descs[0];
726 	sc->sc_tx_head = &descs[1];
727 	sc->sc_rx_tail = &descs[2];
728 	sc->sc_rx_head = &descs[3];
729 
730 	sc->sc_tx_fifo = qcsmem_get(remote, SMEM_GLINK_NATIVE_XPRT_FIFO_0,
731 	    &sc->sc_tx_fifolen);
732 	if (sc->sc_tx_fifo == NULL)
733 		return;
734 	sc->sc_rx_fifo = qcsmem_get(remote, SMEM_GLINK_NATIVE_XPRT_FIFO_1,
735 	    &sc->sc_rx_fifolen);
736 	if (sc->sc_rx_fifo == NULL)
737 		return;
738 
739 	sc->sc_mc = mbox_channel_idx(node, 0, NULL);
740 	if (sc->sc_mc == NULL)
741 		return;
742 
743 	TAILQ_INIT(&sc->sc_glink_channels);
744 	task_set(&sc->sc_glink_rx, qcpas_glink_recv, sc);
745 
746 	sc->sc_glink_ih = fdt_intr_establish(node, IPL_BIO,
747 	    qcpas_glink_intr, sc, sc->sc_dev.dv_xname);
748 	if (sc->sc_glink_ih == NULL)
749 		return;
750 
751 	/* Expect peer to send initial message */
752 }
753 
754 void
755 qcpas_glink_rx(struct qcpas_softc *sc, uint8_t *buf, int len)
756 {
757 	uint32_t head, tail;
758 	int avail;
759 
760 	head = *sc->sc_rx_head;
761 	tail = *sc->sc_rx_tail + sc->sc_rx_off;
762 	if (tail >= sc->sc_rx_fifolen)
763 		tail -= sc->sc_rx_fifolen;
764 
765 	/* Checked by caller */
766 	KASSERT(head != tail);
767 
768 	if (head >= tail)
769 		avail = head - tail;
770 	else
771 		avail = (sc->sc_rx_fifolen - tail) + head;
772 
773 	/* Dumb, but should do. */
774 	KASSERT(avail >= len);
775 
776 	while (len > 0) {
777 		*buf = sc->sc_rx_fifo[tail];
778 		tail++;
779 		if (tail >= sc->sc_rx_fifolen)
780 			tail -= sc->sc_rx_fifolen;
781 		buf++;
782 		sc->sc_rx_off++;
783 		len--;
784 	}
785 }
786 
787 void
788 qcpas_glink_rx_commit(struct qcpas_softc *sc)
789 {
790 	uint32_t tail;
791 
792 	tail = *sc->sc_rx_tail + roundup(sc->sc_rx_off, 8);
793 	if (tail >= sc->sc_rx_fifolen)
794 		tail -= sc->sc_rx_fifolen;
795 
796 	membar_producer();
797 	*sc->sc_rx_tail = tail;
798 	sc->sc_rx_off = 0;
799 }
800 
801 void
802 qcpas_glink_tx(struct qcpas_softc *sc, uint8_t *buf, int len)
803 {
804 	uint32_t head, tail;
805 	int avail;
806 
807 	head = *sc->sc_tx_head + sc->sc_tx_off;
808 	if (head >= sc->sc_tx_fifolen)
809 		head -= sc->sc_tx_fifolen;
810 	tail = *sc->sc_tx_tail;
811 
812 	if (head < tail)
813 		avail = tail - head;
814 	else
815 		avail = (sc->sc_rx_fifolen - head) + tail;
816 
817 	/* Dumb, but should do. */
818 	KASSERT(avail >= len);
819 
820 	while (len > 0) {
821 		sc->sc_tx_fifo[head] = *buf;
822 		head++;
823 		if (head >= sc->sc_tx_fifolen)
824 			head -= sc->sc_tx_fifolen;
825 		buf++;
826 		sc->sc_tx_off++;
827 		len--;
828 	}
829 }
830 
831 void
832 qcpas_glink_tx_commit(struct qcpas_softc *sc)
833 {
834 	uint32_t head;
835 
836 	head = *sc->sc_tx_head + roundup(sc->sc_tx_off, 8);
837 	if (head >= sc->sc_tx_fifolen)
838 		head -= sc->sc_tx_fifolen;
839 
840 	membar_producer();
841 	*sc->sc_tx_head = head;
842 	sc->sc_tx_off = 0;
843 	mbox_send(sc->sc_mc, NULL, 0);
844 }
845 
846 void
847 qcpas_glink_send(void *cookie, void *buf, int len)
848 {
849 	struct qcpas_glink_channel *ch = cookie;
850 	struct qcpas_softc *sc = ch->ch_sc;
851 	struct qcpas_glink_intent *it;
852 	struct glink_msg msg;
853 	uint32_t chunk_size, left_size;
854 
855 	TAILQ_FOREACH(it, &ch->ch_r_intents, it_q) {
856 		if (!it->it_inuse)
857 			break;
858 		if (it->it_size < len)
859 			continue;
860 	}
861 	if (it == NULL) {
862 		printf("%s: all intents in use\n",
863 		    sc->sc_dev.dv_xname);
864 		return;
865 	}
866 	it->it_inuse = 1;
867 
868 	msg.cmd = GLINK_CMD_TX_DATA;
869 	msg.param1 = ch->ch_lcid;
870 	msg.param2 = it->it_id;
871 
872 	chunk_size = len;
873 	left_size = 0;
874 
875 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
876 	qcpas_glink_tx(sc, (char *)&chunk_size, sizeof(chunk_size));
877 	qcpas_glink_tx(sc, (char *)&left_size, sizeof(left_size));
878 	qcpas_glink_tx(sc, buf, len);
879 	qcpas_glink_tx_commit(sc);
880 }
881 
882 void
883 qcpas_glink_recv_version(struct qcpas_softc *sc, uint32_t version,
884     uint32_t features)
885 {
886 	struct glink_msg msg;
887 
888 	if (version != GLINK_VERSION) {
889 		printf("%s: unsupported glink version %u\n",
890 		    sc->sc_dev.dv_xname, version);
891 		return;
892 	}
893 
894 	msg.cmd = GLINK_CMD_VERSION_ACK;
895 	msg.param1 = GLINK_VERSION;
896 	msg.param2 = features & GLINK_FEATURE_INTENT_REUSE;
897 
898 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
899 	qcpas_glink_tx_commit(sc);
900 }
901 
902 void
903 qcpas_glink_recv_open(struct qcpas_softc *sc, uint32_t rcid, uint32_t namelen)
904 {
905 	struct qcpas_glink_protocol *proto = NULL;
906 	struct qcpas_glink_channel *ch;
907 	struct glink_msg msg;
908 	char *name;
909 	int i, err;
910 
911 	name = malloc(namelen, M_TEMP, M_WAITOK);
912 	qcpas_glink_rx(sc, name, namelen);
913 	qcpas_glink_rx_commit(sc);
914 
915 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
916 		if (ch->ch_rcid == rcid) {
917 			printf("%s: duplicate open for %s\n",
918 			    sc->sc_dev.dv_xname, name);
919 			free(name, M_TEMP, namelen);
920 			return;
921 		}
922 	}
923 
924 	for (i = 0; i < nitems(qcpas_glink_protocols); i++) {
925 		if (strcmp(qcpas_glink_protocols[i].name, name) != 0)
926 			continue;
927 		proto = &qcpas_glink_protocols[i];
928 		break;
929 	}
930 	if (proto == NULL) {
931 		free(name, M_TEMP, namelen);
932 		return;
933 	}
934 
935 	ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
936 	ch->ch_sc = sc;
937 	ch->ch_proto = proto;
938 	ch->ch_rcid = rcid;
939 	ch->ch_lcid = ++sc->sc_glink_max_channel;
940 	TAILQ_INIT(&ch->ch_l_intents);
941 	TAILQ_INIT(&ch->ch_r_intents);
942 	TAILQ_INSERT_TAIL(&sc->sc_glink_channels, ch, ch_q);
943 
944 	/* Assume we can leave HW dangling if proto init fails */
945 	err = proto->init(ch);
946 	if (err) {
947 		TAILQ_REMOVE(&sc->sc_glink_channels, ch, ch_q);
948 		free(ch, M_TEMP, sizeof(*ch));
949 		free(name, M_TEMP, namelen);
950 		return;
951 	}
952 
953 	msg.cmd = GLINK_CMD_OPEN_ACK;
954 	msg.param1 = ch->ch_rcid;
955 	msg.param2 = 0;
956 
957 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
958 	qcpas_glink_tx_commit(sc);
959 
960 	msg.cmd = GLINK_CMD_OPEN;
961 	msg.param1 = ch->ch_lcid;
962 	msg.param2 = strlen(name) + 1;
963 
964 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
965 	qcpas_glink_tx(sc, name, strlen(name) + 1);
966 	qcpas_glink_tx_commit(sc);
967 
968 	free(name, M_TEMP, namelen);
969 }
970 
971 void
972 qcpas_glink_recv_open_ack(struct qcpas_softc *sc, uint32_t lcid)
973 {
974 	struct qcpas_glink_channel *ch;
975 	struct glink_msg msg;
976 	struct qcpas_glink_intent_pair intent;
977 	int i;
978 
979 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
980 		if (ch->ch_lcid == lcid)
981 			break;
982 	}
983 	if (ch == NULL) {
984 		printf("%s: unknown channel %u for OPEN_ACK\n",
985 		    sc->sc_dev.dv_xname, lcid);
986 		return;
987 	}
988 
989 	/* Respond with default intent now that channel is open */
990 	for (i = 0; i < 5; i++) {
991 		struct qcpas_glink_intent *it;
992 
993 		it = malloc(sizeof(*it), M_DEVBUF, M_WAITOK | M_ZERO);
994 		it->it_id = ++ch->ch_max_intent;
995 		it->it_size = 1024;
996 		TAILQ_INSERT_TAIL(&ch->ch_l_intents, it, it_q);
997 
998 		msg.cmd = GLINK_CMD_INTENT;
999 		msg.param1 = ch->ch_lcid;
1000 		msg.param2 = 1;
1001 		intent.size = it->it_size;
1002 		intent.iid = it->it_id;
1003 	}
1004 
1005 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
1006 	qcpas_glink_tx(sc, (char *)&intent, sizeof(intent));
1007 	qcpas_glink_tx_commit(sc);
1008 }
1009 
1010 void
1011 qcpas_glink_recv_intent(struct qcpas_softc *sc, uint32_t rcid, uint32_t count)
1012 {
1013 	struct qcpas_glink_intent_pair *intents;
1014 	struct qcpas_glink_channel *ch;
1015 	struct qcpas_glink_intent *it;
1016 	int i;
1017 
1018 	intents = malloc(sizeof(*intents) * count, M_TEMP, M_WAITOK);
1019 	qcpas_glink_rx(sc, (char *)intents, sizeof(*intents) * count);
1020 	qcpas_glink_rx_commit(sc);
1021 
1022 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
1023 		if (ch->ch_rcid == rcid)
1024 			break;
1025 	}
1026 	if (ch == NULL) {
1027 		printf("%s: unknown channel %u for INTENT\n",
1028 		    sc->sc_dev.dv_xname, rcid);
1029 		free(intents, M_TEMP, sizeof(*intents) * count);
1030 		return;
1031 	}
1032 
1033 	for (i = 0; i < count; i++) {
1034 		it = malloc(sizeof(*it), M_DEVBUF, M_WAITOK | M_ZERO);
1035 		it->it_id = intents[i].iid;
1036 		it->it_size = intents[i].size;
1037 		TAILQ_INSERT_TAIL(&ch->ch_r_intents, it, it_q);
1038 	}
1039 
1040 	free(intents, M_TEMP, sizeof(*intents) * count);
1041 }
1042 
1043 void
1044 qcpas_glink_recv_tx_data(struct qcpas_softc *sc, uint32_t rcid, uint32_t liid)
1045 {
1046 	struct qcpas_glink_channel *ch;
1047 	struct qcpas_glink_intent *it;
1048 	struct glink_msg msg;
1049 	uint32_t chunk_size, left_size;
1050 	char *buf;
1051 
1052 	qcpas_glink_rx(sc, (char *)&chunk_size, sizeof(chunk_size));
1053 	qcpas_glink_rx(sc, (char *)&left_size, sizeof(left_size));
1054 	qcpas_glink_rx_commit(sc);
1055 
1056 	buf = malloc(chunk_size, M_TEMP, M_WAITOK);
1057 	qcpas_glink_rx(sc, buf, chunk_size);
1058 	qcpas_glink_rx_commit(sc);
1059 
1060 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
1061 		if (ch->ch_rcid == rcid)
1062 			break;
1063 	}
1064 	if (ch == NULL) {
1065 		printf("%s: unknown channel %u for TX_DATA\n",
1066 		    sc->sc_dev.dv_xname, rcid);
1067 		free(buf, M_TEMP, chunk_size);
1068 		return;
1069 	}
1070 
1071 	TAILQ_FOREACH(it, &ch->ch_l_intents, it_q) {
1072 		if (it->it_id == liid)
1073 			break;
1074 	}
1075 	if (it == NULL) {
1076 		printf("%s: unknown intent %u for TX_DATA\n",
1077 		    sc->sc_dev.dv_xname, liid);
1078 		free(buf, M_TEMP, chunk_size);
1079 		return;
1080 	}
1081 
1082 	/* FIXME: handle message chunking */
1083 	KASSERT(left_size == 0);
1084 
1085 	ch->ch_proto->recv(ch, buf, chunk_size);
1086 	free(buf, M_TEMP, chunk_size);
1087 
1088 	if (!left_size) {
1089 		msg.cmd = GLINK_CMD_RX_DONE_W_REUSE;
1090 		msg.param1 = ch->ch_lcid;
1091 		msg.param2 = it->it_id;
1092 
1093 		qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
1094 		qcpas_glink_tx_commit(sc);
1095 	}
1096 }
1097 
1098 void
1099 qcpas_glink_recv_rx_done(struct qcpas_softc *sc, uint32_t rcid, uint32_t riid,
1100     int reuse)
1101 {
1102 	struct qcpas_glink_channel *ch;
1103 	struct qcpas_glink_intent *it;
1104 
1105 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
1106 		if (ch->ch_rcid == rcid)
1107 			break;
1108 	}
1109 	if (ch == NULL) {
1110 		printf("%s: unknown channel %u for RX_DONE\n",
1111 		    sc->sc_dev.dv_xname, rcid);
1112 		return;
1113 	}
1114 
1115 	TAILQ_FOREACH(it, &ch->ch_r_intents, it_q) {
1116 		if (it->it_id == riid)
1117 			break;
1118 	}
1119 	if (it == NULL) {
1120 		printf("%s: unknown intent %u for RX_DONE\n",
1121 		    sc->sc_dev.dv_xname, riid);
1122 		return;
1123 	}
1124 
1125 	/* FIXME: handle non-reuse */
1126 	KASSERT(reuse);
1127 
1128 	KASSERT(it->it_inuse);
1129 	it->it_inuse = 0;
1130 }
1131 
1132 void
1133 qcpas_glink_recv(void *cookie)
1134 {
1135 	struct qcpas_softc *sc = cookie;
1136 	struct glink_msg msg;
1137 
1138 	while (*sc->sc_rx_tail != *sc->sc_rx_head) {
1139 		membar_consumer();
1140 		qcpas_glink_rx(sc, (uint8_t *)&msg, sizeof(msg));
1141 		qcpas_glink_rx_commit(sc);
1142 
1143 		switch (msg.cmd) {
1144 		case GLINK_CMD_VERSION:
1145 			qcpas_glink_recv_version(sc, msg.param1, msg.param2);
1146 			break;
1147 		case GLINK_CMD_OPEN:
1148 			qcpas_glink_recv_open(sc, msg.param1, msg.param2);
1149 			break;
1150 		case GLINK_CMD_OPEN_ACK:
1151 			qcpas_glink_recv_open_ack(sc, msg.param1);
1152 			break;
1153 		case GLINK_CMD_INTENT:
1154 			qcpas_glink_recv_intent(sc, msg.param1, msg.param2);
1155 			break;
1156 		case GLINK_CMD_RX_INTENT_REQ:
1157 			/* Nothing to do so far */
1158 			break;
1159 		case GLINK_CMD_TX_DATA:
1160 			qcpas_glink_recv_tx_data(sc, msg.param1, msg.param2);
1161 			break;
1162 		case GLINK_CMD_RX_DONE:
1163 			qcpas_glink_recv_rx_done(sc, msg.param1, msg.param2, 0);
1164 			break;
1165 		case GLINK_CMD_RX_DONE_W_REUSE:
1166 			qcpas_glink_recv_rx_done(sc, msg.param1, msg.param2, 1);
1167 			break;
1168 		default:
1169 			printf("%s: unknown cmd %u\n", __func__, msg.cmd);
1170 			return;
1171 		}
1172 	}
1173 }
1174 
1175 int
1176 qcpas_glink_intr(void *cookie)
1177 {
1178 	struct qcpas_softc *sc = cookie;
1179 
1180 	task_add(systq, &sc->sc_glink_rx);
1181 	return 1;
1182 }
1183 
1184 /* GLINK PMIC Router */
1185 
1186 struct pmic_glink_hdr {
1187 	uint32_t owner;
1188 #define PMIC_GLINK_OWNER_BATTMGR	32778
1189 #define PMIC_GLINK_OWNER_USBC		32779
1190 #define PMIC_GLINK_OWNER_USBC_PAN	32780
1191 	uint32_t type;
1192 #define PMIC_GLINK_TYPE_REQ_RESP	1
1193 #define PMIC_GLINK_TYPE_NOTIFY		2
1194 	uint32_t opcode;
1195 };
1196 
1197 #define BATTMGR_OPCODE_BAT_STATUS		0x1
1198 #define BATTMGR_OPCODR_REQUEST_NOTIFICATION	0x4
1199 #define BATTMGR_OPCODE_NOTIF			0x7
1200 #define BATTMGR_OPCODE_BAT_INFO			0x9
1201 #define BATTMGR_OPCODE_BAT_DISCHARGE_TIME	0xc
1202 #define BATTMGR_OPCODE_BAT_CHARGE_TIME		0xd
1203 
1204 #define BATTMGR_NOTIF_BAT_PROPERTY		0x30
1205 #define BATTMGR_NOTIF_USB_PROPERTY		0x32
1206 #define BATTMGR_NOTIF_WLS_PROPERTY		0x34
1207 #define BATTMGR_NOTIF_BAT_STATUS		0x80
1208 #define BATTMGR_NOTIF_BAT_INFO			0x81
1209 
1210 #define BATTMGR_CHEMISTRY_LEN			4
1211 #define BATTMGR_STRING_LEN			128
1212 
1213 struct battmgr_bat_info {
1214 	uint32_t power_unit;
1215 	uint32_t design_capacity;
1216 	uint32_t last_full_capacity;
1217 	uint32_t battery_tech;
1218 	uint32_t design_voltage;
1219 	uint32_t capacity_low;
1220 	uint32_t capacity_warning;
1221 	uint32_t cycle_count;
1222 	uint32_t accuracy;
1223 	uint32_t max_sample_time_ms;
1224 	uint32_t min_sample_time_ms;
1225 	uint32_t max_average_interval_ms;
1226 	uint32_t min_average_interval_ms;
1227 	uint32_t capacity_granularity1;
1228 	uint32_t capacity_granularity2;
1229 	uint32_t swappable;
1230 	uint32_t capabilities;
1231 	char model_number[BATTMGR_STRING_LEN];
1232 	char serial_number[BATTMGR_STRING_LEN];
1233 	char battery_type[BATTMGR_STRING_LEN];
1234 	char oem_info[BATTMGR_STRING_LEN];
1235 	char battery_chemistry[BATTMGR_CHEMISTRY_LEN];
1236 	char uid[BATTMGR_STRING_LEN];
1237 	uint32_t critical_bias;
1238 	uint8_t day;
1239 	uint8_t month;
1240 	uint16_t year;
1241 	uint32_t battery_id;
1242 };
1243 
1244 struct battmgr_bat_status {
1245 	uint32_t battery_state;
1246 #define BATTMGR_BAT_STATE_DISCHARGE	(1 << 0)
1247 #define BATTMGR_BAT_STATE_CHARGING	(1 << 1)
1248 #define BATTMGR_BAT_STATE_CRITICAL_LOW	(1 << 2)
1249 	uint32_t capacity;
1250 	int32_t rate;
1251 	uint32_t battery_voltage;
1252 	uint32_t power_state;
1253 #define BATTMGR_PWR_STATE_AC_ON			(1 << 0)
1254 	uint32_t charging_source;
1255 #define BATTMGR_CHARGING_SOURCE_AC		1
1256 #define BATTMGR_CHARGING_SOURCE_USB		2
1257 #define BATTMGR_CHARGING_SOURCE_WIRELESS	3
1258 	uint32_t temperature;
1259 };
1260 
1261 void	qcpas_pmic_rtr_refresh(void *);
1262 void	qcpas_pmic_rtr_bat_info(struct qcpas_softc *,
1263 	    struct battmgr_bat_info *);
1264 void	qcpas_pmic_rtr_bat_status(struct qcpas_softc *,
1265 	    struct battmgr_bat_status *);
1266 
1267 void
1268 qcpas_pmic_rtr_battmgr_req_info(void *cookie)
1269 {
1270 	struct {
1271 		struct pmic_glink_hdr hdr;
1272 		uint32_t battery_id;
1273 	} msg;
1274 
1275 	msg.hdr.owner = PMIC_GLINK_OWNER_BATTMGR;
1276 	msg.hdr.type = PMIC_GLINK_TYPE_REQ_RESP;
1277 	msg.hdr.opcode = BATTMGR_OPCODE_BAT_INFO;
1278 	msg.battery_id = 0;
1279 	qcpas_glink_send(cookie, &msg, sizeof(msg));
1280 }
1281 
1282 void
1283 qcpas_pmic_rtr_battmgr_req_status(void *cookie)
1284 {
1285 	struct {
1286 		struct pmic_glink_hdr hdr;
1287 		uint32_t battery_id;
1288 	} msg;
1289 
1290 	msg.hdr.owner = PMIC_GLINK_OWNER_BATTMGR;
1291 	msg.hdr.type = PMIC_GLINK_TYPE_REQ_RESP;
1292 	msg.hdr.opcode = BATTMGR_OPCODE_BAT_STATUS;
1293 	msg.battery_id = 0;
1294 	qcpas_glink_send(cookie, &msg, sizeof(msg));
1295 }
1296 
1297 #if NAPM > 0
1298 struct apm_power_info qcpas_pmic_rtr_apm_power_info;
1299 void *qcpas_pmic_rtr_apm_cookie;
1300 #endif
1301 
1302 int
1303 qcpas_pmic_rtr_init(void *cookie)
1304 {
1305 #if NAPM > 0
1306 	struct apm_power_info *info;
1307 
1308 	info = &qcpas_pmic_rtr_apm_power_info;
1309 	info->battery_state = APM_BATT_UNKNOWN;
1310 	info->ac_state = APM_AC_UNKNOWN;
1311 	info->battery_life = 0;
1312 	info->minutes_left = -1;
1313 
1314 	qcpas_pmic_rtr_apm_cookie = cookie;
1315 	apm_setinfohook(qcpas_pmic_rtr_apminfo);
1316 #endif
1317 #ifndef SMALL_KERNEL
1318 	sensor_task_register(cookie, qcpas_pmic_rtr_refresh, 5);
1319 #endif
1320 	return 0;
1321 }
1322 
1323 int
1324 qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len)
1325 {
1326 	struct qcpas_glink_channel *ch = cookie;
1327 	struct qcpas_softc *sc = ch->ch_sc;
1328 	struct pmic_glink_hdr hdr;
1329 	uint32_t notification;
1330 
1331 	if (len < sizeof(hdr)) {
1332 		printf("%s: pmic glink message too small\n",
1333 		    __func__);
1334 		return 0;
1335 	}
1336 
1337 	memcpy(&hdr, buf, sizeof(hdr));
1338 
1339 	switch (hdr.owner) {
1340 	case PMIC_GLINK_OWNER_BATTMGR:
1341 		switch (hdr.opcode) {
1342 		case BATTMGR_OPCODE_NOTIF:
1343 			if (len - sizeof(hdr) != sizeof(uint32_t)) {
1344 				printf("%s: invalid battgmr notification\n",
1345 				    __func__);
1346 				return 0;
1347 			}
1348 			memcpy(&notification, buf + sizeof(hdr),
1349 			    sizeof(uint32_t));
1350 			switch (notification) {
1351 			case BATTMGR_NOTIF_BAT_INFO:
1352 				qcpas_pmic_rtr_battmgr_req_info(cookie);
1353 				/* FALLTHROUGH */
1354 			case BATTMGR_NOTIF_BAT_STATUS:
1355 			case BATTMGR_NOTIF_BAT_PROPERTY:
1356 				qcpas_pmic_rtr_battmgr_req_status(cookie);
1357 				break;
1358 			default:
1359 				printf("%s: unknown battmgr notification"
1360 				    " 0x%02x\n", __func__, notification);
1361 				break;
1362 			}
1363 			break;
1364 		case BATTMGR_OPCODE_BAT_INFO: {
1365 			struct battmgr_bat_info *bat;
1366 			if (len - sizeof(hdr) < sizeof(*bat)) {
1367 				printf("%s: invalid battgmr bat info\n",
1368 				    __func__);
1369 				return 0;
1370 			}
1371 			bat = malloc(sizeof(*bat), M_TEMP, M_WAITOK);
1372 			memcpy(bat, buf + sizeof(hdr), sizeof(*bat));
1373 			qcpas_pmic_rtr_bat_info(sc, bat);
1374 			free(bat, M_TEMP, sizeof(*bat));
1375 			break;
1376 		}
1377 		case BATTMGR_OPCODE_BAT_STATUS: {
1378 			struct battmgr_bat_status *bat;
1379 			if (len - sizeof(hdr) != sizeof(*bat)) {
1380 				printf("%s: invalid battgmr bat status\n",
1381 				    __func__);
1382 				return 0;
1383 			}
1384 			bat = malloc(sizeof(*bat), M_TEMP, M_WAITOK);
1385 			memcpy(bat, buf + sizeof(hdr), sizeof(*bat));
1386 			qcpas_pmic_rtr_bat_status(sc, bat);
1387 			free(bat, M_TEMP, sizeof(*bat));
1388 			break;
1389 		}
1390 		default:
1391 			printf("%s: unknown battmgr opcode 0x%02x\n",
1392 			    __func__, hdr.opcode);
1393 			break;
1394 		}
1395 		break;
1396 	default:
1397 		printf("%s: unknown pmic glink owner 0x%04x\n",
1398 		    __func__, hdr.owner);
1399 		break;
1400 	}
1401 
1402 	return 0;
1403 }
1404 
1405 #if NAPM > 0
1406 int
1407 qcpas_pmic_rtr_apminfo(struct apm_power_info *info)
1408 {
1409 	int error;
1410 
1411 	qcpas_pmic_rtr_battmgr_req_status(qcpas_pmic_rtr_apm_cookie);
1412 	error = tsleep_nsec(&qcpas_pmic_rtr_apm_power_info, PWAIT | PCATCH,
1413 	    "qcapm", SEC_TO_NSEC(5));
1414 	if (error)
1415 		return error;
1416 
1417 	memcpy(info, &qcpas_pmic_rtr_apm_power_info, sizeof(*info));
1418 	return 0;
1419 }
1420 #endif
1421 
1422 void
1423 qcpas_pmic_rtr_refresh(void *arg)
1424 {
1425 	qcpas_pmic_rtr_battmgr_req_status(arg);
1426 }
1427 
1428 void
1429 qcpas_pmic_rtr_bat_info(struct qcpas_softc *sc, struct battmgr_bat_info *bat)
1430 {
1431 #ifndef SMALL_KERNEL
1432 	sc->sc_last_full_capacity = bat->last_full_capacity;
1433 	sc->sc_warning_capacity = bat->capacity_warning;
1434 	sc->sc_low_capacity = bat->capacity_low;
1435 
1436 	sc->sc_sens[0].value = bat->last_full_capacity * 1000;
1437 	sc->sc_sens[0].flags &= ~SENSOR_FUNKNOWN;
1438 
1439 	sc->sc_sens[1].value = bat->capacity_warning * 1000;
1440 	sc->sc_sens[1].flags &= ~SENSOR_FUNKNOWN;
1441 
1442 	sc->sc_sens[2].value = bat->capacity_low * 1000;
1443 	sc->sc_sens[2].flags &= ~SENSOR_FUNKNOWN;
1444 
1445 	sc->sc_sens[3].value = bat->design_voltage * 1000;
1446 	sc->sc_sens[3].flags &= ~SENSOR_FUNKNOWN;
1447 
1448 	sc->sc_sens[8].value = bat->design_capacity * 1000;
1449 	sc->sc_sens[8].flags &= ~SENSOR_FUNKNOWN;
1450 
1451 	sc->sc_sens[9].value = bat->cycle_count;
1452 	sc->sc_sens[9].flags &= ~SENSOR_FUNKNOWN;
1453 #endif
1454 }
1455 
1456 void
1457 qcpas_pmic_rtr_bat_status(struct qcpas_softc *sc,
1458     struct battmgr_bat_status *bat)
1459 {
1460 #if NAPM > 0
1461 	extern int hw_power;
1462 	struct apm_power_info *info = &qcpas_pmic_rtr_apm_power_info;
1463 	uint32_t delta;
1464 	u_char nblife;
1465 #endif
1466 
1467 #ifndef SMALL_KERNEL
1468 	if (bat->capacity >= sc->sc_last_full_capacity)
1469 		strlcpy(sc->sc_sens[4].desc, "battery full",
1470 		    sizeof(sc->sc_sens[4].desc));
1471 	else if (bat->battery_state & BATTMGR_BAT_STATE_DISCHARGE)
1472 		strlcpy(sc->sc_sens[4].desc, "battery discharging",
1473 		    sizeof(sc->sc_sens[4].desc));
1474 	else if (bat->battery_state & BATTMGR_BAT_STATE_CHARGING)
1475 		strlcpy(sc->sc_sens[4].desc, "battery charging",
1476 		    sizeof(sc->sc_sens[4].desc));
1477 	else
1478 		strlcpy(sc->sc_sens[4].desc, "battery idle",
1479 		    sizeof(sc->sc_sens[4].desc));
1480 	if (bat->battery_state & BATTMGR_BAT_STATE_CRITICAL_LOW)
1481 		sc->sc_sens[4].status = SENSOR_S_CRIT;
1482 	else
1483 		sc->sc_sens[4].status = SENSOR_S_OK;
1484 	sc->sc_sens[4].value = bat->battery_state;
1485 	sc->sc_sens[4].flags &= ~SENSOR_FUNKNOWN;
1486 
1487 	sc->sc_sens[5].value = abs(bat->rate) * 1000;
1488 	sc->sc_sens[5].flags &= ~SENSOR_FUNKNOWN;
1489 
1490 	sc->sc_sens[6].value = bat->capacity * 1000;
1491 	if (bat->capacity < sc->sc_low_capacity)
1492 		sc->sc_sens[6].status = SENSOR_S_CRIT;
1493 	else if (bat->capacity < sc->sc_warning_capacity)
1494 		sc->sc_sens[6].status = SENSOR_S_WARN;
1495 	else
1496 		sc->sc_sens[6].status = SENSOR_S_OK;
1497 	sc->sc_sens[6].flags &= ~SENSOR_FUNKNOWN;
1498 
1499 	sc->sc_sens[7].value = bat->battery_voltage * 1000;
1500 	sc->sc_sens[7].flags &= ~SENSOR_FUNKNOWN;
1501 
1502 	sc->sc_sens[10].value = (bat->temperature * 10000) + 273150000;
1503 	sc->sc_sens[10].flags &= ~SENSOR_FUNKNOWN;
1504 #endif
1505 
1506 #if NAPM > 0
1507 	/* Needs BAT_INFO fist */
1508 	if (sc->sc_last_full_capacity == 0) {
1509 		wakeup(&qcpas_pmic_rtr_apm_power_info);
1510 		return;
1511 	}
1512 
1513 	nblife = ((bat->capacity * 100) / sc->sc_last_full_capacity);
1514 	if (info->battery_life != nblife)
1515 		apm_record_event(APM_POWER_CHANGE);
1516 	info->battery_life = nblife;
1517 	if (info->battery_life > 50)
1518 		info->battery_state = APM_BATT_HIGH;
1519 	else if (info->battery_life > 25)
1520 		info->battery_state = APM_BATT_LOW;
1521 	else
1522 		info->battery_state = APM_BATT_CRITICAL;
1523 	if (bat->battery_state & BATTMGR_BAT_STATE_CHARGING)
1524 		info->battery_state = APM_BATT_CHARGING;
1525 	else if (bat->battery_state & BATTMGR_BAT_STATE_CRITICAL_LOW)
1526 		info->battery_state = APM_BATT_CRITICAL;
1527 
1528 	if (bat->rate < 0)
1529 		delta = bat->capacity;
1530 	else
1531 		delta = sc->sc_last_full_capacity - bat->capacity;
1532 	if (bat->rate == 0)
1533 		info->minutes_left = -1;
1534 	else
1535 		info->minutes_left = (60 * delta) / abs(bat->rate);
1536 
1537 	if (bat->power_state & BATTMGR_PWR_STATE_AC_ON) {
1538 		if (info->ac_state != APM_AC_ON)
1539 			apm_record_event(APM_POWER_CHANGE);
1540 		info->ac_state = APM_AC_ON;
1541 		hw_power = 1;
1542 	} else {
1543 		if (info->ac_state != APM_AC_OFF)
1544 			apm_record_event(APM_POWER_CHANGE);
1545 		info->ac_state = APM_AC_OFF;
1546 		hw_power = 0;
1547 	}
1548 
1549 	wakeup(&qcpas_pmic_rtr_apm_power_info);
1550 #endif
1551 }
1552