xref: /openbmc/linux/drivers/hwmon/bt1-pvt.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
187976ce2SSerge Semin // SPDX-License-Identifier: GPL-2.0-only
287976ce2SSerge Semin /*
387976ce2SSerge Semin  * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
487976ce2SSerge Semin  *
587976ce2SSerge Semin  * Authors:
687976ce2SSerge Semin  *   Maxim Kaurkin <maxim.kaurkin@baikalelectronics.ru>
787976ce2SSerge Semin  *   Serge Semin <Sergey.Semin@baikalelectronics.ru>
887976ce2SSerge Semin  *
987976ce2SSerge Semin  * Baikal-T1 Process, Voltage, Temperature sensor driver
1087976ce2SSerge Semin  */
1187976ce2SSerge Semin 
1287976ce2SSerge Semin #include <linux/bitfield.h>
1387976ce2SSerge Semin #include <linux/bitops.h>
1487976ce2SSerge Semin #include <linux/clk.h>
1587976ce2SSerge Semin #include <linux/completion.h>
16a6db1561SSerge Semin #include <linux/delay.h>
1787976ce2SSerge Semin #include <linux/device.h>
1887976ce2SSerge Semin #include <linux/hwmon-sysfs.h>
1987976ce2SSerge Semin #include <linux/hwmon.h>
2087976ce2SSerge Semin #include <linux/interrupt.h>
2187976ce2SSerge Semin #include <linux/io.h>
2287976ce2SSerge Semin #include <linux/kernel.h>
2387976ce2SSerge Semin #include <linux/ktime.h>
2487976ce2SSerge Semin #include <linux/limits.h>
2587976ce2SSerge Semin #include <linux/module.h>
2687976ce2SSerge Semin #include <linux/mutex.h>
2787976ce2SSerge Semin #include <linux/of.h>
2887976ce2SSerge Semin #include <linux/platform_device.h>
29e0daf1a6SMichael Walle #include <linux/polynomial.h>
3087976ce2SSerge Semin #include <linux/seqlock.h>
3187976ce2SSerge Semin #include <linux/sysfs.h>
3287976ce2SSerge Semin #include <linux/types.h>
3387976ce2SSerge Semin 
3487976ce2SSerge Semin #include "bt1-pvt.h"
3587976ce2SSerge Semin 
3687976ce2SSerge Semin /*
3787976ce2SSerge Semin  * For the sake of the code simplification we created the sensors info table
3887976ce2SSerge Semin  * with the sensor names, activation modes, threshold registers base address
3987976ce2SSerge Semin  * and the thresholds bit fields.
4087976ce2SSerge Semin  */
4187976ce2SSerge Semin static const struct pvt_sensor_info pvt_info[] = {
4287976ce2SSerge Semin 	PVT_SENSOR_INFO(0, "CPU Core Temperature", hwmon_temp, TEMP, TTHRES),
4387976ce2SSerge Semin 	PVT_SENSOR_INFO(0, "CPU Core Voltage", hwmon_in, VOLT, VTHRES),
4487976ce2SSerge Semin 	PVT_SENSOR_INFO(1, "CPU Core Low-Vt", hwmon_in, LVT, LTHRES),
4587976ce2SSerge Semin 	PVT_SENSOR_INFO(2, "CPU Core High-Vt", hwmon_in, HVT, HTHRES),
4687976ce2SSerge Semin 	PVT_SENSOR_INFO(3, "CPU Core Standard-Vt", hwmon_in, SVT, STHRES),
4787976ce2SSerge Semin };
4887976ce2SSerge Semin 
4987976ce2SSerge Semin /*
5087976ce2SSerge Semin  * The original translation formulae of the temperature (in degrees of Celsius)
5187976ce2SSerge Semin  * to PVT data and vice-versa are following:
5287976ce2SSerge Semin  * N = 1.8322e-8*(T^4) + 2.343e-5*(T^3) + 8.7018e-3*(T^2) + 3.9269*(T^1) +
5387976ce2SSerge Semin  *     1.7204e2,
5487976ce2SSerge Semin  * T = -1.6743e-11*(N^4) + 8.1542e-8*(N^3) + -1.8201e-4*(N^2) +
5587976ce2SSerge Semin  *     3.1020e-1*(N^1) - 4.838e1,
5687976ce2SSerge Semin  * where T = [-48.380, 147.438]C and N = [0, 1023].
5787976ce2SSerge Semin  * They must be accordingly altered to be suitable for the integer arithmetics.
5887976ce2SSerge Semin  * The technique is called 'factor redistribution', which just makes sure the
5987976ce2SSerge Semin  * multiplications and divisions are made so to have a result of the operations
6087976ce2SSerge Semin  * within the integer numbers limit. In addition we need to translate the
6187976ce2SSerge Semin  * formulae to accept millidegrees of Celsius. Here what they look like after
6287976ce2SSerge Semin  * the alterations:
6387976ce2SSerge Semin  * N = (18322e-20*(T^4) + 2343e-13*(T^3) + 87018e-9*(T^2) + 39269e-3*T +
6487976ce2SSerge Semin  *     17204e2) / 1e4,
6587976ce2SSerge Semin  * T = -16743e-12*(D^4) + 81542e-9*(D^3) - 182010e-6*(D^2) + 310200e-3*D -
6687976ce2SSerge Semin  *     48380,
6787976ce2SSerge Semin  * where T = [-48380, 147438] mC and N = [0, 1023].
6887976ce2SSerge Semin  */
69e0daf1a6SMichael Walle static const struct polynomial __maybe_unused poly_temp_to_N = {
7087976ce2SSerge Semin 	.total_divider = 10000,
7187976ce2SSerge Semin 	.terms = {
7287976ce2SSerge Semin 		{4, 18322, 10000, 10000},
7387976ce2SSerge Semin 		{3, 2343, 10000, 10},
7487976ce2SSerge Semin 		{2, 87018, 10000, 10},
7587976ce2SSerge Semin 		{1, 39269, 1000, 1},
7687976ce2SSerge Semin 		{0, 1720400, 1, 1}
7787976ce2SSerge Semin 	}
7887976ce2SSerge Semin };
7987976ce2SSerge Semin 
80e0daf1a6SMichael Walle static const struct polynomial poly_N_to_temp = {
8187976ce2SSerge Semin 	.total_divider = 1,
8287976ce2SSerge Semin 	.terms = {
8387976ce2SSerge Semin 		{4, -16743, 1000, 1},
8487976ce2SSerge Semin 		{3, 81542, 1000, 1},
8587976ce2SSerge Semin 		{2, -182010, 1000, 1},
8687976ce2SSerge Semin 		{1, 310200, 1000, 1},
8787976ce2SSerge Semin 		{0, -48380, 1, 1}
8887976ce2SSerge Semin 	}
8987976ce2SSerge Semin };
9087976ce2SSerge Semin 
9187976ce2SSerge Semin /*
9287976ce2SSerge Semin  * Similar alterations are performed for the voltage conversion equations.
9387976ce2SSerge Semin  * The original formulae are:
9487976ce2SSerge Semin  * N = 1.8658e3*V - 1.1572e3,
9587976ce2SSerge Semin  * V = (N + 1.1572e3) / 1.8658e3,
9687976ce2SSerge Semin  * where V = [0.620, 1.168] V and N = [0, 1023].
9787976ce2SSerge Semin  * After the optimization they looks as follows:
9887976ce2SSerge Semin  * N = (18658e-3*V - 11572) / 10,
9987976ce2SSerge Semin  * V = N * 10^5 / 18658 + 11572 * 10^4 / 18658.
10087976ce2SSerge Semin  */
101e0daf1a6SMichael Walle static const struct polynomial __maybe_unused poly_volt_to_N = {
10287976ce2SSerge Semin 	.total_divider = 10,
10387976ce2SSerge Semin 	.terms = {
10487976ce2SSerge Semin 		{1, 18658, 1000, 1},
10587976ce2SSerge Semin 		{0, -11572, 1, 1}
10687976ce2SSerge Semin 	}
10787976ce2SSerge Semin };
10887976ce2SSerge Semin 
109e0daf1a6SMichael Walle static const struct polynomial poly_N_to_volt = {
11087976ce2SSerge Semin 	.total_divider = 10,
11187976ce2SSerge Semin 	.terms = {
11287976ce2SSerge Semin 		{1, 100000, 18658, 1},
11387976ce2SSerge Semin 		{0, 115720000, 1, 18658}
11487976ce2SSerge Semin 	}
11587976ce2SSerge Semin };
11687976ce2SSerge Semin 
pvt_update(void __iomem * reg,u32 mask,u32 data)11787976ce2SSerge Semin static inline u32 pvt_update(void __iomem *reg, u32 mask, u32 data)
11887976ce2SSerge Semin {
11987976ce2SSerge Semin 	u32 old;
12087976ce2SSerge Semin 
12187976ce2SSerge Semin 	old = readl_relaxed(reg);
12287976ce2SSerge Semin 	writel((old & ~mask) | (data & mask), reg);
12387976ce2SSerge Semin 
12487976ce2SSerge Semin 	return old & mask;
12587976ce2SSerge Semin }
12687976ce2SSerge Semin 
12787976ce2SSerge Semin /*
12887976ce2SSerge Semin  * Baikal-T1 PVT mode can be updated only when the controller is disabled.
12987976ce2SSerge Semin  * So first we disable it, then set the new mode together with the controller
13087976ce2SSerge Semin  * getting back enabled. The same concerns the temperature trim and
13187976ce2SSerge Semin  * measurements timeout. If it is necessary the interface mutex is supposed
13287976ce2SSerge Semin  * to be locked at the time the operations are performed.
13387976ce2SSerge Semin  */
pvt_set_mode(struct pvt_hwmon * pvt,u32 mode)13487976ce2SSerge Semin static inline void pvt_set_mode(struct pvt_hwmon *pvt, u32 mode)
13587976ce2SSerge Semin {
13687976ce2SSerge Semin 	u32 old;
13787976ce2SSerge Semin 
13887976ce2SSerge Semin 	mode = FIELD_PREP(PVT_CTRL_MODE_MASK, mode);
13987976ce2SSerge Semin 
14087976ce2SSerge Semin 	old = pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
14187976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_MODE_MASK | PVT_CTRL_EN,
14287976ce2SSerge Semin 		   mode | old);
14387976ce2SSerge Semin }
14487976ce2SSerge Semin 
pvt_calc_trim(long temp)14587976ce2SSerge Semin static inline u32 pvt_calc_trim(long temp)
14687976ce2SSerge Semin {
14787976ce2SSerge Semin 	temp = clamp_val(temp, 0, PVT_TRIM_TEMP);
14887976ce2SSerge Semin 
14987976ce2SSerge Semin 	return DIV_ROUND_UP(temp, PVT_TRIM_STEP);
15087976ce2SSerge Semin }
15187976ce2SSerge Semin 
pvt_set_trim(struct pvt_hwmon * pvt,u32 trim)15287976ce2SSerge Semin static inline void pvt_set_trim(struct pvt_hwmon *pvt, u32 trim)
15387976ce2SSerge Semin {
15487976ce2SSerge Semin 	u32 old;
15587976ce2SSerge Semin 
15687976ce2SSerge Semin 	trim = FIELD_PREP(PVT_CTRL_TRIM_MASK, trim);
15787976ce2SSerge Semin 
15887976ce2SSerge Semin 	old = pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
15987976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_TRIM_MASK | PVT_CTRL_EN,
16087976ce2SSerge Semin 		   trim | old);
16187976ce2SSerge Semin }
16287976ce2SSerge Semin 
pvt_set_tout(struct pvt_hwmon * pvt,u32 tout)16387976ce2SSerge Semin static inline void pvt_set_tout(struct pvt_hwmon *pvt, u32 tout)
16487976ce2SSerge Semin {
16587976ce2SSerge Semin 	u32 old;
16687976ce2SSerge Semin 
16787976ce2SSerge Semin 	old = pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
16887976ce2SSerge Semin 	writel(tout, pvt->regs + PVT_TTIMEOUT);
16987976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, old);
17087976ce2SSerge Semin }
17187976ce2SSerge Semin 
17287976ce2SSerge Semin /*
17387976ce2SSerge Semin  * This driver can optionally provide the hwmon alarms for each sensor the PVT
17487976ce2SSerge Semin  * controller supports. The alarms functionality is made compile-time
17587976ce2SSerge Semin  * configurable due to the hardware interface implementation peculiarity
17687976ce2SSerge Semin  * described further in this comment. So in case if alarms are unnecessary in
17787976ce2SSerge Semin  * your system design it's recommended to have them disabled to prevent the PVT
17887976ce2SSerge Semin  * IRQs being periodically raised to get the data cache/alarms status up to
17987976ce2SSerge Semin  * date.
18087976ce2SSerge Semin  *
18187976ce2SSerge Semin  * Baikal-T1 PVT embedded controller is based on the Analog Bits PVT sensor,
18287976ce2SSerge Semin  * but is equipped with a dedicated control wrapper. It exposes the PVT
18387976ce2SSerge Semin  * sub-block registers space via the APB3 bus. In addition the wrapper provides
18487976ce2SSerge Semin  * a common interrupt vector of the sensors conversion completion events and
18587976ce2SSerge Semin  * threshold value alarms. Alas the wrapper interface hasn't been fully thought
18687976ce2SSerge Semin  * through. There is only one sensor can be activated at a time, for which the
18787976ce2SSerge Semin  * thresholds comparator is enabled right after the data conversion is
18887976ce2SSerge Semin  * completed. Due to this if alarms need to be implemented for all available
18987976ce2SSerge Semin  * sensors we can't just set the thresholds and enable the interrupts. We need
19087976ce2SSerge Semin  * to enable the sensors one after another and let the controller to detect
19187976ce2SSerge Semin  * the alarms by itself at each conversion. This also makes pointless to handle
19287976ce2SSerge Semin  * the alarms interrupts, since in occasion they happen synchronously with
19387976ce2SSerge Semin  * data conversion completion. The best driver design would be to have the
19487976ce2SSerge Semin  * completion interrupts enabled only and keep the converted value in the
19587976ce2SSerge Semin  * driver data cache. This solution is implemented if hwmon alarms are enabled
19687976ce2SSerge Semin  * in this driver. In case if the alarms are disabled, the conversion is
19787976ce2SSerge Semin  * performed on demand at the time a sensors input file is read.
19887976ce2SSerge Semin  */
19987976ce2SSerge Semin 
20087976ce2SSerge Semin #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
20187976ce2SSerge Semin 
20287976ce2SSerge Semin #define pvt_hard_isr NULL
20387976ce2SSerge Semin 
pvt_soft_isr(int irq,void * data)20487976ce2SSerge Semin static irqreturn_t pvt_soft_isr(int irq, void *data)
20587976ce2SSerge Semin {
20687976ce2SSerge Semin 	const struct pvt_sensor_info *info;
20787976ce2SSerge Semin 	struct pvt_hwmon *pvt = data;
20887976ce2SSerge Semin 	struct pvt_cache *cache;
20987976ce2SSerge Semin 	u32 val, thres_sts, old;
21087976ce2SSerge Semin 
21187976ce2SSerge Semin 	/*
21287976ce2SSerge Semin 	 * DVALID bit will be cleared by reading the data. We need to save the
21387976ce2SSerge Semin 	 * status before the next conversion happens. Threshold events will be
21487976ce2SSerge Semin 	 * handled a bit later.
21587976ce2SSerge Semin 	 */
21687976ce2SSerge Semin 	thres_sts = readl(pvt->regs + PVT_RAW_INTR_STAT);
21787976ce2SSerge Semin 
21887976ce2SSerge Semin 	/*
21987976ce2SSerge Semin 	 * Then lets recharge the PVT interface with the next sampling mode.
22087976ce2SSerge Semin 	 * Lock the interface mutex to serialize trim, timeouts and alarm
22187976ce2SSerge Semin 	 * thresholds settings.
22287976ce2SSerge Semin 	 */
22387976ce2SSerge Semin 	cache = &pvt->cache[pvt->sensor];
22487976ce2SSerge Semin 	info = &pvt_info[pvt->sensor];
22587976ce2SSerge Semin 	pvt->sensor = (pvt->sensor == PVT_SENSOR_LAST) ?
22687976ce2SSerge Semin 		      PVT_SENSOR_FIRST : (pvt->sensor + 1);
22787976ce2SSerge Semin 
22887976ce2SSerge Semin 	/*
22987976ce2SSerge Semin 	 * For some reason we have to mask the interrupt before changing the
23087976ce2SSerge Semin 	 * mode, otherwise sometimes the temperature mode doesn't get
23187976ce2SSerge Semin 	 * activated even though the actual mode in the ctrl register
23287976ce2SSerge Semin 	 * corresponds to one. Then we read the data. By doing so we also
23387976ce2SSerge Semin 	 * recharge the data conversion. After this the mode corresponding
23487976ce2SSerge Semin 	 * to the next sensor in the row is set. Finally we enable the
23587976ce2SSerge Semin 	 * interrupts back.
23687976ce2SSerge Semin 	 */
23787976ce2SSerge Semin 	mutex_lock(&pvt->iface_mtx);
23887976ce2SSerge Semin 
23987976ce2SSerge Semin 	old = pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID,
24087976ce2SSerge Semin 			 PVT_INTR_DVALID);
24187976ce2SSerge Semin 
24287976ce2SSerge Semin 	val = readl(pvt->regs + PVT_DATA);
24387976ce2SSerge Semin 
24487976ce2SSerge Semin 	pvt_set_mode(pvt, pvt_info[pvt->sensor].mode);
24587976ce2SSerge Semin 
24687976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, old);
24787976ce2SSerge Semin 
24887976ce2SSerge Semin 	mutex_unlock(&pvt->iface_mtx);
24987976ce2SSerge Semin 
25087976ce2SSerge Semin 	/*
25187976ce2SSerge Semin 	 * We can now update the data cache with data just retrieved from the
25287976ce2SSerge Semin 	 * sensor. Lock write-seqlock to make sure the reader has a coherent
25387976ce2SSerge Semin 	 * data.
25487976ce2SSerge Semin 	 */
25587976ce2SSerge Semin 	write_seqlock(&cache->data_seqlock);
25687976ce2SSerge Semin 
25787976ce2SSerge Semin 	cache->data = FIELD_GET(PVT_DATA_DATA_MASK, val);
25887976ce2SSerge Semin 
25987976ce2SSerge Semin 	write_sequnlock(&cache->data_seqlock);
26087976ce2SSerge Semin 
26187976ce2SSerge Semin 	/*
26287976ce2SSerge Semin 	 * While PVT core is doing the next mode data conversion, we'll check
26387976ce2SSerge Semin 	 * whether the alarms were triggered for the current sensor. Note that
26487976ce2SSerge Semin 	 * according to the documentation only one threshold IRQ status can be
26587976ce2SSerge Semin 	 * set at a time, that's why if-else statement is utilized.
26687976ce2SSerge Semin 	 */
26787976ce2SSerge Semin 	if ((thres_sts & info->thres_sts_lo) ^ cache->thres_sts_lo) {
26887976ce2SSerge Semin 		WRITE_ONCE(cache->thres_sts_lo, thres_sts & info->thres_sts_lo);
26987976ce2SSerge Semin 		hwmon_notify_event(pvt->hwmon, info->type, info->attr_min_alarm,
27087976ce2SSerge Semin 				   info->channel);
27187976ce2SSerge Semin 	} else if ((thres_sts & info->thres_sts_hi) ^ cache->thres_sts_hi) {
27287976ce2SSerge Semin 		WRITE_ONCE(cache->thres_sts_hi, thres_sts & info->thres_sts_hi);
27387976ce2SSerge Semin 		hwmon_notify_event(pvt->hwmon, info->type, info->attr_max_alarm,
27487976ce2SSerge Semin 				   info->channel);
27587976ce2SSerge Semin 	}
27687976ce2SSerge Semin 
27787976ce2SSerge Semin 	return IRQ_HANDLED;
27887976ce2SSerge Semin }
27987976ce2SSerge Semin 
pvt_limit_is_visible(enum pvt_sensor_type type)28026797d8bSGuenter Roeck static inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type)
28187976ce2SSerge Semin {
28287976ce2SSerge Semin 	return 0644;
28387976ce2SSerge Semin }
28487976ce2SSerge Semin 
pvt_alarm_is_visible(enum pvt_sensor_type type)28526797d8bSGuenter Roeck static inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type)
28687976ce2SSerge Semin {
28787976ce2SSerge Semin 	return 0444;
28887976ce2SSerge Semin }
28987976ce2SSerge Semin 
pvt_read_data(struct pvt_hwmon * pvt,enum pvt_sensor_type type,long * val)29087976ce2SSerge Semin static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
29187976ce2SSerge Semin 			 long *val)
29287976ce2SSerge Semin {
29387976ce2SSerge Semin 	struct pvt_cache *cache = &pvt->cache[type];
29487976ce2SSerge Semin 	unsigned int seq;
29587976ce2SSerge Semin 	u32 data;
29687976ce2SSerge Semin 
29787976ce2SSerge Semin 	do {
29887976ce2SSerge Semin 		seq = read_seqbegin(&cache->data_seqlock);
29987976ce2SSerge Semin 		data = cache->data;
30087976ce2SSerge Semin 	} while (read_seqretry(&cache->data_seqlock, seq));
30187976ce2SSerge Semin 
30287976ce2SSerge Semin 	if (type == PVT_TEMP)
303e0daf1a6SMichael Walle 		*val = polynomial_calc(&poly_N_to_temp, data);
30487976ce2SSerge Semin 	else
305e0daf1a6SMichael Walle 		*val = polynomial_calc(&poly_N_to_volt, data);
30687976ce2SSerge Semin 
30787976ce2SSerge Semin 	return 0;
30887976ce2SSerge Semin }
30987976ce2SSerge Semin 
pvt_read_limit(struct pvt_hwmon * pvt,enum pvt_sensor_type type,bool is_low,long * val)31087976ce2SSerge Semin static int pvt_read_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
31187976ce2SSerge Semin 			  bool is_low, long *val)
31287976ce2SSerge Semin {
31387976ce2SSerge Semin 	u32 data;
31487976ce2SSerge Semin 
31587976ce2SSerge Semin 	/* No need in serialization, since it is just read from MMIO. */
31687976ce2SSerge Semin 	data = readl(pvt->regs + pvt_info[type].thres_base);
31787976ce2SSerge Semin 
31887976ce2SSerge Semin 	if (is_low)
31987976ce2SSerge Semin 		data = FIELD_GET(PVT_THRES_LO_MASK, data);
32087976ce2SSerge Semin 	else
32187976ce2SSerge Semin 		data = FIELD_GET(PVT_THRES_HI_MASK, data);
32287976ce2SSerge Semin 
32387976ce2SSerge Semin 	if (type == PVT_TEMP)
324e0daf1a6SMichael Walle 		*val = polynomial_calc(&poly_N_to_temp, data);
32587976ce2SSerge Semin 	else
326e0daf1a6SMichael Walle 		*val = polynomial_calc(&poly_N_to_volt, data);
32787976ce2SSerge Semin 
32887976ce2SSerge Semin 	return 0;
32987976ce2SSerge Semin }
33087976ce2SSerge Semin 
pvt_write_limit(struct pvt_hwmon * pvt,enum pvt_sensor_type type,bool is_low,long val)33187976ce2SSerge Semin static int pvt_write_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
33287976ce2SSerge Semin 			   bool is_low, long val)
33387976ce2SSerge Semin {
33487976ce2SSerge Semin 	u32 data, limit, mask;
33587976ce2SSerge Semin 	int ret;
33687976ce2SSerge Semin 
33787976ce2SSerge Semin 	if (type == PVT_TEMP) {
33887976ce2SSerge Semin 		val = clamp(val, PVT_TEMP_MIN, PVT_TEMP_MAX);
339e0daf1a6SMichael Walle 		data = polynomial_calc(&poly_temp_to_N, val);
34087976ce2SSerge Semin 	} else {
34187976ce2SSerge Semin 		val = clamp(val, PVT_VOLT_MIN, PVT_VOLT_MAX);
342e0daf1a6SMichael Walle 		data = polynomial_calc(&poly_volt_to_N, val);
34387976ce2SSerge Semin 	}
34487976ce2SSerge Semin 
34587976ce2SSerge Semin 	/* Serialize limit update, since a part of the register is changed. */
34687976ce2SSerge Semin 	ret = mutex_lock_interruptible(&pvt->iface_mtx);
34787976ce2SSerge Semin 	if (ret)
34887976ce2SSerge Semin 		return ret;
34987976ce2SSerge Semin 
35087976ce2SSerge Semin 	/* Make sure the upper and lower ranges don't intersect. */
35187976ce2SSerge Semin 	limit = readl(pvt->regs + pvt_info[type].thres_base);
35287976ce2SSerge Semin 	if (is_low) {
35387976ce2SSerge Semin 		limit = FIELD_GET(PVT_THRES_HI_MASK, limit);
35487976ce2SSerge Semin 		data = clamp_val(data, PVT_DATA_MIN, limit);
35587976ce2SSerge Semin 		data = FIELD_PREP(PVT_THRES_LO_MASK, data);
35687976ce2SSerge Semin 		mask = PVT_THRES_LO_MASK;
35787976ce2SSerge Semin 	} else {
35887976ce2SSerge Semin 		limit = FIELD_GET(PVT_THRES_LO_MASK, limit);
35987976ce2SSerge Semin 		data = clamp_val(data, limit, PVT_DATA_MAX);
36087976ce2SSerge Semin 		data = FIELD_PREP(PVT_THRES_HI_MASK, data);
36187976ce2SSerge Semin 		mask = PVT_THRES_HI_MASK;
36287976ce2SSerge Semin 	}
36387976ce2SSerge Semin 
36487976ce2SSerge Semin 	pvt_update(pvt->regs + pvt_info[type].thres_base, mask, data);
36587976ce2SSerge Semin 
36687976ce2SSerge Semin 	mutex_unlock(&pvt->iface_mtx);
36787976ce2SSerge Semin 
36887976ce2SSerge Semin 	return 0;
36987976ce2SSerge Semin }
37087976ce2SSerge Semin 
pvt_read_alarm(struct pvt_hwmon * pvt,enum pvt_sensor_type type,bool is_low,long * val)37187976ce2SSerge Semin static int pvt_read_alarm(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
37287976ce2SSerge Semin 			  bool is_low, long *val)
37387976ce2SSerge Semin {
37487976ce2SSerge Semin 	if (is_low)
37587976ce2SSerge Semin 		*val = !!READ_ONCE(pvt->cache[type].thres_sts_lo);
37687976ce2SSerge Semin 	else
37787976ce2SSerge Semin 		*val = !!READ_ONCE(pvt->cache[type].thres_sts_hi);
37887976ce2SSerge Semin 
37987976ce2SSerge Semin 	return 0;
38087976ce2SSerge Semin }
38187976ce2SSerge Semin 
382edcde8cfSKrzysztof Kozlowski static const struct hwmon_channel_info * const pvt_channel_info[] = {
38387976ce2SSerge Semin 	HWMON_CHANNEL_INFO(chip,
38487976ce2SSerge Semin 			   HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL),
38587976ce2SSerge Semin 	HWMON_CHANNEL_INFO(temp,
38687976ce2SSerge Semin 			   HWMON_T_INPUT | HWMON_T_TYPE | HWMON_T_LABEL |
38787976ce2SSerge Semin 			   HWMON_T_MIN | HWMON_T_MIN_ALARM |
38887976ce2SSerge Semin 			   HWMON_T_MAX | HWMON_T_MAX_ALARM |
38987976ce2SSerge Semin 			   HWMON_T_OFFSET),
39087976ce2SSerge Semin 	HWMON_CHANNEL_INFO(in,
39187976ce2SSerge Semin 			   HWMON_I_INPUT | HWMON_I_LABEL |
39287976ce2SSerge Semin 			   HWMON_I_MIN | HWMON_I_MIN_ALARM |
39387976ce2SSerge Semin 			   HWMON_I_MAX | HWMON_I_MAX_ALARM,
39487976ce2SSerge Semin 			   HWMON_I_INPUT | HWMON_I_LABEL |
39587976ce2SSerge Semin 			   HWMON_I_MIN | HWMON_I_MIN_ALARM |
39687976ce2SSerge Semin 			   HWMON_I_MAX | HWMON_I_MAX_ALARM,
39787976ce2SSerge Semin 			   HWMON_I_INPUT | HWMON_I_LABEL |
39887976ce2SSerge Semin 			   HWMON_I_MIN | HWMON_I_MIN_ALARM |
39987976ce2SSerge Semin 			   HWMON_I_MAX | HWMON_I_MAX_ALARM,
40087976ce2SSerge Semin 			   HWMON_I_INPUT | HWMON_I_LABEL |
40187976ce2SSerge Semin 			   HWMON_I_MIN | HWMON_I_MIN_ALARM |
40287976ce2SSerge Semin 			   HWMON_I_MAX | HWMON_I_MAX_ALARM),
40387976ce2SSerge Semin 	NULL
40487976ce2SSerge Semin };
40587976ce2SSerge Semin 
40687976ce2SSerge Semin #else /* !CONFIG_SENSORS_BT1_PVT_ALARMS */
40787976ce2SSerge Semin 
pvt_hard_isr(int irq,void * data)40887976ce2SSerge Semin static irqreturn_t pvt_hard_isr(int irq, void *data)
40987976ce2SSerge Semin {
41087976ce2SSerge Semin 	struct pvt_hwmon *pvt = data;
41187976ce2SSerge Semin 	struct pvt_cache *cache;
41287976ce2SSerge Semin 	u32 val;
41387976ce2SSerge Semin 
41487976ce2SSerge Semin 	/*
41587976ce2SSerge Semin 	 * Mask the DVALID interrupt so after exiting from the handler a
41687976ce2SSerge Semin 	 * repeated conversion wouldn't happen.
41787976ce2SSerge Semin 	 */
41887976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID,
41987976ce2SSerge Semin 		   PVT_INTR_DVALID);
42087976ce2SSerge Semin 
42187976ce2SSerge Semin 	/*
42287976ce2SSerge Semin 	 * Nothing special for alarm-less driver. Just read the data, update
42387976ce2SSerge Semin 	 * the cache and notify a waiter of this event.
42487976ce2SSerge Semin 	 */
42587976ce2SSerge Semin 	val = readl(pvt->regs + PVT_DATA);
42687976ce2SSerge Semin 	if (!(val & PVT_DATA_VALID)) {
42787976ce2SSerge Semin 		dev_err(pvt->dev, "Got IRQ when data isn't valid\n");
42887976ce2SSerge Semin 		return IRQ_HANDLED;
42987976ce2SSerge Semin 	}
43087976ce2SSerge Semin 
43187976ce2SSerge Semin 	cache = &pvt->cache[pvt->sensor];
43287976ce2SSerge Semin 
43387976ce2SSerge Semin 	WRITE_ONCE(cache->data, FIELD_GET(PVT_DATA_DATA_MASK, val));
43487976ce2SSerge Semin 
43587976ce2SSerge Semin 	complete(&cache->conversion);
43687976ce2SSerge Semin 
43787976ce2SSerge Semin 	return IRQ_HANDLED;
43887976ce2SSerge Semin }
43987976ce2SSerge Semin 
44087976ce2SSerge Semin #define pvt_soft_isr NULL
44187976ce2SSerge Semin 
pvt_limit_is_visible(enum pvt_sensor_type type)44226797d8bSGuenter Roeck static inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type)
44387976ce2SSerge Semin {
44487976ce2SSerge Semin 	return 0;
44587976ce2SSerge Semin }
44687976ce2SSerge Semin 
pvt_alarm_is_visible(enum pvt_sensor_type type)44726797d8bSGuenter Roeck static inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type)
44887976ce2SSerge Semin {
44987976ce2SSerge Semin 	return 0;
45087976ce2SSerge Semin }
45187976ce2SSerge Semin 
pvt_read_data(struct pvt_hwmon * pvt,enum pvt_sensor_type type,long * val)45287976ce2SSerge Semin static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
45387976ce2SSerge Semin 			 long *val)
45487976ce2SSerge Semin {
45587976ce2SSerge Semin 	struct pvt_cache *cache = &pvt->cache[type];
4560ffd21d5SSerge Semin 	unsigned long timeout;
45787976ce2SSerge Semin 	u32 data;
45887976ce2SSerge Semin 	int ret;
45987976ce2SSerge Semin 
46087976ce2SSerge Semin 	/*
46187976ce2SSerge Semin 	 * Lock PVT conversion interface until data cache is updated. The
46287976ce2SSerge Semin 	 * data read procedure is following: set the requested PVT sensor
46387976ce2SSerge Semin 	 * mode, enable IRQ and conversion, wait until conversion is finished,
46487976ce2SSerge Semin 	 * then disable conversion and IRQ, and read the cached data.
46587976ce2SSerge Semin 	 */
46687976ce2SSerge Semin 	ret = mutex_lock_interruptible(&pvt->iface_mtx);
46787976ce2SSerge Semin 	if (ret)
46887976ce2SSerge Semin 		return ret;
46987976ce2SSerge Semin 
47087976ce2SSerge Semin 	pvt->sensor = type;
47187976ce2SSerge Semin 	pvt_set_mode(pvt, pvt_info[type].mode);
47287976ce2SSerge Semin 
47387976ce2SSerge Semin 	/*
47487976ce2SSerge Semin 	 * Unmask the DVALID interrupt and enable the sensors conversions.
47587976ce2SSerge Semin 	 * Do the reverse procedure when conversion is done.
47687976ce2SSerge Semin 	 */
47787976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, 0);
47887976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN);
47987976ce2SSerge Semin 
4800ffd21d5SSerge Semin 	/*
4810ffd21d5SSerge Semin 	 * Wait with timeout since in case if the sensor is suddenly powered
4820ffd21d5SSerge Semin 	 * down the request won't be completed and the caller will hang up on
4830ffd21d5SSerge Semin 	 * this procedure until the power is back up again. Multiply the
4840ffd21d5SSerge Semin 	 * timeout by the factor of two to prevent a false timeout.
4850ffd21d5SSerge Semin 	 */
4860ffd21d5SSerge Semin 	timeout = 2 * usecs_to_jiffies(ktime_to_us(pvt->timeout));
4870ffd21d5SSerge Semin 	ret = wait_for_completion_timeout(&cache->conversion, timeout);
48887976ce2SSerge Semin 
48987976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
49087976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID,
49187976ce2SSerge Semin 		   PVT_INTR_DVALID);
49287976ce2SSerge Semin 
49387976ce2SSerge Semin 	data = READ_ONCE(cache->data);
49487976ce2SSerge Semin 
49587976ce2SSerge Semin 	mutex_unlock(&pvt->iface_mtx);
49687976ce2SSerge Semin 
4970ffd21d5SSerge Semin 	if (!ret)
4980ffd21d5SSerge Semin 		return -ETIMEDOUT;
4990ffd21d5SSerge Semin 
50087976ce2SSerge Semin 	if (type == PVT_TEMP)
501e0daf1a6SMichael Walle 		*val = polynomial_calc(&poly_N_to_temp, data);
50287976ce2SSerge Semin 	else
503e0daf1a6SMichael Walle 		*val = polynomial_calc(&poly_N_to_volt, data);
50487976ce2SSerge Semin 
50587976ce2SSerge Semin 	return 0;
50687976ce2SSerge Semin }
50787976ce2SSerge Semin 
pvt_read_limit(struct pvt_hwmon * pvt,enum pvt_sensor_type type,bool is_low,long * val)50887976ce2SSerge Semin static int pvt_read_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
50987976ce2SSerge Semin 			  bool is_low, long *val)
51087976ce2SSerge Semin {
51187976ce2SSerge Semin 	return -EOPNOTSUPP;
51287976ce2SSerge Semin }
51387976ce2SSerge Semin 
pvt_write_limit(struct pvt_hwmon * pvt,enum pvt_sensor_type type,bool is_low,long val)51487976ce2SSerge Semin static int pvt_write_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
51587976ce2SSerge Semin 			   bool is_low, long val)
51687976ce2SSerge Semin {
51787976ce2SSerge Semin 	return -EOPNOTSUPP;
51887976ce2SSerge Semin }
51987976ce2SSerge Semin 
pvt_read_alarm(struct pvt_hwmon * pvt,enum pvt_sensor_type type,bool is_low,long * val)52087976ce2SSerge Semin static int pvt_read_alarm(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
52187976ce2SSerge Semin 			  bool is_low, long *val)
52287976ce2SSerge Semin {
52387976ce2SSerge Semin 	return -EOPNOTSUPP;
52487976ce2SSerge Semin }
52587976ce2SSerge Semin 
526edcde8cfSKrzysztof Kozlowski static const struct hwmon_channel_info * const pvt_channel_info[] = {
52787976ce2SSerge Semin 	HWMON_CHANNEL_INFO(chip,
52887976ce2SSerge Semin 			   HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL),
52987976ce2SSerge Semin 	HWMON_CHANNEL_INFO(temp,
53087976ce2SSerge Semin 			   HWMON_T_INPUT | HWMON_T_TYPE | HWMON_T_LABEL |
53187976ce2SSerge Semin 			   HWMON_T_OFFSET),
53287976ce2SSerge Semin 	HWMON_CHANNEL_INFO(in,
53387976ce2SSerge Semin 			   HWMON_I_INPUT | HWMON_I_LABEL,
53487976ce2SSerge Semin 			   HWMON_I_INPUT | HWMON_I_LABEL,
53587976ce2SSerge Semin 			   HWMON_I_INPUT | HWMON_I_LABEL,
53687976ce2SSerge Semin 			   HWMON_I_INPUT | HWMON_I_LABEL),
53787976ce2SSerge Semin 	NULL
53887976ce2SSerge Semin };
53987976ce2SSerge Semin 
54087976ce2SSerge Semin #endif /* !CONFIG_SENSORS_BT1_PVT_ALARMS */
54187976ce2SSerge Semin 
pvt_hwmon_channel_is_valid(enum hwmon_sensor_types type,int ch)54287976ce2SSerge Semin static inline bool pvt_hwmon_channel_is_valid(enum hwmon_sensor_types type,
54387976ce2SSerge Semin 					      int ch)
54487976ce2SSerge Semin {
54587976ce2SSerge Semin 	switch (type) {
54687976ce2SSerge Semin 	case hwmon_temp:
54787976ce2SSerge Semin 		if (ch < 0 || ch >= PVT_TEMP_CHS)
54887976ce2SSerge Semin 			return false;
54987976ce2SSerge Semin 		break;
55087976ce2SSerge Semin 	case hwmon_in:
55187976ce2SSerge Semin 		if (ch < 0 || ch >= PVT_VOLT_CHS)
55287976ce2SSerge Semin 			return false;
55387976ce2SSerge Semin 		break;
55487976ce2SSerge Semin 	default:
55587976ce2SSerge Semin 		break;
55687976ce2SSerge Semin 	}
55787976ce2SSerge Semin 
55887976ce2SSerge Semin 	/* The rest of the types are independent from the channel number. */
55987976ce2SSerge Semin 	return true;
56087976ce2SSerge Semin }
56187976ce2SSerge Semin 
pvt_hwmon_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int ch)56287976ce2SSerge Semin static umode_t pvt_hwmon_is_visible(const void *data,
56387976ce2SSerge Semin 				    enum hwmon_sensor_types type,
56487976ce2SSerge Semin 				    u32 attr, int ch)
56587976ce2SSerge Semin {
56687976ce2SSerge Semin 	if (!pvt_hwmon_channel_is_valid(type, ch))
56787976ce2SSerge Semin 		return 0;
56887976ce2SSerge Semin 
56987976ce2SSerge Semin 	switch (type) {
57087976ce2SSerge Semin 	case hwmon_chip:
57187976ce2SSerge Semin 		switch (attr) {
57287976ce2SSerge Semin 		case hwmon_chip_update_interval:
57387976ce2SSerge Semin 			return 0644;
57487976ce2SSerge Semin 		}
57587976ce2SSerge Semin 		break;
57687976ce2SSerge Semin 	case hwmon_temp:
57787976ce2SSerge Semin 		switch (attr) {
57887976ce2SSerge Semin 		case hwmon_temp_input:
57987976ce2SSerge Semin 		case hwmon_temp_type:
58087976ce2SSerge Semin 		case hwmon_temp_label:
58187976ce2SSerge Semin 			return 0444;
58287976ce2SSerge Semin 		case hwmon_temp_min:
58387976ce2SSerge Semin 		case hwmon_temp_max:
58487976ce2SSerge Semin 			return pvt_limit_is_visible(ch);
58587976ce2SSerge Semin 		case hwmon_temp_min_alarm:
58687976ce2SSerge Semin 		case hwmon_temp_max_alarm:
58787976ce2SSerge Semin 			return pvt_alarm_is_visible(ch);
58887976ce2SSerge Semin 		case hwmon_temp_offset:
58987976ce2SSerge Semin 			return 0644;
59087976ce2SSerge Semin 		}
59187976ce2SSerge Semin 		break;
59287976ce2SSerge Semin 	case hwmon_in:
59387976ce2SSerge Semin 		switch (attr) {
59487976ce2SSerge Semin 		case hwmon_in_input:
59587976ce2SSerge Semin 		case hwmon_in_label:
59687976ce2SSerge Semin 			return 0444;
59787976ce2SSerge Semin 		case hwmon_in_min:
59887976ce2SSerge Semin 		case hwmon_in_max:
59987976ce2SSerge Semin 			return pvt_limit_is_visible(PVT_VOLT + ch);
60087976ce2SSerge Semin 		case hwmon_in_min_alarm:
60187976ce2SSerge Semin 		case hwmon_in_max_alarm:
60287976ce2SSerge Semin 			return pvt_alarm_is_visible(PVT_VOLT + ch);
60387976ce2SSerge Semin 		}
60487976ce2SSerge Semin 		break;
60587976ce2SSerge Semin 	default:
60687976ce2SSerge Semin 		break;
60787976ce2SSerge Semin 	}
60887976ce2SSerge Semin 
60987976ce2SSerge Semin 	return 0;
61087976ce2SSerge Semin }
61187976ce2SSerge Semin 
pvt_read_trim(struct pvt_hwmon * pvt,long * val)61287976ce2SSerge Semin static int pvt_read_trim(struct pvt_hwmon *pvt, long *val)
61387976ce2SSerge Semin {
61487976ce2SSerge Semin 	u32 data;
61587976ce2SSerge Semin 
61687976ce2SSerge Semin 	data = readl(pvt->regs + PVT_CTRL);
61787976ce2SSerge Semin 	*val = FIELD_GET(PVT_CTRL_TRIM_MASK, data) * PVT_TRIM_STEP;
61887976ce2SSerge Semin 
61987976ce2SSerge Semin 	return 0;
62087976ce2SSerge Semin }
62187976ce2SSerge Semin 
pvt_write_trim(struct pvt_hwmon * pvt,long val)62287976ce2SSerge Semin static int pvt_write_trim(struct pvt_hwmon *pvt, long val)
62387976ce2SSerge Semin {
62487976ce2SSerge Semin 	u32 trim;
62587976ce2SSerge Semin 	int ret;
62687976ce2SSerge Semin 
62787976ce2SSerge Semin 	/*
62887976ce2SSerge Semin 	 * Serialize trim update, since a part of the register is changed and
62987976ce2SSerge Semin 	 * the controller is supposed to be disabled during this operation.
63087976ce2SSerge Semin 	 */
63187976ce2SSerge Semin 	ret = mutex_lock_interruptible(&pvt->iface_mtx);
63287976ce2SSerge Semin 	if (ret)
63387976ce2SSerge Semin 		return ret;
63487976ce2SSerge Semin 
63587976ce2SSerge Semin 	trim = pvt_calc_trim(val);
63687976ce2SSerge Semin 	pvt_set_trim(pvt, trim);
63787976ce2SSerge Semin 
63887976ce2SSerge Semin 	mutex_unlock(&pvt->iface_mtx);
63987976ce2SSerge Semin 
64087976ce2SSerge Semin 	return 0;
64187976ce2SSerge Semin }
64287976ce2SSerge Semin 
pvt_read_timeout(struct pvt_hwmon * pvt,long * val)64387976ce2SSerge Semin static int pvt_read_timeout(struct pvt_hwmon *pvt, long *val)
64487976ce2SSerge Semin {
6450015503eSSerge Semin 	int ret;
64687976ce2SSerge Semin 
6470015503eSSerge Semin 	ret = mutex_lock_interruptible(&pvt->iface_mtx);
6480015503eSSerge Semin 	if (ret)
6490015503eSSerge Semin 		return ret;
65087976ce2SSerge Semin 
65187976ce2SSerge Semin 	/* Return the result in msec as hwmon sysfs interface requires. */
6520015503eSSerge Semin 	*val = ktime_to_ms(pvt->timeout);
6530015503eSSerge Semin 
6540015503eSSerge Semin 	mutex_unlock(&pvt->iface_mtx);
65587976ce2SSerge Semin 
65687976ce2SSerge Semin 	return 0;
65787976ce2SSerge Semin }
65887976ce2SSerge Semin 
pvt_write_timeout(struct pvt_hwmon * pvt,long val)65987976ce2SSerge Semin static int pvt_write_timeout(struct pvt_hwmon *pvt, long val)
66087976ce2SSerge Semin {
66187976ce2SSerge Semin 	unsigned long rate;
6620015503eSSerge Semin 	ktime_t kt, cache;
66387976ce2SSerge Semin 	u32 data;
66487976ce2SSerge Semin 	int ret;
66587976ce2SSerge Semin 
66687976ce2SSerge Semin 	rate = clk_get_rate(pvt->clks[PVT_CLOCK_REF].clk);
66787976ce2SSerge Semin 	if (!rate)
66887976ce2SSerge Semin 		return -ENODEV;
66987976ce2SSerge Semin 
67087976ce2SSerge Semin 	/*
67187976ce2SSerge Semin 	 * If alarms are enabled, the requested timeout must be divided
67287976ce2SSerge Semin 	 * between all available sensors to have the requested delay
67387976ce2SSerge Semin 	 * applicable to each individual sensor.
67487976ce2SSerge Semin 	 */
6750015503eSSerge Semin 	cache = kt = ms_to_ktime(val);
67687976ce2SSerge Semin #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
67787976ce2SSerge Semin 	kt = ktime_divns(kt, PVT_SENSORS_NUM);
67887976ce2SSerge Semin #endif
67987976ce2SSerge Semin 
68087976ce2SSerge Semin 	/*
68187976ce2SSerge Semin 	 * Subtract a constant lag, which always persists due to the limited
68287976ce2SSerge Semin 	 * PVT sampling rate. Make sure the timeout is not negative.
68387976ce2SSerge Semin 	 */
68487976ce2SSerge Semin 	kt = ktime_sub_ns(kt, PVT_TOUT_MIN);
68587976ce2SSerge Semin 	if (ktime_to_ns(kt) < 0)
68687976ce2SSerge Semin 		kt = ktime_set(0, 0);
68787976ce2SSerge Semin 
68887976ce2SSerge Semin 	/*
68987976ce2SSerge Semin 	 * Finally recalculate the timeout in terms of the reference clock
69087976ce2SSerge Semin 	 * period.
69187976ce2SSerge Semin 	 */
69287976ce2SSerge Semin 	data = ktime_divns(kt * rate, NSEC_PER_SEC);
69387976ce2SSerge Semin 
69487976ce2SSerge Semin 	/*
69587976ce2SSerge Semin 	 * Update the measurements delay, but lock the interface first, since
69687976ce2SSerge Semin 	 * we have to disable PVT in order to have the new delay actually
69787976ce2SSerge Semin 	 * updated.
69887976ce2SSerge Semin 	 */
69987976ce2SSerge Semin 	ret = mutex_lock_interruptible(&pvt->iface_mtx);
70087976ce2SSerge Semin 	if (ret)
70187976ce2SSerge Semin 		return ret;
70287976ce2SSerge Semin 
70387976ce2SSerge Semin 	pvt_set_tout(pvt, data);
7040015503eSSerge Semin 	pvt->timeout = cache;
70587976ce2SSerge Semin 
70687976ce2SSerge Semin 	mutex_unlock(&pvt->iface_mtx);
70787976ce2SSerge Semin 
70887976ce2SSerge Semin 	return 0;
70987976ce2SSerge Semin }
71087976ce2SSerge Semin 
pvt_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int ch,long * val)71187976ce2SSerge Semin static int pvt_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
71287976ce2SSerge Semin 			  u32 attr, int ch, long *val)
71387976ce2SSerge Semin {
71487976ce2SSerge Semin 	struct pvt_hwmon *pvt = dev_get_drvdata(dev);
71587976ce2SSerge Semin 
71687976ce2SSerge Semin 	if (!pvt_hwmon_channel_is_valid(type, ch))
71787976ce2SSerge Semin 		return -EINVAL;
71887976ce2SSerge Semin 
71987976ce2SSerge Semin 	switch (type) {
72087976ce2SSerge Semin 	case hwmon_chip:
72187976ce2SSerge Semin 		switch (attr) {
72287976ce2SSerge Semin 		case hwmon_chip_update_interval:
72387976ce2SSerge Semin 			return pvt_read_timeout(pvt, val);
72487976ce2SSerge Semin 		}
72587976ce2SSerge Semin 		break;
72687976ce2SSerge Semin 	case hwmon_temp:
72787976ce2SSerge Semin 		switch (attr) {
72887976ce2SSerge Semin 		case hwmon_temp_input:
72987976ce2SSerge Semin 			return pvt_read_data(pvt, ch, val);
73087976ce2SSerge Semin 		case hwmon_temp_type:
73187976ce2SSerge Semin 			*val = 1;
73287976ce2SSerge Semin 			return 0;
73387976ce2SSerge Semin 		case hwmon_temp_min:
73487976ce2SSerge Semin 			return pvt_read_limit(pvt, ch, true, val);
73587976ce2SSerge Semin 		case hwmon_temp_max:
73687976ce2SSerge Semin 			return pvt_read_limit(pvt, ch, false, val);
73787976ce2SSerge Semin 		case hwmon_temp_min_alarm:
73887976ce2SSerge Semin 			return pvt_read_alarm(pvt, ch, true, val);
73987976ce2SSerge Semin 		case hwmon_temp_max_alarm:
74087976ce2SSerge Semin 			return pvt_read_alarm(pvt, ch, false, val);
74187976ce2SSerge Semin 		case hwmon_temp_offset:
74287976ce2SSerge Semin 			return pvt_read_trim(pvt, val);
74387976ce2SSerge Semin 		}
74487976ce2SSerge Semin 		break;
74587976ce2SSerge Semin 	case hwmon_in:
74687976ce2SSerge Semin 		switch (attr) {
74787976ce2SSerge Semin 		case hwmon_in_input:
74887976ce2SSerge Semin 			return pvt_read_data(pvt, PVT_VOLT + ch, val);
74987976ce2SSerge Semin 		case hwmon_in_min:
75087976ce2SSerge Semin 			return pvt_read_limit(pvt, PVT_VOLT + ch, true, val);
75187976ce2SSerge Semin 		case hwmon_in_max:
75287976ce2SSerge Semin 			return pvt_read_limit(pvt, PVT_VOLT + ch, false, val);
75387976ce2SSerge Semin 		case hwmon_in_min_alarm:
75487976ce2SSerge Semin 			return pvt_read_alarm(pvt, PVT_VOLT + ch, true, val);
75587976ce2SSerge Semin 		case hwmon_in_max_alarm:
75687976ce2SSerge Semin 			return pvt_read_alarm(pvt, PVT_VOLT + ch, false, val);
75787976ce2SSerge Semin 		}
75887976ce2SSerge Semin 		break;
75987976ce2SSerge Semin 	default:
76087976ce2SSerge Semin 		break;
76187976ce2SSerge Semin 	}
76287976ce2SSerge Semin 
76387976ce2SSerge Semin 	return -EOPNOTSUPP;
76487976ce2SSerge Semin }
76587976ce2SSerge Semin 
pvt_hwmon_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int ch,const char ** str)76687976ce2SSerge Semin static int pvt_hwmon_read_string(struct device *dev,
76787976ce2SSerge Semin 				 enum hwmon_sensor_types type,
76887976ce2SSerge Semin 				 u32 attr, int ch, const char **str)
76987976ce2SSerge Semin {
77087976ce2SSerge Semin 	if (!pvt_hwmon_channel_is_valid(type, ch))
77187976ce2SSerge Semin 		return -EINVAL;
77287976ce2SSerge Semin 
77387976ce2SSerge Semin 	switch (type) {
77487976ce2SSerge Semin 	case hwmon_temp:
77587976ce2SSerge Semin 		switch (attr) {
77687976ce2SSerge Semin 		case hwmon_temp_label:
77787976ce2SSerge Semin 			*str = pvt_info[ch].label;
77887976ce2SSerge Semin 			return 0;
77987976ce2SSerge Semin 		}
78087976ce2SSerge Semin 		break;
78187976ce2SSerge Semin 	case hwmon_in:
78287976ce2SSerge Semin 		switch (attr) {
78387976ce2SSerge Semin 		case hwmon_in_label:
78487976ce2SSerge Semin 			*str = pvt_info[PVT_VOLT + ch].label;
78587976ce2SSerge Semin 			return 0;
78687976ce2SSerge Semin 		}
78787976ce2SSerge Semin 		break;
78887976ce2SSerge Semin 	default:
78987976ce2SSerge Semin 		break;
79087976ce2SSerge Semin 	}
79187976ce2SSerge Semin 
79287976ce2SSerge Semin 	return -EOPNOTSUPP;
79387976ce2SSerge Semin }
79487976ce2SSerge Semin 
pvt_hwmon_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int ch,long val)79587976ce2SSerge Semin static int pvt_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
79687976ce2SSerge Semin 			   u32 attr, int ch, long val)
79787976ce2SSerge Semin {
79887976ce2SSerge Semin 	struct pvt_hwmon *pvt = dev_get_drvdata(dev);
79987976ce2SSerge Semin 
80087976ce2SSerge Semin 	if (!pvt_hwmon_channel_is_valid(type, ch))
80187976ce2SSerge Semin 		return -EINVAL;
80287976ce2SSerge Semin 
80387976ce2SSerge Semin 	switch (type) {
80487976ce2SSerge Semin 	case hwmon_chip:
80587976ce2SSerge Semin 		switch (attr) {
80687976ce2SSerge Semin 		case hwmon_chip_update_interval:
80787976ce2SSerge Semin 			return pvt_write_timeout(pvt, val);
80887976ce2SSerge Semin 		}
80987976ce2SSerge Semin 		break;
81087976ce2SSerge Semin 	case hwmon_temp:
81187976ce2SSerge Semin 		switch (attr) {
81287976ce2SSerge Semin 		case hwmon_temp_min:
81387976ce2SSerge Semin 			return pvt_write_limit(pvt, ch, true, val);
81487976ce2SSerge Semin 		case hwmon_temp_max:
81587976ce2SSerge Semin 			return pvt_write_limit(pvt, ch, false, val);
81687976ce2SSerge Semin 		case hwmon_temp_offset:
81787976ce2SSerge Semin 			return pvt_write_trim(pvt, val);
81887976ce2SSerge Semin 		}
81987976ce2SSerge Semin 		break;
82087976ce2SSerge Semin 	case hwmon_in:
82187976ce2SSerge Semin 		switch (attr) {
82287976ce2SSerge Semin 		case hwmon_in_min:
82387976ce2SSerge Semin 			return pvt_write_limit(pvt, PVT_VOLT + ch, true, val);
82487976ce2SSerge Semin 		case hwmon_in_max:
82587976ce2SSerge Semin 			return pvt_write_limit(pvt, PVT_VOLT + ch, false, val);
82687976ce2SSerge Semin 		}
82787976ce2SSerge Semin 		break;
82887976ce2SSerge Semin 	default:
82987976ce2SSerge Semin 		break;
83087976ce2SSerge Semin 	}
83187976ce2SSerge Semin 
83287976ce2SSerge Semin 	return -EOPNOTSUPP;
83387976ce2SSerge Semin }
83487976ce2SSerge Semin 
83587976ce2SSerge Semin static const struct hwmon_ops pvt_hwmon_ops = {
83687976ce2SSerge Semin 	.is_visible = pvt_hwmon_is_visible,
83787976ce2SSerge Semin 	.read = pvt_hwmon_read,
83887976ce2SSerge Semin 	.read_string = pvt_hwmon_read_string,
83987976ce2SSerge Semin 	.write = pvt_hwmon_write
84087976ce2SSerge Semin };
84187976ce2SSerge Semin 
84287976ce2SSerge Semin static const struct hwmon_chip_info pvt_hwmon_info = {
84387976ce2SSerge Semin 	.ops = &pvt_hwmon_ops,
84487976ce2SSerge Semin 	.info = pvt_channel_info
84587976ce2SSerge Semin };
84687976ce2SSerge Semin 
pvt_clear_data(void * data)84787976ce2SSerge Semin static void pvt_clear_data(void *data)
84887976ce2SSerge Semin {
84987976ce2SSerge Semin 	struct pvt_hwmon *pvt = data;
85087976ce2SSerge Semin #if !defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
85187976ce2SSerge Semin 	int idx;
85287976ce2SSerge Semin 
85387976ce2SSerge Semin 	for (idx = 0; idx < PVT_SENSORS_NUM; ++idx)
85487976ce2SSerge Semin 		complete_all(&pvt->cache[idx].conversion);
85587976ce2SSerge Semin #endif
85687976ce2SSerge Semin 
85787976ce2SSerge Semin 	mutex_destroy(&pvt->iface_mtx);
85887976ce2SSerge Semin }
85987976ce2SSerge Semin 
pvt_create_data(struct platform_device * pdev)86087976ce2SSerge Semin static struct pvt_hwmon *pvt_create_data(struct platform_device *pdev)
86187976ce2SSerge Semin {
86287976ce2SSerge Semin 	struct device *dev = &pdev->dev;
86387976ce2SSerge Semin 	struct pvt_hwmon *pvt;
86487976ce2SSerge Semin 	int ret, idx;
86587976ce2SSerge Semin 
86687976ce2SSerge Semin 	pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL);
86787976ce2SSerge Semin 	if (!pvt)
86887976ce2SSerge Semin 		return ERR_PTR(-ENOMEM);
86987976ce2SSerge Semin 
87087976ce2SSerge Semin 	ret = devm_add_action(dev, pvt_clear_data, pvt);
87187976ce2SSerge Semin 	if (ret) {
87287976ce2SSerge Semin 		dev_err(dev, "Can't add PVT data clear action\n");
87387976ce2SSerge Semin 		return ERR_PTR(ret);
87487976ce2SSerge Semin 	}
87587976ce2SSerge Semin 
87687976ce2SSerge Semin 	pvt->dev = dev;
87787976ce2SSerge Semin 	pvt->sensor = PVT_SENSOR_FIRST;
87887976ce2SSerge Semin 	mutex_init(&pvt->iface_mtx);
87987976ce2SSerge Semin 
88087976ce2SSerge Semin #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
88187976ce2SSerge Semin 	for (idx = 0; idx < PVT_SENSORS_NUM; ++idx)
88287976ce2SSerge Semin 		seqlock_init(&pvt->cache[idx].data_seqlock);
88387976ce2SSerge Semin #else
88487976ce2SSerge Semin 	for (idx = 0; idx < PVT_SENSORS_NUM; ++idx)
88587976ce2SSerge Semin 		init_completion(&pvt->cache[idx].conversion);
88687976ce2SSerge Semin #endif
88787976ce2SSerge Semin 
88887976ce2SSerge Semin 	return pvt;
88987976ce2SSerge Semin }
89087976ce2SSerge Semin 
pvt_request_regs(struct pvt_hwmon * pvt)89187976ce2SSerge Semin static int pvt_request_regs(struct pvt_hwmon *pvt)
89287976ce2SSerge Semin {
89387976ce2SSerge Semin 	struct platform_device *pdev = to_platform_device(pvt->dev);
89487976ce2SSerge Semin 
895*c0cf96d7SYangtao Li 	pvt->regs = devm_platform_ioremap_resource(pdev, 0);
8964943c603SZhen Lei 	if (IS_ERR(pvt->regs))
89787976ce2SSerge Semin 		return PTR_ERR(pvt->regs);
89887976ce2SSerge Semin 
89987976ce2SSerge Semin 	return 0;
90087976ce2SSerge Semin }
90187976ce2SSerge Semin 
pvt_disable_clks(void * data)90287976ce2SSerge Semin static void pvt_disable_clks(void *data)
90387976ce2SSerge Semin {
90487976ce2SSerge Semin 	struct pvt_hwmon *pvt = data;
90587976ce2SSerge Semin 
90687976ce2SSerge Semin 	clk_bulk_disable_unprepare(PVT_CLOCK_NUM, pvt->clks);
90787976ce2SSerge Semin }
90887976ce2SSerge Semin 
pvt_request_clks(struct pvt_hwmon * pvt)90987976ce2SSerge Semin static int pvt_request_clks(struct pvt_hwmon *pvt)
91087976ce2SSerge Semin {
91187976ce2SSerge Semin 	int ret;
91287976ce2SSerge Semin 
91387976ce2SSerge Semin 	pvt->clks[PVT_CLOCK_APB].id = "pclk";
91487976ce2SSerge Semin 	pvt->clks[PVT_CLOCK_REF].id = "ref";
91587976ce2SSerge Semin 
91687976ce2SSerge Semin 	ret = devm_clk_bulk_get(pvt->dev, PVT_CLOCK_NUM, pvt->clks);
91787976ce2SSerge Semin 	if (ret) {
91887976ce2SSerge Semin 		dev_err(pvt->dev, "Couldn't get PVT clocks descriptors\n");
91987976ce2SSerge Semin 		return ret;
92087976ce2SSerge Semin 	}
92187976ce2SSerge Semin 
92287976ce2SSerge Semin 	ret = clk_bulk_prepare_enable(PVT_CLOCK_NUM, pvt->clks);
92387976ce2SSerge Semin 	if (ret) {
92487976ce2SSerge Semin 		dev_err(pvt->dev, "Couldn't enable the PVT clocks\n");
92587976ce2SSerge Semin 		return ret;
92687976ce2SSerge Semin 	}
92787976ce2SSerge Semin 
92887976ce2SSerge Semin 	ret = devm_add_action_or_reset(pvt->dev, pvt_disable_clks, pvt);
92987976ce2SSerge Semin 	if (ret) {
93087976ce2SSerge Semin 		dev_err(pvt->dev, "Can't add PVT clocks disable action\n");
93187976ce2SSerge Semin 		return ret;
93287976ce2SSerge Semin 	}
93387976ce2SSerge Semin 
93487976ce2SSerge Semin 	return 0;
93587976ce2SSerge Semin }
93687976ce2SSerge Semin 
pvt_check_pwr(struct pvt_hwmon * pvt)937a6db1561SSerge Semin static int pvt_check_pwr(struct pvt_hwmon *pvt)
938a6db1561SSerge Semin {
939a6db1561SSerge Semin 	unsigned long tout;
940a6db1561SSerge Semin 	int ret = 0;
941a6db1561SSerge Semin 	u32 data;
942a6db1561SSerge Semin 
943a6db1561SSerge Semin 	/*
944a6db1561SSerge Semin 	 * Test out the sensor conversion functionality. If it is not done on
945a6db1561SSerge Semin 	 * time then the domain must have been unpowered and we won't be able
946a6db1561SSerge Semin 	 * to use the device later in this driver.
947a6db1561SSerge Semin 	 * Note If the power source is lost during the normal driver work the
948a6db1561SSerge Semin 	 * data read procedure will either return -ETIMEDOUT (for the
949a6db1561SSerge Semin 	 * alarm-less driver configuration) or just stop the repeated
950a6db1561SSerge Semin 	 * conversion. In the later case alas we won't be able to detect the
951a6db1561SSerge Semin 	 * problem.
952a6db1561SSerge Semin 	 */
953a6db1561SSerge Semin 	pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_ALL, PVT_INTR_ALL);
954a6db1561SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN);
955a6db1561SSerge Semin 	pvt_set_tout(pvt, 0);
956a6db1561SSerge Semin 	readl(pvt->regs + PVT_DATA);
957a6db1561SSerge Semin 
958a6db1561SSerge Semin 	tout = PVT_TOUT_MIN / NSEC_PER_USEC;
959a6db1561SSerge Semin 	usleep_range(tout, 2 * tout);
960a6db1561SSerge Semin 
961a6db1561SSerge Semin 	data = readl(pvt->regs + PVT_DATA);
962a6db1561SSerge Semin 	if (!(data & PVT_DATA_VALID)) {
963a6db1561SSerge Semin 		ret = -ENODEV;
964a6db1561SSerge Semin 		dev_err(pvt->dev, "Sensor is powered down\n");
965a6db1561SSerge Semin 	}
966a6db1561SSerge Semin 
967a6db1561SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
968a6db1561SSerge Semin 
969a6db1561SSerge Semin 	return ret;
970a6db1561SSerge Semin }
971a6db1561SSerge Semin 
pvt_init_iface(struct pvt_hwmon * pvt)9720015503eSSerge Semin static int pvt_init_iface(struct pvt_hwmon *pvt)
97387976ce2SSerge Semin {
9740015503eSSerge Semin 	unsigned long rate;
97587976ce2SSerge Semin 	u32 trim, temp;
97687976ce2SSerge Semin 
9770015503eSSerge Semin 	rate = clk_get_rate(pvt->clks[PVT_CLOCK_REF].clk);
9780015503eSSerge Semin 	if (!rate) {
9790015503eSSerge Semin 		dev_err(pvt->dev, "Invalid reference clock rate\n");
9800015503eSSerge Semin 		return -ENODEV;
9810015503eSSerge Semin 	}
9820015503eSSerge Semin 
98387976ce2SSerge Semin 	/*
98487976ce2SSerge Semin 	 * Make sure all interrupts and controller are disabled so not to
98587976ce2SSerge Semin 	 * accidentally have ISR executed before the driver data is fully
98687976ce2SSerge Semin 	 * initialized. Clear the IRQ status as well.
98787976ce2SSerge Semin 	 */
98887976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_ALL, PVT_INTR_ALL);
98987976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
99087976ce2SSerge Semin 	readl(pvt->regs + PVT_CLR_INTR);
99187976ce2SSerge Semin 	readl(pvt->regs + PVT_DATA);
99287976ce2SSerge Semin 
99387976ce2SSerge Semin 	/* Setup default sensor mode, timeout and temperature trim. */
99487976ce2SSerge Semin 	pvt_set_mode(pvt, pvt_info[pvt->sensor].mode);
99587976ce2SSerge Semin 	pvt_set_tout(pvt, PVT_TOUT_DEF);
99687976ce2SSerge Semin 
9970015503eSSerge Semin 	/*
9980015503eSSerge Semin 	 * Preserve the current ref-clock based delay (Ttotal) between the
9990015503eSSerge Semin 	 * sensors data samples in the driver data so not to recalculate it
10000015503eSSerge Semin 	 * each time on the data requests and timeout reads. It consists of the
10010015503eSSerge Semin 	 * delay introduced by the internal ref-clock timer (N / Fclk) and the
10020015503eSSerge Semin 	 * constant timeout caused by each conversion latency (Tmin):
10030015503eSSerge Semin 	 *   Ttotal = N / Fclk + Tmin
10040015503eSSerge Semin 	 * If alarms are enabled the sensors are polled one after another and
10050015503eSSerge Semin 	 * in order to get the next measurement of a particular sensor the
10060015503eSSerge Semin 	 * caller will have to wait for at most until all the others are
10070015503eSSerge Semin 	 * polled. In that case the formulae will look a bit different:
10080015503eSSerge Semin 	 *   Ttotal = 5 * (N / Fclk + Tmin)
10090015503eSSerge Semin 	 */
10100015503eSSerge Semin #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
10110015503eSSerge Semin 	pvt->timeout = ktime_set(PVT_SENSORS_NUM * PVT_TOUT_DEF, 0);
10120015503eSSerge Semin 	pvt->timeout = ktime_divns(pvt->timeout, rate);
10130015503eSSerge Semin 	pvt->timeout = ktime_add_ns(pvt->timeout, PVT_SENSORS_NUM * PVT_TOUT_MIN);
10140015503eSSerge Semin #else
10150015503eSSerge Semin 	pvt->timeout = ktime_set(PVT_TOUT_DEF, 0);
10160015503eSSerge Semin 	pvt->timeout = ktime_divns(pvt->timeout, rate);
10170015503eSSerge Semin 	pvt->timeout = ktime_add_ns(pvt->timeout, PVT_TOUT_MIN);
10180015503eSSerge Semin #endif
10190015503eSSerge Semin 
102087976ce2SSerge Semin 	trim = PVT_TRIM_DEF;
102187976ce2SSerge Semin 	if (!of_property_read_u32(pvt->dev->of_node,
102287976ce2SSerge Semin 	     "baikal,pvt-temp-offset-millicelsius", &temp))
102387976ce2SSerge Semin 		trim = pvt_calc_trim(temp);
102487976ce2SSerge Semin 
102587976ce2SSerge Semin 	pvt_set_trim(pvt, trim);
10260015503eSSerge Semin 
10270015503eSSerge Semin 	return 0;
102887976ce2SSerge Semin }
102987976ce2SSerge Semin 
pvt_request_irq(struct pvt_hwmon * pvt)103087976ce2SSerge Semin static int pvt_request_irq(struct pvt_hwmon *pvt)
103187976ce2SSerge Semin {
103287976ce2SSerge Semin 	struct platform_device *pdev = to_platform_device(pvt->dev);
103387976ce2SSerge Semin 	int ret;
103487976ce2SSerge Semin 
103587976ce2SSerge Semin 	pvt->irq = platform_get_irq(pdev, 0);
103687976ce2SSerge Semin 	if (pvt->irq < 0)
103787976ce2SSerge Semin 		return pvt->irq;
103887976ce2SSerge Semin 
103987976ce2SSerge Semin 	ret = devm_request_threaded_irq(pvt->dev, pvt->irq,
104087976ce2SSerge Semin 					pvt_hard_isr, pvt_soft_isr,
104187976ce2SSerge Semin #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
104287976ce2SSerge Semin 					IRQF_SHARED | IRQF_TRIGGER_HIGH |
104387976ce2SSerge Semin 					IRQF_ONESHOT,
104487976ce2SSerge Semin #else
104587976ce2SSerge Semin 					IRQF_SHARED | IRQF_TRIGGER_HIGH,
104687976ce2SSerge Semin #endif
104787976ce2SSerge Semin 					"pvt", pvt);
104887976ce2SSerge Semin 	if (ret) {
104987976ce2SSerge Semin 		dev_err(pvt->dev, "Couldn't request PVT IRQ\n");
105087976ce2SSerge Semin 		return ret;
105187976ce2SSerge Semin 	}
105287976ce2SSerge Semin 
105387976ce2SSerge Semin 	return 0;
105487976ce2SSerge Semin }
105587976ce2SSerge Semin 
pvt_create_hwmon(struct pvt_hwmon * pvt)105687976ce2SSerge Semin static int pvt_create_hwmon(struct pvt_hwmon *pvt)
105787976ce2SSerge Semin {
105887976ce2SSerge Semin 	pvt->hwmon = devm_hwmon_device_register_with_info(pvt->dev, "pvt", pvt,
105987976ce2SSerge Semin 		&pvt_hwmon_info, NULL);
106087976ce2SSerge Semin 	if (IS_ERR(pvt->hwmon)) {
106187976ce2SSerge Semin 		dev_err(pvt->dev, "Couldn't create hwmon device\n");
106287976ce2SSerge Semin 		return PTR_ERR(pvt->hwmon);
106387976ce2SSerge Semin 	}
106487976ce2SSerge Semin 
106587976ce2SSerge Semin 	return 0;
106687976ce2SSerge Semin }
106787976ce2SSerge Semin 
106887976ce2SSerge Semin #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
106987976ce2SSerge Semin 
pvt_disable_iface(void * data)107087976ce2SSerge Semin static void pvt_disable_iface(void *data)
107187976ce2SSerge Semin {
107287976ce2SSerge Semin 	struct pvt_hwmon *pvt = data;
107387976ce2SSerge Semin 
107487976ce2SSerge Semin 	mutex_lock(&pvt->iface_mtx);
107587976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
107687976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID,
107787976ce2SSerge Semin 		   PVT_INTR_DVALID);
107887976ce2SSerge Semin 	mutex_unlock(&pvt->iface_mtx);
107987976ce2SSerge Semin }
108087976ce2SSerge Semin 
pvt_enable_iface(struct pvt_hwmon * pvt)108187976ce2SSerge Semin static int pvt_enable_iface(struct pvt_hwmon *pvt)
108287976ce2SSerge Semin {
108387976ce2SSerge Semin 	int ret;
108487976ce2SSerge Semin 
108587976ce2SSerge Semin 	ret = devm_add_action(pvt->dev, pvt_disable_iface, pvt);
108687976ce2SSerge Semin 	if (ret) {
108787976ce2SSerge Semin 		dev_err(pvt->dev, "Can't add PVT disable interface action\n");
108887976ce2SSerge Semin 		return ret;
108987976ce2SSerge Semin 	}
109087976ce2SSerge Semin 
109187976ce2SSerge Semin 	/*
109287976ce2SSerge Semin 	 * Enable sensors data conversion and IRQ. We need to lock the
109387976ce2SSerge Semin 	 * interface mutex since hwmon has just been created and the
109487976ce2SSerge Semin 	 * corresponding sysfs files are accessible from user-space,
109587976ce2SSerge Semin 	 * which theoretically may cause races.
109687976ce2SSerge Semin 	 */
109787976ce2SSerge Semin 	mutex_lock(&pvt->iface_mtx);
109887976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, 0);
109987976ce2SSerge Semin 	pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN);
110087976ce2SSerge Semin 	mutex_unlock(&pvt->iface_mtx);
110187976ce2SSerge Semin 
110287976ce2SSerge Semin 	return 0;
110387976ce2SSerge Semin }
110487976ce2SSerge Semin 
110587976ce2SSerge Semin #else /* !CONFIG_SENSORS_BT1_PVT_ALARMS */
110687976ce2SSerge Semin 
pvt_enable_iface(struct pvt_hwmon * pvt)110787976ce2SSerge Semin static int pvt_enable_iface(struct pvt_hwmon *pvt)
110887976ce2SSerge Semin {
110987976ce2SSerge Semin 	return 0;
111087976ce2SSerge Semin }
111187976ce2SSerge Semin 
111287976ce2SSerge Semin #endif /* !CONFIG_SENSORS_BT1_PVT_ALARMS */
111387976ce2SSerge Semin 
pvt_probe(struct platform_device * pdev)111487976ce2SSerge Semin static int pvt_probe(struct platform_device *pdev)
111587976ce2SSerge Semin {
111687976ce2SSerge Semin 	struct pvt_hwmon *pvt;
111787976ce2SSerge Semin 	int ret;
111887976ce2SSerge Semin 
111987976ce2SSerge Semin 	pvt = pvt_create_data(pdev);
112087976ce2SSerge Semin 	if (IS_ERR(pvt))
112187976ce2SSerge Semin 		return PTR_ERR(pvt);
112287976ce2SSerge Semin 
112387976ce2SSerge Semin 	ret = pvt_request_regs(pvt);
112487976ce2SSerge Semin 	if (ret)
112587976ce2SSerge Semin 		return ret;
112687976ce2SSerge Semin 
112787976ce2SSerge Semin 	ret = pvt_request_clks(pvt);
112887976ce2SSerge Semin 	if (ret)
112987976ce2SSerge Semin 		return ret;
113087976ce2SSerge Semin 
1131a6db1561SSerge Semin 	ret = pvt_check_pwr(pvt);
1132a6db1561SSerge Semin 	if (ret)
1133a6db1561SSerge Semin 		return ret;
1134a6db1561SSerge Semin 
11350015503eSSerge Semin 	ret = pvt_init_iface(pvt);
11360015503eSSerge Semin 	if (ret)
11370015503eSSerge Semin 		return ret;
113887976ce2SSerge Semin 
113987976ce2SSerge Semin 	ret = pvt_request_irq(pvt);
114087976ce2SSerge Semin 	if (ret)
114187976ce2SSerge Semin 		return ret;
114287976ce2SSerge Semin 
114387976ce2SSerge Semin 	ret = pvt_create_hwmon(pvt);
114487976ce2SSerge Semin 	if (ret)
114587976ce2SSerge Semin 		return ret;
114687976ce2SSerge Semin 
114787976ce2SSerge Semin 	ret = pvt_enable_iface(pvt);
114887976ce2SSerge Semin 	if (ret)
114987976ce2SSerge Semin 		return ret;
115087976ce2SSerge Semin 
115187976ce2SSerge Semin 	return 0;
115287976ce2SSerge Semin }
115387976ce2SSerge Semin 
115487976ce2SSerge Semin static const struct of_device_id pvt_of_match[] = {
115587976ce2SSerge Semin 	{ .compatible = "baikal,bt1-pvt" },
115687976ce2SSerge Semin 	{ }
115787976ce2SSerge Semin };
115887976ce2SSerge Semin MODULE_DEVICE_TABLE(of, pvt_of_match);
115987976ce2SSerge Semin 
116087976ce2SSerge Semin static struct platform_driver pvt_driver = {
116187976ce2SSerge Semin 	.probe = pvt_probe,
116287976ce2SSerge Semin 	.driver = {
116387976ce2SSerge Semin 		.name = "bt1-pvt",
116487976ce2SSerge Semin 		.of_match_table = pvt_of_match
116587976ce2SSerge Semin 	}
116687976ce2SSerge Semin };
116787976ce2SSerge Semin module_platform_driver(pvt_driver);
116887976ce2SSerge Semin 
116987976ce2SSerge Semin MODULE_AUTHOR("Maxim Kaurkin <maxim.kaurkin@baikalelectronics.ru>");
117087976ce2SSerge Semin MODULE_DESCRIPTION("Baikal-T1 PVT driver");
117187976ce2SSerge Semin MODULE_LICENSE("GPL v2");
1172