From 48c55694f1ea57edab958c5d95bde3e45e9a66aa Mon Sep 17 00:00:00 2001 From: Amit Nischal Date: Wed, 8 Jun 2016 18:34:48 +0530 Subject: [PATCH] msm: camera: Add support for reset controller framework The current api which performs the clock reset is moved to use the reset framework, so support the changes in camera driver for the same. The reset framework requires to get reset handle and perform assert/deassert of the resets. Change-Id: I5a809e464c90c29b6f69fc0bfba67bae9a9b6551 Signed-off-by: Amit Nischal --- .../bindings/media/video/msm-cpp.txt | 7 +++++- arch/arm/boot/dts/qcom/msm8996-camera.dtsi | 4 ++++ arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi | 2 ++ .../msm/camera_v2/common/cam_soc_api.c | 22 +++++++++++++++++++ .../msm/camera_v2/common/cam_soc_api.h | 16 ++++++++++++++ .../msm/camera_v2/pproc/cpp/msm_cpp.c | 16 +++++++++++++- .../msm/camera_v2/pproc/cpp/msm_cpp.h | 1 + .../msm/camera_v2/pproc/cpp/msm_cpp_soc.c | 18 ++++----------- 8 files changed, 70 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/media/video/msm-cpp.txt b/Documentation/devicetree/bindings/media/video/msm-cpp.txt index b39c20ecbf22..52abf409cb65 100644 --- a/Documentation/devicetree/bindings/media/video/msm-cpp.txt +++ b/Documentation/devicetree/bindings/media/video/msm-cpp.txt @@ -22,6 +22,10 @@ Required properties: case dynamic clock scaling based on prevalent streams need lower clock rate. - qcom,cpp-fw-payload-info: Child node for cpp node having infomration on cpp firmware payload offsets. This is mandatory node. +- resets: reset specifier pair consists of phandle for the reset controller + and reset lines used by this controller. +- reset-names: reset signal name strings sorted in the same order as the resets + property. Required properties of the child node: - qcom,stripe-base = Base offset of stripes in cpp payload. @@ -120,6 +124,7 @@ Example: qcom,ref-we-mmu-pf-ptr-off = <22>; qcom,set-group-buffer-len = <135>; qcom,dup-frame-indicator-off = <70>; - + resets = <&clock_mmss MMSS_CAMSS_MICRO_BCR>; + reset-names = "micro_iface_reset"; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-camera.dtsi b/arch/arm/boot/dts/qcom/msm8996-camera.dtsi index 3422e5e7f500..282e6bcb713b 100644 --- a/arch/arm/boot/dts/qcom/msm8996-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-camera.dtsi @@ -623,6 +623,10 @@ "camss_cpp_axi_clk", "camss_cpp_clk", "micro_iface_clk", "camss_ahb_clk", "smmu_cpp_axi_clk", "cpp_vbif_ahb_clk"; + + resets = <&clock_mmss CAMSS_MICRO_BCR>; + reset-names = "micro_iface_reset"; + qcom,clock-rates = <0 0 0 480000000 0 0 480000000 0 0 0 0>; qcom,min-clock-rate = <200000000>; qcom,bus-master = <1>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi index b4516f381c0c..154bc5b092df 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi @@ -405,6 +405,8 @@ <106 512 0 0>, <106 512 0 0>; qcom,msm-bus-vector-dyn-vote; + resets = <&clock_mmss CAMSS_MICRO_BCR>; + reset-names = "micro_iface_reset"; qcom,cpp-fw-payload-info { qcom,stripe-base = <790>; qcom,plane-base = <715>; diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c index 8da079d9d0c8..d6bb18522e0c 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c +++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c @@ -542,6 +542,28 @@ int msm_camera_put_clk_info_and_rates(struct platform_device *pdev, } EXPORT_SYMBOL(msm_camera_put_clk_info_and_rates); +/* Get reset info from DT */ +int msm_camera_get_reset_info(struct platform_device *pdev, + struct reset_control **micro_iface_reset) +{ + if (!pdev || !micro_iface_reset) + return -EINVAL; + + if (of_property_match_string(pdev->dev.of_node, "reset-names", + "micro_iface_reset")) { + pr_err("err: Reset property not found\n"); + return -EINVAL; + } + + *micro_iface_reset = devm_reset_control_get + (&pdev->dev, "micro_iface_reset"); + if (IS_ERR(*micro_iface_reset)) + return PTR_ERR(*micro_iface_reset); + + return 0; +} +EXPORT_SYMBOL(msm_camera_get_reset_info); + /* Get regulators from DT */ int msm_camera_get_regulator_info(struct platform_device *pdev, struct msm_cam_regulator **vdd_info, diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h index b4494d4d6bab..0e9d26bebe30 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h +++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h @@ -21,6 +21,7 @@ #include #include #include +#include #include enum cam_bus_client { @@ -187,6 +188,21 @@ int msm_camera_clk_enable(struct device *dev, long msm_camera_clk_set_rate(struct device *dev, struct clk *clk, long clk_rate); + +/** + * @brief : Gets reset info + * + * This function extracts the reset information for a specific + * platform device + * + * @param pdev : platform device to get reset information + * @param micro_iface_reset : Pointer to populate the reset names + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ + +int msm_camera_get_reset_info(struct platform_device *pdev, + struct reset_control **micro_iface_reset); /** * @brief : Sets flags of a clock * diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index f4add41c85c9..3ac4c3af3208 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -4017,11 +4017,20 @@ static int cpp_probe(struct platform_device *pdev) } } + rc = msm_camera_get_reset_info(pdev, + &cpp_dev->micro_iface_reset); + if (rc < 0) { + cpp_dev->micro_iface_reset = NULL; + pr_err("%s: failed to get micro_iface_reset\n", + __func__); + goto get_reg_err; + } + rc = msm_camera_get_regulator_info(pdev, &cpp_dev->cpp_vdd, &cpp_dev->num_reg); if (rc < 0) { pr_err("%s: failed to get the regulators\n", __func__); - goto get_reg_err; + goto get_reset_err; } msm_cpp_fetch_dt_params(cpp_dev); @@ -4104,6 +4113,8 @@ static int cpp_probe(struct platform_device *pdev) cpp_probe_init_error: media_entity_cleanup(&cpp_dev->msm_sd.sd.entity); msm_sd_unregister(&cpp_dev->msm_sd); +get_reset_err: + reset_control_put(cpp_dev->micro_iface_reset); get_reg_err: msm_camera_put_clk_info(pdev, &cpp_dev->clk_info, &cpp_dev->cpp_clk, cpp_dev->num_clks); @@ -4161,6 +4172,9 @@ static int cpp_device_remove(struct platform_device *dev) msm_camera_unregister_bus_client(CAM_BUS_CLIENT_CPP); mutex_destroy(&cpp_dev->mutex); kfree(cpp_dev->work); + + reset_control_put(cpp_dev->micro_iface_reset); + destroy_workqueue(cpp_dev->timer_wq); kfree(cpp_dev->cpp_clk); kfree(cpp_dev); diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h index 1784e27b1e37..d5abe0202717 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h @@ -211,6 +211,7 @@ struct cpp_device { struct clk **cpp_clk; struct msm_cam_clk_info *clk_info; size_t num_clks; + struct reset_control *micro_iface_reset; struct msm_cam_regulator *cpp_vdd; int num_reg; struct mutex mutex; diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c index ee52284e3ae3..2c313016bc90 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c @@ -103,20 +103,11 @@ static int cpp_get_clk_freq_tbl(struct clk *clk, struct cpp_hw_info *hw_info, int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev) { - uint32_t msm_micro_iface_idx; int rc; - msm_micro_iface_idx = msm_cpp_get_clock_index(cpp_dev, - "micro_iface_clk"); - if (msm_micro_iface_idx < 0) { - pr_err("Fail to get clock index\n"); - return -EINVAL; - } - - rc = clk_reset(cpp_dev->cpp_clk[msm_micro_iface_idx], - CLK_RESET_ASSERT); + rc = reset_control_assert(cpp_dev->micro_iface_reset); if (rc) { - pr_err("%s:micro_iface_clk assert failed\n", + pr_err("%s:micro_iface_reset assert failed\n", __func__); return -EINVAL; } @@ -129,10 +120,9 @@ int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev) */ usleep_range(1000, 1200); - rc = clk_reset(cpp_dev->cpp_clk[msm_micro_iface_idx], - CLK_RESET_DEASSERT); + rc = reset_control_deassert(cpp_dev->micro_iface_reset); if (rc) { - pr_err("%s:micro_iface_clk de-assert failed\n", __func__); + pr_err("%s:micro_iface_reset de-assert failed\n", __func__); return -EINVAL; }