[2/2] mfd: max597x: Add support for MAX5970 and MAX5978
Commit Message
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Implement a regulator driver with IRQ support for fault management.
Written against documentation [1] and [2] and tested on real hardware.
Every channel has it's own regulator supply nammed 'vss1-supply' and
'vss2-supply'. The regulator supply is used to determine the output
voltage, as the smart switch provides no output regulation.
The driver requires the 'shunt-resistor-micro-ohms' to be present in
the devicetree to properly calculate current related values.
You must specify compatible devictree layout:
regulator@3a {
reg = <0x3a>;
vss1-supply = <&p3v3>;
compatible = "maxim,max5978";
...
regulators {
sw0_ref: SW0 {
regulator-compatible = "SW0";
shunt-resistor-micro-ohms = <12000>;
...
}
}
}
1: https://datasheets.maximintegrated.com/en/ds/MAX5970.pdf
2: https://datasheets.maximintegrated.com/en/ds/MAX5978.pdf
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Signed-off-by: Marcello Sylvester Bauer <sylv@sylv.io>
Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com>
---
drivers/mfd/Kconfig | 10 ++++
drivers/mfd/simple-mfd-i2c.c | 13 +++++
include/linux/mfd/max597x.h | 97 ++++++++++++++++++++++++++++++++++++
3 files changed, 120 insertions(+)
create mode 100644 include/linux/mfd/max597x.h
Comments
Hi Naresh,
I love your patch! Yet something to improve:
[auto build test ERROR on 59c54c59974649b2e7bc92faae4a21e2b2408db2]
url: https://github.com/intel-lab-lkp/linux/commits/Naresh-Solanki/mfd-max597x-Add-support-for-MAX5970-and-MAX5978/20230301-171527
base: 59c54c59974649b2e7bc92faae4a21e2b2408db2
patch link: https://lore.kernel.org/r/20230301091234.3159953-2-Naresh.Solanki%409elements.com
patch subject: [PATCH 2/2] mfd: max597x: Add support for MAX5970 and MAX5978
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20230302/202303020344.8ATqgdUl-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/68623f7868d887a57422ce2cd6f5dc1ee1510f1e
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Naresh-Solanki/mfd-max597x-Add-support-for-MAX5970-and-MAX5978/20230301-171527
git checkout 68623f7868d887a57422ce2cd6f5dc1ee1510f1e
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh SHELL=/bin/bash drivers/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202303020344.8ATqgdUl-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/regulator/max597x-regulator.c: In function 'max597x_regulator_probe':
>> drivers/regulator/max597x-regulator.c:447:41: error: 'struct max597x_data' has no member named 'dev'
447 | devm_kzalloc(max597x->dev, sizeof(struct max597x_regulator),
| ^~
>> drivers/regulator/max597x-regulator.c:453:39: error: 'struct max597x_data' has no member named 'regmap'
453 | data->regmap = max597x->regmap;
| ^~
drivers/regulator/max597x-regulator.c:462:37: error: 'struct max597x_data' has no member named 'dev'
462 | config.dev = max597x->dev;
| ^~
drivers/regulator/max597x-regulator.c:465:55: error: 'struct max597x_data' has no member named 'dev'
465 | rdev = devm_regulator_register(max597x->dev,
| ^~
In file included from include/linux/device.h:15,
from drivers/regulator/max597x-regulator.c:11:
drivers/regulator/max597x-regulator.c:468:40: error: 'struct max597x_data' has no member named 'dev'
468 | dev_err(max597x->dev, "failed to register regulator %s\n",
| ^~
include/linux/dev_printk.h:110:25: note: in definition of macro 'dev_printk_index_wrap'
110 | _p_func(dev, fmt, ##__VA_ARGS__); \
| ^~~
drivers/regulator/max597x-regulator.c:468:25: note: in expansion of macro 'dev_err'
468 | dev_err(max597x->dev, "failed to register regulator %s\n",
| ^~~~~~~
>> drivers/regulator/max597x-regulator.c:476:20: error: 'struct max597x_data' has no member named 'irq'
476 | if (max597x->irq) {
| ^~
drivers/regulator/max597x-regulator.c:478:46: error: 'struct max597x_data' has no member named 'dev'
478 | max597x_setup_irq(max597x->dev, max597x->irq, rdevs, num_switches,
| ^~
drivers/regulator/max597x-regulator.c:478:60: error: 'struct max597x_data' has no member named 'irq'
478 | max597x_setup_irq(max597x->dev, max597x->irq, rdevs, num_switches,
| ^~
drivers/regulator/max597x-regulator.c:481:40: error: 'struct max597x_data' has no member named 'dev'
481 | dev_err(max597x->dev, "IRQ setup failed");
| ^~
include/linux/dev_printk.h:110:25: note: in definition of macro 'dev_printk_index_wrap'
110 | _p_func(dev, fmt, ##__VA_ARGS__); \
| ^~~
drivers/regulator/max597x-regulator.c:481:25: note: in expansion of macro 'dev_err'
481 | dev_err(max597x->dev, "IRQ setup failed");
| ^~~~~~~
drivers/regulator/max597x-regulator.c: At top level:
drivers/regulator/max597x-regulator.c:360:35: warning: 'max597x_regmap_config' defined but not used [-Wunused-const-variable=]
360 | static const struct regmap_config max597x_regmap_config = {
| ^~~~~~~~~~~~~~~~~~~~~
vim +447 drivers/regulator/max597x-regulator.c
38493f008deb435 Patrick Rudolph 2022-07-05 434
38493f008deb435 Patrick Rudolph 2022-07-05 435
38493f008deb435 Patrick Rudolph 2022-07-05 436 struct max597x_data *max597x = dev_get_drvdata(pdev->dev.parent);
38493f008deb435 Patrick Rudolph 2022-07-05 437 struct max597x_regulator *data;
38493f008deb435 Patrick Rudolph 2022-07-05 438
38493f008deb435 Patrick Rudolph 2022-07-05 439 struct regulator_config config = { };
38493f008deb435 Patrick Rudolph 2022-07-05 440 struct regulator_dev *rdev;
38493f008deb435 Patrick Rudolph 2022-07-05 441 struct regulator_dev *rdevs[MAX5970_NUM_SWITCHES];
38493f008deb435 Patrick Rudolph 2022-07-05 442 int num_switches = max597x->num_switches;
38493f008deb435 Patrick Rudolph 2022-07-05 443 int ret, i;
38493f008deb435 Patrick Rudolph 2022-07-05 444
38493f008deb435 Patrick Rudolph 2022-07-05 445 for (i = 0; i < num_switches; i++) {
38493f008deb435 Patrick Rudolph 2022-07-05 446 data =
38493f008deb435 Patrick Rudolph 2022-07-05 @447 devm_kzalloc(max597x->dev, sizeof(struct max597x_regulator),
38493f008deb435 Patrick Rudolph 2022-07-05 448 GFP_KERNEL);
38493f008deb435 Patrick Rudolph 2022-07-05 449 if (!data)
38493f008deb435 Patrick Rudolph 2022-07-05 450 return -ENOMEM;
38493f008deb435 Patrick Rudolph 2022-07-05 451
38493f008deb435 Patrick Rudolph 2022-07-05 452 data->num_switches = num_switches;
38493f008deb435 Patrick Rudolph 2022-07-05 @453 data->regmap = max597x->regmap;
38493f008deb435 Patrick Rudolph 2022-07-05 454
38493f008deb435 Patrick Rudolph 2022-07-05 455 ret = max597x_adc_range(data->regmap, i, &max597x->irng[i], &max597x->mon_rng[i]);
38493f008deb435 Patrick Rudolph 2022-07-05 456 if (ret < 0)
38493f008deb435 Patrick Rudolph 2022-07-05 457 return ret;
38493f008deb435 Patrick Rudolph 2022-07-05 458
38493f008deb435 Patrick Rudolph 2022-07-05 459 data->irng = max597x->irng[i];
38493f008deb435 Patrick Rudolph 2022-07-05 460 data->mon_rng = max597x->mon_rng[i];
38493f008deb435 Patrick Rudolph 2022-07-05 461
38493f008deb435 Patrick Rudolph 2022-07-05 462 config.dev = max597x->dev;
38493f008deb435 Patrick Rudolph 2022-07-05 463 config.driver_data = (void *)data;
38493f008deb435 Patrick Rudolph 2022-07-05 464 config.regmap = data->regmap;
38493f008deb435 Patrick Rudolph 2022-07-05 465 rdev = devm_regulator_register(max597x->dev,
38493f008deb435 Patrick Rudolph 2022-07-05 466 ®ulators[i], &config);
38493f008deb435 Patrick Rudolph 2022-07-05 467 if (IS_ERR(rdev)) {
38493f008deb435 Patrick Rudolph 2022-07-05 468 dev_err(max597x->dev, "failed to register regulator %s\n",
38493f008deb435 Patrick Rudolph 2022-07-05 469 regulators[i].name);
38493f008deb435 Patrick Rudolph 2022-07-05 470 return PTR_ERR(rdev);
38493f008deb435 Patrick Rudolph 2022-07-05 471 }
38493f008deb435 Patrick Rudolph 2022-07-05 472 rdevs[i] = rdev;
38493f008deb435 Patrick Rudolph 2022-07-05 473 max597x->shunt_micro_ohms[i] = data->shunt_micro_ohms;
38493f008deb435 Patrick Rudolph 2022-07-05 474 }
38493f008deb435 Patrick Rudolph 2022-07-05 475
38493f008deb435 Patrick Rudolph 2022-07-05 @476 if (max597x->irq) {
38493f008deb435 Patrick Rudolph 2022-07-05 477 ret =
38493f008deb435 Patrick Rudolph 2022-07-05 478 max597x_setup_irq(max597x->dev, max597x->irq, rdevs, num_switches,
38493f008deb435 Patrick Rudolph 2022-07-05 479 data);
38493f008deb435 Patrick Rudolph 2022-07-05 480 if (ret) {
38493f008deb435 Patrick Rudolph 2022-07-05 481 dev_err(max597x->dev, "IRQ setup failed");
38493f008deb435 Patrick Rudolph 2022-07-05 482 return ret;
38493f008deb435 Patrick Rudolph 2022-07-05 483 }
38493f008deb435 Patrick Rudolph 2022-07-05 484 }
38493f008deb435 Patrick Rudolph 2022-07-05 485
38493f008deb435 Patrick Rudolph 2022-07-05 486 return ret;
38493f008deb435 Patrick Rudolph 2022-07-05 487 }
38493f008deb435 Patrick Rudolph 2022-07-05 488
Hi Naresh,
I love your patch! Perhaps something to improve:
[auto build test WARNING on 59c54c59974649b2e7bc92faae4a21e2b2408db2]
url: https://github.com/intel-lab-lkp/linux/commits/Naresh-Solanki/mfd-max597x-Add-support-for-MAX5970-and-MAX5978/20230301-171527
base: 59c54c59974649b2e7bc92faae4a21e2b2408db2
patch link: https://lore.kernel.org/r/20230301091234.3159953-2-Naresh.Solanki%409elements.com
patch subject: [PATCH 2/2] mfd: max597x: Add support for MAX5970 and MAX5978
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20230302/202303021248.Bk9jYUb1-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/68623f7868d887a57422ce2cd6f5dc1ee1510f1e
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Naresh-Solanki/mfd-max597x-Add-support-for-MAX5970-and-MAX5978/20230301-171527
git checkout 68623f7868d887a57422ce2cd6f5dc1ee1510f1e
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=x86_64 olddefconfig
make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/regulator/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202303021248.Bk9jYUb1-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/regulator/max597x-regulator.c: In function 'max597x_regulator_probe':
drivers/regulator/max597x-regulator.c:447:41: error: 'struct max597x_data' has no member named 'dev'
447 | devm_kzalloc(max597x->dev, sizeof(struct max597x_regulator),
| ^~
drivers/regulator/max597x-regulator.c:453:39: error: 'struct max597x_data' has no member named 'regmap'
453 | data->regmap = max597x->regmap;
| ^~
drivers/regulator/max597x-regulator.c:462:37: error: 'struct max597x_data' has no member named 'dev'
462 | config.dev = max597x->dev;
| ^~
drivers/regulator/max597x-regulator.c:465:55: error: 'struct max597x_data' has no member named 'dev'
465 | rdev = devm_regulator_register(max597x->dev,
| ^~
In file included from include/linux/device.h:15,
from drivers/regulator/max597x-regulator.c:11:
drivers/regulator/max597x-regulator.c:468:40: error: 'struct max597x_data' has no member named 'dev'
468 | dev_err(max597x->dev, "failed to register regulator %s\n",
| ^~
include/linux/dev_printk.h:110:25: note: in definition of macro 'dev_printk_index_wrap'
110 | _p_func(dev, fmt, ##__VA_ARGS__); \
| ^~~
drivers/regulator/max597x-regulator.c:468:25: note: in expansion of macro 'dev_err'
468 | dev_err(max597x->dev, "failed to register regulator %s\n",
| ^~~~~~~
drivers/regulator/max597x-regulator.c:476:20: error: 'struct max597x_data' has no member named 'irq'
476 | if (max597x->irq) {
| ^~
drivers/regulator/max597x-regulator.c:478:46: error: 'struct max597x_data' has no member named 'dev'
478 | max597x_setup_irq(max597x->dev, max597x->irq, rdevs, num_switches,
| ^~
drivers/regulator/max597x-regulator.c:478:60: error: 'struct max597x_data' has no member named 'irq'
478 | max597x_setup_irq(max597x->dev, max597x->irq, rdevs, num_switches,
| ^~
In file included from include/linux/device.h:15,
from drivers/regulator/max597x-regulator.c:11:
drivers/regulator/max597x-regulator.c:481:40: error: 'struct max597x_data' has no member named 'dev'
481 | dev_err(max597x->dev, "IRQ setup failed");
| ^~
include/linux/dev_printk.h:110:25: note: in definition of macro 'dev_printk_index_wrap'
110 | _p_func(dev, fmt, ##__VA_ARGS__); \
| ^~~
drivers/regulator/max597x-regulator.c:481:25: note: in expansion of macro 'dev_err'
481 | dev_err(max597x->dev, "IRQ setup failed");
| ^~~~~~~
At top level:
>> drivers/regulator/max597x-regulator.c:360:35: warning: 'max597x_regmap_config' defined but not used [-Wunused-const-variable=]
360 | static const struct regmap_config max597x_regmap_config = {
| ^~~~~~~~~~~~~~~~~~~~~
vim +/max597x_regmap_config +360 drivers/regulator/max597x-regulator.c
38493f008deb43 Patrick Rudolph 2022-07-05 359
38493f008deb43 Patrick Rudolph 2022-07-05 @360 static const struct regmap_config max597x_regmap_config = {
38493f008deb43 Patrick Rudolph 2022-07-05 361 .reg_bits = 8,
38493f008deb43 Patrick Rudolph 2022-07-05 362 .val_bits = 8,
38493f008deb43 Patrick Rudolph 2022-07-05 363 .max_register = MAX_REGISTERS,
38493f008deb43 Patrick Rudolph 2022-07-05 364 };
38493f008deb43 Patrick Rudolph 2022-07-05 365
On Wed, 01 Mar 2023, Naresh Solanki wrote:
> From: Patrick Rudolph <patrick.rudolph@9elements.com>
>
> Implement a regulator driver with IRQ support for fault management.
> Written against documentation [1] and [2] and tested on real hardware.
>
> Every channel has it's own regulator supply nammed 'vss1-supply' and
> 'vss2-supply'. The regulator supply is used to determine the output
> voltage, as the smart switch provides no output regulation.
> The driver requires the 'shunt-resistor-micro-ohms' to be present in
> the devicetree to properly calculate current related values.
>
> You must specify compatible devictree layout:
>
> regulator@3a {
> reg = <0x3a>;
> vss1-supply = <&p3v3>;
> compatible = "maxim,max5978";
>
> ...
>
> regulators {
> sw0_ref: SW0 {
> regulator-compatible = "SW0";
> shunt-resistor-micro-ohms = <12000>;
> ...
> }
> }
> }
>
> 1: https://datasheets.maximintegrated.com/en/ds/MAX5970.pdf
> 2: https://datasheets.maximintegrated.com/en/ds/MAX5978.pdf
>
> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
> Signed-off-by: Marcello Sylvester Bauer <sylv@sylv.io>
> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com>
> ---
> drivers/mfd/Kconfig | 10 ++++
> drivers/mfd/simple-mfd-i2c.c | 13 +++++
> include/linux/mfd/max597x.h | 97 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 120 insertions(+)
> create mode 100644 include/linux/mfd/max597x.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index d4fc4ca9fdbd..de899e0d2f1a 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -266,6 +266,16 @@ config MFD_MADERA_SPI
> Support for the Cirrus Logic Madera platform audio SoC
> core functionality controlled via SPI.
>
> +config MFD_MAX597X
> + tristate "Maxim 597x power switch and monitor"
> + depends on (I2C && OF)
> + select MFD_SIMPLE_MFD_I2C
> + help
> + This driver controls a Maxim 5970/5978 switch via I2C bus.
> + The MAX5970/5978 is a smart switch with no output regulation, but
> + fault protection and voltage and current monitoring capabilities.
> + Also it supports upto 4 indication leds.
> +
> config MFD_CS47L15
> bool "Cirrus Logic CS47L15"
> select PINCTRL_CS47L15
> diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c
> index e31f13fd6a79..20782b4dd172 100644
> --- a/drivers/mfd/simple-mfd-i2c.c
> +++ b/drivers/mfd/simple-mfd-i2c.c
> @@ -72,9 +72,22 @@ static const struct simple_mfd_data silergy_sy7636a = {
> .mfd_cell_size = ARRAY_SIZE(sy7636a_cells),
> };
>
> +static const struct mfd_cell max597x_cells[] = {
> + { .name = "max597x-regulator", },
> + { .name = "max597x-iio", },
> + { .name = "max597x-led", },
> +};
> +
> +static const struct simple_mfd_data maxim_max597x = {
> + .mfd_cell = max597x_cells,
> + .mfd_cell_size = ARRAY_SIZE(max597x_cells),
> +};
> +
> static const struct of_device_id simple_mfd_i2c_of_match[] = {
> { .compatible = "kontron,sl28cpld" },
> { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a},
> + { .compatible = "maxim,max5970", .data = &maxim_max597x},
> + { .compatible = "maxim,max5978", .data = &maxim_max597x},
> {}
> };
> MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match);
> diff --git a/include/linux/mfd/max597x.h b/include/linux/mfd/max597x.h
> new file mode 100644
> index 000000000000..8a4da98caf3e
> --- /dev/null
> +++ b/include/linux/mfd/max597x.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Device driver for regulators in MAX5970 and MAX5978 IC
> + *
> + * Copyright (c) 2022 9elements GmbH
> + *
> + * Author: Patrick Rudolph <patrick.rudolph@9elements.com>
> + */
> +
> +#ifndef _MAX597X_H
> +#define _MAX597X_H
__MFD_*
> +#include <linux/regmap.h>
> +
> +#define MAX5970_NUM_SWITCHES 2
> +#define MAX5978_NUM_SWITCHES 1
> +#define MAX597X_NUM_LEDS 4
> +
> +struct max597x_data {
> + int num_switches;
> + u32 irng[MAX5970_NUM_SWITCHES];
> + u32 mon_rng[MAX5970_NUM_SWITCHES];
> + u32 shunt_micro_ohms[MAX5970_NUM_SWITCHES];
> +};
> +
> +enum max597x_chip_type {
> + MAX597x_TYPE_MAX5978 = 1,
> + MAX597x_TYPE_MAX5970,
> +};
> +
> +#define MAX5970_REG_CURRENT_L(ch) (0x01 + (ch) * 4)
> +#define MAX5970_REG_CURRENT_H(ch) (0x00 + (ch) * 4)
> +#define MAX5970_REG_VOLTAGE_L(ch) (0x03 + (ch) * 4)
> +#define MAX5970_REG_VOLTAGE_H(ch) (0x02 + (ch) * 4)
> +#define MAX5970_REG_MON_RANGE 0x18
> +#define MAX5970_MON_MASK 0x3
> +#define MAX5970_MON(reg, ch) \
> + (((reg) >> ((ch) * 2)) & MAX5970_MON_MASK)
Why the '\n'?
> +#define MAX5970_MON_MAX_RANGE_UV 16000000
> +
> +#define MAX5970_REG_CH_UV_WARN_H(ch) (0x1A + (ch) * 10)
> +#define MAX5970_REG_CH_UV_WARN_L(ch) (0x1B + (ch) * 10)
> +#define MAX5970_REG_CH_UV_CRIT_H(ch) (0x1C + (ch) * 10)
> +#define MAX5970_REG_CH_UV_CRIT_L(ch) (0x1D + (ch) * 10)
> +#define MAX5970_REG_CH_OV_WARN_H(ch) (0x1E + (ch) * 10)
> +#define MAX5970_REG_CH_OV_WARN_L(ch) (0x1F + (ch) * 10)
> +#define MAX5970_REG_CH_OV_CRIT_H(ch) (0x20 + (ch) * 10)
> +#define MAX5970_REG_CH_OV_CRIT_L(ch) (0x21 + (ch) * 10)
> +
> +#define MAX5970_VAL2REG_H(x) (((x) >> 2) & 0xFF)
> +#define MAX5970_VAL2REG_L(x) ((x) & 0x3)
> +
> +#define MAX5970_REG_DAC_FAST(ch) (0x2E + (ch))
> +
> +#define MAX5970_FAST2SLOW_RATIO 200
> +
> +#define MAX5970_REG_STATUS0 0x31
> +#define MAX5970_CB_IFAULTF(ch) (1 << (ch))
> +#define MAX5970_CB_IFAULTS(ch) (1 << ((ch) + 4))
> +
> +#define MAX5970_REG_STATUS1 0x32
> +#define STATUS1_PROT_MASK 0x3
> +#define STATUS1_PROT(reg) \
> + (((reg) >> 6) & STATUS1_PROT_MASK)
> +#define STATUS1_PROT_SHUTDOWN 0
> +#define STATUS1_PROT_CLEAR_PG 1
> +#define STATUS1_PROT_ALERT_ONLY 2
> +
> +#define MAX5970_REG_STATUS2 0x33
> +#define MAX5970_IRNG_MASK 0x3
> +#define MAX5970_IRNG(reg, ch) \
> + (((reg) >> ((ch) * 2)) & MAX5970_IRNG_MASK)
> +
> +#define MAX5970_REG_STATUS3 0x34
> +#define MAX5970_STATUS3_ALERT BIT(4)
> +#define MAX5970_STATUS3_PG(ch) BIT(ch)
> +
> +#define MAX5970_REG_FAULT0 0x35
> +#define UV_STATUS_WARN(ch) (1 << (ch))
> +#define UV_STATUS_CRIT(ch) (1 << ((ch) + 4))
> +
> +#define MAX5970_REG_FAULT1 0x36
> +#define OV_STATUS_WARN(ch) (1 << (ch))
> +#define OV_STATUS_CRIT(ch) (1 << ((ch) + 4))
> +
> +#define MAX5970_REG_FAULT2 0x37
> +#define OC_STATUS_WARN(ch) (1 << (ch))
> +
> +#define MAX5970_REG_CHXEN 0x3b
> +#define CHXEN(ch) (3 << ((ch) * 2))
> +
> +#define MAX5970_REG_LED_FLASH 0x43
> +
> +#define MAX_REGISTERS 0x49
> +#define ADC_MASK 0x3FF
> +
> +#endif /* _MAX597X_H */
> --
> 2.39.1
>
@@ -266,6 +266,16 @@ config MFD_MADERA_SPI
Support for the Cirrus Logic Madera platform audio SoC
core functionality controlled via SPI.
+config MFD_MAX597X
+ tristate "Maxim 597x power switch and monitor"
+ depends on (I2C && OF)
+ select MFD_SIMPLE_MFD_I2C
+ help
+ This driver controls a Maxim 5970/5978 switch via I2C bus.
+ The MAX5970/5978 is a smart switch with no output regulation, but
+ fault protection and voltage and current monitoring capabilities.
+ Also it supports upto 4 indication leds.
+
config MFD_CS47L15
bool "Cirrus Logic CS47L15"
select PINCTRL_CS47L15
@@ -72,9 +72,22 @@ static const struct simple_mfd_data silergy_sy7636a = {
.mfd_cell_size = ARRAY_SIZE(sy7636a_cells),
};
+static const struct mfd_cell max597x_cells[] = {
+ { .name = "max597x-regulator", },
+ { .name = "max597x-iio", },
+ { .name = "max597x-led", },
+};
+
+static const struct simple_mfd_data maxim_max597x = {
+ .mfd_cell = max597x_cells,
+ .mfd_cell_size = ARRAY_SIZE(max597x_cells),
+};
+
static const struct of_device_id simple_mfd_i2c_of_match[] = {
{ .compatible = "kontron,sl28cpld" },
{ .compatible = "silergy,sy7636a", .data = &silergy_sy7636a},
+ { .compatible = "maxim,max5970", .data = &maxim_max597x},
+ { .compatible = "maxim,max5978", .data = &maxim_max597x},
{}
};
MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match);
new file mode 100644
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Device driver for regulators in MAX5970 and MAX5978 IC
+ *
+ * Copyright (c) 2022 9elements GmbH
+ *
+ * Author: Patrick Rudolph <patrick.rudolph@9elements.com>
+ */
+
+#ifndef _MAX597X_H
+#define _MAX597X_H
+
+#include <linux/regmap.h>
+
+#define MAX5970_NUM_SWITCHES 2
+#define MAX5978_NUM_SWITCHES 1
+#define MAX597X_NUM_LEDS 4
+
+struct max597x_data {
+ int num_switches;
+ u32 irng[MAX5970_NUM_SWITCHES];
+ u32 mon_rng[MAX5970_NUM_SWITCHES];
+ u32 shunt_micro_ohms[MAX5970_NUM_SWITCHES];
+};
+
+enum max597x_chip_type {
+ MAX597x_TYPE_MAX5978 = 1,
+ MAX597x_TYPE_MAX5970,
+};
+
+#define MAX5970_REG_CURRENT_L(ch) (0x01 + (ch) * 4)
+#define MAX5970_REG_CURRENT_H(ch) (0x00 + (ch) * 4)
+#define MAX5970_REG_VOLTAGE_L(ch) (0x03 + (ch) * 4)
+#define MAX5970_REG_VOLTAGE_H(ch) (0x02 + (ch) * 4)
+#define MAX5970_REG_MON_RANGE 0x18
+#define MAX5970_MON_MASK 0x3
+#define MAX5970_MON(reg, ch) \
+ (((reg) >> ((ch) * 2)) & MAX5970_MON_MASK)
+#define MAX5970_MON_MAX_RANGE_UV 16000000
+
+#define MAX5970_REG_CH_UV_WARN_H(ch) (0x1A + (ch) * 10)
+#define MAX5970_REG_CH_UV_WARN_L(ch) (0x1B + (ch) * 10)
+#define MAX5970_REG_CH_UV_CRIT_H(ch) (0x1C + (ch) * 10)
+#define MAX5970_REG_CH_UV_CRIT_L(ch) (0x1D + (ch) * 10)
+#define MAX5970_REG_CH_OV_WARN_H(ch) (0x1E + (ch) * 10)
+#define MAX5970_REG_CH_OV_WARN_L(ch) (0x1F + (ch) * 10)
+#define MAX5970_REG_CH_OV_CRIT_H(ch) (0x20 + (ch) * 10)
+#define MAX5970_REG_CH_OV_CRIT_L(ch) (0x21 + (ch) * 10)
+
+#define MAX5970_VAL2REG_H(x) (((x) >> 2) & 0xFF)
+#define MAX5970_VAL2REG_L(x) ((x) & 0x3)
+
+#define MAX5970_REG_DAC_FAST(ch) (0x2E + (ch))
+
+#define MAX5970_FAST2SLOW_RATIO 200
+
+#define MAX5970_REG_STATUS0 0x31
+#define MAX5970_CB_IFAULTF(ch) (1 << (ch))
+#define MAX5970_CB_IFAULTS(ch) (1 << ((ch) + 4))
+
+#define MAX5970_REG_STATUS1 0x32
+#define STATUS1_PROT_MASK 0x3
+#define STATUS1_PROT(reg) \
+ (((reg) >> 6) & STATUS1_PROT_MASK)
+#define STATUS1_PROT_SHUTDOWN 0
+#define STATUS1_PROT_CLEAR_PG 1
+#define STATUS1_PROT_ALERT_ONLY 2
+
+#define MAX5970_REG_STATUS2 0x33
+#define MAX5970_IRNG_MASK 0x3
+#define MAX5970_IRNG(reg, ch) \
+ (((reg) >> ((ch) * 2)) & MAX5970_IRNG_MASK)
+
+#define MAX5970_REG_STATUS3 0x34
+#define MAX5970_STATUS3_ALERT BIT(4)
+#define MAX5970_STATUS3_PG(ch) BIT(ch)
+
+#define MAX5970_REG_FAULT0 0x35
+#define UV_STATUS_WARN(ch) (1 << (ch))
+#define UV_STATUS_CRIT(ch) (1 << ((ch) + 4))
+
+#define MAX5970_REG_FAULT1 0x36
+#define OV_STATUS_WARN(ch) (1 << (ch))
+#define OV_STATUS_CRIT(ch) (1 << ((ch) + 4))
+
+#define MAX5970_REG_FAULT2 0x37
+#define OC_STATUS_WARN(ch) (1 << (ch))
+
+#define MAX5970_REG_CHXEN 0x3b
+#define CHXEN(ch) (3 << ((ch) * 2))
+
+#define MAX5970_REG_LED_FLASH 0x43
+
+#define MAX_REGISTERS 0x49
+#define ADC_MASK 0x3FF
+
+#endif /* _MAX597X_H */