soc: rockchip: pvtm: Update driver to use clk_bulk and reset array APIs

Change-Id: Ie6ab946fa95fd69607150bd5d48c78f0f58d387d
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
This commit is contained in:
Finley Xiao
2020-04-20 20:57:09 +08:00
committed by Tao Huang
parent 7204bbf8af
commit da913c30e2
7 changed files with 286 additions and 138 deletions

View File

@@ -19,14 +19,12 @@ Required properties:
- "rockchip,rk3399-pmu-pvtm" - for RK3399 SoCs. - "rockchip,rk3399-pmu-pvtm" - for RK3399 SoCs.
- clocks: Must contain an entry for each entry in clock-names. - clocks: Must contain an entry for each entry in clock-names.
See ../../clocks/clock-bindings.txt for details. See ../../clocks/clock-bindings.txt for details.
- clock-names: Should be "clk", "pclk", "core_l", "core_b", "gpu", "ddr" and - clock-names: Should be "clk", "pclk".
"pmu".
Optional properties: Optional properties:
- resets: Must contain an entry for each entry in reset-names. - resets: Must contain an entry for each entry in reset-names.
See ../../reset/reset.txt for details. See ../../reset/reset.txt for details.
- reset-names: Should be "clk", "pclk", "core_l", "core_b", "gpu", "ddr" and - reset-names: Should be "rst", "rst-p".
"pmu".
Example: Example:
@@ -41,11 +39,37 @@ grf: syscon@ff770000 {
pvtm: pvtm { pvtm: pvtm {
compatible = "rockchip,rk3399-pvtm"; compatible = "rockchip,rk3399-pvtm";
clocks = <&cru SCLK_PVTM_CORE_L>, <&cru SCLK_PVTM_CORE_B>, #address-cells = <1>;
<&cru SCLK_PVTM_GPU>, <&cru SCLK_PVTM_DDR>; #size-cells = <0>;
clock-names = "core_l", "core_b", "gpu", "ddr"; status = "disabled";
resets = <&cru SRST_PVTM_CORE_L>, <&cru SRST_PVTM_CORE_B>,
<&cru SRST_PVTM_GPU>, <&cru SRST_PVTM_DDR>; pvtm@0 {
reset-names = "core_l", "core_b", "gpu", "ddr"; 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";
};
}; };
} }

View File

@@ -1155,11 +1155,24 @@
pvtm: pvtm { pvtm: pvtm {
compatible = "rockchip,rk3288-pvtm"; compatible = "rockchip,rk3288-pvtm";
clocks = <&cru SCLK_PVTM_CORE>, <&cru SCLK_PVTM_GPU>; #address-cells = <1>;
clock-names = "core", "gpu"; #size-cells = <0>;
resets = <&cru SRST_CORE_PVTM>, <&cru SRST_GPU_PVTM>;
reset-names = "core", "gpu";
status = "okay"; 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";
};
}; };
}; };

View File

@@ -469,9 +469,15 @@
pmu_pvtm: pmu-pvtm { pmu_pvtm: pmu-pvtm {
compatible = "rockchip,px30-pmu-pvtm"; compatible = "rockchip,px30-pmu-pvtm";
clocks = <&pmucru SCLK_PVTM_PMU>; #address-cells = <1>;
clock-names = "pmu"; #size-cells = <0>;
status = "okay"; status = "okay";
pvtm@1 {
reg = <1>;
clocks = <&pmucru SCLK_PVTM_PMU>;
clock-names = "clk";
};
}; };
}; };
@@ -690,9 +696,15 @@
pvtm: pvtm { pvtm: pvtm {
compatible = "rockchip,px30-pvtm"; compatible = "rockchip,px30-pvtm";
clocks = <&cru SCLK_PVTM>; #address-cells = <1>;
clock-names = "core"; #size-cells = <0>;
status = "okay"; status = "okay";
pvtm@0 {
reg = <0>;
clocks = <&cru SCLK_PVTM>;
clock-names = "clk";
};
}; };
}; };

View File

