mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
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:
@@ -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";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_clk.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
@@ -22,30 +23,12 @@
|
||||
#include <linux/soc/rockchip/pvtm.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 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 = {
|
||||
|
||||
Reference in New Issue
Block a user