From ee4fec5f44a2c0f59327748217319f78e49b90a7 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 7 Jul 2016 02:08:38 +0000 Subject: memory: atmel-ebi: use PTR_ERR_OR_ZERO() to simplify the code Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR. Generated by coccinelle. Signed-off-by: Wei Yongjun Signed-off-by: Alexandre Belloni --- drivers/memory/atmel-ebi.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c index f87ad6f5d2dc..b5ed3bd082b5 100644 --- a/drivers/memory/atmel-ebi.c +++ b/drivers/memory/atmel-ebi.c @@ -410,10 +410,7 @@ static int at91sam9_ebi_init(struct at91_ebi *ebi) field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC); fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); - if (IS_ERR(fields->mode)) - return PTR_ERR(fields->mode); - - return 0; + return PTR_ERR_OR_ZERO(fields->mode); } static int sama5d3_ebi_init(struct at91_ebi *ebi) @@ -441,10 +438,7 @@ static int sama5d3_ebi_init(struct at91_ebi *ebi) field.reg = SAMA5_SMC_MODE(SAMA5_SMC_GENERIC); fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field); - if (IS_ERR(fields->mode)) - return PTR_ERR(fields->mode); - - return 0; + return PTR_ERR_OR_ZERO(fields->mode); } static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np, -- cgit v1.2.3 From 6b37d3e956a43dba0d340fd112df185b7516fc66 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 4 Jul 2016 19:47:56 +0200 Subject: reset: socfpga: no need to store modrst_offset Since we can just add it to membase once, there is no need to store modrst_offset separately, and to repeat the addition with every access. Signed-off-by: Philipp Zabel Tested-by: Dinh Nguyen --- drivers/reset/reset-socfpga.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index 12add9b0fa49..78ebf8424375 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -28,7 +28,6 @@ struct socfpga_reset_data { spinlock_t lock; void __iomem *membase; - u32 modrst_offset; struct reset_controller_dev rcdev; }; @@ -45,9 +44,8 @@ static int socfpga_reset_assert(struct reset_controller_dev *rcdev, spin_lock_irqsave(&data->lock, flags); - reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS)); - writel(reg | BIT(offset), data->membase + data->modrst_offset + - (bank * NR_BANKS)); + reg = readl(data->membase + (bank * NR_BANKS)); + writel(reg | BIT(offset), data->membase + (bank * NR_BANKS)); spin_unlock_irqrestore(&data->lock, flags); return 0; @@ -67,9 +65,8 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev, spin_lock_irqsave(&data->lock, flags); - reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS)); - writel(reg & ~BIT(offset), data->membase + data->modrst_offset + - (bank * NR_BANKS)); + reg = readl(data->membase + (bank * NR_BANKS)); + writel(reg & ~BIT(offset), data->membase + (bank * NR_BANKS)); spin_unlock_irqrestore(&data->lock, flags); @@ -85,7 +82,7 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev, int offset = id % BITS_PER_LONG; u32 reg; - reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS)); + reg = readl(data->membase + (bank * NR_BANKS)); return !(reg & BIT(offset)); } @@ -102,6 +99,7 @@ static int socfpga_reset_probe(struct platform_device *pdev) struct resource *res; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + u32 modrst_offset; /* * The binding was mainlined without the required property. @@ -122,10 +120,11 @@ static int socfpga_reset_probe(struct platform_device *pdev) if (IS_ERR(data->membase)) return PTR_ERR(data->membase); - if (of_property_read_u32(np, "altr,modrst-offset", &data->modrst_offset)) { + if (of_property_read_u32(np, "altr,modrst-offset", &modrst_offset)) { dev_warn(dev, "missing altr,modrst-offset property, assuming 0x10!\n"); - data->modrst_offset = 0x10; + modrst_offset = 0x10; } + data->membase += modrst_offset; spin_lock_init(&data->lock); -- cgit v1.2.3 From 2d301c0721f59d20bb82a901ba8fad7b74c95728 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 30 Jun 2016 17:07:05 +0200 Subject: bus: tegra-aconnect: Make symbol tristate The driver uses symbols that weren't being exported in earlier versions of the Linux kernel and hence it had to be made bool. The exports have been merged into v4.8-rc1, so the driver can now be built as a module again. Signed-off-by: Thierry Reding --- drivers/bus/Kconfig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 3b205e212337..4ed7d26e0d19 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -132,12 +132,8 @@ config SUNXI_RSB with various RSB based devices, such as AXP223, AXP8XX PMICs, and AC100/AC200 ICs. -# TODO: This uses pm_clk_*() symbols that aren't exported in v4.7 and hence -# the driver will fail to build as a module. However there are patches to -# address that queued for v4.8, so this can be turned into a tristate symbol -# after v4.8-rc1. config TEGRA_ACONNECT - bool "Tegra ACONNECT Bus Driver" + tristate "Tegra ACONNECT Bus Driver" depends on ARCH_TEGRA_210_SOC depends on OF && PM select PM_CLK -- cgit v1.2.3 From 3a99cb090b523f88d0a19598d39704afac11adcb Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 16 Aug 2016 11:17:36 +0100 Subject: bus: tegra-aconnect: Use of_pm_clk_add_clk() Commit 498b5fdd40dd ("PM / clk: Add support for adding a specific clock from device-tree") add a new helper function for adding a clock from device-tree to a device. Update the Tegra ACONNECT driver to use this new function to simplify the driver. Signed-off-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/bus/tegra-aconnect.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/bus/tegra-aconnect.c b/drivers/bus/tegra-aconnect.c index 7e4104b74fa8..084ae286fa23 100644 --- a/drivers/bus/tegra-aconnect.c +++ b/drivers/bus/tegra-aconnect.c @@ -15,24 +15,6 @@ #include #include -static int tegra_aconnect_add_clock(struct device *dev, char *name) -{ - struct clk *clk; - int ret; - - clk = clk_get(dev, name); - if (IS_ERR(clk)) { - dev_err(dev, "%s clock not found\n", name); - return PTR_ERR(clk); - } - - ret = pm_clk_add_clk(dev, clk); - if (ret) - clk_put(clk); - - return ret; -} - static int tegra_aconnect_probe(struct platform_device *pdev) { int ret; @@ -44,11 +26,11 @@ static int tegra_aconnect_probe(struct platform_device *pdev) if (ret) return ret; - ret = tegra_aconnect_add_clock(&pdev->dev, "ape"); + ret = of_pm_clk_add_clk(&pdev->dev, "ape"); if (ret) goto clk_destroy; - ret = tegra_aconnect_add_clock(&pdev->dev, "apb2ape"); + ret = of_pm_clk_add_clk(&pdev->dev, "apb2ape"); if (ret) goto clk_destroy; -- cgit v1.2.3 From a9ccc123a8e05365f7515dcd023b01100809a6fa Mon Sep 17 00:00:00 2001 From: Vince Hsu Date: Thu, 11 Aug 2016 09:13:36 +0800 Subject: soc/tegra: pmc: Fix incorrect DPD request Reading the DPD_REQ & DPD2_REQ registers returns the previous requests. If we sets the current request bit with the returned value, then other pads will be turned on or off unexpectedly. Signed-off-by: Vince Hsu Reviewed-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/soc/tegra/pmc.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 71c834f3847e..7792ed88d80b 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -967,8 +967,8 @@ static void tegra_io_rail_unprepare(void) int tegra_io_rail_power_on(unsigned int id) { - unsigned long request, status, value; - unsigned int bit, mask; + unsigned long request, status; + unsigned int bit; int err; mutex_lock(&pmc->powergates_lock); @@ -977,15 +977,9 @@ int tegra_io_rail_power_on(unsigned int id) if (err) goto error; - mask = 1 << bit; + tegra_pmc_writel(IO_DPD_REQ_CODE_OFF | BIT(bit), request); - value = tegra_pmc_readl(request); - value |= mask; - value &= ~IO_DPD_REQ_CODE_MASK; - value |= IO_DPD_REQ_CODE_OFF; - tegra_pmc_writel(value, request); - - err = tegra_io_rail_poll(status, mask, 0, 250); + err = tegra_io_rail_poll(status, BIT(bit), 0, 250); if (err) { pr_info("tegra_io_rail_poll() failed: %d\n", err); goto error; @@ -1002,8 +996,8 @@ EXPORT_SYMBOL(tegra_io_rail_power_on); int tegra_io_rail_power_off(unsigned int id) { - unsigned long request, status, value; - unsigned int bit, mask; + unsigned long request, status; + unsigned int bit; int err; mutex_lock(&pmc->powergates_lock); @@ -1014,15 +1008,9 @@ int tegra_io_rail_power_off(unsigned int id) goto error; } - mask = 1 << bit; - - value = tegra_pmc_readl(request); - value |= mask; - value &= ~IO_DPD_REQ_CODE_MASK; - value |= IO_DPD_REQ_CODE_ON; - tegra_pmc_writel(value, request); + tegra_pmc_writel(IO_DPD_REQ_CODE_ON | BIT(bit), request); - err = tegra_io_rail_poll(status, mask, mask, 250); + err = tegra_io_rail_poll(status, BIT(bit), BIT(bit), 250); if (err) goto error; -- cgit v1.2.3 From 6f27ab3e424a9532fd8e36c8732abb38eb0da993 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Thu, 18 Aug 2016 18:24:39 +0800 Subject: soc: rockchip: support active_wakeup for rockchip power-domains Register gpd_dev_ops.active_wakeup function to support keep power during suspend state. And add flag to each power domain to decide whether keep power during suspend or not. Signed-off-by: Elaine Zhang Signed-off-by: Heiko Stuebner --- drivers/soc/rockchip/pm_domains.c | 100 ++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 44842a205e4b..7acd1517dd37 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -27,6 +27,7 @@ struct rockchip_domain_info { int req_mask; int idle_mask; int ack_mask; + bool active_wakeup; }; struct rockchip_pmu_info { @@ -75,23 +76,24 @@ struct rockchip_pmu { #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd) -#define DOMAIN(pwr, status, req, idle, ack) \ +#define DOMAIN(pwr, status, req, idle, ack, wakeup) \ { \ .pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \ .status_mask = (status >= 0) ? BIT(status) : 0, \ .req_mask = (req >= 0) ? BIT(req) : 0, \ .idle_mask = (idle >= 0) ? BIT(idle) : 0, \ .ack_mask = (ack >= 0) ? BIT(ack) : 0, \ + .active_wakeup = wakeup, \ } -#define DOMAIN_RK3288(pwr, status, req) \ - DOMAIN(pwr, status, req, req, (req) + 16) +#define DOMAIN_RK3288(pwr, status, req, wakeup) \ + DOMAIN(pwr, status, req, req, (req) + 16, wakeup) -#define DOMAIN_RK3368(pwr, status, req) \ - DOMAIN(pwr, status, req, (req) + 16, req) +#define DOMAIN_RK3368(pwr, status, req, wakeup) \ + DOMAIN(pwr, status, req, (req) + 16, req, wakeup) -#define DOMAIN_RK3399(pwr, status, req) \ - DOMAIN(pwr, status, req, req, req) +#define DOMAIN_RK3399(pwr, status, req, wakeup) \ + DOMAIN(pwr, status, req, req, req, wakeup) static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) { @@ -295,6 +297,17 @@ static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd, pm_clk_destroy(dev); } +static bool rockchip_active_wakeup(struct device *dev) +{ + struct generic_pm_domain *genpd; + struct rockchip_pm_domain *pd; + + genpd = pd_to_genpd(dev->pm_domain); + pd = container_of(genpd, struct rockchip_pm_domain, genpd); + + return pd->info->active_wakeup; +} + static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, struct device_node *node) { @@ -415,6 +428,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, pd->genpd.power_on = rockchip_pd_power_on; pd->genpd.attach_dev = rockchip_pd_attach_dev; pd->genpd.detach_dev = rockchip_pd_detach_dev; + pd->genpd.dev_ops.active_wakeup = rockchip_active_wakeup; pd->genpd.flags = GENPD_FLAG_PM_CLK; pm_genpd_init(&pd->genpd, NULL, false); @@ -623,48 +637,48 @@ err_out: } static const struct rockchip_domain_info rk3288_pm_domains[] = { - [RK3288_PD_VIO] = DOMAIN_RK3288(7, 7, 4), - [RK3288_PD_HEVC] = DOMAIN_RK3288(14, 10, 9), - [RK3288_PD_VIDEO] = DOMAIN_RK3288(8, 8, 3), - [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2), + [RK3288_PD_VIO] = DOMAIN_RK3288(7, 7, 4, false), + [RK3288_PD_HEVC] = DOMAIN_RK3288(14, 10, 9, false), + [RK3288_PD_VIDEO] = DOMAIN_RK3288(8, 8, 3, false), + [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2, false), }; static const struct rockchip_domain_info rk3368_pm_domains[] = { - [RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6), - [RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8), - [RK3368_PD_VIDEO] = DOMAIN_RK3368(14, 13, 7), - [RK3368_PD_GPU_0] = DOMAIN_RK3368(16, 15, 2), - [RK3368_PD_GPU_1] = DOMAIN_RK3368(17, 16, 2), + [RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true), + [RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false), + [RK3368_PD_VIDEO] = DOMAIN_RK3368(14, 13, 7, false), + [RK3368_PD_GPU_0] = DOMAIN_RK3368(16, 15, 2, false), + [RK3368_PD_GPU_1] = DOMAIN_RK3368(17, 16, 2, false), }; static const struct rockchip_domain_info rk3399_pm_domains[] = { - [RK3399_PD_TCPD0] = DOMAIN_RK3399(8, 8, -1), - [RK3399_PD_TCPD1] = DOMAIN_RK3399(9, 9, -1), - [RK3399_PD_CCI] = DOMAIN_RK3399(10, 10, -1), - [RK3399_PD_CCI0] = DOMAIN_RK3399(-1, -1, 15), - [RK3399_PD_CCI1] = DOMAIN_RK3399(-1, -1, 16), - [RK3399_PD_PERILP] = DOMAIN_RK3399(11, 11, 1), - [RK3399_PD_PERIHP] = DOMAIN_RK3399(12, 12, 2), - [RK3399_PD_CENTER] = DOMAIN_RK3399(13, 13, 14), - [RK3399_PD_VIO] = DOMAIN_RK3399(14, 14, 17), - [RK3399_PD_GPU] = DOMAIN_RK3399(15, 15, 0), - [RK3399_PD_VCODEC] = DOMAIN_RK3399(16, 16, 3), - [RK3399_PD_VDU] = DOMAIN_RK3399(17, 17, 4), - [RK3399_PD_RGA] = DOMAIN_RK3399(18, 18, 5), - [RK3399_PD_IEP] = DOMAIN_RK3399(19, 19, 6), - [RK3399_PD_VO] = DOMAIN_RK3399(20, 20, -1), - [RK3399_PD_VOPB] = DOMAIN_RK3399(-1, -1, 7), - [RK3399_PD_VOPL] = DOMAIN_RK3399(-1, -1, 8), - [RK3399_PD_ISP0] = DOMAIN_RK3399(22, 22, 9), - [RK3399_PD_ISP1] = DOMAIN_RK3399(23, 23, 10), - [RK3399_PD_HDCP] = DOMAIN_RK3399(24, 24, 11), - [RK3399_PD_GMAC] = DOMAIN_RK3399(25, 25, 23), - [RK3399_PD_EMMC] = DOMAIN_RK3399(26, 26, 24), - [RK3399_PD_USB3] = DOMAIN_RK3399(27, 27, 12), - [RK3399_PD_EDP] = DOMAIN_RK3399(28, 28, 22), - [RK3399_PD_GIC] = DOMAIN_RK3399(29, 29, 27), - [RK3399_PD_SD] = DOMAIN_RK3399(30, 30, 28), - [RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399(31, 31, 29), + [RK3399_PD_TCPD0] = DOMAIN_RK3399(8, 8, -1, false), + [RK3399_PD_TCPD1] = DOMAIN_RK3399(9, 9, -1, false), + [RK3399_PD_CCI] = DOMAIN_RK3399(10, 10, -1, true), + [RK3399_PD_CCI0] = DOMAIN_RK3399(-1, -1, 15, true), + [RK3399_PD_CCI1] = DOMAIN_RK3399(-1, -1, 16, true), + [RK3399_PD_PERILP] = DOMAIN_RK3399(11, 11, 1, true), + [RK3399_PD_PERIHP] = DOMAIN_RK3399(12, 12, 2, true), + [RK3399_PD_CENTER] = DOMAIN_RK3399(13, 13, 14, true), + [RK3399_PD_VIO] = DOMAIN_RK3399(14, 14, 17, false), + [RK3399_PD_GPU] = DOMAIN_RK3399(15, 15, 0, false), + [RK3399_PD_VCODEC] = DOMAIN_RK3399(16, 16, 3, false), + [RK3399_PD_VDU] = DOMAIN_RK3399(17, 17, 4, false), + [RK3399_PD_RGA] = DOMAIN_RK3399(18, 18, 5, false), + [RK3399_PD_IEP] = DOMAIN_RK3399(19, 19, 6, false), + [RK3399_PD_VO] = DOMAIN_RK3399(20, 20, -1, false), + [RK3399_PD_VOPB] = DOMAIN_RK3399(-1, -1, 7, false), + [RK3399_PD_VOPL] = DOMAIN_RK3399(-1, -1, 8, false), + [RK3399_PD_ISP0] = DOMAIN_RK3399(22, 22, 9, false), + [RK3399_PD_ISP1] = DOMAIN_RK3399(23, 23, 10, false), + [RK3399_PD_HDCP] = DOMAIN_RK3399(24, 24, 11, false), + [RK3399_PD_GMAC] = DOMAIN_RK3399(25, 25, 23, true), + [RK3399_PD_EMMC] = DOMAIN_RK3399(26, 26, 24, true), + [RK3399_PD_USB3] = DOMAIN_RK3399(27, 27, 12, true), + [RK3399_PD_EDP] = DOMAIN_RK3399(28, 28, 22, false), + [RK3399_PD_GIC] = DOMAIN_RK3399(29, 29, 27, true), + [RK3399_PD_SD] = DOMAIN_RK3399(30, 30, 28, true), + [RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399(31, 31, 29, true), }; static const struct rockchip_pmu_info rk3288_pmu = { -- cgit v1.2.3 From e180f887ba40a916153e29e6ad48c34d28966740 Mon Sep 17 00:00:00 2001 From: Henry Chen Date: Wed, 13 Jul 2016 11:34:28 +0800 Subject: soc: mediatek: PMIC wrap: Extend the waiting time to 10ms. Read data fails sometimes because of a timeout that PMIC cannot transfer data to PMIC wrap on time, extend the waiting time to 10ms to reduce the failed rate. Signed-off-by: Henry Chen Signed-off-by: Matthias Brugger --- drivers/soc/mediatek/mtk-pmic-wrap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index a003ba26ca6e..a5f10936fb9c 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -583,7 +583,7 @@ static int pwrap_wait_for_state(struct pmic_wrapper *wrp, { unsigned long timeout; - timeout = jiffies + usecs_to_jiffies(255); + timeout = jiffies + usecs_to_jiffies(10000); do { if (time_after(jiffies, timeout)) -- cgit v1.2.3 From 951a5af92276f5b2f1b8834bd5eef96d8788f66b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 1 Jul 2016 14:18:59 -0700 Subject: soc: qcom: smem: Silence probe defer error If we fail to get the hwspinlock due to probe defer, we shouldn't print an error message. Just be silent in this case. Cc: Bjorn Andersson Signed-off-by: Stephen Boyd Reviewed-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 2e1aa9f130f4..18ec52f2078a 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -740,7 +740,8 @@ static int qcom_smem_probe(struct platform_device *pdev) hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0); if (hwlock_id < 0) { - dev_err(&pdev->dev, "failed to retrieve hwlock\n"); + if (hwlock_id != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to retrieve hwlock\n"); return hwlock_id; } -- cgit v1.2.3 From dea8524218099ff73ffd1ebd08d97ce6a45b7e0e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jul 2016 11:01:56 -0400 Subject: firmware: qcom_scm: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/firmware/Kconfig:config QCOM_SCM drivers/firmware/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: Andy Gross Cc: David Brown Cc: linux-arm-msm@vger.kernel.org Cc: linux-soc@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Andy Gross --- drivers/firmware/qcom_scm.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index e64a501adbf4..d95c70227c05 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -1,4 +1,7 @@ -/* Copyright (c) 2010,2015, The Linux Foundation. All rights reserved. +/* + * Qualcomm SCM driver + * + * Copyright (c) 2010,2015, The Linux Foundation. All rights reserved. * Copyright (C) 2015 Linaro Ltd. * * This program is free software; you can redistribute it and/or modify @@ -12,7 +15,7 @@ * */ #include -#include +#include #include #include #include @@ -376,8 +379,6 @@ static const struct of_device_id qcom_scm_dt_match[] = { {} }; -MODULE_DEVICE_TABLE(of, qcom_scm_dt_match); - static struct platform_driver qcom_scm_driver = { .driver = { .name = "qcom_scm", @@ -414,14 +415,4 @@ static int __init qcom_scm_init(void) return platform_driver_register(&qcom_scm_driver); } - subsys_initcall(qcom_scm_init); - -static void __exit qcom_scm_exit(void) -{ - platform_driver_unregister(&qcom_scm_driver); -} -module_exit(qcom_scm_exit); - -MODULE_DESCRIPTION("Qualcomm SCM driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 3a1281848830fcb3202cfd7ffe62d19641471d05 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 9 Aug 2016 17:36:02 -0700 Subject: soc: qcom: smd: Correct compile stub prototypes The prototypes for the compile stubs was not properly marked as static inline, this patch corrects this. Fixes: f79a917e69e1 ("Merge tag 'qcom-soc-for-4.7-2' into net-next") Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- include/linux/soc/qcom/smd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h index cbb0f06c41b2..910ce1d9ba89 100644 --- a/include/linux/soc/qcom/smd.h +++ b/include/linux/soc/qcom/smd.h @@ -83,14 +83,14 @@ qcom_smd_open_channel(struct qcom_smd_channel *channel, return NULL; } -void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel) +static inline void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel) { /* This shouldn't be possible */ WARN_ON(1); return NULL; } -void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data) +static inline void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data) { /* This shouldn't be possible */ WARN_ON(1); -- cgit v1.2.3 From 0a0c08cae01b33b29abd24608d3800986546f0af Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 9 Aug 2016 17:39:19 -0700 Subject: soc: qcom: smd: Simplify multi channel handling Multi-channel clients split between several drivers need a way to close individual channels, as these drivers might be removed individually. With this in place the responsibility of closing additionally opened channels to the client as well only concerning smd about the primary channel. With this approach we will only trigger removal of SMD devices based on the state of the primary channel, however we get in sync with how rpmsg works. Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 34 ++++++++++++++++------------------ include/linux/soc/qcom/smd.h | 7 +++++++ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index ac1957dfdf24..63e72eb9baa7 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -197,7 +197,6 @@ struct qcom_smd_channel { void *drvdata; struct list_head list; - struct list_head dev_list; }; /** @@ -891,8 +890,6 @@ static int qcom_smd_dev_remove(struct device *dev) struct qcom_smd_device *qsdev = to_smd_device(dev); struct qcom_smd_driver *qsdrv = to_smd_driver(dev); struct qcom_smd_channel *channel = qsdev->channel; - struct qcom_smd_channel *tmp; - struct qcom_smd_channel *ch; qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSING); @@ -911,15 +908,9 @@ static int qcom_smd_dev_remove(struct device *dev) if (qsdrv->remove) qsdrv->remove(qsdev); - /* - * The client is now gone, close and release all channels associated - * with this sdev - */ - list_for_each_entry_safe(ch, tmp, &channel->dev_list, dev_list) { - qcom_smd_channel_close(ch); - list_del(&ch->dev_list); - ch->qsdev = NULL; - } + /* The client is now gone, close the primary channel */ + qcom_smd_channel_close(channel); + channel->qsdev = NULL; return 0; } @@ -1091,6 +1082,8 @@ qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name) * * Returns a channel handle on success, or -EPROBE_DEFER if the channel isn't * ready. + * + * Any channels returned must be closed with a call to qcom_smd_close_channel() */ struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_channel *parent, const char *name, @@ -1120,15 +1113,21 @@ struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_channel *parent, return ERR_PTR(ret); } - /* - * Append the list of channel to the channels associated with the sdev - */ - list_add_tail(&channel->dev_list, &sdev->channel->dev_list); - return channel; } EXPORT_SYMBOL(qcom_smd_open_channel); +/** + * qcom_smd_close_channel() - close an additionally opened channel + * @channel: channel handle, returned by qcom_smd_open_channel() + */ +void qcom_smd_close_channel(struct qcom_smd_channel *channel) +{ + qcom_smd_channel_close(channel); + channel->qsdev = NULL; +} +EXPORT_SYMBOL(qcom_smd_close_channel); + /* * Allocate the qcom_smd_channel object for a newly found smd channel, * retrieving and validating the smem items involved. @@ -1150,7 +1149,6 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed if (!channel) return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(&channel->dev_list); channel->edge = edge; channel->name = devm_kstrdup(smd->dev, name, GFP_KERNEL); if (!channel->name) diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h index 910ce1d9ba89..324b1decfffb 100644 --- a/include/linux/soc/qcom/smd.h +++ b/include/linux/soc/qcom/smd.h @@ -55,6 +55,7 @@ void qcom_smd_driver_unregister(struct qcom_smd_driver *drv); struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_channel *channel, const char *name, qcom_smd_cb_t cb); +void qcom_smd_close_channel(struct qcom_smd_channel *channel); void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel); void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data); int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len); @@ -83,6 +84,12 @@ qcom_smd_open_channel(struct qcom_smd_channel *channel, return NULL; } +static inline void qcom_smd_close_channel(struct qcom_smd_channel *channel) +{ + /* This shouldn't be possible */ + WARN_ON(1); +} + static inline void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel) { /* This shouldn't be possible */ -- cgit v1.2.3 From 381a0b4ce45b2ad809b79049e6316a83d5eaa2ea Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 9 Aug 2016 17:42:55 -0700 Subject: soc: qcom: smd: Request irqs after parsing properties The code exectued by the interrupt handler depends on the values parsed after requesting the irq, just to be save we should therefor move the request_irq() call to be done after parsing the properties. Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index 63e72eb9baa7..679f7778a4e3 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -1348,22 +1348,6 @@ static int qcom_smd_parse_edge(struct device *dev, edge->of_node = of_node_get(node); - irq = irq_of_parse_and_map(node, 0); - if (irq < 0) { - dev_err(dev, "required smd interrupt missing\n"); - return -EINVAL; - } - - ret = devm_request_irq(dev, irq, - qcom_smd_edge_intr, IRQF_TRIGGER_RISING, - node->name, edge); - if (ret) { - dev_err(dev, "failed to request smd irq\n"); - return ret; - } - - edge->irq = irq; - key = "qcom,smd-edge"; ret = of_property_read_u32(node, key, &edge->edge_id); if (ret) { @@ -1398,6 +1382,22 @@ static int qcom_smd_parse_edge(struct device *dev, return -EINVAL; } + irq = irq_of_parse_and_map(node, 0); + if (irq < 0) { + dev_err(dev, "required smd interrupt missing\n"); + return -EINVAL; + } + + ret = devm_request_irq(dev, irq, + qcom_smd_edge_intr, IRQF_TRIGGER_RISING, + node->name, edge); + if (ret) { + dev_err(dev, "failed to request smd irq\n"); + return ret; + } + + edge->irq = irq; + return 0; } -- cgit v1.2.3 From da0573026c2d3d445c39385024bfc3ce6beebe09 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 15 Aug 2016 11:15:57 -0700 Subject: soc: qcom: smd: Represent smd edges as devices By representing each edge as its own device the channels are no longer tied to being parented by the same smd device and as such an edge can live as children of e.g. remoteproc instances. Signed-off-by: Bjorn Andersson Signed-off-by: Andy Gross --- drivers/soc/qcom/smd.c | 197 +++++++++++++++++++++++++++---------------- include/linux/soc/qcom/smd.h | 18 ++++ 2 files changed, 140 insertions(+), 75 deletions(-) diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c index 679f7778a4e3..f20816bef1b5 100644 --- a/drivers/soc/qcom/smd.c +++ b/drivers/soc/qcom/smd.c @@ -95,7 +95,7 @@ static const struct { /** * struct qcom_smd_edge - representing a remote processor - * @smd: handle to qcom_smd + * @dev: device for this edge * @of_node: of_node handle for information related to this edge * @edge_id: identifier of this edge * @remote_pid: identifier of remote processor @@ -111,7 +111,8 @@ static const struct { * @state_work: work item for edge state changes */ struct qcom_smd_edge { - struct qcom_smd *smd; + struct device dev; + struct device_node *of_node; unsigned edge_id; unsigned remote_pid; @@ -135,6 +136,8 @@ struct qcom_smd_edge { struct work_struct state_work; }; +#define to_smd_edge(d) container_of(d, struct qcom_smd_edge, dev) + /* * SMD channel states. */ @@ -199,19 +202,6 @@ struct qcom_smd_channel { struct list_head list; }; -/** - * struct qcom_smd - smd struct - * @dev: device struct - * @num_edges: number of entries in @edges - * @edges: array of edges to be handled - */ -struct qcom_smd { - struct device *dev; - - unsigned num_edges; - struct qcom_smd_edge edges[0]; -}; - /* * Format of the smd_info smem items, for byte aligned channels. */ @@ -420,7 +410,7 @@ static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel, if (channel->state == state) return; - dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state); + dev_dbg(&edge->dev, "set_state(%s, %d)\n", channel->name, state); SET_TX_CHANNEL_FLAG(channel, fDSR, is_open); SET_TX_CHANNEL_FLAG(channel, fCTS, is_open); @@ -964,13 +954,12 @@ static int qcom_smd_create_device(struct qcom_smd_channel *channel) struct qcom_smd_device *qsdev; struct qcom_smd_edge *edge = channel->edge; struct device_node *node; - struct qcom_smd *smd = edge->smd; int ret; if (channel->qsdev) return -EEXIST; - dev_dbg(smd->dev, "registering '%s'\n", channel->name); + dev_dbg(&edge->dev, "registering '%s'\n", channel->name); qsdev = kzalloc(sizeof(*qsdev), GFP_KERNEL); if (!qsdev) @@ -981,7 +970,7 @@ static int qcom_smd_create_device(struct qcom_smd_channel *channel) edge->of_node->name, node ? node->name : channel->name); - qsdev->dev.parent = smd->dev; + qsdev->dev.parent = &edge->dev; qsdev->dev.bus = &qcom_smd_bus; qsdev->dev.release = qcom_smd_release_device; qsdev->dev.of_node = node; @@ -992,7 +981,7 @@ static int qcom_smd_create_device(struct qcom_smd_channel *channel) ret = device_register(&qsdev->dev); if (ret) { - dev_err(smd->dev, "device_register failed: %d\n", ret); + dev_err(&edge->dev, "device_register failed: %d\n", ret); put_device(&qsdev->dev); } @@ -1138,19 +1127,18 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed char *name) { struct qcom_smd_channel *channel; - struct qcom_smd *smd = edge->smd; size_t fifo_size; size_t info_size; void *fifo_base; void *info; int ret; - channel = devm_kzalloc(smd->dev, sizeof(*channel), GFP_KERNEL); + channel = devm_kzalloc(&edge->dev, sizeof(*channel), GFP_KERNEL); if (!channel) return ERR_PTR(-ENOMEM); channel->edge = edge; - channel->name = devm_kstrdup(smd->dev, name, GFP_KERNEL); + channel->name = devm_kstrdup(&edge->dev, name, GFP_KERNEL); if (!channel->name) return ERR_PTR(-ENOMEM); @@ -1173,7 +1161,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed } else if (info_size == 2 * sizeof(struct smd_channel_info)) { channel->info = info; } else { - dev_err(smd->dev, + dev_err(&edge->dev, "channel info of size %zu not supported\n", info_size); ret = -EINVAL; goto free_name_and_channel; @@ -1188,7 +1176,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed /* The channel consist of a rx and tx fifo of equal size */ fifo_size /= 2; - dev_dbg(smd->dev, "new channel '%s' info-size: %zu fifo-size: %zu\n", + dev_dbg(&edge->dev, "new channel '%s' info-size: %zu fifo-size: %zu\n", name, info_size, fifo_size); channel->tx_fifo = fifo_base; @@ -1200,8 +1188,8 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed return channel; free_name_and_channel: - devm_kfree(smd->dev, channel->name); - devm_kfree(smd->dev, channel); + devm_kfree(&edge->dev, channel->name); + devm_kfree(&edge->dev, channel); return ERR_PTR(ret); } @@ -1217,7 +1205,6 @@ static void qcom_channel_scan_worker(struct work_struct *work) struct qcom_smd_alloc_entry *alloc_tbl; struct qcom_smd_alloc_entry *entry; struct qcom_smd_channel *channel; - struct qcom_smd *smd = edge->smd; unsigned long flags; unsigned fifo_id; unsigned info_id; @@ -1261,7 +1248,7 @@ static void qcom_channel_scan_worker(struct work_struct *work) list_add(&channel->list, &edge->channels); spin_unlock_irqrestore(&edge->channels_lock, flags); - dev_dbg(smd->dev, "new channel found: '%s'\n", channel->name); + dev_dbg(&edge->dev, "new channel found: '%s'\n", channel->name); set_bit(i, edge->allocated[tbl]); wake_up_interruptible(&edge->new_channel_event); @@ -1401,15 +1388,102 @@ static int qcom_smd_parse_edge(struct device *dev, return 0; } -static int qcom_smd_probe(struct platform_device *pdev) +/* + * Release function for an edge. + * Reset the state of each associated channel and free the edge context. + */ +static void qcom_smd_edge_release(struct device *dev) +{ + struct qcom_smd_channel *channel; + struct qcom_smd_edge *edge = to_smd_edge(dev); + + list_for_each_entry(channel, &edge->channels, list) { + SET_RX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); + SET_RX_CHANNEL_INFO(channel, head, 0); + SET_RX_CHANNEL_INFO(channel, tail, 0); + } + + kfree(edge); +} + +/** + * qcom_smd_register_edge() - register an edge based on an device_node + * @parent: parent device for the edge + * @node: device_node describing the edge + * + * Returns an edge reference, or negative ERR_PTR() on failure. + */ +struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent, + struct device_node *node) { struct qcom_smd_edge *edge; - struct device_node *node; - struct qcom_smd *smd; - size_t array_size; - int num_edges; int ret; - int i = 0; + + edge = kzalloc(sizeof(*edge), GFP_KERNEL); + if (!edge) + return ERR_PTR(-ENOMEM); + + init_waitqueue_head(&edge->new_channel_event); + + edge->dev.parent = parent; + edge->dev.release = qcom_smd_edge_release; + dev_set_name(&edge->dev, "%s:%s", dev_name(parent), node->name); + ret = device_register(&edge->dev); + if (ret) { + pr_err("failed to register smd edge\n"); + return ERR_PTR(ret); + } + + ret = qcom_smd_parse_edge(&edge->dev, node, edge); + if (ret) { + dev_err(&edge->dev, "failed to parse smd edge\n"); + goto unregister_dev; + } + + schedule_work(&edge->scan_work); + + return edge; + +unregister_dev: + put_device(&edge->dev); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(qcom_smd_register_edge); + +static int qcom_smd_remove_device(struct device *dev, void *data) +{ + device_unregister(dev); + of_node_put(dev->of_node); + put_device(dev); + + return 0; +} + +/** + * qcom_smd_unregister_edge() - release an edge and its children + * @edge: edge reference acquired from qcom_smd_register_edge + */ +int qcom_smd_unregister_edge(struct qcom_smd_edge *edge) +{ + int ret; + + disable_irq(edge->irq); + cancel_work_sync(&edge->scan_work); + cancel_work_sync(&edge->state_work); + + ret = device_for_each_child(&edge->dev, NULL, qcom_smd_remove_device); + if (ret) + dev_warn(&edge->dev, "can't remove smd device: %d\n", ret); + + device_unregister(&edge->dev); + + return 0; +} +EXPORT_SYMBOL(qcom_smd_unregister_edge); + +static int qcom_smd_probe(struct platform_device *pdev) +{ + struct device_node *node; void *p; /* Wait for smem */ @@ -1417,29 +1491,17 @@ static int qcom_smd_probe(struct platform_device *pdev) if (PTR_ERR(p) == -EPROBE_DEFER) return PTR_ERR(p); - num_edges = of_get_available_child_count(pdev->dev.of_node); - array_size = sizeof(*smd) + num_edges * sizeof(struct qcom_smd_edge); - smd = devm_kzalloc(&pdev->dev, array_size, GFP_KERNEL); - if (!smd) - return -ENOMEM; - smd->dev = &pdev->dev; + for_each_available_child_of_node(pdev->dev.of_node, node) + qcom_smd_register_edge(&pdev->dev, node); - smd->num_edges = num_edges; - for_each_available_child_of_node(pdev->dev.of_node, node) { - edge = &smd->edges[i++]; - edge->smd = smd; - init_waitqueue_head(&edge->new_channel_event); - - ret = qcom_smd_parse_edge(&pdev->dev, node, edge); - if (ret) - continue; - - schedule_work(&edge->scan_work); - } + return 0; +} - platform_set_drvdata(pdev, smd); +static int qcom_smd_remove_edge(struct device *dev, void *data) +{ + struct qcom_smd_edge *edge = to_smd_edge(dev); - return 0; + return qcom_smd_unregister_edge(edge); } /* @@ -1448,28 +1510,13 @@ static int qcom_smd_probe(struct platform_device *pdev) */ static int qcom_smd_remove(struct platform_device *pdev) { - struct qcom_smd_channel *channel; - struct qcom_smd_edge *edge; - struct qcom_smd *smd = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < smd->num_edges; i++) { - edge = &smd->edges[i]; - - disable_irq(edge->irq); - cancel_work_sync(&edge->scan_work); - cancel_work_sync(&edge->state_work); - - /* No need to lock here, because the writer is gone */ - list_for_each_entry(channel, &edge->channels, list) { - if (!channel->qsdev) - continue; + int ret; - qcom_smd_destroy_device(channel); - } - } + ret = device_for_each_child(&pdev->dev, NULL, qcom_smd_remove_edge); + if (ret) + dev_warn(&pdev->dev, "can't remove smd device: %d\n", ret); - return 0; + return ret; } static const struct of_device_id qcom_smd_of_match[] = { diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h index 324b1decfffb..f148e0ffbec7 100644 --- a/include/linux/soc/qcom/smd.h +++ b/include/linux/soc/qcom/smd.h @@ -61,6 +61,10 @@ void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data); int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len); +struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent, + struct device_node *node); +int qcom_smd_unregister_edge(struct qcom_smd_edge *edge); + #else static inline int qcom_smd_driver_register(struct qcom_smd_driver *drv) @@ -111,6 +115,20 @@ static inline int qcom_smd_send(struct qcom_smd_channel *channel, return -ENXIO; } +static inline struct qcom_smd_edge * +qcom_smd_register_edge(struct device *parent, + struct device_node *node) +{ + return ERR_PTR(-ENXIO); +} + +static inline int qcom_smd_unregister_edge(struct qcom_smd_edge *edge) +{ + /* This shouldn't be possible */ + WARN_ON(1); + return -ENXIO; +} + #endif #define module_qcom_smd_driver(__smd_driver) \ -- cgit v1.2.3 From ca9f71f05793e8d0972df4c6df30378a073e63c5 Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Fri, 22 Jul 2016 11:37:47 +0200 Subject: dt-bindings: mfd: Add STM32F4 RCC numeric constants into DT include file Ths patch lists STM32F4's RCC numeric constants. It will be used by clock and reset drivers, and DT bindings. Signed-off-by: Maxime Coquelin Signed-off-by: Gabriel Fernandez Signed-off-by: Philipp Zabel --- include/dt-bindings/mfd/stm32f4-rcc.h | 98 +++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 include/dt-bindings/mfd/stm32f4-rcc.h diff --git a/include/dt-bindings/mfd/stm32f4-rcc.h b/include/dt-bindings/mfd/stm32f4-rcc.h new file mode 100644 index 000000000000..e98942dc0d44 --- /dev/null +++ b/include/dt-bindings/mfd/stm32f4-rcc.h @@ -0,0 +1,98 @@ +/* + * This header provides constants for the STM32F4 RCC IP + */ + +#ifndef _DT_BINDINGS_MFD_STM32F4_RCC_H +#define _DT_BINDINGS_MFD_STM32F4_RCC_H + +/* AHB1 */ +#define STM32F4_RCC_AHB1_GPIOA 0 +#define STM32F4_RCC_AHB1_GPIOB 1 +#define STM32F4_RCC_AHB1_GPIOC 2 +#define STM32F4_RCC_AHB1_GPIOD 3 +#define STM32F4_RCC_AHB1_GPIOE 4 +#define STM32F4_RCC_AHB1_GPIOF 5 +#define STM32F4_RCC_AHB1_GPIOG 6 +#define STM32F4_RCC_AHB1_GPIOH 7 +#define STM32F4_RCC_AHB1_GPIOI 8 +#define STM32F4_RCC_AHB1_GPIOJ 9 +#define STM32F4_RCC_AHB1_GPIOK 10 +#define STM32F4_RCC_AHB1_CRC 12 +#define STM32F4_RCC_AHB1_DMA1 21 +#define STM32F4_RCC_AHB1_DMA2 22 +#define STM32F4_RCC_AHB1_DMA2D 23 +#define STM32F4_RCC_AHB1_ETHMAC 25 +#define STM32F4_RCC_AHB1_OTGHS 29 + +#define STM32F4_AHB1_RESET(bit) (STM32F4_RCC_AHB1_##bit + (0x10 * 8)) +#define STM32F4_AHB1_CLOCK(bit) (STM32F4_RCC_AHB1_##bit + (0x30 * 8)) + + +/* AHB2 */ +#define STM32F4_RCC_AHB2_DCMI 0 +#define STM32F4_RCC_AHB2_CRYP 4 +#define STM32F4_RCC_AHB2_HASH 5 +#define STM32F4_RCC_AHB2_RNG 6 +#define STM32F4_RCC_AHB2_OTGFS 7 + +#define STM32F4_AHB2_RESET(bit) (STM32F4_RCC_AHB2_##bit + (0x14 * 8)) +#define STM32F4_AHB2_CLOCK(bit) (STM32F4_RCC_AHB2_##bit + (0x34 * 8)) + +/* AHB3 */ +#define STM32F4_RCC_AHB3_FMC 0 + +#define STM32F4_AHB3_RESET(bit) (STM32F4_RCC_AHB3_##bit + (0x18 * 8)) +#define STM32F4_AHB3_CLOCK(bit) (STM32F4_RCC_AHB3_##bit + (0x38 * 8)) + +/* APB1 */ +#define STM32F4_RCC_APB1_TIM2 0 +#define STM32F4_RCC_APB1_TIM3 1 +#define STM32F4_RCC_APB1_TIM4 2 +#define STM32F4_RCC_APB1_TIM5 3 +#define STM32F4_RCC_APB1_TIM6 4 +#define STM32F4_RCC_APB1_TIM7 5 +#define STM32F4_RCC_APB1_TIM12 6 +#define STM32F4_RCC_APB1_TIM13 7 +#define STM32F4_RCC_APB1_TIM14 8 +#define STM32F4_RCC_APB1_WWDG 11 +#define STM32F4_RCC_APB1_SPI2 14 +#define STM32F4_RCC_APB1_SPI3 15 +#define STM32F4_RCC_APB1_UART2 17 +#define STM32F4_RCC_APB1_UART3 18 +#define STM32F4_RCC_APB1_UART4 19 +#define STM32F4_RCC_APB1_UART5 20 +#define STM32F4_RCC_APB1_I2C1 21 +#define STM32F4_RCC_APB1_I2C2 22 +#define STM32F4_RCC_APB1_I2C3 23 +#define STM32F4_RCC_APB1_CAN1 25 +#define STM32F4_RCC_APB1_CAN2 26 +#define STM32F4_RCC_APB1_PWR 28 +#define STM32F4_RCC_APB1_DAC 29 +#define STM32F4_RCC_APB1_UART7 30 +#define STM32F4_RCC_APB1_UART8 31 + +#define STM32F4_APB1_RESET(bit) (STM32F4_RCC_APB1_##bit + (0x20 * 8)) +#define STM32F4_APB1_CLOCK(bit) (STM32F4_RCC_APB1_##bit + (0x40 * 8)) + +/* APB2 */ +#define STM32F4_RCC_APB2_TIM1 0 +#define STM32F4_RCC_APB2_TIM8 1 +#define STM32F4_RCC_APB2_USART1 4 +#define STM32F4_RCC_APB2_USART6 5 +#define STM32F4_RCC_APB2_ADC 8 +#define STM32F4_RCC_APB2_SDIO 11 +#define STM32F4_RCC_APB2_SPI1 12 +#define STM32F4_RCC_APB2_SPI4 13 +#define STM32F4_RCC_APB2_SYSCFG 14 +#define STM32F4_RCC_APB2_TIM9 16 +#define STM32F4_RCC_APB2_TIM10 17 +#define STM32F4_RCC_APB2_TIM11 18 +#define STM32F4_RCC_APB2_SPI5 20 +#define STM32F4_RCC_APB2_SPI6 21 +#define STM32F4_RCC_APB2_SAI1 22 +#define STM32F4_RCC_APB2_LTDC 26 + +#define STM32F4_APB2_RESET(bit) (STM32F4_RCC_APB2_##bit + (0x24 * 8)) +#define STM32F4_APB2_CLOCK(bit) (STM32F4_RCC_APB2_##bit + (0x44 * 8)) + +#endif /* _DT_BINDINGS_MFD_STM32F4_RCC_H */ -- cgit v1.2.3 From 57bd63a4934ff5ef6f19a9b87de5e190e91edc80 Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Fri, 22 Jul 2016 11:37:48 +0200 Subject: dt-bindings: Document the STM32 reset bindings This adds documentation of device tree bindings for the STM32 reset controller. Signed-off-by: Maxime Coquelin Signed-off-by: Gabriel Fernandez Acked-by: Rob Herring Signed-off-by: Philipp Zabel --- .../devicetree/bindings/clock/st,stm32-rcc.txt | 42 ++++++++++++++++++---- .../devicetree/bindings/reset/st,stm32-rcc.txt | 6 ++++ 2 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/reset/st,stm32-rcc.txt diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt index fee3205cdff9..c209de6cfadb 100644 --- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt +++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt @@ -1,16 +1,16 @@ STMicroelectronics STM32 Reset and Clock Controller =================================================== -The RCC IP is both a reset and a clock controller. This documentation only -describes the clock part. +The RCC IP is both a reset and a clock controller. -Please also refer to clock-bindings.txt in this directory for common clock -controller binding usage. +Please refer to clock-bindings.txt for common clock controller binding usage. +Please also refer to reset.txt for common reset controller binding usage. Required properties: - compatible: Should be "st,stm32f42xx-rcc" - reg: should be register base and length as documented in the datasheet +- #reset-cells: 1, see below - #clock-cells: 2, device nodes should specify the clock in their "clocks" property, containing a phandle to the clock device node, an index selecting between gated clocks and other clocks and an index specifying the clock to @@ -19,6 +19,7 @@ Required properties: Example: rcc: rcc@40023800 { + #reset-cells = <1>; #clock-cells = <2> compatible = "st,stm32f42xx-rcc", "st,stm32-rcc"; reg = <0x40023800 0x400>; @@ -35,16 +36,23 @@ from the first RCC clock enable register (RCC_AHB1ENR, address offset 0x30). It is calculated as: index = register_offset / 4 * 32 + bit_offset. Where bit_offset is the bit offset within the register (LSB is 0, MSB is 31). +To simplify the usage and to share bit definition with the reset and clock +drivers of the RCC IP, macros are available to generate the index in +human-readble format. + +For STM32F4 series, the macro are available here: + - include/dt-bindings/mfd/stm32f4-rcc.h + Example: /* Gated clock, AHB1 bit 0 (GPIOA) */ ... { - clocks = <&rcc 0 0> + clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)> }; /* Gated clock, AHB2 bit 4 (CRYP) */ ... { - clocks = <&rcc 0 36> + clocks = <&rcc 0 STM32F4_AHB2_CLOCK(CRYP)> }; Specifying other clocks @@ -61,5 +69,25 @@ Example: /* Misc clock, FCLK */ ... { - clocks = <&rcc 1 1> + clocks = <&rcc 1 STM32F4_APB1_CLOCK(TIM2)> + }; + + +Specifying softreset control of devices +======================================= + +Device nodes should specify the reset channel required in their "resets" +property, containing a phandle to the reset device node and an index specifying +which channel to use. +The index is the bit number within the RCC registers bank, starting from RCC +base address. +It is calculated as: index = register_offset / 4 * 32 + bit_offset. +Where bit_offset is the bit offset within the register. +For example, for CRC reset: + crc = AHB1RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x10 / 4 * 32 + 12 = 140 + +example: + + timer2 { + resets = <&rcc STM32F4_APB1_RESET(TIM2)>; }; diff --git a/Documentation/devicetree/bindings/reset/st,stm32-rcc.txt b/Documentation/devicetree/bindings/reset/st,stm32-rcc.txt new file mode 100644 index 000000000000..01db34375192 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/st,stm32-rcc.txt @@ -0,0 +1,6 @@ +STMicroelectronics STM32 Peripheral Reset Controller +==================================================== + +The RCC IP is both a reset and a clock controller. + +Please see Documentation/devicetree/bindings/clock/st,stm32-rcc.txt -- cgit v1.2.3 From b70b009b243acce0562dee2e7eee9293cc69383c Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Fri, 22 Jul 2016 11:37:49 +0200 Subject: drivers: reset: Add STM32 reset driver The STM32 MCUs family IPs can be reset by accessing some registers from the RCC block. The list of available reset lines is documented in the DT bindings. Signed-off-by: Maxime Coquelin Signed-off-by: Gabriel Fernandez Signed-off-by: Philipp Zabel --- drivers/reset/Makefile | 1 + drivers/reset/reset-stm32.c | 108 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 drivers/reset/reset-stm32.c diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 5d65a93d3c43..64ebb0c4615c 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o obj-$(CONFIG_ARCH_MESON) += reset-meson.o +obj-$(CONFIG_ARCH_STM32) += reset-stm32.o obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o obj-$(CONFIG_ARCH_STI) += sti/ obj-$(CONFIG_ARCH_HISI) += hisilicon/ diff --git a/drivers/reset/reset-stm32.c b/drivers/reset/reset-stm32.c new file mode 100644 index 000000000000..3a7c8527e66a --- /dev/null +++ b/drivers/reset/reset-stm32.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin + * License terms: GNU General Public License (GPL), version 2 + * + * Heavily based on sunxi driver from Maxime Ripard. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct stm32_reset_data { + spinlock_t lock; + void __iomem *membase; + struct reset_controller_dev rcdev; +}; + +static int stm32_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct stm32_reset_data *data = container_of(rcdev, + struct stm32_reset_data, + rcdev); + int bank = id / BITS_PER_LONG; + int offset = id % BITS_PER_LONG; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl(data->membase + (bank * 4)); + writel(reg | BIT(offset), data->membase + (bank * 4)); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int stm32_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct stm32_reset_data *data = container_of(rcdev, + struct stm32_reset_data, + rcdev); + int bank = id / BITS_PER_LONG; + int offset = id % BITS_PER_LONG; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl(data->membase + (bank * 4)); + writel(reg & ~BIT(offset), data->membase + (bank * 4)); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static const struct reset_control_ops stm32_reset_ops = { + .assert = stm32_reset_assert, + .deassert = stm32_reset_deassert, +}; + +static const struct of_device_id stm32_reset_dt_ids[] = { + { .compatible = "st,stm32-rcc", }, + { /* sentinel */ }, +}; + +static int stm32_reset_probe(struct platform_device *pdev) +{ + struct stm32_reset_data *data; + struct resource *res; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(data->membase)) + return PTR_ERR(data->membase); + + spin_lock_init(&data->lock); + + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = resource_size(res) * 8; + data->rcdev.ops = &stm32_reset_ops; + data->rcdev.of_node = pdev->dev.of_node; + + return devm_reset_controller_register(&pdev->dev, &data->rcdev); +} + +static struct platform_driver stm32_reset_driver = { + .probe = stm32_reset_probe, + .driver = { + .name = "stm32-rcc-reset", + .of_match_table = stm32_reset_dt_ids, + }, +}; +builtin_platform_driver(stm32_reset_driver); -- cgit v1.2.3 From 9af80712985562b40fa37e6b80b82bedb57fcbc6 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Fri, 22 Jul 2016 11:37:50 +0200 Subject: ARM: dts: stm32f429: add missing #reset-cells of rcc This patch adds #reset-cells property to rcc node. Signed-off-by: Gabriel Fernandez Signed-off-by: Philipp Zabel --- arch/arm/boot/dts/stm32f429.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi index 35df462559ca..fe892361a8b9 100644 --- a/arch/arm/boot/dts/stm32f429.dtsi +++ b/arch/arm/boot/dts/stm32f429.dtsi @@ -326,6 +326,7 @@ }; rcc: rcc@40023810 { + #reset-cells = <1>; #clock-cells = <2>; compatible = "st,stm32f42xx-rcc", "st,stm32-rcc"; reg = <0x40023800 0x400>; -- cgit v1.2.3 From 54e991b56639437f922113b6b12f34e8044418d8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 2 Aug 2016 13:18:29 +0900 Subject: reset: uniphier: add reset controller driver for UniPhier SoCs This is the initial commit for UniPhier reset controller driver. Signed-off-by: Masahiro Yamada Acked-by: Rob Herring Signed-off-by: Philipp Zabel --- .../devicetree/bindings/reset/uniphier-reset.txt | 93 +++++ MAINTAINERS | 1 + drivers/reset/Kconfig | 10 + drivers/reset/Makefile | 1 + drivers/reset/reset-uniphier.c | 440 +++++++++++++++++++++ 5 files changed, 545 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/uniphier-reset.txt create mode 100644 drivers/reset/reset-uniphier.c diff --git a/Documentation/devicetree/bindings/reset/uniphier-reset.txt b/Documentation/devicetree/bindings/reset/uniphier-reset.txt new file mode 100644 index 000000000000..e6bbfccd56c3 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/uniphier-reset.txt @@ -0,0 +1,93 @@ +UniPhier reset controller + + +System reset +------------ + +Required properties: +- compatible: should be one of the following: + "socionext,uniphier-sld3-reset" - for PH1-sLD3 SoC. + "socionext,uniphier-ld4-reset" - for PH1-LD4 SoC. + "socionext,uniphier-pro4-reset" - for PH1-Pro4 SoC. + "socionext,uniphier-sld8-reset" - for PH1-sLD8 SoC. + "socionext,uniphier-pro5-reset" - for PH1-Pro5 SoC. + "socionext,uniphier-pxs2-reset" - for ProXstream2/PH1-LD6b SoC. + "socionext,uniphier-ld11-reset" - for PH1-LD11 SoC. + "socionext,uniphier-ld20-reset" - for PH1-LD20 SoC. +- #reset-cells: should be 1. + +Example: + + sysctrl@61840000 { + compatible = "socionext,uniphier-ld20-sysctrl", + "simple-mfd", "syscon"; + reg = <0x61840000 0x4000>; + + reset { + compatible = "socionext,uniphier-ld20-reset"; + #reset-cells = <1>; + }; + + other nodes ... + }; + + +Media I/O (MIO) reset +--------------------- + +Required properties: +- compatible: should be one of the following: + "socionext,uniphier-sld3-mio-reset" - for PH1-sLD3 SoC. + "socionext,uniphier-ld4-mio-reset" - for PH1-LD4 SoC. + "socionext,uniphier-pro4-mio-reset" - for PH1-Pro4 SoC. + "socionext,uniphier-sld8-mio-reset" - for PH1-sLD8 SoC. + "socionext,uniphier-pro5-mio-reset" - for PH1-Pro5 SoC. + "socionext,uniphier-pxs2-mio-reset" - for ProXstream2/PH1-LD6b SoC. + "socionext,uniphier-ld11-mio-reset" - for PH1-LD11 SoC. + "socionext,uniphier-ld20-mio-reset" - for PH1-LD20 SoC. +- #reset-cells: should be 1. + +Example: + + mioctrl@59810000 { + compatible = "socionext,uniphier-ld20-mioctrl", + "simple-mfd", "syscon"; + reg = <0x59810000 0x800>; + + reset { + compatible = "socionext,uniphier-ld20-mio-reset"; + #reset-cells = <1>; + }; + + other nodes ... + }; + + +Peripheral reset +---------------- + +Required properties: +- compatible: should be one of the following: + "socionext,uniphier-ld4-peri-reset" - for PH1-LD4 SoC. + "socionext,uniphier-pro4-peri-reset" - for PH1-Pro4 SoC. + "socionext,uniphier-sld8-peri-reset" - for PH1-sLD8 SoC. + "socionext,uniphier-pro5-peri-reset" - for PH1-Pro5 SoC. + "socionext,uniphier-pxs2-peri-reset" - for ProXstream2/PH1-LD6b SoC. + "socionext,uniphier-ld11-peri-reset" - for PH1-LD11 SoC. + "socionext,uniphier-ld20-peri-reset" - for PH1-LD20 SoC. +- #reset-cells: should be 1. + +Example: + + perictrl@59820000 { + compatible = "socionext,uniphier-ld20-perictrl", + "simple-mfd", "syscon"; + reg = <0x59820000 0x200>; + + reset { + compatible = "socionext,uniphier-ld20-peri-reset"; + #reset-cells = <1>; + }; + + other nodes ... + }; diff --git a/MAINTAINERS b/MAINTAINERS index 20bb1d00098c..fde95b8f37db 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1830,6 +1830,7 @@ F: arch/arm64/boot/dts/socionext/ F: drivers/bus/uniphier-system-bus.c F: drivers/i2c/busses/i2c-uniphier* F: drivers/pinctrl/uniphier/ +F: drivers/reset/reset-uniphier.c F: drivers/tty/serial/8250/8250_uniphier.c N: uniphier diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 4be1b8c21f6f..7dfe8d84d6bb 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -27,6 +27,16 @@ config TI_SYSCON_RESET you wish to use the reset framework for such memory-mapped devices, say Y here. Otherwise, say N. +config RESET_UNIPHIER + tristate "Reset controller driver for UniPhier SoCs" + depends on ARCH_UNIPHIER || COMPILE_TEST + depends on OF && MFD_SYSCON + default ARCH_UNIPHIER + help + Support for reset controllers on UniPhier SoCs. + Say Y if you want to control reset signals provided by System Control + block, Media I/O block, Peripheral Block. + source "drivers/reset/sti/Kconfig" source "drivers/reset/hisilicon/Kconfig" diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 64ebb0c4615c..9b45dcfa2a5f 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o obj-$(CONFIG_ATH79) += reset-ath79.o obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o +obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c new file mode 100644 index 000000000000..8b2558e7363e --- /dev/null +++ b/drivers/reset/reset-uniphier.c @@ -0,0 +1,440 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct uniphier_reset_data { + unsigned int id; + unsigned int reg; + unsigned int bit; + unsigned int flags; +#define UNIPHIER_RESET_ACTIVE_LOW BIT(0) +}; + +#define UNIPHIER_RESET_ID_END (unsigned int)(-1) + +#define UNIPHIER_RESET_END \ + { .id = UNIPHIER_RESET_ID_END } + +#define UNIPHIER_RESET(_id, _reg, _bit) \ + { \ + .id = (_id), \ + .reg = (_reg), \ + .bit = (_bit), \ + } + +#define UNIPHIER_RESETX(_id, _reg, _bit) \ + { \ + .id = (_id), \ + .reg = (_reg), \ + .bit = (_bit), \ + .flags = UNIPHIER_RESET_ACTIVE_LOW, \ + } + +/* System reset data */ +#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) + +const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { + 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_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = { + 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_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */ + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */ + UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */ + UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */ + UNIPHIER_RESETX(20, 0x2014, 5), /* USB31-PHY0 */ + UNIPHIER_RESETX(21, 0x2014, 1), /* USB31-PHY1 */ + UNIPHIER_RESETX(28, 0x2014, 12), /* SATA */ + UNIPHIER_RESET(29, 0x2014, 8), /* SATA-PHY (active high) */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = { + UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { + UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */ + UNIPHIER_LD20_SYS_RESET_GIO(12), /* 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_RESET_END, +}; + +/* Media I/O reset data */ +#define UNIPHIER_MIO_RESET_SD(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26) + +#define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch) \ + UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_USB2(id, ch) \ + UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24) + +#define UNIPHIER_MIO_RESET_DMAC(id) \ + UNIPHIER_RESETX((id), 0x110, 17) + +const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = { + UNIPHIER_MIO_RESET_SD(0, 0), + UNIPHIER_MIO_RESET_SD(1, 1), + UNIPHIER_MIO_RESET_SD(2, 2), + UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0), + UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1), + UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2), + UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1), + UNIPHIER_MIO_RESET_DMAC(7), + 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_B