[PATCH v3 15/21] reset: add driver for generic reset controllers

Andre Przywara andre.przywara at arm.com
Mon Feb 24 15:52:05 CET 2020


On Sat, 25 Jan 2020 17:52:57 +0530
Amit Singh Tomar <amittomer25 at gmail.com> wrote:

Hi,

> The simplest and most generic form of a reset controller just exposes
> multiple MMIO registers, where each bit toggles a separate reset line.
> Add a generic driver to describe this kind of reset controller.
> 
> This is used on the Action Semi S700, for instance, but also by other
> SoCs.

As tempting as this may be, but the S900 uses the more common style of integrating the reset controller in the CMU device:
	mmc0: mmc at e0330000 {
	...
		clocks = <&cmu CLK_SD0>;
		resets = <&cmu RESET_SD0>;
	...

So you should probably follow suit here for the S700 as well, especially as the Linux S700 CMU driver already defines resets, they just don't seem to be used yet.

So please drop this patch and the next one, and integrate the reset functionality in clk_owl.c, similar to what we do for sunxi.

Cheers,
Andre.

> 
> Signed-off-by: Amit Singh Tomar <amittomer25 at gmail.com>
> [Andre: make more generic, let it cover multiple registers, slight rework]
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changes since v2:
>         * Newly added patch, not there in v2/v1.
> ---
>  drivers/reset/Kconfig         |   6 +++
>  drivers/reset/Makefile        |   1 +
>  drivers/reset/reset-generic.c | 111 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 118 insertions(+)
>  create mode 100644 drivers/reset/reset-generic.c
> 
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 75ccd65..1cdc159 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -12,6 +12,12 @@ config DM_RESET
>  	  although driving such reset isgnals using GPIOs may be more
>  	  appropriate in this case.
>  
> +config GENERIC_RESET
> +        bool "Generic Reset controller driver"
> +        depends on DM_RESET
> +        help
> +          Support Generic reset controller.
> +
>  config SANDBOX_RESET
>  	bool "Enable the sandbox reset test driver"
>  	depends on DM_MAILBOX && SANDBOX
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 0a044d5..5e027a1 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -4,6 +4,7 @@
>  #
>  
>  obj-$(CONFIG_DM_RESET) += reset-uclass.o
> +obj-$(CONFIG_GENERIC_RESET) += reset-generic.o
>  obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o
>  obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o
>  obj-$(CONFIG_STI_RESET) += sti-reset.o
> diff --git a/drivers/reset/reset-generic.c b/drivers/reset/reset-generic.c
> new file mode 100644
> index 0000000..9c45087
> --- /dev/null
> +++ b/drivers/reset/reset-generic.c
> @@ -0,0 +1,111 @@
> +/*
> + * Copyright (C) 2017 Amit Singh Tomar <amittomer25 at gmail.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <reset-uclass.h>
> +#include <linux/bitops.h>
> +#include <linux/io.h>
> +#include <linux/sizes.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct generic_reset_priv {
> +	void __iomem *membase;
> +	int max_reset;
> +};
> +
> +#define BITS_PER_BYTE 8
> +static int generic_reset_toggle(struct reset_ctl *rst, bool assert)
> +{
> +	struct generic_reset_priv *priv = dev_get_priv(rst->dev);
> +	int reg_width = sizeof(u32);
> +	int bank, offset;
> +	u32 reg;
> +
> +	if (rst->id >= priv->max_reset)
> +		return -EINVAL;
> +
> +	bank = rst->id / (reg_width * BITS_PER_BYTE);
> +	offset = rst->id % (reg_width * BITS_PER_BYTE);
> +
> +	reg = readl(priv->membase + (bank * reg_width));
> +	if (assert)
> +		writel(reg & ~BIT(offset), priv->membase + (bank * reg_width));
> +	else
> +		writel(reg | BIT(offset), priv->membase + (bank * reg_width));
> +
> +	return 0;
> +}
> +
> +static int generic_reset_assert(struct reset_ctl *rst)
> +{
> +	return generic_reset_toggle(rst, true);
> +}
> +
> +static int generic_reset_deassert(struct reset_ctl *rst)
> +{
> +	return generic_reset_toggle(rst, false);
> +}
> +
> +static int generic_reset_free(struct reset_ctl *rst)
> +{
> +	return 0;
> +}
> +
> +static int generic_reset_request(struct reset_ctl *rst)
> +{
> +	struct generic_reset_priv *priv = dev_get_priv(rst->dev);
> +
> +	if (rst->id >= priv->max_reset)
> +		return -EINVAL;
> +
> +	return generic_reset_assert(rst);
> +}
> +
> +struct reset_ops generic_reset_reset_ops = {
> +	.free = generic_reset_free,
> +	.request = generic_reset_request,
> +	.rst_assert = generic_reset_assert,
> +	.rst_deassert = generic_reset_deassert,
> +};
> +
> +static const struct udevice_id generic_reset_ids[] = {
> +	{ .compatible = "generic-reset" },
> +	{ .compatible = "actions,s700-reset" },
> +	{ }
> +};
> +
> +static int generic_reset_probe(struct udevice *dev)
> +{
> +	struct generic_reset_priv *priv = dev_get_priv(dev);
> +	fdt_addr_t addr;
> +	fdt_size_t size;
> +
> +	addr = devfdt_get_addr_size_index(dev, 0, &size);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +
> +	priv->max_reset = dev_read_u32_default(dev, "num-resets", -1);
> +	if (priv->max_reset == -1)
> +		priv->max_reset = size * BITS_PER_BYTE;
> +
> +	priv->membase = devm_ioremap(dev, addr, size);
> +	if (!priv->membase)
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(generic_reset) = {
> +	.name = "generic_reset",
> +	.id = UCLASS_RESET,
> +	.of_match = generic_reset_ids,
> +	.ops = &generic_reset_reset_ops,
> +	.probe = generic_reset_probe,
> +	.priv_auto_alloc_size = sizeof(struct generic_reset_priv),
> +};



More information about the U-Boot mailing list