[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220205185429.2278860-22-paul.kocialkowski@bootlin.com>
Date: Sat, 5 Feb 2022 19:53:44 +0100
From: Paul Kocialkowski <paul.kocialkowski@...tlin.com>
To: linux-media@...r.kernel.org, devicetree@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org, linux-sunxi@...ts.linux.dev,
linux-kernel@...r.kernel.org, linux-phy@...ts.infradead.org,
linux-clk@...r.kernel.org, linux-staging@...ts.linux.dev
Cc: Yong Deng <yong.deng@...ewell.com>,
Mauro Carvalho Chehab <mchehab@...nel.org>,
Rob Herring <robh+dt@...nel.org>,
Maxime Ripard <mripard@...nel.org>,
Sakari Ailus <sakari.ailus@...ux.intel.com>,
Hans Verkuil <hans.verkuil@...co.com>,
Chen-Yu Tsai <wens@...e.org>,
Jernej Skrabec <jernej.skrabec@...il.com>,
Paul Kocialkowski <paul.kocialkowski@...tlin.com>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Helen Koike <helen.koike@...labora.com>,
Laurent Pinchart <laurent.pinchart@...asonboard.com>,
Thomas Petazzoni <thomas.petazzoni@...tlin.com>
Subject: [PATCH v2 21/66] 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>
---
.../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 8155e9560164..2355088fdc37 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->clk_ram);
- if (of_device_is_compatible(dev->of_node,
- "allwinner,sun50i-a64-csi"))
- clk_rate_exclusive_put(csi_dev->clk_mod);
clk_disable_unprepare(csi_dev->clk_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->clk_mod, 300000000);
-
ret = clk_prepare_enable(csi_dev->clk_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->clk_ram);
clk_mod_disable:
- if (of_device_is_compatible(dev->of_node, "allwinner,sun50i-a64-csi"))
- clk_rate_exclusive_put(csi_dev->clk_mod);
clk_disable_unprepare(csi_dev->clk_mod);
return ret;
}
@@ -819,6 +811,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 clk_mod_rate;
void __iomem *io_base;
int ret;
int irq;
@@ -856,28 +849,53 @@ static int sun6i_csi_resources_setup(struct sun6i_csi_device *csi_dev,
return PTR_ERR(csi_dev->clk_ram);
}
+ if (of_device_is_compatible(dev->of_node, "allwinner,sun50i-a64-csi"))
+ clk_mod_rate = 300000000;
+ else
+ clk_mod_rate = 297000000;
+
+ ret = clk_set_rate_exclusive(csi_dev->clk_mod, clk_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_clk_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_clk_rate_exclusive;
+ }
ret = devm_request_irq(dev, irq, sun6i_csi_isr, 0, SUN6I_CSI_NAME,
csi_dev);
if (ret) {
dev_err(dev, "failed to request interrupt\n");
- return ret;
+ goto error_clk_rate_exclusive;
}
return 0;
+
+error_clk_rate_exclusive:
+ clk_rate_exclusive_put(csi_dev->clk_mod);
+
+ return ret;
+}
+
+static void sun6i_csi_resources_cleanup(struct sun6i_csi_device *csi_dev)
+{
+ clk_rate_exclusive_put(csi_dev->clk_mod);
}
static int sun6i_csi_probe(struct platform_device *platform_dev)
@@ -897,7 +915,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)
@@ -905,6 +932,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.34.1
Powered by blists - more mailing lists