// SPDX-License-Identifier: GPL-2.0+
/*
* IIO driver for PAC1921 High-Side Power/Current Monitor
*
* Copyright (C) 2024 Matteo Martelli <matteomartelli3@gmail.com>
*/
#include <linux/unaligned.h>
#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/i2c.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/limits.h>
#include <linux/regmap.h>
#include <linux/units.h>
/* pac1921 registers */
#define PAC1921_REG_GAIN_CFG 0x00
#define PAC1921_REG_INT_CFG 0x01
#define PAC1921_REG_CONTROL 0x02
#define PAC1921_REG_VBUS 0x10
#define PAC1921_REG_VSENSE 0x12
#define PAC1921_REG_OVERFLOW_STS 0x1C
#define PAC1921_REG_VPOWER 0x1D
/* pac1921 gain configuration bits */
#define PAC1921_GAIN_DI_GAIN_MASK GENMASK(5, 3)
#define PAC1921_GAIN_DV_GAIN_MASK GENMASK(2, 0)
/* pac1921 integration configuration bits */
#define PAC1921_INT_CFG_SMPL_MASK GENMASK(7, 4)
#define PAC1921_INT_CFG_VSFEN BIT(3)
#define PAC1921_INT_CFG_VBFEN BIT(2)
#define PAC1921_INT_CFG_RIOV BIT(1)
#define PAC1921_INT_CFG_INTEN BIT(0)
/* pac1921 control bits */
#define PAC1921_CONTROL_MXSL_MASK GENMASK(7, 6)
enum pac1921_mxsl {
PAC1921_MXSL_VPOWER_PIN = 0,
PAC1921_MXSL_VSENSE_FREE_RUN = 1,
PAC1921_MXSL_VBUS_FREE_RUN = 2,
PAC1921_MXSL_VPOWER_FREE_RUN = 3,
};
#define PAC1921_CONTROL_SLEEP BIT(2)
/* pac1921 result registers mask and resolution */
#define PAC1921_RES_MASK GENMASK(15, 6)
#define PAC1921_RES_RESOLUTION 1023
/* pac1921 overflow status bits */
#define PAC1921_OVERFLOW_VSOV BIT(2)
#define PAC1921_OVERFLOW_VBOV BIT(1)
#define PAC1921_OVERFLOW_VPOV BIT(0)
/* pac1921 constants */
#define PAC1921_MAX_VSENSE_MV 100
#define PAC1921_MAX_VBUS_V 32
/* Time to first communication after power up (tINT_T) */
#define PAC1921_POWERUP_TIME_MS 20
/* Time from Sleep State to Start of Integration Period (tSLEEP_TO_INT) */
#define PAC1921_SLEEP_TO_INT_TIME_US 86
/* pac1921 defaults */
#define PAC1921_DEFAULT_DV_GAIN 0 /* 2^(value): 1x gain (HW default) */
#define PAC1921_DEFAULT_DI_GAIN 0 /* 2^(value): 1x gain (HW default) */
#define PAC1921_DEFAULT_NUM_SAMPLES 0 /* 2^(value): 1 sample (HW default) */
#define PAC1921_ACPI_GET_uOHMS_VALS 0
#define PAC1921_ACPI_GET_LABEL 1
/* f7bb9932-86ee-4516-a236-7a7a742e55cb */
static const guid_t pac1921_guid =
GUID_INIT(0xf7bb9932, 0x86ee, 0x4516, 0xa2,
0x36, 0x7a, 0x7a, 0x74, 0x2e, 0x55, 0xcb);
/*
* Pre-computed scale factors for BUS voltage
* format: IIO_VAL_INT_PLUS_NANO
* unit: mV
*
* Vbus scale (mV) = max_vbus (mV) / dv_gain / resolution
*/
static const int pac1921_vbus_scales[][2] = {
{ 31, 280547409 }, /* dv_gain x1 */
{ 15, 640273704 }, /* dv_gain x2 */
{ 7, 820136852 }, /* dv_gain x4 */
{ 3, 910068426 }, /* dv_gain x8 */
{ 1, 955034213 }, /* dv_gain x16 */
{ 0, 977517106 }, /* dv_gain x32 */
};
/*
* Pre-computed scales for SENSE voltage
* format: IIO_VAL_INT_PLUS_NANO
* unit: mV
*
* Vsense scale (mV) = max_vsense (mV) / di_gain / resolution
*/
static const int pac1921_vsense_scales[][2] = {
{