diff --git a/Documentation/devicetree/bindings/soc/rockchip/rockchip-pvtm.txt b/Documentation/devicetree/bindings/soc/rockchip/rockchip-pvtm.txt index 06a0bdc5fc9e..4bc908ff927c 100644 --- a/Documentation/devicetree/bindings/soc/rockchip/rockchip-pvtm.txt +++ b/Documentation/devicetree/bindings/soc/rockchip/rockchip-pvtm.txt @@ -19,14 +19,12 @@ Required properties: - "rockchip,rk3399-pmu-pvtm" - for RK3399 SoCs. - clocks: Must contain an entry for each entry in clock-names. See ../../clocks/clock-bindings.txt for details. -- clock-names: Should be "clk", "pclk", "core_l", "core_b", "gpu", "ddr" and - "pmu". +- clock-names: Should be "clk", "pclk". Optional properties: - resets: Must contain an entry for each entry in reset-names. See ../../reset/reset.txt for details. -- reset-names: Should be "clk", "pclk", "core_l", "core_b", "gpu", "ddr" and - "pmu". +- reset-names: Should be "rst", "rst-p". Example: @@ -41,11 +39,37 @@ grf: syscon@ff770000 { pvtm: pvtm { compatible = "rockchip,rk3399-pvtm"; - clocks = <&cru SCLK_PVTM_CORE_L>, <&cru SCLK_PVTM_CORE_B>, - <&cru SCLK_PVTM_GPU>, <&cru SCLK_PVTM_DDR>; - clock-names = "core_l", "core_b", "gpu", "ddr"; - resets = <&cru SRST_PVTM_CORE_L>, <&cru SRST_PVTM_CORE_B>, - <&cru SRST_PVTM_GPU>, <&cru SRST_PVTM_DDR>; - reset-names = "core_l", "core_b", "gpu", "ddr"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + pvtm@0 { + reg = <0>; + clocks = <&cru SCLK_PVTM_CORE_L>; + clock-names = "clk"; + resets = <&cru SRST_PVTM_CORE_L>; + reset-names = "rst"; + }; + pvtm@1 { + reg = <1>; + clocks = <&cru SCLK_PVTM_CORE_B>; + clock-names = "clk"; + resets = <&cru SRST_PVTM_CORE_B>; + reset-names = "rst"; + }; + pvtm@2 { + reg = <2>; + clocks = <&cru SCLK_PVTM_DDR>; + clock-names = "clk"; + resets = <&cru SRST_PVTM_DDR>; + reset-names = "rst"; + }; + pvtm@3 { + reg = <3>; + clocks = <&cru SCLK_PVTM_GPU>; + clock-names = "clk"; + resets = <&cru SRST_PVTM_GPU>; + reset-names = "rst"; + }; }; } diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index c332cea5908f..079b66fa6120 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -1155,11 +1155,24 @@ pvtm: pvtm { compatible = "rockchip,rk3288-pvtm"; - clocks = <&cru SCLK_PVTM_CORE>, <&cru SCLK_PVTM_GPU>; - clock-names = "core", "gpu"; - resets = <&cru SRST_CORE_PVTM>, <&cru SRST_GPU_PVTM>; - reset-names = "core", "gpu"; + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + pvtm@0 { + reg = <0>; + clocks = <&cru SCLK_PVTM_CORE>; + clock-names = "clk"; + resets = <&cru SRST_CORE_PVTM>; + reset-names = "rst"; + }; + pvtm@1 { + reg = <1>; + clocks = <&cru SCLK_PVTM_GPU>; + clock-names = "clk"; + resets = <&cru SRST_GPU_PVTM>; + reset-names = "rst"; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 9ad733e3e8d4..d1dfb7021dee 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -469,9 +469,15 @@ pmu_pvtm: pmu-pvtm { compatible = "rockchip,px30-pmu-pvtm"; - clocks = <&pmucru SCLK_PVTM_PMU>; - clock-names = "pmu"; + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + pvtm@1 { + reg = <1>; + clocks = <&pmucru SCLK_PVTM_PMU>; + clock-names = "clk"; + }; }; }; @@ -690,9 +696,15 @@ pvtm: pvtm { compatible = "rockchip,px30-pvtm"; - clocks = <&cru SCLK_PVTM>; - clock-names = "core"; + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + pvtm@0 { + reg = <0>; + clocks = <&cru SCLK_PVTM>; + clock-names = "clk"; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk1808.dtsi b/arch/arm64/boot/dts/rockchip/rk1808.dtsi index 1d52ec66754e..d6cb1b4477e8 100644 --- a/arch/arm64/boot/dts/rockchip/rk1808.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk1808.dtsi @@ -391,9 +391,15 @@ npu_pvtm: npu-pvtm { compatible = "rockchip,rk1808-npu-pvtm"; - clocks = <&cru SCLK_PVTM_NPU>; - clock-names = "npu"; + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + pvtm@2 { + reg = <2>; + clocks = <&cru SCLK_PVTM_NPU>; + clock-names = "clk"; + } }; rgb: rgb { @@ -465,9 +471,15 @@ pmu_pvtm: pmu-pvtm { compatible = "rockchip,rk1808-pmu-pvtm"; - clocks = <&cru SCLK_PVTM_PMU>; - clock-names = "pmu"; + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + pvtm@1 { + reg = <1>; + clocks = <&cru SCLK_PVTM_PMU>; + clock-names = "clk"; + }; }; reboot-mode { @@ -496,9 +508,15 @@ pvtm: pvtm { compatible = "rockchip,rk1808-pvtm"; - clocks = <&cru SCLK_PVTM_CORE>; - clock-names = "core"; + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + pvtm@0 { + reg = <0>; + clocks = <&cru SCLK_PVTM_CORE>; + clock-names = "clk"; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi index 8cdc6f0d237c..0529c797f0c1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi @@ -373,8 +373,14 @@ pmu_pvtm: pmu-pvtm { compatible = "rockchip,rk3308-pmu-pvtm"; - clocks = <&cru SCLK_PVTM_PMU>; - clock-names = "pmu"; + #address-cells = <1>; + #size-cells = <0>; + + pvtm@1 { + reg = <1>; + clocks = <&cru SCLK_PVTM_PMU>; + clock-names = "clk"; + }; }; reboot-mode { @@ -403,8 +409,14 @@ pvtm: pvtm { compatible = "rockchip,rk3308-pvtm"; - clocks = <&cru SCLK_PVTM_CORE>; - clock-names = "core"; + #address-cells = <1>; + #size-cells = <0>; + + pvtm@0 { + reg = <0>; + clocks = <&cru SCLK_PVTM_CORE>; + clock-names = "clk"; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index 429c95839464..1b97c7d12da3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -1172,11 +1172,17 @@ pmu_pvtm: pmu-pvtm { compatible = "rockchip,rk3399-pmu-pvtm"; - clocks = <&pmucru SCLK_PVTM_PMU>; - clock-names = "pmu"; - resets = <&cru SRST_PVTM>; - reset-names = "pmu"; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; + + pvtm@4 { + reg = <4>; + clocks = <&pmucru SCLK_PVTM_PMU>; + clock-names = "clk"; + resets = <&cru SRST_PVTM>; + reset-names = "rst"; + }; }; }; @@ -1616,17 +1622,38 @@ pvtm: pvtm { compatible = "rockchip,rk3399-pvtm"; - clocks = <&cru SCLK_PVTM_CORE_L>, - <&cru SCLK_PVTM_CORE_B>, - <&cru SCLK_PVTM_GPU>, - <&cru SCLK_PVTM_DDR>; - clock-names = "core_l", "core_b", "gpu", "ddr"; - resets = <&cru SRST_PVTM_CORE_L>, - <&cru SRST_PVTM_CORE_B>, - <&cru SRST_PVTM_GPU>, - <&cru SRST_PVTM_DDR>; - reset-names = "core_l", "core_b", "gpu", "ddr"; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; + + pvtm@0 { + reg = <0>; + clocks = <&cru SCLK_PVTM_CORE_L>; + clock-names = "clk"; + resets = <&cru SRST_PVTM_CORE_L>; + reset-names = "rst"; + }; + pvtm@1 { + reg = <1>; + clocks = <&cru SCLK_PVTM_CORE_B>; + clock-names = "clk"; + resets = <&cru SRST_PVTM_CORE_B>; + reset-names = "rst"; + }; + pvtm@2 { + reg = <2>; + clocks = <&cru SCLK_PVTM_DDR>; + clock-names = "clk"; + resets = <&cru SRST_PVTM_DDR>; + reset-names = "rst"; + }; + pvtm@3 { + reg = <3>; + clocks = <&cru SCLK_PVTM_GPU>; + clock-names = "clk"; + resets = <&cru SRST_PVTM_GPU>; + reset-names = "rst"; + }; }; }; diff --git a/drivers/soc/rockchip/rockchip_pvtm.c b/drivers/soc/rockchip/rockchip_pvtm.c index ef726d10f18c..ce8767ddb7d0 100644 --- a/drivers/soc/rockchip/rockchip_pvtm.c +++ b/drivers/soc/rockchip/rockchip_pvtm.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -22,30 +23,12 @@ #include #include -#define PX30_PVTM_CORE 0 -#define PX30_PVTM_PMU 1 - -#define RK1808_PVTM_CORE 0 -#define RK1808_PVTM_PMU 1 -#define RK1808_PVTM_NPU 2 - -#define RK3288_PVTM_CORE 0 -#define RK3288_PVTM_GPU 1 - -#define RK3399_PVTM_CORE_L 0 -#define RK3399_PVTM_CORE_B 1 -#define RK3399_PVTM_DDR 2 -#define RK3399_PVTM_GPU 3 -#define RK3399_PVTM_PMU 4 - -#define PVTM_START_EN 0x1 - #define wr_mask_bit(v, off, mask) ((v) << (off) | (mask) << (16 + off)) #define PVTM(_ch, _name, _num_sub, _start, _en, _cal, _done, _freq) \ { \ .ch = _ch, \ - .clk_name = _name, \ + .name = _name, \ .num_sub = _num_sub, \ .bit_start = _start, \ .bit_en = _en, \ @@ -60,7 +43,7 @@ struct rockchip_pvtm_channel { u32 reg_cal; u32 reg_freq; unsigned char ch; - unsigned char *clk_name; + unsigned char *name; unsigned int num_sub; unsigned int bit_start; unsigned int bit_en; @@ -83,7 +66,8 @@ struct rockchip_pvtm { struct list_head node; struct device *dev; struct regmap *grf; - struct clk *clk; + int num_clks; + struct clk_bulk_data *clks; struct reset_control *rst; const struct rockchip_pvtm_channel *channel; struct thermal_zone_device *tz; @@ -155,10 +139,10 @@ static int __init pvtm_debug_init(void) } list_for_each_entry(pvtm, &pvtm_list, node) { - dentry = debugfs_create_dir(pvtm->channel->clk_name, rootdir); + dentry = debugfs_create_dir(pvtm->channel->name, rootdir); if (!dentry) { dev_err(pvtm->dev, "failed to creat pvtm %s debug dir\n", - pvtm->channel->clk_name); + pvtm->channel->name); return -ENOMEM; } @@ -166,7 +150,7 @@ static int __init pvtm_debug_init(void) (void *)pvtm, &pvtm_value_fops); if (!d) { dev_err(pvtm->dev, "failed to pvtm %s value node\n", - pvtm->channel->clk_name); + pvtm->channel->name); return -ENOMEM; } } @@ -269,12 +253,12 @@ static void rk3399_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm, { unsigned int ch = pvtm->channel->ch; - if (ch == RK3399_PVTM_CORE_B) { + if (ch == 1) { regmap_write(pvtm->grf, pvtm->con + 0x14, wr_mask_bit(sub_ch >> 0x3, 0, 0x1)); sub_ch &= 0x3; } - if (ch != RK3399_PVTM_PMU) + if (ch != 4) regmap_write(pvtm->grf, pvtm->con, wr_mask_bit(sub_ch, (ch * 0x4 + 0x2), 0x3)); } @@ -284,28 +268,24 @@ static u32 rockchip_pvtm_get_value(struct rockchip_pvtm *pvtm, unsigned int time_us) { const struct rockchip_pvtm_channel *channel = pvtm->channel; - unsigned int ch = pvtm->channel->ch; unsigned int clk_cnt, check_cnt = 100; u32 sta, val = 0; int ret; - ret = clk_prepare_enable(pvtm->clk); + ret = clk_bulk_prepare_enable(pvtm->num_clks, pvtm->clks); if (ret < 0) { - dev_err(pvtm->dev, "failed to enable %d\n", ch); + dev_err(pvtm->dev, "failed to prepare/enable pvtm clks\n"); return 0; } - - if (pvtm->rst) { - ret = rockchip_pvtm_reset(pvtm); - if (ret) { - clk_disable_unprepare(pvtm->clk); - return 0; - } + ret = rockchip_pvtm_reset(pvtm); + if (ret) { + dev_err(pvtm->dev, "failed to reset pvtm\n"); + goto disable_clks; } /* if last status is enabled, stop calculating cycles first*/ regmap_read(pvtm->grf, pvtm->con, &sta); - if (sta & PVTM_START_EN) + if (sta & BIT(channel->bit_en)) regmap_write(pvtm->grf, pvtm->con, wr_mask_bit(0, channel->bit_start, 0x1)); @@ -345,13 +325,14 @@ static u32 rockchip_pvtm_get_value(struct rockchip_pvtm *pvtm, regmap_write(pvtm->grf, pvtm->con, wr_mask_bit(0, channel->bit_en, 0x1)); - clk_disable_unprepare(pvtm->clk); +disable_clks: + clk_bulk_disable_unprepare(pvtm->num_clks, pvtm->clks); return val; } static const struct rockchip_pvtm_channel px30_pvtm_channels[] = { - PVTM(PX30_PVTM_CORE, "core", 3, 0, 1, 0x4, 0, 0x4), + PVTM(0, "core", 3, 0, 1, 0x4, 0, 0x4), }; static const struct rockchip_pvtm_info px30_pvtm = { @@ -364,7 +345,7 @@ static const struct rockchip_pvtm_info px30_pvtm = { }; static const struct rockchip_pvtm_channel px30_pmupvtm_channels[] = { - PVTM(PX30_PVTM_PMU, "pmu", 1, 0, 1, 0x4, 0, 0x4), + PVTM(1, "pmu", 1, 0, 1, 0x4, 0, 0x4), }; static const struct rockchip_pvtm_info px30_pmupvtm = { @@ -376,7 +357,7 @@ static const struct rockchip_pvtm_info px30_pmupvtm = { }; static const struct rockchip_pvtm_channel rk1808_pvtm_channels[] = { - PVTM(RK1808_PVTM_CORE, "core", 5, 0, 1, 0x4, 0, 0x4), + PVTM(0, "core", 5, 0, 1, 0x4, 0, 0x4), }; static const struct rockchip_pvtm_info rk1808_pvtm = { @@ -389,7 +370,7 @@ static const struct rockchip_pvtm_info rk1808_pvtm = { }; static const struct rockchip_pvtm_channel rk1808_pmupvtm_channels[] = { - PVTM(RK1808_PVTM_PMU, "pmu", 1, 0, 1, 0x4, 0, 0x4), + PVTM(1, "pmu", 1, 0, 1, 0x4, 0, 0x4), }; static const struct rockchip_pvtm_info rk1808_pmupvtm = { @@ -401,7 +382,7 @@ static const struct rockchip_pvtm_info rk1808_pmupvtm = { }; static const struct rockchip_pvtm_channel rk1808_npupvtm_channels[] = { - PVTM(RK1808_PVTM_NPU, "npu", 5, 0, 1, 0x4, 0, 0x4), + PVTM(2, "npu", 5, 0, 1, 0x4, 0, 0x4), }; static const struct rockchip_pvtm_info rk1808_npupvtm = { @@ -414,8 +395,8 @@ static const struct rockchip_pvtm_info rk1808_npupvtm = { }; static const struct rockchip_pvtm_channel rk3288_pvtm_channels[] = { - PVTM(RK3288_PVTM_CORE, "core", 1, 0, 1, 0x4, 1, 0x4), - PVTM(RK3288_PVTM_GPU, "gpu", 1, 8, 9, 0x8, 0, 0x8), + PVTM(0, "core", 1, 0, 1, 0x4, 1, 0x4), + PVTM(1, "gpu", 1, 8, 9, 0x8, 0, 0x8), }; static const struct rockchip_pvtm_info rk3288_pvtm = { @@ -435,10 +416,10 @@ static const struct rockchip_pvtm_info rk3308_pmupvtm = { }; static const struct rockchip_pvtm_channel rk3399_pvtm_channels[] = { - PVTM(RK3399_PVTM_CORE_L, "core_l", 4, 0, 1, 0x4, 0, 0x4), - PVTM(RK3399_PVTM_CORE_B, "core_b", 6, 4, 5, 0x8, 1, 0x8), - PVTM(RK3399_PVTM_DDR, "ddr", 4, 8, 9, 0xc, 3, 0x10), - PVTM(RK3399_PVTM_GPU, "gpu", 4, 12, 13, 0x10, 2, 0xc), + PVTM(0, "core_l", 4, 0, 1, 0x4, 0, 0x4), + PVTM(1, "core_b", 6, 4, 5, 0x8, 1, 0x8), + PVTM(2, "ddr", 4, 8, 9, 0xc, 3, 0x10), + PVTM(3, "gpu", 4, 12, 13, 0x10, 2, 0xc), }; static const struct rockchip_pvtm_info rk3399_pvtm = { @@ -451,7 +432,7 @@ static const struct rockchip_pvtm_info rk3399_pvtm = { }; static const struct rockchip_pvtm_channel rk3399_pmupvtm_channels[] = { - PVTM(RK3399_PVTM_PMU, "pmu", 1, 0, 1, 0x4, 0, 0x4), + PVTM(4, "pmu", 1, 0, 1, 0x4, 0, 0x4), }; static const struct rockchip_pvtm_info rk3399_pmupvtm = { @@ -507,17 +488,109 @@ static const struct of_device_id rockchip_pvtm_match[] = { }; MODULE_DEVICE_TABLE(of, rockchip_pvtm_match); +static int rockchip_pvtm_get_ch_index(const struct rockchip_pvtm_info *info, + u32 ch, u32 *index) +{ + int i; + + for (i = 0; i < info->num_channels; i++) { + if (ch == info->channels[i].ch) { + *index = i; + return 0; + } + } + + return -EINVAL; +} + +static struct rockchip_pvtm * +rockchip_pvtm_init(struct device *dev, struct device_node *node, + const struct rockchip_pvtm_info *info, + struct regmap *grf) +{ + struct rockchip_pvtm *pvtm; + const char *tz_name; + u32 ch, index, i; + + if (of_property_read_u32(node, "reg", &ch)) { + dev_err(dev, "%s: failed to retrieve pvtm ch\n", node->name); + return NULL; + } + if (rockchip_pvtm_get_ch_index(info, ch, &index)) { + dev_err(dev, "%s: invalid pvtm ch %d\n", node->name, ch); + return NULL; + } + + pvtm = devm_kzalloc(dev, sizeof(*pvtm), GFP_KERNEL); + if (!pvtm) + return NULL; + + pvtm->dev = dev; + pvtm->grf = grf; + pvtm->con = info->con; + pvtm->sta = info->sta; + pvtm->get_value = info->get_value; + pvtm->channel = &info->channels[index]; + if (info->set_ring_sel) + pvtm->set_ring_sel = info->set_ring_sel; + + if (!of_property_read_string(node, "thermal-zone", &tz_name)) { + pvtm->tz = thermal_zone_get_zone_by_name(tz_name); + if (IS_ERR(pvtm->tz)) { + dev_err(pvtm->dev, "failed to retrieve pvtm_tz\n"); + pvtm->tz = NULL; + } + } + + pvtm->num_clks = of_clk_get_parent_count(node); + if (pvtm->num_clks <= 0) { + dev_err(dev, "%s: does not have clocks\n", node->name); + return NULL; + } + pvtm->clks = devm_kcalloc(dev, pvtm->num_clks, sizeof(*pvtm->clks), + GFP_KERNEL); + if (!pvtm->clks) + return NULL; + for (i = 0; i < pvtm->num_clks; i++) { + pvtm->clks[i].clk = of_clk_get(node, i); + if (IS_ERR(pvtm->clks[i].clk)) { + dev_err(dev, "%s: failed to get clk at index %d\n", + node->name, i); + return NULL; + } + } + + pvtm->rst = devm_reset_control_array_get_optional_exclusive(dev); + if (IS_ERR(pvtm->rst)) + dev_dbg(dev, "%s: failed to get reset\n", node->name); + + return pvtm; +} + +static void rockchip_del_pvtm(const struct rockchip_pvtm_info *info) +{ + struct rockchip_pvtm *pvtm, *tmp; + int i; + + if (list_empty(&pvtm_list)) + return; + + for (i = 0; i < info->num_channels; i++) { + list_for_each_entry_safe(pvtm, tmp, &pvtm_list, node) { + if (pvtm->channel->ch == info->channels[i].ch) + list_del(&pvtm->node); + } + } +} + static int rockchip_pvtm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = pdev->dev.of_node; + struct device_node *node; const struct of_device_id *match; - const struct rockchip_pvtm_info *info; struct rockchip_pvtm *pvtm; struct regmap *grf; - struct thermal_zone_device *pvtm_tz = NULL; - const char *tz_name; - int i; match = of_match_device(dev->driver->of_match_table, dev); if (!match || !match->data) { @@ -525,58 +598,27 @@ static int rockchip_pvtm_probe(struct platform_device *pdev) return -EINVAL; } - info = match->data; - if (!dev->parent || !dev->parent->of_node) return -EINVAL; - grf = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(grf)) return PTR_ERR(grf); - pvtm = devm_kzalloc(dev, sizeof(*pvtm) * info->num_channels, - GFP_KERNEL); - if (!pvtm) - return -ENOMEM; - - if (!of_property_read_string(np, "thermal-zone", &tz_name)) { - pvtm_tz = thermal_zone_get_zone_by_name(tz_name); - if (IS_ERR(pvtm_tz)) { - dev_err(dev, "debug failed to get pvtm_tz\n"); - pvtm_tz = NULL; + for_each_available_child_of_node(np, node) { + pvtm = rockchip_pvtm_init(dev, node, match->data, grf); + if (!pvtm) { + dev_err(dev, "failed to handle node %s\n", node->name); + goto error; } - } - - for (i = 0; i < info->num_channels; i++) { - pvtm[i].dev = &pdev->dev; - pvtm[i].grf = grf; - pvtm[i].con = info->con; - pvtm[i].sta = info->sta; - pvtm[i].get_value = info->get_value; - pvtm[i].channel = &info->channels[i]; - pvtm[i].tz = pvtm_tz; - if (info->set_ring_sel) - pvtm[i].set_ring_sel = info->set_ring_sel; - - pvtm[i].clk = devm_clk_get(dev, info->channels[i].clk_name); - if (IS_ERR_OR_NULL(pvtm[i].clk)) { - dev_err(dev, "failed to get clk %d %s\n", i, - info->channels[i].clk_name); - return PTR_ERR(pvtm[i].clk); - } - - pvtm[i].rst = - devm_reset_control_get(dev, info->channels[i].clk_name); - if (IS_ERR_OR_NULL(pvtm[i].rst)) { - dev_info(dev, "failed to get rst %d %s\n", i, - info->channels[i].clk_name); - pvtm[i].rst = NULL; - } - - list_add(&pvtm[i].node, &pvtm_list); + list_add(&pvtm->node, &pvtm_list); } return 0; + +error: + rockchip_del_pvtm(match->data); + + return -EINVAL; } static struct platform_driver rockchip_pvtm_driver = {