18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2020 MaxLinear, Inc.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This driver is a hardware monitoring driver for PVT controller
68c2ecf20Sopenharmony_ci * (MR75203) which is used to configure & control Moortec embedded
78c2ecf20Sopenharmony_ci * analog IP to enable multiple embedded temperature sensor(TS),
88c2ecf20Sopenharmony_ci * voltage monitor(VM) & process detector(PD) modules.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci#include <linux/bits.h>
118c2ecf20Sopenharmony_ci#include <linux/clk.h>
128c2ecf20Sopenharmony_ci#include <linux/hwmon.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
158c2ecf20Sopenharmony_ci#include <linux/mutex.h>
168c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
178c2ecf20Sopenharmony_ci#include <linux/property.h>
188c2ecf20Sopenharmony_ci#include <linux/regmap.h>
198c2ecf20Sopenharmony_ci#include <linux/reset.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/* PVT Common register */
228c2ecf20Sopenharmony_ci#define PVT_IP_CONFIG	0x04
238c2ecf20Sopenharmony_ci#define TS_NUM_MSK	GENMASK(4, 0)
248c2ecf20Sopenharmony_ci#define TS_NUM_SFT	0
258c2ecf20Sopenharmony_ci#define PD_NUM_MSK	GENMASK(12, 8)
268c2ecf20Sopenharmony_ci#define PD_NUM_SFT	8
278c2ecf20Sopenharmony_ci#define VM_NUM_MSK	GENMASK(20, 16)
288c2ecf20Sopenharmony_ci#define VM_NUM_SFT	16
298c2ecf20Sopenharmony_ci#define CH_NUM_MSK	GENMASK(31, 24)
308c2ecf20Sopenharmony_ci#define CH_NUM_SFT	24
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* Macro Common Register */
338c2ecf20Sopenharmony_ci#define CLK_SYNTH		0x00
348c2ecf20Sopenharmony_ci#define CLK_SYNTH_LO_SFT	0
358c2ecf20Sopenharmony_ci#define CLK_SYNTH_HI_SFT	8
368c2ecf20Sopenharmony_ci#define CLK_SYNTH_HOLD_SFT	16
378c2ecf20Sopenharmony_ci#define CLK_SYNTH_EN		BIT(24)
388c2ecf20Sopenharmony_ci#define CLK_SYS_CYCLES_MAX	514
398c2ecf20Sopenharmony_ci#define CLK_SYS_CYCLES_MIN	2
408c2ecf20Sopenharmony_ci#define HZ_PER_MHZ		1000000L
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#define SDIF_DISABLE	0x04
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define SDIF_STAT	0x08
458c2ecf20Sopenharmony_ci#define SDIF_BUSY	BIT(0)
468c2ecf20Sopenharmony_ci#define SDIF_LOCK	BIT(1)
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define SDIF_W		0x0c
498c2ecf20Sopenharmony_ci#define SDIF_PROG	BIT(31)
508c2ecf20Sopenharmony_ci#define SDIF_WRN_W	BIT(27)
518c2ecf20Sopenharmony_ci#define SDIF_WRN_R	0x00
528c2ecf20Sopenharmony_ci#define SDIF_ADDR_SFT	24
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define SDIF_HALT	0x10
558c2ecf20Sopenharmony_ci#define SDIF_CTRL	0x14
568c2ecf20Sopenharmony_ci#define SDIF_SMPL_CTRL	0x20
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/* TS & PD Individual Macro Register */
598c2ecf20Sopenharmony_ci#define COM_REG_SIZE	0x40
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define SDIF_DONE(n)	(COM_REG_SIZE + 0x14 + 0x40 * (n))
628c2ecf20Sopenharmony_ci#define SDIF_SMPL_DONE	BIT(0)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define SDIF_DATA(n)	(COM_REG_SIZE + 0x18 + 0x40 * (n))
658c2ecf20Sopenharmony_ci#define SAMPLE_DATA_MSK	GENMASK(15, 0)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define HILO_RESET(n)	(COM_REG_SIZE + 0x2c + 0x40 * (n))
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/* VM Individual Macro Register */
708c2ecf20Sopenharmony_ci#define VM_COM_REG_SIZE	0x200
718c2ecf20Sopenharmony_ci#define VM_SDIF_DONE(vm)	(VM_COM_REG_SIZE + 0x34 + 0x200 * (vm))
728c2ecf20Sopenharmony_ci#define VM_SDIF_DATA(vm, ch)	\
738c2ecf20Sopenharmony_ci	(VM_COM_REG_SIZE + 0x40 + 0x200 * (vm) + 0x4 * (ch))
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci/* SDA Slave Register */
768c2ecf20Sopenharmony_ci#define IP_CTRL			0x00
778c2ecf20Sopenharmony_ci#define IP_RST_REL		BIT(1)
788c2ecf20Sopenharmony_ci#define IP_RUN_CONT		BIT(3)
798c2ecf20Sopenharmony_ci#define IP_AUTO			BIT(8)
808c2ecf20Sopenharmony_ci#define IP_VM_MODE		BIT(10)
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci#define IP_CFG			0x01
838c2ecf20Sopenharmony_ci#define CFG0_MODE_2		BIT(0)
848c2ecf20Sopenharmony_ci#define CFG0_PARALLEL_OUT	0
858c2ecf20Sopenharmony_ci#define CFG0_12_BIT		0
868c2ecf20Sopenharmony_ci#define CFG1_VOL_MEAS_MODE	0
878c2ecf20Sopenharmony_ci#define CFG1_PARALLEL_OUT	0
888c2ecf20Sopenharmony_ci#define CFG1_14_BIT		0
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci#define IP_DATA		0x03
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#define IP_POLL		0x04
938c2ecf20Sopenharmony_ci#define VM_CH_INIT	BIT(20)
948c2ecf20Sopenharmony_ci#define VM_CH_REQ	BIT(21)
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#define IP_TMR			0x05
978c2ecf20Sopenharmony_ci#define POWER_DELAY_CYCLE_256	0x100
988c2ecf20Sopenharmony_ci#define POWER_DELAY_CYCLE_64	0x40
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#define PVT_POLL_DELAY_US	20
1018c2ecf20Sopenharmony_ci#define PVT_POLL_TIMEOUT_US	20000
1028c2ecf20Sopenharmony_ci#define PVT_H_CONST		100000
1038c2ecf20Sopenharmony_ci#define PVT_CAL5_CONST		2047
1048c2ecf20Sopenharmony_ci#define PVT_G_CONST		40000
1058c2ecf20Sopenharmony_ci#define PVT_CONV_BITS		10
1068c2ecf20Sopenharmony_ci#define PVT_N_CONST		90
1078c2ecf20Sopenharmony_ci#define PVT_R_CONST		245805
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistruct pvt_device {
1108c2ecf20Sopenharmony_ci	struct regmap		*c_map;
1118c2ecf20Sopenharmony_ci	struct regmap		*t_map;
1128c2ecf20Sopenharmony_ci	struct regmap		*p_map;
1138c2ecf20Sopenharmony_ci	struct regmap		*v_map;
1148c2ecf20Sopenharmony_ci	struct clk		*clk;
1158c2ecf20Sopenharmony_ci	struct reset_control	*rst;
1168c2ecf20Sopenharmony_ci	u32			t_num;
1178c2ecf20Sopenharmony_ci	u32			p_num;
1188c2ecf20Sopenharmony_ci	u32			v_num;
1198c2ecf20Sopenharmony_ci	u32			c_num;
1208c2ecf20Sopenharmony_ci	u32			ip_freq;
1218c2ecf20Sopenharmony_ci	u8			*vm_idx;
1228c2ecf20Sopenharmony_ci};
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic umode_t pvt_is_visible(const void *data, enum hwmon_sensor_types type,
1258c2ecf20Sopenharmony_ci			      u32 attr, int channel)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	switch (type) {
1288c2ecf20Sopenharmony_ci	case hwmon_temp:
1298c2ecf20Sopenharmony_ci		if (attr == hwmon_temp_input)
1308c2ecf20Sopenharmony_ci			return 0444;
1318c2ecf20Sopenharmony_ci		break;
1328c2ecf20Sopenharmony_ci	case hwmon_in:
1338c2ecf20Sopenharmony_ci		if (attr == hwmon_in_input)
1348c2ecf20Sopenharmony_ci			return 0444;
1358c2ecf20Sopenharmony_ci		break;
1368c2ecf20Sopenharmony_ci	default:
1378c2ecf20Sopenharmony_ci		break;
1388c2ecf20Sopenharmony_ci	}
1398c2ecf20Sopenharmony_ci	return 0;
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistatic int pvt_read_temp(struct device *dev, u32 attr, int channel, long *val)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	struct pvt_device *pvt = dev_get_drvdata(dev);
1458c2ecf20Sopenharmony_ci	struct regmap *t_map = pvt->t_map;
1468c2ecf20Sopenharmony_ci	u32 stat, nbs;
1478c2ecf20Sopenharmony_ci	int ret;
1488c2ecf20Sopenharmony_ci	u64 tmp;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	switch (attr) {
1518c2ecf20Sopenharmony_ci	case hwmon_temp_input:
1528c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(t_map, SDIF_DONE(channel),
1538c2ecf20Sopenharmony_ci					       stat, stat & SDIF_SMPL_DONE,
1548c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
1558c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
1568c2ecf20Sopenharmony_ci		if (ret)
1578c2ecf20Sopenharmony_ci			return ret;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		ret = regmap_read(t_map, SDIF_DATA(channel), &nbs);
1608c2ecf20Sopenharmony_ci		if(ret < 0)
1618c2ecf20Sopenharmony_ci			return ret;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci		nbs &= SAMPLE_DATA_MSK;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci		/*
1668c2ecf20Sopenharmony_ci		 * Convert the register value to
1678c2ecf20Sopenharmony_ci		 * degrees centigrade temperature
1688c2ecf20Sopenharmony_ci		 */
1698c2ecf20Sopenharmony_ci		tmp = nbs * PVT_H_CONST;
1708c2ecf20Sopenharmony_ci		do_div(tmp, PVT_CAL5_CONST);
1718c2ecf20Sopenharmony_ci		*val = tmp - PVT_G_CONST - pvt->ip_freq;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci		return 0;
1748c2ecf20Sopenharmony_ci	default:
1758c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic int pvt_read_in(struct device *dev, u32 attr, int channel, long *val)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	struct pvt_device *pvt = dev_get_drvdata(dev);
1828c2ecf20Sopenharmony_ci	struct regmap *v_map = pvt->v_map;
1838c2ecf20Sopenharmony_ci	u8 vm_idx, ch_idx;
1848c2ecf20Sopenharmony_ci	u32 n, stat;
1858c2ecf20Sopenharmony_ci	int ret;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	if (channel >= pvt->v_num * pvt->c_num)
1888c2ecf20Sopenharmony_ci		return -EINVAL;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	vm_idx = pvt->vm_idx[channel / pvt->c_num];
1918c2ecf20Sopenharmony_ci	ch_idx = channel % pvt->c_num;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	switch (attr) {
1948c2ecf20Sopenharmony_ci	case hwmon_in_input:
1958c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(v_map, VM_SDIF_DONE(vm_idx),
1968c2ecf20Sopenharmony_ci					       stat, stat & SDIF_SMPL_DONE,
1978c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
1988c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
1998c2ecf20Sopenharmony_ci		if (ret)
2008c2ecf20Sopenharmony_ci			return ret;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci		ret = regmap_read(v_map, VM_SDIF_DATA(vm_idx, ch_idx), &n);
2038c2ecf20Sopenharmony_ci		if(ret < 0)
2048c2ecf20Sopenharmony_ci			return ret;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci		n &= SAMPLE_DATA_MSK;
2078c2ecf20Sopenharmony_ci		/*
2088c2ecf20Sopenharmony_ci		 * Convert the N bitstream count into voltage.
2098c2ecf20Sopenharmony_ci		 * To support negative voltage calculation for 64bit machines
2108c2ecf20Sopenharmony_ci		 * n must be cast to long, since n and *val differ both in
2118c2ecf20Sopenharmony_ci		 * signedness and in size.
2128c2ecf20Sopenharmony_ci		 * Division is used instead of right shift, because for signed
2138c2ecf20Sopenharmony_ci		 * numbers, the sign bit is used to fill the vacated bit
2148c2ecf20Sopenharmony_ci		 * positions, and if the number is negative, 1 is used.
2158c2ecf20Sopenharmony_ci		 * BIT(x) may not be used instead of (1 << x) because it's
2168c2ecf20Sopenharmony_ci		 * unsigned.
2178c2ecf20Sopenharmony_ci		 */
2188c2ecf20Sopenharmony_ci		*val = (PVT_N_CONST * (long)n - PVT_R_CONST) / (1 << PVT_CONV_BITS);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci		return 0;
2218c2ecf20Sopenharmony_ci	default:
2228c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic int pvt_read(struct device *dev, enum hwmon_sensor_types type,
2278c2ecf20Sopenharmony_ci		    u32 attr, int channel, long *val)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	switch (type) {
2308c2ecf20Sopenharmony_ci	case hwmon_temp:
2318c2ecf20Sopenharmony_ci		return pvt_read_temp(dev, attr, channel, val);
2328c2ecf20Sopenharmony_ci	case hwmon_in:
2338c2ecf20Sopenharmony_ci		return pvt_read_in(dev, attr, channel, val);
2348c2ecf20Sopenharmony_ci	default:
2358c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistatic const u32 pvt_chip_config[] = {
2408c2ecf20Sopenharmony_ci	HWMON_C_REGISTER_TZ,
2418c2ecf20Sopenharmony_ci	0
2428c2ecf20Sopenharmony_ci};
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_cistatic const struct hwmon_channel_info pvt_chip = {
2458c2ecf20Sopenharmony_ci	.type = hwmon_chip,
2468c2ecf20Sopenharmony_ci	.config = pvt_chip_config,
2478c2ecf20Sopenharmony_ci};
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic struct hwmon_channel_info pvt_temp = {
2508c2ecf20Sopenharmony_ci	.type = hwmon_temp,
2518c2ecf20Sopenharmony_ci};
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic struct hwmon_channel_info pvt_in = {
2548c2ecf20Sopenharmony_ci	.type = hwmon_in,
2558c2ecf20Sopenharmony_ci};
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic const struct hwmon_ops pvt_hwmon_ops = {
2588c2ecf20Sopenharmony_ci	.is_visible = pvt_is_visible,
2598c2ecf20Sopenharmony_ci	.read = pvt_read,
2608c2ecf20Sopenharmony_ci};
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistatic struct hwmon_chip_info pvt_chip_info = {
2638c2ecf20Sopenharmony_ci	.ops = &pvt_hwmon_ops,
2648c2ecf20Sopenharmony_ci};
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cistatic int pvt_init(struct pvt_device *pvt)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	u16 sys_freq, key, middle, low = 4, high = 8;
2698c2ecf20Sopenharmony_ci	struct regmap *t_map = pvt->t_map;
2708c2ecf20Sopenharmony_ci	struct regmap *p_map = pvt->p_map;
2718c2ecf20Sopenharmony_ci	struct regmap *v_map = pvt->v_map;
2728c2ecf20Sopenharmony_ci	u32 t_num = pvt->t_num;
2738c2ecf20Sopenharmony_ci	u32 p_num = pvt->p_num;
2748c2ecf20Sopenharmony_ci	u32 v_num = pvt->v_num;
2758c2ecf20Sopenharmony_ci	u32 clk_synth, val;
2768c2ecf20Sopenharmony_ci	int ret;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	sys_freq = clk_get_rate(pvt->clk) / HZ_PER_MHZ;
2798c2ecf20Sopenharmony_ci	while (high >= low) {
2808c2ecf20Sopenharmony_ci		middle = (low + high + 1) / 2;
2818c2ecf20Sopenharmony_ci		key = DIV_ROUND_CLOSEST(sys_freq, middle);
2828c2ecf20Sopenharmony_ci		if (key > CLK_SYS_CYCLES_MAX) {
2838c2ecf20Sopenharmony_ci			low = middle + 1;
2848c2ecf20Sopenharmony_ci			continue;
2858c2ecf20Sopenharmony_ci		} else if (key < CLK_SYS_CYCLES_MIN) {
2868c2ecf20Sopenharmony_ci			high = middle - 1;
2878c2ecf20Sopenharmony_ci			continue;
2888c2ecf20Sopenharmony_ci		} else {
2898c2ecf20Sopenharmony_ci			break;
2908c2ecf20Sopenharmony_ci		}
2918c2ecf20Sopenharmony_ci	}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	/*
2948c2ecf20Sopenharmony_ci	 * The system supports 'clk_sys' to 'clk_ip' frequency ratios
2958c2ecf20Sopenharmony_ci	 * from 2:1 to 512:1
2968c2ecf20Sopenharmony_ci	 */
2978c2ecf20Sopenharmony_ci	key = clamp_val(key, CLK_SYS_CYCLES_MIN, CLK_SYS_CYCLES_MAX) - 2;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	clk_synth = ((key + 1) >> 1) << CLK_SYNTH_LO_SFT |
3008c2ecf20Sopenharmony_ci		    (key >> 1) << CLK_SYNTH_HI_SFT |
3018c2ecf20Sopenharmony_ci		    (key >> 1) << CLK_SYNTH_HOLD_SFT | CLK_SYNTH_EN;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	pvt->ip_freq = sys_freq * 100 / (key + 2);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	if (t_num) {
3068c2ecf20Sopenharmony_ci		ret = regmap_write(t_map, SDIF_SMPL_CTRL, 0x0);
3078c2ecf20Sopenharmony_ci		if(ret < 0)
3088c2ecf20Sopenharmony_ci			return ret;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci		ret = regmap_write(t_map, SDIF_HALT, 0x0);
3118c2ecf20Sopenharmony_ci		if(ret < 0)
3128c2ecf20Sopenharmony_ci			return ret;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci		ret = regmap_write(t_map, CLK_SYNTH, clk_synth);
3158c2ecf20Sopenharmony_ci		if(ret < 0)
3168c2ecf20Sopenharmony_ci			return ret;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		ret = regmap_write(t_map, SDIF_DISABLE, 0x0);
3198c2ecf20Sopenharmony_ci		if(ret < 0)
3208c2ecf20Sopenharmony_ci			return ret;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(t_map, SDIF_STAT,
3238c2ecf20Sopenharmony_ci					       val, !(val & SDIF_BUSY),
3248c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
3258c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
3268c2ecf20Sopenharmony_ci		if (ret)
3278c2ecf20Sopenharmony_ci			return ret;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci		val = CFG0_MODE_2 | CFG0_PARALLEL_OUT | CFG0_12_BIT |
3308c2ecf20Sopenharmony_ci		      IP_CFG << SDIF_ADDR_SFT | SDIF_WRN_W | SDIF_PROG;
3318c2ecf20Sopenharmony_ci		ret = regmap_write(t_map, SDIF_W, val);
3328c2ecf20Sopenharmony_ci		if(ret < 0)
3338c2ecf20Sopenharmony_ci			return ret;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(t_map, SDIF_STAT,
3368c2ecf20Sopenharmony_ci					       val, !(val & SDIF_BUSY),
3378c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
3388c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
3398c2ecf20Sopenharmony_ci		if (ret)
3408c2ecf20Sopenharmony_ci			return ret;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci		val = POWER_DELAY_CYCLE_256 | IP_TMR << SDIF_ADDR_SFT |
3438c2ecf20Sopenharmony_ci			      SDIF_WRN_W | SDIF_PROG;
3448c2ecf20Sopenharmony_ci		ret = regmap_write(t_map, SDIF_W, val);
3458c2ecf20Sopenharmony_ci		if(ret < 0)
3468c2ecf20Sopenharmony_ci			return ret;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(t_map, SDIF_STAT,
3498c2ecf20Sopenharmony_ci					       val, !(val & SDIF_BUSY),
3508c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
3518c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
3528c2ecf20Sopenharmony_ci		if (ret)
3538c2ecf20Sopenharmony_ci			return ret;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci		val = IP_RST_REL | IP_RUN_CONT | IP_AUTO |
3568c2ecf20Sopenharmony_ci		      IP_CTRL << SDIF_ADDR_SFT |
3578c2ecf20Sopenharmony_ci		      SDIF_WRN_W | SDIF_PROG;
3588c2ecf20Sopenharmony_ci		ret = regmap_write(t_map, SDIF_W, val);
3598c2ecf20Sopenharmony_ci		if(ret < 0)
3608c2ecf20Sopenharmony_ci			return ret;
3618c2ecf20Sopenharmony_ci	}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	if (p_num) {
3648c2ecf20Sopenharmony_ci		ret = regmap_write(p_map, SDIF_HALT, 0x0);
3658c2ecf20Sopenharmony_ci		if(ret < 0)
3668c2ecf20Sopenharmony_ci			return ret;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci		ret = regmap_write(p_map, SDIF_DISABLE, BIT(p_num) - 1);
3698c2ecf20Sopenharmony_ci		if(ret < 0)
3708c2ecf20Sopenharmony_ci			return ret;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci		ret = regmap_write(p_map, CLK_SYNTH, clk_synth);
3738c2ecf20Sopenharmony_ci		if(ret < 0)
3748c2ecf20Sopenharmony_ci			return ret;
3758c2ecf20Sopenharmony_ci	}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	if (v_num) {
3788c2ecf20Sopenharmony_ci		ret = regmap_write(v_map, SDIF_SMPL_CTRL, 0x0);
3798c2ecf20Sopenharmony_ci		if(ret < 0)
3808c2ecf20Sopenharmony_ci			return ret;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci		ret = regmap_write(v_map, SDIF_HALT, 0x0);
3838c2ecf20Sopenharmony_ci		if(ret < 0)
3848c2ecf20Sopenharmony_ci			return ret;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci		ret = regmap_write(v_map, CLK_SYNTH, clk_synth);
3878c2ecf20Sopenharmony_ci		if(ret < 0)
3888c2ecf20Sopenharmony_ci			return ret;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci		ret = regmap_write(v_map, SDIF_DISABLE, 0x0);
3918c2ecf20Sopenharmony_ci		if(ret < 0)
3928c2ecf20Sopenharmony_ci			return ret;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
3958c2ecf20Sopenharmony_ci					       val, !(val & SDIF_BUSY),
3968c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
3978c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
3988c2ecf20Sopenharmony_ci		if (ret)
3998c2ecf20Sopenharmony_ci			return ret;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci		val = (BIT(pvt->c_num) - 1) | VM_CH_INIT |
4028c2ecf20Sopenharmony_ci		      IP_POLL << SDIF_ADDR_SFT | SDIF_WRN_W | SDIF_PROG;
4038c2ecf20Sopenharmony_ci		ret = regmap_write(v_map, SDIF_W, val);
4048c2ecf20Sopenharmony_ci		if (ret < 0)
4058c2ecf20Sopenharmony_ci			return ret;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
4088c2ecf20Sopenharmony_ci					       val, !(val & SDIF_BUSY),
4098c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
4108c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
4118c2ecf20Sopenharmony_ci		if (ret)
4128c2ecf20Sopenharmony_ci			return ret;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci		val = CFG1_VOL_MEAS_MODE | CFG1_PARALLEL_OUT |
4158c2ecf20Sopenharmony_ci		      CFG1_14_BIT | IP_CFG << SDIF_ADDR_SFT |
4168c2ecf20Sopenharmony_ci		      SDIF_WRN_W | SDIF_PROG;
4178c2ecf20Sopenharmony_ci		ret = regmap_write(v_map, SDIF_W, val);
4188c2ecf20Sopenharmony_ci		if(ret < 0)
4198c2ecf20Sopenharmony_ci			return ret;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
4228c2ecf20Sopenharmony_ci					       val, !(val & SDIF_BUSY),
4238c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
4248c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
4258c2ecf20Sopenharmony_ci		if (ret)
4268c2ecf20Sopenharmony_ci			return ret;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci		val = POWER_DELAY_CYCLE_64 | IP_TMR << SDIF_ADDR_SFT |
4298c2ecf20Sopenharmony_ci		      SDIF_WRN_W | SDIF_PROG;
4308c2ecf20Sopenharmony_ci		ret = regmap_write(v_map, SDIF_W, val);
4318c2ecf20Sopenharmony_ci		if(ret < 0)
4328c2ecf20Sopenharmony_ci			return ret;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci		ret = regmap_read_poll_timeout(v_map, SDIF_STAT,
4358c2ecf20Sopenharmony_ci					       val, !(val & SDIF_BUSY),
4368c2ecf20Sopenharmony_ci					       PVT_POLL_DELAY_US,
4378c2ecf20Sopenharmony_ci					       PVT_POLL_TIMEOUT_US);
4388c2ecf20Sopenharmony_ci		if (ret)
4398c2ecf20Sopenharmony_ci			return ret;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci		val = IP_RST_REL | IP_RUN_CONT | IP_AUTO | IP_VM_MODE |
4428c2ecf20Sopenharmony_ci		      IP_CTRL << SDIF_ADDR_SFT |
4438c2ecf20Sopenharmony_ci		      SDIF_WRN_W | SDIF_PROG;
4448c2ecf20Sopenharmony_ci		ret = regmap_write(v_map, SDIF_W, val);
4458c2ecf20Sopenharmony_ci		if(ret < 0)
4468c2ecf20Sopenharmony_ci			return ret;
4478c2ecf20Sopenharmony_ci	}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	return 0;
4508c2ecf20Sopenharmony_ci}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cistatic struct regmap_config pvt_regmap_config = {
4538c2ecf20Sopenharmony_ci	.reg_bits = 32,
4548c2ecf20Sopenharmony_ci	.reg_stride = 4,
4558c2ecf20Sopenharmony_ci	.val_bits = 32,
4568c2ecf20Sopenharmony_ci};
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic int pvt_get_regmap(struct platform_device *pdev, char *reg_name,
4598c2ecf20Sopenharmony_ci			  struct pvt_device *pvt)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
4628c2ecf20Sopenharmony_ci	struct regmap **reg_map;
4638c2ecf20Sopenharmony_ci	void __iomem *io_base;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	if (!strcmp(reg_name, "common"))
4668c2ecf20Sopenharmony_ci		reg_map = &pvt->c_map;
4678c2ecf20Sopenharmony_ci	else if (!strcmp(reg_name, "ts"))
4688c2ecf20Sopenharmony_ci		reg_map = &pvt->t_map;
4698c2ecf20Sopenharmony_ci	else if (!strcmp(reg_name, "pd"))
4708c2ecf20Sopenharmony_ci		reg_map = &pvt->p_map;
4718c2ecf20Sopenharmony_ci	else if (!strcmp(reg_name, "vm"))
4728c2ecf20Sopenharmony_ci		reg_map = &pvt->v_map;
4738c2ecf20Sopenharmony_ci	else
4748c2ecf20Sopenharmony_ci		return -EINVAL;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	io_base = devm_platform_ioremap_resource_byname(pdev, reg_name);
4778c2ecf20Sopenharmony_ci	if (IS_ERR(io_base))
4788c2ecf20Sopenharmony_ci		return PTR_ERR(io_base);
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	pvt_regmap_config.name = reg_name;
4818c2ecf20Sopenharmony_ci	*reg_map = devm_regmap_init_mmio(dev, io_base, &pvt_regmap_config);
4828c2ecf20Sopenharmony_ci	if (IS_ERR(*reg_map)) {
4838c2ecf20Sopenharmony_ci		dev_err(dev, "failed to init register map\n");
4848c2ecf20Sopenharmony_ci		return PTR_ERR(*reg_map);
4858c2ecf20Sopenharmony_ci	}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	return 0;
4888c2ecf20Sopenharmony_ci}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_cistatic void pvt_clk_disable(void *data)
4918c2ecf20Sopenharmony_ci{
4928c2ecf20Sopenharmony_ci	struct pvt_device *pvt = data;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	clk_disable_unprepare(pvt->clk);
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_cistatic int pvt_clk_enable(struct device *dev, struct pvt_device *pvt)
4988c2ecf20Sopenharmony_ci{
4998c2ecf20Sopenharmony_ci	int ret;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(pvt->clk);
5028c2ecf20Sopenharmony_ci	if (ret)
5038c2ecf20Sopenharmony_ci		return ret;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	return devm_add_action_or_reset(dev, pvt_clk_disable, pvt);
5068c2ecf20Sopenharmony_ci}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_cistatic void pvt_reset_control_assert(void *data)
5098c2ecf20Sopenharmony_ci{
5108c2ecf20Sopenharmony_ci	struct pvt_device *pvt = data;
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	reset_control_assert(pvt->rst);
5138c2ecf20Sopenharmony_ci}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_cistatic int pvt_reset_control_deassert(struct device *dev, struct pvt_device *pvt)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	int ret;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	ret = reset_control_deassert(pvt->rst);
5208c2ecf20Sopenharmony_ci	if (ret)
5218c2ecf20Sopenharmony_ci		return ret;
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	return devm_add_action_or_reset(dev, pvt_reset_control_assert, pvt);
5248c2ecf20Sopenharmony_ci}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_cistatic int mr75203_probe(struct platform_device *pdev)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	u32 ts_num, vm_num, pd_num, ch_num, val, index, i;
5298c2ecf20Sopenharmony_ci	const struct hwmon_channel_info **pvt_info;
5308c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
5318c2ecf20Sopenharmony_ci	u32 *temp_config, *in_config;
5328c2ecf20Sopenharmony_ci	struct device *hwmon_dev;
5338c2ecf20Sopenharmony_ci	struct pvt_device *pvt;
5348c2ecf20Sopenharmony_ci	int ret;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL);
5378c2ecf20Sopenharmony_ci	if (!pvt)
5388c2ecf20Sopenharmony_ci		return -ENOMEM;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	ret = pvt_get_regmap(pdev, "common", pvt);
5418c2ecf20Sopenharmony_ci	if (ret)
5428c2ecf20Sopenharmony_ci		return ret;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	pvt->clk = devm_clk_get(dev, NULL);
5458c2ecf20Sopenharmony_ci	if (IS_ERR(pvt->clk))
5468c2ecf20Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(pvt->clk), "failed to get clock\n");
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	ret = pvt_clk_enable(dev, pvt);
5498c2ecf20Sopenharmony_ci	if (ret) {
5508c2ecf20Sopenharmony_ci		dev_err(dev, "failed to enable clock\n");
5518c2ecf20Sopenharmony_ci		return ret;
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	pvt->rst = devm_reset_control_get_exclusive(dev, NULL);
5558c2ecf20Sopenharmony_ci	if (IS_ERR(pvt->rst))
5568c2ecf20Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(pvt->rst),
5578c2ecf20Sopenharmony_ci				     "failed to get reset control\n");
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	ret = pvt_reset_control_deassert(dev, pvt);
5608c2ecf20Sopenharmony_ci	if (ret)
5618c2ecf20Sopenharmony_ci		return dev_err_probe(dev, ret, "cannot deassert reset control\n");
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	ret = regmap_read(pvt->c_map, PVT_IP_CONFIG, &val);
5648c2ecf20Sopenharmony_ci	if(ret < 0)
5658c2ecf20Sopenharmony_ci		return ret;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	ts_num = (val & TS_NUM_MSK) >> TS_NUM_SFT;
5688c2ecf20Sopenharmony_ci	pd_num = (val & PD_NUM_MSK) >> PD_NUM_SFT;
5698c2ecf20Sopenharmony_ci	vm_num = (val & VM_NUM_MSK) >> VM_NUM_SFT;
5708c2ecf20Sopenharmony_ci	ch_num = (val & CH_NUM_MSK) >> CH_NUM_SFT;
5718c2ecf20Sopenharmony_ci	pvt->t_num = ts_num;
5728c2ecf20Sopenharmony_ci	pvt->p_num = pd_num;
5738c2ecf20Sopenharmony_ci	pvt->v_num = vm_num;
5748c2ecf20Sopenharmony_ci	pvt->c_num = ch_num;
5758c2ecf20Sopenharmony_ci	val = 0;
5768c2ecf20Sopenharmony_ci	if (ts_num)
5778c2ecf20Sopenharmony_ci		val++;
5788c2ecf20Sopenharmony_ci	if (vm_num)
5798c2ecf20Sopenharmony_ci		val++;
5808c2ecf20Sopenharmony_ci	if (!val)
5818c2ecf20Sopenharmony_ci		return -ENODEV;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	pvt_info = devm_kcalloc(dev, val + 2, sizeof(*pvt_info), GFP_KERNEL);
5848c2ecf20Sopenharmony_ci	if (!pvt_info)
5858c2ecf20Sopenharmony_ci		return -ENOMEM;
5868c2ecf20Sopenharmony_ci	pvt_info[0] = &pvt_chip;
5878c2ecf20Sopenharmony_ci	index = 1;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	if (ts_num) {
5908c2ecf20Sopenharmony_ci		ret = pvt_get_regmap(pdev, "ts", pvt);
5918c2ecf20Sopenharmony_ci		if (ret)
5928c2ecf20Sopenharmony_ci			return ret;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci		temp_config = devm_kcalloc(dev, ts_num + 1,
5958c2ecf20Sopenharmony_ci					   sizeof(*temp_config), GFP_KERNEL);
5968c2ecf20Sopenharmony_ci		if (!temp_config)
5978c2ecf20Sopenharmony_ci			return -ENOMEM;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci		memset32(temp_config, HWMON_T_INPUT, ts_num);
6008c2ecf20Sopenharmony_ci		pvt_temp.config = temp_config;
6018c2ecf20Sopenharmony_ci		pvt_info[index++] = &pvt_temp;
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	if (pd_num) {
6058c2ecf20Sopenharmony_ci		ret = pvt_get_regmap(pdev, "pd", pvt);
6068c2ecf20Sopenharmony_ci		if (ret)
6078c2ecf20Sopenharmony_ci			return ret;
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	if (vm_num) {
6118c2ecf20Sopenharmony_ci		u32 total_ch;
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci		ret = pvt_get_regmap(pdev, "vm", pvt);
6148c2ecf20Sopenharmony_ci		if (ret)
6158c2ecf20Sopenharmony_ci			return ret;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci		pvt->vm_idx = devm_kcalloc(dev, vm_num, sizeof(*pvt->vm_idx),
6188c2ecf20Sopenharmony_ci					   GFP_KERNEL);
6198c2ecf20Sopenharmony_ci		if (!pvt->vm_idx)
6208c2ecf20Sopenharmony_ci			return -ENOMEM;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci		ret = device_property_read_u8_array(dev, "intel,vm-map",
6238c2ecf20Sopenharmony_ci						    pvt->vm_idx, vm_num);
6248c2ecf20Sopenharmony_ci		if (ret) {
6258c2ecf20Sopenharmony_ci			/*
6268c2ecf20Sopenharmony_ci			 * Incase intel,vm-map property is not defined, we
6278c2ecf20Sopenharmony_ci			 * assume incremental channel numbers.
6288c2ecf20Sopenharmony_ci			 */
6298c2ecf20Sopenharmony_ci			for (i = 0; i < vm_num; i++)
6308c2ecf20Sopenharmony_ci				pvt->vm_idx[i] = i;
6318c2ecf20Sopenharmony_ci		} else {
6328c2ecf20Sopenharmony_ci			for (i = 0; i < vm_num; i++)
6338c2ecf20Sopenharmony_ci				if (pvt->vm_idx[i] >= vm_num ||
6348c2ecf20Sopenharmony_ci				    pvt->vm_idx[i] == 0xff) {
6358c2ecf20Sopenharmony_ci					pvt->v_num = i;
6368c2ecf20Sopenharmony_ci					vm_num = i;
6378c2ecf20Sopenharmony_ci					break;
6388c2ecf20Sopenharmony_ci				}
6398c2ecf20Sopenharmony_ci		}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci		total_ch = ch_num * vm_num;
6428c2ecf20Sopenharmony_ci		in_config = devm_kcalloc(dev, total_ch + 1,
6438c2ecf20Sopenharmony_ci					 sizeof(*in_config), GFP_KERNEL);
6448c2ecf20Sopenharmony_ci		if (!in_config)
6458c2ecf20Sopenharmony_ci			return -ENOMEM;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci		memset32(in_config, HWMON_I_INPUT, total_ch);
6488c2ecf20Sopenharmony_ci		in_config[total_ch] = 0;
6498c2ecf20Sopenharmony_ci		pvt_in.config = in_config;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci		pvt_info[index++] = &pvt_in;
6528c2ecf20Sopenharmony_ci	}
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	ret = pvt_init(pvt);
6558c2ecf20Sopenharmony_ci	if (ret) {
6568c2ecf20Sopenharmony_ci		dev_err(dev, "failed to init pvt: %d\n", ret);
6578c2ecf20Sopenharmony_ci		return ret;
6588c2ecf20Sopenharmony_ci	}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	pvt_chip_info.info = pvt_info;
6618c2ecf20Sopenharmony_ci	hwmon_dev = devm_hwmon_device_register_with_info(dev, "pvt",
6628c2ecf20Sopenharmony_ci							 pvt,
6638c2ecf20Sopenharmony_ci							 &pvt_chip_info,
6648c2ecf20Sopenharmony_ci							 NULL);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	return PTR_ERR_OR_ZERO(hwmon_dev);
6678c2ecf20Sopenharmony_ci}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_cistatic const struct of_device_id moortec_pvt_of_match[] = {
6708c2ecf20Sopenharmony_ci	{ .compatible = "moortec,mr75203" },
6718c2ecf20Sopenharmony_ci	{ }
6728c2ecf20Sopenharmony_ci};
6738c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, moortec_pvt_of_match);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_cistatic struct platform_driver moortec_pvt_driver = {
6768c2ecf20Sopenharmony_ci	.driver = {
6778c2ecf20Sopenharmony_ci		.name = "moortec-pvt",
6788c2ecf20Sopenharmony_ci		.of_match_table = moortec_pvt_of_match,
6798c2ecf20Sopenharmony_ci	},
6808c2ecf20Sopenharmony_ci	.probe = mr75203_probe,
6818c2ecf20Sopenharmony_ci};
6828c2ecf20Sopenharmony_cimodule_platform_driver(moortec_pvt_driver);
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
685