Skip to content

Commit 69b8065

Browse files
paulkocialkowskimchehab
authored andcommitted
media: sun6i-csi: Use runtime pm for clocks and reset
Wrap the clock and reset preparation into runtime pm functions for better organization of the code. Also fix the clock and reset enable order to first deassert reset, as recommended in Allwinner literature. Make the driver depend on PM while at it since runtime pm is mandatory for the driver to work. Signed-off-by: Paul Kocialkowski <[email protected]> Reviewed-by: Jernej Skrabec <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent bc67ec9 commit 69b8065

File tree

2 files changed

+60
-26
lines changed

2 files changed

+60
-26
lines changed

drivers/media/platform/sunxi/sun6i-csi/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
config VIDEO_SUN6I_CSI
33
tristate "Allwinner V3s Camera Sensor Interface driver"
44
depends on V4L_PLATFORM_DRIVERS
5-
depends on VIDEO_DEV && COMMON_CLK && RESET_CONTROLLER && HAS_DMA
5+
depends on VIDEO_DEV && COMMON_CLK && RESET_CONTROLLER && HAS_DMA && PM
66
depends on ARCH_SUNXI || COMPILE_TEST
77
select MEDIA_CONTROLLER
88
select VIDEO_V4L2_SUBDEV_API

drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -152,40 +152,18 @@ int sun6i_csi_set_power(struct sun6i_csi_device *csi_dev, bool enable)
152152

153153
if (!enable) {
154154
regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, 0);
155+
pm_runtime_put(dev);
155156

156-
clk_disable_unprepare(csi_dev->clock_ram);
157-
clk_disable_unprepare(csi_dev->clock_mod);
158-
reset_control_assert(csi_dev->reset);
159157
return 0;
160158
}
161159

162-
ret = clk_prepare_enable(csi_dev->clock_mod);
163-
if (ret) {
164-
dev_err(csi_dev->dev, "Enable csi clk err %d\n", ret);
160+
ret = pm_runtime_resume_and_get(dev);
161+
if (ret < 0)
165162
return ret;
166-
}
167-
168-
ret = clk_prepare_enable(csi_dev->clock_ram);
169-
if (ret) {
170-
dev_err(csi_dev->dev, "Enable clk_dram_csi clk err %d\n", ret);
171-
goto clk_mod_disable;
172-
}
173-
174-
ret = reset_control_deassert(csi_dev->reset);
175-
if (ret) {
176-
dev_err(csi_dev->dev, "reset err %d\n", ret);
177-
goto clk_ram_disable;
178-
}
179163

180164
regmap_update_bits(regmap, CSI_EN_REG, CSI_EN_CSI_EN, CSI_EN_CSI_EN);
181165

182166
return 0;
183-
184-
clk_ram_disable:
185-
clk_disable_unprepare(csi_dev->clock_ram);
186-
clk_mod_disable:
187-
clk_disable_unprepare(csi_dev->clock_mod);
188-
return ret;
189167
}
190168

191169
static enum csi_input_fmt get_csi_input_format(struct sun6i_csi_device *csi_dev,
@@ -797,6 +775,56 @@ static irqreturn_t sun6i_csi_interrupt(int irq, void *private)
797775
return IRQ_HANDLED;
798776
}
799777

778+
static int sun6i_csi_suspend(struct device *dev)
779+
{
780+
struct sun6i_csi_device *csi_dev = dev_get_drvdata(dev);
781+
782+
reset_control_assert(csi_dev->reset);
783+
clk_disable_unprepare(csi_dev->clock_ram);
784+
clk_disable_unprepare(csi_dev->clock_mod);
785+
786+
return 0;
787+
}
788+
789+
static int sun6i_csi_resume(struct device *dev)
790+
{
791+
struct sun6i_csi_device *csi_dev = dev_get_drvdata(dev);
792+
int ret;
793+
794+
ret = reset_control_deassert(csi_dev->reset);
795+
if (ret) {
796+
dev_err(dev, "failed to deassert reset\n");
797+
return ret;
798+
}
799+
800+
ret = clk_prepare_enable(csi_dev->clock_mod);
801+
if (ret) {
802+
dev_err(dev, "failed to enable module clock\n");
803+
goto error_reset;
804+
}
805+
806+
ret = clk_prepare_enable(csi_dev->clock_ram);
807+
if (ret) {
808+
dev_err(dev, "failed to enable ram clock\n");
809+
goto error_clock_mod;
810+
}
811+
812+
return 0;
813+
814+
error_clock_mod:
815+
clk_disable_unprepare(csi_dev->clock_mod);
816+
817+
error_reset:
818+
reset_control_assert(csi_dev->reset);
819+
820+
return ret;
821+
}
822+
823+
static const struct dev_pm_ops sun6i_csi_pm_ops = {
824+
.runtime_suspend = sun6i_csi_suspend,
825+
.runtime_resume = sun6i_csi_resume,
826+
};
827+
800828
static const struct regmap_config sun6i_csi_regmap_config = {
801829
.reg_bits = 32,
802830
.reg_stride = 4,
@@ -876,6 +904,10 @@ static int sun6i_csi_resources_setup(struct sun6i_csi_device *csi_dev,
876904
goto error_clock_rate_exclusive;
877905
}
878906

907+
/* Runtime PM */
908+
909+
pm_runtime_enable(dev);
910+
879911
return 0;
880912

881913
error_clock_rate_exclusive:
@@ -886,6 +918,7 @@ static int sun6i_csi_resources_setup(struct sun6i_csi_device *csi_dev,
886918

887919
static void sun6i_csi_resources_cleanup(struct sun6i_csi_device *csi_dev)
888920
{
921+
pm_runtime_disable(csi_dev->dev);
889922
clk_rate_exclusive_put(csi_dev->clock_mod);
890923
}
891924

@@ -968,6 +1001,7 @@ static struct platform_driver sun6i_csi_platform_driver = {
9681001
.driver = {
9691002
.name = SUN6I_CSI_NAME,
9701003
.of_match_table = of_match_ptr(sun6i_csi_of_match),
1004+
.pm = &sun6i_csi_pm_ops,
9711005
},
9721006
};
9731007

0 commit comments

Comments
 (0)