Message ID | 20231222150133.732662-3-krzysztof.kozlowski@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | reset: gpio: ASoC: shared GPIO resets | expand |
On 12/22/23 10:01, Krzysztof Kozlowski wrote: > Add simple driver to control GPIO-based resets using the reset > controller API for the cases when the GPIOs are shared and reset should > be coordinated. The driver is expected to be used by reset core > framework for ad-hoc reset controllers. How do we handle power sequencing? Often GPIOs need some pre/post delay in order to ensure proper power sequencing. For regular reset drivers, this is internal to the driver. Maybe something like my-device { reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; reset-gpios-post-deassert-us = <100>; }; Of course, this is a bit ambiguous if you have multiple devices using the same GPIO with different delays. Maybe we take the max? But the driver below seems to only have access to one device. Which I suppose begs the question: how do we know when it's safe to deassert the reset (e.g. we've gotten to the point where all devices using this reset gpio have gotten far enough to detect that they use it)? --Sean > Cc: Bartosz Golaszewski <brgl@bgdev.pl> > Cc: Sean Anderson <sean.anderson@seco.com> > Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> > --- > MAINTAINERS | 5 ++ > drivers/reset/Kconfig | 9 ++++ > drivers/reset/Makefile | 1 + > drivers/reset/reset-gpio.c | 105 +++++++++++++++++++++++++++++++++++++ > 4 files changed, 120 insertions(+) > create mode 100644 drivers/reset/reset-gpio.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 7fe27cd60e1b..a0fbd4814bc7 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -8866,6 +8866,11 @@ F: Documentation/i2c/muxes/i2c-mux-gpio.rst > F: drivers/i2c/muxes/i2c-mux-gpio.c > F: include/linux/platform_data/i2c-mux-gpio.h > > +GENERIC GPIO RESET DRIVER > +M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> > +S: Maintained > +F: drivers/reset/reset-gpio.c > + > GENERIC HDLC (WAN) DRIVERS > M: Krzysztof Halasa <khc@pm.waw.pl> > S: Maintained > diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig > index ccd59ddd7610..bb1b5a326eb7 100644 > --- a/drivers/reset/Kconfig > +++ b/drivers/reset/Kconfig > @@ -66,6 +66,15 @@ config RESET_BRCMSTB_RESCAL > This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on > BCM7216. > > +config RESET_GPIO > + tristate "GPIO reset controller" > + help > + This enables a generic reset controller for resets attached via > + GPIOs. Typically for OF platforms this driver expects "reset-gpios" > + property. > + > + If compiled as module, it will be called reset-gpio. > + > config RESET_HSDK > bool "Synopsys HSDK Reset Driver" > depends on HAS_IOMEM > diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile > index 8270da8a4baa..fd8b49fa46fc 100644 > --- a/drivers/reset/Makefile > +++ b/drivers/reset/Makefile > @@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o > obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o > obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o > obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o > +obj-$(CONFIG_RESET_GPIO) += reset-gpio.o > obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o > obj-$(CONFIG_RESET_IMX7) += reset-imx7.o > obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o > diff --git a/drivers/reset/reset-gpio.c b/drivers/reset/reset-gpio.c > new file mode 100644 > index 000000000000..6952996dbc9f > --- /dev/null > +++ b/drivers/reset/reset-gpio.c > @@ -0,0 +1,105 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/gpio/consumer.h> > +#include <linux/mod_devicetable.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/platform_device.h> > +#include <linux/reset-controller.h> > + > +struct reset_gpio_priv { > + struct reset_controller_dev rc; > + struct gpio_desc *reset; > +}; > + > +static inline struct reset_gpio_priv > +*rc_to_reset_gpio(struct reset_controller_dev *rc) > +{ > + return container_of(rc, struct reset_gpio_priv, rc); > +} > + > +static int reset_gpio_assert(struct reset_controller_dev *rc, unsigned long id) > +{ > + struct reset_gpio_priv *priv = rc_to_reset_gpio(rc); > + > + gpiod_set_value_cansleep(priv->reset, 1); > + > + return 0; > +} > + > +static int reset_gpio_deassert(struct reset_controller_dev *rc, > + unsigned long id) > +{ > + struct reset_gpio_priv *priv = rc_to_reset_gpio(rc); > + > + gpiod_set_value_cansleep(priv->reset, 0); > + > + return 0; > +} > + > +static int reset_gpio_status(struct reset_controller_dev *rc, unsigned long id) > +{ > + struct reset_gpio_priv *priv = rc_to_reset_gpio(rc); > + > + return gpiod_get_value_cansleep(priv->reset); > +} > + > +static const struct reset_control_ops reset_gpio_ops = { > + .assert = reset_gpio_assert, > + .deassert = reset_gpio_deassert, > + .status = reset_gpio_status, > +}; > + > +static int reset_gpio_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct device_node **platdata = dev_get_platdata(dev); > + struct reset_gpio_priv *priv; > + > + if (!platdata && !*platdata) > + return -EINVAL; > + > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, &priv->rc); > + device_set_node(dev, of_fwnode_handle(*platdata)); > + > + /* > + * Need to get non-exclusive because it is used in reset core as cookie > + * to find existing controllers. However the actual use is exclusive. > + */ > + priv->reset = devm_gpiod_get(dev, "reset", > + GPIOD_OUT_HIGH); > + if (IS_ERR(priv->reset)) > + return dev_err_probe(dev, PTR_ERR(priv->reset), > + "Could not get reset gpios\n"); > + > + priv->rc.ops = &reset_gpio_ops; > + priv->rc.owner = THIS_MODULE; > + priv->rc.dev = dev; > + priv->rc.cookie = priv->reset; > + priv->rc.nr_resets = 1; > + > + return devm_reset_controller_register(dev, &priv->rc); > +} > + > +static const struct platform_device_id reset_gpio_ids[] = { > + { .name = "reset-gpio", }, > + {} > +}; > +MODULE_DEVICE_TABLE(platform, reset_gpio_ids); > + > +static struct platform_driver reset_gpio_driver = { > + .probe = reset_gpio_probe, > + .id_table = reset_gpio_ids, > + .driver = { > + .name = "reset-gpio", > + }, > +}; > +module_platform_driver(reset_gpio_driver); > + > +MODULE_AUTHOR("Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>"); > +MODULE_DESCRIPTION("Generic GPIO reset driver"); > +MODULE_LICENSE("GPL");
On 28/12/2023 17:05, Sean Anderson wrote: > On 12/22/23 10:01, Krzysztof Kozlowski wrote: >> Add simple driver to control GPIO-based resets using the reset >> controller API for the cases when the GPIOs are shared and reset should >> be coordinated. The driver is expected to be used by reset core >> framework for ad-hoc reset controllers. > > How do we handle power sequencing? Often GPIOs need some pre/post delay in > order to ensure proper power sequencing. For regular reset drivers, this is > internal to the driver. It's not part of this patchset. Power sequencing is an old topic and generic solutions were failing, rejected, did not solve the problems, etc (choose your reason). Delays are device specific, so they go to drivers (depending on the compatible). Complex power sequencing is way too much for simplified reset-framework handling, so anyway it is expected you do it in your driver. > > Maybe something like > > my-device { > reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; > reset-gpios-post-deassert-us = <100>; Feel free to add it later. This patchset, and actually all patches should, solves one problem while allowing you to extend it later. If there is a architectural problem in my approach not allowing you to extend it later, then we should discuss it. > }; > > Of course, this is a bit ambiguous if you have multiple devices using the same > GPIO with different delays. Maybe we take the max? But the driver below seems > to only have access to one device. Which I suppose begs the question: how do > we know when it's safe to deassert the reset (e.g. we've gotten to the point > where all devices using this reset gpio have gotten far enough to detect that > they use it)? The driver (reset consumer) knows when it is safe or not. You must implement proper reset handling in your driver. Best regards, Krzysztof
On 1/4/24 03:57, Krzysztof Kozlowski wrote: > On 28/12/2023 17:05, Sean Anderson wrote: >> On 12/22/23 10:01, Krzysztof Kozlowski wrote: >>> Add simple driver to control GPIO-based resets using the reset >>> controller API for the cases when the GPIOs are shared and reset should >>> be coordinated. The driver is expected to be used by reset core >>> framework for ad-hoc reset controllers. >> >> How do we handle power sequencing? Often GPIOs need some pre/post delay in >> order to ensure proper power sequencing. For regular reset drivers, this is >> internal to the driver. > > It's not part of this patchset. Power sequencing is an old topic and > generic solutions were failing, rejected, did not solve the problems, > etc (choose your reason). > > Delays are device specific, so they go to drivers (depending on the > compatible). Complex power sequencing is way too much for simplified > reset-framework handling, so anyway it is expected you do it in your driver. Well, the reason to bring it up is twofold: - Traditionally, drivers expect the reset controller to handle all necessary delays. For example, reset-k210 includes a 10us delay between asserting and deasserting the reset. There's a similar thing in reset-imx7, and several other reset drivers. - We would need to add custom assert/deassert delays to every driver using this interface. These are not always added, since any given device may require delays which can be inferred from its compatible. However, an integrated system may require delays to be different from what any individual device requires. >> >> Maybe something like >> >> my-device { >> reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; >> reset-gpios-post-deassert-us = <100>; > > Feel free to add it later. This patchset, and actually all patches > should, solves one problem while allowing you to extend it later. Yes, but we should try to avoid creating problems for ourselves in the future. > If there is a architectural problem in my approach not allowing you to > extend it later, then we should discuss it. Well, I brought up just such an architectural issue below... >> }; >> >> Of course, this is a bit ambiguous if you have multiple devices using the same >> GPIO with different delays. This is the most concerning one to me. >> Maybe we take the max? But the driver below seems >> to only have access to one device. Which I suppose begs the question: how do >> we know when it's safe to deassert the reset (e.g. we've gotten to the point >> where all devices using this reset gpio have gotten far enough to detect that >> they use it)? > > The driver (reset consumer) knows when it is safe or not. You must > implement proper reset handling in your driver. The driver has no idea whether it is safe or not. It just calls reset_assert/deassert at the appropriate time, and the reset framework/controller is supposed to coordinate things so e.g. the device doesn't get reset multiple times as multiple drivers all probe. --Sean
On 04/01/2024 17:04, Sean Anderson wrote: > On 1/4/24 03:57, Krzysztof Kozlowski wrote: >> On 28/12/2023 17:05, Sean Anderson wrote: >>> On 12/22/23 10:01, Krzysztof Kozlowski wrote: >>>> Add simple driver to control GPIO-based resets using the reset >>>> controller API for the cases when the GPIOs are shared and reset should >>>> be coordinated. The driver is expected to be used by reset core >>>> framework for ad-hoc reset controllers. >>> >>> How do we handle power sequencing? Often GPIOs need some pre/post delay in >>> order to ensure proper power sequencing. For regular reset drivers, this is >>> internal to the driver. >> >> It's not part of this patchset. Power sequencing is an old topic and >> generic solutions were failing, rejected, did not solve the problems, >> etc (choose your reason). >> >> Delays are device specific, so they go to drivers (depending on the >> compatible). Complex power sequencing is way too much for simplified >> reset-framework handling, so anyway it is expected you do it in your driver. > > Well, the reason to bring it up is twofold: > > - Traditionally, drivers expect the reset controller to handle all > necessary delays. For example, reset-k210 includes a 10us delay > between asserting and deasserting the reset. There's a similar thing > in reset-imx7, and several other reset drivers. > - We would need to add custom assert/deassert delays to every driver > using this interface. These are not always added, since any given > device may require delays which can be inferred from its compatible. > However, an integrated system may require delays to be different from > what any individual device requires. > >>> >>> Maybe something like >>> >>> my-device { >>> reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; >>> reset-gpios-post-deassert-us = <100>; >> >> Feel free to add it later. This patchset, and actually all patches >> should, solves one problem while allowing you to extend it later. > > Yes, but we should try to avoid creating problems for ourselves in the > future. > >> If there is a architectural problem in my approach not allowing you to >> extend it later, then we should discuss it. > > Well, I brought up just such an architectural issue below... Sorry, but where the issue? You did not present any arguments stating that it is not possible to add your feature. What is the problem to parse that property? > >>> }; >>> >>> Of course, this is a bit ambiguous if you have multiple devices using the same >>> GPIO with different delays. > > This is the most concerning one to me. > >>> Maybe we take the max? But the driver below seems >>> to only have access to one device. Which I suppose begs the question: how do >>> we know when it's safe to deassert the reset (e.g. we've gotten to the point >>> where all devices using this reset gpio have gotten far enough to detect that >>> they use it)? >> >> The driver (reset consumer) knows when it is safe or not. You must >> implement proper reset handling in your driver. > > The driver has no idea whether it is safe or not. It just calls > reset_assert/deassert at the appropriate time, and the reset > framework/controller is supposed to coordinate things so e.g. the device > doesn't get reset multiple times as multiple drivers all probe. Sorry, then I don't get what you refer to. The driver calls deassert when it is safe for it to do it, so the driver *knows*. Now, you claim that driver does not know that... core also does not know, so no one knows. Best regards, Krzysztof
On 04/01/2024 17:04, Sean Anderson wrote: > >>> Maybe we take the max? But the driver below seems >>> to only have access to one device. Which I suppose begs the question: how do >>> we know when it's safe to deassert the reset (e.g. we've gotten to the point >>> where all devices using this reset gpio have gotten far enough to detect that >>> they use it)? >> >> The driver (reset consumer) knows when it is safe or not. You must >> implement proper reset handling in your driver. > > The driver has no idea whether it is safe or not. It just calls > reset_assert/deassert at the appropriate time, and the reset > framework/controller is supposed to coordinate things so e.g. the device > doesn't get reset multiple times as multiple drivers all probe. Hm, wait, now maybe I understand your concern. Did you read the patchset? This is for the coordinated, shared, non-exclusive reset by design. And as stated during previous discussions: that's the driver's job to be sure it is called like that. Best regards, Krzysztof
On 1/4/24 11:08, Krzysztof Kozlowski wrote: > On 04/01/2024 17:04, Sean Anderson wrote: >> On 1/4/24 03:57, Krzysztof Kozlowski wrote: >>> On 28/12/2023 17:05, Sean Anderson wrote: >>>> On 12/22/23 10:01, Krzysztof Kozlowski wrote: >>>>> Add simple driver to control GPIO-based resets using the reset >>>>> controller API for the cases when the GPIOs are shared and reset should >>>>> be coordinated. The driver is expected to be used by reset core >>>>> framework for ad-hoc reset controllers. >>>> >>>> How do we handle power sequencing? Often GPIOs need some pre/post delay in >>>> order to ensure proper power sequencing. For regular reset drivers, this is >>>> internal to the driver. >>> >>> It's not part of this patchset. Power sequencing is an old topic and >>> generic solutions were failing, rejected, did not solve the problems, >>> etc (choose your reason). >>> >>> Delays are device specific, so they go to drivers (depending on the >>> compatible). Complex power sequencing is way too much for simplified >>> reset-framework handling, so anyway it is expected you do it in your driver. >> >> Well, the reason to bring it up is twofold: >> >> - Traditionally, drivers expect the reset controller to handle all >> necessary delays. For example, reset-k210 includes a 10us delay >> between asserting and deasserting the reset. There's a similar thing >> in reset-imx7, and several other reset drivers. >> - We would need to add custom assert/deassert delays to every driver >> using this interface. These are not always added, since any given >> device may require delays which can be inferred from its compatible. >> However, an integrated system may require delays to be different from >> what any individual device requires. >> >>>> >>>> Maybe something like >>>> >>>> my-device { >>>> reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; >>>> reset-gpios-post-deassert-us = <100>; >>> >>> Feel free to add it later. This patchset, and actually all patches >>> should, solves one problem while allowing you to extend it later. >> >> Yes, but we should try to avoid creating problems for ourselves in the >> future. >> >>> If there is a architectural problem in my approach not allowing you to >>> extend it later, then we should discuss it. >> >> Well, I brought up just such an architectural issue below... > > Sorry, but where the issue? You did not present any arguments stating > that it is not possible to add your feature. > > What is the problem to parse that property? > >> >>>> }; >>>> >>>> Of course, this is a bit ambiguous if you have multiple devices using the same >>>> GPIO with different delays. >> >> This is the most concerning one to me. >> >>>> Maybe we take the max? But the driver below seems >>>> to only have access to one device. Which I suppose begs the question: how do >>>> we know when it's safe to deassert the reset (e.g. we've gotten to the point >>>> where all devices using this reset gpio have gotten far enough to detect that >>>> they use it)? >>> >>> The driver (reset consumer) knows when it is safe or not. You must >>> implement proper reset handling in your driver. >> >> The driver has no idea whether it is safe or not. It just calls >> reset_assert/deassert at the appropriate time, and the reset >> framework/controller is supposed to coordinate things so e.g. the device >> doesn't get reset multiple times as multiple drivers all probe. > > > Sorry, then I don't get what you refer to. The driver calls deassert > when it is safe for it to do it, so the driver *knows*. Now, you claim > that driver does not know that... core also does not know, so no one knows. Yes! That is the problem with this design. Someone has to coordinate the reset, and it can't be the driver. But the core also doesn't have enough information. So no one can do it. For example, say we want to share a reset GPIO between two devices. Each device has the following constraints: device post-assert delay post-deassert delay ====== ================= =================== A 500us 1ms B 1ms 300us If we leave things up to the drivers, then whoever probes first will get to decide the reset sequence. So if we choose the post-assert delay to be 1ms and the post-deassert delay to be 1ms then everyone is happy. How can we make sure the reset controller enforces this? Well, we can do the above thing and specify something like A { reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; reset-gpios-post-assert-us = <1000>; reset-gpios-post-deassert-us = <1000>; }; B { reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; }; But what if B gets probed first? Then we will have to also specify the delays on B as well. I'm not a big fan of this because - We have to specify (identical) delays in every consumer (instead of having a central place to put the delays) - Having the delays depend on the probe order (if one of the consumers' delays don't match) will result in bugs for board maintainers. Maybe we should just warn in that case and that is enough? - Actually, the same problem exists for reset-gpios (e.g. if one driver specifies ACTIVE_HIGH and another specifies ACTIVE_LOW). Maybe the delays should go instead on the gpio controller? So something like (taking inspiration from gpio-hog): gpio { gpio-controller; #gpio-cells = <2>; my-reset { gpio-reset; gpio = <555 GPIO_ACTIVE_LOW>; post-assert-us = <1000>; post-deassert-us = <1000>; }; }; > Hm, wait, now maybe I understand your concern. Did you read the > patchset? This is for the coordinated, shared, non-exclusive reset by > design. And as stated during previous discussions: that's the driver's > job to be sure it is called like that. Well, one of the major advantages of moving GPIO resets to a reset controller is that the reset framework can coordinate things if we want. This is a rather natural extension of this patchset IMO. Even if you are not adding this functionality now, it is good not to make it difficult for future work. --Sean
On 04/01/2024 17:30, Sean Anderson wrote: > On 1/4/24 11:08, Krzysztof Kozlowski wrote: >> On 04/01/2024 17:04, Sean Anderson wrote: >>> On 1/4/24 03:57, Krzysztof Kozlowski wrote: >>>> On 28/12/2023 17:05, Sean Anderson wrote: >>>>> On 12/22/23 10:01, Krzysztof Kozlowski wrote: >>>>>> Add simple driver to control GPIO-based resets using the reset >>>>>> controller API for the cases when the GPIOs are shared and reset should >>>>>> be coordinated. The driver is expected to be used by reset core >>>>>> framework for ad-hoc reset controllers. >>>>> >>>>> How do we handle power sequencing? Often GPIOs need some pre/post delay in >>>>> order to ensure proper power sequencing. For regular reset drivers, this is >>>>> internal to the driver. >>>> >>>> It's not part of this patchset. Power sequencing is an old topic and >>>> generic solutions were failing, rejected, did not solve the problems, >>>> etc (choose your reason). >>>> >>>> Delays are device specific, so they go to drivers (depending on the >>>> compatible). Complex power sequencing is way too much for simplified >>>> reset-framework handling, so anyway it is expected you do it in your driver. >>> >>> Well, the reason to bring it up is twofold: >>> >>> - Traditionally, drivers expect the reset controller to handle all >>> necessary delays. For example, reset-k210 includes a 10us delay >>> between asserting and deasserting the reset. There's a similar thing >>> in reset-imx7, and several other reset drivers. >>> - We would need to add custom assert/deassert delays to every driver >>> using this interface. These are not always added, since any given >>> device may require delays which can be inferred from its compatible. >>> However, an integrated system may require delays to be different from >>> what any individual device requires. >>> >>>>> >>>>> Maybe something like >>>>> >>>>> my-device { >>>>> reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; >>>>> reset-gpios-post-deassert-us = <100>; >>>> >>>> Feel free to add it later. This patchset, and actually all patches >>>> should, solves one problem while allowing you to extend it later. >>> >>> Yes, but we should try to avoid creating problems for ourselves in the >>> future. >>> >>>> If there is a architectural problem in my approach not allowing you to >>>> extend it later, then we should discuss it. >>> >>> Well, I brought up just such an architectural issue below... >> >> Sorry, but where the issue? You did not present any arguments stating >> that it is not possible to add your feature. >> >> What is the problem to parse that property? >> >>> >>>>> }; >>>>> >>>>> Of course, this is a bit ambiguous if you have multiple devices using the same >>>>> GPIO with different delays. >>> >>> This is the most concerning one to me. >>> >>>>> Maybe we take the max? But the driver below seems >>>>> to only have access to one device. Which I suppose begs the question: how do >>>>> we know when it's safe to deassert the reset (e.g. we've gotten to the point >>>>> where all devices using this reset gpio have gotten far enough to detect that >>>>> they use it)? >>>> >>>> The driver (reset consumer) knows when it is safe or not. You must >>>> implement proper reset handling in your driver. >>> >>> The driver has no idea whether it is safe or not. It just calls >>> reset_assert/deassert at the appropriate time, and the reset >>> framework/controller is supposed to coordinate things so e.g. the device >>> doesn't get reset multiple times as multiple drivers all probe. >> >> >> Sorry, then I don't get what you refer to. The driver calls deassert >> when it is safe for it to do it, so the driver *knows*. Now, you claim >> that driver does not know that... core also does not know, so no one knows. > > Yes! That is the problem with this design. Someone has to coordinate the > reset, and it can't be the driver. But the core also doesn't have enough > information. So no one can do it. The point is that the driver coordinates. > > For example, say we want to share a reset GPIO between two devices. Each > device has the following constraints: > > device post-assert delay post-deassert delay > ====== ================= =================== > A 500us 1ms > B 1ms 300us And now imagine that these values are incompatible between them, so using 1ms on device A is wrong - too long. This is just not doable. You invented some imaginary case to prove that hardware is broken. Now, if we are back to realistic cases - use just the longest reset time. > > If we leave things up to the drivers, then whoever probes first will get > to decide the reset sequence. In current design yes, but it's not a problem to change it. Where is the limitation? Just read other values and update the reset time. > > So if we choose the post-assert delay to be 1ms and the post-deassert > delay to be 1ms then everyone is happy. How can we make sure the reset No, not everyone is happy, if these values are incompatible. OTOH, if they are compatible, just put same values to your DTS, because that's the requirement of the reset line. > controller enforces this? Well, we can do the above thing and specify > something like > > A { > reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; > reset-gpios-post-assert-us = <1000>; > reset-gpios-post-deassert-us = <1000>; > }; > > B { > reset-gpios = <&gpio 555 GPIO_ACTIVE_LOW>; > }; > > But what if B gets probed first? Then we will have to also specify the > delays on B as well. I'm not a big fan of this because It's a shared reset line, thus the shared or global delays can be described in every place. That's for DT correctness. Now from the driver point of view, there is no problem to update the reset values after probing A. > > - We have to specify (identical) delays in every consumer (instead of > having a central place to put the delays) > - Having the delays depend on the probe order (if one of the consumers' > delays don't match) will result in bugs for board maintainers. Maybe > we should just warn in that case and that is enough? No, it does not depend. Just update the values. > - Actually, the same problem exists for reset-gpios (e.g. if one driver > specifies ACTIVE_HIGH and another specifies ACTIVE_LOW). No, actually this is handled. This is not a shared reset line and it will not be handled. Second device probe should fail. > > Maybe the delays should go instead on the gpio controller? So something > like (taking inspiration from gpio-hog): We talked about this for other patchsets and answer was no, that's not the property of GPIO. > > gpio { > gpio-controller; > #gpio-cells = <2>; > > my-reset { > gpio-reset; > gpio = <555 GPIO_ACTIVE_LOW>; > post-assert-us = <1000>; > post-deassert-us = <1000>; > }; > }; > >> Hm, wait, now maybe I understand your concern. Did you read the >> patchset? This is for the coordinated, shared, non-exclusive reset by >> design. And as stated during previous discussions: that's the driver's >> job to be sure it is called like that. > > Well, one of the major advantages of moving GPIO resets to a reset > controller is that the reset framework can coordinate things if we want. > This is a rather natural extension of this patchset IMO. Even if you are > not adding this functionality now, it is good not to make it difficult > for future work. And nothing is made here difficult. You want same delays on each consumer? No problem in adding them, just few lines. You want contradictory or inconsistent delays? A bit more code, but still nothing here is blocked. You want totally random stuff because hardware is broken? You might need to write dedicated reset controller for your case because generic binding stops being generic for such cases. Best regards, Krzysztof
On Do, 2024-01-04 at 20:08 +0100, Krzysztof Kozlowski wrote: > On 04/01/2024 17:30, Sean Anderson wrote: > > On 1/4/24 11:08, Krzysztof Kozlowski wrote: > > > On 04/01/2024 17:04, Sean Anderson wrote: > > > > On 1/4/24 03:57, Krzysztof Kozlowski wrote: > > > > > The driver (reset consumer) knows when it is safe or not. You must > > > > > implement proper reset handling in your driver. > > > > > > > > The driver has no idea whether it is safe or not. It just calls > > > > reset_assert/deassert at the appropriate time, and the reset > > > > framework/controller is supposed to coordinate things so e.g. the device > > > > doesn't get reset multiple times as multiple drivers all probe. > > > > > > Sorry, then I don't get what you refer to. The driver calls deassert > > > when it is safe for it to do it, so the driver *knows*. Now, you claim > > > that driver does not know that... core also does not know, so no one knows. > > > > Yes! That is the problem with this design. Someone has to coordinate the > > reset, and it can't be the driver. But the core also doesn't have enough > > information. So no one can do it. > > The point is that the driver coordinates. Currently the reset controller API supports two types of shared resets. I hope distinguishing the two types and illustrating them helps the discussion: 1) For devices that just require the reset to be deasserted while they are active, and don't care otherwise, there is the clk-like behavior described in [1]. requested reset signal via reset_control_deassert/assert(): device A: ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ device B: ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ actual reset signal to both devices: ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ In this scenario, there should be no delays in the reset controller driver. reset_control_deassert() may return as soon as the physical reset signal is deasserted [2]. Any post-deassert delays required by the devices are handled in the device drivers, and they can be different for each device. The devices have to be able to cope with a (much) longer post-deassert delay than expected (e.g. device B in this case). It is assumed that the reset signal is initially asserted. The reset-gpio patchset supports this. 2) The second type is for devices that require a single reset pulse for initialization, at any time before they become active. This is described in [3]. requested reset signal via reset_control_reset/rearm(): device A: ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ device B: ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ actual reset signal to both devices: ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ Here the reset controller needs to know the delay between assertion and deassertion - either baked into the hardware or as a delay call in the .reset callback. This is not supported by the reset-gpio patchset. It could be implemented via a delay property in the device tree that would have to be the same for all devices sharing the reset line, and by adding the .reset callback to the reset controller driver. The only issue is that the initial state of the reset line should be deasserted, and at reset_control_get() time, when the reset-gpio controller is instantiated, it is not yet known which type the driver will use. Sharing a reset line between devices of different type is not supported. Unfortunately, this will only fail at reset_control_deassert() / reset_control_reset() time when the second device tries to use the reset control in a different way than the first. [1] https://docs.kernel.org/driver-api/reset.html#assertion-and-deassertion [2] https://docs.kernel.org/driver-api/reset.html#c.reset_control_deassert [3] https://docs.kernel.org/driver-api/reset.html#triggering > > For example, say we want to share a reset GPIO between two devices. Each > > device has the following constraints: > > > > device post-assert delay post-deassert delay > > ====== ================= =================== > > A 500us 1ms > > B 1ms 300us > > And now imagine that these values are incompatible between them, so > using 1ms on device A is wrong - too long. > > This is just not doable. You invented some imaginary case to prove that > hardware is broken. > > Now, if we are back to realistic cases - use just the longest reset time. Right. This all only works if no device has an upper bound to the allowed delays on the shared reset line. I interpret the post-assert delay to be the desired length of the reset pulse between the rising edge and the falling edge in case 2) above, since in case 1) a post-assert delay is not useful. The post-deassert delays are not supposed to be handled by the reset controller drivers at all, except where they are needed to reach the deasserted state on the reset line. Reset drivers that do have post- deassert delays in the .deassert callback might be bending the rules a bit for convenience. regards Philipp
On Thu, Jan 04, 2024 at 08:08:50PM +0100, Krzysztof Kozlowski wrote: > On 04/01/2024 17:30, Sean Anderson wrote: > > device post-assert delay post-deassert delay > > ====== ================= =================== > > A 500us 1ms > > B 1ms 300us ... > Now, if we are back to realistic cases - use just the longest reset time. Isn't the main concern here that when one device probes we don't yet know the times for the other devices? > > If we leave things up to the drivers, then whoever probes first will get > > to decide the reset sequence. > In current design yes, but it's not a problem to change it. Where is the > limitation? Just read other values and update the reset time. We might have already done a reset by that time and earlier devices might prevent later devices from resetting again. It shouldn't be such an issue for the post delay, but might be one for the pre delay.
On 05/01/2024 15:33, Mark Brown wrote: > On Thu, Jan 04, 2024 at 08:08:50PM +0100, Krzysztof Kozlowski wrote: >> On 04/01/2024 17:30, Sean Anderson wrote: > >>> device post-assert delay post-deassert delay >>> ====== ================= =================== >>> A 500us 1ms >>> B 1ms 300us > > ... > >> Now, if we are back to realistic cases - use just the longest reset time. > > Isn't the main concern here that when one device probes we don't yet > know the times for the other devices? You can never know when second device will appear. It might come from modules, DTB overlay etc. If we want to satisfy all users, then we need to wait till all users appear, which I think is not even possible, considering runtime loaded overlays. > >>> If we leave things up to the drivers, then whoever probes first will get >>> to decide the reset sequence. > >> In current design yes, but it's not a problem to change it. Where is the >> limitation? Just read other values and update the reset time. > > We might have already done a reset by that time and earlier devices > might prevent later devices from resetting again. It shouldn't be such > an issue for the post delay, but might be one for the pre delay. If the reset deassert (or assert, depending what's the default state) is triggered in the probe, then it will happen with the probe of the first device. If the delays of that reset are not suitable for the second - not yet probed - then what do you propose? I have the answer: do not use the simple, generic solution. The simple and generic solutions work for simple and generic cases. Best regards, Krzysztof
On 05/01/2024 15:31, Philipp Zabel wrote: >>>> Sorry, then I don't get what you refer to. The driver calls deassert >>>> when it is safe for it to do it, so the driver *knows*. Now, you claim >>>> that driver does not know that... core also does not know, so no one knows. >>> >>> Yes! That is the problem with this design. Someone has to coordinate the >>> reset, and it can't be the driver. But the core also doesn't have enough >>> information. So no one can do it. >> >> The point is that the driver coordinates. > > Currently the reset controller API supports two types of shared resets. > I hope distinguishing the two types and illustrating them helps the > discussion: > > 1) For devices that just require the reset to be deasserted while they > are active, and don't care otherwise, there is the clk-like behavior > described in [1]. > > requested reset signal via reset_control_deassert/assert(): > device A: ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ > device B: ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ > > actual reset signal to both devices: > ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ > > In this scenario, there should be no delays in the reset controller > driver. reset_control_deassert() may return as soon as the physical > reset signal is deasserted [2]. Any post-deassert delays required by > the devices are handled in the device drivers, and they can be > different for each device. The devices have to be able to cope with a > (much) longer post-deassert delay than expected (e.g. device B in this > case). It is assumed that the reset signal is initially asserted. > > The reset-gpio patchset supports this. Yep! :) > > 2) The second type is for devices that require a single reset pulse for > initialization, at any time before they become active. This is > described in [3]. > > requested reset signal via reset_control_reset/rearm(): > device A: ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ > device B: ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ > > actual reset signal to both devices: > ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ > > Here the reset controller needs to know the delay between assertion and > deassertion - either baked into the hardware or as a delay call in the > .reset callback. > > This is not supported by the reset-gpio patchset. It could be Yep, as well. > implemented via a delay property in the device tree that would have to > be the same for all devices sharing the reset line, and by adding the Or through dedicated node to which reset-gpio binds, just like in Sean's code some years ago. Nothing stops achieving that, except of course convincing Rob. The point is that although my design does not solve it, it also does not prevent it in the future. > .reset callback to the reset controller driver. The only issue is that > the initial state of the reset line should be deasserted, and at > reset_control_get() time, when the reset-gpio controller is > instantiated, it is not yet known which type the driver will use. > > Sharing a reset line between devices of different type is not > supported. Unfortunately, this will only fail at > reset_control_deassert() / reset_control_reset() time when the second > device tries to use the reset control in a different way than the > first. > > [1] https://docs.kernel.org/driver-api/reset.html#assertion-and-deassertion > [2] https://docs.kernel.org/driver-api/reset.html#c.reset_control_deassert > [3] https://docs.kernel.org/driver-api/reset.html#triggering > >>> For example, say we want to share a reset GPIO between two devices. Each >>> device has the following constraints: >>> >>> device post-assert delay post-deassert delay >>> ====== ================= =================== >>> A 500us 1ms >>> B 1ms 300us >> >> And now imagine that these values are incompatible between them, so >> using 1ms on device A is wrong - too long. >> >> This is just not doable. You invented some imaginary case to prove that >> hardware is broken. >> >> Now, if we are back to realistic cases - use just the longest reset time. > > Right. This all only works if no device has an upper bound to the > allowed delays on the shared reset line. If device had an upper bound, it would be quite a conflicting design, tricky to implement. I don't think we should target such case with generic solution. > > I interpret the post-assert delay to be the desired length of the reset > pulse between the rising edge and the falling edge in case 2) above, > since in case 1) a post-assert delay is not useful. > > The post-deassert delays are not supposed to be handled by the reset > controller drivers at all, except where they are needed to reach the > deasserted state on the reset line. Reset drivers that do have post- > deassert delays in the .deassert callback might be bending the rules a > bit for convenience. Best regards, Krzysztof
On 1/9/24 04:41, Krzysztof Kozlowski wrote: > On 05/01/2024 15:31, Philipp Zabel wrote: >>>>> Sorry, then I don't get what you refer to. The driver calls deassert >>>>> when it is safe for it to do it, so the driver *knows*. Now, you claim >>>>> that driver does not know that... core also does not know, so no one knows. >>>> >>>> Yes! That is the problem with this design. Someone has to coordinate the >>>> reset, and it can't be the driver. But the core also doesn't have enough >>>> information. So no one can do it. >>> >>> The point is that the driver coordinates. >> >> Currently the reset controller API supports two types of shared resets. >> I hope distinguishing the two types and illustrating them helps the >> discussion: >> >> 1) For devices that just require the reset to be deasserted while they >> are active, and don't care otherwise, there is the clk-like behavior >> described in [1]. >> >> requested reset signal via reset_control_deassert/assert(): >> device A: ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ >> device B: ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ >> >> actual reset signal to both devices: >> ⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺ >> >> In this scenario, there should be no delays in the reset controller >> driver. reset_control_deassert() may return as soon as the physical >> reset signal is deasserted [2]. Any post-deassert delays required by >> the devices are handled in the device drivers, and they can be >> different for each device. The devices have to be able to cope with a >> (much) longer post-deassert delay than expected (e.g. device B in this >> case). It is assumed that the reset signal is initially asserted. >> >> The reset-gpio patchset supports this. > > Yep! :) > >> >> 2) The second type is for devices that require a single reset pulse for >> initialization, at any time before they become active. This is >> described in [3]. >> >> requested reset signal via reset_control_reset/rearm(): >> device A: ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ >> device B: ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ >> >> actual reset signal to both devices: >> ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽/⎺⎺\⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽ >> >> Here the reset controller needs to know the delay between assertion and >> deassertion - either baked into the hardware or as a delay call in the >> .reset callback. >> >> This is not supported by the reset-gpio patchset. It could be > > Yep, as well. > >> implemented via a delay property in the device tree that would have to >> be the same for all devices sharing the reset line, and by adding the > > Or through dedicated node to which reset-gpio binds, just like in Sean's > code some years ago. Nothing stops achieving that, except of course > convincing Rob. The point is that although my design does not solve it, > it also does not prevent it in the future. Given this and > If the reset deassert (or assert, depending what's the default state) is > triggered in the probe, then it will happen with the probe of the first > device. If the delays of that reset are not suitable for the second - > not yet probed - then what do you propose? I have the answer: do not use > the simple, generic solution. The simple and generic solutions work for > simple and generic cases. I think a separate pseudo-device is necessary a generic solution. So I guess I will revive my patchset. >> .reset callback to the reset controller driver. The only issue is that >> the initial state of the reset line should be deasserted, and at >> reset_control_get() time, when the reset-gpio controller is >> instantiated, it is not yet known which type the driver will use. >> >> Sharing a reset line between devices of different type is not >> supported. Unfortunately, this will only fail at >> reset_control_deassert() / reset_control_reset() time when the second >> device tries to use the reset control in a different way than the >> first. >> >> [1] https://cas5-0-urlprotect.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fdocs.kernel.org%2fdriver%2dapi%2freset.html%23assertion%2dand%2ddeassertion&umid=0ba4c26a-9b7a-4e4b-8dba-ac7f2f194fcd&auth=d807158c60b7d2502abde8a2fc01f40662980862-4bd780a2a258eadb798324d4af563d691f01efb6 >> [2] https://cas5-0-urlprotect.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fdocs.kernel.org%2fdriver%2dapi%2freset.html%23c.reset%5fcontrol%5fdeassert&umid=0ba4c26a-9b7a-4e4b-8dba-ac7f2f194fcd&auth=d807158c60b7d2502abde8a2fc01f40662980862-d6349120c92e1887c5765842e10b274192584bde >> [3] https://cas5-0-urlprotect.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fdocs.kernel.org%2fdriver%2dapi%2freset.html%23triggering&umid=0ba4c26a-9b7a-4e4b-8dba-ac7f2f194fcd&auth=d807158c60b7d2502abde8a2fc01f40662980862-973380c68f114aad02c47e69b5ceb92a23759963 >> >>>> For example, say we want to share a reset GPIO between two devices. Each >>>> device has the following constraints: >>>> >>>> device post-assert delay post-deassert delay >>>> ====== ================= =================== >>>> A 500us 1ms >>>> B 1ms 300us >>> >>> And now imagine that these values are incompatible between them, so >>> using 1ms on device A is wrong - too long. >>> >>> This is just not doable. You invented some imaginary case to prove that >>> hardware is broken. >>> >>> Now, if we are back to realistic cases - use just the longest reset time. >> >> Right. This all only works if no device has an upper bound to the >> allowed delays on the shared reset line. > > If device had an upper bound, it would be quite a conflicting design, > tricky to implement. I don't think we should target such case with > generic solution. This is why I had explicit properties for the various durations. That way the system integrator can go through the reset requirements and specify something which satisfies all devices. --Sean
diff --git a/MAINTAINERS b/MAINTAINERS index 7fe27cd60e1b..a0fbd4814bc7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8866,6 +8866,11 @@ F: Documentation/i2c/muxes/i2c-mux-gpio.rst F: drivers/i2c/muxes/i2c-mux-gpio.c F: include/linux/platform_data/i2c-mux-gpio.h +GENERIC GPIO RESET DRIVER +M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> +S: Maintained +F: drivers/reset/reset-gpio.c + GENERIC HDLC (WAN) DRIVERS M: Krzysztof Halasa <khc@pm.waw.pl> S: Maintained diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index ccd59ddd7610..bb1b5a326eb7 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -66,6 +66,15 @@ config RESET_BRCMSTB_RESCAL This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on BCM7216. +config RESET_GPIO + tristate "GPIO reset controller" + help + This enables a generic reset controller for resets attached via + GPIOs. Typically for OF platforms this driver expects "reset-gpios" + property. + + If compiled as module, it will be called reset-gpio. + config RESET_HSDK bool "Synopsys HSDK Reset Driver" depends on HAS_IOMEM diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 8270da8a4baa..fd8b49fa46fc 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o +obj-$(CONFIG_RESET_GPIO) += reset-gpio.o obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o diff --git a/drivers/reset/reset-gpio.c b/drivers/reset/reset-gpio.c new file mode 100644 index 000000000000..6952996dbc9f --- /dev/null +++ b/drivers/reset/reset-gpio.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/gpio/consumer.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/reset-controller.h> + +struct reset_gpio_priv { + struct reset_controller_dev rc; + struct gpio_desc *reset; +}; + +static inline struct reset_gpio_priv +*rc_to_reset_gpio(struct reset_controller_dev *rc) +{ + return container_of(rc, struct reset_gpio_priv, rc); +} + +static int reset_gpio_assert(struct reset_controller_dev *rc, unsigned long id) +{ + struct reset_gpio_priv *priv = rc_to_reset_gpio(rc); + + gpiod_set_value_cansleep(priv->reset, 1); + + return 0; +} + +static int reset_gpio_deassert(struct reset_controller_dev *rc, + unsigned long id) +{ + struct reset_gpio_priv *priv = rc_to_reset_gpio(rc); + + gpiod_set_value_cansleep(priv->reset, 0); + + return 0; +} + +static int reset_gpio_status(struct reset_controller_dev *rc, unsigned long id) +{ + struct reset_gpio_priv *priv = rc_to_reset_gpio(rc); + + return gpiod_get_value_cansleep(priv->reset); +} + +static const struct reset_control_ops reset_gpio_ops = { + .assert = reset_gpio_assert, + .deassert = reset_gpio_deassert, + .status = reset_gpio_status, +}; + +static int reset_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node **platdata = dev_get_platdata(dev); + struct reset_gpio_priv *priv; + + if (!platdata && !*platdata) + return -EINVAL; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, &priv->rc); + device_set_node(dev, of_fwnode_handle(*platdata)); + + /* + * Need to get non-exclusive because it is used in reset core as cookie + * to find existing controllers. However the actual use is exclusive. + */ + priv->reset = devm_gpiod_get(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->reset)) + return dev_err_probe(dev, PTR_ERR(priv->reset), + "Could not get reset gpios\n"); + + priv->rc.ops = &reset_gpio_ops; + priv->rc.owner = THIS_MODULE; + priv->rc.dev = dev; + priv->rc.cookie = priv->reset; + priv->rc.nr_resets = 1; + + return devm_reset_controller_register(dev, &priv->rc); +} + +static const struct platform_device_id reset_gpio_ids[] = { + { .name = "reset-gpio", }, + {} +}; +MODULE_DEVICE_TABLE(platform, reset_gpio_ids); + +static struct platform_driver reset_gpio_driver = { + .probe = reset_gpio_probe, + .id_table = reset_gpio_ids, + .driver = { + .name = "reset-gpio", + }, +}; +module_platform_driver(reset_gpio_driver); + +MODULE_AUTHOR("Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>"); +MODULE_DESCRIPTION("Generic GPIO reset driver"); +MODULE_LICENSE("GPL");
Add simple driver to control GPIO-based resets using the reset controller API for the cases when the GPIOs are shared and reset should be coordinated. The driver is expected to be used by reset core framework for ad-hoc reset controllers. Cc: Bartosz Golaszewski <brgl@bgdev.pl> Cc: Sean Anderson <sean.anderson@seco.com> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> --- MAINTAINERS | 5 ++ drivers/reset/Kconfig | 9 ++++ drivers/reset/Makefile | 1 + drivers/reset/reset-gpio.c | 105 +++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 drivers/reset/reset-gpio.c