aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/media
diff options
context:
space:
mode:
authorPaul Kocialkowski <paul.kocialkowski@bootlin.com>2022-08-26 20:32:01 +0200
committerMauro Carvalho Chehab <mchehab@kernel.org>2022-09-24 11:21:45 +0200
commit740b5b3d156b6a9cb3b3d3ee2427acca0a890607 (patch)
treef33a045f7f2f04f5487e7bb3d147602c26041207 /drivers/media
parentmedia: sun6i-csi: Tidy up platform code (diff)
downloadwireguard-linux-740b5b3d156b6a9cb3b3d3ee2427acca0a890607.tar.xz
wireguard-linux-740b5b3d156b6a9cb3b3d3ee2427acca0a890607.zip
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@bootlin.com> Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c54
1 files 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;
}