From 014d65b60e46e1af262419139c07bfa1f0775715 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 05:06:32 -0600 Subject: [PATCH 1/8] bus: sunxi-rsb: Move OF match table For some reason, this driver's OF match table was placed above the probe/remove functions, far away from the platform_driver definition. Adding device PM ops would move the table even farther away. Let's move it to the usual place, right before the platform_driver. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 1bb00a959c67..c13340cab27a 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -614,12 +614,6 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb) return 0; } -static const struct of_device_id sunxi_rsb_of_match_table[] = { - { .compatible = "allwinner,sun8i-a23-rsb" }, - {} -}; -MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table); - static int sunxi_rsb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -747,6 +741,12 @@ static int sunxi_rsb_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id sunxi_rsb_of_match_table[] = { + { .compatible = "allwinner,sun8i-a23-rsb" }, + {} +}; +MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table); + static struct platform_driver sunxi_rsb_driver = { .probe = sunxi_rsb_probe, .remove = sunxi_rsb_remove, From 22754ac9a632f9bcb2cfd91243459e679778a497 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 05:06:33 -0600 Subject: [PATCH 2/8] bus: sunxi-rsb: Split out controller init/exit functions This separates the resource acquisition from the hardware initialization phase, so the hardware initialization can be repeated after system suspend/resume. The same is done for the exit/remove function, except that there is no resource deallocation phase due to the use of devres. The requested RSB clock frequency is stored in `struct sunxi_rsb` so it will be available when reinitializing the hardware. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 127 ++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 56 deletions(-) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index c13340cab27a..3f290da45619 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -126,6 +126,7 @@ struct sunxi_rsb { struct completion complete; struct mutex lock; unsigned int status; + u32 clk_freq; }; /* bus / slave device related functions */ @@ -614,16 +615,74 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb) return 0; } +static int sunxi_rsb_hw_init(struct sunxi_rsb *rsb) +{ + struct device *dev = rsb->dev; + unsigned long p_clk_freq; + u32 clk_delay, reg; + int clk_div, ret; + + ret = clk_prepare_enable(rsb->clk); + if (ret) { + dev_err(dev, "failed to enable clk: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(rsb->rstc); + if (ret) { + dev_err(dev, "failed to deassert reset line: %d\n", ret); + goto err_clk_disable; + } + + /* reset the controller */ + writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL); + readl_poll_timeout(rsb->regs + RSB_CTRL, reg, + !(reg & RSB_CTRL_SOFT_RST), 1000, 100000); + + /* + * Clock frequency and delay calculation code is from + * Allwinner U-boot sources. + * + * From A83 user manual: + * bus clock frequency = parent clock frequency / (2 * (divider + 1)) + */ + p_clk_freq = clk_get_rate(rsb->clk); + clk_div = p_clk_freq / rsb->clk_freq / 2; + if (!clk_div) + clk_div = 1; + else if (clk_div > RSB_CCR_MAX_CLK_DIV + 1) + clk_div = RSB_CCR_MAX_CLK_DIV + 1; + + clk_delay = clk_div >> 1; + if (!clk_delay) + clk_delay = 1; + + dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2); + writel(RSB_CCR_SDA_OUT_DELAY(clk_delay) | RSB_CCR_CLK_DIV(clk_div - 1), + rsb->regs + RSB_CCR); + + return 0; + +err_clk_disable: + clk_disable_unprepare(rsb->clk); + + return ret; +} + +static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb) +{ + reset_control_assert(rsb->rstc); + clk_disable_unprepare(rsb->clk); +} + static int sunxi_rsb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct resource *r; struct sunxi_rsb *rsb; - unsigned long p_clk_freq; - u32 clk_delay, clk_freq = 3000000; - int clk_div, irq, ret; - u32 reg; + u32 clk_freq = 3000000; + int irq, ret; of_property_read_u32(np, "clock-frequency", &clk_freq); if (clk_freq > RSB_MAX_FREQ) { @@ -638,6 +697,7 @@ static int sunxi_rsb_probe(struct platform_device *pdev) return -ENOMEM; rsb->dev = dev; + rsb->clk_freq = clk_freq; platform_set_drvdata(pdev, rsb); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); rsb->regs = devm_ioremap_resource(dev, r); @@ -655,63 +715,27 @@ static int sunxi_rsb_probe(struct platform_device *pdev) return ret; } - ret = clk_prepare_enable(rsb->clk); - if (ret) { - dev_err(dev, "failed to enable clk: %d\n", ret); - return ret; - } - - p_clk_freq = clk_get_rate(rsb->clk); - rsb->rstc = devm_reset_control_get(dev, NULL); if (IS_ERR(rsb->rstc)) { ret = PTR_ERR(rsb->rstc); dev_err(dev, "failed to retrieve reset controller: %d\n", ret); - goto err_clk_disable; - } - - ret = reset_control_deassert(rsb->rstc); - if (ret) { - dev_err(dev, "failed to deassert reset line: %d\n", ret); - goto err_clk_disable; + return ret; } init_completion(&rsb->complete); mutex_init(&rsb->lock); - /* reset the controller */ - writel(RSB_CTRL_SOFT_RST, rsb->regs + RSB_CTRL); - readl_poll_timeout(rsb->regs + RSB_CTRL, reg, - !(reg & RSB_CTRL_SOFT_RST), 1000, 100000); - - /* - * Clock frequency and delay calculation code is from - * Allwinner U-boot sources. - * - * From A83 user manual: - * bus clock frequency = parent clock frequency / (2 * (divider + 1)) - */ - clk_div = p_clk_freq / clk_freq / 2; - if (!clk_div) - clk_div = 1; - else if (clk_div > RSB_CCR_MAX_CLK_DIV + 1) - clk_div = RSB_CCR_MAX_CLK_DIV + 1; - - clk_delay = clk_div >> 1; - if (!clk_delay) - clk_delay = 1; - - dev_info(dev, "RSB running at %lu Hz\n", p_clk_freq / clk_div / 2); - writel(RSB_CCR_SDA_OUT_DELAY(clk_delay) | RSB_CCR_CLK_DIV(clk_div - 1), - rsb->regs + RSB_CCR); - ret = devm_request_irq(dev, irq, sunxi_rsb_irq, 0, RSB_CTRL_NAME, rsb); if (ret) { dev_err(dev, "can't register interrupt handler irq %d: %d\n", irq, ret); - goto err_reset_assert; + return ret; } + ret = sunxi_rsb_hw_init(rsb); + if (ret) + return ret; + /* initialize all devices on the bus into RSB mode */ ret = sunxi_rsb_init_device_mode(rsb); if (ret) @@ -720,14 +744,6 @@ static int sunxi_rsb_probe(struct platform_device *pdev) of_rsb_register_devices(rsb); return 0; - -err_reset_assert: - reset_control_assert(rsb->rstc); - -err_clk_disable: - clk_disable_unprepare(rsb->clk); - - return ret; } static int sunxi_rsb_remove(struct platform_device *pdev) @@ -735,8 +751,7 @@ static int sunxi_rsb_remove(struct platform_device *pdev) struct sunxi_rsb *rsb = platform_get_drvdata(pdev); device_for_each_child(rsb->dev, NULL, sunxi_rsb_remove_devices); - reset_control_assert(rsb->rstc); - clk_disable_unprepare(rsb->clk); + sunxi_rsb_hw_exit(rsb); return 0; } From 843107498f91e57d1d4b22cd8787112726fdaeb4 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 05:06:34 -0600 Subject: [PATCH 3/8] bus: sunxi-rsb: Implement suspend/resume/shutdown callbacks Since system firmware is likely to use the RSB bus to communicate with a PMIC while the system is suspended, we cannot make any assumptions about the controller state after resuming. Thus it is important to completely reinitialize the controller. The RSB bus needs to be ready as soon as IRQs are enabled, to handle wakeup event IRQs coming from the PMIC. Thus it uses NOIRQ callbacks. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 3f290da45619..efd222f36cdc 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -675,6 +676,22 @@ static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb) clk_disable_unprepare(rsb->clk); } +static int __maybe_unused sunxi_rsb_suspend(struct device *dev) +{ + struct sunxi_rsb *rsb = dev_get_drvdata(dev); + + sunxi_rsb_hw_exit(rsb); + + return 0; +} + +static int __maybe_unused sunxi_rsb_resume(struct device *dev) +{ + struct sunxi_rsb *rsb = dev_get_drvdata(dev); + + return sunxi_rsb_hw_init(rsb); +} + static int sunxi_rsb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -756,6 +773,17 @@ static int sunxi_rsb_remove(struct platform_device *pdev) return 0; } +static void sunxi_rsb_shutdown(struct platform_device *pdev) +{ + struct sunxi_rsb *rsb = platform_get_drvdata(pdev); + + sunxi_rsb_hw_exit(rsb); +} + +static const struct dev_pm_ops sunxi_rsb_dev_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sunxi_rsb_suspend, sunxi_rsb_resume) +}; + static const struct of_device_id sunxi_rsb_of_match_table[] = { { .compatible = "allwinner,sun8i-a23-rsb" }, {} @@ -765,9 +793,11 @@ MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table); static struct platform_driver sunxi_rsb_driver = { .probe = sunxi_rsb_probe, .remove = sunxi_rsb_remove, + .shutdown = sunxi_rsb_shutdown, .driver = { .name = RSB_CTRL_NAME, .of_match_table = sunxi_rsb_of_match_table, + .pm = &sunxi_rsb_dev_pm_ops, }, }; From 4a0dbc12e61823ece7172df953c3333c8f5f9222 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 05:06:35 -0600 Subject: [PATCH 4/8] bus: sunxi-rsb: Implement runtime power management Gate the clock to save power while the controller is idle. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/bus/sunxi-rsb.c | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index efd222f36cdc..ba5100dfc413 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -337,6 +338,10 @@ static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, return -EINVAL; } + ret = pm_runtime_resume_and_get(rsb->dev); + if (ret) + return ret; + mutex_lock(&rsb->lock); writel(addr, rsb->regs + RSB_ADDR); @@ -352,6 +357,9 @@ static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, unlock: mutex_unlock(&rsb->lock); + pm_runtime_mark_last_busy(rsb->dev); + pm_runtime_put_autosuspend(rsb->dev); + return ret; } @@ -379,6 +387,10 @@ static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, return -EINVAL; } + ret = pm_runtime_resume_and_get(rsb->dev); + if (ret) + return ret; + mutex_lock(&rsb->lock); writel(addr, rsb->regs + RSB_ADDR); @@ -389,6 +401,9 @@ static int sunxi_rsb_write(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr, mutex_unlock(&rsb->lock); + pm_runtime_mark_last_busy(rsb->dev); + pm_runtime_put_autosuspend(rsb->dev); + return ret; } @@ -672,10 +687,29 @@ err_clk_disable: static void sunxi_rsb_hw_exit(struct sunxi_rsb *rsb) { + /* Keep the clock and PM reference counts consistent. */ + if (pm_runtime_status_suspended(rsb->dev)) + pm_runtime_resume(rsb->dev); reset_control_assert(rsb->rstc); clk_disable_unprepare(rsb->clk); } +static int __maybe_unused sunxi_rsb_runtime_suspend(struct device *dev) +{ + struct sunxi_rsb *rsb = dev_get_drvdata(dev); + + clk_disable_unprepare(rsb->clk); + + return 0; +} + +static int __maybe_unused sunxi_rsb_runtime_resume(struct device *dev) +{ + struct sunxi_rsb *rsb = dev_get_drvdata(dev); + + return clk_prepare_enable(rsb->clk); +} + static int __maybe_unused sunxi_rsb_suspend(struct device *dev) { struct sunxi_rsb *rsb = dev_get_drvdata(dev); @@ -758,6 +792,12 @@ static int sunxi_rsb_probe(struct platform_device *pdev) if (ret) dev_warn(dev, "Initialize device mode failed: %d\n", ret); + pm_suspend_ignore_children(dev, true); + pm_runtime_set_active(dev); + pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); + pm_runtime_use_autosuspend(dev); + pm_runtime_enable(dev); + of_rsb_register_devices(rsb); return 0; @@ -768,6 +808,7 @@ static int sunxi_rsb_remove(struct platform_device *pdev) struct sunxi_rsb *rsb = platform_get_drvdata(pdev); device_for_each_child(rsb->dev, NULL, sunxi_rsb_remove_devices); + pm_runtime_disable(&pdev->dev); sunxi_rsb_hw_exit(rsb); return 0; @@ -777,10 +818,13 @@ static void sunxi_rsb_shutdown(struct platform_device *pdev) { struct sunxi_rsb *rsb = platform_get_drvdata(pdev); + pm_runtime_disable(&pdev->dev); sunxi_rsb_hw_exit(rsb); } static const struct dev_pm_ops sunxi_rsb_dev_pm_ops = { + SET_RUNTIME_PM_OPS(sunxi_rsb_runtime_suspend, + sunxi_rsb_runtime_resume, NULL) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sunxi_rsb_suspend, sunxi_rsb_resume) }; From 3c15e00e7b58bc2b37e53d2612f0a0163281be77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 26 Nov 2020 11:41:42 +0100 Subject: [PATCH 5/8] mfd/bus: sunxi-rsb: Make .remove() callback return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver core ignores the return value of struct device_driver::remove because there is only little that can be done. To simplify the quest to make this function return void, let struct sunxi_rsb_driver::remove return void, too. All users already unconditionally return 0, this commit makes this obvious and ensures future users don't behave differently. To simplify even further, make axp20x_device_remove() return void instead of returning 0 unconditionally, too. Signed-off-by: Uwe Kleine-König Reviewed-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/bus/sunxi-rsb.c | 4 +++- drivers/mfd/axp20x-i2c.c | 4 +++- drivers/mfd/axp20x-rsb.c | 4 ++-- drivers/mfd/axp20x.c | 4 +--- include/linux/mfd/axp20x.h | 2 +- include/linux/sunxi-rsb.h | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index 1bb00a959c67..117716e23ffb 100644 --- a/drivers/bus/sunxi-rsb.c +++ b/drivers/bus/sunxi-rsb.c @@ -170,7 +170,9 @@ static int sunxi_rsb_device_remove(struct device *dev) { const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver); - return drv->remove(to_sunxi_rsb_device(dev)); + drv->remove(to_sunxi_rsb_device(dev)); + + return 0; } static struct bus_type sunxi_rsb_bus = { diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c index 2cfde81f5fbf..00ab48018d8d 100644 --- a/drivers/mfd/axp20x-i2c.c +++ b/drivers/mfd/axp20x-i2c.c @@ -54,7 +54,9 @@ static int axp20x_i2c_remove(struct i2c_client *i2c) { struct axp20x_dev *axp20x = i2c_get_clientdata(i2c); - return axp20x_device_remove(axp20x); + axp20x_device_remove(axp20x); + + return 0; } #ifdef CONFIG_OF diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c index 4cdc79f5cc48..214bc0d84d44 100644 --- a/drivers/mfd/axp20x-rsb.c +++ b/drivers/mfd/axp20x-rsb.c @@ -49,11 +49,11 @@ static int axp20x_rsb_probe(struct sunxi_rsb_device *rdev) return axp20x_device_probe(axp20x); } -static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev) +static void axp20x_rsb_remove(struct sunxi_rsb_device *rdev) { struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev); - return axp20x_device_remove(axp20x); + axp20x_device_remove(axp20x); } static const struct of_device_id axp20x_rsb_of_match[] = { diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index aa59496e4376..3eae04e24ac8 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -987,7 +987,7 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) } EXPORT_SYMBOL(axp20x_device_probe); -int axp20x_device_remove(struct axp20x_dev *axp20x) +void axp20x_device_remove(struct axp20x_dev *axp20x) { if (axp20x == axp20x_pm_power_off) { axp20x_pm_power_off = NULL; @@ -996,8 +996,6 @@ int axp20x_device_remove(struct axp20x_dev *axp20x) mfd_remove_devices(axp20x->dev); regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); - - return 0; } EXPORT_SYMBOL(axp20x_device_remove); diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index fd5957c042da..9ab0e2fca7ea 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -696,6 +696,6 @@ int axp20x_device_probe(struct axp20x_dev *axp20x); * * This tells the axp20x core to remove the associated mfd devices */ -int axp20x_device_remove(struct axp20x_dev *axp20x); +void axp20x_device_remove(struct axp20x_dev *axp20x); #endif /* __LINUX_MFD_AXP20X_H */ diff --git a/include/linux/sunxi-rsb.h b/include/linux/sunxi-rsb.h index 7e75bb0346d0..bf0d365f471c 100644 --- a/include/linux/sunxi-rsb.h +++ b/include/linux/sunxi-rsb.h @@ -59,7 +59,7 @@ static inline void sunxi_rsb_device_set_drvdata(struct sunxi_rsb_device *rdev, struct sunxi_rsb_driver { struct device_driver driver; int (*probe)(struct sunxi_rsb_device *rdev); - int (*remove)(struct sunxi_rsb_device *rdev); + void (*remove)(struct sunxi_rsb_device *rdev); }; static inline struct sunxi_rsb_driver *to_sunxi_rsb_driver(struct device_driver *d) From 59657d55d1a04fa5d50f96487c96c1d82f02a7f6 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 27 Jan 2021 17:24:47 +0000 Subject: [PATCH 6/8] dt-bindings: sram: sunxi-sram: Add H616 compatible string The H616 adds a second EMAC clock register. We don't know about the exact SRAM properties yet, so this gets omitted for now. Signed-off-by: Andre Przywara Acked-by: Rob Herring Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210127172500.13356-8-andre.przywara@arm.com --- .../bindings/sram/allwinner,sun4i-a10-system-control.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml index b66a07e21d1e..1c426c211e36 100644 --- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml +++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml @@ -49,6 +49,7 @@ properties: - items: - const: allwinner,suniv-f1c100s-system-control - const: allwinner,sun4i-a10-system-control + - const: allwinner,sun50i-h616-system-control reg: maxItems: 1 From 9117d0c975b8e1596320c9f21f8ba9b9ecc79cbd Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 27 Jan 2021 17:24:48 +0000 Subject: [PATCH 7/8] soc: sunxi: sram: Add support for more than one EMAC clock The Allwinner H616 adds a second EMAC clock register at offset 0x34, for controlling the second EMAC in this chip. Allow to extend the regmap in this case, to cover more than the current 4 bytes exported. Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210127172500.13356-9-andre.przywara@arm.com --- drivers/soc/sunxi/sunxi_sram.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index d4c7bd59429e..42833e33a96c 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -283,7 +283,7 @@ int sunxi_sram_release(struct device *dev) EXPORT_SYMBOL(sunxi_sram_release); struct sunxi_sramc_variant { - bool has_emac_clock; + int num_emac_clocks; }; static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { @@ -291,20 +291,31 @@ static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { }; static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = { - .has_emac_clock = true, + .num_emac_clocks = 1, }; static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = { - .has_emac_clock = true, + .num_emac_clocks = 1, +}; + +static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { + .num_emac_clocks = 2, }; #define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 static bool sunxi_sram_regmap_accessible_reg(struct device *dev, unsigned int reg) { - if (reg == SUNXI_SRAM_EMAC_CLOCK_REG) - return true; - return false; + const struct sunxi_sramc_variant *variant; + + variant = of_device_get_match_data(dev); + + if (reg < SUNXI_SRAM_EMAC_CLOCK_REG) + return false; + if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) + return false; + + return true; } static struct regmap_config sunxi_sram_emac_clock_regmap = { @@ -312,7 +323,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { .val_bits = 32, .reg_stride = 4, /* last defined register */ - .max_register = SUNXI_SRAM_EMAC_CLOCK_REG, + .max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4, /* other devices have no business accessing other registers */ .readable_reg = sunxi_sram_regmap_accessible_reg, .writeable_reg = sunxi_sram_regmap_accessible_reg, @@ -343,7 +354,7 @@ static int sunxi_sram_probe(struct platform_device *pdev) if (!d) return -ENOMEM; - if (variant->has_emac_clock) { + if (variant->num_emac_clocks > 0) { emac_clock = devm_regmap_init_mmio(&pdev->dev, base, &sunxi_sram_emac_clock_regmap); @@ -387,6 +398,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = { .compatible = "allwinner,sun50i-h5-system-control", .data = &sun50i_a64_sramc_variant, }, + { + .compatible = "allwinner,sun50i-h616-system-control", + .data = &sun50i_h616_sramc_variant, + }, { }, }; MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match); From 308e78946a73e2bfe0ebd4ca9559c153c80bd45f Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 27 Jan 2021 17:24:54 +0000 Subject: [PATCH 8/8] dt-bindings: bus: rsb: Add H616 compatible string Add the obvious compatible name to the existing RSB binding, and pair it with the existing A23 fallback compatible string, as the devices are compatible. Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210127172500.13356-15-andre.przywara@arm.com --- .../devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml b/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml index 32d33b983d66..3d719f468a5b 100644 --- a/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml +++ b/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml @@ -21,7 +21,9 @@ properties: oneOf: - const: allwinner,sun8i-a23-rsb - items: - - const: allwinner,sun8i-a83t-rsb + - enum: + - allwinner,sun8i-a83t-rsb + - allwinner,sun50i-h616-rsb - const: allwinner,sun8i-a23-rsb reg: