Home | History | Annotate | Line # | Download | only in acpi
      1 /* $NetBSD: qcompas.c,v 1.2 2026/02/03 08:45:53 skrll Exp $ */
      2 /*	$OpenBSD: qcpas.c,v 1.8 2024/11/08 21:13:34 landry Exp $	*/
      3 /*
      4  * Copyright (c) 2023 Patrick Wildt <patrick (at) blueri.se>
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include <sys/param.h>
     20 #include <sys/systm.h>
     21 #include <sys/device.h>
     22 #include <sys/kmem.h>
     23 #include <sys/mutex.h>
     24 #include <sys/condvar.h>
     25 #include <sys/callout.h>
     26 #include <sys/exec_elf.h>
     27 
     28 #include <uvm/uvm_extern.h>
     29 
     30 #include <dev/firmload.h>
     31 #include <dev/sysmon/sysmonvar.h>
     32 #include <dev/sysmon/sysmon_taskq.h>
     33 
     34 #include <dev/acpi/acpivar.h>
     35 #include <dev/acpi/acpi_intr.h>
     36 #include <dev/acpi/qcomipcc.h>
     37 #include <dev/acpi/qcompep.h>
     38 #include <dev/acpi/qcomscm.h>
     39 #include <dev/acpi/qcomsmem.h>
     40 #include <dev/acpi/qcomsmptp.h>
     41 
     42 #define DRIVER_NAME		"qcompas"
     43 
     44 #define MDT_TYPE_MASK				(7 << 24)
     45 #define MDT_TYPE_HASH				(2 << 24)
     46 #define MDT_RELOCATABLE				(1 << 27)
     47 
     48 extern struct arm32_bus_dma_tag arm_generic_dma_tag;
     49 
     50 enum qcpas_batt_sensor {
     51 	/* Battery sensors (must be first) */
     52 	QCPAS_DVOLTAGE,
     53 	QCPAS_VOLTAGE,
     54 	QCPAS_DCAPACITY,
     55 	QCPAS_LFCCAPACITY,
     56 	QCPAS_CAPACITY,
     57 	QCPAS_CHARGERATE,
     58 	QCPAS_DISCHARGERATE,
     59 	QCPAS_CHARGING,
     60 	QCPAS_CHARGE_STATE,
     61 	QCPAS_DCYCLES,
     62 	QCPAS_TEMPERATURE,
     63 	/* AC adapter sensors */
     64 	QCPAS_ACADAPTER,
     65 	/* Total number of sensors */
     66 	QCPAS_NUM_SENSORS
     67 };
     68 
     69 struct qcpas_dmamem {
     70 	bus_dmamap_t		tdm_map;
     71 	bus_dma_segment_t	tdm_seg;
     72 	size_t			tdm_size;
     73 	void			*tdm_kva;
     74 };
     75 #define QCPAS_DMA_MAP(_tdm)	((_tdm)->tdm_map)
     76 #define QCPAS_DMA_LEN(_tdm)	((_tdm)->tdm_size)
     77 #define QCPAS_DMA_DVA(_tdm)	((_tdm)->tdm_map->dm_segs[0].ds_addr)
     78 #define QCPAS_DMA_KVA(_tdm)	((_tdm)->tdm_kva)
     79 
     80 struct qcpas_softc {
     81 	device_t		sc_dev;
     82 	bus_dma_tag_t		sc_dmat;
     83 
     84 	char			*sc_sub;
     85 
     86 	void			*sc_ih[5];
     87 
     88 	kmutex_t		sc_ready_lock;
     89 	kcondvar_t		sc_ready_cv;
     90 	bool			sc_ready;
     91 
     92 	paddr_t			sc_mem_phys[2];
     93 	size_t			sc_mem_size[2];
     94 	uint8_t			*sc_mem_region[2];
     95 	vaddr_t			sc_mem_reloc[2];
     96 
     97 	const char		*sc_fwname;
     98 	const char		*sc_dtb_fwname;
     99 	uint32_t		sc_pas_id;
    100 	uint32_t		sc_dtb_pas_id;
    101 	uint32_t		sc_lite_pas_id;
    102 	const char		*sc_load_state;
    103 	uint32_t		sc_glink_remote_pid;
    104 	uint32_t		sc_crash_reason;
    105 
    106 	struct qcpas_dmamem	*sc_metadata[2];
    107 
    108 	/* GLINK */
    109 	volatile uint32_t	*sc_tx_tail;
    110 	volatile uint32_t	*sc_tx_head;
    111 	volatile uint32_t	*sc_rx_tail;
    112 	volatile uint32_t	*sc_rx_head;
    113 
    114 	uint32_t		sc_tx_off;
    115 	uint32_t		sc_rx_off;
    116 
    117 	uint8_t			*sc_tx_fifo;
    118 	int			sc_tx_fifolen;
    119 	uint8_t			*sc_rx_fifo;
    120 	int			sc_rx_fifolen;
    121 	void			*sc_glink_ih;
    122 
    123 	void			*sc_ipcc;
    124 
    125 	uint32_t		sc_glink_max_channel;
    126 	TAILQ_HEAD(,qcpas_glink_channel) sc_glink_channels;
    127 
    128 	uint32_t		sc_warning_capacity;
    129 	uint32_t		sc_low_capacity;
    130 	uint32_t		sc_power_state;
    131 	struct sysmon_envsys	*sc_sme;
    132 	envsys_data_t		sc_sens[QCPAS_NUM_SENSORS];
    133 	struct sysmon_envsys	*sc_sme_acadapter;
    134 	struct sysmon_pswitch	sc_smpsw_acadapter;
    135 	callout_t		sc_rtr_refresh;
    136 };
    137 
    138 static int	qcpas_match(device_t, cfdata_t, void *);
    139 static void	qcpas_attach(device_t, device_t, void *);
    140 
    141 CFATTACH_DECL_NEW(qcompas, sizeof(struct qcpas_softc),
    142     qcpas_match, qcpas_attach, NULL, NULL);
    143 
    144 static void	qcpas_mountroot(device_t);
    145 static void	qcpas_firmload(void *);
    146 static int	qcpas_map_memory(struct qcpas_softc *);
    147 static int	qcpas_mdt_init(struct qcpas_softc *, int, u_char *, size_t);
    148 static void	qcpas_glink_attach(struct qcpas_softc *);
    149 static void	qcpas_glink_recv(void *);
    150 static void	qcpas_get_limits(struct sysmon_envsys *, envsys_data_t *,
    151 				 sysmon_envsys_lim_t *, uint32_t *);
    152 
    153 static struct qcpas_dmamem *
    154 		qcpas_dmamem_alloc(struct qcpas_softc *, bus_size_t, bus_size_t);
    155 static void	qcpas_dmamem_free(struct qcpas_softc *, struct qcpas_dmamem *);
    156 
    157 static int	qcpas_intr_wdog(void *);
    158 static int	qcpas_intr_fatal(void *);
    159 static int	qcpas_intr_ready(void *);
    160 static int	qcpas_intr_handover(void *);
    161 static int	qcpas_intr_stop_ack(void *);
    162 
    163 struct qcpas_mem_region {
    164 	bus_addr_t		start;
    165 	bus_size_t		size;
    166 };
    167 
    168 struct qcpas_data {
    169 	bus_addr_t		reg_addr;
    170 	bus_size_t		reg_size;
    171 	uint32_t		pas_id;
    172 	uint32_t		dtb_pas_id;
    173 	uint32_t		lite_pas_id;
    174 	const char		*load_state;
    175 	uint32_t		glink_remote_pid;
    176 	struct qcpas_mem_region	mem_region[2];
    177 	const char		*fwname;
    178 	const char		*dtb_fwname;
    179 	uint32_t		crash_reason;
    180 };
    181 
    182 static struct qcpas_data qcpas_x1e_data = {
    183 	.reg_addr = 0x30000000,
    184 	.reg_size = 0x100,
    185 	.pas_id = 1,
    186 	.dtb_pas_id = 36,
    187 	.lite_pas_id = 31,
    188 	.load_state = "adsp",
    189 	.glink_remote_pid = 2,
    190 	.mem_region = {
    191 		[0] = { .start = 0x87e00000, .size = 0x3a00000 },
    192 		[1] = { .start = 0x8b800000, .size = 0x80000 },
    193 	},
    194 	.fwname = "qcadsp8380.mbn",
    195 	.dtb_fwname = "adsp_dtbs.elf",
    196 	.crash_reason = 423,
    197 };
    198 
    199 #define IPCC_CLIENT_LPASS       	3
    200 #define IPCC_MPROC_SIGNAL_GLINK_QMP	0
    201 
    202 static const struct device_compatible_entry compat_data[] = {
    203         { .compat = "QCOM0C1B",         .data = &qcpas_x1e_data },
    204         DEVICE_COMPAT_EOL
    205 };
    206 
    207 static int
    208 qcpas_match(device_t parent, cfdata_t match, void *aux)
    209 {
    210 	struct acpi_attach_args *aa = aux;
    211 
    212 	return acpi_compatible_match(aa, compat_data);
    213 }
    214 
    215 static void
    216 qcpas_attach(device_t parent, device_t self, void *aux)
    217 {
    218 	struct qcpas_softc *sc = device_private(self);
    219 	struct acpi_attach_args *aa = aux;
    220 	const struct qcpas_data *data;
    221 	struct acpi_resources res;
    222 	ACPI_STATUS rv;
    223 	int i;
    224 
    225 	rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", &res,
    226 	    &acpi_resource_parse_ops_default);
    227 	if (ACPI_FAILURE(rv)) {
    228 		return;
    229 	}
    230 	acpi_resource_cleanup(&res);
    231 
    232 	data = acpi_compatible_lookup(aa, compat_data)->data;
    233 
    234 	sc->sc_dev = self;
    235 	sc->sc_dmat = &arm_generic_dma_tag;
    236 	mutex_init(&sc->sc_ready_lock, MUTEX_DEFAULT, IPL_VM);
    237 	cv_init(&sc->sc_ready_cv, "qcpasrdy");
    238 
    239 	sc->sc_fwname = data->fwname;
    240 	sc->sc_dtb_fwname = data->dtb_fwname;
    241 	sc->sc_pas_id = data->pas_id;
    242 	sc->sc_dtb_pas_id = data->dtb_pas_id;
    243 	sc->sc_lite_pas_id = data->lite_pas_id;
    244 	sc->sc_load_state = data->load_state;
    245 	sc->sc_glink_remote_pid = data->glink_remote_pid;
    246 	sc->sc_crash_reason = data->crash_reason;
    247 	for (i = 0; i < __arraycount(sc->sc_mem_phys); i++) {
    248 		sc->sc_mem_phys[i] = data->mem_region[i].start;
    249 		KASSERT((sc->sc_mem_phys[i] & PAGE_MASK) == 0);
    250 		sc->sc_mem_size[i] = data->mem_region[i].size;
    251 		KASSERT((sc->sc_mem_size[i] & PAGE_MASK) == 0);
    252 	}
    253 
    254 	rv = acpi_eval_string(aa->aa_node->ad_handle, "_SUB", &sc->sc_sub);
    255 	if (ACPI_FAILURE(rv)) {
    256 		aprint_error_dev(self, "failed to evaluate _SUB: %s\n",
    257 		    AcpiFormatException(rv));
    258 		return;
    259 	}
    260 	aprint_verbose_dev(self, "subsystem ID %s\n", sc->sc_sub);
    261 
    262 	sc->sc_ih[0] = acpi_intr_establish(self,
    263 	    (uint64_t)(uintptr_t)aa->aa_node->ad_handle,
    264 	    IPL_VM, false, qcpas_intr_wdog, sc, device_xname(self));
    265 	sc->sc_ih[1] =
    266 	    qcsmptp_intr_establish(0, qcpas_intr_fatal, sc);
    267 	sc->sc_ih[2] =
    268 	    qcsmptp_intr_establish(1, qcpas_intr_ready, sc);
    269 	sc->sc_ih[3] =
    270 	    qcsmptp_intr_establish(2, qcpas_intr_handover, sc);
    271 	sc->sc_ih[4] =
    272 	    qcsmptp_intr_establish(3, qcpas_intr_stop_ack, sc);
    273 
    274 	if (qcpas_map_memory(sc) != 0)
    275 		return;
    276 
    277 	config_mountroot(self, qcpas_mountroot);
    278 }
    279 
    280 static void
    281 qcpas_firmload(void *arg)
    282 {
    283 	struct qcpas_softc *sc = arg;
    284 	firmware_handle_t fwh = NULL, dtb_fwh = NULL;
    285 	char fwname[128];
    286 	size_t fwlen = 0, dtb_fwlen = 0;
    287 	u_char *fw = NULL, *dtb_fw = NULL;
    288 	int ret, error;
    289 
    290 	snprintf(fwname, sizeof(fwname), "%s/%s", sc->sc_sub, sc->sc_fwname);
    291 	error = firmware_open(DRIVER_NAME, fwname, &fwh);
    292 	if (error == 0) {
    293 		fwlen = firmware_get_size(fwh);
    294 		fw = fwlen ? firmware_malloc(fwlen) : NULL;
    295 		error = fw == NULL ? ENOMEM :
    296 			firmware_read(fwh, 0, fw, fwlen);
    297 	}
    298 	if (error) {
    299 		device_printf(sc->sc_dev, "failed to load %s/%s: %d\n",
    300 		    DRIVER_NAME, fwname, error);
    301 		goto cleanup;
    302 	}
    303 	aprint_normal_dev(sc->sc_dev, "loading %s/%s\n", DRIVER_NAME, fwname);
    304 
    305 	if (sc->sc_lite_pas_id) {
    306 		if (qcscm_pas_shutdown(sc->sc_lite_pas_id)) {
    307 			device_printf(sc->sc_dev,
    308 			    "failed to shutdown lite firmware\n");
    309 		}
    310 	}
    311 
    312 	if (sc->sc_dtb_pas_id) {
    313 		snprintf(fwname, sizeof(fwname), "%s/%s", sc->sc_sub,
    314 		    sc->sc_dtb_fwname);
    315 		error = firmware_open(DRIVER_NAME, fwname, &dtb_fwh);
    316 		if (error == 0) {
    317 			dtb_fwlen = firmware_get_size(dtb_fwh);
    318 			dtb_fw = dtb_fwlen ? firmware_malloc(dtb_fwlen) : NULL;
    319 			error = dtb_fw == NULL ? ENOMEM :
    320 				firmware_read(dtb_fwh, 0, dtb_fw, dtb_fwlen);
    321 		}
    322 		if (error) {
    323 			device_printf(sc->sc_dev, "failed to load %s/%s: %d\n",
    324 			    DRIVER_NAME, fwname, error);
    325 			goto cleanup;
    326 		}
    327 		aprint_normal_dev(sc->sc_dev, "loading %s/%s\n", DRIVER_NAME, fwname);
    328 	}
    329 
    330 	if (sc->sc_load_state) {
    331 		char buf[64];
    332 		snprintf(buf, sizeof(buf),
    333 		    "{class: image, res: load_state, name: %s, val: on}",
    334 		    sc->sc_load_state);
    335 		ret = qcaoss_send(buf, sizeof(buf));
    336 		if (ret != 0) {
    337 			device_printf(sc->sc_dev, "failed to toggle load state\n");
    338 			goto cleanup;
    339 		}
    340 	}
    341 
    342 	if (sc->sc_dtb_pas_id) {
    343 		qcpas_mdt_init(sc, sc->sc_dtb_pas_id, dtb_fw, dtb_fwlen);
    344 	}
    345 
    346 	ret = qcpas_mdt_init(sc, sc->sc_pas_id, fw, fwlen);
    347 	if (ret != 0) {
    348 		device_printf(sc->sc_dev, "failed to boot coprocessor\n");
    349 		goto cleanup;
    350 	}
    351 
    352 	qcpas_glink_attach(sc);
    353 
    354 	/* Battery sensors */
    355 	sc->sc_sme = sysmon_envsys_create();
    356 	sc->sc_sme->sme_name = "battery";
    357 	sc->sc_sme->sme_cookie = sc;
    358 	sc->sc_sme->sme_flags = SME_DISABLE_REFRESH;
    359 	sc->sc_sme->sme_class = SME_CLASS_BATTERY;
    360 	sc->sc_sme->sme_get_limits = qcpas_get_limits;
    361 
    362 	/* AC adapter sensors */
    363 	sc->sc_sme_acadapter = sysmon_envsys_create();
    364 	sc->sc_sme_acadapter->sme_name = "charger";
    365 	sc->sc_sme_acadapter->sme_cookie = sc;
    366 	sc->sc_sme_acadapter->sme_flags = SME_DISABLE_REFRESH;
    367 	sc->sc_sme_acadapter->sme_class = SME_CLASS_ACADAPTER;
    368 
    369 #define INIT_SENSOR(sme, idx, unit, str)				\
    370 	do {								\
    371 		strlcpy(sc->sc_sens[idx].desc, str,			\
    372 		    sizeof(sc->sc_sens[0].desc));			\
    373 		sc->sc_sens[idx].units = unit;				\
    374 		sc->sc_sens[idx].state = ENVSYS_SINVALID;		\
    375 		sysmon_envsys_sensor_attach(sme,			\
    376 		    &sc->sc_sens[idx]);					\
    377 	} while (0)
    378 
    379 	INIT_SENSOR(sc->sc_sme, QCPAS_DVOLTAGE, ENVSYS_SVOLTS_DC, "design voltage");
    380 	INIT_SENSOR(sc->sc_sme, QCPAS_VOLTAGE, ENVSYS_SVOLTS_DC, "voltage");
    381 	INIT_SENSOR(sc->sc_sme, QCPAS_DCAPACITY, ENVSYS_SWATTHOUR, "design cap");
    382 	INIT_SENSOR(sc->sc_sme, QCPAS_LFCCAPACITY, ENVSYS_SWATTHOUR, "last full cap");
    383 	INIT_SENSOR(sc->sc_sme, QCPAS_CAPACITY, ENVSYS_SWATTHOUR, "charge");
    384 	INIT_SENSOR(sc->sc_sme, QCPAS_CHARGERATE, ENVSYS_SWATTS, "charge rate");
    385 	INIT_SENSOR(sc->sc_sme, QCPAS_DISCHARGERATE, ENVSYS_SWATTS, "discharge rate");
    386 	INIT_SENSOR(sc->sc_sme, QCPAS_CHARGING, ENVSYS_BATTERY_CHARGE, "charging");
    387 	INIT_SENSOR(sc->sc_sme, QCPAS_CHARGE_STATE, ENVSYS_BATTERY_CAPACITY, "charge state");
    388 	INIT_SENSOR(sc->sc_sme, QCPAS_DCYCLES, ENVSYS_INTEGER, "discharge cycles");
    389 	INIT_SENSOR(sc->sc_sme, QCPAS_TEMPERATURE, ENVSYS_STEMP, "temperature");
    390 	INIT_SENSOR(sc->sc_sme_acadapter, QCPAS_ACADAPTER, ENVSYS_INDICATOR, "connected");
    391 
    392 #undef INIT_SENSOR
    393 
    394 	sc->sc_sens[QCPAS_CHARGE_STATE].value_cur =
    395 	    ENVSYS_BATTERY_CAPACITY_NORMAL;
    396 	sc->sc_sens[QCPAS_CAPACITY].flags |=
    397 	    ENVSYS_FPERCENT | ENVSYS_FVALID_MAX | ENVSYS_FMONLIMITS;
    398 	sc->sc_sens[QCPAS_CHARGE_STATE].flags |=
    399 	    ENVSYS_FMONSTCHANGED;
    400 
    401 	sc->sc_sens[QCPAS_VOLTAGE].flags = ENVSYS_FMONNOTSUPP;
    402 	sc->sc_sens[QCPAS_CHARGERATE].flags = ENVSYS_FMONNOTSUPP;
    403 	sc->sc_sens[QCPAS_DISCHARGERATE].flags = ENVSYS_FMONNOTSUPP;
    404 	sc->sc_sens[QCPAS_DCAPACITY].flags = ENVSYS_FMONNOTSUPP;
    405 	sc->sc_sens[QCPAS_LFCCAPACITY].flags = ENVSYS_FMONNOTSUPP;
    406 	sc->sc_sens[QCPAS_DVOLTAGE].flags = ENVSYS_FMONNOTSUPP;
    407 
    408 	sc->sc_sens[QCPAS_CHARGERATE].flags |= ENVSYS_FHAS_ENTROPY;
    409 	sc->sc_sens[QCPAS_DISCHARGERATE].flags |= ENVSYS_FHAS_ENTROPY;
    410 
    411 	sysmon_envsys_register(sc->sc_sme);
    412 	sysmon_envsys_register(sc->sc_sme_acadapter);
    413 
    414 	sc->sc_smpsw_acadapter.smpsw_name = "acpiacad0";
    415 	sc->sc_smpsw_acadapter.smpsw_type = PSWITCH_TYPE_ACADAPTER;
    416 	sysmon_pswitch_register(&sc->sc_smpsw_acadapter);
    417 
    418 cleanup:
    419 	if (dtb_fw != NULL) {
    420 		firmware_free(dtb_fw, dtb_fwlen);
    421 	}
    422 	if (fw != NULL) {
    423 		firmware_free(fw, fwlen);
    424 	}
    425 	if (dtb_fwh != NULL) {
    426 		firmware_close(dtb_fwh);
    427 	}
    428 	if (fwh != NULL) {
    429 		firmware_close(fwh);
    430 	}
    431 }
    432 
    433 static void
    434 qcpas_mountroot(device_t self)
    435 {
    436 	struct qcpas_softc *sc = device_private(self);
    437 
    438 	sysmon_task_queue_sched(0, qcpas_firmload, sc);
    439 }
    440 
    441 static int
    442 qcpas_map_memory(struct qcpas_softc *sc)
    443 {
    444 	int i;
    445 
    446 	for (i = 0; i < __arraycount(sc->sc_mem_phys); i++) {
    447 		paddr_t pa, epa;
    448 		vaddr_t va;
    449 
    450 		if (sc->sc_mem_size[i] == 0)
    451 			break;
    452 
    453 		va = uvm_km_alloc(kernel_map, sc->sc_mem_size[i], 0, UVM_KMF_VAONLY);
    454 		KASSERT(va != 0);
    455 		sc->sc_mem_region[i] = (void *)va;
    456 
    457 		for (pa = sc->sc_mem_phys[i], epa = sc->sc_mem_phys[i] + sc->sc_mem_size[i];
    458 		     pa < epa;
    459 		     pa += PAGE_SIZE, va += PAGE_SIZE) {
    460 			pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE, PMAP_WRITE_COMBINE);
    461 		}
    462 		pmap_update(pmap_kernel());
    463 	}
    464 
    465 	return 0;
    466 }
    467 
    468 static int
    469 qcpas_mdt_init(struct qcpas_softc *sc, int pas_id, u_char *fw, size_t fwlen)
    470 {
    471 	Elf32_Ehdr *ehdr;
    472 	Elf32_Phdr *phdr;
    473 	paddr_t minpa = -1, maxpa = 0;
    474 	int i, hashseg = 0, relocate = 0;
    475 	uint8_t *metadata;
    476 	int error;
    477 	ssize_t off;
    478 	int idx;
    479 
    480 	if (pas_id == sc->sc_dtb_pas_id)
    481 		idx = 1;
    482 	else
    483 		idx = 0;
    484 
    485 	ehdr = (Elf32_Ehdr *)fw;
    486 	phdr = (Elf32_Phdr *)&ehdr[1];
    487 
    488 	if (ehdr->e_phnum < 2 || phdr[0].p_type == PT_LOAD)
    489 		return EINVAL;
    490 
    491 	for (i = 0; i < ehdr->e_phnum; i++) {
    492 		if ((phdr[i].p_flags & MDT_TYPE_MASK) == MDT_TYPE_HASH) {
    493 			if (i > 0 && !hashseg)
    494 				hashseg = i;
    495 			continue;
    496 		}
    497 		if (phdr[i].p_type != PT_LOAD || phdr[i].p_memsz == 0)
    498 			continue;
    499 		if (phdr[i].p_flags & MDT_RELOCATABLE)
    500 			relocate = 1;
    501 		if (phdr[i].p_paddr < minpa)
    502 			minpa = phdr[i].p_paddr;
    503 		if (phdr[i].p_paddr + phdr[i].p_memsz > maxpa)
    504 			maxpa =
    505 			    roundup(phdr[i].p_paddr + phdr[i].p_memsz,
    506 			    PAGE_SIZE);
    507 	}
    508 
    509 	if (!hashseg)
    510 		return EINVAL;
    511 
    512 	if (sc->sc_metadata[idx] == NULL) {
    513 		sc->sc_metadata[idx] = qcpas_dmamem_alloc(sc, phdr[0].p_filesz +
    514 		    phdr[hashseg].p_filesz, PAGE_SIZE);
    515 		if (sc->sc_metadata[idx] == NULL) {
    516 			return EINVAL;
    517 		}
    518 	}
    519 
    520 	metadata = QCPAS_DMA_KVA(sc->sc_metadata[idx]);
    521 
    522 	memcpy(metadata, fw, phdr[0].p_filesz);
    523 	if (phdr[0].p_filesz + phdr[hashseg].p_filesz == fwlen) {
    524 		memcpy(metadata + phdr[0].p_filesz,
    525 		    fw + phdr[0].p_filesz, phdr[hashseg].p_filesz);
    526 	} else if (phdr[hashseg].p_offset + phdr[hashseg].p_filesz <= fwlen) {
    527 		memcpy(metadata + phdr[0].p_filesz,
    528 		    fw + phdr[hashseg].p_offset, phdr[hashseg].p_filesz);
    529 	} else {
    530 		device_printf(sc->sc_dev, "metadata split segment not supported\n");
    531 		return EINVAL;
    532 	}
    533 
    534 	cpu_drain_writebuf();
    535 
    536 	error = qcscm_pas_init_image(pas_id,
    537 	    QCPAS_DMA_DVA(sc->sc_metadata[idx]));
    538 	if (error != 0) {
    539 		device_printf(sc->sc_dev, "init image failed: %d\n", error);
    540 		qcpas_dmamem_free(sc, sc->sc_metadata[idx]);
    541 		return error;
    542 	}
    543 
    544 	if (relocate) {
    545 		if (qcscm_pas_mem_setup(pas_id,
    546 		    sc->sc_mem_phys[idx], maxpa - minpa) != 0) {
    547 			device_printf(sc->sc_dev, "mem setup failed\n");
    548 			qcpas_dmamem_free(sc, sc->sc_metadata[idx]);
    549 			return EINVAL;
    550 		}
    551 	}
    552 
    553 	sc->sc_mem_reloc[idx] = relocate ? minpa : sc->sc_mem_phys[idx];
    554 
    555 	for (i = 0; i < ehdr->e_phnum; i++) {
    556 		if ((phdr[i].p_flags & MDT_TYPE_MASK) == MDT_TYPE_HASH ||
    557 		    phdr[i].p_type != PT_LOAD || phdr[i].p_memsz == 0)
    558 			continue;
    559 		off = phdr[i].p_paddr - sc->sc_mem_reloc[idx];
    560 		if (off < 0 || off + phdr[i].p_memsz > sc->sc_mem_size[0])
    561 			return EINVAL;
    562 		if (phdr[i].p_filesz > phdr[i].p_memsz)
    563 			return EINVAL;
    564 
    565 		if (phdr[i].p_filesz && phdr[i].p_offset < fwlen &&
    566 		    phdr[i].p_offset + phdr[i].p_filesz <= fwlen) {
    567 			memcpy(sc->sc_mem_region[idx] + off,
    568 			    fw + phdr[i].p_offset, phdr[i].p_filesz);
    569 		} else if (phdr[i].p_filesz) {
    570 			device_printf(sc->sc_dev, "firmware split segment not supported\n");
    571 			return EINVAL;
    572 		}
    573 
    574 		if (phdr[i].p_memsz > phdr[i].p_filesz)
    575 			memset(sc->sc_mem_region[idx] + off + phdr[i].p_filesz,
    576 			    0, phdr[i].p_memsz - phdr[i].p_filesz);
    577 	}
    578 
    579 	cpu_drain_writebuf();
    580 
    581 	if (qcscm_pas_auth_and_reset(pas_id) != 0) {
    582 		device_printf(sc->sc_dev, "auth and reset failed\n");
    583 		qcpas_dmamem_free(sc, sc->sc_metadata[idx]);
    584 		return EINVAL;
    585 	}
    586 
    587 	if (pas_id == sc->sc_dtb_pas_id)
    588 		return 0;
    589 
    590 	mutex_enter(&sc->sc_ready_lock);
    591 	while (!sc->sc_ready) {
    592 		error = cv_timedwait(&sc->sc_ready_cv, &sc->sc_ready_lock,
    593 		    hz * 5);
    594 		if (error == EWOULDBLOCK) {
    595 			break;
    596 		}
    597 	}
    598 	mutex_exit(&sc->sc_ready_lock);
    599 	if (!sc->sc_ready) {
    600 		device_printf(sc->sc_dev, "timeout waiting for ready signal\n");
    601 		return ETIMEDOUT;
    602 	}
    603 
    604 	/* XXX: free metadata ? */
    605 
    606 	return 0;
    607 }
    608 
    609 static struct qcpas_dmamem *
    610 qcpas_dmamem_alloc(struct qcpas_softc *sc, bus_size_t size, bus_size_t align)
    611 {
    612 	struct qcpas_dmamem *tdm;
    613 	int nsegs;
    614 
    615 	tdm = kmem_zalloc(sizeof(*tdm), KM_SLEEP);
    616 	tdm->tdm_size = size;
    617 
    618 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
    619 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &tdm->tdm_map) != 0)
    620 		goto tdmfree;
    621 
    622 	if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0,
    623 	    &tdm->tdm_seg, 1, &nsegs, BUS_DMA_WAITOK) != 0)
    624 		goto destroy;
    625 
    626 	if (bus_dmamem_map(sc->sc_dmat, &tdm->tdm_seg, nsegs, size,
    627 	    &tdm->tdm_kva, BUS_DMA_WAITOK | BUS_DMA_PREFETCHABLE) != 0)
    628 		goto free;
    629 
    630 	if (bus_dmamap_load(sc->sc_dmat, tdm->tdm_map, tdm->tdm_kva, size,
    631 	    NULL, BUS_DMA_WAITOK) != 0)
    632 		goto unmap;
    633 
    634 	memset(tdm->tdm_kva, 0, size);
    635 
    636 	return (tdm);
    637 
    638 unmap:
    639 	bus_dmamem_unmap(sc->sc_dmat, tdm->tdm_kva, size);
    640 free:
    641 	bus_dmamem_free(sc->sc_dmat, &tdm->tdm_seg, 1);
    642 destroy:
    643 	bus_dmamap_destroy(sc->sc_dmat, tdm->tdm_map);
    644 tdmfree:
    645 	kmem_free(tdm, sizeof(*tdm));
    646 
    647 	return (NULL);
    648 }
    649 
    650 static void
    651 qcpas_dmamem_free(struct qcpas_softc *sc, struct qcpas_dmamem *tdm)
    652 {
    653 	bus_dmamem_unmap(sc->sc_dmat, tdm->tdm_kva, tdm->tdm_size);
    654 	bus_dmamem_free(sc->sc_dmat, &tdm->tdm_seg, 1);
    655 	bus_dmamap_destroy(sc->sc_dmat, tdm->tdm_map);
    656 	kmem_free(tdm, sizeof(*tdm));
    657 }
    658 
    659 static void
    660 qcpas_report_crash(struct qcpas_softc *sc, const char *source)
    661 {
    662 	char *msg;
    663 	int size;
    664 
    665 	msg = qcsmem_get(-1, sc->sc_crash_reason, &size);
    666 	if (msg == NULL || size <= 0) {
    667 		device_printf(sc->sc_dev, "%s\n", source);
    668 	} else {
    669 		device_printf(sc->sc_dev, "%s: \"%s\"\n", source, msg);
    670 	}
    671 }
    672 
    673 static int
    674 qcpas_intr_wdog(void *cookie)
    675 {
    676 	struct qcpas_softc *sc = cookie;
    677 
    678 	qcpas_report_crash(sc, "watchdog");
    679 
    680 	return 0;
    681 }
    682 
    683 static int
    684 qcpas_intr_fatal(void *cookie)
    685 {
    686 	struct qcpas_softc *sc = cookie;
    687 
    688 	qcpas_report_crash(sc, "fatal error");
    689 
    690 	return 0;
    691 }
    692 
    693 static int
    694 qcpas_intr_ready(void *cookie)
    695 {
    696 	struct qcpas_softc *sc = cookie;
    697 
    698 	aprint_debug_dev(sc->sc_dev, "%s\n", __func__);
    699 
    700 	mutex_enter(&sc->sc_ready_lock);
    701 	sc->sc_ready = true;
    702 	cv_broadcast(&sc->sc_ready_cv);
    703 	mutex_exit(&sc->sc_ready_lock);
    704 
    705 	return 0;
    706 }
    707 
    708 static int
    709 qcpas_intr_handover(void *cookie)
    710 {
    711 	struct qcpas_softc *sc = cookie;
    712 
    713 	aprint_debug_dev(sc->sc_dev, "%s\n", __func__);
    714 
    715 	return 0;
    716 }
    717 
    718 static int
    719 qcpas_intr_stop_ack(void *cookie)
    720 {
    721 	struct qcpas_softc *sc = cookie;
    722 
    723 	aprint_debug_dev(sc->sc_dev, "%s\n", __func__);
    724 
    725 	return 0;
    726 }
    727 
    728 /* GLINK */
    729 
    730 #define SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR	478
    731 #define SMEM_GLINK_NATIVE_XPRT_FIFO_0		479
    732 #define SMEM_GLINK_NATIVE_XPRT_FIFO_1		480
    733 
    734 struct glink_msg {
    735 	uint16_t cmd;
    736 	uint16_t param1;
    737 	uint32_t param2;
    738 	uint8_t data[];
    739 } __packed;
    740 
    741 struct qcpas_glink_intent_pair {
    742 	uint32_t size;
    743 	uint32_t iid;
    744 } __packed;
    745 
    746 struct qcpas_glink_intent {
    747 	TAILQ_ENTRY(qcpas_glink_intent) it_q;
    748 	uint32_t it_id;
    749 	uint32_t it_size;
    750 	int it_inuse;
    751 };
    752 
    753 struct qcpas_glink_channel {
    754 	TAILQ_ENTRY(qcpas_glink_channel) ch_q;
    755 	struct qcpas_softc *ch_sc;
    756 	struct qcpas_glink_protocol *ch_proto;
    757 	uint32_t ch_rcid;
    758 	uint32_t ch_lcid;
    759 	uint32_t ch_max_intent;
    760 	TAILQ_HEAD(,qcpas_glink_intent) ch_l_intents;
    761 	TAILQ_HEAD(,qcpas_glink_intent) ch_r_intents;
    762 };
    763 
    764 #define GLINK_CMD_VERSION		0
    765 #define GLINK_CMD_VERSION_ACK		1
    766 #define  GLINK_VERSION				1
    767 #define  GLINK_FEATURE_INTENT_REUSE		(1 << 0)
    768 #define GLINK_CMD_OPEN			2
    769 #define GLINK_CMD_CLOSE			3
    770 #define GLINK_CMD_OPEN_ACK		4
    771 #define GLINK_CMD_INTENT		5
    772 #define GLINK_CMD_RX_DONE		6
    773 #define GLINK_CMD_RX_INTENT_REQ		7
    774 #define GLINK_CMD_RX_INTENT_REQ_ACK	8
    775 #define GLINK_CMD_TX_DATA		9
    776 #define GLINK_CMD_CLOSE_ACK		11
    777 #define GLINK_CMD_TX_DATA_CONT		12
    778 #define GLINK_CMD_READ_NOTIF		13
    779 #define GLINK_CMD_RX_DONE_W_REUSE	14
    780 
    781 static int	qcpas_glink_intr(void *);
    782 
    783 static void	qcpas_glink_tx(struct qcpas_softc *, uint8_t *, int);
    784 static void	qcpas_glink_tx_commit(struct qcpas_softc *);
    785 static void	qcpas_glink_rx(struct qcpas_softc *, uint8_t *, int);
    786 static void	qcpas_glink_rx_commit(struct qcpas_softc *);
    787 
    788 static void	qcpas_glink_send(void *, void *, int);
    789 
    790 static int	qcpas_pmic_rtr_init(void *);
    791 static int	qcpas_pmic_rtr_recv(void *, uint8_t *, int);
    792 
    793 struct qcpas_glink_protocol {
    794 	const char *name;
    795 	int (*init)(void *cookie);
    796 	int (*recv)(void *cookie, uint8_t *buf, int len);
    797 } qcpas_glink_protocols[] = {
    798 	{ "PMIC_RTR_ADSP_APPS", qcpas_pmic_rtr_init , qcpas_pmic_rtr_recv },
    799 };
    800 
    801 static void
    802 qcpas_glink_attach(struct qcpas_softc *sc)
    803 {
    804 	uint32_t remote = sc->sc_glink_remote_pid;
    805 	uint32_t *descs;
    806 	int size;
    807 
    808 	if (qcsmem_alloc(remote, SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR, 32) != 0 ||
    809 	    qcsmem_alloc(remote, SMEM_GLINK_NATIVE_XPRT_FIFO_0, 16384) != 0)
    810 		return;
    811 
    812 	descs = qcsmem_get(remote, SMEM_GLINK_NATIVE_XPRT_DESCRIPTOR, &size);
    813 	if (descs == NULL || size != 32)
    814 		return;
    815 
    816 	sc->sc_tx_tail = &descs[0];
    817 	sc->sc_tx_head = &descs[1];
    818 	sc->sc_rx_tail = &descs[2];
    819 	sc->sc_rx_head = &descs[3];
    820 
    821 	sc->sc_tx_fifo = qcsmem_get(remote, SMEM_GLINK_NATIVE_XPRT_FIFO_0,
    822 	    &sc->sc_tx_fifolen);
    823 	if (sc->sc_tx_fifo == NULL)
    824 		return;
    825 	sc->sc_rx_fifo = qcsmem_get(remote, SMEM_GLINK_NATIVE_XPRT_FIFO_1,
    826 	    &sc->sc_rx_fifolen);
    827 	if (sc->sc_rx_fifo == NULL)
    828 		return;
    829 
    830 	sc->sc_ipcc = qcipcc_channel(IPCC_CLIENT_LPASS,
    831 	    IPCC_MPROC_SIGNAL_GLINK_QMP);
    832 	if (sc->sc_ipcc == NULL)
    833 		return;
    834 
    835 	TAILQ_INIT(&sc->sc_glink_channels);
    836 
    837 	sc->sc_glink_ih = qcipcc_intr_establish(IPCC_CLIENT_LPASS,
    838 	    IPCC_MPROC_SIGNAL_GLINK_QMP, IPL_VM, qcpas_glink_intr, sc);
    839 	if (sc->sc_glink_ih == NULL)
    840 		return;
    841 
    842 	/* Expect peer to send initial message */
    843 }
    844 
    845 static void
    846 qcpas_glink_rx(struct qcpas_softc *sc, uint8_t *buf, int len)
    847 {
    848 	uint32_t head, tail;
    849 	int avail;
    850 
    851 	head = *sc->sc_rx_head;
    852 	tail = *sc->sc_rx_tail + sc->sc_rx_off;
    853 	if (tail >= sc->sc_rx_fifolen)
    854 		tail -= sc->sc_rx_fifolen;
    855 
    856 	/* Checked by caller */
    857 	KASSERT(head != tail);
    858 
    859 	if (head >= tail)
    860 		avail = head - tail;
    861 	else
    862 		avail = (sc->sc_rx_fifolen - tail) + head;
    863 
    864 	/* Dumb, but should do. */
    865 	KASSERT(avail >= len);
    866 
    867 	while (len > 0) {
    868 		*buf = sc->sc_rx_fifo[tail];
    869 		tail++;
    870 		if (tail >= sc->sc_rx_fifolen)
    871 			tail -= sc->sc_rx_fifolen;
    872 		buf++;
    873 		sc->sc_rx_off++;
    874 		len--;
    875 	}
    876 }
    877 
    878 static void
    879 qcpas_glink_rx_commit(struct qcpas_softc *sc)
    880 {
    881 	uint32_t tail;
    882 
    883 	tail = *sc->sc_rx_tail + roundup(sc->sc_rx_off, 8);
    884 	if (tail >= sc->sc_rx_fifolen)
    885 		tail -= sc->sc_rx_fifolen;
    886 
    887 	membar_producer();
    888 	*sc->sc_rx_tail = tail;
    889 	sc->sc_rx_off = 0;
    890 }
    891 
    892 static void
    893 qcpas_glink_tx(struct qcpas_softc *sc, uint8_t *buf, int len)
    894 {
    895 	uint32_t head, tail;
    896 	int avail;
    897 
    898 	head = *sc->sc_tx_head + sc->sc_tx_off;
    899 	if (head >= sc->sc_tx_fifolen)
    900 		head -= sc->sc_tx_fifolen;
    901 	tail = *sc->sc_tx_tail;
    902 
    903 	if (head < tail)
    904 		avail = tail - head;
    905 	else
    906 		avail = (sc->sc_rx_fifolen - head) + tail;
    907 
    908 	/* Dumb, but should do. */
    909 	KASSERT(avail >= len);
    910 
    911 	while (len > 0) {
    912 		sc->sc_tx_fifo[head] = *buf;
    913 		head++;
    914 		if (head >= sc->sc_tx_fifolen)
    915 			head -= sc->sc_tx_fifolen;
    916 		buf++;
    917 		sc->sc_tx_off++;
    918 		len--;
    919 	}
    920 }
    921 
    922 static void
    923 qcpas_glink_tx_commit(struct qcpas_softc *sc)
    924 {
    925 	uint32_t head;
    926 
    927 	head = *sc->sc_tx_head + roundup(sc->sc_tx_off, 8);
    928 	if (head >= sc->sc_tx_fifolen)
    929 		head -= sc->sc_tx_fifolen;
    930 
    931 	membar_producer();
    932 	*sc->sc_tx_head = head;
    933 	sc->sc_tx_off = 0;
    934 	qcipcc_send(sc->sc_ipcc);
    935 }
    936 
    937 static void
    938 qcpas_glink_send(void *cookie, void *buf, int len)
    939 {
    940 	struct qcpas_glink_channel *ch = cookie;
    941 	struct qcpas_softc *sc = ch->ch_sc;
    942 	struct qcpas_glink_intent *it;
    943 	struct glink_msg msg;
    944 	uint32_t chunk_size, left_size;
    945 
    946 	TAILQ_FOREACH(it, &ch->ch_r_intents, it_q) {
    947 		if (!it->it_inuse)
    948 			break;
    949 		if (it->it_size < len)
    950 			continue;
    951 	}
    952 	if (it == NULL) {
    953 		device_printf(sc->sc_dev, "all intents in use\n");
    954 		return;
    955 	}
    956 	it->it_inuse = 1;
    957 
    958 	msg.cmd = GLINK_CMD_TX_DATA;
    959 	msg.param1 = ch->ch_lcid;
    960 	msg.param2 = it->it_id;
    961 
    962 	chunk_size = len;
    963 	left_size = 0;
    964 
    965 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
    966 	qcpas_glink_tx(sc, (char *)&chunk_size, sizeof(chunk_size));
    967 	qcpas_glink_tx(sc, (char *)&left_size, sizeof(left_size));
    968 	qcpas_glink_tx(sc, buf, len);
    969 	qcpas_glink_tx_commit(sc);
    970 }
    971 
    972 static void
    973 qcpas_glink_recv_version(struct qcpas_softc *sc, uint32_t ver,
    974     uint32_t features)
    975 {
    976 	struct glink_msg msg;
    977 
    978 	if (ver != GLINK_VERSION) {
    979 		device_printf(sc->sc_dev,
    980 		    "unsupported glink version %u\n", ver);
    981 		return;
    982 	}
    983 
    984 	msg.cmd = GLINK_CMD_VERSION_ACK;
    985 	msg.param1 = GLINK_VERSION;
    986 	msg.param2 = features & GLINK_FEATURE_INTENT_REUSE;
    987 
    988 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
    989 	qcpas_glink_tx_commit(sc);
    990 }
    991 
    992 static void
    993 qcpas_glink_recv_open(struct qcpas_softc *sc, uint32_t rcid, uint32_t namelen)
    994 {
    995 	struct qcpas_glink_protocol *proto = NULL;
    996 	struct qcpas_glink_channel *ch;
    997 	struct glink_msg msg;
    998 	char *name;
    999 	int i, err;
   1000 
   1001 	name = kmem_zalloc(namelen, KM_SLEEP);
   1002 	qcpas_glink_rx(sc, name, namelen);
   1003 	qcpas_glink_rx_commit(sc);
   1004 
   1005 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
   1006 		if (ch->ch_rcid == rcid) {
   1007 			device_printf(sc->sc_dev, "duplicate open for %s\n",
   1008 			    name);
   1009 			kmem_free(name, namelen);
   1010 			return;
   1011 		}
   1012 	}
   1013 
   1014 	for (i = 0; i < __arraycount(qcpas_glink_protocols); i++) {
   1015 		if (strcmp(qcpas_glink_protocols[i].name, name) != 0)
   1016 			continue;
   1017 		proto = &qcpas_glink_protocols[i];
   1018 		break;
   1019 	}
   1020 	if (proto == NULL) {
   1021 		kmem_free(name, namelen);
   1022 		return;
   1023 	}
   1024 
   1025 	ch = kmem_zalloc(sizeof(*ch), KM_SLEEP);
   1026 	ch->ch_sc = sc;
   1027 	ch->ch_proto = proto;
   1028 	ch->ch_rcid = rcid;
   1029 	ch->ch_lcid = ++sc->sc_glink_max_channel;
   1030 	TAILQ_INIT(&ch->ch_l_intents);
   1031 	TAILQ_INIT(&ch->ch_r_intents);
   1032 	TAILQ_INSERT_TAIL(&sc->sc_glink_channels, ch, ch_q);
   1033 
   1034 	/* Assume we can leave HW dangling if proto init fails */
   1035 	err = proto->init(ch);
   1036 	if (err) {
   1037 		TAILQ_REMOVE(&sc->sc_glink_channels, ch, ch_q);
   1038 		kmem_free(ch, sizeof(*ch));
   1039 		kmem_free(name, namelen);
   1040 		return;
   1041 	}
   1042 
   1043 	msg.cmd = GLINK_CMD_OPEN_ACK;
   1044 	msg.param1 = ch->ch_rcid;
   1045 	msg.param2 = 0;
   1046 
   1047 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
   1048 	qcpas_glink_tx_commit(sc);
   1049 
   1050 	msg.cmd = GLINK_CMD_OPEN;
   1051 	msg.param1 = ch->ch_lcid;
   1052 	msg.param2 = strlen(name) + 1;
   1053 
   1054 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
   1055 	qcpas_glink_tx(sc, name, strlen(name) + 1);
   1056 	qcpas_glink_tx_commit(sc);
   1057 
   1058 	kmem_free(name, namelen);
   1059 }
   1060 
   1061 static void
   1062 qcpas_glink_recv_open_ack(struct qcpas_softc *sc, uint32_t lcid)
   1063 {
   1064 	struct qcpas_glink_channel *ch;
   1065 	struct glink_msg msg;
   1066 	struct qcpas_glink_intent_pair intent;
   1067 	int i;
   1068 
   1069 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
   1070 		if (ch->ch_lcid == lcid)
   1071 			break;
   1072 	}
   1073 	if (ch == NULL) {
   1074 		device_printf(sc->sc_dev, "unknown channel %u for OPEN_ACK\n",
   1075 		    lcid);
   1076 		return;
   1077 	}
   1078 
   1079 	/* Respond with default intent now that channel is open */
   1080 	for (i = 0; i < 5; i++) {
   1081 		struct qcpas_glink_intent *it;
   1082 
   1083 		it = kmem_zalloc(sizeof(*it), KM_SLEEP);
   1084 		it->it_id = ++ch->ch_max_intent;
   1085 		it->it_size = 1024;
   1086 		TAILQ_INSERT_TAIL(&ch->ch_l_intents, it, it_q);
   1087 
   1088 		msg.cmd = GLINK_CMD_INTENT;
   1089 		msg.param1 = ch->ch_lcid;
   1090 		msg.param2 = 1;
   1091 		intent.size = it->it_size;
   1092 		intent.iid = it->it_id;
   1093 	}
   1094 
   1095 	qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
   1096 	qcpas_glink_tx(sc, (char *)&intent, sizeof(intent));
   1097 	qcpas_glink_tx_commit(sc);
   1098 }
   1099 
   1100 static void
   1101 qcpas_glink_recv_intent(struct qcpas_softc *sc, uint32_t rcid, uint32_t count)
   1102 {
   1103 	struct qcpas_glink_intent_pair *intents;
   1104 	struct qcpas_glink_channel *ch;
   1105 	struct qcpas_glink_intent *it;
   1106 	int i;
   1107 
   1108 	intents = kmem_zalloc(sizeof(*intents) * count, KM_SLEEP);
   1109 	qcpas_glink_rx(sc, (char *)intents, sizeof(*intents) * count);
   1110 	qcpas_glink_rx_commit(sc);
   1111 
   1112 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
   1113 		if (ch->ch_rcid == rcid)
   1114 			break;
   1115 	}
   1116 	if (ch == NULL) {
   1117 		device_printf(sc->sc_dev, "unknown channel %u for INTENT\n",
   1118 		    rcid);
   1119 		kmem_free(intents, sizeof(*intents) * count);
   1120 		return;
   1121 	}
   1122 
   1123 	for (i = 0; i < count; i++) {
   1124 		it = kmem_zalloc(sizeof(*it), KM_SLEEP);
   1125 		it->it_id = intents[i].iid;
   1126 		it->it_size = intents[i].size;
   1127 		TAILQ_INSERT_TAIL(&ch->ch_r_intents, it, it_q);
   1128 	}
   1129 
   1130 	kmem_free(intents, sizeof(*intents) * count);
   1131 }
   1132 
   1133 static void
   1134 qcpas_glink_recv_tx_data(struct qcpas_softc *sc, uint32_t rcid, uint32_t liid)
   1135 {
   1136 	struct qcpas_glink_channel *ch;
   1137 	struct qcpas_glink_intent *it;
   1138 	struct glink_msg msg;
   1139 	uint32_t chunk_size, left_size;
   1140 	char *buf;
   1141 
   1142 	qcpas_glink_rx(sc, (char *)&chunk_size, sizeof(chunk_size));
   1143 	qcpas_glink_rx(sc, (char *)&left_size, sizeof(left_size));
   1144 	qcpas_glink_rx_commit(sc);
   1145 
   1146 	buf = kmem_zalloc(chunk_size, KM_SLEEP);
   1147 	qcpas_glink_rx(sc, buf, chunk_size);
   1148 	qcpas_glink_rx_commit(sc);
   1149 
   1150 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
   1151 		if (ch->ch_rcid == rcid)
   1152 			break;
   1153 	}
   1154 	if (ch == NULL) {
   1155 		device_printf(sc->sc_dev, "unknown channel %u for TX_DATA\n",
   1156 		    rcid);
   1157 		kmem_free(buf, chunk_size);
   1158 		return;
   1159 	}
   1160 
   1161 	TAILQ_FOREACH(it, &ch->ch_l_intents, it_q) {
   1162 		if (it->it_id == liid)
   1163 			break;
   1164 	}
   1165 	if (it == NULL) {
   1166 		device_printf(sc->sc_dev, "unknown intent %u for TX_DATA\n",
   1167 		    liid);
   1168 		kmem_free(buf, chunk_size);
   1169 		return;
   1170 	}
   1171 
   1172 	/* FIXME: handle message chunking */
   1173 	KASSERT(left_size == 0);
   1174 
   1175 	ch->ch_proto->recv(ch, buf, chunk_size);
   1176 	kmem_free(buf, chunk_size);
   1177 
   1178 	if (!left_size) {
   1179 		msg.cmd = GLINK_CMD_RX_DONE_W_REUSE;
   1180 		msg.param1 = ch->ch_lcid;
   1181 		msg.param2 = it->it_id;
   1182 
   1183 		qcpas_glink_tx(sc, (char *)&msg, sizeof(msg));
   1184 		qcpas_glink_tx_commit(sc);
   1185 	}
   1186 }
   1187 
   1188 static void
   1189 qcpas_glink_recv_rx_done(struct qcpas_softc *sc, uint32_t rcid, uint32_t riid,
   1190     int reuse)
   1191 {
   1192 	struct qcpas_glink_channel *ch;
   1193 	struct qcpas_glink_intent *it;
   1194 
   1195 	TAILQ_FOREACH(ch, &sc->sc_glink_channels, ch_q) {
   1196 		if (ch->ch_rcid == rcid)
   1197 			break;
   1198 	}
   1199 	if (ch == NULL) {
   1200 		device_printf(sc->sc_dev, "unknown channel %u for RX_DONE\n",
   1201 		    rcid);
   1202 		return;
   1203 	}
   1204 
   1205 	TAILQ_FOREACH(it, &ch->ch_r_intents, it_q) {
   1206 		if (it->it_id == riid)
   1207 			break;
   1208 	}
   1209 	if (it == NULL) {
   1210 		device_printf(sc->sc_dev, "unknown intent %u for RX_DONE\n",
   1211 		    riid);
   1212 		return;
   1213 	}
   1214 
   1215 	/* FIXME: handle non-reuse */
   1216 	KASSERT(reuse);
   1217 
   1218 	KASSERT(it->it_inuse);
   1219 	it->it_inuse = 0;
   1220 }
   1221 
   1222 static void
   1223 qcpas_glink_recv(void *arg)
   1224 {
   1225 	struct qcpas_softc *sc = arg;
   1226 	struct glink_msg msg;
   1227 
   1228 	while (*sc->sc_rx_tail != *sc->sc_rx_head) {
   1229 		membar_consumer();
   1230 		qcpas_glink_rx(sc, (uint8_t *)&msg, sizeof(msg));
   1231 		qcpas_glink_rx_commit(sc);
   1232 
   1233 		switch (msg.cmd) {
   1234 		case GLINK_CMD_VERSION:
   1235 			qcpas_glink_recv_version(sc, msg.param1, msg.param2);
   1236 			break;
   1237 		case GLINK_CMD_OPEN:
   1238 			qcpas_glink_recv_open(sc, msg.param1, msg.param2);
   1239 			break;
   1240 		case GLINK_CMD_OPEN_ACK:
   1241 			qcpas_glink_recv_open_ack(sc, msg.param1);
   1242 			break;
   1243 		case GLINK_CMD_INTENT:
   1244 			qcpas_glink_recv_intent(sc, msg.param1, msg.param2);
   1245 			break;
   1246 		case GLINK_CMD_RX_INTENT_REQ:
   1247 			/* Nothing to do so far */
   1248 			break;
   1249 		case GLINK_CMD_TX_DATA:
   1250 			qcpas_glink_recv_tx_data(sc, msg.param1, msg.param2);
   1251 			break;
   1252 		case GLINK_CMD_RX_DONE:
   1253 			qcpas_glink_recv_rx_done(sc, msg.param1, msg.param2, 0);
   1254 			break;
   1255 		case GLINK_CMD_RX_DONE_W_REUSE:
   1256 			qcpas_glink_recv_rx_done(sc, msg.param1, msg.param2, 1);
   1257 			break;
   1258 		default:
   1259 			device_printf(sc->sc_dev, "unknown cmd %u\n", msg.cmd);
   1260 			return;
   1261 		}
   1262 	}
   1263 }
   1264 
   1265 static int
   1266 qcpas_glink_intr(void *cookie)
   1267 {
   1268 	struct qcpas_softc *sc = cookie;
   1269 
   1270 	sysmon_task_queue_sched(0, qcpas_glink_recv, sc);
   1271 
   1272 	return 1;
   1273 }
   1274 
   1275 /* GLINK PMIC Router */
   1276 
   1277 struct pmic_glink_hdr {
   1278 	uint32_t owner;
   1279 #define PMIC_GLINK_OWNER_BATTMGR	32778
   1280 #define PMIC_GLINK_OWNER_USBC		32779
   1281 #define PMIC_GLINK_OWNER_USBC_PAN	32780
   1282 	uint32_t type;
   1283 #define PMIC_GLINK_TYPE_REQ_RESP	1
   1284 #define PMIC_GLINK_TYPE_NOTIFY		2
   1285 	uint32_t opcode;
   1286 };
   1287 
   1288 #define BATTMGR_OPCODE_BAT_STATUS		0x1
   1289 #define BATTMGR_OPCODR_REQUEST_NOTIFICATION	0x4
   1290 #define BATTMGR_OPCODE_NOTIF			0x7
   1291 #define BATTMGR_OPCODE_BAT_INFO			0x9
   1292 #define BATTMGR_OPCODE_BAT_DISCHARGE_TIME	0xc
   1293 #define BATTMGR_OPCODE_BAT_CHARGE_TIME		0xd
   1294 
   1295 #define BATTMGR_NOTIF_BAT_PROPERTY		0x30
   1296 #define BATTMGR_NOTIF_USB_PROPERTY		0x32
   1297 #define BATTMGR_NOTIF_WLS_PROPERTY		0x34
   1298 #define BATTMGR_NOTIF_BAT_STATUS		0x80
   1299 #define BATTMGR_NOTIF_BAT_INFO			0x81
   1300 
   1301 #define BATTMGR_CHEMISTRY_LEN			4
   1302 #define BATTMGR_STRING_LEN			128
   1303 
   1304 struct battmgr_bat_info {
   1305 	uint32_t power_unit;
   1306 	uint32_t design_capacity;
   1307 	uint32_t last_full_capacity;
   1308 	uint32_t battery_tech;
   1309 	uint32_t design_voltage;
   1310 	uint32_t capacity_low;
   1311 	uint32_t capacity_warning;
   1312 	uint32_t cycle_count;
   1313 	uint32_t accuracy;
   1314 	uint32_t max_sample_time_ms;
   1315 	uint32_t min_sample_time_ms;
   1316 	uint32_t max_average_interval_ms;
   1317 	uint32_t min_average_interval_ms;
   1318 	uint32_t capacity_granularity1;
   1319 	uint32_t capacity_granularity2;
   1320 	uint32_t swappable;
   1321 	uint32_t capabilities;
   1322 	char model_number[BATTMGR_STRING_LEN];
   1323 	char serial_number[BATTMGR_STRING_LEN];
   1324 	char battery_type[BATTMGR_STRING_LEN];
   1325 	char oem_info[BATTMGR_STRING_LEN];
   1326 	char battery_chemistry[BATTMGR_CHEMISTRY_LEN];
   1327 	char uid[BATTMGR_STRING_LEN];
   1328 	uint32_t critical_bias;
   1329 	uint8_t day;
   1330 	uint8_t month;
   1331 	uint16_t year;
   1332 	uint32_t battery_id;
   1333 };
   1334 
   1335 struct battmgr_bat_status {
   1336 	uint32_t battery_state;
   1337 #define BATTMGR_BAT_STATE_DISCHARGE	(1 << 0)
   1338 #define BATTMGR_BAT_STATE_CHARGING	(1 << 1)
   1339 #define BATTMGR_BAT_STATE_CRITICAL_LOW	(1 << 2)
   1340 	uint32_t capacity;
   1341 	int32_t rate;
   1342 	uint32_t battery_voltage;
   1343 	uint32_t power_state;
   1344 #define BATTMGR_PWR_STATE_AC_ON			(1 << 0)
   1345 	uint32_t charging_source;
   1346 #define BATTMGR_CHARGING_SOURCE_AC		1
   1347 #define BATTMGR_CHARGING_SOURCE_USB		2
   1348 #define BATTMGR_CHARGING_SOURCE_WIRELESS	3
   1349 	uint32_t temperature;
   1350 };
   1351 
   1352 static void	qcpas_pmic_rtr_refresh(void *);
   1353 static void	qcpas_pmic_rtr_bat_info(struct qcpas_softc *,
   1354 		    struct battmgr_bat_info *);
   1355 static void	qcpas_pmic_rtr_bat_status(struct qcpas_softc *,
   1356 		    struct battmgr_bat_status *);
   1357 
   1358 static void
   1359 qcpas_pmic_rtr_battmgr_req_info(void *cookie)
   1360 {
   1361 	struct {
   1362 		struct pmic_glink_hdr hdr;
   1363 		uint32_t battery_id;
   1364 	} msg;
   1365 
   1366 	msg.hdr.owner = PMIC_GLINK_OWNER_BATTMGR;
   1367 	msg.hdr.type = PMIC_GLINK_TYPE_REQ_RESP;
   1368 	msg.hdr.opcode = BATTMGR_OPCODE_BAT_INFO;
   1369 	msg.battery_id = 0;
   1370 	qcpas_glink_send(cookie, &msg, sizeof(msg));
   1371 }
   1372 
   1373 static void
   1374 qcpas_pmic_rtr_battmgr_req_status(void *cookie)
   1375 {
   1376 	struct {
   1377 		struct pmic_glink_hdr hdr;
   1378 		uint32_t battery_id;
   1379 	} msg;
   1380 
   1381 	msg.hdr.owner = PMIC_GLINK_OWNER_BATTMGR;
   1382 	msg.hdr.type = PMIC_GLINK_TYPE_REQ_RESP;
   1383 	msg.hdr.opcode = BATTMGR_OPCODE_BAT_STATUS;
   1384 	msg.battery_id = 0;
   1385 	qcpas_glink_send(cookie, &msg, sizeof(msg));
   1386 }
   1387 
   1388 static int
   1389 qcpas_pmic_rtr_init(void *cookie)
   1390 {
   1391 	struct qcpas_glink_channel *ch = cookie;
   1392 	struct qcpas_softc *sc = ch->ch_sc;
   1393 
   1394 	callout_init(&sc->sc_rtr_refresh, 0);
   1395 	callout_setfunc(&sc->sc_rtr_refresh, qcpas_pmic_rtr_refresh, ch);
   1396 
   1397 	callout_schedule(&sc->sc_rtr_refresh, hz * 5);
   1398 
   1399 	return 0;
   1400 }
   1401 
   1402 static int
   1403 qcpas_pmic_rtr_recv(void *cookie, uint8_t *buf, int len)
   1404 {
   1405 	struct qcpas_glink_channel *ch = cookie;
   1406 	struct qcpas_softc *sc = ch->ch_sc;
   1407 	struct pmic_glink_hdr hdr;
   1408 	uint32_t notification;
   1409 
   1410 	if (len < sizeof(hdr)) {
   1411 		device_printf(sc->sc_dev, "pmic glink message too small\n");
   1412 		return 0;
   1413 	}
   1414 
   1415 	memcpy(&hdr, buf, sizeof(hdr));
   1416 
   1417 	switch (hdr.owner) {
   1418 	case PMIC_GLINK_OWNER_BATTMGR:
   1419 		switch (hdr.opcode) {
   1420 		case BATTMGR_OPCODE_NOTIF:
   1421 			if (len - sizeof(hdr) != sizeof(uint32_t)) {
   1422 				device_printf(sc->sc_dev,
   1423 				    "invalid battgmr notification\n");
   1424 				return 0;
   1425 			}
   1426 			memcpy(&notification, buf + sizeof(hdr),
   1427 			    sizeof(uint32_t));
   1428 			switch (notification) {
   1429 			case BATTMGR_NOTIF_BAT_INFO:
   1430 				qcpas_pmic_rtr_battmgr_req_info(cookie);
   1431 				/* FALLTHROUGH */
   1432 			case BATTMGR_NOTIF_BAT_STATUS:
   1433 			case BATTMGR_NOTIF_BAT_PROPERTY:
   1434 				qcpas_pmic_rtr_battmgr_req_status(cookie);
   1435 				break;
   1436 			default:
   1437 				aprint_debug_dev(sc->sc_dev,
   1438 				    "unknown battmgr notification 0x%02x\n",
   1439 				    notification);
   1440 				break;
   1441 			}
   1442 			break;
   1443 		case BATTMGR_OPCODE_BAT_INFO: {
   1444 			struct battmgr_bat_info *bat;
   1445 			if (len - sizeof(hdr) < sizeof(*bat)) {
   1446 				device_printf(sc->sc_dev,
   1447 				    "invalid battgmr bat info\n");
   1448 				return 0;
   1449 			}
   1450 			bat = kmem_alloc(sizeof(*bat), KM_SLEEP);
   1451 			memcpy(bat, buf + sizeof(hdr), sizeof(*bat));
   1452 			qcpas_pmic_rtr_bat_info(sc, bat);
   1453 			kmem_free(bat, sizeof(*bat));
   1454 			break;
   1455 		}
   1456 		case BATTMGR_OPCODE_BAT_STATUS: {
   1457 			struct battmgr_bat_status *bat;
   1458 			if (len - sizeof(hdr) != sizeof(*bat)) {
   1459 				device_printf(sc->sc_dev,
   1460 				    "invalid battgmr bat status\n");
   1461 				return 0;
   1462 			}
   1463 			bat = kmem_alloc(sizeof(*bat), KM_SLEEP);
   1464 			memcpy(bat, buf + sizeof(hdr), sizeof(*bat));
   1465 			qcpas_pmic_rtr_bat_status(sc, bat);
   1466 			kmem_free(bat, sizeof(*bat));
   1467 			break;
   1468 		}
   1469 		default:
   1470 			device_printf(sc->sc_dev,
   1471 			    "unknown battmgr opcode 0x%02x\n",
   1472 			    hdr.opcode);
   1473 			break;
   1474 		}
   1475 		break;
   1476 	default:
   1477 		device_printf(sc->sc_dev,
   1478 		    "unknown pmic glink owner 0x%04x\n",
   1479 		    hdr.owner);
   1480 		break;
   1481 	}
   1482 
   1483 	return 0;
   1484 }
   1485 
   1486 static void
   1487 qcpas_pmic_rtr_refresh(void *arg)
   1488 {
   1489 	struct qcpas_glink_channel *ch = arg;
   1490 	struct qcpas_softc *sc = ch->ch_sc;
   1491 
   1492 	qcpas_pmic_rtr_battmgr_req_status(ch);
   1493 
   1494 	callout_schedule(&sc->sc_rtr_refresh, hz * 5);
   1495 }
   1496 
   1497 static void
   1498 qcpas_pmic_rtr_bat_info(struct qcpas_softc *sc, struct battmgr_bat_info *bat)
   1499 {
   1500 	sc->sc_warning_capacity = bat->capacity_warning;
   1501 	sc->sc_low_capacity = bat->capacity_low;
   1502 
   1503 	sc->sc_sens[QCPAS_DCAPACITY].value_cur =
   1504 	    bat->design_capacity * 1000;
   1505 	sc->sc_sens[QCPAS_DCAPACITY].state = ENVSYS_SVALID;
   1506 
   1507 	sc->sc_sens[QCPAS_LFCCAPACITY].value_cur =
   1508 	    bat->last_full_capacity * 1000;
   1509 	sc->sc_sens[QCPAS_LFCCAPACITY].state = ENVSYS_SVALID;
   1510 
   1511 	sc->sc_sens[QCPAS_DVOLTAGE].value_cur =
   1512 	    bat->design_voltage * 1000;
   1513 	sc->sc_sens[QCPAS_DVOLTAGE].state = ENVSYS_SVALID;
   1514 
   1515 	sc->sc_sens[QCPAS_DCYCLES].value_cur =
   1516 	    bat->cycle_count;
   1517 	sc->sc_sens[QCPAS_DCYCLES].state = ENVSYS_SVALID;
   1518 
   1519 	sc->sc_sens[QCPAS_CAPACITY].value_max =
   1520 	    bat->last_full_capacity * 1000;
   1521 	sysmon_envsys_update_limits(sc->sc_sme,
   1522 	    &sc->sc_sens[QCPAS_CAPACITY]);
   1523 }
   1524 
   1525 void
   1526 qcpas_pmic_rtr_bat_status(struct qcpas_softc *sc,
   1527     struct battmgr_bat_status *bat)
   1528 {
   1529 	sc->sc_sens[QCPAS_CHARGING].value_cur =
   1530 	    (bat->battery_state & BATTMGR_BAT_STATE_CHARGING) != 0;
   1531 	sc->sc_sens[QCPAS_CHARGING].state = ENVSYS_SVALID;
   1532 	if ((bat->battery_state & BATTMGR_BAT_STATE_CHARGING) != 0) {
   1533 		sc->sc_sens[QCPAS_CHARGERATE].value_cur =
   1534 		    abs(bat->rate) * 1000;
   1535 		sc->sc_sens[QCPAS_CHARGERATE].state = ENVSYS_SVALID;
   1536 		sc->sc_sens[QCPAS_DISCHARGERATE].state = ENVSYS_SINVALID;
   1537 	} else if ((bat->battery_state & BATTMGR_BAT_STATE_DISCHARGE) != 0) {
   1538 		sc->sc_sens[QCPAS_CHARGERATE].state = ENVSYS_SINVALID;
   1539 		sc->sc_sens[QCPAS_DISCHARGERATE].value_cur =
   1540 		    abs(bat->rate) * 1000;
   1541 		sc->sc_sens[QCPAS_DISCHARGERATE].state = ENVSYS_SVALID;
   1542 	} else {
   1543 		sc->sc_sens[QCPAS_DISCHARGERATE].state = ENVSYS_SINVALID;
   1544 		sc->sc_sens[QCPAS_CHARGERATE].state = ENVSYS_SINVALID;
   1545 	}
   1546 
   1547 	sc->sc_sens[QCPAS_VOLTAGE].value_cur =
   1548 	    bat->battery_voltage * 1000;
   1549 	sc->sc_sens[QCPAS_VOLTAGE].state = ENVSYS_SVALID;
   1550 
   1551 	sc->sc_sens[QCPAS_TEMPERATURE].value_cur =
   1552 	    (bat->temperature * 10000) + 273150000;
   1553 	sc->sc_sens[QCPAS_TEMPERATURE].state = ENVSYS_SVALID;
   1554 
   1555 	sc->sc_sens[QCPAS_CAPACITY].value_cur =
   1556 	    bat->capacity * 1000;
   1557 	sc->sc_sens[QCPAS_CAPACITY].state = ENVSYS_SVALID;
   1558 
   1559 	sc->sc_sens[QCPAS_CHARGE_STATE].value_cur =
   1560 	    ENVSYS_BATTERY_CAPACITY_NORMAL;
   1561 	sc->sc_sens[QCPAS_CHARGE_STATE].state = ENVSYS_SVALID;
   1562 
   1563 	if (bat->capacity < sc->sc_warning_capacity) {
   1564 		sc->sc_sens[QCPAS_CAPACITY].state = ENVSYS_SWARNUNDER;
   1565 		sc->sc_sens[QCPAS_CHARGE_STATE].value_cur =
   1566 		    ENVSYS_BATTERY_CAPACITY_WARNING;
   1567 	}
   1568 
   1569 	if (bat->capacity < sc->sc_low_capacity) {
   1570 		sc->sc_sens[QCPAS_CAPACITY].state = ENVSYS_SCRITUNDER;
   1571 		sc->sc_sens[QCPAS_CHARGE_STATE].value_cur =
   1572 		    ENVSYS_BATTERY_CAPACITY_LOW;
   1573 	}
   1574 
   1575 	if ((bat->battery_state & BATTMGR_BAT_STATE_CRITICAL_LOW) != 0) {
   1576 		sc->sc_sens[QCPAS_CAPACITY].state = ENVSYS_SCRITICAL;
   1577 		sc->sc_sens[QCPAS_CHARGE_STATE].value_cur =
   1578 		    ENVSYS_BATTERY_CAPACITY_CRITICAL;
   1579 	}
   1580 
   1581 	if ((bat->power_state & BATTMGR_PWR_STATE_AC_ON) !=
   1582 	    (sc->sc_power_state & BATTMGR_PWR_STATE_AC_ON)) {
   1583 		sysmon_pswitch_event(&sc->sc_smpsw_acadapter,
   1584 		    (bat->power_state & BATTMGR_PWR_STATE_AC_ON) != 0 ?
   1585 		    PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
   1586 
   1587 		aprint_debug_dev(sc->sc_dev, "AC adapter %sconnected\n",
   1588 		    (bat->power_state & BATTMGR_PWR_STATE_AC_ON) == 0 ?
   1589 		    "not " : "");
   1590 	}
   1591 
   1592 	sc->sc_power_state = bat->power_state;
   1593 	sc->sc_sens[QCPAS_ACADAPTER].value_cur =
   1594 	    (bat->power_state & BATTMGR_PWR_STATE_AC_ON) != 0;
   1595 	sc->sc_sens[QCPAS_ACADAPTER].state = ENVSYS_SVALID;
   1596 }
   1597 
   1598 static void
   1599 qcpas_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
   1600     sysmon_envsys_lim_t *limits, uint32_t *props)
   1601 {
   1602 	struct qcpas_softc *sc = sme->sme_cookie;
   1603 
   1604 	if (edata->sensor != QCPAS_CAPACITY) {
   1605 		return;
   1606 	}
   1607 
   1608 	limits->sel_critmin = sc->sc_low_capacity * 1000;
   1609 	limits->sel_warnmin = sc->sc_warning_capacity * 1000;
   1610 
   1611 	*props |= PROP_BATTCAP | PROP_BATTWARN | PROP_DRIVER_LIMITS;
   1612 }
   1613