Reviewed-by: Igor Opaniuk <igor.opan...@linaro.org> On Mon, 28 Jan 2019 at 11:15, Shawn Guo <shawn....@linaro.org> wrote: > > It adds a Driver Model compatible reset driver for HiSlicon platform. > The driver implements a custom .of_xlate function, and uses .data field > as reset register offset and .id field as bit shift. > > Signed-off-by: Shawn Guo <shawn....@linaro.org> > --- > drivers/reset/Kconfig | 6 +++ > drivers/reset/Makefile | 1 + > drivers/reset/reset-hisilicon.c | 95 +++++++++++++++++++++++++++++++++ > 3 files changed, 102 insertions(+) > create mode 100644 drivers/reset/reset-hisilicon.c > > diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig > index a81e76769604..6ec6f39c85f0 100644 > --- a/drivers/reset/Kconfig > +++ b/drivers/reset/Kconfig > @@ -121,4 +121,10 @@ config RESET_SUNXI > This enables support for common reset driver for > Allwinner SoCs. > > +config RESET_HISILICON > + bool "Reset controller driver for HiSilicon SoCs" > + depends on DM_RESET > + help > + Support for reset controller on HiSilicon SoCs. > + > endmenu > diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile > index 4fad7d412985..7fec75bb4923 100644 > --- a/drivers/reset/Makefile > +++ b/drivers/reset/Makefile > @@ -19,3 +19,4 @@ obj-$(CONFIG_RESET_MESON) += reset-meson.o > obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o > obj-$(CONFIG_RESET_MEDIATEK) += reset-mediatek.o > obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o > +obj-$(CONFIG_RESET_HISILICON) += reset-hisilicon.o > diff --git a/drivers/reset/reset-hisilicon.c b/drivers/reset/reset-hisilicon.c > new file mode 100644 > index 000000000000..3a06110f76f3 > --- /dev/null > +++ b/drivers/reset/reset-hisilicon.c > @@ -0,0 +1,95 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2019, Linaro Limited > + */ > + > +#include <asm/io.h> > +#include <common.h> > +#include <dm.h> > +#include <reset-uclass.h> > + > +struct hisi_reset_priv { > + void __iomem *base; > +}; > + > +static int hisi_reset_deassert(struct reset_ctl *rst) > +{ > + struct hisi_reset_priv *priv = dev_get_priv(rst->dev); > + u32 val; > + > + val = readl(priv->base + rst->data); > + val &= ~BIT(rst->id); > + writel(val, priv->base + rst->data); > + > + return 0; > +} > + > +static int hisi_reset_assert(struct reset_ctl *rst) > +{ > + struct hisi_reset_priv *priv = dev_get_priv(rst->dev); > + u32 val; > + > + val = readl(priv->base + rst->data); > + val |= BIT(rst->id); > + writel(val, priv->base + rst->data); > + > + return 0; > +} > + > +static int hisi_reset_free(struct reset_ctl *rst) > +{ > + return 0; > +} > + > +static int hisi_reset_request(struct reset_ctl *rst) > +{ > + return 0; > +} > + > +static int hisi_reset_of_xlate(struct reset_ctl *rst, > + struct ofnode_phandle_args *args) > +{ > + if (args->args_count != 2) { > + debug("Invalid args_count: %d\n", args->args_count); > + return -EINVAL; > + } > + > + /* We use .data field as register offset and .id field as bit shift. > */ > + rst->data = args->args[0]; > + rst->id = args->args[1]; > + > + return 0; > +} > + > +static const struct reset_ops hisi_reset_reset_ops = { > + .of_xlate = hisi_reset_of_xlate, > + .request = hisi_reset_request, > + .free = hisi_reset_free, > + .rst_assert = hisi_reset_assert, > + .rst_deassert = hisi_reset_deassert, > +}; > + > +static const struct udevice_id hisi_reset_ids[] = { > + { .compatible = "hisilicon,hi3798cv200-crg" }, > + { } > +}; > + > +static int hisi_reset_probe(struct udevice *dev) > +{ > + struct hisi_reset_priv *priv = dev_get_priv(dev); > + > + priv->base = dev_remap_addr(dev); > + if (!priv->base) > + return -ENOMEM; > + > + return 0; > +} > + > +U_BOOT_DRIVER(hisi_reset) = { > + .name = "hisilicon_reset", > + .id = UCLASS_RESET, > + .of_match = hisi_reset_ids, > + .ops = &hisi_reset_reset_ops, > + .probe = hisi_reset_probe, > + .priv_auto_alloc_size = sizeof(struct hisi_reset_priv), > +}; > -- > 2.18.0 >
-- Regards, Igor Opaniuk _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot