| From fae12653260a4239292531c83e581ae4a84f83b1 Mon Sep 17 00:00:00 2001 |
| From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Date: Thu, 22 Aug 2013 14:29:46 -0300 |
| Subject: [media] v4l: vsp1: Add support for RT clock |
| |
| The VSPR and VSPS instances use two clocks, the VSP1 system clock and |
| the VSP1 realtime clock. Both of them need to be enabled to access the |
| VSP1 registers. |
| Add support for an optional RT clock and enable/disable it along with |
| the system clock. |
| |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> |
| (cherry picked from commit f2226a33bf9a431f616b435aa10a9ad4fea1d042) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/media/platform/vsp1/vsp1.h | 1 + |
| drivers/media/platform/vsp1/vsp1_drv.c | 40 +++++++++++++++++++++++++++++----- |
| 2 files changed, 36 insertions(+), 5 deletions(-) |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h |
| index 11ac94bec3a3..d6c6ecd039ff 100644 |
| --- a/drivers/media/platform/vsp1/vsp1.h |
| +++ b/drivers/media/platform/vsp1/vsp1.h |
| @@ -42,6 +42,7 @@ struct vsp1_device { |
| |
| void __iomem *mmio; |
| struct clk *clock; |
| + struct clk *rt_clock; |
| |
| struct mutex lock; |
| int ref_count; |
| diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c |
| index aa8b9b288e61..1c9e771aa15c 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_drv.c |
| +++ b/drivers/media/platform/vsp1/vsp1_drv.c |
| @@ -290,6 +290,33 @@ static int vsp1_device_init(struct vsp1_device *vsp1) |
| return 0; |
| } |
| |
| +static int vsp1_clocks_enable(struct vsp1_device *vsp1) |
| +{ |
| + int ret; |
| + |
| + ret = clk_prepare_enable(vsp1->clock); |
| + if (ret < 0) |
| + return ret; |
| + |
| + if (IS_ERR(vsp1->rt_clock)) |
| + return 0; |
| + |
| + ret = clk_prepare_enable(vsp1->rt_clock); |
| + if (ret < 0) { |
| + clk_disable_unprepare(vsp1->clock); |
| + return ret; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +static void vsp1_clocks_disable(struct vsp1_device *vsp1) |
| +{ |
| + if (!IS_ERR(vsp1->rt_clock)) |
| + clk_disable_unprepare(vsp1->rt_clock); |
| + clk_disable_unprepare(vsp1->clock); |
| +} |
| + |
| /* |
| * vsp1_device_get - Acquire the VSP1 device |
| * |
| @@ -307,7 +334,7 @@ struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1) |
| if (vsp1->ref_count > 0) |
| goto done; |
| |
| - ret = clk_prepare_enable(vsp1->clock); |
| + ret = vsp1_clocks_enable(vsp1); |
| if (ret < 0) { |
| __vsp1 = NULL; |
| goto done; |
| @@ -315,7 +342,7 @@ struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1) |
| |
| ret = vsp1_device_init(vsp1); |
| if (ret < 0) { |
| - clk_disable_unprepare(vsp1->clock); |
| + vsp1_clocks_disable(vsp1); |
| __vsp1 = NULL; |
| goto done; |
| } |
| @@ -339,7 +366,7 @@ void vsp1_device_put(struct vsp1_device *vsp1) |
| mutex_lock(&vsp1->lock); |
| |
| if (--vsp1->ref_count == 0) |
| - clk_disable_unprepare(vsp1->clock); |
| + vsp1_clocks_disable(vsp1); |
| |
| mutex_unlock(&vsp1->lock); |
| } |
| @@ -358,7 +385,7 @@ static int vsp1_pm_suspend(struct device *dev) |
| if (vsp1->ref_count == 0) |
| return 0; |
| |
| - clk_disable_unprepare(vsp1->clock); |
| + vsp1_clocks_disable(vsp1); |
| return 0; |
| } |
| |
| @@ -371,7 +398,7 @@ static int vsp1_pm_resume(struct device *dev) |
| if (vsp1->ref_count) |
| return 0; |
| |
| - return clk_prepare_enable(vsp1->clock); |
| + return vsp1_clocks_enable(vsp1); |
| } |
| #endif |
| |
| @@ -445,6 +472,9 @@ static int vsp1_probe(struct platform_device *pdev) |
| return PTR_ERR(vsp1->clock); |
| } |
| |
| + /* The RT clock is optional */ |
| + vsp1->rt_clock = devm_clk_get(&pdev->dev, "rt"); |
| + |
| irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
| if (!irq) { |
| dev_err(&pdev->dev, "missing IRQ\n"); |
| -- |
| 1.8.5.rc3 |
| |