From 3d6ac7bb28d02de6e54c896c7b0c886e9328b3f2 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 1 Apr 2023 08:37:23 +0000 Subject: [PATCH] Implement regulator notifiers which get called when the voltage/current for a regulator is changed or when the regulator gets initialized when it attaches for the first time. The latter makes it possible to register a notifier for a regulator that hasn't attached yet. ok dlg@ --- sys/dev/ofw/ofw_regulator.c | 45 ++++++++++++++++++++++++++++++++++++- sys/dev/ofw/ofw_regulator.h | 12 +++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/sys/dev/ofw/ofw_regulator.c b/sys/dev/ofw/ofw_regulator.c index c0b3deba12e..2235dbebd46 100644 --- a/sys/dev/ofw/ofw_regulator.c +++ b/sys/dev/ofw/ofw_regulator.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ofw_regulator.c,v 1.16 2022/02/14 12:54:43 jsg Exp $ */ +/* $OpenBSD: ofw_regulator.c,v 1.17 2023/04/01 08:37:23 kettenis Exp $ */ /* * Copyright (c) 2016 Mark Kettenis * @@ -30,9 +30,13 @@ LIST_HEAD(, regulator_device) regulator_devices = LIST_HEAD_INITIALIZER(regulator_devices); +LIST_HEAD(, regulator_notifier) regulator_notifiers = + LIST_HEAD_INITIALIZER(regulator_notifiers); + int regulator_type(int); uint32_t regulator_gpio_get(int); int regulator_gpio_set(int, uint32_t); +void regulator_do_notify(uint32_t, uint32_t); void regulator_register(struct regulator_device *rd) @@ -73,6 +77,15 @@ regulator_register(struct regulator_device *rd) return; LIST_INSERT_HEAD(®ulator_devices, rd, rd_list); + + if (rd->rd_get_voltage) { + regulator_do_notify(rd->rd_phandle, + regulator_get_voltage(rd->rd_phandle)); + } + if (rd->rd_get_current) { + regulator_do_notify(rd->rd_phandle, + regulator_get_current(rd->rd_phandle)); + } } int @@ -224,12 +237,16 @@ regulator_set_voltage(uint32_t phandle, uint32_t voltage) return EINVAL; if (rd && rd->rd_set_voltage) { + regulator_do_notify(rd->rd_phandle, voltage); + old = rd->rd_get_voltage(rd->rd_cookie); error = rd->rd_set_voltage(rd->rd_cookie, voltage); if (voltage > old && rd->rd_ramp_delay > 0) { delta = voltage - old; delay(howmany(delta, rd->rd_ramp_delay)); } + + regulator_do_notify(rd->rd_phandle, voltage); return error; } @@ -299,12 +316,16 @@ regulator_set_current(uint32_t phandle, uint32_t current) return EINVAL; if (rd && rd->rd_set_current) { + regulator_do_notify(rd->rd_phandle, current); + old = rd->rd_get_current(rd->rd_cookie); error = rd->rd_set_current(rd->rd_cookie, current); if (current > old && rd->rd_ramp_delay > 0) { delta = current - old; delay(howmany(delta, rd->rd_ramp_delay)); } + + regulator_do_notify(rd->rd_phandle, current); return error; } @@ -375,6 +396,7 @@ regulator_gpio_get(int node) int regulator_gpio_set(int node, uint32_t value) { + uint32_t phandle = OF_getpropint(node, "phandle", 0); uint32_t *gpio, *gpios, *states; uint32_t min, max; uint32_t idx; @@ -422,6 +444,8 @@ regulator_gpio_set(int node, uint32_t value) if (i >= slen / (2 * sizeof(uint32_t))) return EINVAL; + regulator_do_notify(phandle, value); + i = 0; gpio = gpios; while (gpio && gpio < gpios + (glen / sizeof(uint32_t))) { @@ -430,8 +454,27 @@ regulator_gpio_set(int node, uint32_t value) i++; } + regulator_do_notify(phandle, value); + free(gpios, M_TEMP, glen); free(states, M_TEMP, slen); return 0; } + +void +regulator_notify(struct regulator_notifier *rn) +{ + LIST_INSERT_HEAD(®ulator_notifiers, rn, rn_list); +} + +void +regulator_do_notify(uint32_t phandle, uint32_t value) +{ + struct regulator_notifier *rn; + + LIST_FOREACH(rn, ®ulator_notifiers, rn_list) { + if (rn->rn_phandle == phandle) + rn->rn_notify(rn->rn_cookie, value); + } +} diff --git a/sys/dev/ofw/ofw_regulator.h b/sys/dev/ofw/ofw_regulator.h index c3fc2bd04cc..5d893b9b948 100644 --- a/sys/dev/ofw/ofw_regulator.h +++ b/sys/dev/ofw/ofw_regulator.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ofw_regulator.h,v 1.7 2019/02/20 07:36:37 patrick Exp $ */ +/* $OpenBSD: ofw_regulator.h,v 1.8 2023/04/01 08:37:23 kettenis Exp $ */ /* * Copyright (c) 2016 Mark Kettenis * @@ -44,4 +44,14 @@ int regulator_set_voltage(uint32_t, uint32_t); uint32_t regulator_get_current(uint32_t); int regulator_set_current(uint32_t, uint32_t); +struct regulator_notifier { + uint32_t rn_phandle; + void *rn_cookie; + void (*rn_notify)(void *, uint32_t); + + LIST_ENTRY(regulator_notifier) rn_list; +}; + +void regulator_notify(struct regulator_notifier *); + #endif /* _DEV_OFW_REGULATOR_H_ */ -- 2.20.1