diff options
-rw-r--r-- | Documentation/devicetree/bindings/reset/uniphier-reset.txt | 27 | ||||
-rw-r--r-- | MAINTAINERS | 7 | ||||
-rw-r--r-- | drivers/reset/Kconfig | 9 | ||||
-rw-r--r-- | drivers/reset/Makefile | 2 | ||||
-rw-r--r-- | drivers/reset/core.c | 238 | ||||
-rw-r--r-- | drivers/reset/reset-gemini.c | 110 | ||||
-rw-r--r-- | drivers/reset/reset-hsdk-v1.c | 137 | ||||
-rw-r--r-- | drivers/reset/reset-sunxi.c | 4 | ||||
-rw-r--r-- | drivers/reset/reset-uniphier.c | 117 | ||||
-rw-r--r-- | drivers/reset/reset-zx2967.c | 2 | ||||
-rw-r--r-- | include/dt-bindings/reset/snps,hsdk-v1-reset.h | 17 | ||||
-rw-r--r-- | include/linux/reset.h | 68 |
12 files changed, 547 insertions, 191 deletions
diff --git a/Documentation/devicetree/bindings/reset/uniphier-reset.txt b/Documentation/devicetree/bindings/reset/uniphier-reset.txt index 83ab0f599c40..68a6f487c409 100644 --- a/Documentation/devicetree/bindings/reset/uniphier-reset.txt +++ b/Documentation/devicetree/bindings/reset/uniphier-reset.txt @@ -6,7 +6,6 @@ System reset Required properties: - compatible: should be one of the following: - "socionext,uniphier-sld3-reset" - for sLD3 SoC "socionext,uniphier-ld4-reset" - for LD4 SoC "socionext,uniphier-pro4-reset" - for Pro4 SoC "socionext,uniphier-sld8-reset" - for sLD8 SoC @@ -37,7 +36,6 @@ Media I/O (MIO) reset, SD reset Required properties: - compatible: should be one of the following: - "socionext,uniphier-sld3-mio-reset" - for sLD3 SoC "socionext,uniphier-ld4-mio-reset" - for LD4 SoC "socionext,uniphier-pro4-mio-reset" - for Pro4 SoC "socionext,uniphier-sld8-mio-reset" - for sLD8 SoC @@ -92,3 +90,28 @@ Example: other nodes ... }; + + +Analog signal amplifier reset +----------------------------- + +Required properties: +- compatible: should be one of the following: + "socionext,uniphier-ld11-adamv-reset" - for LD11 SoC + "socionext,uniphier-ld20-adamv-reset" - for LD20 SoC +- #reset-cells: should be 1. + +Example: + + adamv@57920000 { + compatible = "socionext,uniphier-ld11-adamv", + "simple-mfd", "syscon"; + reg = <0x57920000 0x1000>; + + adamv_rst: reset { + compatible = "socionext,uniphier-ld11-adamv-reset"; + #reset-cells = <1>; + }; + + other nodes ... + }; diff --git a/MAINTAINERS b/MAINTAINERS index 44cb004c765d..3a21e206ada9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12643,6 +12643,13 @@ L: linux-mmc@vger.kernel.org S: Maintained F: drivers/mmc/host/dw_mmc* +SYNOPSYS HSDK RESET CONTROLLER DRIVER +M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> +S: Supported +F: drivers/reset/reset-hsdk-v1.c +F: include/dt-bindings/reset/snps,hsdk-v1-reset.h +F: Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt + SYSTEM CONFIGURATION (SYSCON) M: Lee Jones <lee.jones@linaro.org> M: Arnd Bergmann <arnd@arndb.de> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 608c071e4bbf..52d5251660b9 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -34,12 +34,11 @@ config RESET_BERLIN help This enables the reset controller driver for Marvell Berlin SoCs. -config RESET_GEMINI - bool "Gemini Reset Driver" if COMPILE_TEST - default ARCH_GEMINI - select MFD_SYSCON +config RESET_HSDK_V1 + bool "HSDK v1 Reset Driver" + default n help - This enables the reset controller driver for Cortina Systems Gemini. + This enables the reset controller driver for HSDK v1. config RESET_IMX7 bool "i.MX7 Reset Driver" if COMPILE_TEST diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 7081f9da2599..b62783f50fe5 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o obj-$(CONFIG_RESET_ATH79) += reset-ath79.o obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o -obj-$(CONFIG_RESET_GEMINI) += reset-gemini.o +obj-$(CONFIG_RESET_HSDK_V1) += reset-hsdk-v1.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o obj-$(CONFIG_RESET_MESON) += reset-meson.o diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 0090784ff410..1d21c6f7d56c 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -43,11 +43,24 @@ struct reset_control { unsigned int id; struct kref refcnt; bool shared; + bool array; atomic_t deassert_count; atomic_t triggered_count; }; /** + * struct reset_control_array - an array of reset controls + * @base: reset control for compatibility with reset control API functions + * @num_rstcs: number of reset controls + * @rstc: array of reset controls + */ +struct reset_control_array { + struct reset_control base; + unsigned int num_rstcs; + struct reset_control *rstc[]; +}; + +/** * of_reset_simple_xlate - translate reset_spec to the reset line number * @rcdev: a pointer to the reset controller device * @reset_spec: reset line specifier as found in the device tree @@ -135,6 +148,65 @@ int devm_reset_controller_register(struct device *dev, } EXPORT_SYMBOL_GPL(devm_reset_controller_register); +static inline struct reset_control_array * +rstc_to_array(struct reset_control *rstc) { + return container_of(rstc, struct reset_control_array, base); +} + +static int reset_control_array_reset(struct reset_control_array *resets) +{ + int ret, i; + + for (i = 0; i < resets->num_rstcs; i++) { + ret = reset_control_reset(resets->rstc[i]); + if (ret) + return ret; + } + + return 0; +} + +static int reset_control_array_assert(struct reset_control_array *resets) +{ + int ret, i; + + for (i = 0; i < resets->num_rstcs; i++) { + ret = reset_control_assert(resets->rstc[i]); + if (ret) + goto err; + } + + return 0; + +err: + while (i--) + reset_control_deassert(resets->rstc[i]); + return ret; +} + +static int reset_control_array_deassert(struct reset_control_array *resets) +{ + int ret, i; + + for (i = 0; i < resets->num_rstcs; i++) { + ret = reset_control_deassert(resets->rstc[i]); + if (ret) + goto err; + } + + return 0; + +err: + while (i--) + reset_control_assert(resets->rstc[i]); + return ret; +} + +static inline bool reset_control_is_array(struct reset_control *rstc) +{ + return rstc->array; +} + /** * reset_control_reset - reset the controlled device * @rstc: reset controller @@ -158,6 +230,9 @@ int reset_control_reset(struct reset_control *rstc) if (WARN_ON(IS_ERR(rstc))) return -EINVAL; + if (reset_control_is_array(rstc)) + return reset_control_array_reset(rstc_to_array(rstc)); + if (!rstc->rcdev->ops->reset) return -ENOTSUPP; @@ -202,8 +277,8 @@ int reset_control_assert(struct reset_control *rstc) if (WARN_ON(IS_ERR(rstc))) return -EINVAL; - if (!rstc->rcdev->ops->assert) - return -ENOTSUPP; + if (reset_control_is_array(rstc)) + return reset_control_array_assert(rstc_to_array(rstc)); if (rstc->shared) { if (WARN_ON(atomic_read(&rstc->triggered_count) != 0)) @@ -214,6 +289,21 @@ int reset_control_assert(struct reset_control *rstc) if (atomic_dec_return(&rstc->deassert_count) != 0) return 0; + + /* + * Shared reset controls allow the reset line to be in any state + * after this call, so doing nothing is a valid option. + */ + if (!rstc->rcdev->ops->assert) + return 0; + } else { + /* + * If the reset controller does not implement .assert(), there + * is no way to guarantee that the reset line is asserted after + * this call. + */ + if (!rstc->rcdev->ops->assert) + return -ENOTSUPP; } return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); @@ -240,8 +330,8 @@ int reset_control_deassert(struct reset_control *rstc) if (WARN_ON(IS_ERR(rstc))) return -EINVAL; - if (!rstc->rcdev->ops->deassert) - return -ENOTSUPP; + if (reset_control_is_array(rstc)) + return reset_control_array_deassert(rstc_to_array(rstc)); if (rstc->shared) { if (WARN_ON(atomic_read(&rstc->triggered_count) != 0)) @@ -251,6 +341,16 @@ int reset_control_deassert(struct reset_control *rstc) return 0; } + /* + * If the reset controller does not implement .deassert(), we assume + * that it handles self-deasserting reset lines via .reset(). In that + * case, the reset lines are deasserted by default. If that is not the + * case, the reset controller driver should implement .deassert() and + * return -ENOTSUPP. + */ + if (!rstc->rcdev->ops->deassert) + return 0; + return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id); } EXPORT_SYMBOL_GPL(reset_control_deassert); @@ -266,7 +366,7 @@ int reset_control_status(struct reset_control *rstc) if (!rstc) return 0; - if (WARN_ON(IS_ERR(rstc))) + if (WARN_ON(IS_ERR(rstc)) || reset_control_is_array(rstc)) return -EINVAL; if (rstc->rcdev->ops->status) @@ -404,6 +504,16 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, } EXPORT_SYMBOL_GPL(__reset_control_get); +static void reset_control_array_put(struct reset_control_array *resets) +{ + int i; + + mutex_lock(&reset_list_mutex); + for (i = 0; i < resets->num_rstcs; i++) + __reset_control_put_internal(resets->rstc[i]); + mutex_unlock(&reset_list_mutex); +} + /** * reset_control_put - free the reset controller * @rstc: reset controller @@ -413,6 +523,11 @@ void reset_control_put(struct reset_control *rstc) if (IS_ERR_OR_NULL(rstc)) return; + if (reset_control_is_array(rstc)) { + reset_control_array_put(rstc_to_array(rstc)); + return; + } + mutex_lock(&reset_list_mutex); __reset_control_put_internal(rstc); mutex_unlock(&reset_list_mutex); @@ -472,3 +587,116 @@ int device_reset(struct device *dev) return ret; } EXPORT_SYMBOL_GPL(device_reset); + +/** + * APIs to manage an array of reset controls. + */ +/** + * of_reset_control_get_count - Count number of resets available with a device + * + * @node: device node that contains 'resets'. + * + * Returns positive reset count on success, or error number on failure and + * on count being zero. + */ +static int of_reset_control_get_count(struct device_node *node) +{ + int count; + + if (!node) + return -EINVAL; + + count = of_count_phandle_with_args(node, "resets", "#reset-cells"); + if (count == 0) + count = -ENOENT; + + return count; +} + +/** + * of_reset_control_array_get - Get a list of reset controls using + * device node. + * + * @np: device node for the device that requests the reset controls array + * @shared: whether reset controls are shared or not + * @optional: whether it is optional to get the reset controls + * + * Returns pointer to allocated reset_control_array on success or + * error on failure + */ +struct reset_control * +of_reset_control_array_get(struct device_node *np, bool shared, bool optional) +{ + struct reset_control_array *resets; + struct reset_control *rstc; + int num, i; + + num = of_reset_control_get_count(np); + if (num < 0) + return optional ? NULL : ERR_PTR(num); + + resets = kzalloc(sizeof(*resets) + sizeof(resets->rstc[0]) * num, + GFP_KERNEL); + if (!resets) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < num; i++) { + rstc = __of_reset_control_get(np, NULL, i, shared, optional); + if (IS_ERR(rstc)) + goto err_rst; + resets->rstc[i] = rstc; + } + resets->num_rstcs = num; + resets->base.array = true; + + return &resets->base; + +err_rst: + mutex_lock(&reset_list_mutex); + while (--i >= 0) + __reset_control_put_internal(resets->rstc[i]); + mutex_unlock(&reset_list_mutex); + + kfree(resets); + + return rstc; +} +EXPORT_SYMBOL_GPL(of_reset_control_array_get); + +/** + * devm_reset_control_array_get - Resource managed reset control array get + * + * @dev: device that requests the list of reset controls + * @shared: whether reset controls are shared or not + * @optional: whether it is optional to get the reset controls + * + * The reset control array APIs are intended for a list of resets + * that just have to be asserted or deasserted, without any + * requirements on the order. + * + * Returns pointer to allocated reset_control_array on success or + * error on failure + */ +struct reset_control * +devm_reset_control_array_get(struct device *dev, bool shared, bool optional) +{ + struct reset_control **devres; + struct reset_control *rstc; + + devres = devres_alloc(devm_reset_control_release, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return ERR_PTR(-ENOMEM); + + rstc = of_reset_control_array_get(dev->of_node, shared, optional); + if (IS_ERR(rstc)) { + devres_free(devres); + return rstc; + } + + *devres = rstc; + devres_add(dev, devres); + + return rstc; +} +EXPORT_SYMBOL_GPL(devm_reset_control_array_get); diff --git a/drivers/reset/reset-gemini.c b/drivers/reset/reset-gemini.c deleted file mode 100644 index a2478997c75b..000000000000 --- a/drivers/reset/reset-gemini.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Cortina Gemini Reset controller driver - * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/err.h> -#include <linux/init.h> -#include <linux/mfd/syscon.h> -#include <linux/regmap.h> -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/reset-controller.h> -#include <dt-bindings/reset/cortina,gemini-reset.h> - -/** - * struct gemini_reset - gemini reset controller - * @map: regmap to access the containing system controller - * @rcdev: reset controller device - */ -struct gemini_reset { - struct regmap *map; - struct reset_controller_dev rcdev; -}; - -#define GEMINI_GLOBAL_SOFT_RESET 0x0c - -#define to_gemini_reset(p) \ - container_of((p), struct gemini_reset, rcdev) - -/* - * This is a self-deasserting reset controller. - */ -static int gemini_reset(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct gemini_reset *gr = to_gemini_reset(rcdev); - - /* Manual says to always set BIT 30 (CPU1) to 1 */ - return regmap_write(gr->map, - GEMINI_GLOBAL_SOFT_RESET, - BIT(GEMINI_RESET_CPU1) | BIT(id)); -} - -static int gemini_reset_status(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct gemini_reset *gr = to_gemini_reset(rcdev); - u32 val; - int ret; - - ret = regmap_read(gr->map, GEMINI_GLOBAL_SOFT_RESET, &val); - if (ret) - return ret; - - return !!(val & BIT(id)); -} - -static const struct reset_control_ops gemini_reset_ops = { - .reset = gemini_reset, - .status = gemini_reset_status, -}; - -static int gemini_reset_probe(struct platform_device *pdev) -{ - struct gemini_reset *gr; - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - int ret; - - gr = devm_kzalloc(dev, sizeof(*gr), GFP_KERNEL); - if (!gr) - return -ENOMEM; - - gr->map = syscon_node_to_regmap(np); - if (IS_ERR(gr->map)) { - ret = PTR_ERR(gr->map); - dev_err(dev, "unable to get regmap (%d)", ret); - return ret; - } - gr->rcdev.owner = THIS_MODULE; - gr->rcdev.nr_resets = 32; - gr->rcdev.ops = &gemini_reset_ops; - gr->rcdev.of_node = pdev->dev.of_node; - - ret = devm_reset_controller_register(&pdev->dev, &gr->rcdev); - if (ret) - return ret; - - dev_info(dev, "registered Gemini reset controller\n"); - return 0; -} - -static const struct of_device_id gemini_reset_dt_ids[] = { - { .compatible = "cortina,gemini-syscon", }, - { /* sentinel */ }, -}; - -static struct platform_driver gemini_reset_driver = { - .probe = gemini_reset_probe, - .driver = { - .name = "gemini-reset", - .of_match_table = gemini_reset_dt_ids, - .suppress_bind_attrs = true, - }, -}; -builtin_platform_driver(gemini_reset_driver); diff --git a/drivers/reset/reset-hsdk-v1.c b/drivers/reset/reset-hsdk-v1.c new file mode 100644 index 000000000000..bca13e4bf622 --- /dev/null +++ b/drivers/reset/reset-hsdk-v1.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2017 Synopsys. + * + * Synopsys HSDKv1 SDP reset driver. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/reset-controller.h> +#include <linux/slab.h> +#include <linux/types.h> + +#define to_hsdkv1_rst(p) container_of((p), struct hsdkv1_rst, rcdev) + +struct hsdkv1_rst { + void __iomem *regs_ctl; + void __iomem *regs_rst; + spinlock_t lock; + struct reset_controller_dev rcdev; +}; + +static const u32 rst_map[] = { + BIT(16), /* APB_RST */ + BIT(17), /* AXI_RST */ + BIT(18), /* ETH_RST */ + BIT(19), /* USB_RST */ + BIT(20), /* SDIO_RST */ + BIT(21), /* HDMI_RST */ + BIT(22), /* GFX_RST */ + BIT(25), /* DMAC_RST */ + BIT(31), /* EBI_RST */ +}; + +#define HSDK_MAX_RESETS ARRAY_SIZE(rst_map) + +#define CGU_SYS_RST_CTRL 0x0 +#define CGU_IP_SW_RESET 0x0 +#define CGU_IP_SW_RESET_DELAY_SHIFT 16 +#define CGU_IP_SW_RESET_DELAY_MASK GENMASK(31, CGU_IP_SW_RESET_DELAY_SHIFT) +#define CGU_IP_SW_RESET_DELAY 0 +#define CGU_IP_SW_RESET_RESET BIT(0) +#define SW_RESET_TIMEOUT 10000 + +static void hsdkv1_reset_config(struct hsdkv1_rst *rst, unsigned long id) +{ + writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL); +} + +static int hsdkv1_reset_do(struct hsdkv1_rst *rst) +{ + u32 reg; + + reg = readl(rst->regs_rst + CGU_IP_SW_RESET); + reg &= ~CGU_IP_SW_RESET_DELAY_MASK; + reg |= CGU_IP_SW_RESET_DELAY << CGU_IP_SW_RESET_DELAY_SHIFT; + reg |= CGU_IP_SW_RESET_RESET; + writel(reg, rst->regs_rst + CGU_IP_SW_RESET); + + /* wait till reset bit is back to 0 */ + return readl_poll_timeout_atomic(rst->regs_rst + CGU_IP_SW_RESET, reg, + !(reg & CGU_IP_SW_RESET_RESET), 5, SW_RESET_TIMEOUT); +} + +static int hsdkv1_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct hsdkv1_rst *rst = to_hsdkv1_rst(rcdev); + unsigned long flags; + int ret; + + spin_lock_irqsave(&rst->lock, flags); + hsdkv1_reset_config(rst, id); + ret = hsdkv1_reset_do(rst); + spin_unlock_irqrestore(&rst->lock, flags); + + return ret; +} + +static const struct reset_control_ops hsdkv1_reset_ops = { + .reset = hsdkv1_reset_reset, +}; + +static int hsdkv1_reset_probe(struct platform_device *pdev) +{ + struct hsdkv1_rst *rst; + struct resource *mem; + + rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL); + if (!rst) + return -ENOMEM; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rst->regs_ctl = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(rst->regs_ctl)) + return PTR_ERR(rst->regs_ctl); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); + rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(rst->regs_rst)) + return PTR_ERR(rst->regs_rst); + + spin_lock_init(&rst->lock); + + rst->rcdev.owner = THIS_MODULE; + rst->rcdev.ops = &hsdkv1_reset_ops; + rst->rcdev.of_node = pdev->dev.of_node; + rst->rcdev.nr_resets = HSDK_MAX_RESETS; + rst->rcdev.of_reset_n_cells = 1; + + return reset_controller_register(&rst->rcdev); +} + +static const struct of_device_id hsdkv1_reset_dt_match[] = { + { .compatible = "snps,hsdk-v1.0-reset" }, + { }, +}; + +static struct platform_driver hsdkv1_reset_driver = { + .probe = hsdkv1_reset_probe, + .driver = { + .name = "hsdk-v1.0-reset", + .of_match_table = hsdkv1_reset_dt_match, + }, +}; +builtin_platform_driver(hsdkv1_reset_driver); + +MODULE_AUTHOR("Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>"); +MODULE_DESCRIPTION("Synopsys HSDKv1 SDP reset driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c index cd585cd2f04d..2c7dd1fd08df 100644 --- a/drivers/reset/reset-sunxi.c +++ b/drivers/reset/reset-sunxi.c @@ -107,7 +107,7 @@ static int sunxi_reset_init(struct device_node *np) spin_lock_init(&data->lock); data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = size * 32; + data->rcdev.nr_resets = size * 8; data->rcdev.ops = &sunxi_reset_ops; data->rcdev.of_node = np; @@ -162,7 +162,7 @@ static int sunxi_reset_probe(struct platform_device *pdev) spin_lock_init(&data->lock); data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = resource_size(res) * 32; + data->rcdev.nr_resets = resource_size(res) * 8; data->rcdev.ops = &sunxi_reset_ops; data->rcdev.of_node = pdev->dev.of_node; diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c index c4ba89832796..bda2dd196ae5 100644 --- a/drivers/reset/reset-uniphier.c +++ b/drivers/reset/reset-uniphier.c @@ -50,59 +50,35 @@ struct uniphier_reset_data { } /* System reset data */ -#define UNIPHIER_SLD3_SYS_RESET_NAND(id) \ - UNIPHIER_RESETX((id), 0x2004, 2) - -#define UNIPHIER_LD11_SYS_RESET_NAND(id) \ - UNIPHIER_RESETX((id), 0x200c, 0) - -#define UNIPHIER_LD11_SYS_RESET_EMMC(id) \ - UNIPHIER_RESETX((id), 0x200c, 2) - -#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \ - UNIPHIER_RESETX((id), 0x2000, 10) - -#define UNIPHIER_LD11_SYS_RESET_STDMAC(id) \ - UNIPHIER_RESETX((id), 0x200c, 8) - -#define UNIPHIER_PRO4_SYS_RESET_GIO(id) \ - UNIPHIER_RESETX((id), 0x2000, 6) - -#define UNIPHIER_LD20_SYS_RESET_GIO(id) \ - UNIPHIER_RESETX((id), 0x200c, 5) - -#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \ - UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17) - -static const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = { - UNIPHIER_SLD3_SYS_RESET_NAND(2), - UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */ +static const struct uniphier_reset_data uniphier_ld4_sys_reset_data[] = { + UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */ + UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (Ether, HSC, MIO) */ UNIPHIER_RESET_END, }; static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { - UNIPHIER_SLD3_SYS_RESET_NAND(2), - UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */ - UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */ - UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), - UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */ + UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, MIO, RLE) */ + UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (Ether, SATA, USB3) */ + UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */ + UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */ UNIPHIER_RESET_END, }; static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = { - UNIPHIER_SLD3_SYS_RESET_NAND(2), - UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */ - UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */ - UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), - UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */ + UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC) */ + UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (PCIe, USB3) */ + UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */ + UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */ UNIPHIER_RESET_END, }; static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { - UNIPHIER_SLD3_SYS_RESET_NAND(2), - UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */ - UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), - UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */ + UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, RLE) */ + UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */ + UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */ UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */ UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */ UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */ @@ -114,21 +90,27 @@ static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { }; static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = { - UNIPHIER_LD11_SYS_RESET_NAND(2), - UNIPHIER_LD11_SYS_RESET_EMMC(4), - UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */ + UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */ + UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */ + UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC, MIO) */ + UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */ + UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */ + UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */ UNIPHIER_RESET_END, }; static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { - UNIPHIER_LD11_SYS_RESET_NAND(2), - UNIPHIER_LD11_SYS_RESET_EMMC(4), - UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */ - UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */ + UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */ + UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */ + UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC) */ + UNIPHIER_RESETX(12, 0x200c, 5), /* GIO (PCIe, USB3) */ UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */ UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */ UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */ UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */ + UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */ + UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */ + UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */ UNIPHIER_RESET_END, }; @@ -151,7 +133,7 @@ static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { #define UNIPHIER_MIO_RESET_DMAC(id) \ UNIPHIER_RESETX((id), 0x110, 17) -static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = { +static const struct uniphier_reset_data uniphier_ld4_mio_reset_data[] = { UNIPHIER_MIO_RESET_SD(0, 0), UNIPHIER_MIO_RESET_SD(1, 1), UNIPHIER_MIO_RESET_SD(2, 2), @@ -163,11 +145,9 @@ static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = { UNIPHIER_MIO_RESET_USB2(8, 0), UNIPHIER_MIO_RESET_USB2(9, 1), UNIPHIER_MIO_RESET_USB2(10, 2), - UNIPHIER_MIO_RESET_USB2(11, 3), UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0), UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1), UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2), - UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3), UNIPHIER_RESET_END, }; @@ -216,6 +196,12 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { UNIPHIER_RESET_END, }; +/* Analog signal amplifiers reset data */ +static const struct uniphier_reset_data uniphier_ld11_adamv_reset_data[] = { + UNIPHIER_RESETX(0, 0x10, 6), /* EVEA */ + UNIPHIER_RESET_END, +}; + /* core implementaton */ struct uniphier_reset_priv { struct reset_controller_dev rcdev; @@ -346,12 +332,8 @@ static int uniphier_reset_probe(struct platform_device *pdev) static const struct of_device_id uniphier_reset_match[] = { /* System reset */ { - .compatible = "socionext,uniphier-sld3-reset", - .data = uniphier_sld3_sys_reset_data, - }, - { .compatible = "socionext,uniphier-ld4-reset", - .data = uniphier_sld3_sys_reset_data, + .data = uniphier_ld4_sys_reset_data, }, { .compatible = "socionext,uniphier-pro4-reset", @@ -359,7 +341,7 @@ static const struct of_device_id uniphier_reset_match[] = { }, { .compatible = "socionext,uniphier-sld8-reset", - .data = uniphier_sld3_sys_reset_data, + .data = uniphier_ld4_sys_reset_data, }, { .compatible = "socionext,uniphier-pro5-reset", @@ -379,20 +361,16 @@ static const struct of_device_id uniphier_reset_match[] = { }, /* Media I/O reset, SD reset */ { - .compatible = "socionext,uniphier-sld3-mio-reset", - .data = uniphier_sld3_mio_reset_data, - }, - { .compatible = "socionext,uniphier-ld4-mio-reset", - .data = uniphier_sld3_mio_reset_data, + .data = uniphier_ld4_mio_reset_data, }, { .compatible = "socionext,uniphier-pro4-mio-reset", - .data = uniphier_sld3_mio_reset_data, + .data = uniphier_ld4_mio_reset_data, }, { .compatible = "socionext,uniphier-sld8-mio-reset", - .data = uniphier_sld3_mio_reset_data, + .data = uniphier_ld4_mio_reset_data, }, { .compatible = "socionext,uniphier-pro5-sd-reset", @@ -404,7 +382,7 @@ static const struct of_device_id uniphier_reset_match[] = { }, { .compatible = "socionext,uniphier-ld11-mio-reset", - .data = uniphier_sld3_mio_reset_data, + .data = uniphier_ld4_mio_reset_data, }, { .compatible = "socionext,uniphier-ld11-sd-reset", @@ -443,6 +421,15 @@ static const struct of_device_id uniphier_reset_match[] = { .compatible = "socionext,uniphier-ld20-peri-reset", .data = uniphier_pro4_peri_reset_data, }, + /* Analog signal amplifiers reset */ + { + .compatible = "socionext,uniphier-ld11-adamv-reset", + .data = uniphier_ld11_adamv_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-adamv-reset", + .data = uniphier_ld11_adamv_reset_data, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, uniphier_reset_match); diff --git a/drivers/reset/reset-zx2967.c b/drivers/reset/reset-zx2967.c index 4dabb9ec4841..4f319f7753d4 100644 --- a/drivers/reset/reset-zx2967.c +++ b/drivers/reset/reset-zx2967.c @@ -55,7 +55,7 @@ static int zx2967_reset_deassert(struct reset_controller_dev *rcdev, return zx2967_reset_act(rcdev, id, false); } -static struct reset_control_ops zx2967_reset_ops = { +static const struct reset_control_ops zx2967_reset_ops = { .assert = zx2967_reset_assert, .deassert = zx2967_reset_deassert, }; diff --git a/include/dt-bindings/reset/snps,hsdk-v1-reset.h b/include/dt-bindings/reset/snps,hsdk-v1-reset.h new file mode 100644 index 000000000000..d898c89b7123 --- /dev/null +++ b/include/dt-bindings/reset/snps,hsdk-v1-reset.h @@ -0,0 +1,17 @@ +/** + * This header provides index for the HSDK v1 reset controller. + */ +#ifndef _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1 +#define _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1 + +#define HSDK_V1_APB_RESET 0 +#define HSDK_V1_AXI_RESET 1 +#define HSDK_V1_ETH_RESET 2 +#define HSDK_V1_USB_RESET 3 +#define HSDK_V1_SDIO_RESET 4 +#define HSDK_V1_HDMI_RESET 5 +#define HSDK_V1_GFX_RESET 6 +#define HSDK_V1_DMAC_RESET 7 +#define HSDK_V1_EBI_RESET 8 + +#endif /*_DT_BINDINGS_RESET_CONTROLLER_HSDK_V1*/ diff --git a/include/linux/reset.h b/include/linux/reset.h index 13d8681210d5..56463f37f3e6 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -25,6 +25,11 @@ struct reset_control *__devm_reset_control_get(struct device *dev, int __must_check device_reset(struct device *dev); +struct reset_control *devm_reset_control_array_get(struct device *dev, + bool shared, bool optional); +struct reset_control *of_reset_control_array_get(struct device_node *np, + bool shared, bool optional); + static inline int device_reset_optional(struct device *dev) { return device_reset(dev); @@ -89,6 +94,18 @@ static inline struct reset_control *__devm_reset_control_get( return optional ? NULL : ERR_PTR(-ENOTSUPP); } +static inline struct reset_control * +devm_reset_control_array_get(struct device *dev, bool shared, bool optional) +{ + return optional ? NULL : ERR_PTR(-ENOTSUPP); +} + +static inline struct reset_control * +of_reset_control_array_get(struct device_node *np, bool shared, bool optional) +{ + return optional ? NULL : ERR_PTR(-ENOTSUPP); +} + #endif /* CONFIG_RESET_CONTROLLER */ /** @@ -374,4 +391,55 @@ static inline struct reset_control *devm_reset_control_get_by_index( { return devm_reset_control_get_exclusive_by_index(dev, index); } + +/* + * APIs to manage a list of reset controllers + */ +static inline struct reset_control * +devm_reset_control_array_get_exclusive(struct device *dev) +{ + return devm_reset_control_array_get(dev, false, false); +} + +static inline struct reset_control * +devm_reset_control_array_get_shared(struct device *dev) +{ + return devm_reset_control_array_get(dev, true, false); +} + +static inline struct reset_control * +devm_reset_control_array_get_optional_exclusive(struct device *dev) +{ + return devm_reset_control_array_get(dev, false, true); +} + +static inline struct reset_control * +devm_reset_control_array_get_optional_shared(struct device *dev) +{ + return devm_reset_control_array_get(dev, true, true); +} + +static inline struct reset_control * +of_reset_control_array_get_exclusive(struct device_node *node) +{ + return of_reset_control_array_get(node, false, false); +} + +static inline struct reset_control * +of_reset_control_array_get_shared(struct device_node *node) +{ + return of_reset_control_array_get(node, true, false); +} + +static inline struct reset_control * +of_reset_control_array_get_optional_exclusive(struct device_node *node) +{ |