[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220826183240.604834-5-paul.kocialkowski@bootlin.com>
Date: Fri, 26 Aug 2022 20:32:01 +0200
From: Paul Kocialkowski <paul.kocialkowski@...tlin.com>
To: linux-kernel@...r.kernel.org, linux-media@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org, linux-sunxi@...ts.linux.dev
Cc: Yong Deng <yong.deng@...ewell.com>,
Paul Kocialkowski <paul.kocialkowski@...tlin.com>,
Mauro Carvalho Chehab <mchehab@...nel.org>,
Chen-Yu Tsai <wens@...e.org>,
Jernej Skrabec <jernej.skrabec@...il.com>,
Samuel Holland <samuel@...lland.org>,
Laurent Pinchart <laurent.pinchart@...asonboard.com>,
Maxime Ripard <mripard@...nel.org>,
Thomas Petazzoni <thomas.petazzoni@...tlin.com>
Subject: [PATCH v6 04/43] media: sun6i-csi: Always set exclusive module clock rate
In some situations the default rate of the module clock is not the
required one for operation (for example when reconfiguring the clock
tree to use a different parent). As a result, always set the correct
rate for the clock (and take care of cleanup).
Signed-off-by: Paul Kocialkowski <paul.kocialkowski@...tlin.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@...il.com>
---
.../platform/sunxi/sun6i-csi/sun6i_csi.c | 54 ++++++++++++++-----
1 file changed, 41 insertions(+), 13 deletions(-)
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
index 514f97d67c1c..89a15cd779ac 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c
@@ -154,9 +154,6 @@ int sun6i_csi_set_power(struct sun6i_csi_device *csi_dev, bool enable)
regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, 0);
clk_disable_unprepare(csi_dev->clock_ram);
- if (of_device_is_compatible(dev->of_node,
- "allwinner,sun50i-a64-csi"))
- clk_rate_exclusive_put(csi_dev->clock_mod);
clk_disable_unprepare(csi_dev->clock_mod);
reset_control_assert(csi_dev->reset);
return 0;
@@ -168,9 +165,6 @@ int sun6i_csi_set_power(struct sun6i_csi_device *csi_dev, bool enable)
return ret;
}
- if (of_device_is_compatible(dev->of_node, "allwinner,sun50i-a64-csi"))
- clk_set_rate_exclusive(csi_dev->clock_mod, 300000000);
-
ret = clk_prepare_enable(csi_dev->clock_ram);
if (ret) {
dev_err(csi_dev->dev, "Enable clk_dram_csi clk err %d\n", ret);
@@ -190,8 +184,6 @@ int sun6i_csi_set_power(struct sun6i_csi_device *csi_dev, bool enable)
clk_ram_disable:
clk_disable_unprepare(csi_dev->clock_ram);
clk_mod_disable:
- if (of_device_is_compatible(dev->of_node, "allwinner,sun50i-a64-csi"))
- clk_rate_exclusive_put(csi_dev->clock_mod);
clk_disable_unprepare(csi_dev->clock_mod);
return ret;
}
@@ -816,6 +808,7 @@ static int sun6i_csi_resources_setup(struct sun6i_csi_device *csi_dev,
struct platform_device *platform_dev)
{
struct device *dev = csi_dev->dev;
+ unsigned long clock_mod_rate;
void __iomem *io_base;
int ret;
int irq;
@@ -847,28 +840,53 @@ static int sun6i_csi_resources_setup(struct sun6i_csi_device *csi_dev,
return PTR_ERR(csi_dev->clock_ram);
}
+ if (of_device_is_compatible(dev->of_node, "allwinner,sun50i-a64-csi"))
+ clock_mod_rate = 300000000;
+ else
+ clock_mod_rate = 297000000;
+
+ ret = clk_set_rate_exclusive(csi_dev->clock_mod, clock_mod_rate);
+ if (ret) {
+ dev_err(dev, "failed to set mod clock rate\n");
+ return ret;
+ }
+
/* Reset */
csi_dev->reset = devm_reset_control_get_shared(dev, NULL);
if (IS_ERR(csi_dev->reset)) {
dev_err(dev, "failed to acquire reset\n");
- return PTR_ERR(csi_dev->reset);
+ ret = PTR_ERR(csi_dev->reset);
+ goto error_clock_rate_exclusive;
}
/* Interrupt */
irq = platform_get_irq(platform_dev, 0);
- if (irq < 0)
- return -ENXIO;
+ if (irq < 0) {
+ dev_err(dev, "failed to get interrupt\n");
+ ret = -ENXIO;
+ goto error_clock_rate_exclusive;
+ }
ret = devm_request_irq(dev, irq, sun6i_csi_interrupt, 0, SUN6I_CSI_NAME,
csi_dev);
if (ret) {
dev_err(dev, "failed to request interrupt\n");
- return ret;
+ goto error_clock_rate_exclusive;
}
return 0;
+
+error_clock_rate_exclusive:
+ clk_rate_exclusive_put(csi_dev->clock_mod);
+
+ return ret;
+}
+
+static void sun6i_csi_resources_cleanup(struct sun6i_csi_device *csi_dev)
+{
+ clk_rate_exclusive_put(csi_dev->clock_mod);
}
static int sun6i_csi_probe(struct platform_device *platform_dev)
@@ -888,7 +906,16 @@ static int sun6i_csi_probe(struct platform_device *platform_dev)
if (ret)
return ret;
- return sun6i_csi_v4l2_init(csi_dev);
+ ret = sun6i_csi_v4l2_init(csi_dev);
+ if (ret)
+ goto error_resources;
+
+ return 0;
+
+error_resources:
+ sun6i_csi_resources_cleanup(csi_dev);
+
+ return ret;
}
static int sun6i_csi_remove(struct platform_device *pdev)
@@ -896,6 +923,7 @@ static int sun6i_csi_remove(struct platform_device *pdev)
struct sun6i_csi_device *csi_dev = platform_get_drvdata(pdev);
sun6i_csi_v4l2_cleanup(csi_dev);
+ sun6i_csi_resources_cleanup(csi_dev);
return 0;
}
--
2.37.1
Powered by blists - more mailing lists