#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/ktime.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/polynomial.h>
#include <linux/seqlock.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include "bt1-pvt.h"
static const struct pvt_sensor_info pvt_info[] = …;
static const struct polynomial __maybe_unused poly_temp_to_N = …;
static const struct polynomial poly_N_to_temp = …;
static const struct polynomial __maybe_unused poly_volt_to_N = …;
static const struct polynomial poly_N_to_volt = …;
static inline u32 pvt_update(void __iomem *reg, u32 mask, u32 data)
{ … }
static inline void pvt_set_mode(struct pvt_hwmon *pvt, u32 mode)
{ … }
static inline u32 pvt_calc_trim(long temp)
{ … }
static inline void pvt_set_trim(struct pvt_hwmon *pvt, u32 trim)
{ … }
static inline void pvt_set_tout(struct pvt_hwmon *pvt, u32 tout)
{ … }
#if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
#define pvt_hard_isr …
static irqreturn_t pvt_soft_isr(int irq, void *data)
{ … }
static inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type)
{ … }
static inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type)
{ … }
static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
long *val)
{ … }
static int pvt_read_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
bool is_low, long *val)
{ … }
static int pvt_write_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
bool is_low, long val)
{ … }
static int pvt_read_alarm(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
bool is_low, long *val)
{ … }
static const struct hwmon_channel_info * const pvt_channel_info[] = …;
#else
static irqreturn_t pvt_hard_isr(int irq, void *data)
{
struct pvt_hwmon *pvt = data;
struct pvt_cache *cache;
u32 val;
pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID,
PVT_INTR_DVALID);
val = readl(pvt->regs + PVT_DATA);
if (!(val & PVT_DATA_VALID)) {
dev_err(pvt->dev, "Got IRQ when data isn't valid\n");
return IRQ_HANDLED;
}
cache = &pvt->cache[pvt->sensor];
WRITE_ONCE(cache->data, FIELD_GET(PVT_DATA_DATA_MASK, val));
complete(&cache->conversion);
return IRQ_HANDLED;
}
#define pvt_soft_isr …
static inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type)
{
return 0;
}
static inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type)
{
return 0;
}
static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
long *val)
{
struct pvt_cache *cache = &pvt->cache[type];
unsigned long timeout;
u32 data;
int ret;
ret = mutex_lock_interruptible(&pvt->iface_mtx);
if (ret)
return ret;
pvt->sensor = type;
pvt_set_mode(pvt, pvt_info[type].mode);
pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, 0);
pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN);
timeout = 2 * usecs_to_jiffies(ktime_to_us(pvt->timeout));
ret = wait_for_completion_timeout(&cache->conversion, timeout);
pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID,
PVT_INTR_DVALID);
data = READ_ONCE(cache->data);
mutex_unlock(&pvt->iface_mtx);
if (!ret)
return -ETIMEDOUT;
if (type == PVT_TEMP)
*val = polynomial_calc(&poly_N_to_temp, data);
else
*val = polynomial_calc(&poly_N_to_volt, data);
return 0;
}
static int pvt_read_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
bool is_low, long *val)
{
return -EOPNOTSUPP;
}
static int pvt_write_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
bool is_low, long val)
{
return -EOPNOTSUPP;
}
static int pvt_read_alarm(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
bool is_low, long *val)
{
return -EOPNOTSUPP;
}
static const struct hwmon_channel_info * const pvt_channel_info[] = {
HWMON_CHANNEL_INFO(chip,
HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL),
HWMON_CHANNEL_INFO(temp,
HWMON_T_INPUT | HWMON_T_TYPE | HWMON_T_LABEL |
HWMON_T_OFFSET),
HWMON_CHANNEL_INFO(in,
HWMON_I_INPUT | HWMON_I_LABEL,
HWMON_I_INPUT | HWMON_I_LABEL,
HWMON_I_INPUT | HWMON_I_LABEL,
HWMON_I_INPUT | HWMON_I_LABEL),
NULL
};
#endif
static inline bool pvt_hwmon_channel_is_valid(enum hwmon_sensor_types type,
int ch)
{ … }
static umode_t pvt_hwmon_is_visible(const void *data,
enum hwmon_sensor_types type,
u32 attr, int ch)
{ … }
static int pvt_read_trim(struct pvt_hwmon *pvt, long *val)
{ … }
static int pvt_write_trim(struct pvt_hwmon *pvt, long val)
{ … }
static int pvt_read_timeout(struct pvt_hwmon *pvt, long *val)
{ … }
static int pvt_write_timeout(struct pvt_hwmon *pvt, long val)
{ … }
static int pvt_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int ch, long *val)
{ … }
static int pvt_hwmon_read_string(struct device *dev,
enum hwmon_sensor_types type,
u32 attr, int ch, const char **str)
{ … }
static int pvt_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int ch, long val)
{ … }
static const struct hwmon_ops pvt_hwmon_ops = …;
static const struct hwmon_chip_info pvt_hwmon_info = …;
static void pvt_clear_data(void *data)
{ … }
static struct pvt_hwmon *pvt_create_data(struct platform_device *pdev)
{ … }
static int pvt_request_regs(struct pvt_hwmon *pvt)
{ … }
static void pvt_disable_clks(void *data)
{ … }
static int pvt_request_clks(struct pvt_hwmon *pvt)
{ … }
static int pvt_check_pwr(struct pvt_hwmon *pvt)
{ … }
static int pvt_init_iface(struct pvt_hwmon *pvt)
{ … }
static int pvt_request_irq(struct pvt_hwmon *pvt)
{ … }
static int pvt_create_hwmon(struct pvt_hwmon *pvt)
{ … }
#if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
static void pvt_disable_iface(void *data)
{ … }
static int pvt_enable_iface(struct pvt_hwmon *pvt)
{ … }
#else
static int pvt_enable_iface(struct pvt_hwmon *pvt)
{
return 0;
}
#endif
static int pvt_probe(struct platform_device *pdev)
{ … }
static const struct of_device_id pvt_of_match[] = …;
MODULE_DEVICE_TABLE(of, pvt_of_match);
static struct platform_driver pvt_driver = …;
module_platform_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;