List of fixes:
- Fix for VM sensor allocation
- Fix multi-channel voltage reading
- Protect from negative voltage value
- Fix temperature equation and coefficients
List of new features:
- Add option to skip reset controller
- Add VM active channel support
- Add VM pre-scalar support
- Add parsing of thermal coefficients from device-tree
- Add debugfs to updater temperature coefficients on the fly
Eliav Farber (16):
hwmon: (mr75203) fix VM sensor allocation when "intel,vm-map" not
defined
hwmon: (mr75203) update pvt->v_num to the actual number of used
sensors
hwmon: (mr75203) update Moortec PVT controller intel,vm-map property
hwmon: (mr75203) add Moortec PVT controller reset-control-skip
property
hwmon: (mr75203) add option to skip reset controller
hwmon: (mr75203) fix multi-channel voltage reading
hwmon: (mr75203) add VM active channels property for Moortec PVT
controller
hwmon: (mr75203) add VM active channel support
hwmon: (mr75203) add VM pre-scalar property for Moortec PVT controller
hwmon: (mr75203) add VM pre-scalar support
hwmon: (mr75203) add protection for negative voltage value
hwmon: (mr75203) modify the temperature equation
hwmon: (mr75203) add thermal coefficient properties for Moortec PVT
controller
hwmon: (mr75203) parse thermal coefficients from device-tree
hwmon: (mr75203) fix coding style space errors
hwmon: (mr75203) add debugfs to read and write temperature
coefficients
.../bindings/hwmon/moortec,mr75203.yaml | 60 ++-
drivers/hwmon/mr75203.c | 465 +++++++++++++++---
2 files changed, 459 insertions(+), 66 deletions(-)
--
2.37.1
Add active channel support per VM, which is useful when not all VM
channels are used.
Number of active channel is read from device-tree.
When absent in device-tree, all channels are assumed to be used.
Setting number of active channels to 0, means that entire VM sesnor is
not used (this can partially replace the "intel,vm-map" functionality).
Signed-off-by: Eliav Farber <[email protected]>
---
drivers/hwmon/mr75203.c | 92 +++++++++++++++++++++++++++++++----------
1 file changed, 70 insertions(+), 22 deletions(-)
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index 4419e481d47c..9b45fd089fcf 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -107,6 +107,11 @@
#define PVT_N_CONST 90
#define PVT_R_CONST 245805
+struct voltage_device {
+ u8 vm_map;
+ u8 ch_map;
+};
+
struct pvt_device {
struct regmap *c_map;
struct regmap *t_map;
@@ -114,12 +119,13 @@ struct pvt_device {
struct regmap *v_map;
struct clk *clk;
struct reset_control *rst;
+ struct voltage_device *vd;
u32 t_num;
u32 p_num;
u32 v_num;
- u32 c_num;
u32 ip_freq;
- u8 *vm_idx;
+ u8 vm_ch_max;
+ u8 vm_ch_total;
};
static umode_t pvt_is_visible(const void *data, enum hwmon_sensor_types type,
@@ -186,11 +192,11 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
u8 ch_idx;
int ret;
- if (channel >= pvt->v_num * pvt->c_num)
+ if (channel >= pvt->vm_ch_total)
return -EINVAL;
- vm_idx = pvt->vm_idx[channel / pvt->c_num];
- ch_idx = channel % pvt->c_num;
+ vm_idx = pvt->vd[channel].vm_map;
+ ch_idx = pvt->vd[channel].ch_map;
switch (attr) {
case hwmon_in_input:
@@ -390,7 +396,7 @@ static int pvt_init(struct pvt_device *pvt)
if (ret)
return ret;
- val = GENMASK(pvt->c_num - 1, 0) | VM_CH_INIT |
+ val = GENMASK(pvt->vm_ch_max - 1, 0) | VM_CH_INIT |
IP_POLL << SDIF_ADDR_SFT |
SDIF_WRN_W | SDIF_PROG;
ret = regmap_write(v_map, SDIF_W, val);
@@ -519,7 +525,7 @@ static int pvt_reset_control_deassert(struct device *dev, struct pvt_device *pvt
static int mr75203_probe(struct platform_device *pdev)
{
const struct hwmon_channel_info **pvt_info;
- u32 ts_num, vm_num, pd_num, ch_num, val, index, i;
+ u32 ts_num, vm_num, pd_num, ch_num, val, index, i, j, k;
struct device *dev = &pdev->dev;
u32 *temp_config, *in_config;
struct device *hwmon_dev;
@@ -569,7 +575,6 @@ static int mr75203_probe(struct platform_device *pdev)
pvt->t_num = ts_num;
pvt->p_num = pd_num;
pvt->v_num = vm_num;
- pvt->c_num = ch_num;
val = 0;
if (ts_num)
val++;
@@ -606,43 +611,86 @@ static int mr75203_probe(struct platform_device *pdev)
}
if (vm_num) {
- u32 total_ch = ch_num * vm_num;
+ u8 vm_idx[vm_num];
+ u8 vm_active_ch[vm_num];
ret = pvt_get_regmap(pdev, "vm", pvt);
if (ret)
return ret;
- pvt->vm_idx = devm_kcalloc(dev, vm_num, sizeof(*pvt->vm_idx),
- GFP_KERNEL);
- if (!pvt->vm_idx)
- return -ENOMEM;
-
- ret = device_property_read_u8_array(dev, "intel,vm-map",
- pvt->vm_idx, vm_num);
+ ret = device_property_read_u8_array(dev, "intel,vm-map", vm_idx,
+ vm_num);
if (ret) {
/*
* Incase intel,vm-map property is not defined, we
* assume incremental channel numbers.
*/
for (i = 0; i < vm_num; i++)
- pvt->vm_idx[i] = i;
+ vm_idx[i] = i;
} else {
for (i = 0; i < vm_num; i++)
- if (pvt->vm_idx[i] >= vm_num ||
- pvt->vm_idx[i] == 0xff)
+ if (vm_idx[i] >= vm_num || vm_idx[i] == 0xff)
break;
vm_num = i;
pvt->v_num = i;
}
- in_config = devm_kcalloc(dev, total_ch + 1,
+ ret = device_property_read_u8_array(dev, "vm-active-channels",
+ vm_active_ch, vm_num);
+ if (ret) {
+ /*
+ * Incase vm-active-channels property is not defined,
+ * we assume each VM sensor has all of its channels
+ * active.
+ */
+ for (i = 0; i < vm_num; i++)
+ vm_active_ch[i] = ch_num;
+
+ pvt->vm_ch_max = ch_num;
+ pvt->vm_ch_total = ch_num * vm_num;
+ } else {
+ for (i = 0; i < vm_num; i++) {
+ if (vm_active_ch[i] > ch_num) {
+ dev_err(dev,
+ "invalid active channels: %u\n",
+ vm_active_ch[i]);
+ return -EINVAL;
+ }
+
+ pvt->vm_ch_total += vm_active_ch[i];
+
+ if (vm_active_ch[i] > pvt->vm_ch_max)
+ pvt->vm_ch_max = vm_active_ch[i];
+ }
+ }
+
+ /*
+ * Map between the channel-number to VM-index and channel-index.
+ * Example - 3 VMs, vm_active_ch = [05 02 04]:
+ * vm_map = [0 0 0 0 0 1 1 2 2 2 2]
+ * ch_map = [0 1 2 3 4 0 1 0 1 2 3]
+ */
+ pvt->vd = devm_kcalloc(dev, pvt->vm_ch_total, sizeof(*pvt->vd),
+ GFP_KERNEL);
+ if (!pvt->vd)
+ return -ENOMEM;
+
+ k = 0;
+ for (i = 0; i < vm_num; i++)
+ for (j = 0; j < vm_active_ch[i]; j++) {
+ pvt->vd[k].vm_map = vm_idx[i];
+ pvt->vd[k].ch_map = j;
+ k++;
+ }
+
+ in_config = devm_kcalloc(dev, pvt->vm_ch_total + 1,
sizeof(*in_config), GFP_KERNEL);
if (!in_config)
return -ENOMEM;
- memset32(in_config, HWMON_I_INPUT, total_ch);
- in_config[total_ch] = 0;
+ memset32(in_config, HWMON_I_INPUT, pvt->vm_ch_total);
+ in_config[pvt->vm_ch_total] = 0;
pvt_in.config = in_config;
pvt_info[index++] = &pvt_in;
--
2.37.1
Fix: "ERROR: space required before the open parenthesis '('"
Signed-off-by: Eliav Farber <[email protected]>
---
drivers/hwmon/mr75203.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index 79831a0d5dca..2777feca1c11 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -172,7 +172,7 @@ static int pvt_read_temp(struct device *dev, u32 attr, int channel, long *val)
return ret;
ret = regmap_read(t_map, SDIF_DATA(channel), &nbs);
- if(ret < 0)
+ if (ret < 0)
return ret;
nbs &= SAMPLE_DATA_MSK;
@@ -217,7 +217,7 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
return ret;
ret = regmap_read(v_map, VM_SDIF_DATA(vm_idx, ch_idx), &n);
- if(ret < 0)
+ if (ret < 0)
return ret;
n &= SAMPLE_DATA_MSK;
@@ -320,19 +320,19 @@ static int pvt_init(struct pvt_device *pvt)
if (t_num) {
ret = regmap_write(t_map, SDIF_SMPL_CTRL, 0x0);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_write(t_map, SDIF_HALT, 0x0);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_write(t_map, CLK_SYNTH, clk_synth);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_write(t_map, SDIF_DISABLE, 0x0);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_read_poll_timeout(t_map, SDIF_STAT,
@@ -345,7 +345,7 @@ static int pvt_init(struct pvt_device *pvt)
val = CFG0_MODE_2 | CFG0_PARALLEL_OUT | CFG0_12_BIT |
IP_CFG << SDIF_ADDR_SFT | SDIF_WRN_W | SDIF_PROG;
ret = regmap_write(t_map, SDIF_W, val);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_read_poll_timeout(t_map, SDIF_STAT,
@@ -358,7 +358,7 @@ static int pvt_init(struct pvt_device *pvt)
val = POWER_DELAY_CYCLE_256 | IP_TMR << SDIF_ADDR_SFT |
SDIF_WRN_W | SDIF_PROG;
ret = regmap_write(t_map, SDIF_W, val);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_read_poll_timeout(t_map, SDIF_STAT,
@@ -372,39 +372,39 @@ static int pvt_init(struct pvt_device *pvt)
IP_CTRL << SDIF_ADDR_SFT |
SDIF_WRN_W | SDIF_PROG;
ret = regmap_write(t_map, SDIF_W, val);
- if(ret < 0)
+ if (ret < 0)
return ret;
}
if (p_num) {
ret = regmap_write(p_map, SDIF_HALT, 0x0);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_write(p_map, SDIF_DISABLE, BIT(p_num) - 1);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_write(p_map, CLK_SYNTH, clk_synth);
- if(ret < 0)
+ if (ret < 0)
return ret;
}
if (v_num) {
ret = regmap_write(v_map, SDIF_SMPL_CTRL, 0x0);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_write(v_map, SDIF_HALT, 0x0);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_write(v_map, CLK_SYNTH, clk_synth);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_write(v_map, SDIF_DISABLE, 0x0);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
@@ -432,7 +432,7 @@ static int pvt_init(struct pvt_device *pvt)
CFG1_14_BIT | IP_CFG << SDIF_ADDR_SFT |
SDIF_WRN_W | SDIF_PROG;
ret = regmap_write(v_map, SDIF_W, val);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
@@ -445,7 +445,7 @@ static int pvt_init(struct pvt_device *pvt)
val = POWER_DELAY_CYCLE_64 | IP_TMR << SDIF_ADDR_SFT |
SDIF_WRN_W | SDIF_PROG;
ret = regmap_write(v_map, SDIF_W, val);
- if(ret < 0)
+ if (ret < 0)
return ret;
ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
@@ -459,7 +459,7 @@ static int pvt_init(struct pvt_device *pvt)
IP_CTRL << SDIF_ADDR_SFT |
SDIF_WRN_W | SDIF_PROG;
ret = regmap_write(v_map, SDIF_W, val);
- if(ret < 0)
+ if (ret < 0)
return ret;
}
@@ -584,7 +584,7 @@ static int mr75203_probe(struct platform_device *pdev)
}
ret = regmap_read(pvt->c_map, PVT_IP_CONFIG, &val);
- if(ret < 0)
+ if (ret < 0)
return ret;
ts_num = (val & TS_NUM_MSK) >> TS_NUM_SFT;
--
2.37.1
Adding a "reset-control-skip" bool property to the mr75203 node will
avoid looking up and obtaining a reference to a reset controller.
Signed-off-by: Eliav Farber <[email protected]>
---
drivers/hwmon/mr75203.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index f89f7bb5d698..bec63b611eb4 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
@@ -525,14 +526,19 @@ static int mr75203_probe(struct platform_device *pdev)
return ret;
}
- pvt->rst = devm_reset_control_get_exclusive(dev, NULL);
- if (IS_ERR(pvt->rst))
- return dev_err_probe(dev, PTR_ERR(pvt->rst),
- "failed to get reset control\n");
+ if (of_property_read_bool(dev->of_node, "reset-control-skip")) {
+ dev_info(dev, "skipping reset-control\n");
+ } else {
+ pvt->rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (IS_ERR(pvt->rst))
+ return dev_err_probe(dev, PTR_ERR(pvt->rst),
+ "failed to get reset control\n");
- ret = pvt_reset_control_deassert(dev, pvt);
- if (ret)
- return dev_err_probe(dev, ret, "cannot deassert reset control\n");
+ ret = pvt_reset_control_deassert(dev, pvt);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "cannot deassert reset control\n");
+ }
ret = regmap_read(pvt->c_map, PVT_IP_CONFIG, &val);
if(ret < 0)
--
2.37.1
This change adds debugfs to read and write TS coefficients - g, h, j and
cal5.
The coefficients can vary between product and product, so to calibrate
them it can be very useful to to be able to modify them on the fly.
e.g.
cat /sys/kernel/debug/940f23d0000.pvt/ts_coeff_cal5
4096
echo 83000 > sys/kernel/debug/940f23d0000.pvt/ts_coeff_g
Signed-off-by: Eliav Farber <[email protected]>
---
drivers/hwmon/mr75203.c | 196 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 196 insertions(+)
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index 2777feca1c11..04a702830987 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -9,6 +9,7 @@
*/
#include <linux/bits.h>
#include <linux/clk.h>
+#include <linux/debugfs.h>
#include <linux/hwmon.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
@@ -125,6 +126,7 @@ struct pvt_device {
struct clk *clk;
struct reset_control *rst;
struct voltage_device *vd;
+ struct dentry *dbgfs_dir;
u32 t_num;
u32 p_num;
u32 v_num;
@@ -137,6 +139,198 @@ struct pvt_device {
u8 vm_ch_total;
};
+static ssize_t pvt_ts_coeff_h_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct pvt_device *pvt = file->private_data;
+ char buf[16];
+ unsigned int len;
+
+ len = sprintf(buf, "%u\n", pvt->ts_coeff_h);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t pvt_ts_coeff_h_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct pvt_device *pvt = file->private_data;
+ int ret;
+ u32 coeff;
+
+ ret = kstrtou32_from_user(user_buf, count, 0, &coeff);
+ if (ret)
+ return ret;
+
+ pvt->ts_coeff_h = coeff;
+
+ return count;
+}
+
+static const struct file_operations pvt_ts_coeff_h_fops = {
+ .read = pvt_ts_coeff_h_read,
+ .write = pvt_ts_coeff_h_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t pvt_ts_coeff_g_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct pvt_device *pvt = file->private_data;
+ char buf[16];
+ unsigned int len;
+
+ len = sprintf(buf, "%u\n", pvt->ts_coeff_g);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t pvt_ts_coeff_g_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct pvt_device *pvt = file->private_data;
+ int ret;
+ u32 coeff;
+
+ ret = kstrtou32_from_user(user_buf, count, 0, &coeff);
+ if (ret)
+ return ret;
+
+ pvt->ts_coeff_g = coeff;
+
+ return count;
+}
+
+static const struct file_operations pvt_ts_coeff_g_fops = {
+ .read = pvt_ts_coeff_g_read,
+ .write = pvt_ts_coeff_g_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t pvt_ts_coeff_j_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct pvt_device *pvt = file->private_data;
+ char buf[16];
+ unsigned int len;
+
+ len = sprintf(buf, "%d\n", pvt->ts_coeff_j);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t pvt_ts_coeff_j_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct pvt_device *pvt = file->private_data;
+ int ret;
+ s32 coeff;
+
+ ret = kstrtos32_from_user(user_buf, count, 0, &coeff);
+ if (ret)
+ return ret;
+
+ pvt->ts_coeff_j = coeff;
+
+ return count;
+}
+
+static const struct file_operations pvt_ts_coeff_j_fops = {
+ .read = pvt_ts_coeff_j_read,
+ .write = pvt_ts_coeff_j_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static ssize_t pvt_ts_coeff_cal5_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct pvt_device *pvt = file->private_data;
+ char buf[16];
+ unsigned int len;
+
+ len = sprintf(buf, "%u\n", pvt->ts_coeff_cal5);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t pvt_ts_coeff_cal5_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct pvt_device *pvt = file->private_data;
+ int ret;
+ u32 coeff;
+
+ ret = kstrtou32_from_user(user_buf, count, 0, &coeff);
+ if (ret)
+ return ret;
+
+ if (coeff == 0)
+ return -EINVAL;
+
+ pvt->ts_coeff_cal5 = coeff;
+
+ return count;
+}
+
+static const struct file_operations pvt_ts_coeff_cal5_fops = {
+ .read = pvt_ts_coeff_cal5_read,
+ .write = pvt_ts_coeff_cal5_write,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+static void devm_pvt_ts_dbgfs_remove(void *data)
+{
+ struct pvt_device *pvt = (struct pvt_device *)data;
+
+ debugfs_remove_recursive(pvt->dbgfs_dir);
+ pvt->dbgfs_dir = NULL;
+}
+
+static int pvt_ts_dbgfs_create(struct pvt_device *pvt, struct device *dev)
+{
+ int ret;
+
+ pvt->dbgfs_dir = debugfs_create_dir(dev_name(dev), NULL);
+ if (!pvt->dbgfs_dir) {
+ dev_err(dev, "Failed to create dbgfs_dir\n");
+ return -EINVAL;
+ }
+
+ debugfs_create_file("ts_coeff_h", 0644, pvt->dbgfs_dir, pvt,
+ &pvt_ts_coeff_h_fops);
+ debugfs_create_file("ts_coeff_g", 0644, pvt->dbgfs_dir, pvt,
+ &pvt_ts_coeff_g_fops);
+ debugfs_create_file("ts_coeff_j", 0644, pvt->dbgfs_dir, pvt,
+ &pvt_ts_coeff_j_fops);
+ debugfs_create_file("ts_coeff_cal5", 0644, pvt->dbgfs_dir, pvt,
+ &pvt_ts_coeff_cal5_fops);
+
+ ret = devm_add_action_or_reset(dev, devm_pvt_ts_dbgfs_remove, pvt);
+ if (ret) {
+ dev_err(dev, "failed to add action to remove pvt dbgfs (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static umode_t pvt_is_visible(const void *data, enum hwmon_sensor_types type,
u32 attr, int channel)
{
@@ -653,6 +847,8 @@ static int mr75203_probe(struct platform_device *pdev)
dev_dbg(dev, "ts-coeff: h = %u, g = %u, j = %d, cal5 = %u\n",
pvt->ts_coeff_h, pvt->ts_coeff_g, pvt->ts_coeff_j,
pvt->ts_coeff_cal5);
+
+ pvt_ts_dbgfs_create(pvt, dev);
}
if (pd_num) {
--
2.37.1
Add optional "vm-active-channels" property to define the number of
active channels per VM.
Signed-off-by: Eliav Farber <[email protected]>
---
.../devicetree/bindings/hwmon/moortec,mr75203.yaml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml b/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
index da9c3cdcb6f0..6111b5069b3c 100644
--- a/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
+++ b/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
@@ -49,6 +49,13 @@ properties:
reset-control-skip bool property defines if obtaining a
reference to a reset controller should be skipped.
+ vm-active-channels:
+ description:
+ vm-active-channels defines the number of channels per VM
+ that are actually used and are connected to some source.
+ A value of 0 means that the entire VM sensor is nou used.
+ $ref: /schemas/types.yaml#definitions/uint8-array
+
required:
- compatible
- reg
@@ -60,6 +67,7 @@ required:
additionalProperties:
- intel,vm-map
- reset-control-skip
+ - vm-active-channels
examples:
- |
@@ -73,5 +81,6 @@ examples:
intel,vm-map = [03 01 04 ff ff];
clocks = <&osc0>;
resets = <&rcu0 0x40 7>;
+ vm-active-channels = [08 10 02];
#thermal-sensor-cells = <1>;
};
--
2.37.1
Adding a "reset-control-skip" bool property to the mr75203 node will
avoid looking up and obtaining a reference to a reset controller.
Signed-off-by: Eliav Farber <[email protected]>
---
.../devicetree/bindings/hwmon/moortec,mr75203.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml b/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
index f9e849cc73e0..da9c3cdcb6f0 100644
--- a/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
+++ b/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
@@ -44,6 +44,11 @@ properties:
"#thermal-sensor-cells":
const: 1
+ reset-control-skip:
+ description:
+ reset-control-skip bool property defines if obtaining a
+ reference to a reset controller should be skipped.
+
required:
- compatible
- reg
@@ -54,6 +59,7 @@ required:
additionalProperties:
- intel,vm-map
+ - reset-control-skip
examples:
- |
--
2.37.1
Use thermal coefficients from the device tree if they exist.
Otherwise, use default values.
The equation used in the driver is:
T = G + H * (n / cal5 - 0.5) + J * F
With this change we can support also Mode 1 Conversion, which
uses A instead of G, and B instead of H.
We can also support the series 6 equation that has different
coefficients and has a slightly different format:
T = G + H * (n / cal5 - 0.5)
by setting J to 0.
Signed-off-by: Eliav Farber <[email protected]>
---
drivers/hwmon/mr75203.c | 44 +++++++++++++++++++++++++++++++++++++----
1 file changed, 40 insertions(+), 4 deletions(-)
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index 59e2dc8fa333..79831a0d5dca 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -129,6 +129,10 @@ struct pvt_device {
u32 p_num;
u32 v_num;
u32 ip_freq;
+ u32 ts_coeff_h;
+ u32 ts_coeff_g;
+ s32 ts_coeff_j;
+ u32 ts_coeff_cal5;
u8 vm_ch_max;
u8 vm_ch_total;
};
@@ -177,10 +181,10 @@ static int pvt_read_temp(struct device *dev, u32 attr, int channel, long *val)
* Convert the register value to degrees centigrade temperature:
* T = G + H * (n / cal5 - 0.5) + J * F
*/
- *val = PVT_G_CONST;
- *val += PVT_H_CONST * nbs / PVT_CAL5_CONST;
- *val -= PVT_H_CONST / 2;
- *val += PVT_J_CONST * pvt->ip_freq / HZ_PER_MHZ;
+ *val = pvt->ts_coeff_g;
+ *val += pvt->ts_coeff_h * nbs / pvt->ts_coeff_cal5;
+ *val -= pvt->ts_coeff_h / 2;
+ *val += pvt->ts_coeff_j * pvt->ip_freq / HZ_PER_MHZ;
return 0;
default:
@@ -617,6 +621,38 @@ static int mr75203_probe(struct platform_device *pdev)
memset32(temp_config, HWMON_T_INPUT, ts_num);
pvt_temp.config = temp_config;
pvt_info[index++] = &pvt_temp;
+
+ /*
+ * Incase ts-coeff-h/g/j/cal5 property is not defined, use
+ * default value.
+ */
+ ret = of_property_read_u32(np, "ts-coeff-h", &pvt->ts_coeff_h);
+ if (ret)
+ pvt->ts_coeff_h = PVT_H_CONST;
+
+ ret = of_property_read_u32(np, "ts-coeff-g", &pvt->ts_coeff_g);
+ if (ret)
+ pvt->ts_coeff_g = PVT_G_CONST;
+
+ ret = of_property_read_s32(np, "ts-coeff-j", &pvt->ts_coeff_j);
+ if (ret)
+ pvt->ts_coeff_j = PVT_J_CONST;
+
+ ret = of_property_read_u32(np, "ts-coeff-cal5",
+ &pvt->ts_coeff_cal5);
+ if (ret) {
+ pvt->ts_coeff_cal5 = PVT_CAL5_CONST;
+ } else {
+ if (pvt->ts_coeff_cal5 == 0) {
+ dev_err(dev, "invalid ts-coeff-cal5 (%u)\n",
+ pvt->ts_coeff_cal5);
+ return -EINVAL;
+ }
+ }
+
+ dev_dbg(dev, "ts-coeff: h = %u, g = %u, j = %d, cal5 = %u\n",
+ pvt->ts_coeff_h, pvt->ts_coeff_g, pvt->ts_coeff_j,
+ pvt->ts_coeff_cal5);
}
if (pd_num) {
--
2.37.1
Fix a bug that in case "intel,vm-map" is missing 'num' is set to 0,
and no voltage channel infos are allocated.
Signed-off-by: Eliav Farber <[email protected]>
---
drivers/hwmon/mr75203.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index 046523d47c29..0e29877a1a9c 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -580,8 +580,6 @@ static int mr75203_probe(struct platform_device *pdev)
}
if (vm_num) {
- u32 num = vm_num;
-
ret = pvt_get_regmap(pdev, "vm", pvt);
if (ret)
return ret;
@@ -594,30 +592,28 @@ static int mr75203_probe(struct platform_device *pdev)
ret = device_property_read_u8_array(dev, "intel,vm-map",
pvt->vm_idx, vm_num);
if (ret) {
- num = 0;
+ /*
+ * Incase intel,vm-map property is not defined, we
+ * assume incremental channel numbers.
+ */
+ for (i = 0; i < vm_num; i++)
+ pvt->vm_idx[i] = i;
} else {
for (i = 0; i < vm_num; i++)
if (pvt->vm_idx[i] >= vm_num ||
- pvt->vm_idx[i] == 0xff) {
- num = i;
+ pvt->vm_idx[i] == 0xff)
break;
- }
- }
- /*
- * Incase intel,vm-map property is not defined, we assume
- * incremental channel numbers.
- */
- for (i = num; i < vm_num; i++)
- pvt->vm_idx[i] = i;
+ vm_num = i;
+ }
- in_config = devm_kcalloc(dev, num + 1,
+ in_config = devm_kcalloc(dev, vm_num + 1,
sizeof(*in_config), GFP_KERNEL);
if (!in_config)
return -ENOMEM;
- memset32(in_config, HWMON_I_INPUT, num);
- in_config[num] = 0;
+ memset32(in_config, HWMON_I_INPUT, vm_num);
+ in_config[vm_num] = 0;
pvt_in.config = in_config;
pvt_info[index++] = &pvt_in;
--
2.37.1
Add pre-scalar support to normalzie the voltage output results for
channels the use pre-scalar units to get the measurement to be within
the range that the sensor supports.
The pre-scalar value is used if it exists in device-tree, otherwise
default value of 1 is used.
Signed-off-by: Eliav Farber <[email protected]>
---
drivers/hwmon/mr75203.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index 9b45fd089fcf..417b135c1b3f 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -110,8 +110,12 @@
struct voltage_device {
u8 vm_map;
u8 ch_map;
+ u32 pre_scaler;
};
+#define PRE_SCALR_PROPERTY_NAME 32
+#define PRE_SCALR_DEFAULT_VAL 1
+
struct pvt_device {
struct regmap *c_map;
struct regmap *t_map;
@@ -213,7 +217,9 @@ static int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
n &= SAMPLE_DATA_MSK;
/* Convert the N bitstream count into voltage */
- *val = (PVT_N_CONST * n - PVT_R_CONST) >> PVT_CONV_BITS;
+ *val = pvt->vd[channel].pre_scaler;
+ *val *= (PVT_N_CONST * n - PVT_R_CONST);
+ *val >>= PVT_CONV_BITS;
return 0;
default:
@@ -525,6 +531,7 @@ static int pvt_reset_control_deassert(struct device *dev, struct pvt_device *pvt
static int mr75203_probe(struct platform_device *pdev)
{
const struct hwmon_channel_info **pvt_info;
+ const struct device_node *np = pdev->dev.of_node;
u32 ts_num, vm_num, pd_num, ch_num, val, index, i, j, k;
struct device *dev = &pdev->dev;
u32 *temp_config, *in_config;
@@ -550,7 +557,7 @@ static int mr75203_probe(struct platform_device *pdev)
return ret;
}
- if (of_property_read_bool(dev->of_node, "reset-control-skip")) {
+ if (of_property_read_bool(np, "reset-control-skip")) {
dev_info(dev, "skipping reset-control\n");
} else {
pvt->rst = devm_reset_control_get_exclusive(dev, NULL);
@@ -613,6 +620,8 @@ static int mr75203_probe(struct platform_device *pdev)
if (vm_num) {
u8 vm_idx[vm_num];
u8 vm_active_ch[vm_num];
+ char prop_name[PRE_SCALR_PROPERTY_NAME] = {0};
+ u32 pre_scaler;
ret = pvt_get_regmap(pdev, "vm", pvt);
if (ret)
@@ -684,6 +693,21 @@ static int mr75203_probe(struct platform_device *pdev)
k++;
}
+ /*
+ * Incase vm-pre-scalar-ch# property is not defined, we assume
+ * default pre-scaler of 1.
+ */
+ for (i = 0; i < pvt->vm_ch_total; i++) {
+ snprintf(prop_name, sizeof(prop_name),
+ "vm-pre-scalar-ch%u", i);
+
+ ret = of_property_read_u32(np, prop_name, &pre_scaler);
+ if (ret)
+ pvt->vd[i].pre_scaler = PRE_SCALR_DEFAULT_VAL;
+ else
+ pvt->vd[i].pre_scaler = pre_scaler;
+ }
+
in_config = devm_kcalloc(dev, pvt->vm_ch_total + 1,
sizeof(*in_config), GFP_KERNEL);
if (!in_config)
--
2.37.1
The "intel,vm-map property" is optional and not required.
Signed-off-by: Eliav Farber <[email protected]>
---
Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml b/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
index 6f3e3c01f717..f9e849cc73e0 100644
--- a/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
+++ b/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
@@ -48,12 +48,12 @@ required:
- compatible
- reg
- reg-names
- - intel,vm-map
- clocks
- resets
- "#thermal-sensor-cells"
-additionalProperties: false
+additionalProperties:
+ - intel,vm-map
examples:
- |
--
2.37.1
Hi Eliav,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on groeck-staging/hwmon-next]
[also build test WARNING on linus/master v6.0-rc1 next-20220816]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Eliav-Farber/Variety-of-fixes-and-new-features-for-mr75203-driver/20220816-183655
base: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
config: powerpc-randconfig-r024-20220815 (https://download.01.org/0day-ci/archive/20220817/[email protected]/config)
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project aed5e3bea138ce581d682158eb61c27b3cfdd6ec)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install powerpc cross compiling tool for clang build
# apt-get install binutils-powerpc-linux-gnu
# https://github.com/intel-lab-lkp/linux/commit/75e49737eb6188733096da72eb4692cfed872101
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Eliav-Farber/Variety-of-fixes-and-new-features-for-mr75203-driver/20220816-183655
git checkout 75e49737eb6188733096da72eb4692cfed872101
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=powerpc SHELL=/bin/bash drivers/hwmon/
If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>
All warnings (new ones prefixed by >>):
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:640:
arch/powerpc/include/asm/io-defs.h:43:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:637:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:178:1: note: expanded from here
__do_insb
^
arch/powerpc/include/asm/io.h:577:56: note: expanded from macro '__do_insb'
#define __do_insb(p, b, n) readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/hwmon/mr75203.c:19:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:640:
arch/powerpc/include/asm/io-defs.h:45:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:637:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:180:1: note: expanded from here
__do_insw
^
arch/powerpc/include/asm/io.h:578:56: note: expanded from macro '__do_insw'
#define __do_insw(p, b, n) readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/hwmon/mr75203.c:19:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:640:
arch/powerpc/include/asm/io-defs.h:47:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:637:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:182:1: note: expanded from here
__do_insl
^
arch/powerpc/include/asm/io.h:579:56: note: expanded from macro '__do_insl'
#define __do_insl(p, b, n) readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/hwmon/mr75203.c:19:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:640:
arch/powerpc/include/asm/io-defs.h:49:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:637:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:184:1: note: expanded from here
__do_outsb
^
arch/powerpc/include/asm/io.h:580:58: note: expanded from macro '__do_outsb'
#define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/hwmon/mr75203.c:19:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:640:
arch/powerpc/include/asm/io-defs.h:51:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:637:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:186:1: note: expanded from here
__do_outsw
^
arch/powerpc/include/asm/io.h:581:58: note: expanded from macro '__do_outsw'
#define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
~~~~~~~~~~~~~~~~~~~~~^
In file included from drivers/hwmon/mr75203.c:19:
In file included from include/linux/regmap.h:20:
In file included from include/linux/iopoll.h:14:
In file included from include/linux/io.h:13:
In file included from arch/powerpc/include/asm/io.h:640:
arch/powerpc/include/asm/io-defs.h:53:1: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/include/asm/io.h:637:3: note: expanded from macro 'DEF_PCI_AC_NORET'
__do_##name al; \
^~~~~~~~~~~~~~
<scratch space>:188:1: note: expanded from here
__do_outsl
^
arch/powerpc/include/asm/io.h:582:58: note: expanded from macro '__do_outsl'
#define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
~~~~~~~~~~~~~~~~~~~~~^
>> drivers/hwmon/mr75203.c:604:13: warning: variable length array used [-Wvla]
u8 vm_idx[vm_num];
^~~~~~
drivers/hwmon/mr75203.c:605:19: warning: variable length array used [-Wvla]
u8 vm_active_ch[vm_num];
^~~~~~
8 warnings generated.
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for HOTPLUG_CPU
Depends on [n]: SMP [=y] && (PPC_PSERIES [=n] || PPC_PMAC [=n] || PPC_POWERNV [=n] || FSL_SOC_BOOKE [=n])
Selected by [y]:
- PM_SLEEP_SMP [=y] && SMP [=y] && (ARCH_SUSPEND_POSSIBLE [=y] || ARCH_HIBERNATION_POSSIBLE [=y]) && PM_SLEEP [=y]
vim +604 drivers/hwmon/mr75203.c
514
515 static int mr75203_probe(struct platform_device *pdev)
516 {
517 const struct hwmon_channel_info **pvt_info;
518 u32 ts_num, vm_num, pd_num, ch_num, val, index, i, j, k;
519 struct device *dev = &pdev->dev;
520 u32 *temp_config, *in_config;
521 struct device *hwmon_dev;
522 struct pvt_device *pvt;
523 int ret;
524
525 pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL);
526 if (!pvt)
527 return -ENOMEM;
528
529 ret = pvt_get_regmap(pdev, "common", pvt);
530 if (ret)
531 return ret;
532
533 pvt->clk = devm_clk_get(dev, NULL);
534 if (IS_ERR(pvt->clk))
535 return dev_err_probe(dev, PTR_ERR(pvt->clk), "failed to get clock\n");
536
537 ret = pvt_clk_enable(dev, pvt);
538 if (ret) {
539 dev_err(dev, "failed to enable clock\n");
540 return ret;
541 }
542
543 if (of_property_read_bool(dev->of_node, "reset-control-skip")) {
544 dev_info(dev, "skipping reset-control\n");
545 } else {
546 pvt->rst = devm_reset_control_get_exclusive(dev, NULL);
547 if (IS_ERR(pvt->rst))
548 return dev_err_probe(dev, PTR_ERR(pvt->rst),
549 "failed to get reset control\n");
550
551 ret = pvt_reset_control_deassert(dev, pvt);
552 if (ret)
553 return dev_err_probe(dev, ret,
554 "cannot deassert reset control\n");
555 }
556
557 ret = regmap_read(pvt->c_map, PVT_IP_CONFIG, &val);
558 if(ret < 0)
559 return ret;
560
561 ts_num = (val & TS_NUM_MSK) >> TS_NUM_SFT;
562 pd_num = (val & PD_NUM_MSK) >> PD_NUM_SFT;
563 vm_num = (val & VM_NUM_MSK) >> VM_NUM_SFT;
564 ch_num = (val & CH_NUM_MSK) >> CH_NUM_SFT;
565 pvt->t_num = ts_num;
566 pvt->p_num = pd_num;
567 pvt->v_num = vm_num;
568 val = 0;
569 if (ts_num)
570 val++;
571 if (vm_num)
572 val++;
573 if (!val)
574 return -ENODEV;
575
576 pvt_info = devm_kcalloc(dev, val + 2, sizeof(*pvt_info), GFP_KERNEL);
577 if (!pvt_info)
578 return -ENOMEM;
579 pvt_info[0] = HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ);
580 index = 1;
581
582 if (ts_num) {
583 ret = pvt_get_regmap(pdev, "ts", pvt);
584 if (ret)
585 return ret;
586
587 temp_config = devm_kcalloc(dev, ts_num + 1,
588 sizeof(*temp_config), GFP_KERNEL);
589 if (!temp_config)
590 return -ENOMEM;
591
592 memset32(temp_config, HWMON_T_INPUT, ts_num);
593 pvt_temp.config = temp_config;
594 pvt_info[index++] = &pvt_temp;
595 }
596
597 if (pd_num) {
598 ret = pvt_get_regmap(pdev, "pd", pvt);
599 if (ret)
600 return ret;
601 }
602
603 if (vm_num) {
> 604 u8 vm_idx[vm_num];
605 u8 vm_active_ch[vm_num];
606
607 ret = pvt_get_regmap(pdev, "vm", pvt);
608 if (ret)
609 return ret;
610
611 ret = device_property_read_u8_array(dev, "intel,vm-map", vm_idx,
612 vm_num);
613 if (ret) {
614 /*
615 * Incase intel,vm-map property is not defined, we
616 * assume incremental channel numbers.
617 */
618 for (i = 0; i < vm_num; i++)
619 vm_idx[i] = i;
620 } else {
621 for (i = 0; i < vm_num; i++)
622 if (vm_idx[i] >= vm_num || vm_idx[i] == 0xff)
623 break;
624
625 vm_num = i;
626 pvt->v_num = i;
627 }
628
629 ret = device_property_read_u8_array(dev, "vm-active-channels",
630 vm_active_ch, vm_num);
631 if (ret) {
632 /*
633 * Incase vm-active-channels property is not defined,
634 * we assume each VM sensor has all of its channels
635 * active.
636 */
637 for (i = 0; i < vm_num; i++)
638 vm_active_ch[i] = ch_num;
639
640 pvt->vm_ch_max = ch_num;
641 pvt->vm_ch_total = ch_num * vm_num;
642 } else {
643 for (i = 0; i < vm_num; i++) {
644 if (vm_active_ch[i] > ch_num) {
645 dev_err(dev,
646 "invalid active channels: %u\n",
647 vm_active_ch[i]);
648 return -EINVAL;
649 }
650
651 pvt->vm_ch_total += vm_active_ch[i];
652
653 if (vm_active_ch[i] > pvt->vm_ch_max)
654 pvt->vm_ch_max = vm_active_ch[i];
655 }
656 }
657
658 /*
659 * Map between the channel-number to VM-index and channel-index.
660 * Example - 3 VMs, vm_active_ch = [05 02 04]:
661 * vm_map = [0 0 0 0 0 1 1 2 2 2 2]
662 * ch_map = [0 1 2 3 4 0 1 0 1 2 3]
663 */
664 pvt->vd = devm_kcalloc(dev, pvt->vm_ch_total, sizeof(*pvt->vd),
665 GFP_KERNEL);
666 if (!pvt->vd)
667 return -ENOMEM;
668
669 k = 0;
670 for (i = 0; i < vm_num; i++)
671 for (j = 0; j < vm_active_ch[i]; j++) {
672 pvt->vd[k].vm_map = vm_idx[i];
673 pvt->vd[k].ch_map = j;
674 k++;
675 }
676
677 in_config = devm_kcalloc(dev, pvt->vm_ch_total + 1,
678 sizeof(*in_config), GFP_KERNEL);
679 if (!in_config)
680 return -ENOMEM;
681
682 memset32(in_config, HWMON_I_INPUT, pvt->vm_ch_total);
683 in_config[pvt->vm_ch_total] = 0;
684 pvt_in.config = in_config;
685
686 pvt_info[index++] = &pvt_in;
687 }
688
689 ret = pvt_init(pvt);
690 if (ret) {
691 dev_err(dev, "failed to init pvt: %d\n", ret);
692 return ret;
693 }
694
695 pvt_chip_info.info = pvt_info;
696 hwmon_dev = devm_hwmon_device_register_with_info(dev, "pvt",
697 pvt,
698 &pvt_chip_info,
699 NULL);
700
701 return PTR_ERR_OR_ZERO(hwmon_dev);
702 }
703
--
0-DAY CI Kernel Test Service
https://01.org/lkp
Hi Eliav,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on groeck-staging/hwmon-next]
[also build test WARNING on linus/master v6.0-rc1 next-20220816]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Eliav-Farber/Variety-of-fixes-and-new-features-for-mr75203-driver/20220816-183655
base: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
config: powerpc-randconfig-s031-20220816 (https://download.01.org/0day-ci/archive/20220817/[email protected]/config)
compiler: powerpc-linux-gcc (GCC) 12.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/75e49737eb6188733096da72eb4692cfed872101
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Eliav-Farber/Variety-of-fixes-and-new-features-for-mr75203-driver/20220816-183655
git checkout 75e49737eb6188733096da72eb4692cfed872101
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=powerpc SHELL=/bin/bash drivers/hwmon/
If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>
sparse warnings: (new ones prefixed by >>)
>> drivers/hwmon/mr75203.c:604:27: sparse: sparse: Variable length array is used.
drivers/hwmon/mr75203.c:605:33: sparse: sparse: Variable length array is used.
vim +604 drivers/hwmon/mr75203.c
514
515 static int mr75203_probe(struct platform_device *pdev)
516 {
517 const struct hwmon_channel_info **pvt_info;
518 u32 ts_num, vm_num, pd_num, ch_num, val, index, i, j, k;
519 struct device *dev = &pdev->dev;
520 u32 *temp_config, *in_config;
521 struct device *hwmon_dev;
522 struct pvt_device *pvt;
523 int ret;
524
525 pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL);
526 if (!pvt)
527 return -ENOMEM;
528
529 ret = pvt_get_regmap(pdev, "common", pvt);
530 if (ret)
531 return ret;
532
533 pvt->clk = devm_clk_get(dev, NULL);
534 if (IS_ERR(pvt->clk))
535 return dev_err_probe(dev, PTR_ERR(pvt->clk), "failed to get clock\n");
536
537 ret = pvt_clk_enable(dev, pvt);
538 if (ret) {
539 dev_err(dev, "failed to enable clock\n");
540 return ret;
541 }
542
543 if (of_property_read_bool(dev->of_node, "reset-control-skip")) {
544 dev_info(dev, "skipping reset-control\n");
545 } else {
546 pvt->rst = devm_reset_control_get_exclusive(dev, NULL);
547 if (IS_ERR(pvt->rst))
548 return dev_err_probe(dev, PTR_ERR(pvt->rst),
549 "failed to get reset control\n");
550
551 ret = pvt_reset_control_deassert(dev, pvt);
552 if (ret)
553 return dev_err_probe(dev, ret,
554 "cannot deassert reset control\n");
555 }
556
557 ret = regmap_read(pvt->c_map, PVT_IP_CONFIG, &val);
558 if(ret < 0)
559 return ret;
560
561 ts_num = (val & TS_NUM_MSK) >> TS_NUM_SFT;
562 pd_num = (val & PD_NUM_MSK) >> PD_NUM_SFT;
563 vm_num = (val & VM_NUM_MSK) >> VM_NUM_SFT;
564 ch_num = (val & CH_NUM_MSK) >> CH_NUM_SFT;
565 pvt->t_num = ts_num;
566 pvt->p_num = pd_num;
567 pvt->v_num = vm_num;
568 val = 0;
569 if (ts_num)
570 val++;
571 if (vm_num)
572 val++;
573 if (!val)
574 return -ENODEV;
575
576 pvt_info = devm_kcalloc(dev, val + 2, sizeof(*pvt_info), GFP_KERNEL);
577 if (!pvt_info)
578 return -ENOMEM;
579 pvt_info[0] = HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ);
580 index = 1;
581
582 if (ts_num) {
583 ret = pvt_get_regmap(pdev, "ts", pvt);
584 if (ret)
585 return ret;
586
587 temp_config = devm_kcalloc(dev, ts_num + 1,
588 sizeof(*temp_config), GFP_KERNEL);
589 if (!temp_config)
590 return -ENOMEM;
591
592 memset32(temp_config, HWMON_T_INPUT, ts_num);
593 pvt_temp.config = temp_config;
594 pvt_info[index++] = &pvt_temp;
595 }
596
597 if (pd_num) {
598 ret = pvt_get_regmap(pdev, "pd", pvt);
599 if (ret)
600 return ret;
601 }
602
603 if (vm_num) {
> 604 u8 vm_idx[vm_num];
605 u8 vm_active_ch[vm_num];
606
607 ret = pvt_get_regmap(pdev, "vm", pvt);
608 if (ret)
609 return ret;
610
611 ret = device_property_read_u8_array(dev, "intel,vm-map", vm_idx,
612 vm_num);
613 if (ret) {
614 /*
615 * Incase intel,vm-map property is not defined, we
616 * assume incremental channel numbers.
617 */
618 for (i = 0; i < vm_num; i++)
619 vm_idx[i] = i;
620 } else {
621 for (i = 0; i < vm_num; i++)
622 if (vm_idx[i] >= vm_num || vm_idx[i] == 0xff)
623 break;
624
625 vm_num = i;
626 pvt->v_num = i;
627 }
628
629 ret = device_property_read_u8_array(dev, "vm-active-channels",
630 vm_active_ch, vm_num);
631 if (ret) {
632 /*
633 * Incase vm-active-channels property is not defined,
634 * we assume each VM sensor has all of its channels
635 * active.
636 */
637 for (i = 0; i < vm_num; i++)
638 vm_active_ch[i] = ch_num;
639
640 pvt->vm_ch_max = ch_num;
641 pvt->vm_ch_total = ch_num * vm_num;
642 } else {
643 for (i = 0; i < vm_num; i++) {
644 if (vm_active_ch[i] > ch_num) {
645 dev_err(dev,
646 "invalid active channels: %u\n",
647 vm_active_ch[i]);
648 return -EINVAL;
649 }
650
651 pvt->vm_ch_total += vm_active_ch[i];
652
653 if (vm_active_ch[i] > pvt->vm_ch_max)
654 pvt->vm_ch_max = vm_active_ch[i];
655 }
656 }
657
658 /*
659 * Map between the channel-number to VM-index and channel-index.
660 * Example - 3 VMs, vm_active_ch = [05 02 04]:
661 * vm_map = [0 0 0 0 0 1 1 2 2 2 2]
662 * ch_map = [0 1 2 3 4 0 1 0 1 2 3]
663 */
664 pvt->vd = devm_kcalloc(dev, pvt->vm_ch_total, sizeof(*pvt->vd),
665 GFP_KERNEL);
666 if (!pvt->vd)
667 return -ENOMEM;
668
669 k = 0;
670 for (i = 0; i < vm_num; i++)
671 for (j = 0; j < vm_active_ch[i]; j++) {
672 pvt->vd[k].vm_map = vm_idx[i];
673 pvt->vd[k].ch_map = j;
674 k++;
675 }
676
677 in_config = devm_kcalloc(dev, pvt->vm_ch_total + 1,
678 sizeof(*in_config), GFP_KERNEL);
679 if (!in_config)
680 return -ENOMEM;
681
682 memset32(in_config, HWMON_I_INPUT, pvt->vm_ch_total);
683 in_config[pvt->vm_ch_total] = 0;
684 pvt_in.config = in_config;
685
686 pvt_info[index++] = &pvt_in;
687 }
688
689 ret = pvt_init(pvt);
690 if (ret) {
691 dev_err(dev, "failed to init pvt: %d\n", ret);
692 return ret;
693 }
694
695 pvt_chip_info.info = pvt_info;
696 hwmon_dev = devm_hwmon_device_register_with_info(dev, "pvt",
697 pvt,
698 &pvt_chip_info,
699 NULL);
700
701 return PTR_ERR_OR_ZERO(hwmon_dev);
702 }
703
--
0-DAY CI Kernel Test Service
https://01.org/lkp
Hi Eliav,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on groeck-staging/hwmon-next]
[also build test WARNING on linus/master v6.0-rc1 next-20220816]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Eliav-Farber/Variety-of-fixes-and-new-features-for-mr75203-driver/20220816-183655
base: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git hwmon-next
config: microblaze-randconfig-r013-20220815 (https://download.01.org/0day-ci/archive/20220817/[email protected]/config)
compiler: microblaze-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/75e49737eb6188733096da72eb4692cfed872101
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Eliav-Farber/Variety-of-fixes-and-new-features-for-mr75203-driver/20220816-183655
git checkout 75e49737eb6188733096da72eb4692cfed872101
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=microblaze SHELL=/bin/bash drivers/hwmon/
If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>
All warnings (new ones prefixed by >>):
drivers/hwmon/mr75203.c: In function 'mr75203_probe':
>> drivers/hwmon/mr75203.c:604:17: warning: ISO C90 forbids variable length array 'vm_idx' [-Wvla]
604 | u8 vm_idx[vm_num];
| ^~
>> drivers/hwmon/mr75203.c:605:17: warning: ISO C90 forbids variable length array 'vm_active_ch' [-Wvla]
605 | u8 vm_active_ch[vm_num];
| ^~
vim +/vm_idx +604 drivers/hwmon/mr75203.c
514
515 static int mr75203_probe(struct platform_device *pdev)
516 {
517 const struct hwmon_channel_info **pvt_info;
518 u32 ts_num, vm_num, pd_num, ch_num, val, index, i, j, k;
519 struct device *dev = &pdev->dev;
520 u32 *temp_config, *in_config;
521 struct device *hwmon_dev;
522 struct pvt_device *pvt;
523 int ret;
524
525 pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL);
526 if (!pvt)
527 return -ENOMEM;
528
529 ret = pvt_get_regmap(pdev, "common", pvt);
530 if (ret)
531 return ret;
532
533 pvt->clk = devm_clk_get(dev, NULL);
534 if (IS_ERR(pvt->clk))
535 return dev_err_probe(dev, PTR_ERR(pvt->clk), "failed to get clock\n");
536
537 ret = pvt_clk_enable(dev, pvt);
538 if (ret) {
539 dev_err(dev, "failed to enable clock\n");
540 return ret;
541 }
542
543 if (of_property_read_bool(dev->of_node, "reset-control-skip")) {
544 dev_info(dev, "skipping reset-control\n");
545 } else {
546 pvt->rst = devm_reset_control_get_exclusive(dev, NULL);
547 if (IS_ERR(pvt->rst))
548 return dev_err_probe(dev, PTR_ERR(pvt->rst),
549 "failed to get reset control\n");
550
551 ret = pvt_reset_control_deassert(dev, pvt);
552 if (ret)
553 return dev_err_probe(dev, ret,
554 "cannot deassert reset control\n");
555 }
556
557 ret = regmap_read(pvt->c_map, PVT_IP_CONFIG, &val);
558 if(ret < 0)
559 return ret;
560
561 ts_num = (val & TS_NUM_MSK) >> TS_NUM_SFT;
562 pd_num = (val & PD_NUM_MSK) >> PD_NUM_SFT;
563 vm_num = (val & VM_NUM_MSK) >> VM_NUM_SFT;
564 ch_num = (val & CH_NUM_MSK) >> CH_NUM_SFT;
565 pvt->t_num = ts_num;
566 pvt->p_num = pd_num;
567 pvt->v_num = vm_num;
568 val = 0;
569 if (ts_num)
570 val++;
571 if (vm_num)
572 val++;
573 if (!val)
574 return -ENODEV;
575
576 pvt_info = devm_kcalloc(dev, val + 2, sizeof(*pvt_info), GFP_KERNEL);
577 if (!pvt_info)
578 return -ENOMEM;
579 pvt_info[0] = HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ);
580 index = 1;
581
582 if (ts_num) {
583 ret = pvt_get_regmap(pdev, "ts", pvt);
584 if (ret)
585 return ret;
586
587 temp_config = devm_kcalloc(dev, ts_num + 1,
588 sizeof(*temp_config), GFP_KERNEL);
589 if (!temp_config)
590 return -ENOMEM;
591
592 memset32(temp_config, HWMON_T_INPUT, ts_num);
593 pvt_temp.config = temp_config;
594 pvt_info[index++] = &pvt_temp;
595 }
596
597 if (pd_num) {
598 ret = pvt_get_regmap(pdev, "pd", pvt);
599 if (ret)
600 return ret;
601 }
602
603 if (vm_num) {
> 604 u8 vm_idx[vm_num];
> 605 u8 vm_active_ch[vm_num];
606
607 ret = pvt_get_regmap(pdev, "vm", pvt);
608 if (ret)
609 return ret;
610
611 ret = device_property_read_u8_array(dev, "intel,vm-map", vm_idx,
612 vm_num);
613 if (ret) {
614 /*
615 * Incase intel,vm-map property is not defined, we
616 * assume incremental channel numbers.
617 */
618 for (i = 0; i < vm_num; i++)
619 vm_idx[i] = i;
620 } else {
621 for (i = 0; i < vm_num; i++)
622 if (vm_idx[i] >= vm_num || vm_idx[i] == 0xff)
623 break;
624
625 vm_num = i;
626 pvt->v_num = i;
627 }
628
629 ret = device_property_read_u8_array(dev, "vm-active-channels",
630 vm_active_ch, vm_num);
631 if (ret) {
632 /*
633 * Incase vm-active-channels property is not defined,
634 * we assume each VM sensor has all of its channels
635 * active.
636 */
637 for (i = 0; i < vm_num; i++)
638 vm_active_ch[i] = ch_num;
639
640 pvt->vm_ch_max = ch_num;
641 pvt->vm_ch_total = ch_num * vm_num;
642 } else {
643 for (i = 0; i < vm_num; i++) {
644 if (vm_active_ch[i] > ch_num) {
645 dev_err(dev,
646 "invalid active channels: %u\n",
647 vm_active_ch[i]);
648 return -EINVAL;
649 }
650
651 pvt->vm_ch_total += vm_active_ch[i];
652
653 if (vm_active_ch[i] > pvt->vm_ch_max)
654 pvt->vm_ch_max = vm_active_ch[i];
655 }
656 }
657
658 /*
659 * Map between the channel-number to VM-index and channel-index.
660 * Example - 3 VMs, vm_active_ch = [05 02 04]:
661 * vm_map = [0 0 0 0 0 1 1 2 2 2 2]
662 * ch_map = [0 1 2 3 4 0 1 0 1 2 3]
663 */
664 pvt->vd = devm_kcalloc(dev, pvt->vm_ch_total, sizeof(*pvt->vd),
665 GFP_KERNEL);
666 if (!pvt->vd)
667 return -ENOMEM;
668
669 k = 0;
670 for (i = 0; i < vm_num; i++)
671 for (j = 0; j < vm_active_ch[i]; j++) {
672 pvt->vd[k].vm_map = vm_idx[i];
673 pvt->vd[k].ch_map = j;
674 k++;
675 }
676
677 in_config = devm_kcalloc(dev, pvt->vm_ch_total + 1,
678 sizeof(*in_config), GFP_KERNEL);
679 if (!in_config)
680 return -ENOMEM;
681
682 memset32(in_config, HWMON_I_INPUT, pvt->vm_ch_total);
683 in_config[pvt->vm_ch_total] = 0;
684 pvt_in.config = in_config;
685
686 pvt_info[index++] = &pvt_in;
687 }
688
689 ret = pvt_init(pvt);
690 if (ret) {
691 dev_err(dev, "failed to init pvt: %d\n", ret);
692 return ret;
693 }
694
695 pvt_chip_info.info = pvt_info;
696 hwmon_dev = devm_hwmon_device_register_with_info(dev, "pvt",
697 pvt,
698 &pvt_chip_info,
699 NULL);
700
701 return PTR_ERR_OR_ZERO(hwmon_dev);
702 }
703
--
0-DAY CI Kernel Test Service
https://01.org/lkp
On Tue, Aug 16, 2022 at 08:27:44AM +0000, Eliav Farber wrote:
> The "intel,vm-map property" is optional and not required.
Please follow the subject format for the subsystem (bindings).
>
> Signed-off-by: Eliav Farber <[email protected]>
> ---
> Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml b/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
> index 6f3e3c01f717..f9e849cc73e0 100644
> --- a/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
> +++ b/Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
> @@ -48,12 +48,12 @@ required:
> - compatible
> - reg
> - reg-names
> - - intel,vm-map
> - clocks
> - resets
> - "#thermal-sensor-cells"
>
> -additionalProperties: false
> +additionalProperties:
> + - intel,vm-map
Please test your changes. Not valid json-schema.
>
> examples:
> - |
> --
> 2.37.1
>