xref: /openbsd/sys/dev/acpi/qciic.c (revision 3bef86f7)
1 /*	$OpenBSD: qciic.c,v 1.5 2022/11/06 15:36:13 patrick Exp $	*/
2 /*
3  * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
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/intr.h>
23 #include <machine/bus.h>
24 
25 #include <dev/acpi/acpireg.h>
26 #include <dev/acpi/acpivar.h>
27 #include <dev/acpi/acpidev.h>
28 #include <dev/acpi/amltypes.h>
29 #include <dev/acpi/dsdt.h>
30 
31 #define _I2C_PRIVATE
32 #include <dev/i2c/i2cvar.h>
33 
34 /* Registers */
35 #define GENI_I2C_TX_TRANS_LEN		0x26c
36 #define GENI_I2C_RX_TRANS_LEN		0x270
37 #define GENI_M_CMD0			0x600
38 #define  GENI_M_CMD0_OPCODE_I2C_WRITE	(0x1 << 27)
39 #define  GENI_M_CMD0_OPCODE_I2C_READ	(0x2 << 27)
40 #define  GENI_M_CMD0_SLV_ADDR_SHIFT	9
41 #define  GENI_M_CMD0_STOP_STRETCH	(1 << 2)
42 #define GENI_M_IRQ_STATUS		0x610
43 #define GENI_M_IRQ_CLEAR		0x618
44 #define  GENI_M_IRQ_CMD_DONE		(1 << 0)
45 #define GENI_TX_FIFO			0x700
46 #define GENI_RX_FIFO			0x780
47 #define GENI_TX_FIFO_STATUS		0x800
48 #define GENI_RX_FIFO_STATUS		0x804
49 #define  GENI_RX_FIFO_STATUS_WC(val)	((val) & 0xffffff)
50 
51 #define HREAD4(sc, reg)							\
52 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
53 #define HWRITE4(sc, reg, val)						\
54 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
55 
56 struct qciic_softc {
57 	struct device		sc_dev;
58 	bus_space_tag_t		sc_iot;
59 	bus_space_handle_t	sc_ioh;
60 
61 	struct acpi_softc	*sc_acpi;
62 	struct aml_node		*sc_node;
63 	struct device		*sc_iic;
64 
65 	struct i2c_controller	sc_ic;
66 };
67 
68 struct qciic_crs {
69 	uint16_t i2c_addr;
70 	struct aml_node *i2c_bus;
71 	int irq_int;
72 	uint8_t irq_flags;
73 	struct aml_node *gpio_int_node;
74 	uint16_t gpio_int_pin;
75 	uint16_t gpio_int_flags;
76 	struct aml_node *node;
77 };
78 
79 int	qciic_acpi_match(struct device *, void *, void *);
80 void	qciic_acpi_attach(struct device *, struct device *, void *);
81 
82 const struct cfattach qciic_acpi_ca = {
83 	sizeof (struct qciic_softc), qciic_acpi_match, qciic_acpi_attach
84 };
85 
86 struct cfdriver qciic_cd = {
87 	NULL, "qciic", DV_DULL
88 };
89 
90 int	qciic_acquire_bus(void *, int);
91 void	qciic_release_bus(void *, int);
92 int	qciic_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
93 	    void *, size_t, int);
94 
95 void	*qciic_i2c_intr_establish(void *, void *, int, int (*)(void *),
96 	    void *, const char *);
97 void	qciic_i2c_intr_disestablish(void *, void *);
98 const char *qciic_i2c_intr_string(void *, void *);
99 
100 int	qciic_acpi_parse_crs(int, union acpi_resource *, void *);
101 void	qciic_acpi_bus_scan(struct device *, struct i2cbus_attach_args *,
102 	    void *);
103 int	qciic_acpi_found_hid(struct aml_node *, void *);
104 int	qciic_acpi_found_ihidev(struct qciic_softc *,
105 	    struct aml_node *, char *, struct qciic_crs);
106 
107 const char *qciic_hids[] = {
108 	"QCOM0610",
109 	"QCOM0811",
110 	NULL
111 };
112 
113 int
114 qciic_acpi_match(struct device *parent, void *match, void *aux)
115 {
116 	struct acpi_attach_args *aaa = aux;
117 	struct cfdata *cf = match;
118 
119 	if (aaa->aaa_naddr < 1)
120 		return 0;
121 	return acpi_matchhids(aaa, qciic_hids, cf->cf_driver->cd_name);
122 }
123 
124 void
125 qciic_acpi_attach(struct device *parent, struct device *self, void *aux)
126 {
127 	struct qciic_softc *sc = (struct qciic_softc *)self;
128 	struct acpi_attach_args *aaa = aux;
129 	struct i2cbus_attach_args iba;
130 
131 	sc->sc_acpi = (struct acpi_softc *)parent;
132 	sc->sc_node = aaa->aaa_node;
133 	printf(" %s", aaa->aaa_node->name);
134 
135 	printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]);
136 
137 	sc->sc_iot = aaa->aaa_bst[0];
138 	if (bus_space_map(sc->sc_iot, aaa->aaa_addr[0], aaa->aaa_size[0],
139 	    0, &sc->sc_ioh)) {
140 		printf(": can't map registers\n");
141 		return;
142 	}
143 
144 	printf("\n");
145 
146 	sc->sc_ic.ic_cookie = sc;
147 	sc->sc_ic.ic_acquire_bus = qciic_acquire_bus;
148 	sc->sc_ic.ic_release_bus = qciic_release_bus;
149 	sc->sc_ic.ic_exec = qciic_exec;
150 	sc->sc_ic.ic_intr_establish = qciic_i2c_intr_establish;
151 	sc->sc_ic.ic_intr_disestablish = qciic_i2c_intr_disestablish;
152 	sc->sc_ic.ic_intr_string = qciic_i2c_intr_string;
153 
154 #ifndef SMALL_KERNEL
155 	/*
156 	 * XXX Registering the I2C9 node with ACPI leads to AML
157 	 * executing I2C transaction that fail and spin with the
158 	 * kernel lock held until they fail.
159 	 */
160 	if (strcmp(aaa->aaa_dev, "QCOM0610") != 0) {
161 		sc->sc_node->i2c = &sc->sc_ic;
162 		acpi_register_gsb(sc->sc_acpi, sc->sc_node);
163 	}
164 #endif
165 
166 	memset(&iba, 0, sizeof(iba));
167 	iba.iba_name = "iic";
168 	iba.iba_tag = &sc->sc_ic;
169 	iba.iba_bus_scan = qciic_acpi_bus_scan;
170 	iba.iba_bus_scan_arg = sc;
171 	config_found(&sc->sc_dev, &iba, iicbus_print);
172 }
173 
174 int
175 qciic_acquire_bus(void *cookie, int flags)
176 {
177 	return 0;
178 }
179 
180 void
181 qciic_release_bus(void *cookie, int flags)
182 {
183 }
184 
185 int
186 qciic_wait(struct qciic_softc *sc, uint32_t bits)
187 {
188 	uint32_t stat;
189 	int timo;
190 
191 	for (timo = 50000; timo > 0; timo--) {
192 		stat = HREAD4(sc, GENI_M_IRQ_STATUS);
193 		if (stat & bits)
194 			break;
195 		delay(10);
196 	}
197 	if (timo == 0)
198 		return ETIMEDOUT;
199 
200 	return 0;
201 }
202 
203 int
204 qciic_read(struct qciic_softc *sc, uint8_t *buf, size_t len)
205 {
206 	uint32_t stat, word;
207 	int timo, i;
208 
209 	word = 0;
210 	for (i = 0; i < len; i++) {
211 		if ((i % 4) == 0) {
212 			for (timo = 50000; timo > 0; timo--) {
213 				stat = HREAD4(sc, GENI_RX_FIFO_STATUS);
214 				if (GENI_RX_FIFO_STATUS_WC(stat) > 0)
215 					break;
216 				delay(10);
217 			}
218 			if (timo == 0)
219 				return ETIMEDOUT;
220 			word = HREAD4(sc, GENI_RX_FIFO);
221 		}
222 		buf[i] = word >> ((i % 4) * 8);
223 	}
224 
225 	return 0;
226 }
227 
228 int
229 qciic_write(struct qciic_softc *sc, const uint8_t *buf, size_t len)
230 {
231 	uint32_t stat, word;
232 	int timo, i;
233 
234 	word = 0;
235 	for (i = 0; i < len; i++) {
236 		word |= buf[i] << ((i % 4) * 8);
237 		if ((i % 4) == 3 || i == (len - 1)) {
238 			for (timo = 50000; timo > 0; timo--) {
239 				stat = HREAD4(sc, GENI_TX_FIFO_STATUS);
240 				if (stat < 16)
241 					break;
242 				delay(10);
243 			}
244 			if (timo == 0)
245 				return ETIMEDOUT;
246 			HWRITE4(sc, GENI_TX_FIFO, word);
247 			word = 0;
248 		}
249 	}
250 
251 	return 0;
252 }
253 
254 int
255 qciic_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd,
256     size_t cmdlen, void *buf, size_t buflen, int flags)
257 {
258 	struct qciic_softc *sc = cookie;
259 	uint32_t m_cmd, m_param, stat;
260 	int error;
261 
262 	m_param = addr << GENI_M_CMD0_SLV_ADDR_SHIFT;
263 	m_param |= GENI_M_CMD0_STOP_STRETCH;
264 
265 	if (buflen == 0 && I2C_OP_STOP_P(op))
266 		m_param &= ~GENI_M_CMD0_STOP_STRETCH;
267 
268 	if (cmdlen > 0) {
269 		stat = HREAD4(sc, GENI_M_IRQ_STATUS);
270 		HWRITE4(sc, GENI_M_IRQ_CLEAR, stat);
271 		HWRITE4(sc, GENI_I2C_TX_TRANS_LEN, cmdlen);
272 		m_cmd = GENI_M_CMD0_OPCODE_I2C_WRITE | m_param;
273 		HWRITE4(sc, GENI_M_CMD0, m_cmd);
274 
275 		error = qciic_write(sc, cmd, cmdlen);
276 		if (error)
277 			return error;
278 
279 		error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE);
280 		if (error)
281 			return error;
282 	}
283 
284 	if (buflen == 0)
285 		return 0;
286 
287 	if (I2C_OP_STOP_P(op))
288 		m_param &= ~GENI_M_CMD0_STOP_STRETCH;
289 
290 	if (I2C_OP_READ_P(op)) {
291 		stat = HREAD4(sc, GENI_M_IRQ_STATUS);
292 		HWRITE4(sc, GENI_M_IRQ_CLEAR, stat);
293 		HWRITE4(sc, GENI_I2C_RX_TRANS_LEN, buflen);
294 		m_cmd = GENI_M_CMD0_OPCODE_I2C_READ | m_param;
295 		HWRITE4(sc, GENI_M_CMD0, m_cmd);
296 
297 		error = qciic_read(sc, buf, buflen);
298 		if (error)
299 			return error;
300 
301 		error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE);
302 		if (error)
303 			return error;
304 	} else {
305 		stat = HREAD4(sc, GENI_M_IRQ_STATUS);
306 		HWRITE4(sc, GENI_M_IRQ_CLEAR, stat);
307 		HWRITE4(sc, GENI_I2C_TX_TRANS_LEN, buflen);
308 		m_cmd = GENI_M_CMD0_OPCODE_I2C_WRITE | m_param;
309 		HWRITE4(sc, GENI_M_CMD0, m_cmd);
310 
311 		error = qciic_write(sc, buf, buflen);
312 		if (error)
313 			return error;
314 
315 		error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE);
316 		if (error)
317 			return error;
318 	}
319 
320 	return 0;
321 }
322 
323 void *
324 qciic_i2c_intr_establish(void *cookie, void *ih, int level,
325     int (*func)(void *), void *arg, const char *name)
326 {
327 	struct qciic_crs *crs = ih;
328 
329 	if (crs->gpio_int_node) {
330 		if (!crs->gpio_int_node->gpio)
331 			/* found ACPI device but no driver for it */
332 			return NULL;
333 
334 		struct acpi_gpio *gpio = crs->gpio_int_node->gpio;
335 		gpio->intr_establish(gpio->cookie, crs->gpio_int_pin,
336 				     crs->gpio_int_flags, func, arg);
337 		return ih;
338 	}
339 
340 	return acpi_intr_establish(crs->irq_int, crs->irq_flags,
341 	    level, func, arg, name);
342 }
343 
344 void
345 qciic_i2c_intr_disestablish(void *cookie, void *ih)
346 {
347 	/* XXX GPIO interrupts */
348 	acpi_intr_disestablish(ih);
349 }
350 
351 const char *
352 qciic_i2c_intr_string(void *cookie, void *ih)
353 {
354 	struct qciic_crs *crs = ih;
355 	static char irqstr[64];
356 
357 	if (crs->gpio_int_node) {
358 		if (crs->gpio_int_node->gpio)
359 			snprintf(irqstr, sizeof(irqstr), "gpio %d",
360 			    crs->gpio_int_pin);
361 	} else
362 		snprintf(irqstr, sizeof(irqstr), "irq %d", crs->irq_int);
363 
364 	return irqstr;
365 }
366 
367 int
368 qciic_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg)
369 {
370 	struct qciic_crs *sc_crs = arg;
371 	struct aml_node *node;
372 	uint16_t pin;
373 
374 	switch (AML_CRSTYPE(crs)) {
375 	case LR_SERBUS:
376 		if (crs->lr_serbus.type == LR_SERBUS_I2C) {
377 			sc_crs->i2c_addr = crs->lr_i2cbus._adr;
378 			sc_crs->i2c_bus = aml_searchname(sc_crs->node,
379 			    &crs->lr_i2cbus.vdata[crs->lr_i2cbus.tlength - 6]);
380 		}
381 		break;
382 
383 	case LR_GPIO:
384 		node = aml_searchname(sc_crs->node,
385 		    (char *)&crs->pad[crs->lr_gpio.res_off]);
386 		pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off];
387 		if (crs->lr_gpio.type == LR_GPIO_INT) {
388 			sc_crs->gpio_int_node = node;
389 			sc_crs->gpio_int_pin = pin;
390 			sc_crs->gpio_int_flags = crs->lr_gpio.tflags;
391 		}
392 		break;
393 	}
394 
395 	return 0;
396 }
397 
398 void
399 qciic_acpi_bus_scan(struct device *iic, struct i2cbus_attach_args *iba,
400     void *aux)
401 {
402 	struct qciic_softc *sc = aux;
403 
404 	sc->sc_iic = iic;
405 	aml_find_node(acpi_softc->sc_root, "_HID", qciic_acpi_found_hid, sc);
406 }
407 
408 int
409 qciic_acpi_found_hid(struct aml_node *node, void *arg)
410 {
411 	struct qciic_softc *sc = arg;
412 	struct qciic_crs crs;
413 	struct aml_value res;
414 	int64_t sta;
415 	char cdev[16], dev[16];
416 	struct i2c_attach_args ia;
417 
418 	/* Skip our own _HID. */
419 	if (node->parent == sc->sc_node)
420 		return 0;
421 
422 	if (acpi_parsehid(node, arg, cdev, dev, 16) != 0)
423 		return 0;
424 
425 	sta = acpi_getsta(acpi_softc, node->parent);
426 	if ((sta & STA_PRESENT) == 0)
427 		return 0;
428 
429 	if (aml_evalname(acpi_softc, node->parent, "_CRS", 0, NULL, &res))
430 		return 0;
431 
432 	if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) {
433 		aml_freevalue(&res);
434 		return 0;
435 	}
436 	memset(&crs, 0, sizeof(crs));
437 	crs.node = node->parent;
438 	aml_parse_resource(&res, qciic_acpi_parse_crs, &crs);
439 	aml_freevalue(&res);
440 
441 	/* Skip if not using this bus. */
442 	if (crs.i2c_bus != sc->sc_node)
443 		return 0;
444 
445 	acpi_attach_deps(acpi_softc, node->parent);
446 
447 	if (strcmp(dev, "PNP0C50") == 0 || strcmp(cdev, "PNP0C50") == 0)
448 		return qciic_acpi_found_ihidev(sc, node, dev, crs);
449 
450 	memset(&ia, 0, sizeof(ia));
451 	ia.ia_tag = &sc->sc_ic;
452 	ia.ia_name = dev;
453 	ia.ia_addr = crs.i2c_addr;
454 	ia.ia_cookie = node->parent;
455 
456 	config_found(sc->sc_iic, &ia, iic_print);
457 	node->parent->attached = 1;
458 
459 	return 0;
460 }
461 
462 int
463 qciic_acpi_found_ihidev(struct qciic_softc *sc, struct aml_node *node,
464     char *dev, struct qciic_crs crs)
465 {
466 	struct i2c_attach_args ia;
467 	struct aml_value cmd[4], res;
468 
469 	/* 3cdff6f7-4267-4555-ad05-b30a3d8938de */
470 	static uint8_t i2c_hid_guid[] = {
471 		0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
472 		0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
473 	};
474 
475 	if (!aml_searchname(node->parent, "_DSM")) {
476 		printf("%s: couldn't find _DSM at %s\n", sc->sc_dev.dv_xname,
477 		    aml_nodename(node->parent));
478 		return 0;
479 	}
480 
481 	memset(&cmd, 0, sizeof(cmd));
482 	cmd[0].type = AML_OBJTYPE_BUFFER;
483 	cmd[0].v_buffer = (uint8_t *)&i2c_hid_guid;
484 	cmd[0].length = sizeof(i2c_hid_guid);
485 	/* rev */
486 	cmd[1].type = AML_OBJTYPE_INTEGER;
487 	cmd[1].v_integer = 1;
488 	cmd[1].length = 1;
489 	/* func */
490 	cmd[2].type = AML_OBJTYPE_INTEGER;
491 	cmd[2].v_integer = 1; /* HID */
492 	cmd[2].length = 1;
493 	/* not used */
494 	cmd[3].type = AML_OBJTYPE_PACKAGE;
495 	cmd[3].length = 0;
496 
497 	if (aml_evalname(acpi_softc, node->parent, "_DSM", 4, cmd, &res)) {
498 		printf("%s: eval of _DSM at %s failed\n",
499 		    sc->sc_dev.dv_xname, aml_nodename(node->parent));
500 		return 0;
501 	}
502 
503 	if (res.type != AML_OBJTYPE_INTEGER) {
504 		printf("%s: bad _DSM result at %s: %d\n",
505 		    sc->sc_dev.dv_xname, aml_nodename(node->parent), res.type);
506 		aml_freevalue(&res);
507 		return 0;
508 	}
509 
510 	memset(&ia, 0, sizeof(ia));
511 	ia.ia_tag = &sc->sc_ic;
512 	ia.ia_name = "ihidev";
513 	ia.ia_size = aml_val2int(&res); /* hid descriptor address */
514 	ia.ia_addr = crs.i2c_addr;
515 	ia.ia_cookie = dev;
516 
517 	aml_freevalue(&res);
518 
519 	if (!(crs.irq_int == 0 && crs.gpio_int_node == NULL))
520 		ia.ia_intr = &crs;
521 
522 	if (config_found(sc->sc_iic, &ia, iic_print)) {
523 		node->parent->attached = 1;
524 		return 0;
525 	}
526 
527 	return 1;
528 }
529