This commit is contained in:
purplerain 2023-05-18 12:23:26 +00:00
parent 9e7f51724c
commit 4b78db449c
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
42 changed files with 1110 additions and 143 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ofw_misc.c,v 1.42 2023/04/26 21:37:46 patrick Exp $ */
/* $OpenBSD: ofw_misc.c,v 1.43 2023/05/17 23:25:45 patrick Exp $ */
/*
* Copyright (c) 2017-2021 Mark Kettenis
*
@ -1344,3 +1344,108 @@ mbox_recv(struct mbox_channel *mc, void *data, size_t len)
return ENXIO;
}
/* hwlock support */
LIST_HEAD(, hwlock_device) hwlock_devices =
LIST_HEAD_INITIALIZER(hwlock_devices);
void
hwlock_register(struct hwlock_device *hd)
{
hd->hd_cells = OF_getpropint(hd->hd_node, "#hwlock-cells", 0);
hd->hd_phandle = OF_getpropint(hd->hd_node, "phandle", 0);
if (hd->hd_phandle == 0)
return;
LIST_INSERT_HEAD(&hwlock_devices, hd, hd_list);
}
int
hwlock_lock_cells(uint32_t *cells, int lock)
{
struct hwlock_device *hd;
uint32_t phandle = cells[0];
LIST_FOREACH(hd, &hwlock_devices, hd_list) {
if (hd->hd_phandle == phandle)
break;
}
if (hd && hd->hd_lock)
return hd->hd_lock(hd->hd_cookie, &cells[1], lock);
return ENXIO;
}
uint32_t *
hwlock_next_hwlock(uint32_t *cells)
{
uint32_t phandle = cells[0];
int node, ncells;
node = OF_getnodebyphandle(phandle);
if (node == 0)
return NULL;
ncells = OF_getpropint(node, "#hwlock-cells", 0);
return cells + ncells + 1;
}
int
hwlock_do_lock_idx(int node, int idx, int lock)
{
uint32_t *hwlocks;
uint32_t *hwlock;
int rv = -1;
int len;
len = OF_getproplen(node, "hwlocks");
if (len <= 0)
return -1;
hwlocks = malloc(len, M_TEMP, M_WAITOK);
OF_getpropintarray(node, "hwlocks", hwlocks, len);
hwlock = hwlocks;
while (hwlock && hwlock < hwlocks + (len / sizeof(uint32_t))) {
if (idx <= 0)
rv = hwlock_lock_cells(hwlock, lock);
if (idx == 0)
break;
hwlock = hwlock_next_hwlock(hwlock);
idx--;
}
free(hwlocks, M_TEMP, len);
return rv;
}
int
hwlock_lock_idx(int node, int idx)
{
return hwlock_do_lock_idx(node, idx, 1);
}
int
hwlock_lock_idx_timeout(int node, int idx, int ms)
{
int i, ret = ENXIO;
for (i = 0; i <= ms; i++) {
ret = hwlock_do_lock_idx(node, idx, 1);
if (ret == EAGAIN) {
delay(1000);
continue;
}
break;
}
return ret;
}
int
hwlock_unlock_idx(int node, int idx)
{
return hwlock_do_lock_idx(node, idx, 0);
}