in mr75203.c [500:639]
static int mr75203_probe(struct platform_device *pdev)
{
const struct hwmon_channel_info **pvt_info;
u32 ts_num, vm_num, pd_num, val, index, i;
struct device *dev = &pdev->dev;
u32 *temp_config, *in_config;
struct device *hwmon_dev;
struct pvt_device *pvt;
int ret;
pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL);
if (!pvt)
return -ENOMEM;
ret = pvt_get_regmap(pdev, "common", pvt);
if (ret)
return ret;
pvt->clk = devm_clk_get(dev, NULL);
if (IS_ERR(pvt->clk))
return dev_err_probe(dev, PTR_ERR(pvt->clk), "failed to get clock\n");
ret = pvt_clk_enable(dev, pvt);
if (ret) {
dev_err(dev, "failed to enable clock\n");
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");
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)
return ret;
ts_num = (val & TS_NUM_MSK) >> TS_NUM_SFT;
pd_num = (val & PD_NUM_MSK) >> PD_NUM_SFT;
vm_num = (val & VM_NUM_MSK) >> VM_NUM_SFT;
pvt->t_num = ts_num;
pvt->p_num = pd_num;
pvt->v_num = vm_num;
val = 0;
if (ts_num)
val++;
if (vm_num)
val++;
if (!val)
return -ENODEV;
pvt_info = devm_kcalloc(dev, val + 2, sizeof(*pvt_info), GFP_KERNEL);
if (!pvt_info)
return -ENOMEM;
pvt_info[0] = &pvt_chip;
index = 1;
if (ts_num) {
ret = pvt_get_regmap(pdev, "ts", pvt);
if (ret)
return ret;
temp_config = devm_kcalloc(dev, ts_num + 1,
sizeof(*temp_config), GFP_KERNEL);
if (!temp_config)
return -ENOMEM;
memset32(temp_config, HWMON_T_INPUT, ts_num);
pvt_temp.config = temp_config;
pvt_info[index++] = &pvt_temp;
}
if (pd_num) {
ret = pvt_get_regmap(pdev, "pd", pvt);
if (ret)
return ret;
}
if (vm_num) {
u32 num = 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);
if (ret) {
num = 0;
} else {
for (i = 0; i < vm_num; i++)
if (pvt->vm_idx[i] >= vm_num ||
pvt->vm_idx[i] == 0xff) {
num = i;
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;
in_config = devm_kcalloc(dev, num + 1,
sizeof(*in_config), GFP_KERNEL);
if (!in_config)
return -ENOMEM;
memset32(in_config, HWMON_I_INPUT, num);
in_config[num] = 0;
pvt_in.config = in_config;
pvt_info[index++] = &pvt_in;
}
ret = pvt_init(pvt);
if (ret) {
dev_err(dev, "failed to init pvt: %d\n", ret);
return ret;
}
pvt_chip_info.info = pvt_info;
hwmon_dev = devm_hwmon_device_register_with_info(dev, "pvt",
pvt,
&pvt_chip_info,
NULL);
return PTR_ERR_OR_ZERO(hwmon_dev);
}