From 42e53668b933d08e893d9f76bdf0baed4f492d5c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 30 Dec 2019 22:36:04 -0600 Subject: [PATCH 154/351] 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 call to reset_control_deassert() is replaced with a call to reset_control_reset() to ensure the hardware is fully reinitialized, regardless of the state firmware left it in. 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 --- drivers/bus/sunxi-rsb.c | 129 +++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 56 deletions(-) diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c index e67be95c0660..1795ad7f0bfe 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 */ @@ -585,15 +586,75 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb) return 0; } +static int sunxi_rsb_init_controller(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_reset(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 int sunxi_rsb_exit_controller(struct sunxi_rsb *rsb) +{ + reset_control_assert(rsb->rstc); + clk_disable_unprepare(rsb->clk); + + return 0; +} + static int sunxi_rsb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; 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) { @@ -608,6 +669,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); rsb->regs = devm_platform_ioremap_resource(pdev, 0); @@ -625,63 +687,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_init_controller(rsb); + if (ret) + return ret; + /* initialize all devices on the bus into RSB mode */ ret = sunxi_rsb_init_device_mode(rsb); if (ret) @@ -690,14 +716,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) @@ -705,8 +723,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_exit_controller(rsb); return 0; } -- 2.34.0