@@ -391,9 +391,15 @@
npu_pvtm: npu-pvtm { npu_pvtm: npu-pvtm {
compatible = "rockchip,rk1808-npu-pvtm"; compatible = "rockchip,rk1808-npu-pvtm";
clocks = <&cru SCLK_PVTM_NPU>; #address-cells = <1>;
clock-names = "npu"; #size-cells = <0>;
status = "okay"; status = "okay";
pvtm@2 {
reg = <2>;
clocks = <&cru SCLK_PVTM_NPU>;
clock-names = "clk";
}
}; };
rgb: rgb { rgb: rgb {
@@ -465,9 +471,15 @@
pmu_pvtm: pmu-pvtm { pmu_pvtm: pmu-pvtm {
compatible = "rockchip,rk1808-pmu-pvtm"; compatible = "rockchip,rk1808-pmu-pvtm";
clocks = <&cru SCLK_PVTM_PMU>; #address-cells = <1>;
clock-names = "pmu"; #size-cells = <0>;
status = "okay"; status = "okay";
pvtm@1 {
reg = <1>;
clocks = <&cru SCLK_PVTM_PMU>;
clock-names = "clk";
};
}; };
reboot-mode { reboot-mode {
@@ -496,9 +508,15 @@
pvtm: pvtm { pvtm: pvtm {
compatible = "rockchip,rk1808-pvtm"; compatible = "rockchip,rk1808-pvtm";
clocks = <&cru SCLK_PVTM_CORE>; #address-cells = <1>;
clock-names = "core"; #size-cells = <0>;
status = "okay"; status = "okay";
pvtm@0 {
reg = <0>;
clocks = <&cru SCLK_PVTM_CORE>;
clock-names = "clk";
};
}; };
}; };

View File

@@ -373,8 +373,14 @@
pmu_pvtm: pmu-pvtm { pmu_pvtm: pmu-pvtm {
compatible = "rockchip,rk3308-pmu-pvtm"; compatible = "rockchip,rk3308-pmu-pvtm";
clocks = <&cru SCLK_PVTM_PMU>; #address-cells = <1>;
clock-names = "pmu"; #size-cells = <0>;
pvtm@1 {
reg = <1>;
clocks = <&cru SCLK_PVTM_PMU>;
clock-names = "clk";
};
}; };
reboot-mode { reboot-mode {
@@ -403,8 +409,14 @@
pvtm: pvtm { pvtm: pvtm {
compatible = "rockchip,rk3308-pvtm"; compatible = "rockchip,rk3308-pvtm";
clocks = <&cru SCLK_PVTM_CORE>; #address-cells = <1>;
clock-names = "core"; #size-cells = <0>;
pvtm@0 {
reg = <0>;
clocks = <&cru SCLK_PVTM_CORE>;
clock-names = "clk";
};
}; };
}; };

View File

@@ -1172,11 +1172,17 @@
pmu_pvtm: pmu-pvtm { pmu_pvtm: pmu-pvtm {
compatible = "rockchip,rk3399-pmu-pvtm"; compatible = "rockchip,rk3399-pmu-pvtm";
clocks = <&pmucru SCLK_PVTM_PMU>; #address-cells = <1>;
clock-names = "pmu"; #size-cells = <0>;
resets = <&cru SRST_PVTM>;
reset-names = "pmu";
status = "disabled"; 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 { pvtm: pvtm {
compatible = "rockchip,rk3399-pvtm"; compatible = "rockchip,rk3399-pvtm";
clocks = <&cru SCLK_PVTM_CORE_L>, #address-cells = <1>;
<&cru SCLK_PVTM_CORE_B>, #size-cells = <0>;
<&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";
status = "disabled"; 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";
};
}; };
}; };

View File

@@ -14,6 +14,7 @@
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_clk.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
@@ -22,30 +23,12 @@
#include <linux/soc/rockchip/pvtm.h> #include <linux/soc/rockchip/pvtm.h>
#include <linux/thermal.h> #include <linux/thermal.h>
#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 wr_mask_bit(v, off, mask) ((v) << (off) | (mask) << (16 + off))
#define PVTM(_ch, _name, _num_sub, _start, _en, _cal, _done, _freq) \ #define PVTM(_ch, _name, _num_sub, _start, _en, _cal, _done, _freq) \
{ \ { \
.ch = _ch, \ .ch = _ch, \
.clk_name = _name, \ .name = _name, \
.num_sub = _num_sub, \ .num_sub = _num_sub, \
.bit_start = _start, \ .bit_start = _start, \
.bit_en = _en, \ .bit_en = _en, \
@@ -60,7 +43,7 @@ struct rockchip_pvtm_channel {
u32 reg_cal; u32 reg_cal;
u32 reg_freq; u32 reg_freq;
unsigned char ch; unsigned char ch;
unsigned char *clk_name; unsigned char *name;
unsigned int num_sub; unsigned int num_sub;
unsigned int bit_start; unsigned int bit_start;
unsigned int bit_en; unsigned int bit_en;
@@ -83,7 +66,8 @@ struct rockchip_pvtm {
struct list_head node; struct list_head node;
struct device *dev; struct device *dev;
struct regmap *grf; struct regmap *grf;
struct clk *clk; int num_clks;
struct clk_bulk_data *clks;
struct reset_control *rst; struct reset_control *rst;
const struct rockchip_pvtm_channel *channel; const struct rockchip_pvtm_channel *channel;
struct thermal_zone_device *tz; struct thermal_zone_device *tz;
@@ -155,10 +139,10 @@ static int __init pvtm_debug_init(void)
} }
list_for_each_entry(pvtm, &pvtm_list, node) { 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) { if (!dentry) {
dev_err(pvtm->dev, "failed to creat pvtm %s debug dir\n", dev_err(pvtm->dev, "failed to creat pvtm %s debug dir\n",
pvtm->channel->clk_name); pvtm->channel->name);
return -ENOMEM; return -ENOMEM;
} }
@@ -166,7 +150,7 @@ static int __init pvtm_debug_init(void)
(void *)pvtm, &pvtm_value_fops); (void *)pvtm, &pvtm_value_fops);
if (!d) { if (!d) {
dev_err(pvtm->dev, "failed to pvtm %s value node\n", dev_err(pvtm->dev, "failed to pvtm %s value node\n",
pvtm->channel->clk_name); pvtm->channel->name);
return -ENOMEM; return -ENOMEM;
} }
} }
@@ -269,12 +253,12 @@ static void rk3399_pvtm_set_ring_sel(struct rockchip_pvtm *pvtm,
{ {
unsigned int ch = pvtm->channel->ch; unsigned int ch = pvtm->channel->ch;
if (ch == RK3399_PVTM_CORE_B) { if (ch == 1) {
regmap_write(pvtm->grf, pvtm->con + 0x14, regmap_write(pvtm->grf, pvtm->con + 0x14,
wr_mask_bit(sub_ch >> 0x3, 0, 0x1)); wr_mask_bit(sub_ch >> 0x3, 0, 0x1));
sub_ch &= 0x3; sub_ch &= 0x3;
} }
if (ch != RK3399_PVTM_PMU) if (ch != 4)
regmap_write(pvtm->grf, pvtm->con, regmap_write(pvtm->grf, pvtm->con,
wr_mask_bit(sub_ch, (ch * 0x4 + 0x2), 0x3)); 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) unsigned int time_us)
{ {
const struct rockchip_pvtm_channel *channel = pvtm->channel; const struct rockchip_pvtm_channel *channel = pvtm->channel;
unsigned int ch = pvtm->channel->ch;
unsigned int clk_cnt, check_cnt = 100; unsigned int clk_cnt, check_cnt = 100;
u32 sta, val = 0; u32 sta, val = 0;
int ret; int ret;
ret = clk_prepare_enable(pvtm->clk); ret = clk_bulk_prepare_enable(pvtm->num_clks, pvtm->clks);
if (ret < 0) { 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; return 0;
} }
ret = rockchip_pvtm_reset(pvtm);
if (pvtm->rst) { if (ret) {
ret = rockchip_pvtm_reset(pvtm); dev_err(pvtm->dev, "failed to reset pvtm\n");
if (ret) { goto disable_clks;
clk_disable_unprepare(pvtm->clk);
return 0;
}
} }
/* if last status is enabled, stop calculating cycles first*/ /* if last status is enabled, stop calculating cycles first*/
regmap_read(pvtm->grf, pvtm->con, &sta); regmap_read(pvtm->grf, pvtm->con, &sta);
if (sta & PVTM_START_EN) if (sta & BIT(channel->bit_en))
regmap_write(pvtm->grf, pvtm->con, regmap_write(pvtm->grf, pvtm->con,
wr_mask_bit(0, channel->bit_start, 0x1)); 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, regmap_write(pvtm->grf, pvtm->con,
wr_mask_bit(0, channel->bit_en, 0x1)); 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; return val;
} }
static const struct rockchip_pvtm_channel px30_pvtm_channels[] = { 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 = { 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[] = { 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 = { 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[] = { 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 = { 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[] = { 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 = { 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[] = { 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 = { 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[] = { static const struct rockchip_pvtm_channel rk3288_pvtm_channels[] = {
PVTM(RK3288_PVTM_CORE, "core", 1, 0, 1, 0x4, 1, 0x4), PVTM(0, "core", 1, 0, 1, 0x4, 1, 0x4),
PVTM(RK3288_PVTM_GPU, "gpu", 1, 8, 9, 0x8, 0, 0x8), PVTM(1, "gpu", 1, 8, 9, 0x8, 0, 0x8),
}; };
static const struct rockchip_pvtm_info rk3288_pvtm = { 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[] = { static const struct rockchip_pvtm_channel rk3399_pvtm_channels[] = {
PVTM(RK3399_PVTM_CORE_L, "core_l", 4, 0, 1, 0x4, 0, 0x4), PVTM(0, "core_l", 4, 0, 1, 0x4, 0, 0x4),
PVTM(RK3399_PVTM_CORE_B, "core_b", 6, 4, 5, 0x8, 1, 0x8), PVTM(1, "core_b", 6, 4, 5, 0x8, 1, 0x8),
PVTM(RK3399_PVTM_DDR, "ddr", 4, 8, 9, 0xc, 3, 0x10), PVTM(2, "ddr", 4, 8, 9, 0xc, 3, 0x10),
PVTM(RK3399_PVTM_GPU, "gpu", 4, 12, 13, 0x10, 2, 0xc), PVTM(3, "gpu", 4, 12, 13, 0x10, 2, 0xc),
}; };
static const struct rockchip_pvtm_info rk3399_pvtm = { 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[] = { 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 = { 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); 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) static int rockchip_pvtm_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device_node *node;
const struct of_device_id *match; const struct of_device_id *match;
const struct rockchip_pvtm_info *info;
struct rockchip_pvtm *pvtm; struct rockchip_pvtm *pvtm;
struct regmap *grf; 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); match = of_match_device(dev->driver->of_match_table, dev);
if (!match || !match->data) { if (!match || !match->data) {
@@ -525,58 +598,27 @@ static int rockchip_pvtm_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
info = match->data;
if (!dev->parent || !dev->parent->of_node) if (!dev->parent || !dev->parent->of_node)
return -EINVAL; return -EINVAL;
grf = syscon_node_to_regmap(dev->parent->of_node); grf = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(grf)) if (IS_ERR(grf))
return PTR_ERR(grf); return PTR_ERR(grf);
pvtm = devm_kzalloc(dev, sizeof(*pvtm) * info->num_channels, for_each_available_child_of_node(np, node) {
GFP_KERNEL); pvtm = rockchip_pvtm_init(dev, node, match->data, grf);
if (!pvtm) if (!pvtm) {
return -ENOMEM; dev_err(dev, "failed to handle node %s\n", node->name);
goto error;
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;
} }
} list_add(&pvtm->node, &pvtm_list);
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);
} }
return 0; return 0;
error:
rockchip_del_pvtm(match->data);
return -EINVAL;
} }
static struct platform_driver rockchip_pvtm_driver = { static struct platform_driver rockchip_pvtm_driver = {