* [PATCH 1/3] mfd: da9063: Add HWMON dependencies @ 2021-07-06 14:34 Vincent Pelletier 2021-07-06 14:34 ` [PATCH 2/3] hwmon: da9063: HWMON driver Vincent Pelletier ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Vincent Pelletier @ 2021-07-06 14:34 UTC (permalink / raw) To: Jean Delvare, Guenter Roeck, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> Dependencies required for DA9063 HWMON support. Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> Directly set da9063->t_offset. Let MFD probe succeed even if DA9063_REG_T_OFFSET cannot be read. Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> --- Changes in v2: - registers.h changes moved from patch 2 Originally submitted by Steve Twiss in 2014: https://marc.info/?l=linux-kernel&m=139560864709852&w=2 drivers/mfd/da9063-core.c | 8 +++++++ include/linux/mfd/da9063/core.h | 3 +++ include/linux/mfd/da9063/registers.h | 34 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c index df407c3afce3..14c2a8df9ae3 100644 --- a/drivers/mfd/da9063-core.c +++ b/drivers/mfd/da9063-core.c @@ -197,6 +197,14 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) } } + ret = regmap_read(da9063->regmap, DA9063_REG_T_OFFSET, &da9063->t_offset); + if (ret < 0) { + da9063->t_offset = 0; + dev_warn(da9063->dev, + "Temperature trimming value cannot be read (defaulting to 0)\n"); + ret = 0; + } + return ret; } diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h index fa7a43f02f27..c0c57c6f6230 100644 --- a/include/linux/mfd/da9063/core.h +++ b/include/linux/mfd/da9063/core.h @@ -85,6 +85,9 @@ struct da9063 { int chip_irq; unsigned int irq_base; struct regmap_irq_chip_data *regmap_irq; + + /* Trimming */ + int t_offset; }; int da9063_device_init(struct da9063 *da9063, unsigned int irq); diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h index 6e0f66a2e727..297631ddda39 100644 --- a/include/linux/mfd/da9063/registers.h +++ b/include/linux/mfd/da9063/registers.h @@ -512,6 +512,7 @@ /* DA9063_REG_GPIO_0_1 (addr=0x15) */ #define DA9063_GPIO0_PIN_MASK 0x03 +#define DA9063_GPIO0_PIN_MASK_SHIFT 0 #define DA9063_GPIO0_PIN_ADCIN1 0x00 #define DA9063_GPIO0_PIN_GPI 0x01 #define DA9063_GPIO0_PIN_GPO_OD 0x02 @@ -523,6 +524,7 @@ #define DA9063_GPIO0_TYPE_GPO_VDD_IO2 0x04 #define DA9063_GPIO0_NO_WAKEUP 0x08 #define DA9063_GPIO1_PIN_MASK 0x30 +#define DA9063_GPIO1_PIN_MASK_SHIFT 4 #define DA9063_GPIO1_PIN_ADCIN2_COMP 0x00 #define DA9063_GPIO1_PIN_GPI 0x10 #define DA9063_GPIO1_PIN_GPO_OD 0x20 @@ -536,6 +538,7 @@ /* DA9063_REG_GPIO_2_3 (addr=0x16) */ #define DA9063_GPIO2_PIN_MASK 0x03 +#define DA9063_GPIO2_PIN_MASK_SHIFT 0 #define DA9063_GPIO2_PIN_ADCIN3 0x00 #define DA9063_GPIO2_PIN_GPI 0x01 #define DA9063_GPIO2_PIN_GPO_PSS 0x02 @@ -851,6 +854,7 @@ #define DA9063_VSYS_VAL_BASE 0x00 /* DA9063_REG_ADC_RES_L (addr=0x37) */ +#define DA9063_ADC_RES_L_SHIFT 6 #define DA9063_ADC_RES_L_BITS 2 #define DA9063_ADC_RES_L_MASK 0xC0 @@ -1014,6 +1018,36 @@ #define DA9063_GPIO_DIM 0x80 #define DA9063_GPIO_PWM_MASK 0x7F +/* DA9063_REG_ADC_CFG (addr=0xC9) */ +#define DA9063_REG_ADCIN1_CUR_MASK 0x03 +#define DA9063_REG_ADCIN1_CUR_SHIFT 0 +#define DA9063_ADCIN1_CUR_1UA 0x00 +#define DA9063_ADCIN1_CUR_2UA 0x01 +#define DA9063_ADCIN1_CUR_10UA 0x02 +#define DA9063_ADCIN1_CUR_40UA 0x03 +#define DA9063_REG_ADCIN2_CUR_MASK 0x0C +#define DA9063_REG_ADCIN2_CUR_SHIFT 2 +#define DA9063_ADCIN2_CUR_1UA 0x00 +#define DA9063_ADCIN2_CUR_2UA 0x01 +#define DA9063_ADCIN2_CUR_10UA 0x02 +#define DA9063_ADCIN2_CUR_40UA 0x03 +#define DA9063_REG_ADCIN3_CUR_MASK 0x10 +#define DA9063_REG_ADCIN3_CUR_SHIFT 4 +#define DA9063_ADCIN3_CUR_10UA 0x00 +#define DA9063_ADCIN3_CUR_40UA 0x01 +#define DA9063_REG_ADCIN1_DEB_MASK 0x20 +#define DA9063_REG_ADCIN1_DEB_SHIFT 5 +#define DA9063_ADCIN1_DEB_OFF 0x00 +#define DA9063_ADCIN1_DEB_ON 0x01 +#define DA9063_REG_ADCIN2_DEB_MASK 0x40 +#define DA9063_REG_ADCIN2_DEB_SHIFT 6 +#define DA9063_ADCIN2_DEB_OFF 0x00 +#define DA9063_ADCIN2_DEB_ON 0x01 +#define DA9063_REG_ADCIN3_DEB_MASK 0x80 +#define DA9063_REG_ADCIN3_DEB_SHIFT 7 +#define DA9063_ADCIN3_DEB_OFF 0x00 +#define DA9063_ADCIN3_DEB_ON 0x01 + /* DA9063_REG_CONFIG_H (addr=0x10D) */ #define DA9063_PWM_CLK_MASK 0x01 #define DA9063_PWM_CLK_PWM2MHZ 0x00 -- 2.32.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/3] hwmon: da9063: HWMON driver 2021-07-06 14:34 [PATCH 1/3] mfd: da9063: Add HWMON dependencies Vincent Pelletier @ 2021-07-06 14:34 ` Vincent Pelletier 2021-07-06 17:42 ` Guenter Roeck 2021-07-06 14:34 ` [PATCH 3/3] Documentation: hwmon: New information for DA9063 Vincent Pelletier 2021-07-06 17:28 ` [PATCH 1/3] mfd: da9063: Add HWMON dependencies Guenter Roeck 2 siblings, 1 reply; 11+ messages in thread From: Vincent Pelletier @ 2021-07-06 14:34 UTC (permalink / raw) To: Jean Delvare, Guenter Roeck, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> Add the HWMON driver for DA9063 Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> Simplify and modernise the code a bit. Fix logic inversion in detecting conversion end. Drop support for ADCIN: these are multi-purpose channels and must not be reconfigured unless explicitly authorised by the board description. Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> --- Changes in v2: - drop of_match_table: this should be meaningless in such sub-function driver (at least judging by other sub-function drivers for the da9063) - sort includes - switch to devm_hwmon_device_register_with_info - registers.h changes moved to patch 1 - add SPDX header This patch depends on patch 1/3. Originally submitted by Steve Twiss in 2014: https://marc.info/?l=linux-kernel&m=139560868309857&w=2 drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/da9063-hwmon.c | 275 +++++++++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+) create mode 100644 drivers/hwmon/da9063-hwmon.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 87624902ea80..17244cfaa855 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -515,6 +515,16 @@ config SENSORS_DA9055 This driver can also be built as a module. If so, the module will be called da9055-hwmon. +config SENSORS_DA9063 + tristate "Dialog Semiconductor DA9063" + depends on MFD_DA9063 + help + If you say yes here you get support for the hardware + monitoring features of the DA9063 Power Management IC. + + This driver can also be built as a module. If so, the module + will be called da9063-hwmon. + config SENSORS_I5K_AMB tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" depends on PCI diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 59e78bc212cf..6855711ed9ec 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_CORSAIR_CPRO) += corsair-cpro.o obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o +obj-$(CONFIG_SENSORS_DA9063) += da9063-hwmon.o obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DRIVETEMP) += drivetemp.o diff --git a/drivers/hwmon/da9063-hwmon.c b/drivers/hwmon/da9063-hwmon.c new file mode 100644 index 000000000000..f020be5d5d6b --- /dev/null +++ b/drivers/hwmon/da9063-hwmon.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* da9063-hwmon.c - Hardware monitor support for DA9063 + * Copyright (C) 2014 Dialog Semiconductor Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/mfd/da9063/core.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/string.h> + +#define DA9063_ADC_RES (1 << (DA9063_ADC_RES_L_BITS + DA9063_ADC_RES_M_BITS)) +#define DA9063_ADC_MAX (DA9063_ADC_RES - 1) +#define DA9063_2V5 2500 +#define DA9063_5V0 5000 +#define DA9063_5V5 5500 +#define DA9063_TJUNC_M -398 +#define DA9063_TJUNC_O 330000 +#define DA9063_VBBAT_M 2048 + +enum da9063_adc { + DA9063_CHAN_VSYS = DA9063_ADC_MUX_VSYS, + DA9063_CHAN_ADCIN1 = DA9063_ADC_MUX_ADCIN1, + DA9063_CHAN_ADCIN2 = DA9063_ADC_MUX_ADCIN2, + DA9063_CHAN_ADCIN3 = DA9063_ADC_MUX_ADCIN3, + DA9063_CHAN_TJUNC = DA9063_ADC_MUX_T_SENSE, + DA9063_CHAN_VBBAT = DA9063_ADC_MUX_VBBAT, + DA9063_CHAN_LDO_G1 = DA9063_ADC_MUX_LDO_G1, + DA9063_CHAN_LDO_G2 = DA9063_ADC_MUX_LDO_G2, + DA9063_CHAN_LDO_G3 = DA9063_ADC_MUX_LDO_G3 +}; + +struct da9063_hwmon { + struct da9063 *da9063; + struct mutex hwmon_mutex; + struct completion adc_ready; + signed char tjunc_offset; +}; + +static int da9063_adc_manual_read(struct da9063_hwmon *hwmon, int channel) +{ + int ret; + unsigned char val; + unsigned char data[2]; + int adc_man; + + mutex_lock(&hwmon->hwmon_mutex); + + init_completion(&hwmon->adc_ready); + + val = (channel & DA9063_ADC_MUX_MASK) | DA9063_ADC_MAN; + ret = regmap_update_bits(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, + DA9063_ADC_MUX_MASK | DA9063_ADC_MAN, val); + if (ret < 0) + goto err_mread; + + ret = wait_for_completion_timeout(&hwmon->adc_ready, + msecs_to_jiffies(1000)); + if (ret == 0) { + ret = -ETIMEDOUT; + goto err_mread; + } + + ret = regmap_read(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, &adc_man); + if (ret < 0) + goto err_mread; + + /* data value is not ready */ + if (adc_man & DA9063_ADC_MAN) { + ret = -EINVAL; + goto err_mread; + } + + ret = regmap_bulk_read(hwmon->da9063->regmap, + DA9063_REG_ADC_RES_L, data, 2); + if (ret < 0) + goto err_mread; + + ret = (data[0] & DA9063_ADC_RES_L_MASK) >> DA9063_ADC_RES_L_SHIFT; + ret |= data[1] << DA9063_ADC_RES_L_BITS; +err_mread: + mutex_unlock(&hwmon->hwmon_mutex); + return ret; +} + +static irqreturn_t da9063_hwmon_irq_handler(int irq, void *irq_data) +{ + struct da9063_hwmon *hwmon = irq_data; + + complete(&hwmon->adc_ready); + return IRQ_HANDLED; +} + +static umode_t da9063_is_visible(const void *drvdata, enum + hwmon_sensor_types type, u32 attr, int channel) +{ + return 0444; +} + +static const enum da9063_adc da9063_in_index[] = { + DA9063_CHAN_VSYS, DA9063_CHAN_VBBAT +}; + +static const enum da9063_adc da9063_temp_index[] = { + DA9063_CHAN_TJUNC +}; + +static int da9063_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct da9063_hwmon *hwmon = dev_get_drvdata(dev); + enum da9063_adc adc_channel; + int tmp; + + switch (type) { + case hwmon_in: + if (attr != hwmon_in_input) + return -EOPNOTSUPP; + adc_channel = da9063_in_index[channel]; + break; + case hwmon_temp: + if (attr != hwmon_temp_input) + return -EOPNOTSUPP; + adc_channel = da9063_temp_index[channel]; + break; + default: + return -EOPNOTSUPP; + } + + tmp = da9063_adc_manual_read(hwmon, adc_channel); + if (tmp < 0) + return tmp; + + switch (adc_channel) { + case DA9063_CHAN_VSYS: + *val = ((DA9063_5V5 - DA9063_2V5) * tmp) / DA9063_ADC_MAX + + DA9063_2V5; + break; + case DA9063_CHAN_TJUNC: + tmp -= hwmon->tjunc_offset; + *val = DA9063_TJUNC_M * tmp + DA9063_TJUNC_O; + break; + case DA9063_CHAN_VBBAT: + *val = (DA9063_5V0 * tmp) / DA9063_ADC_MAX; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const char * const da9063_in_name[] = { + "VSYS", "VBBAT" +}; + +static const char * const da9063_temp_name[] = { + "TJUNC" +}; + +static int da9063_read_string(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + switch (type) { + case hwmon_in: + if (attr != hwmon_in_label) + return -EOPNOTSUPP; + *str = da9063_in_name[channel]; + break; + case hwmon_temp: + if (attr != hwmon_temp_label) + return -EOPNOTSUPP; + *str = da9063_temp_name[channel]; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static const struct hwmon_ops da9063_ops = { + .is_visible = da9063_is_visible, + .read = da9063_read, + .read_string = da9063_read_string, +}; + +static const struct hwmon_channel_info *da9063_channel_info[] = { + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | HWMON_I_LABEL, + HWMON_I_INPUT | HWMON_I_LABEL), + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_LABEL), + NULL +}; + +static const struct hwmon_chip_info da9063_chip_info = { + .ops = &da9063_ops, + .info = da9063_channel_info, +}; + +static int da9063_hwmon_probe(struct platform_device *pdev) +{ + struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); + struct da9063_hwmon *hwmon; + struct device *hwmon_dev; + int irq; + int ret; + + hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9063_hwmon), + GFP_KERNEL); + if (!hwmon) + return -ENOMEM; + + mutex_init(&hwmon->hwmon_mutex); + init_completion(&hwmon->adc_ready); + hwmon->da9063 = da9063; + + irq = platform_get_irq_byname(pdev, DA9063_DRVNAME_HWMON); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + da9063_hwmon_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "HWMON", hwmon); + if (ret) { + dev_err(&pdev->dev, "Failed to request IRQ.\n"); + return ret; + } + + platform_set_drvdata(pdev, hwmon); + + /* set trim temperature offset to value read at startup */ + hwmon->tjunc_offset = (signed char)hwmon->da9063->t_offset; + + hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "da9063", + hwmon, + &da9063_chip_info, + NULL); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static struct platform_driver da9063_hwmon_driver = { + .probe = da9063_hwmon_probe, + .driver = { + .name = DA9063_DRVNAME_HWMON, + }, +}; +module_platform_driver(da9063_hwmon_driver); + +MODULE_DESCRIPTION("Hardware monitor support device driver for Dialog DA9063"); +MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DA9063_DRVNAME_HWMON); -- 2.32.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/3] hwmon: da9063: HWMON driver 2021-07-06 14:34 ` [PATCH 2/3] hwmon: da9063: HWMON driver Vincent Pelletier @ 2021-07-06 17:42 ` Guenter Roeck 2021-07-07 0:20 ` Vincent Pelletier 0 siblings, 1 reply; 11+ messages in thread From: Guenter Roeck @ 2021-07-06 17:42 UTC (permalink / raw) To: Vincent Pelletier Cc: Jean Delvare, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] On Tue, Jul 06, 2021 at 02:34:48PM +0000, Vincent Pelletier wrote: > From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> > > Add the HWMON driver for DA9063 > > Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> > > Simplify and modernise the code a bit. > Fix logic inversion in detecting conversion end. > Drop support for ADCIN: these are multi-purpose channels and must not > be reconfigured unless explicitly authorised by the board description. > That is a bit too much information to be after the first Signed-off-by: tag, and the code changes are too substantial to warrant Steve's Signed-off-by: without his explicit permission. I'd suggest to drop the change log and change Steve's Signed-off-by: to something like Originally-from: or similar. > Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> > --- > Changes in v2: > - drop of_match_table: this should be meaningless in such sub-function > driver (at least judging by other sub-function drivers for the da9063) > - sort includes > - switch to devm_hwmon_device_register_with_info > - registers.h changes moved to patch 1 > - add SPDX header > > This patch depends on patch 1/3. FWIW, that is implied by having a patch series. > Originally submitted by Steve Twiss in 2014: > https://marc.info/?l=linux-kernel&m=139560868309857&w=2 > > drivers/hwmon/Kconfig | 10 ++ > drivers/hwmon/Makefile | 1 + > drivers/hwmon/da9063-hwmon.c | 275 +++++++++++++++++++++++++++++++++++ > 3 files changed, 286 insertions(+) > create mode 100644 drivers/hwmon/da9063-hwmon.c > > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig > index 87624902ea80..17244cfaa855 100644 > --- a/drivers/hwmon/Kconfig > +++ b/drivers/hwmon/Kconfig > @@ -515,6 +515,16 @@ config SENSORS_DA9055 > This driver can also be built as a module. If so, the module > will be called da9055-hwmon. > > +config SENSORS_DA9063 > + tristate "Dialog Semiconductor DA9063" > + depends on MFD_DA9063 > + help > + If you say yes here you get support for the hardware > + monitoring features of the DA9063 Power Management IC. > + > + This driver can also be built as a module. If so, the module > + will be called da9063-hwmon. > + > config SENSORS_I5K_AMB > tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" > depends on PCI > diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile > index 59e78bc212cf..6855711ed9ec 100644 > --- a/drivers/hwmon/Makefile > +++ b/drivers/hwmon/Makefile > @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_CORSAIR_CPRO) += corsair-cpro.o > obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o > obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o > obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o > +obj-$(CONFIG_SENSORS_DA9063) += da9063-hwmon.o > obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o > obj-$(CONFIG_SENSORS_DME1737) += dme1737.o > obj-$(CONFIG_SENSORS_DRIVETEMP) += drivetemp.o > diff --git a/drivers/hwmon/da9063-hwmon.c b/drivers/hwmon/da9063-hwmon.c > new file mode 100644 > index 000000000000..f020be5d5d6b > --- /dev/null > +++ b/drivers/hwmon/da9063-hwmon.c > @@ -0,0 +1,275 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* da9063-hwmon.c - Hardware monitor support for DA9063 > + * Copyright (C) 2014 Dialog Semiconductor Ltd. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Library General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Library General Public License for more details. Drop boilerplate; that is what SPDX is for. > + */ > + > +#include <linux/delay.h> > +#include <linux/err.h> > +#include <linux/hwmon.h> > +#include <linux/hwmon-sysfs.h> > +#include <linux/init.h> > +#include <linux/kernel.h> > +#include <linux/mfd/da9063/core.h> > +#include <linux/mod_devicetable.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/regmap.h> > +#include <linux/slab.h> > +#include <linux/string.h> > + > +#define DA9063_ADC_RES (1 << (DA9063_ADC_RES_L_BITS + DA9063_ADC_RES_M_BITS)) > +#define DA9063_ADC_MAX (DA9063_ADC_RES - 1) > +#define DA9063_2V5 2500 > +#define DA9063_5V0 5000 > +#define DA9063_5V5 5500 > +#define DA9063_TJUNC_M -398 > +#define DA9063_TJUNC_O 330000 > +#define DA9063_VBBAT_M 2048 > + > +enum da9063_adc { > + DA9063_CHAN_VSYS = DA9063_ADC_MUX_VSYS, > + DA9063_CHAN_ADCIN1 = DA9063_ADC_MUX_ADCIN1, > + DA9063_CHAN_ADCIN2 = DA9063_ADC_MUX_ADCIN2, > + DA9063_CHAN_ADCIN3 = DA9063_ADC_MUX_ADCIN3, > + DA9063_CHAN_TJUNC = DA9063_ADC_MUX_T_SENSE, > + DA9063_CHAN_VBBAT = DA9063_ADC_MUX_VBBAT, > + DA9063_CHAN_LDO_G1 = DA9063_ADC_MUX_LDO_G1, > + DA9063_CHAN_LDO_G2 = DA9063_ADC_MUX_LDO_G2, > + DA9063_CHAN_LDO_G3 = DA9063_ADC_MUX_LDO_G3 > +}; > + > +struct da9063_hwmon { > + struct da9063 *da9063; > + struct mutex hwmon_mutex; > + struct completion adc_ready; > + signed char tjunc_offset; > +}; > + > +static int da9063_adc_manual_read(struct da9063_hwmon *hwmon, int channel) > +{ > + int ret; > + unsigned char val; > + unsigned char data[2]; > + int adc_man; > + > + mutex_lock(&hwmon->hwmon_mutex); > + > + init_completion(&hwmon->adc_ready); > + > + val = (channel & DA9063_ADC_MUX_MASK) | DA9063_ADC_MAN; > + ret = regmap_update_bits(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, > + DA9063_ADC_MUX_MASK | DA9063_ADC_MAN, val); > + if (ret < 0) > + goto err_mread; > + > + ret = wait_for_completion_timeout(&hwmon->adc_ready, > + msecs_to_jiffies(1000)); > + if (ret == 0) { > + ret = -ETIMEDOUT; > + goto err_mread; > + } > + > + ret = regmap_read(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, &adc_man); > + if (ret < 0) > + goto err_mread; > + > + /* data value is not ready */ > + if (adc_man & DA9063_ADC_MAN) { > + ret = -EINVAL; -EINVAL seems wrong. Maybe -EIO or -ETIMEDOUT. > + goto err_mread; > + } > + > + ret = regmap_bulk_read(hwmon->da9063->regmap, > + DA9063_REG_ADC_RES_L, data, 2); > + if (ret < 0) > + goto err_mread; > + > + ret = (data[0] & DA9063_ADC_RES_L_MASK) >> DA9063_ADC_RES_L_SHIFT; > + ret |= data[1] << DA9063_ADC_RES_L_BITS; > +err_mread: > + mutex_unlock(&hwmon->hwmon_mutex); > + return ret; > +} > + > +static irqreturn_t da9063_hwmon_irq_handler(int irq, void *irq_data) > +{ > + struct da9063_hwmon *hwmon = irq_data; > + > + complete(&hwmon->adc_ready); > + return IRQ_HANDLED; > +} > + > +static umode_t da9063_is_visible(const void *drvdata, enum > + hwmon_sensor_types type, u32 attr, int channel) > +{ > + return 0444; > +} > + > +static const enum da9063_adc da9063_in_index[] = { > + DA9063_CHAN_VSYS, DA9063_CHAN_VBBAT > +}; > + > +static const enum da9063_adc da9063_temp_index[] = { > + DA9063_CHAN_TJUNC > +}; > + > +static int da9063_read(struct device *dev, enum hwmon_sensor_types type, > + u32 attr, int channel, long *val) > +{ > + struct da9063_hwmon *hwmon = dev_get_drvdata(dev); > + enum da9063_adc adc_channel; > + int tmp; > + > + switch (type) { > + case hwmon_in: > + if (attr != hwmon_in_input) > + return -EOPNOTSUPP; > + adc_channel = da9063_in_index[channel]; > + break; > + case hwmon_temp: > + if (attr != hwmon_temp_input) > + return -EOPNOTSUPP; > + adc_channel = da9063_temp_index[channel]; There is only one channel for temperatures. I don't see value in reading that value from an array of size 1. > + break; > + default: > + return -EOPNOTSUPP; > + } > + > + tmp = da9063_adc_manual_read(hwmon, adc_channel); > + if (tmp < 0) > + return tmp; > + > + switch (adc_channel) { > + case DA9063_CHAN_VSYS: > + *val = ((DA9063_5V5 - DA9063_2V5) * tmp) / DA9063_ADC_MAX + > + DA9063_2V5; > + break; > + case DA9063_CHAN_TJUNC: > + tmp -= hwmon->tjunc_offset; > + *val = DA9063_TJUNC_M * tmp + DA9063_TJUNC_O; > + break; > + case DA9063_CHAN_VBBAT: > + *val = (DA9063_5V0 * tmp) / DA9063_ADC_MAX; > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +static const char * const da9063_in_name[] = { > + "VSYS", "VBBAT" > +}; > + > +static const char * const da9063_temp_name[] = { > + "TJUNC" > +}; > + > +static int da9063_read_string(struct device *dev, enum hwmon_sensor_types type, > + u32 attr, int channel, const char **str) > +{ > + switch (type) { > + case hwmon_in: > + if (attr != hwmon_in_label) > + return -EOPNOTSUPP; > + *str = da9063_in_name[channel]; > + break; > + case hwmon_temp: > + if (attr != hwmon_temp_label) > + return -EOPNOTSUPP; > + *str = da9063_temp_name[channel]; > + break; > + default: > + return -EOPNOTSUPP; > + } > + > + return 0; > +} > + > +static const struct hwmon_ops da9063_ops = { > + .is_visible = da9063_is_visible, > + .read = da9063_read, > + .read_string = da9063_read_string, > +}; > + > +static const struct hwmon_channel_info *da9063_channel_info[] = { > + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), > + HWMON_CHANNEL_INFO(in, > + HWMON_I_INPUT | HWMON_I_LABEL, > + HWMON_I_INPUT | HWMON_I_LABEL), > + HWMON_CHANNEL_INFO(temp, > + HWMON_T_INPUT | HWMON_T_LABEL), > + NULL > +}; > + > +static const struct hwmon_chip_info da9063_chip_info = { > + .ops = &da9063_ops, > + .info = da9063_channel_info, > +}; > + > +static int da9063_hwmon_probe(struct platform_device *pdev) > +{ > + struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); > + struct da9063_hwmon *hwmon; > + struct device *hwmon_dev; > + int irq; > + int ret; > + > + hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9063_hwmon), > + GFP_KERNEL); > + if (!hwmon) > + return -ENOMEM; > + > + mutex_init(&hwmon->hwmon_mutex); > + init_completion(&hwmon->adc_ready); Does this have a useful purpose ? It is initialized again prior to actually waiting. Or is this to address the potential race with an interrupt firing prior to hwmon registration ? > + hwmon->da9063 = da9063; > + > + irq = platform_get_irq_byname(pdev, DA9063_DRVNAME_HWMON); > + if (irq < 0) > + return irq; > + > + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, > + da9063_hwmon_irq_handler, > + IRQF_TRIGGER_LOW | IRQF_ONESHOT, Is that correct ? The trigger condition is normally provided by devicetree. > + "HWMON", hwmon); > + if (ret) { > + dev_err(&pdev->dev, "Failed to request IRQ.\n"); > + return ret; > + } > + > + platform_set_drvdata(pdev, hwmon); Where is this used ? > + > + /* set trim temperature offset to value read at startup */ > + hwmon->tjunc_offset = (signed char)hwmon->da9063->t_offset; Can you explain why this is read in and passed from the mfd driver and not here ? > + > + hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "da9063", > + hwmon, > + &da9063_chip_info, > + NULL); > + > + return PTR_ERR_OR_ZERO(hwmon_dev); > +} > + > +static struct platform_driver da9063_hwmon_driver = { > + .probe = da9063_hwmon_probe, > + .driver = { > + .name = DA9063_DRVNAME_HWMON, > + }, > +}; > +module_platform_driver(da9063_hwmon_driver); > + > +MODULE_DESCRIPTION("Hardware monitor support device driver for Dialog DA9063"); > +MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); > +MODULE_LICENSE("GPL v2"); > +MODULE_ALIAS("platform:" DA9063_DRVNAME_HWMON); > -- > 2.32.0 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/3] hwmon: da9063: HWMON driver 2021-07-06 17:42 ` Guenter Roeck @ 2021-07-07 0:20 ` Vincent Pelletier 2021-07-07 0:58 ` Guenter Roeck 0 siblings, 1 reply; 11+ messages in thread From: Vincent Pelletier @ 2021-07-07 0:20 UTC (permalink / raw) To: Guenter Roeck Cc: Jean Delvare, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] Hello, Thanks a lot for your reviews. On Tue, 6 Jul 2021 10:42:01 -0700, Guenter Roeck <linux@roeck-us.net> wrote: > -EINVAL seems wrong. Maybe -EIO or -ETIMEDOUT. On this topic, I've been hesitating to change this code to the following. Would it be acceptable ? ret = wait_for_completion_timeout(...) if (ret == 0) warn[_once](...) ... if (adc_man & DA9063_ADC_MAN) { ret = -ETIMEDOUT; goto err_mread; } The warn is to make it easier to debug in case of IRQ issue. The reason I'm caring is that I happen to have triggered such issue while testing this driver, as the GPIO and PLIC on the hifive-unmatched seem to disagree with each other. I debugged this and reported to linux-riscv, and I believe the issue is not in da9063-hwmon: it also affects da9063-onkey, and my GPIO-level workaround fixes both. On a tangential topic: this chip is supposed to complete an ADC cycle in 10ms, so 1s timeout seems a lot to me. On the one hand it made the IRQ issue obvious, but on the other hand a safety factor of 100 seems enormous to me. What would be a usual/reasonable safety factor ? 10 ? 2 ? > > + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, > > + da9063_hwmon_irq_handler, > > + IRQF_TRIGGER_LOW | IRQF_ONESHOT, > > Is that correct ? The trigger condition is normally provided by > devicetree. At least it is consistent with the existing and related da9063-onkey: irq = platform_get_irq_byname(pdev, "ONKEY"); if (irq < 0) return irq; error = devm_request_threaded_irq(&pdev->dev, irq, NULL, da9063_onkey_irq_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "ONKEY", onkey); I am not familiar enough with IRQ handling to tell if IRQF_TRIGGER_LOW has an actual meaning here: in my understanding the regmap handler decides how to clear an interrupt based on regmap_irq_chip content, and this is coming from mfd/da9063-irq.c . Are both devm_request_threaded_irq() equally wrong ? > > + /* set trim temperature offset to value read at startup */ > > + hwmon->tjunc_offset = (signed char)hwmon->da9063->t_offset; > > Can you explain why this is read in and passed from the mfd driver > and not here ? I cannot, at least not with something other than "this is how I found the code", which I realise is not satisfactory. I've been holding back on changes as I felt constrained by preserving the original author's name on the changes (both Author and Signed-off-by), but this split was indeed bothering me. Regards, -- Vincent Pelletier GPG fingerprint 983A E8B7 3B91 1598 7A92 3845 CAC9 3691 4257 B0C1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/3] hwmon: da9063: HWMON driver 2021-07-07 0:20 ` Vincent Pelletier @ 2021-07-07 0:58 ` Guenter Roeck 2021-07-07 23:28 ` Vincent Pelletier 0 siblings, 1 reply; 11+ messages in thread From: Guenter Roeck @ 2021-07-07 0:58 UTC (permalink / raw) To: Vincent Pelletier Cc: Jean Delvare, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] On Wed, Jul 07, 2021 at 12:20:45AM +0000, Vincent Pelletier wrote: > Hello, > > Thanks a lot for your reviews. > > On Tue, 6 Jul 2021 10:42:01 -0700, Guenter Roeck <linux@roeck-us.net> wrote: > > -EINVAL seems wrong. Maybe -EIO or -ETIMEDOUT. > > On this topic, I've been hesitating to change this code to the > following. Would it be acceptable ? > > ret = wait_for_completion_timeout(...) > if (ret == 0) > warn[_once](...) > ... > if (adc_man & DA9063_ADC_MAN) { > ret = -ETIMEDOUT; > goto err_mread; > } > > The warn is to make it easier to debug in case of IRQ issue. The reason "to debug". Then make it a debug message. > I'm caring is that I happen to have triggered such issue while testing > this driver, as the GPIO and PLIC on the hifive-unmatched seem to > disagree with each other. I debugged this and reported to linux-riscv, > and I believe the issue is not in da9063-hwmon: it also affects > da9063-onkey, and my GPIO-level workaround fixes both. > > On a tangential topic: this chip is supposed to complete an ADC cycle > in 10ms, so 1s timeout seems a lot to me. On the one hand it made the > IRQ issue obvious, but on the other hand a safety factor of 100 seems > enormous to me. What would be a usual/reasonable safety factor ? 10 ? > 2 ? Your call, really. Guenter > > > > + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, > > > + da9063_hwmon_irq_handler, > > > + IRQF_TRIGGER_LOW | IRQF_ONESHOT, > > > > Is that correct ? The trigger condition is normally provided by > > devicetree. > > At least it is consistent with the existing and related da9063-onkey: > > irq = platform_get_irq_byname(pdev, "ONKEY"); > if (irq < 0) > return irq; > > error = devm_request_threaded_irq(&pdev->dev, irq, > NULL, da9063_onkey_irq_handler, > IRQF_TRIGGER_LOW | IRQF_ONESHOT, > "ONKEY", onkey); > > I am not familiar enough with IRQ handling to tell if IRQF_TRIGGER_LOW > has an actual meaning here: in my understanding the regmap handler > decides how to clear an interrupt based on regmap_irq_chip content, and > this is coming from mfd/da9063-irq.c . > > Are both devm_request_threaded_irq() equally wrong ? > No idea. My understanding is that devicetree data is used unless an explicit method is specified. That is why I was asking _if_ this is correct, and did not claim that it is wrong. > > > + /* set trim temperature offset to value read at startup */ > > > + hwmon->tjunc_offset = (signed char)hwmon->da9063->t_offset; > > > > Can you explain why this is read in and passed from the mfd driver > > and not here ? > > I cannot, at least not with something other than "this is how I found > the code", which I realise is not satisfactory. > I've been holding back on changes as I felt constrained by preserving > the original author's name on the changes (both Author and > Signed-off-by), but this split was indeed bothering me. > Sorry, that is not a good argument. On the contrary, if I have to assume that the code has non-technical constraints, I am inclined to just reject it for that very reason. Guenter ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/3] hwmon: da9063: HWMON driver 2021-07-07 0:58 ` Guenter Roeck @ 2021-07-07 23:28 ` Vincent Pelletier 0 siblings, 0 replies; 11+ messages in thread From: Vincent Pelletier @ 2021-07-07 23:28 UTC (permalink / raw) To: Guenter Roeck Cc: Jean Delvare, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] On Tue, 6 Jul 2021 17:58:00 -0700, Guenter Roeck <linux@roeck-us.net> wrote: > On Wed, Jul 07, 2021 at 12:20:45AM +0000, Vincent Pelletier wrote: > > On Tue, 6 Jul 2021 10:42:01 -0700, Guenter Roeck <linux@roeck-us.net> wrote: > > > > + /* set trim temperature offset to value read at startup */ > > > > + hwmon->tjunc_offset = (signed char)hwmon->da9063->t_offset; > > > > > > Can you explain why this is read in and passed from the mfd driver > > > and not here ? > > > > I cannot, at least not with something other than "this is how I found > > the code", which I realise is not satisfactory. > > I've been holding back on changes as I felt constrained by preserving > > the original author's name on the changes (both Author and > > Signed-off-by), but this split was indeed bothering me. > > > Sorry, that is not a good argument. On the contrary, if I have to assume > that the code has non-technical constraints, I am inclined to just reject > it for that very reason. These constraints are self-imposed and authorship-motivated: I do not want to steal credit, and I do not know where the "why did you remove my name from this ?" threshold is. So if I am unsure whether a slightly surprising (to my untrained eyes) but not broken piece of code is actually usual or should be changed, I erred on the status-quo side in order to make a good-faith effort at preserving the original author's name on the change. So in turn, your suggestion to change the Signed-off-by into an Originally-from removed these constraints. Is this formulation clearer ? -- Vincent Pelletier GPG fingerprint 983A E8B7 3B91 1598 7A92 3845 CAC9 3691 4257 B0C1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/3] Documentation: hwmon: New information for DA9063 2021-07-06 14:34 [PATCH 1/3] mfd: da9063: Add HWMON dependencies Vincent Pelletier 2021-07-06 14:34 ` [PATCH 2/3] hwmon: da9063: HWMON driver Vincent Pelletier @ 2021-07-06 14:34 ` Vincent Pelletier 2021-07-06 17:28 ` Guenter Roeck 2021-07-06 17:28 ` [PATCH 1/3] mfd: da9063: Add HWMON dependencies Guenter Roeck 2 siblings, 1 reply; 11+ messages in thread From: Vincent Pelletier @ 2021-07-06 14:34 UTC (permalink / raw) To: Jean Delvare, Guenter Roeck, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> Addition of HWMON documentation for the DA9063 driver. Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> Updated temperature formula, as of datasheet rev 2.3. Converted to ReStructuredText. Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> --- Changes in v2: - ReST-ified Originally submitted by Steve Twiss in 2014: https://marc.info/?l=linux-kernel&m=139560868209856&w=2 Documentation/hwmon/da9063.rst | 73 ++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Documentation/hwmon/da9063.rst diff --git a/Documentation/hwmon/da9063.rst b/Documentation/hwmon/da9063.rst new file mode 100644 index 000000000000..aae69c58a5d6 --- /dev/null +++ b/Documentation/hwmon/da9063.rst @@ -0,0 +1,73 @@ +Kernel driver da9063-hwmon +========================== + +Supported chips: + + * Dialog Semiconductor DA9063 PMIC + + Prefix: 'da9063' + + Datasheet: Publicly available at the Dialog Semiconductor website: + + http://www.dialog-semiconductor.com/products/power-management/DA9063 + +Authors: + - S Twiss <stwiss.opensource@diasemi.com> + - Vincent Pelletier <plr.vincent@gmail.com> + +Description +----------- + +The DA9063 PMIC provides a general purpose ADC with 10 bits of resolution. +It uses track and hold circuitry with an analogue input multiplexer which +allows the conversion of up to 9 different inputs: + +- Channel 0: VSYS_RES measurement of the system VDD (2.5 - 5.5V) +- Channel 1: ADCIN1_RES high impedance input (0 - 2.5V) +- Channel 2: ADCIN2_RES high impedance input (0 - 2.5V) +- Channel 3: ADCIN3_RES high impedance input (0 - 2.5V) +- Channel 4: Tjunc measurement of internal temperature sensor +- Channel 5: VBBAT measurement of the backup battery voltage (0 - 5.0V) +- Channel 6: N/A Reserved +- Channel 7: N/A Reserved +- Channel 8: MON1_RES group 1 internal regulators voltage (0 - 5.0V) +- Channel 9: MON2_RES group 2 internal regulators voltage (0 - 5.0V) +- Channel 10: MON3_RES group 3 internal regulators voltage (0 - 5.0V) + +The MUX selects from and isolates the 9 inputs and presents the channel to +be measured to the ADC input. When selected, an input amplifier on the VSYS +channel subtracts the VDDCORE reference voltage and scales the signal to the +correct value for the ADC. + +The analog ADC includes current sources at ADC_IN1, ADC_IN2 and ADC_IN3 to +support resistive measurements. + +Channels 1, 2 and 3 current source capability can be set through the ADC +thresholds ADC_CFG register and values for ADCIN1_CUR, ADCIN2_CUR and +ADCIN3_CUR. Settings for ADCIN1_CUR and ADCIN2_CUR are 1.0, 2.0, 10 and +40 micro Amps. The setting for ADCIN3_CUR is 10 micro Amps. + +Voltage Monitoring +------------------ + +The manual measurement allows monitoring of the system voltage VSYS, the +auxiliary channels ADCIN1, ADCIN2 and ADCIN3, and a VBBAT measurement of +the backup battery voltage (0 - 5.0V). The manual measurements store 10 +bits of ADC resolution. + +The manual ADC measurements attributes described above are supported by +the driver. + +The automatic ADC measurement is not supported by the driver. + +Temperature Monitoring +---------------------- + +Temperatures are sampled by a 10 bit ADC. Junction temperatures +are monitored by the ADC channels. + +The junction temperature is calculated: + + Degrees celsius = -0.398 * (ADC_RES - T_OFFSET) + 330; + +The junction temperature attribute is supported by the driver. -- 2.32.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 3/3] Documentation: hwmon: New information for DA9063 2021-07-06 14:34 ` [PATCH 3/3] Documentation: hwmon: New information for DA9063 Vincent Pelletier @ 2021-07-06 17:28 ` Guenter Roeck 0 siblings, 0 replies; 11+ messages in thread From: Guenter Roeck @ 2021-07-06 17:28 UTC (permalink / raw) To: Vincent Pelletier Cc: Jean Delvare, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] On Tue, Jul 06, 2021 at 02:34:49PM +0000, Vincent Pelletier wrote: > From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> > > Addition of HWMON documentation for the DA9063 driver. > > Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> > > Updated temperature formula, as of datasheet rev 2.3. > Converted to ReStructuredText. > > Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> > --- > Changes in v2: > - ReST-ified > > Originally submitted by Steve Twiss in 2014: > https://marc.info/?l=linux-kernel&m=139560868209856&w=2 > > Documentation/hwmon/da9063.rst | 73 ++++++++++++++++++++++++++++++++++ Needs to be added to index.rst. > 1 file changed, 73 insertions(+) > create mode 100644 Documentation/hwmon/da9063.rst > > diff --git a/Documentation/hwmon/da9063.rst b/Documentation/hwmon/da9063.rst > new file mode 100644 > index 000000000000..aae69c58a5d6 > --- /dev/null > +++ b/Documentation/hwmon/da9063.rst > @@ -0,0 +1,73 @@ > +Kernel driver da9063-hwmon > +========================== > + > +Supported chips: > + > + * Dialog Semiconductor DA9063 PMIC > + > + Prefix: 'da9063' > + > + Datasheet: Publicly available at the Dialog Semiconductor website: > + > + http://www.dialog-semiconductor.com/products/power-management/DA9063 > + > +Authors: > + - S Twiss <stwiss.opensource@diasemi.com> > + - Vincent Pelletier <plr.vincent@gmail.com> > + > +Description > +----------- > + > +The DA9063 PMIC provides a general purpose ADC with 10 bits of resolution. > +It uses track and hold circuitry with an analogue input multiplexer which > +allows the conversion of up to 9 different inputs: > + > +- Channel 0: VSYS_RES measurement of the system VDD (2.5 - 5.5V) > +- Channel 1: ADCIN1_RES high impedance input (0 - 2.5V) > +- Channel 2: ADCIN2_RES high impedance input (0 - 2.5V) > +- Channel 3: ADCIN3_RES high impedance input (0 - 2.5V) > +- Channel 4: Tjunc measurement of internal temperature sensor > +- Channel 5: VBBAT measurement of the backup battery voltage (0 - 5.0V) > +- Channel 6: N/A Reserved > +- Channel 7: N/A Reserved > +- Channel 8: MON1_RES group 1 internal regulators voltage (0 - 5.0V) > +- Channel 9: MON2_RES group 2 internal regulators voltage (0 - 5.0V) > +- Channel 10: MON3_RES group 3 internal regulators voltage (0 - 5.0V) > + > +The MUX selects from and isolates the 9 inputs and presents the channel to > +be measured to the ADC input. When selected, an input amplifier on the VSYS > +channel subtracts the VDDCORE reference voltage and scales the signal to the > +correct value for the ADC. > + > +The analog ADC includes current sources at ADC_IN1, ADC_IN2 and ADC_IN3 to > +support resistive measurements. > + > +Channels 1, 2 and 3 current source capability can be set through the ADC > +thresholds ADC_CFG register and values for ADCIN1_CUR, ADCIN2_CUR and > +ADCIN3_CUR. Settings for ADCIN1_CUR and ADCIN2_CUR are 1.0, 2.0, 10 and > +40 micro Amps. The setting for ADCIN3_CUR is 10 micro Amps. > + > +Voltage Monitoring > +------------------ > + > +The manual measurement allows monitoring of the system voltage VSYS, the > +auxiliary channels ADCIN1, ADCIN2 and ADCIN3, and a VBBAT measurement of > +the backup battery voltage (0 - 5.0V). The manual measurements store 10 > +bits of ADC resolution. > + > +The manual ADC measurements attributes described above are supported by > +the driver. > + > +The automatic ADC measurement is not supported by the driver. > + > +Temperature Monitoring > +---------------------- > + > +Temperatures are sampled by a 10 bit ADC. Junction temperatures > +are monitored by the ADC channels. > + > +The junction temperature is calculated: > + > + Degrees celsius = -0.398 * (ADC_RES - T_OFFSET) + 330; > + > +The junction temperature attribute is supported by the driver. > -- > 2.32.0 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/3] mfd: da9063: Add HWMON dependencies 2021-07-06 14:34 [PATCH 1/3] mfd: da9063: Add HWMON dependencies Vincent Pelletier 2021-07-06 14:34 ` [PATCH 2/3] hwmon: da9063: HWMON driver Vincent Pelletier 2021-07-06 14:34 ` [PATCH 3/3] Documentation: hwmon: New information for DA9063 Vincent Pelletier @ 2021-07-06 17:28 ` Guenter Roeck 2 siblings, 0 replies; 11+ messages in thread From: Guenter Roeck @ 2021-07-06 17:28 UTC (permalink / raw) To: Vincent Pelletier Cc: Jean Delvare, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] On Tue, Jul 06, 2021 at 02:34:47PM +0000, Vincent Pelletier wrote: > From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> > > Dependencies required for DA9063 HWMON support. > > Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> > > Directly set da9063->t_offset. > Let MFD probe succeed even if DA9063_REG_T_OFFSET cannot be read. > > Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> > --- > Changes in v2: > - registers.h changes moved from patch 2 Please version your patch series. > > Originally submitted by Steve Twiss in 2014: > https://marc.info/?l=linux-kernel&m=139560864709852&w=2 > > drivers/mfd/da9063-core.c | 8 +++++++ > include/linux/mfd/da9063/core.h | 3 +++ > include/linux/mfd/da9063/registers.h | 34 ++++++++++++++++++++++++++++ > 3 files changed, 45 insertions(+) > > diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c > index df407c3afce3..14c2a8df9ae3 100644 > --- a/drivers/mfd/da9063-core.c > +++ b/drivers/mfd/da9063-core.c > @@ -197,6 +197,14 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) > } > } > > + ret = regmap_read(da9063->regmap, DA9063_REG_T_OFFSET, &da9063->t_offset); > + if (ret < 0) { > + da9063->t_offset = 0; > + dev_warn(da9063->dev, > + "Temperature trimming value cannot be read (defaulting to 0)\n"); > + ret = 0; > + } > + > return ret; > } > > diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h > index fa7a43f02f27..c0c57c6f6230 100644 > --- a/include/linux/mfd/da9063/core.h > +++ b/include/linux/mfd/da9063/core.h > @@ -85,6 +85,9 @@ struct da9063 { > int chip_irq; > unsigned int irq_base; > struct regmap_irq_chip_data *regmap_irq; > + > + /* Trimming */ > + int t_offset; > }; > > int da9063_device_init(struct da9063 *da9063, unsigned int irq); > diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h > index 6e0f66a2e727..297631ddda39 100644 > --- a/include/linux/mfd/da9063/registers.h > +++ b/include/linux/mfd/da9063/registers.h > @@ -512,6 +512,7 @@ > > /* DA9063_REG_GPIO_0_1 (addr=0x15) */ > #define DA9063_GPIO0_PIN_MASK 0x03 > +#define DA9063_GPIO0_PIN_MASK_SHIFT 0 > #define DA9063_GPIO0_PIN_ADCIN1 0x00 > #define DA9063_GPIO0_PIN_GPI 0x01 > #define DA9063_GPIO0_PIN_GPO_OD 0x02 > @@ -523,6 +524,7 @@ > #define DA9063_GPIO0_TYPE_GPO_VDD_IO2 0x04 > #define DA9063_GPIO0_NO_WAKEUP 0x08 > #define DA9063_GPIO1_PIN_MASK 0x30 > +#define DA9063_GPIO1_PIN_MASK_SHIFT 4 > #define DA9063_GPIO1_PIN_ADCIN2_COMP 0x00 > #define DA9063_GPIO1_PIN_GPI 0x10 > #define DA9063_GPIO1_PIN_GPO_OD 0x20 > @@ -536,6 +538,7 @@ > > /* DA9063_REG_GPIO_2_3 (addr=0x16) */ > #define DA9063_GPIO2_PIN_MASK 0x03 > +#define DA9063_GPIO2_PIN_MASK_SHIFT 0 > #define DA9063_GPIO2_PIN_ADCIN3 0x00 > #define DA9063_GPIO2_PIN_GPI 0x01 > #define DA9063_GPIO2_PIN_GPO_PSS 0x02 > @@ -851,6 +854,7 @@ > #define DA9063_VSYS_VAL_BASE 0x00 > > /* DA9063_REG_ADC_RES_L (addr=0x37) */ > +#define DA9063_ADC_RES_L_SHIFT 6 > #define DA9063_ADC_RES_L_BITS 2 > #define DA9063_ADC_RES_L_MASK 0xC0 > > @@ -1014,6 +1018,36 @@ > #define DA9063_GPIO_DIM 0x80 > #define DA9063_GPIO_PWM_MASK 0x7F > > +/* DA9063_REG_ADC_CFG (addr=0xC9) */ > +#define DA9063_REG_ADCIN1_CUR_MASK 0x03 > +#define DA9063_REG_ADCIN1_CUR_SHIFT 0 > +#define DA9063_ADCIN1_CUR_1UA 0x00 > +#define DA9063_ADCIN1_CUR_2UA 0x01 > +#define DA9063_ADCIN1_CUR_10UA 0x02 > +#define DA9063_ADCIN1_CUR_40UA 0x03 > +#define DA9063_REG_ADCIN2_CUR_MASK 0x0C > +#define DA9063_REG_ADCIN2_CUR_SHIFT 2 > +#define DA9063_ADCIN2_CUR_1UA 0x00 > +#define DA9063_ADCIN2_CUR_2UA 0x01 > +#define DA9063_ADCIN2_CUR_10UA 0x02 > +#define DA9063_ADCIN2_CUR_40UA 0x03 > +#define DA9063_REG_ADCIN3_CUR_MASK 0x10 > +#define DA9063_REG_ADCIN3_CUR_SHIFT 4 > +#define DA9063_ADCIN3_CUR_10UA 0x00 > +#define DA9063_ADCIN3_CUR_40UA 0x01 > +#define DA9063_REG_ADCIN1_DEB_MASK 0x20 > +#define DA9063_REG_ADCIN1_DEB_SHIFT 5 > +#define DA9063_ADCIN1_DEB_OFF 0x00 > +#define DA9063_ADCIN1_DEB_ON 0x01 > +#define DA9063_REG_ADCIN2_DEB_MASK 0x40 > +#define DA9063_REG_ADCIN2_DEB_SHIFT 6 > +#define DA9063_ADCIN2_DEB_OFF 0x00 > +#define DA9063_ADCIN2_DEB_ON 0x01 > +#define DA9063_REG_ADCIN3_DEB_MASK 0x80 > +#define DA9063_REG_ADCIN3_DEB_SHIFT 7 > +#define DA9063_ADCIN3_DEB_OFF 0x00 > +#define DA9063_ADCIN3_DEB_ON 0x01 > + > /* DA9063_REG_CONFIG_H (addr=0x10D) */ > #define DA9063_PWM_CLK_MASK 0x01 > #define DA9063_PWM_CLK_PWM2MHZ 0x00 > -- > 2.32.0 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/3] mfd: da9063: Add HWMON dependencies @ 2021-07-06 0:01 Vincent Pelletier 2021-07-06 0:01 ` [PATCH 2/3] hwmon: da9063: HWMON driver Vincent Pelletier 0 siblings, 1 reply; 11+ messages in thread From: Vincent Pelletier @ 2021-07-06 0:01 UTC (permalink / raw) To: Jean Delvare, Guenter Roeck, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> Dependencies required for DA9063 HWMON support. Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> Directly set da9063->t_offset. Let MFD probe succeed even if DA9063_REG_T_OFFSET cannot be read. Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> --- Originally submitted by Steve Twiss in 2014: https://marc.info/?l=linux-kernel&m=139560864709852&w=2 drivers/mfd/da9063-core.c | 8 ++++++++ include/linux/mfd/da9063/core.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c index df407c3afce3..14c2a8df9ae3 100644 --- a/drivers/mfd/da9063-core.c +++ b/drivers/mfd/da9063-core.c @@ -197,6 +197,14 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq) } } + ret = regmap_read(da9063->regmap, DA9063_REG_T_OFFSET, &da9063->t_offset); + if (ret < 0) { + da9063->t_offset = 0; + dev_warn(da9063->dev, + "Temperature trimming value cannot be read (defaulting to 0)\n"); + ret = 0; + } + return ret; } diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h index fa7a43f02f27..c0c57c6f6230 100644 --- a/include/linux/mfd/da9063/core.h +++ b/include/linux/mfd/da9063/core.h @@ -85,6 +85,9 @@ struct da9063 { int chip_irq; unsigned int irq_base; struct regmap_irq_chip_data *regmap_irq; + + /* Trimming */ + int t_offset; }; int da9063_device_init(struct da9063 *da9063, unsigned int irq); -- 2.32.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/3] hwmon: da9063: HWMON driver 2021-07-06 0:01 Vincent Pelletier @ 2021-07-06 0:01 ` Vincent Pelletier 2021-07-06 0:28 ` Guenter Roeck 0 siblings, 1 reply; 11+ messages in thread From: Vincent Pelletier @ 2021-07-06 0:01 UTC (permalink / raw) To: Jean Delvare, Guenter Roeck, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> Add the HWMON driver for DA9063 Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> Simplify and modernise the code a bit. Add minimal of_match_table. Fix logic inversion in detecting conversion end. Drop support for ADCIN: these are multi-purpose channels and must not be reconfigured unless explicitly authorised by the board description. Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> --- This patch depends on patch 1/3. Originally submitted by Steve Twiss in 2014: https://marc.info/?l=linux-kernel&m=139560868309857&w=2 drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/da9063-hwmon.c | 287 +++++++++++++++++++++++++++ include/linux/mfd/da9063/registers.h | 34 ++++ 4 files changed, 332 insertions(+) create mode 100644 drivers/hwmon/da9063-hwmon.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 87624902ea80..17244cfaa855 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -515,6 +515,16 @@ config SENSORS_DA9055 This driver can also be built as a module. If so, the module will be called da9055-hwmon. +config SENSORS_DA9063 + tristate "Dialog Semiconductor DA9063" + depends on MFD_DA9063 + help + If you say yes here you get support for the hardware + monitoring features of the DA9063 Power Management IC. + + This driver can also be built as a module. If so, the module + will be called da9063-hwmon. + config SENSORS_I5K_AMB tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" depends on PCI diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 59e78bc212cf..6855711ed9ec 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_CORSAIR_CPRO) += corsair-cpro.o obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o +obj-$(CONFIG_SENSORS_DA9063) += da9063-hwmon.o obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DRIVETEMP) += drivetemp.o diff --git a/drivers/hwmon/da9063-hwmon.c b/drivers/hwmon/da9063-hwmon.c new file mode 100644 index 000000000000..35b5bb0290ca --- /dev/null +++ b/drivers/hwmon/da9063-hwmon.c @@ -0,0 +1,287 @@ +/* da9063-hwmon.c - Hardware monitor support for DA9063 + * Copyright (C) 2014 Dialog Semiconductor Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/platform_device.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/regmap.h> +#include <linux/mfd/da9063/core.h> +#include <linux/mod_devicetable.h> + +#define DA9063_ADC_RES (1 << (DA9063_ADC_RES_L_BITS + DA9063_ADC_RES_M_BITS)) +#define DA9063_ADC_MAX (DA9063_ADC_RES - 1) +#define DA9063_2V5 2500 +#define DA9063_5V0 5000 +#define DA9063_5V5 5500 +#define DA9063_TJUNC_M -398 +#define DA9063_TJUNC_O 330000 +#define DA9063_VBBAT_M 2048 + +enum da9063_adc { + DA9063_CHAN_VSYS = DA9063_ADC_MUX_VSYS, + DA9063_CHAN_ADCIN1 = DA9063_ADC_MUX_ADCIN1, + DA9063_CHAN_ADCIN2 = DA9063_ADC_MUX_ADCIN2, + DA9063_CHAN_ADCIN3 = DA9063_ADC_MUX_ADCIN3, + DA9063_CHAN_TJUNC = DA9063_ADC_MUX_T_SENSE, + DA9063_CHAN_VBBAT = DA9063_ADC_MUX_VBBAT, + DA9063_CHAN_LDO_G1 = DA9063_ADC_MUX_LDO_G1, + DA9063_CHAN_LDO_G2 = DA9063_ADC_MUX_LDO_G2, + DA9063_CHAN_LDO_G3 = DA9063_ADC_MUX_LDO_G3 +}; + +struct da9063_hwmon { + struct da9063 *da9063; + struct mutex hwmon_mutex; + struct completion adc_ready; + signed char tjunc_offset; +}; + +static int da9063_adc_convert(struct da9063_hwmon *hwmon, int channel, + int *value) +{ + int val = *value; + int ret = 0; + + switch (channel) { + case DA9063_CHAN_VSYS: + val = ((DA9063_5V5 - DA9063_2V5) * val) / DA9063_ADC_MAX + + DA9063_2V5; + break; + case DA9063_CHAN_TJUNC: + val -= hwmon->tjunc_offset; + val = DA9063_TJUNC_M * val + DA9063_TJUNC_O; + break; + case DA9063_CHAN_VBBAT: + val = (DA9063_5V0 * val) / DA9063_ADC_MAX; + break; + default: + ret = -EINVAL; + goto err_convert; + } + + *value = val; +err_convert: + return ret; +} + + +static int da9063_adc_manual_read(struct da9063_hwmon *hwmon, int channel) +{ + int ret; + unsigned char val; + unsigned char data[2]; + int adc_man; + + mutex_lock(&hwmon->hwmon_mutex); + + init_completion(&hwmon->adc_ready); + + val = (channel & DA9063_ADC_MUX_MASK) | DA9063_ADC_MAN; + ret = regmap_update_bits(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, + DA9063_ADC_MUX_MASK | DA9063_ADC_MAN, val); + if (ret < 0) + goto err_mread; + + ret = wait_for_completion_timeout(&hwmon->adc_ready, + msecs_to_jiffies(1000)); + if (ret == 0) { + ret = -ETIMEDOUT; + goto err_mread; + } + + ret = regmap_read(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, &adc_man); + if (ret < 0) + goto err_mread; + + /* data value is not ready */ + if (adc_man & DA9063_ADC_MAN) { + ret = -EINVAL; + goto err_mread; + } + + ret = regmap_bulk_read(hwmon->da9063->regmap, + DA9063_REG_ADC_RES_L, data, 2); + if (ret < 0) + goto err_mread; + + ret = (data[0] & DA9063_ADC_RES_L_MASK) >> DA9063_ADC_RES_L_SHIFT; + ret |= data[1] << DA9063_ADC_RES_L_BITS; +err_mread: + mutex_unlock(&hwmon->hwmon_mutex); + return ret; +} + +static irqreturn_t da9063_hwmon_irq_handler(int irq, void *irq_data) +{ + struct da9063_hwmon *hwmon = irq_data; + complete(&hwmon->adc_ready); + return IRQ_HANDLED; +} + +static ssize_t da9063_adc_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct da9063_hwmon *hwmon = dev_get_drvdata(dev); + int channel = to_sensor_dev_attr(devattr)->index; + int val; + int ret; + + switch (channel) { + case DA9063_CHAN_VSYS: + case DA9063_CHAN_TJUNC: + case DA9063_CHAN_VBBAT: + /* fallthrough for internal measures */ + val = da9063_adc_manual_read(hwmon, channel); + if (val < 0) { + dev_err(dev, "ADC read error %d\n", val); + return val; + } + break; + + default: + /* error case */ + ret = -EINVAL; + goto err_read; + } + + ret = da9063_adc_convert(hwmon, channel, &val); + if (ret < 0) { + dev_err(dev, "Failed to convert ADC value %d\n", ret); + goto err_read; + } + + return sprintf(buf, "%d\n", val); +err_read: + return ret; +} + + +static ssize_t da9063_label_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int channel = to_sensor_dev_attr(devattr)->index; + char *label; + + switch (channel) { + case DA9063_CHAN_VSYS: + label = "VSYS"; + break; + case DA9063_CHAN_TJUNC: + label = "TJUNC"; + break; + case DA9063_CHAN_VBBAT: + label = "VBBAT"; + break; + default: + label = "UNKNOWN"; + } + + return sprintf(buf, "%s\n", label); +} + +static SENSOR_DEVICE_ATTR_RO(in0_input, + da9063_adc, DA9063_CHAN_VSYS); +static SENSOR_DEVICE_ATTR_RO(in0_label, + da9063_label, DA9063_CHAN_VSYS); + +static SENSOR_DEVICE_ATTR_RO(in4_input, + da9063_adc, DA9063_CHAN_VBBAT); +static SENSOR_DEVICE_ATTR_RO(in4_label, + da9063_label, DA9063_CHAN_VBBAT); + +static SENSOR_DEVICE_ATTR_RO(temp1_input, + da9063_adc, DA9063_CHAN_TJUNC); +static SENSOR_DEVICE_ATTR_RO(temp1_label, + da9063_label, DA9063_CHAN_TJUNC); + +static struct attribute *da9063_attrs[] = { + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in0_label.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in4_label.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_label.dev_attr.attr, + NULL +}; + +ATTRIBUTE_GROUPS(da9063); + +static int da9063_hwmon_probe(struct platform_device *pdev) +{ + struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); + struct da9063_hwmon *hwmon; + struct device *hwmon_dev; + int irq; + int ret; + + hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9063_hwmon), + GFP_KERNEL); + if (!hwmon) + return -ENOMEM; + + mutex_init(&hwmon->hwmon_mutex); + init_completion(&hwmon->adc_ready); + hwmon->da9063 = da9063; + + irq = platform_get_irq_byname(pdev, DA9063_DRVNAME_HWMON); + if (irq < 0) + return irq; + + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + da9063_hwmon_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "HWMON", hwmon); + if (ret) { + dev_err(&pdev->dev, "Failed to request IRQ.\n"); + return ret; + } + + platform_set_drvdata(pdev, hwmon); + + /* set trim temperature offset to value read at startup */ + hwmon->tjunc_offset = (signed char)hwmon->da9063->t_offset; + + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, + "da9063", + hwmon, da9063_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const struct of_device_id da9063_dt_ids[] = { + { .compatible = DA9063_DRVNAME_HWMON, }, + { } +}; +MODULE_DEVICE_TABLE(of, da9063_dt_ids); + +static struct platform_driver da9063_hwmon_driver = { + .probe = da9063_hwmon_probe, + .driver = { + .name = DA9063_DRVNAME_HWMON, + .of_match_table = da9063_dt_ids, + }, +}; +module_platform_driver(da9063_hwmon_driver); + +MODULE_DESCRIPTION("Hardware monitor support device driver for Dialog DA9063"); +MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DA9063_DRVNAME_HWMON); diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h index 6e0f66a2e727..297631ddda39 100644 --- a/include/linux/mfd/da9063/registers.h +++ b/include/linux/mfd/da9063/registers.h @@ -512,6 +512,7 @@ /* DA9063_REG_GPIO_0_1 (addr=0x15) */ #define DA9063_GPIO0_PIN_MASK 0x03 +#define DA9063_GPIO0_PIN_MASK_SHIFT 0 #define DA9063_GPIO0_PIN_ADCIN1 0x00 #define DA9063_GPIO0_PIN_GPI 0x01 #define DA9063_GPIO0_PIN_GPO_OD 0x02 @@ -523,6 +524,7 @@ #define DA9063_GPIO0_TYPE_GPO_VDD_IO2 0x04 #define DA9063_GPIO0_NO_WAKEUP 0x08 #define DA9063_GPIO1_PIN_MASK 0x30 +#define DA9063_GPIO1_PIN_MASK_SHIFT 4 #define DA9063_GPIO1_PIN_ADCIN2_COMP 0x00 #define DA9063_GPIO1_PIN_GPI 0x10 #define DA9063_GPIO1_PIN_GPO_OD 0x20 @@ -536,6 +538,7 @@ /* DA9063_REG_GPIO_2_3 (addr=0x16) */ #define DA9063_GPIO2_PIN_MASK 0x03 +#define DA9063_GPIO2_PIN_MASK_SHIFT 0 #define DA9063_GPIO2_PIN_ADCIN3 0x00 #define DA9063_GPIO2_PIN_GPI 0x01 #define DA9063_GPIO2_PIN_GPO_PSS 0x02 @@ -851,6 +854,7 @@ #define DA9063_VSYS_VAL_BASE 0x00 /* DA9063_REG_ADC_RES_L (addr=0x37) */ +#define DA9063_ADC_RES_L_SHIFT 6 #define DA9063_ADC_RES_L_BITS 2 #define DA9063_ADC_RES_L_MASK 0xC0 @@ -1014,6 +1018,36 @@ #define DA9063_GPIO_DIM 0x80 #define DA9063_GPIO_PWM_MASK 0x7F +/* DA9063_REG_ADC_CFG (addr=0xC9) */ +#define DA9063_REG_ADCIN1_CUR_MASK 0x03 +#define DA9063_REG_ADCIN1_CUR_SHIFT 0 +#define DA9063_ADCIN1_CUR_1UA 0x00 +#define DA9063_ADCIN1_CUR_2UA 0x01 +#define DA9063_ADCIN1_CUR_10UA 0x02 +#define DA9063_ADCIN1_CUR_40UA 0x03 +#define DA9063_REG_ADCIN2_CUR_MASK 0x0C +#define DA9063_REG_ADCIN2_CUR_SHIFT 2 +#define DA9063_ADCIN2_CUR_1UA 0x00 +#define DA9063_ADCIN2_CUR_2UA 0x01 +#define DA9063_ADCIN2_CUR_10UA 0x02 +#define DA9063_ADCIN2_CUR_40UA 0x03 +#define DA9063_REG_ADCIN3_CUR_MASK 0x10 +#define DA9063_REG_ADCIN3_CUR_SHIFT 4 +#define DA9063_ADCIN3_CUR_10UA 0x00 +#define DA9063_ADCIN3_CUR_40UA 0x01 +#define DA9063_REG_ADCIN1_DEB_MASK 0x20 +#define DA9063_REG_ADCIN1_DEB_SHIFT 5 +#define DA9063_ADCIN1_DEB_OFF 0x00 +#define DA9063_ADCIN1_DEB_ON 0x01 +#define DA9063_REG_ADCIN2_DEB_MASK 0x40 +#define DA9063_REG_ADCIN2_DEB_SHIFT 6 +#define DA9063_ADCIN2_DEB_OFF 0x00 +#define DA9063_ADCIN2_DEB_ON 0x01 +#define DA9063_REG_ADCIN3_DEB_MASK 0x80 +#define DA9063_REG_ADCIN3_DEB_SHIFT 7 +#define DA9063_ADCIN3_DEB_OFF 0x00 +#define DA9063_ADCIN3_DEB_ON 0x01 + /* DA9063_REG_CONFIG_H (addr=0x10D) */ #define DA9063_PWM_CLK_MASK 0x01 #define DA9063_PWM_CLK_PWM2MHZ 0x00 -- 2.32.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/3] hwmon: da9063: HWMON driver 2021-07-06 0:01 ` [PATCH 2/3] hwmon: da9063: HWMON driver Vincent Pelletier @ 2021-07-06 0:28 ` Guenter Roeck 0 siblings, 0 replies; 11+ messages in thread From: Guenter Roeck @ 2021-07-06 0:28 UTC (permalink / raw) To: Vincent Pelletier, Jean Delvare, Jonathan Corbet, Support Opensource, Lee Jones, linux-hwmon, linux-doc, linux-kernel, Opensource [Steve Twiss] On 7/5/21 5:01 PM, Vincent Pelletier wrote: > From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com> > > Add the HWMON driver for DA9063 > > Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com> > > Simplify and modernise the code a bit. > Add minimal of_match_table. > Fix logic inversion in detecting conversion end. > Drop support for ADCIN: these are multi-purpose channels and must not > be reconfigured unless explicitly authorised by the board description. > > Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com> > --- > This patch depends on patch 1/3. > Originally submitted by Steve Twiss in 2014: > https://marc.info/?l=linux-kernel&m=139560868309857&w=2 > > drivers/hwmon/Kconfig | 10 + > drivers/hwmon/Makefile | 1 + > drivers/hwmon/da9063-hwmon.c | 287 +++++++++++++++++++++++++++ > include/linux/mfd/da9063/registers.h | 34 ++++ > 4 files changed, 332 insertions(+) > create mode 100644 drivers/hwmon/da9063-hwmon.c > > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig > index 87624902ea80..17244cfaa855 100644 > --- a/drivers/hwmon/Kconfig > +++ b/drivers/hwmon/Kconfig > @@ -515,6 +515,16 @@ config SENSORS_DA9055 > This driver can also be built as a module. If so, the module > will be called da9055-hwmon. > > +config SENSORS_DA9063 > + tristate "Dialog Semiconductor DA9063" > + depends on MFD_DA9063 > + help > + If you say yes here you get support for the hardware > + monitoring features of the DA9063 Power Management IC. > + > + This driver can also be built as a module. If so, the module > + will be called da9063-hwmon. > + > config SENSORS_I5K_AMB > tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" > depends on PCI > diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile > index 59e78bc212cf..6855711ed9ec 100644 > --- a/drivers/hwmon/Makefile > +++ b/drivers/hwmon/Makefile > @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_CORSAIR_CPRO) += corsair-cpro.o > obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o > obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o > obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o > +obj-$(CONFIG_SENSORS_DA9063) += da9063-hwmon.o > obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o > obj-$(CONFIG_SENSORS_DME1737) += dme1737.o > obj-$(CONFIG_SENSORS_DRIVETEMP) += drivetemp.o > diff --git a/drivers/hwmon/da9063-hwmon.c b/drivers/hwmon/da9063-hwmon.c > new file mode 100644 > index 000000000000..35b5bb0290ca > --- /dev/null > +++ b/drivers/hwmon/da9063-hwmon.c > @@ -0,0 +1,287 @@ > +/* da9063-hwmon.c - Hardware monitor support for DA9063 > + * Copyright (C) 2014 Dialog Semiconductor Ltd. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Library General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Library General Public License for more details. > + */ > + > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/err.h> > +#include <linux/delay.h> > +#include <linux/init.h> > +#include <linux/slab.h> > +#include <linux/string.h> > +#include <linux/platform_device.h> > +#include <linux/hwmon.h> > +#include <linux/hwmon-sysfs.h> > +#include <linux/regmap.h> > +#include <linux/mfd/da9063/core.h> > +#include <linux/mod_devicetable.h> > + Alphabetic include file order, please. > +#define DA9063_ADC_RES (1 << (DA9063_ADC_RES_L_BITS + DA9063_ADC_RES_M_BITS)) > +#define DA9063_ADC_MAX (DA9063_ADC_RES - 1) > +#define DA9063_2V5 2500 > +#define DA9063_5V0 5000 > +#define DA9063_5V5 5500 > +#define DA9063_TJUNC_M -398 > +#define DA9063_TJUNC_O 330000 > +#define DA9063_VBBAT_M 2048 > + > +enum da9063_adc { > + DA9063_CHAN_VSYS = DA9063_ADC_MUX_VSYS, > + DA9063_CHAN_ADCIN1 = DA9063_ADC_MUX_ADCIN1, > + DA9063_CHAN_ADCIN2 = DA9063_ADC_MUX_ADCIN2, > + DA9063_CHAN_ADCIN3 = DA9063_ADC_MUX_ADCIN3, > + DA9063_CHAN_TJUNC = DA9063_ADC_MUX_T_SENSE, > + DA9063_CHAN_VBBAT = DA9063_ADC_MUX_VBBAT, > + DA9063_CHAN_LDO_G1 = DA9063_ADC_MUX_LDO_G1, > + DA9063_CHAN_LDO_G2 = DA9063_ADC_MUX_LDO_G2, > + DA9063_CHAN_LDO_G3 = DA9063_ADC_MUX_LDO_G3 > +}; > + > +struct da9063_hwmon { > + struct da9063 *da9063; > + struct mutex hwmon_mutex; > + struct completion adc_ready; > + signed char tjunc_offset; > +}; > + > +static int da9063_adc_convert(struct da9063_hwmon *hwmon, int channel, > + int *value) > +{ > + int val = *value; > + int ret = 0; > + > + switch (channel) { > + case DA9063_CHAN_VSYS: > + val = ((DA9063_5V5 - DA9063_2V5) * val) / DA9063_ADC_MAX + > + DA9063_2V5; > + break; > + case DA9063_CHAN_TJUNC: > + val -= hwmon->tjunc_offset; > + val = DA9063_TJUNC_M * val + DA9063_TJUNC_O; > + break; > + case DA9063_CHAN_VBBAT: > + val = (DA9063_5V0 * val) / DA9063_ADC_MAX; > + break; > + default: > + ret = -EINVAL; > + goto err_convert; > + } > + > + *value = val; > +err_convert: > + return ret; > +} > + > + > +static int da9063_adc_manual_read(struct da9063_hwmon *hwmon, int channel) > +{ > + int ret; > + unsigned char val; > + unsigned char data[2]; > + int adc_man; > + > + mutex_lock(&hwmon->hwmon_mutex); > + > + init_completion(&hwmon->adc_ready); > + > + val = (channel & DA9063_ADC_MUX_MASK) | DA9063_ADC_MAN; > + ret = regmap_update_bits(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, > + DA9063_ADC_MUX_MASK | DA9063_ADC_MAN, val); > + if (ret < 0) > + goto err_mread; > + > + ret = wait_for_completion_timeout(&hwmon->adc_ready, > + msecs_to_jiffies(1000)); > + if (ret == 0) { > + ret = -ETIMEDOUT; > + goto err_mread; > + } > + > + ret = regmap_read(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, &adc_man); > + if (ret < 0) > + goto err_mread; > + > + /* data value is not ready */ > + if (adc_man & DA9063_ADC_MAN) { > + ret = -EINVAL; > + goto err_mread; > + } > + > + ret = regmap_bulk_read(hwmon->da9063->regmap, > + DA9063_REG_ADC_RES_L, data, 2); > + if (ret < 0) > + goto err_mread; > + > + ret = (data[0] & DA9063_ADC_RES_L_MASK) >> DA9063_ADC_RES_L_SHIFT; > + ret |= data[1] << DA9063_ADC_RES_L_BITS; > +err_mread: > + mutex_unlock(&hwmon->hwmon_mutex); > + return ret; > +} > + > +static irqreturn_t da9063_hwmon_irq_handler(int irq, void *irq_data) > +{ > + struct da9063_hwmon *hwmon = irq_data; > + complete(&hwmon->adc_ready); > + return IRQ_HANDLED; > +} > + > +static ssize_t da9063_adc_show(struct device *dev, > + struct device_attribute *devattr, char *buf) > +{ > + struct da9063_hwmon *hwmon = dev_get_drvdata(dev); > + int channel = to_sensor_dev_attr(devattr)->index; > + int val; > + int ret; > + > + switch (channel) { > + case DA9063_CHAN_VSYS: > + case DA9063_CHAN_TJUNC: > + case DA9063_CHAN_VBBAT: > + /* fallthrough for internal measures */ > + val = da9063_adc_manual_read(hwmon, channel); > + if (val < 0) { > + dev_err(dev, "ADC read error %d\n", val); > + return val; > + } > + break; > + > + default: > + /* error case */ > + ret = -EINVAL; > + goto err_read; goto to return statement is unnecessary (and inconsistent). > + } > + > + ret = da9063_adc_convert(hwmon, channel, &val); > + if (ret < 0) { > + dev_err(dev, "Failed to convert ADC value %d\n", ret); > + goto err_read; > + } > + > + return sprintf(buf, "%d\n", val); > +err_read: > + return ret; > +} > + > + > +static ssize_t da9063_label_show(struct device *dev, > + struct device_attribute *devattr, char *buf) > +{ > + int channel = to_sensor_dev_attr(devattr)->index; > + char *label; > + > + switch (channel) { > + case DA9063_CHAN_VSYS: > + label = "VSYS"; > + break; > + case DA9063_CHAN_TJUNC: > + label = "TJUNC"; > + break; > + case DA9063_CHAN_VBBAT: > + label = "VBBAT"; > + break; > + default: > + label = "UNKNOWN"; > + } > + > + return sprintf(buf, "%s\n", label); > +} > + > +static SENSOR_DEVICE_ATTR_RO(in0_input, > + da9063_adc, DA9063_CHAN_VSYS); > +static SENSOR_DEVICE_ATTR_RO(in0_label, > + da9063_label, DA9063_CHAN_VSYS); > + > +static SENSOR_DEVICE_ATTR_RO(in4_input, > + da9063_adc, DA9063_CHAN_VBBAT); > +static SENSOR_DEVICE_ATTR_RO(in4_label, > + da9063_label, DA9063_CHAN_VBBAT); > + > +static SENSOR_DEVICE_ATTR_RO(temp1_input, > + da9063_adc, DA9063_CHAN_TJUNC); > +static SENSOR_DEVICE_ATTR_RO(temp1_label, > + da9063_label, DA9063_CHAN_TJUNC); > + > +static struct attribute *da9063_attrs[] = { > + &sensor_dev_attr_in0_input.dev_attr.attr, > + &sensor_dev_attr_in0_label.dev_attr.attr, > + &sensor_dev_attr_in4_input.dev_attr.attr, > + &sensor_dev_attr_in4_label.dev_attr.attr, > + &sensor_dev_attr_temp1_input.dev_attr.attr, > + &sensor_dev_attr_temp1_label.dev_attr.attr, > + NULL > +}; > + > +ATTRIBUTE_GROUPS(da9063); > + > +static int da9063_hwmon_probe(struct platform_device *pdev) > +{ > + struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); > + struct da9063_hwmon *hwmon; > + struct device *hwmon_dev; > + int irq; > + int ret; > + > + hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9063_hwmon), > + GFP_KERNEL); > + if (!hwmon) > + return -ENOMEM; > + > + mutex_init(&hwmon->hwmon_mutex); > + init_completion(&hwmon->adc_ready); > + hwmon->da9063 = da9063; > + > + irq = platform_get_irq_byname(pdev, DA9063_DRVNAME_HWMON); > + if (irq < 0) > + return irq; > + > + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, > + da9063_hwmon_irq_handler, > + IRQF_TRIGGER_LOW | IRQF_ONESHOT, > + "HWMON", hwmon); > + if (ret) { > + dev_err(&pdev->dev, "Failed to request IRQ.\n"); > + return ret; > + } > + > + platform_set_drvdata(pdev, hwmon); > + > + /* set trim temperature offset to value read at startup */ > + hwmon->tjunc_offset = (signed char)hwmon->da9063->t_offset; > + > + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, > + "da9063", > + hwmon, da9063_groups); New hwmon drivers must use [devm_]hwmon_device_register_with_info() to register the hwmon device. > + > + return PTR_ERR_OR_ZERO(hwmon_dev); > +} > + > +static const struct of_device_id da9063_dt_ids[] = { > + { .compatible = DA9063_DRVNAME_HWMON, }, > + { } > +}; > +MODULE_DEVICE_TABLE(of, da9063_dt_ids); > + > +static struct platform_driver da9063_hwmon_driver = { > + .probe = da9063_hwmon_probe, > + .driver = { > + .name = DA9063_DRVNAME_HWMON, > + .of_match_table = da9063_dt_ids, > + }, > +}; > +module_platform_driver(da9063_hwmon_driver); > + > +MODULE_DESCRIPTION("Hardware monitor support device driver for Dialog DA9063"); > +MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); > +MODULE_LICENSE("GPL v2"); > +MODULE_ALIAS("platform:" DA9063_DRVNAME_HWMON); > diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h This isn't appropriate as part of the hwmon driver. > index 6e0f66a2e727..297631ddda39 100644 > --- a/include/linux/mfd/da9063/registers.h > +++ b/include/linux/mfd/da9063/registers.h > @@ -512,6 +512,7 @@ > > /* DA9063_REG_GPIO_0_1 (addr=0x15) */ > #define DA9063_GPIO0_PIN_MASK 0x03 > +#define DA9063_GPIO0_PIN_MASK_SHIFT 0 > #define DA9063_GPIO0_PIN_ADCIN1 0x00 > #define DA9063_GPIO0_PIN_GPI 0x01 > #define DA9063_GPIO0_PIN_GPO_OD 0x02 > @@ -523,6 +524,7 @@ > #define DA9063_GPIO0_TYPE_GPO_VDD_IO2 0x04 > #define DA9063_GPIO0_NO_WAKEUP 0x08 > #define DA9063_GPIO1_PIN_MASK 0x30 > +#define DA9063_GPIO1_PIN_MASK_SHIFT 4 > #define DA9063_GPIO1_PIN_ADCIN2_COMP 0x00 > #define DA9063_GPIO1_PIN_GPI 0x10 > #define DA9063_GPIO1_PIN_GPO_OD 0x20 > @@ -536,6 +538,7 @@ > > /* DA9063_REG_GPIO_2_3 (addr=0x16) */ > #define DA9063_GPIO2_PIN_MASK 0x03 > +#define DA9063_GPIO2_PIN_MASK_SHIFT 0 > #define DA9063_GPIO2_PIN_ADCIN3 0x00 > #define DA9063_GPIO2_PIN_GPI 0x01 > #define DA9063_GPIO2_PIN_GPO_PSS 0x02 > @@ -851,6 +854,7 @@ > #define DA9063_VSYS_VAL_BASE 0x00 > > /* DA9063_REG_ADC_RES_L (addr=0x37) */ > +#define DA9063_ADC_RES_L_SHIFT 6 > #define DA9063_ADC_RES_L_BITS 2 > #define DA9063_ADC_RES_L_MASK 0xC0 > > @@ -1014,6 +1018,36 @@ > #define DA9063_GPIO_DIM 0x80 > #define DA9063_GPIO_PWM_MASK 0x7F > > +/* DA9063_REG_ADC_CFG (addr=0xC9) */ > +#define DA9063_REG_ADCIN1_CUR_MASK 0x03 > +#define DA9063_REG_ADCIN1_CUR_SHIFT 0 > +#define DA9063_ADCIN1_CUR_1UA 0x00 > +#define DA9063_ADCIN1_CUR_2UA 0x01 > +#define DA9063_ADCIN1_CUR_10UA 0x02 > +#define DA9063_ADCIN1_CUR_40UA 0x03 > +#define DA9063_REG_ADCIN2_CUR_MASK 0x0C > +#define DA9063_REG_ADCIN2_CUR_SHIFT 2 > +#define DA9063_ADCIN2_CUR_1UA 0x00 > +#define DA9063_ADCIN2_CUR_2UA 0x01 > +#define DA9063_ADCIN2_CUR_10UA 0x02 > +#define DA9063_ADCIN2_CUR_40UA 0x03 > +#define DA9063_REG_ADCIN3_CUR_MASK 0x10 > +#define DA9063_REG_ADCIN3_CUR_SHIFT 4 > +#define DA9063_ADCIN3_CUR_10UA 0x00 > +#define DA9063_ADCIN3_CUR_40UA 0x01 > +#define DA9063_REG_ADCIN1_DEB_MASK 0x20 > +#define DA9063_REG_ADCIN1_DEB_SHIFT 5 > +#define DA9063_ADCIN1_DEB_OFF 0x00 > +#define DA9063_ADCIN1_DEB_ON 0x01 > +#define DA9063_REG_ADCIN2_DEB_MASK 0x40 > +#define DA9063_REG_ADCIN2_DEB_SHIFT 6 > +#define DA9063_ADCIN2_DEB_OFF 0x00 > +#define DA9063_ADCIN2_DEB_ON 0x01 > +#define DA9063_REG_ADCIN3_DEB_MASK 0x80 > +#define DA9063_REG_ADCIN3_DEB_SHIFT 7 > +#define DA9063_ADCIN3_DEB_OFF 0x00 > +#define DA9063_ADCIN3_DEB_ON 0x01 > + > /* DA9063_REG_CONFIG_H (addr=0x10D) */ > #define DA9063_PWM_CLK_MASK 0x01 > #define DA9063_PWM_CLK_PWM2MHZ 0x00 > ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2021-07-07 23:28 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-07-06 14:34 [PATCH 1/3] mfd: da9063: Add HWMON dependencies Vincent Pelletier 2021-07-06 14:34 ` [PATCH 2/3] hwmon: da9063: HWMON driver Vincent Pelletier 2021-07-06 17:42 ` Guenter Roeck 2021-07-07 0:20 ` Vincent Pelletier 2021-07-07 0:58 ` Guenter Roeck 2021-07-07 23:28 ` Vincent Pelletier 2021-07-06 14:34 ` [PATCH 3/3] Documentation: hwmon: New information for DA9063 Vincent Pelletier 2021-07-06 17:28 ` Guenter Roeck 2021-07-06 17:28 ` [PATCH 1/3] mfd: da9063: Add HWMON dependencies Guenter Roeck -- strict thread matches above, loose matches on Subject: below -- 2021-07-06 0:01 Vincent Pelletier 2021-07-06 0:01 ` [PATCH 2/3] hwmon: da9063: HWMON driver Vincent Pelletier 2021-07-06 0:28 ` Guenter Roeck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).