* [PATCH v2 0/5] mfd: max597x: Add support for max597x
@ 2022-07-07 13:41 Naresh Solanki
2022-07-07 13:41 ` [PATCH v2 1/5] dt-bindings: mfd: Add bindings for MAX5970 and MAX5978 Naresh Solanki
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Naresh Solanki @ 2022-07-07 13:41 UTC (permalink / raw)
To: linux-kernel; +Cc: Naresh Solanki
max597x is multifunction device with hot swap controller, fault
protection & upto four indication leds.
max5978 has single hot swap controller whereas max5970 has two hot swap
controllers.
Changes in V2:
- Update depends in Kconfig.
Marcello Sylvester Bauer (1):
dt-bindings: mfd: Add bindings for MAX5970 and MAX5978
Patrick Rudolph (4):
mfd: max597x: Add support for MAX5970 and MAX5978
regulator: max597x: Add support for max597x regulator
iio: max597x: Add support for max597x
leds: max597x: Add support for max597x
.../devicetree/bindings/mfd/max5970.yaml | 164 ++++++
drivers/iio/adc/Kconfig | 9 +
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/max597x-iio.c | 156 ++++++
drivers/leds/Kconfig | 10 +
drivers/leds/Makefile | 1 +
drivers/leds/leds-max597x.c | 130 +++++
drivers/mfd/Kconfig | 12 +
drivers/mfd/Makefile | 2 +
drivers/mfd/max597x.c | 109 ++++
drivers/regulator/Kconfig | 10 +
drivers/regulator/Makefile | 1 +
drivers/regulator/max597x-regulator.c | 506 ++++++++++++++++++
include/linux/mfd/max597x.h | 100 ++++
14 files changed, 1211 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/max5970.yaml
create mode 100644 drivers/iio/adc/max597x-iio.c
create mode 100644 drivers/leds/leds-max597x.c
create mode 100644 drivers/mfd/max597x.c
create mode 100644 drivers/regulator/max597x-regulator.c
create mode 100644 include/linux/mfd/max597x.h
base-commit: 9f09069cde34dcd86f5ecf3a3139fd752020812f
--
2.35.3
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 1/5] dt-bindings: mfd: Add bindings for MAX5970 and MAX5978 2022-07-07 13:41 [PATCH v2 0/5] mfd: max597x: Add support for max597x Naresh Solanki @ 2022-07-07 13:41 ` Naresh Solanki 2022-07-07 13:41 ` [PATCH v2 2/5] mfd: max597x: Add support " Naresh Solanki ` (3 subsequent siblings) 4 siblings, 0 replies; 9+ messages in thread From: Naresh Solanki @ 2022-07-07 13:41 UTC (permalink / raw) To: linux-kernel, Lee Jones, Patrick Rudolph Cc: Marcello Sylvester Bauer, Naresh Solanki From: Marcello Sylvester Bauer <sylv@sylv.io> The MAX597x is a hot swap controller with configurable fault protection. It also has 10bit ADC for current & voltage measurements. 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> --- .../devicetree/bindings/mfd/max5970.yaml | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/max5970.yaml diff --git a/Documentation/devicetree/bindings/mfd/max5970.yaml b/Documentation/devicetree/bindings/mfd/max5970.yaml new file mode 100644 index 000000000000..a0cc6a7543b5 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/max5970.yaml @@ -0,0 +1,164 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/max5970.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Regulator driver for MAX5970 smart switch from Maxim Integrated. + +maintainers: + - Patrick Rudolph <patrick.rudolph@9elements.com> + +description: | + The smart switch provides no output regulation, but independent fault protection + and voltage and current sensing. + Programming is done through I2C bus. + + Datasheets: + https://datasheets.maximintegrated.com/en/ds/MAX5970.pdf + https://datasheets.maximintegrated.com/en/ds/MAX5978.pdf + +properties: + compatible: + enum: + - maxim,max5970 + - maxim,max5978 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + leds: + type: object + description: + Properties for single channel. + + patternProperties: + "^led@[0-3]$": + $ref: /schemas/leds/common.yaml# + type: object + + additionalProperties: true + + vss1-supply: + description: Supply of the first channel. + + "#io-channel-cells": + const: 1 + + regulators: + type: object + description: + Properties for single channel. + + patternProperties: + "^(sw[0-1])$": + $ref: /schemas/regulator/regulator.yaml# + type: object + + shunt-resistor-micro-ohms: + description: | + The value of curent sense resistor in microohms. + Must be specified for each channel. + + additionalProperties: true + +required: + - compatible + - reg + - regulators + - vss1-supply + +allOf: + - $ref: /schemas/regulator/regulator.yaml# + - if: + properties: + compatible: + enum: + - maxim,max5970 + then: + properties: + vss2-supply: + description: Supply of the second channel. + + io-channels: + items: + - description: voltage first channel + - description: current first channel + - description: voltage second channel + - description: current second channel + description: | + Voltage and current for first and second channel. + required: + - vss2-supply + + else: + properties: + io-channels: + items: + - description: voltage first channel + - description: current first channel + description: | + Voltage and current for first channel. + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + leds { + #address-cells = <1>; + #size-cells = <0>; + led@0 { + reg = <0>; + label = "led0"; + default-state = "on"; + }; + led@1 { + reg = <1>; + label = "led1"; + default-state = "on"; + }; + }; + regulator@3a { + reg = <0x3a>; + vss1-supply = <&p3v3>; + compatible = "maxim,max5978"; + + regulators { + sw0_ref_0: SW0 { + regulator-compatible = "SW0"; + shunt-resistor-micro-ohms = <12000>; + }; + }; + }; + }; + + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + regulator@3a { + reg = <0x3a>; + vss1-supply = <&p3v3>; + vss2-supply = <&p5v>; + compatible = "maxim,max5970"; + + regulators { + sw0_ref_1: SW0 { + regulator-compatible = "SW0"; + shunt-resistor-micro-ohms = <12000>; + }; + sw1_ref_1: SW1 { + regulator-compatible = "SW1"; + shunt-resistor-micro-ohms = <10000>; + }; + }; + }; + }; +... -- 2.35.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/5] mfd: max597x: Add support for MAX5970 and MAX5978 2022-07-07 13:41 [PATCH v2 0/5] mfd: max597x: Add support for max597x Naresh Solanki 2022-07-07 13:41 ` [PATCH v2 1/5] dt-bindings: mfd: Add bindings for MAX5970 and MAX5978 Naresh Solanki @ 2022-07-07 13:41 ` Naresh Solanki 2022-08-08 13:55 ` Lee Jones 2022-07-07 13:41 ` [PATCH v2 3/5] regulator: max597x: Add support for max597x regulator Naresh Solanki ` (2 subsequent siblings) 4 siblings, 1 reply; 9+ messages in thread From: Naresh Solanki @ 2022-07-07 13:41 UTC (permalink / raw) To: linux-kernel, Lee Jones Cc: Patrick Rudolph, Marcello Sylvester Bauer, Naresh Solanki 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 | 12 ++++ drivers/mfd/Makefile | 2 + drivers/mfd/max597x.c | 109 ++++++++++++++++++++++++++++++++++++ include/linux/mfd/max597x.h | 100 +++++++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+) create mode 100644 drivers/mfd/max597x.c create mode 100644 include/linux/mfd/max597x.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3b59456f5545..2422ae155118 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -253,6 +253,18 @@ 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 + depends on OF + select MFD_CORE + select REGMAP_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/Makefile b/drivers/mfd/Makefile index 858cacf659d6..f5f46b86401f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -95,6 +95,8 @@ obj-$(CONFIG_MFD_MADERA) += madera.o obj-$(CONFIG_MFD_MADERA_I2C) += madera-i2c.o obj-$(CONFIG_MFD_MADERA_SPI) += madera-spi.o +obj-$(CONFIG_MFD_MAX597X) += max597x.o + obj-$(CONFIG_TPS6105X) += tps6105x.o obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_TPS6507X) += tps6507x.o diff --git a/drivers/mfd/max597x.c b/drivers/mfd/max597x.c new file mode 100644 index 000000000000..b2450e64d3eb --- /dev/null +++ b/drivers/mfd/max597x.c @@ -0,0 +1,109 @@ +// 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> + */ + +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/i2c.h> +#include <linux/mfd/core.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/version.h> +#include <linux/mfd/max597x.h> + +static const struct regmap_config max597x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX_REGISTERS, +}; + +static const struct mfd_cell max597x_devs[] = { + { + .name = "max597x-regulator", + }, + { + .name = "max597x-iio", + }, + { + .name = "max597x-led", + }, +}; + +static int max597x_probe(struct i2c_client *i2c, const struct i2c_device_id *id) +{ + struct max597x_data *max597x; + struct regmap *regmap; + enum max597x_chip_type chip = id->driver_data; + + max597x = + devm_kzalloc(&i2c->dev, sizeof(struct max597x_data), GFP_KERNEL); + switch (chip) { + case MAX597x_TYPE_MAX5970: + max597x->num_switches = 2; + break; + case MAX597x_TYPE_MAX5978: + max597x->num_switches = 1; + break; + } + + regmap = devm_regmap_init_i2c(i2c, &max597x_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&i2c->dev, "No regmap\n"); + return -EINVAL; + } + max597x->regmap = regmap; + max597x->irq = i2c->irq; + max597x->dev = &i2c->dev; + i2c_set_clientdata(i2c, max597x); + + return devm_mfd_add_devices(max597x->dev, PLATFORM_DEVID_AUTO, + max597x_devs, ARRAY_SIZE(max597x_devs), + NULL, 0, NULL); +} + +static const struct i2c_device_id max597x_table[] = { + {.name = "max5970", MAX597x_TYPE_MAX5970}, + {.name = "max5978", MAX597x_TYPE_MAX5978}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, max597x_table); + +static const struct of_device_id max597x_of_match[] = { + { .compatible = "maxim,max5970", + .data = (void *)MAX597x_TYPE_MAX5970 + }, + { .compatible = "maxim,max5978", + .data = (void *)MAX597x_TYPE_MAX5978 + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, max597x_of_match); + +static struct i2c_driver max597x_driver = { + .id_table = max597x_table, + .driver = { + .name = "max597x", + .of_match_table = of_match_ptr(max597x_of_match), + }, + .probe = max597x_probe, +}; + +module_i2c_driver(max597x_driver); + +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); +MODULE_DESCRIPTION("MAX5970_hot-swap controller driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/max597x.h b/include/linux/mfd/max597x.h new file mode 100644 index 000000000000..ac7e9c84d06c --- /dev/null +++ b/include/linux/mfd/max597x.h @@ -0,0 +1,100 @@ +/* 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 { + struct device *dev; + int irq; + int num_switches; + struct regmap *regmap; + 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 */ -- 2.35.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/5] mfd: max597x: Add support for MAX5970 and MAX5978 2022-07-07 13:41 ` [PATCH v2 2/5] mfd: max597x: Add support " Naresh Solanki @ 2022-08-08 13:55 ` Lee Jones 0 siblings, 0 replies; 9+ messages in thread From: Lee Jones @ 2022-08-08 13:55 UTC (permalink / raw) To: Naresh Solanki Cc: linux-kernel, Patrick Rudolph, Marcello Sylvester Bauer, Lee Jones On Thu, 07 Jul 2022, 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 Nit "its" and "supplies" > '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 "property to be ..." > the devicetree to properly calculate current related values. Drop "the" and it's "Device Tree" > You must specify compatible devictree layout: This doesn't need to be in the commit message. Save it for the documentation. > 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> What is the relationship between all of these people? What did each of them provide to the patch? > --- > drivers/mfd/Kconfig | 12 ++++ > drivers/mfd/Makefile | 2 + > drivers/mfd/max597x.c | 109 ++++++++++++++++++++++++++++++++++++ > include/linux/mfd/max597x.h | 100 +++++++++++++++++++++++++++++++++ > 4 files changed, 223 insertions(+) > create mode 100644 drivers/mfd/max597x.c > create mode 100644 include/linux/mfd/max597x.h > > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig > index 3b59456f5545..2422ae155118 100644 > --- a/drivers/mfd/Kconfig > +++ b/drivers/mfd/Kconfig > @@ -253,6 +253,18 @@ 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" Power Switch and Monitor > + depends on I2C > + depends on OF > + select MFD_CORE > + select REGMAP_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. LEDs > + > config MFD_CS47L15 > bool "Cirrus Logic CS47L15" > select PINCTRL_CS47L15 > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > index 858cacf659d6..f5f46b86401f 100644 > --- a/drivers/mfd/Makefile > +++ b/drivers/mfd/Makefile > @@ -95,6 +95,8 @@ obj-$(CONFIG_MFD_MADERA) += madera.o > obj-$(CONFIG_MFD_MADERA_I2C) += madera-i2c.o > obj-$(CONFIG_MFD_MADERA_SPI) += madera-spi.o > > +obj-$(CONFIG_MFD_MAX597X) += max597x.o Why don't you put it next to the existing MAX entries? > obj-$(CONFIG_TPS6105X) += tps6105x.o > obj-$(CONFIG_TPS65010) += tps65010.o > obj-$(CONFIG_TPS6507X) += tps6507x.o > diff --git a/drivers/mfd/max597x.c b/drivers/mfd/max597x.c > new file mode 100644 > index 000000000000..b2450e64d3eb > --- /dev/null > +++ b/drivers/mfd/max597x.c > @@ -0,0 +1,109 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Device driver for regulators in MAX5970 and MAX5978 IC This is not a regulator driver. Please state what the 2 devices are. > + * Copyright (c) 2022 9elements GmbH > + * > + * Author: Patrick Rudolph <patrick.rudolph@9elements.com> > + */ > + > +#include <linux/bitops.h> > +#include <linux/device.h> > +#include <linux/err.h> > +#include <linux/leds.h> > +#include <linux/module.h> > +#include <linux/io.h> > +#include <linux/of.h> > +#include <linux/i2c.h> > +#include <linux/mfd/core.h> > +#include <linux/regmap.h> > +#include <linux/regulator/driver.h> > +#include <linux/regulator/machine.h> > +#include <linux/regulator/of_regulator.h> > +#include <linux/version.h> > +#include <linux/mfd/max597x.h> Alphabetical. Also, are you sure *all* of these are needed? > +static const struct regmap_config max597x_regmap_config = { > + .reg_bits = 8, > + .val_bits = 8, > + .max_register = MAX_REGISTERS, > +}; > + > +static const struct mfd_cell max597x_devs[] = { max597x_cells > + { > + .name = "max597x-regulator", > + }, > + { > + .name = "max597x-iio", > + }, > + { > + .name = "max597x-led", > + }, Like this please: { .name = "max597x-regulator" }, { .name = "max597x-iio" }, { .name = "max597x-led" }, > +}; > + > +static int max597x_probe(struct i2c_client *i2c, const struct i2c_device_id *id) > +{ > + struct max597x_data *max597x; "_ddata *ddata" > + struct regmap *regmap; > + enum max597x_chip_type chip = id->driver_data; > + > + max597x = No break. > + devm_kzalloc(&i2c->dev, sizeof(struct max597x_data), GFP_KERNEL); sizeof(*ddata) '\n' > + switch (chip) { > + case MAX597x_TYPE_MAX5970: > + max597x->num_switches = 2; > + break; > + case MAX597x_TYPE_MAX5978: > + max597x->num_switches = 1; > + break; > + } Are you planning on expanding the information in .data? If not, why not put the number of switches in there instead? > + regmap = devm_regmap_init_i2c(i2c, &max597x_regmap_config); > + if (IS_ERR(regmap)) { > + dev_err(&i2c->dev, "No regmap\n"); Is that really what that means? "Failed to initialise regmap" > + return -EINVAL; > + } '\n' > + max597x->regmap = regmap; Why not put the value straight into max597x->regmap instead of creating a local variable that's only used once? > + max597x->irq = i2c->irq; > + max597x->dev = &i2c->dev; What the reason for saving this? > + i2c_set_clientdata(i2c, max597x); > + > + return devm_mfd_add_devices(max597x->dev, PLATFORM_DEVID_AUTO, > + max597x_devs, ARRAY_SIZE(max597x_devs), > + NULL, 0, NULL); > +} > + > +static const struct i2c_device_id max597x_table[] = { > + {.name = "max5970", MAX597x_TYPE_MAX5970}, > + {.name = "max5978", MAX597x_TYPE_MAX5978}, Spaces after the { and before the } please. > + {}, > +}; > + Remove this line. > +MODULE_DEVICE_TABLE(i2c, max597x_table); > + > +static const struct of_device_id max597x_of_match[] = { > + { .compatible = "maxim,max5970", Needs to be on the line below. > + .data = (void *)MAX597x_TYPE_MAX5970 > + }, > + { .compatible = "maxim,max5978", Line below. > + .data = (void *)MAX597x_TYPE_MAX5978 > + }, > + {}, > +}; > + Remove. > +MODULE_DEVICE_TABLE(of, max597x_of_match); > + > +static struct i2c_driver max597x_driver = { > + .id_table = max597x_table, > + .driver = { > + .name = "max597x", > + .of_match_table = of_match_ptr(max597x_of_match), > + }, Wrong tab spacing. Should line up with the .driver. > + .probe = max597x_probe, > +}; > + Remove. > +module_i2c_driver(max597x_driver); > + > +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); > +MODULE_DESCRIPTION("MAX5970_hot-swap controller driver"); This is not a good description. > +MODULE_LICENSE("GPL v2"); > diff --git a/include/linux/mfd/max597x.h b/include/linux/mfd/max597x.h > new file mode 100644 > index 000000000000..ac7e9c84d06c > --- /dev/null > +++ b/include/linux/mfd/max597x.h > @@ -0,0 +1,100 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Device driver for regulators in MAX5970 and MAX5978 IC As above. > + * Copyright (c) 2022 9elements GmbH > + * > + * Author: Patrick Rudolph <patrick.rudolph@9elements.com> > + */ > + > +#ifndef _MAX597X_H > +#define _MAX597X_H MFD_ > +#include <linux/regmap.h> device.h > +#define MAX5970_NUM_SWITCHES 2 > +#define MAX5978_NUM_SWITCHES 1 > +#define MAX597X_NUM_LEDS 4 > + > +struct max597x_data { Place this at the bottom of the file. > + struct device *dev; > + int irq; > + int num_switches; > + struct regmap *regmap; > + u32 irng[MAX5970_NUM_SWITCHES]; > + u32 mon_rng[MAX5970_NUM_SWITCHES]; > + u32 shunt_micro_ohms[MAX5970_NUM_SWITCHES]; Why are these here? > +}; > + > +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)) BIT()? Same for the macros below. > +#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 */ -- Lee Jones [李琼斯] Principal Technical Lead - Developer Services Linaro.org │ Open source software for Arm SoCs Follow Linaro: Facebook | Twitter | Blog ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 3/5] regulator: max597x: Add support for max597x regulator 2022-07-07 13:41 [PATCH v2 0/5] mfd: max597x: Add support for max597x Naresh Solanki 2022-07-07 13:41 ` [PATCH v2 1/5] dt-bindings: mfd: Add bindings for MAX5970 and MAX5978 Naresh Solanki 2022-07-07 13:41 ` [PATCH v2 2/5] mfd: max597x: Add support " Naresh Solanki @ 2022-07-07 13:41 ` Naresh Solanki 2022-07-07 13:43 ` Mark Brown 2022-07-07 13:41 ` [PATCH v2 4/5] iio: max597x: Add support for max597x Naresh Solanki 2022-07-07 13:41 ` [PATCH v2 5/5] leds: " Naresh Solanki 4 siblings, 1 reply; 9+ messages in thread From: Naresh Solanki @ 2022-07-07 13:41 UTC (permalink / raw) To: linux-kernel, Liam Girdwood, Mark Brown Cc: Patrick Rudolph, Marcello Sylvester Bauer, Naresh Solanki From: Patrick Rudolph <patrick.rudolph@9elements.com> max597x is hot swap controller. This regulator driver controls the same & also configures fault protection features supported by the chip. 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/regulator/Kconfig | 10 + drivers/regulator/Makefile | 1 + drivers/regulator/max597x-regulator.c | 506 ++++++++++++++++++++++++++ 3 files changed, 517 insertions(+) create mode 100644 drivers/regulator/max597x-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index cbe0f96ca342..e26ad891bb03 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -546,6 +546,16 @@ config REGULATOR_MAX1586 regulator via I2C bus. The provided regulator is suitable for PXA27x chips to control VCC_CORE and VCC_USIM voltages. +config REGULATOR_MAX597X + tristate "Maxim 597x power switch and monitor" + depends on I2C + depends on OF + depends MFD_MAX597X + 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. + config REGULATOR_MAX77620 tristate "Maxim 77620/MAX20024 voltage regulator" depends on MFD_MAX77620 || COMPILE_TEST diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 8d3ee8b6d41d..4a8a42998561 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o +obj-$(CONFIG_REGULATOR_MAX597X) += max597x-regulator.o obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o diff --git a/drivers/regulator/max597x-regulator.c b/drivers/regulator/max597x-regulator.c new file mode 100644 index 000000000000..f95acd1c5e3a --- /dev/null +++ b/drivers/regulator/max597x-regulator.c @@ -0,0 +1,506 @@ +// 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> + */ + +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/version.h> +#include <linux/platform_device.h> + +#include <linux/mfd/max597x.h> + +struct max597x_regulator { + int num_switches, mon_rng, irng, shunt_micro_ohms, lim_uA; + struct regmap *regmap; +}; + +enum max597x_regulator_id { + MAX597X_SW0, + MAX597X_SW1, +}; + +static int max597x_uvp_ovp_check_mode(struct regulator_dev *rdev, int severity) +{ + int ret, reg; + + /* Status1 register contains the soft strap values sampled at POR */ + ret = regmap_read(rdev->regmap, MAX5970_REG_STATUS1, ®); + if (ret) + return ret; + + /* Check soft straps match requested mode */ + if (severity == REGULATOR_SEVERITY_PROT) { + if (STATUS1_PROT(reg) != STATUS1_PROT_SHUTDOWN) + return -EOPNOTSUPP; + + return 0; + } + if (STATUS1_PROT(reg) == STATUS1_PROT_SHUTDOWN) + return -EOPNOTSUPP; + + return 0; +} + +static int max597x_set_vp(struct regulator_dev *rdev, int lim_uV, int severity, + bool enable, bool overvoltage) +{ + int off_h, off_l, reg, ret; + struct max597x_regulator *data = rdev_get_drvdata(rdev); + int channel = rdev_get_id(rdev); + + if (overvoltage) { + if (severity == REGULATOR_SEVERITY_WARN) { + off_h = MAX5970_REG_CH_OV_WARN_H(channel); + off_l = MAX5970_REG_CH_OV_WARN_L(channel); + } else { + off_h = MAX5970_REG_CH_OV_CRIT_H(channel); + off_l = MAX5970_REG_CH_OV_CRIT_L(channel); + } + } else { + if (severity == REGULATOR_SEVERITY_WARN) { + off_h = MAX5970_REG_CH_UV_WARN_H(channel); + off_l = MAX5970_REG_CH_UV_WARN_L(channel); + } else { + off_h = MAX5970_REG_CH_UV_CRIT_H(channel); + off_l = MAX5970_REG_CH_UV_CRIT_L(channel); + } + } + + if (enable) + /* reg = ADC_MASK * (lim_uV / 1000000) / (data->mon_rng / 1000000) */ + reg = ADC_MASK * lim_uV / data->mon_rng; + else + reg = 0; + + ret = regmap_write(rdev->regmap, off_h, MAX5970_VAL2REG_H(reg)); + if (ret) + return ret; + + ret = regmap_write(rdev->regmap, off_l, MAX5970_VAL2REG_L(reg)); + if (ret) + return ret; + + return 0; +} + +static int max597x_set_uvp(struct regulator_dev *rdev, int lim_uV, int severity, + bool enable) +{ + int ret; + + /* + * MAX5970 has enable control as a special value in limit reg. Can't + * set limit but keep feature disabled or enable W/O given limit. + */ + if ((lim_uV && !enable) || (!lim_uV && enable)) + return -EINVAL; + + ret = max597x_uvp_ovp_check_mode(rdev, severity); + if (ret) + return ret; + + return max597x_set_vp(rdev, lim_uV, severity, enable, false); +} + +static int max597x_set_ovp(struct regulator_dev *rdev, int lim_uV, int severity, + bool enable) +{ + int ret; + + /* + * MAX5970 has enable control as a special value in limit reg. Can't + * set limit but keep feature disabled or enable W/O given limit. + */ + if ((lim_uV && !enable) || (!lim_uV && enable)) + return -EINVAL; + + ret = max597x_uvp_ovp_check_mode(rdev, severity); + if (ret) + return ret; + + return max597x_set_vp(rdev, lim_uV, severity, enable, true); +} + +static int max597x_set_ocp(struct regulator_dev *rdev, int lim_uA, + int severity, bool enable) +{ + int ret, val, reg; + unsigned int vthst, vthfst; + + struct max597x_regulator *data = rdev_get_drvdata(rdev); + int rdev_id = rdev_get_id(rdev); + /* + * MAX5970 doesn't has enable control for ocp. + * If limit is specified but enable is not set then hold the value in + * variable & later use it when ocp needs to be enabled. + */ + if (lim_uA != 0 && lim_uA != data->lim_uA) + data->lim_uA = lim_uA; + + if (severity != REGULATOR_SEVERITY_PROT) + return -EINVAL; + + if (enable) { + + /* Calc Vtrip threshold in uV. */ + vthst = + div_u64(mul_u32_u32(data->shunt_micro_ohms, data->lim_uA), + 1000000); + + /* + * As recommended in datasheed, add 20% margin to avoid + * spurious event & passive component tolerance. + */ + vthst = div_u64(mul_u32_u32(vthst, 120), 100); + + /* Calc fast Vtrip threshold in uV */ + vthfst = vthst * (MAX5970_FAST2SLOW_RATIO / 100); + + if (vthfst > data->irng) { + dev_err(&rdev->dev, "Current limit out of range\n"); + return -EINVAL; + } + /* Fast trip threshold to be programmed */ + val = div_u64(mul_u32_u32(0xFF, vthfst), data->irng); + } else + /* + * Since there is no option to disable ocp, set limit to max + * value + */ + val = 0xFF; + + reg = MAX5970_REG_DAC_FAST(rdev_id); + ret = regmap_write(rdev->regmap, reg, val); + + return ret; +} + +static int max597x_get_status(struct regulator_dev *rdev) +{ + int val, ret; + + ret = regmap_read(rdev->regmap, MAX5970_REG_STATUS3, &val); + if (ret) + return REGULATOR_FAILED_RETRY; + + if (val & MAX5970_STATUS3_ALERT) + return REGULATOR_STATUS_ERROR; + + ret = regulator_is_enabled_regmap(rdev); + if (ret < 0) + return ret; + + if (ret) + return REGULATOR_STATUS_ON; + + return REGULATOR_STATUS_OFF; +} + +static const struct regulator_ops max597x_switch_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_status = max597x_get_status, + .set_over_voltage_protection = max597x_set_ovp, + .set_under_voltage_protection = max597x_set_uvp, + .set_over_current_protection = max597x_set_ocp, +}; + +static int max597x_dt_parse(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *cfg) +{ + struct max597x_regulator *data = cfg->driver_data; + int ret = 0; + + ret = + of_property_read_u32(np, "shunt-resistor-micro-ohms", + &data->shunt_micro_ohms); + if (ret < 0) + dev_err(cfg->dev, + "property 'shunt-resistor-micro-ohms' not found, err %d\n", + ret); + return ret; + +} + +#define MAX597X_SWITCH(_ID, _ereg, _chan, _supply) { \ + .name = #_ID, \ + .of_match = of_match_ptr(#_ID), \ + .ops = &max597x_switch_ops, \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .id = MAX597X_##_ID, \ + .owner = THIS_MODULE, \ + .supply_name = _supply, \ + .enable_reg = _ereg, \ + .enable_mask = CHXEN((_chan)), \ + .of_parse_cb = max597x_dt_parse, \ +} + +static const struct regulator_desc regulators[] = { + MAX597X_SWITCH(SW0, MAX5970_REG_CHXEN, 0, "vss1"), + MAX597X_SWITCH(SW1, MAX5970_REG_CHXEN, 1, "vss2"), +}; + +static int max597x_regmap_read_clear(struct regmap *map, unsigned int reg, + unsigned int *val) +{ + int ret; + + ret = regmap_read(map, reg, val); + if (ret) + return ret; + + if (*val) + return regmap_write(map, reg, *val); + + return 0; +} + +static int max597x_irq_handler(int irq, struct regulator_irq_data *rid, + unsigned long *dev_mask) +{ + struct regulator_err_state *stat; + struct max597x_regulator *d = (struct max597x_regulator *)rid->data; + int val, ret, i; + + ret = max597x_regmap_read_clear(d->regmap, MAX5970_REG_FAULT0, &val); + if (ret) + return REGULATOR_FAILED_RETRY; + + *dev_mask = 0; + for (i = 0; i < d->num_switches; i++) { + stat = &rid->states[i]; + stat->notifs = 0; + stat->errors = 0; + } + + for (i = 0; i < d->num_switches; i++) { + stat = &rid->states[i]; + + if (val & UV_STATUS_CRIT(i)) { + *dev_mask |= 1 << i; + stat->notifs |= REGULATOR_EVENT_UNDER_VOLTAGE; + stat->errors |= REGULATOR_ERROR_UNDER_VOLTAGE; + } else if (val & UV_STATUS_WARN(i)) { + *dev_mask |= 1 << i; + stat->notifs |= REGULATOR_EVENT_UNDER_VOLTAGE_WARN; + stat->errors |= REGULATOR_ERROR_UNDER_VOLTAGE_WARN; + } + } + + ret = max597x_regmap_read_clear(d->regmap, MAX5970_REG_FAULT1, &val); + if (ret) + return REGULATOR_FAILED_RETRY; + + for (i = 0; i < d->num_switches; i++) { + stat = &rid->states[i]; + + if (val & OV_STATUS_CRIT(i)) { + *dev_mask |= 1 << i; + stat->notifs |= REGULATOR_EVENT_REGULATION_OUT; + stat->errors |= REGULATOR_ERROR_REGULATION_OUT; + } else if (val & OV_STATUS_WARN(i)) { + *dev_mask |= 1 << i; + stat->notifs |= REGULATOR_EVENT_OVER_VOLTAGE_WARN; + stat->errors |= REGULATOR_ERROR_OVER_VOLTAGE_WARN; + } + } + + ret = max597x_regmap_read_clear(d->regmap, MAX5970_REG_FAULT2, &val); + if (ret) + return REGULATOR_FAILED_RETRY; + + for (i = 0; i < d->num_switches; i++) { + stat = &rid->states[i]; + + if (val & OC_STATUS_WARN(i)) { + *dev_mask |= 1 << i; + stat->notifs |= REGULATOR_EVENT_OVER_CURRENT_WARN; + stat->errors |= REGULATOR_ERROR_OVER_CURRENT_WARN; + } + } + + ret = regmap_read(d->regmap, MAX5970_REG_STATUS0, &val); + if (ret) + return REGULATOR_FAILED_RETRY; + + for (i = 0; i < d->num_switches; i++) { + stat = &rid->states[i]; + + if ((val & MAX5970_CB_IFAULTF(i)) + || (val & MAX5970_CB_IFAULTS(i))) { + *dev_mask |= 1 << i; + stat->notifs |= + REGULATOR_EVENT_OVER_CURRENT | + REGULATOR_EVENT_DISABLE; + stat->errors |= + REGULATOR_ERROR_OVER_CURRENT | REGULATOR_ERROR_FAIL; + + /* Clear the sub-IRQ status */ + regulator_disable_regmap(stat->rdev); + } + } + return 0; +} + +static const struct regmap_config max597x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX_REGISTERS, +}; + +static int max597x_adc_range(struct regmap *regmap, const int ch, + u32 *irng, u32 *mon_rng) +{ + unsigned int reg; + int ret; + + /* Decode current ADC range */ + ret = regmap_read(regmap, MAX5970_REG_STATUS2, ®); + if (ret) + return ret; + switch (MAX5970_IRNG(reg, ch)) { + case 0: + *irng = 100000; /* 100 mV */ + break; + case 1: + *irng = 50000; /* 50 mV */ + break; + case 2: + *irng = 25000; /* 25 mV */ + break; + default: + return -EINVAL; + } + + /* Decode current voltage monitor range */ + ret = regmap_read(regmap, MAX5970_REG_MON_RANGE, ®); + if (ret) + return ret; + + *mon_rng = MAX5970_MON_MAX_RANGE_UV >> MAX5970_MON(reg, ch); + + return 0; +} + +static int max597x_setup_irq(struct device *dev, + int irq, + struct regulator_dev *rdevs[MAX5970_NUM_SWITCHES], + int num_switches, struct max597x_regulator *data) +{ + struct regulator_irq_desc max597x_notif = { + .name = "max597x-irq", + .map_event = max597x_irq_handler, + .data = data, + }; + int errs = REGULATOR_ERROR_UNDER_VOLTAGE | + REGULATOR_ERROR_UNDER_VOLTAGE_WARN | + REGULATOR_ERROR_OVER_VOLTAGE_WARN | + REGULATOR_ERROR_REGULATION_OUT | + REGULATOR_ERROR_OVER_CURRENT | + REGULATOR_ERROR_OVER_CURRENT_WARN | REGULATOR_ERROR_FAIL; + void *irq_helper; + + /* Register notifiers - can fail if IRQ is not given */ + irq_helper = devm_regulator_irq_helper(dev, &max597x_notif, + irq, 0, errs, NULL, + &rdevs[0], num_switches); + if (IS_ERR(irq_helper)) { + if (PTR_ERR(irq_helper) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_warn(dev, "IRQ disabled %pe\n", irq_helper); + } + + return 0; +} + +static int max597x_regulator_probe(struct platform_device *pdev) +{ + + + struct max597x_data *max597x = dev_get_drvdata(pdev->dev.parent); + struct max597x_regulator *data; + + struct regulator_config config = { }; + struct regulator_dev *rdev; + struct regulator_dev *rdevs[MAX5970_NUM_SWITCHES]; + int num_switches = max597x->num_switches; + int ret, i; + + for (i = 0; i < num_switches; i++) { + data = + devm_kzalloc(max597x->dev, sizeof(struct max597x_regulator), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->num_switches = num_switches; + data->regmap = max597x->regmap; + + if (ret < 0) + return ret; + + ret = max597x_adc_range(data->regmap, i, &max597x->irng[i], &max597x->mon_rng[i]); + if (ret < 0) + return ret; + + data->irng = max597x->irng[i]; + data->mon_rng = max597x->mon_rng[i]; + + config.dev = max597x->dev; + config.driver_data = (void *)data; + config.regmap = data->regmap; + rdev = devm_regulator_register(max597x->dev, + ®ulators[i], &config); + if (IS_ERR(rdev)) { + dev_err(max597x->dev, "failed to register regulator %s\n", + regulators[i].name); + return PTR_ERR(rdev); + } + rdevs[i] = rdev; + max597x->shunt_micro_ohms[i] = data->shunt_micro_ohms; + } + + if (max597x->irq) { + ret = + max597x_setup_irq(max597x->dev, max597x->irq, rdevs, num_switches, + data); + if (ret) { + dev_err(max597x->dev, "IRQ setup failed"); + return ret; + } + } + + return ret; +} + +static struct platform_driver max597x_regulator_driver = { + .driver = { + .name = "max597x-regulator", + }, + .probe = max597x_regulator_probe, +}; + +module_platform_driver(max597x_regulator_driver); + + +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); +MODULE_DESCRIPTION("MAX5970_hot-swap controller driver"); +MODULE_LICENSE("GPL v2"); -- 2.35.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 3/5] regulator: max597x: Add support for max597x regulator 2022-07-07 13:41 ` [PATCH v2 3/5] regulator: max597x: Add support for max597x regulator Naresh Solanki @ 2022-07-07 13:43 ` Mark Brown 0 siblings, 0 replies; 9+ messages in thread From: Mark Brown @ 2022-07-07 13:43 UTC (permalink / raw) To: Naresh Solanki Cc: linux-kernel, Liam Girdwood, Patrick Rudolph, Marcello Sylvester Bauer [-- Attachment #1: Type: text/plain, Size: 576 bytes --] On Thu, Jul 07, 2022 at 03:41:39PM +0200, Naresh Solanki wrote: > From: Patrick Rudolph <patrick.rudolph@9elements.com> > > max597x is hot swap controller. > This regulator driver controls the same & also configures fault > protection features supported by the chip. Please do not submit new versions of already applied patches, please submit incremental updates to the existing code. Modifying existing commits creates problems for other users building on top of those commits so it's best practice to only change pubished git commits if absolutely essential. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 4/5] iio: max597x: Add support for max597x 2022-07-07 13:41 [PATCH v2 0/5] mfd: max597x: Add support for max597x Naresh Solanki ` (2 preceding siblings ...) 2022-07-07 13:41 ` [PATCH v2 3/5] regulator: max597x: Add support for max597x regulator Naresh Solanki @ 2022-07-07 13:41 ` Naresh Solanki 2022-07-07 14:38 ` kernel test robot 2022-07-07 13:41 ` [PATCH v2 5/5] leds: " Naresh Solanki 4 siblings, 1 reply; 9+ messages in thread From: Naresh Solanki @ 2022-07-07 13:41 UTC (permalink / raw) To: linux-kernel; +Cc: Patrick Rudolph, Naresh Solanki From: Patrick Rudolph <patrick.rudolph@9elements.com> max597x has 10bit ADC for voltage & current monitoring. Use iio framework to expose the same in sysfs. Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> --- drivers/iio/adc/Kconfig | 9 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/max597x-iio.c | 156 ++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/iio/adc/max597x-iio.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 48ace7412874..8d23c81d4105 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -683,6 +683,15 @@ config MAX1363 To compile this driver as a module, choose M here: the module will be called max1363. +config MAX597X_IIO + tristate "Maxim 597x power switch and monitor" + depends on I2C + depends on OF + depends MFD_MAX597X + help + This driver exposes Maxim 5970/5978 voltage/current monitoring + interface using iio framework. + config MAX9611 tristate "Maxim max9611/max9612 ADC driver" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 39d806f6d457..f8cb5a30a946 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX1118) += max1118.o obj-$(CONFIG_MAX1241) += max1241.o obj-$(CONFIG_MAX1363) += max1363.o +obj-$(CONFIG_MAX597X_IIO) += max597x-iio.o obj-$(CONFIG_MAX9611) += max9611.o obj-$(CONFIG_MCP320X) += mcp320x.o obj-$(CONFIG_MCP3422) += mcp3422.o diff --git a/drivers/iio/adc/max597x-iio.c b/drivers/iio/adc/max597x-iio.c new file mode 100644 index 000000000000..de0ea762c5c8 --- /dev/null +++ b/drivers/iio/adc/max597x-iio.c @@ -0,0 +1,156 @@ +// 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> + */ + +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/iio/iio.h> +#include <linux/of.h> +#include <linux/i2c.h> +#include <linux/mfd/max597x.h> +#include <linux/regmap.h> +#include <linux/version.h> +#include <linux/platform_device.h> + +struct max597x_iio { + struct regmap *regmap; + int shunt_micro_ohms[MAX5970_NUM_SWITCHES]; + unsigned int irng[MAX5970_NUM_SWITCHES]; + unsigned int mon_rng[MAX5970_NUM_SWITCHES]; +}; + +#define MAX597X_ADC_CHANNEL(_idx, _type) { \ + .type = IIO_ ## _type, \ + .indexed = 1, \ + .channel = (_idx), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .address = MAX5970_REG_ ## _type ## _L(_idx), \ +} + +static const struct iio_chan_spec max5978_adc_iio_channels[] = { + MAX597X_ADC_CHANNEL(0, VOLTAGE), + MAX597X_ADC_CHANNEL(0, CURRENT), +}; + +static const struct iio_chan_spec max5970_adc_iio_channels[] = { + MAX597X_ADC_CHANNEL(0, VOLTAGE), + MAX597X_ADC_CHANNEL(0, CURRENT), + MAX597X_ADC_CHANNEL(1, VOLTAGE), + MAX597X_ADC_CHANNEL(1, CURRENT), +}; + +static int max597x_iio_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long info) +{ + int ret; + struct max597x_iio *data = iio_priv(iio_dev); + unsigned int reg_l, reg_h; + + switch (info) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(data->regmap, chan->address, ®_l); + if (ret < 0) + return ret; + ret = regmap_read(data->regmap, chan->address - 1, ®_h); + if (ret < 0) + return ret; + *val = (reg_h << 2) | (reg_l & 3); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + + switch (chan->address) { + case MAX5970_REG_CURRENT_L(0): + fallthrough; + case MAX5970_REG_CURRENT_L(1): + /* in A, convert to mA */ + *val = data->irng[chan->channel] * 1000; + *val2 = + data->shunt_micro_ohms[chan->channel] * ADC_MASK; + return IIO_VAL_FRACTIONAL; + + case MAX5970_REG_VOLTAGE_L(0): + fallthrough; + case MAX5970_REG_VOLTAGE_L(1): + /* in uV, convert to mV */ + *val = data->mon_rng[chan->channel]; + *val2 = ADC_MASK * 1000; + return IIO_VAL_FRACTIONAL; + } + + break; + } + return -EINVAL; +} + +static const struct iio_info max597x_adc_iio_info = { + .read_raw = &max597x_iio_read_raw, +}; + +static int max597x_iio_probe(struct platform_device *pdev) +{ + struct max597x_data *max597x = dev_get_drvdata(pdev->dev.parent); + struct iio_dev *indio_dev; + struct max597x_iio *priv; + int ret, i; + + /* registering iio */ + indio_dev = devm_iio_device_alloc(max597x->dev, sizeof(*priv)); + if (!indio_dev) { + dev_err(max597x->dev, "failed allocating iio device\n"); + return -ENOMEM; + } + indio_dev->name = dev_name(max597x->dev); + indio_dev->info = &max597x_adc_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + switch (max597x->num_switches) { + case MAX597x_TYPE_MAX5970: + indio_dev->channels = max5970_adc_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(max5970_adc_iio_channels); + break; + case MAX597x_TYPE_MAX5978: + indio_dev->channels = max5978_adc_iio_channels; + indio_dev->num_channels = ARRAY_SIZE(max5978_adc_iio_channels); + break; + } + + priv = iio_priv(indio_dev); + priv->regmap = max597x->regmap; + for (i = 0; i < indio_dev->num_channels; i++) { + priv->irng[i] = max597x->irng[i]; + priv->mon_rng[i] = max597x->mon_rng[i]; + priv->shunt_micro_ohms[i] = max597x->shunt_micro_ohms[i]; + } + + ret = devm_iio_device_register(max597x->dev, indio_dev); + if (ret) + dev_err(max597x->dev, "could not register iio device"); + + return ret; + +} + +static struct platform_driver max597x_iio_driver = { + .driver = { + .name = "max597x-iio", + }, + .probe = max597x_iio_probe, +}; + +module_platform_driver(max597x_iio_driver); + + +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); +MODULE_DESCRIPTION("MAX5970_hot-swap controller driver"); +MODULE_LICENSE("GPL v2"); -- 2.35.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 4/5] iio: max597x: Add support for max597x 2022-07-07 13:41 ` [PATCH v2 4/5] iio: max597x: Add support for max597x Naresh Solanki @ 2022-07-07 14:38 ` kernel test robot 0 siblings, 0 replies; 9+ messages in thread From: kernel test robot @ 2022-07-07 14:38 UTC (permalink / raw) To: Naresh Solanki, linux-kernel; +Cc: kbuild-all, Patrick Rudolph, Naresh Solanki Hi Naresh, Thank you for the patch! Yet something to improve: [auto build test ERROR on 9f09069cde34dcd86f5ecf3a3139fd752020812f] url: https://github.com/intel-lab-lkp/linux/commits/Naresh-Solanki/mfd-max597x-Add-support-for-max597x/20220707-214501 base: 9f09069cde34dcd86f5ecf3a3139fd752020812f config: um-i386_defconfig compiler: gcc-11 (Debian 11.3.0-3) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/22ea6b6b3fde4f8c03be1f1d0345f3d1fcc295e8 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-max597x/20220707-214501 git checkout 22ea6b6b3fde4f8c03be1f1d0345f3d1fcc295e8 make W=1 ARCH=um SUBARCH=i386 defconfig make W=1 ARCH=um SUBARCH=i386 If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): drivers/regulator/Kconfig:554: syntax error drivers/regulator/Kconfig:553: invalid statement drivers/regulator/Kconfig:554: invalid statement drivers/regulator/Kconfig:555:warning: ignoring unsupported character '/' drivers/regulator/Kconfig:555:warning: ignoring unsupported character '.' drivers/regulator/Kconfig:555: unknown statement "This" drivers/regulator/Kconfig:556:warning: ignoring unsupported character '/' drivers/regulator/Kconfig:556:warning: ignoring unsupported character ',' drivers/regulator/Kconfig:556: unknown statement "The" drivers/regulator/Kconfig:557:warning: ignoring unsupported character '.' drivers/regulator/Kconfig:557: unknown statement "fault" >> drivers/iio/adc/Kconfig:691: syntax error drivers/iio/adc/Kconfig:690: invalid statement drivers/iio/adc/Kconfig:691: invalid statement drivers/iio/adc/Kconfig:692:warning: ignoring unsupported character '/' drivers/iio/adc/Kconfig:692:warning: ignoring unsupported character '/' drivers/iio/adc/Kconfig:692: unknown statement "This" drivers/iio/adc/Kconfig:693:warning: ignoring unsupported character '.' drivers/iio/adc/Kconfig:693: unknown statement "interface" make[2]: *** [scripts/kconfig/Makefile:87: defconfig] Error 1 make[1]: *** [Makefile:629: defconfig] Error 2 make: *** [Makefile:219: __sub-make] Error 2 make: Target 'defconfig' not remade because of errors. -- drivers/regulator/Kconfig:554: syntax error drivers/regulator/Kconfig:553: invalid statement drivers/regulator/Kconfig:554: invalid statement drivers/regulator/Kconfig:555:warning: ignoring unsupported character '/' drivers/regulator/Kconfig:555:warning: ignoring unsupported character '.' drivers/regulator/Kconfig:555: unknown statement "This" drivers/regulator/Kconfig:556:warning: ignoring unsupported character '/' drivers/regulator/Kconfig:556:warning: ignoring unsupported character ',' drivers/regulator/Kconfig:556: unknown statement "The" drivers/regulator/Kconfig:557:warning: ignoring unsupported character '.' drivers/regulator/Kconfig:557: unknown statement "fault" >> drivers/iio/adc/Kconfig:691: syntax error drivers/iio/adc/Kconfig:690: invalid statement drivers/iio/adc/Kconfig:691: invalid statement drivers/iio/adc/Kconfig:692:warning: ignoring unsupported character '/' drivers/iio/adc/Kconfig:692:warning: ignoring unsupported character '/' drivers/iio/adc/Kconfig:692: unknown statement "This" drivers/iio/adc/Kconfig:693:warning: ignoring unsupported character '.' drivers/iio/adc/Kconfig:693: unknown statement "interface" make[2]: *** [scripts/kconfig/Makefile:77: oldconfig] Error 1 make[1]: *** [Makefile:629: oldconfig] Error 2 make: *** [Makefile:219: __sub-make] Error 2 make: Target 'oldconfig' not remade because of errors. -- drivers/regulator/Kconfig:554: syntax error drivers/regulator/Kconfig:553: invalid statement drivers/regulator/Kconfig:554: invalid statement drivers/regulator/Kconfig:555:warning: ignoring unsupported character '/' drivers/regulator/Kconfig:555:warning: ignoring unsupported character '.' drivers/regulator/Kconfig:555: unknown statement "This" drivers/regulator/Kconfig:556:warning: ignoring unsupported character '/' drivers/regulator/Kconfig:556:warning: ignoring unsupported character ',' drivers/regulator/Kconfig:556: unknown statement "The" drivers/regulator/Kconfig:557:warning: ignoring unsupported character '.' drivers/regulator/Kconfig:557: unknown statement "fault" >> drivers/iio/adc/Kconfig:691: syntax error drivers/iio/adc/Kconfig:690: invalid statement drivers/iio/adc/Kconfig:691: invalid statement drivers/iio/adc/Kconfig:692:warning: ignoring unsupported character '/' drivers/iio/adc/Kconfig:692:warning: ignoring unsupported character '/' drivers/iio/adc/Kconfig:692: unknown statement "This" drivers/iio/adc/Kconfig:693:warning: ignoring unsupported character '.' drivers/iio/adc/Kconfig:693: unknown statement "interface" make[2]: *** [scripts/kconfig/Makefile:77: olddefconfig] Error 1 make[1]: *** [Makefile:629: olddefconfig] Error 2 make: *** [Makefile:219: __sub-make] Error 2 make: Target 'olddefconfig' not remade because of errors. vim +691 drivers/iio/adc/Kconfig 8 9 config AB8500_GPADC 10 bool "ST-Ericsson AB8500 GPADC driver" 11 depends on AB8500_CORE && REGULATOR_AB8500 12 default y 13 help 14 AB8500 Analog Baseband, mixed signal integrated circuit GPADC 15 (General Purpose Analog to Digital Converter) driver used to monitor 16 internal voltages, convert accessory and battery, AC (charger, mains) 17 and USB voltages integral to the U8500 platform. 18 19 config AD_SIGMA_DELTA 20 tristate 21 select IIO_BUFFER 22 select IIO_TRIGGERED_BUFFER 23 24 config AD7091R5 25 tristate "Analog Devices AD7091R5 ADC Driver" 26 depends on I2C 27 select REGMAP_I2C 28 help 29 Say yes here to build support for Analog Devices AD7091R-5 ADC. 30 31 config AD7124 32 tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver" 33 depends on SPI_MASTER 34 select AD_SIGMA_DELTA 35 help 36 Say yes here to build support for Analog Devices AD7124-4 and AD7124-8 37 SPI analog to digital converters (ADC). 38 39 To compile this driver as a module, choose M here: the module will be 40 called ad7124. 41 42 config AD7192 43 tristate "Analog Devices AD7190 AD7192 AD7193 AD7195 ADC driver" 44 depends on SPI 45 select AD_SIGMA_DELTA 46 help 47 Say yes here to build support for Analog Devices AD7190, 48 AD7192, AD7193 or AD7195 SPI analog to digital converters (ADC). 49 If unsure, say N (but it's safe to say "Y"). 50 51 To compile this driver as a module, choose M here: the 52 module will be called ad7192. 53 54 config AD7266 55 tristate "Analog Devices AD7265/AD7266 ADC driver" 56 depends on SPI_MASTER 57 select IIO_BUFFER 58 select IIO_TRIGGER 59 select IIO_TRIGGERED_BUFFER 60 help 61 Say yes here to build support for Analog Devices AD7265 and AD7266 62 ADCs. 63 64 To compile this driver as a module, choose M here: the module will be 65 called ad7266. 66 67 config AD7280 68 tristate "Analog Devices AD7280A Lithium Ion Battery Monitoring System" 69 depends on SPI 70 select CRC8 71 help 72 Say yes here to build support for Analog Devices AD7280A 73 Lithium Ion Battery Monitoring System. 74 75 To compile this driver as a module, choose M here: the 76 module will be called ad7280a 77 78 config AD7291 79 tristate "Analog Devices AD7291 ADC driver" 80 depends on I2C 81 help 82 Say yes here to build support for Analog Devices AD7291 83 8 Channel ADC with temperature sensor. 84 85 To compile this driver as a module, choose M here: the 86 module will be called ad7291. 87 88 config AD7292 89 tristate "Analog Devices AD7292 ADC driver" 90 depends on SPI 91 help 92 Say yes here to build support for Analog Devices AD7292 93 8 Channel ADC with temperature sensor. 94 95 To compile this driver as a module, choose M here: the 96 module will be called ad7292. 97 98 config AD7298 99 tristate "Analog Devices AD7298 ADC driver" 100 depends on SPI 101 select IIO_BUFFER 102 select IIO_TRIGGERED_BUFFER 103 help 104 Say yes here to build support for Analog Devices AD7298 105 8 Channel ADC with temperature sensor. 106 107 To compile this driver as a module, choose M here: the 108 module will be called ad7298. 109 110 config AD7476 111 tristate "Analog Devices AD7476 1-channel ADCs driver and other similar devices from AD and TI" 112 depends on SPI 113 select IIO_BUFFER 114 select IIO_TRIGGERED_BUFFER 115 help 116 Say yes here to build support for the following SPI analog to 117 digital converters (ADCs): 118 Analog Devices: AD7273, AD7274, AD7276, AD7277, AD7278, AD7475, 119 AD7476, AD7477, AD7478, AD7466, AD7467, AD7468, AD7495, AD7910, 120 AD7920. 121 Texas Instruments: ADS7866, ADS7867, ADS7868. 122 123 To compile this driver as a module, choose M here: the 124 module will be called ad7476. 125 126 config AD7606 127 tristate 128 select IIO_BUFFER 129 select IIO_TRIGGERED_BUFFER 130 131 config AD7606_IFACE_PARALLEL 132 tristate "Analog Devices AD7606 ADC driver with parallel interface support" 133 depends on HAS_IOMEM 134 select AD7606 135 help 136 Say yes here to build parallel interface support for Analog Devices: 137 ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). 138 139 To compile this driver as a module, choose M here: the 140 module will be called ad7606_parallel. 141 142 config AD7606_IFACE_SPI 143 tristate "Analog Devices AD7606 ADC driver with spi interface support" 144 depends on SPI 145 select AD7606 146 help 147 Say yes here to build spi interface support for Analog Devices: 148 ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). 149 150 To compile this driver as a module, choose M here: the 151 module will be called ad7606_spi. 152 153 config AD7766 154 tristate "Analog Devices AD7766/AD7767 ADC driver" 155 depends on SPI_MASTER 156 select IIO_BUFFER 157 select IIO_TRIGGERED_BUFFER 158 help 159 Say yes here to build support for Analog Devices AD7766, AD7766-1, 160 AD7766-2, AD7767, AD7767-1, AD7767-2 SPI analog to digital converters. 161 162 To compile this driver as a module, choose M here: the module will be 163 called ad7766. 164 165 config AD7768_1 166 tristate "Analog Devices AD7768-1 ADC driver" 167 depends on SPI 168 select IIO_BUFFER 169 select IIO_TRIGGER 170 select IIO_TRIGGERED_BUFFER 171 help 172 Say yes here to build support for Analog Devices AD7768-1 SPI 173 simultaneously sampling sigma-delta analog to digital converter (ADC). 174 175 To compile this driver as a module, choose M here: the module will be 176 called ad7768-1. 177 178 config AD7780 179 tristate "Analog Devices AD7780 and similar ADCs driver" 180 depends on SPI 181 depends on GPIOLIB || COMPILE_TEST 182 select AD_SIGMA_DELTA 183 help 184 Say yes here to build support for Analog Devices AD7170, AD7171, 185 AD7780 and AD7781 SPI analog to digital converters (ADC). 186 187 To compile this driver as a module, choose M here: the 188 module will be called ad7780. 189 190 config AD7791 191 tristate "Analog Devices AD7791 ADC driver" 192 depends on SPI 193 select AD_SIGMA_DELTA 194 help 195 Say yes here to build support for Analog Devices AD7787, AD7788, AD7789, 196 AD7790 and AD7791 SPI analog to digital converters (ADC). 197 198 To compile this driver as a module, choose M here: the module will be 199 called ad7791. 200 201 config AD7793 202 tristate "Analog Devices AD7793 and similar ADCs driver" 203 depends on SPI 204 select AD_SIGMA_DELTA 205 help 206 Say yes here to build support for Analog Devices AD7785, AD7792, AD7793, 207 AD7794 and AD7795 SPI analog to digital converters (ADC). 208 209 To compile this driver as a module, choose M here: the 210 module will be called AD7793. 211 212 config AD7887 213 tristate "Analog Devices AD7887 ADC driver" 214 depends on SPI 215 select IIO_BUFFER 216 select IIO_TRIGGERED_BUFFER 217 help 218 Say yes here to build support for Analog Devices 219 AD7887 SPI analog to digital converter (ADC). 220 221 To compile this driver as a module, choose M here: the 222 module will be called ad7887. 223 224 config AD7923 225 tristate "Analog Devices AD7923 and similar ADCs driver" 226 depends on SPI 227 select IIO_BUFFER 228 select IIO_TRIGGERED_BUFFER 229 help 230 Say yes here to build support for Analog Devices 231 AD7904, AD7914, AD7923, AD7924 4 Channel ADCs. 232 233 To compile this driver as a module, choose M here: the 234 module will be called ad7923. 235 236 config AD7949 237 tristate "Analog Devices AD7949 and similar ADCs driver" 238 depends on SPI 239 help 240 Say yes here to build support for Analog Devices 241 AD7949, AD7682, AD7689 8 Channel ADCs. 242 243 To compile this driver as a module, choose M here: the 244 module will be called ad7949. 245 246 config AD799X 247 tristate "Analog Devices AD799x ADC driver" 248 depends on I2C 249 select IIO_BUFFER 250 select IIO_TRIGGERED_BUFFER 251 help 252 Say yes here to build support for Analog Devices: 253 ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998 254 i2c analog to digital converters (ADC). Provides direct access 255 via sysfs. 256 257 To compile this driver as a module, choose M here: the module will be 258 called ad799x. 259 260 config AD9467 261 tristate "Analog Devices AD9467 High Speed ADC driver" 262 depends on SPI 263 depends on ADI_AXI_ADC 264 help 265 Say yes here to build support for Analog Devices: 266 * AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter 267 268 The driver requires the assistance of the AXI ADC IP core to operate, 269 since SPI is used for configuration only, while data has to be 270 streamed into memory via DMA. 271 272 To compile this driver as a module, choose M here: the module will be 273 called ad9467. 274 275 config ADI_AXI_ADC 276 tristate "Analog Devices Generic AXI ADC IP core driver" 277 select IIO_BUFFER 278 select IIO_BUFFER_HW_CONSUMER 279 select IIO_BUFFER_DMAENGINE 280 depends on HAS_IOMEM 281 depends on OF 282 help 283 Say yes here to build support for Analog Devices Generic 284 AXI ADC IP core. The IP core is used for interfacing with 285 analog-to-digital (ADC) converters that require either a high-speed 286 serial interface (JESD204B/C) or a source synchronous parallel 287 interface (LVDS/CMOS). 288 Typically (for such devices) SPI will be used for configuration only, 289 while this IP core handles the streaming of data into memory via DMA. 290 291 Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip 292 If unsure, say N (but it's safe to say "Y"). 293 294 To compile this driver as a module, choose M here: the 295 module will be called adi-axi-adc. 296 297 config ASPEED_ADC 298 tristate "Aspeed ADC" 299 depends on ARCH_ASPEED || COMPILE_TEST 300 depends on COMMON_CLK 301 help 302 If you say yes here you get support for the ADC included in Aspeed 303 BMC SoCs. 304 305 To compile this driver as a module, choose M here: the module will be 306 called aspeed_adc. 307 308 config AT91_ADC 309 tristate "Atmel AT91 ADC" 310 depends on ARCH_AT91 || COMPILE_TEST 311 depends on INPUT && SYSFS && OF 312 select IIO_BUFFER 313 select IIO_TRIGGERED_BUFFER 314 help 315 Say yes here to build support for Atmel AT91 ADC. 316 317 To compile this driver as a module, choose M here: the module will be 318 called at91_adc. 319 320 config AT91_SAMA5D2_ADC 321 tristate "Atmel AT91 SAMA5D2 ADC" 322 depends on ARCH_AT91 || COMPILE_TEST 323 depends on HAS_IOMEM 324 select IIO_BUFFER 325 select IIO_TRIGGERED_BUFFER 326 help 327 Say yes here to build support for Atmel SAMA5D2 ADC which is 328 available on SAMA5D2 SoC family. 329 330 To compile this driver as a module, choose M here: the module will be 331 called at91-sama5d2_adc. 332 333 config AXP20X_ADC 334 tristate "X-Powers AXP20X and AXP22X ADC driver" 335 depends on MFD_AXP20X 336 help 337 Say yes here to have support for X-Powers power management IC (PMIC) 338 AXP20X and AXP22X ADC devices. 339 340 To compile this driver as a module, choose M here: the module will be 341 called axp20x_adc. 342 343 config AXP288_ADC 344 tristate "X-Powers AXP288 ADC driver" 345 depends on MFD_AXP20X 346 help 347 Say yes here to have support for X-Powers power management IC (PMIC) ADC 348 device. Depending on platform configuration, this general purpose ADC can 349 be used for sampling sensors such as thermal resistors. 350 351 To compile this driver as a module, choose M here: the module will be 352 called axp288_adc. 353 354 config BCM_IPROC_ADC 355 tristate "Broadcom IPROC ADC driver" 356 depends on (ARCH_BCM_IPROC && OF) || COMPILE_TEST 357 depends on MFD_SYSCON 358 default ARCH_BCM_CYGNUS 359 help 360 Say Y here if you want to add support for the Broadcom static 361 ADC driver. 362 363 Broadcom iProc ADC driver. Broadcom iProc ADC controller has 8 364 channels. The driver allows the user to read voltage values. 365 366 config BERLIN2_ADC 367 tristate "Marvell Berlin2 ADC driver" 368 depends on ARCH_BERLIN || COMPILE_TEST 369 help 370 Marvell Berlin2 ADC driver. This ADC has 8 channels, with one used for 371 temperature measurement. 372 373 config CC10001_ADC 374 tristate "Cosmic Circuits 10001 ADC driver" 375 depends on HAS_IOMEM && HAVE_CLK && REGULATOR 376 select IIO_BUFFER 377 select IIO_TRIGGERED_BUFFER 378 help 379 Say yes here to build support for Cosmic Circuits 10001 ADC. 380 381 This driver can also be built as a module. If so, the module will be 382 called cc10001_adc. 383 384 config CPCAP_ADC 385 tristate "Motorola CPCAP PMIC ADC driver" 386 depends on MFD_CPCAP 387 select IIO_BUFFER 388 select IIO_TRIGGERED_BUFFER 389 help 390 Say yes here to build support for Motorola CPCAP PMIC ADC. 391 392 This driver can also be built as a module. If so, the module will be 393 called cpcap-adc. 394 395 config DA9150_GPADC 396 tristate "Dialog DA9150 GPADC driver support" 397 depends on MFD_DA9150 398 help 399 Say yes here to build support for Dialog DA9150 GPADC. 400 401 This driver can also be built as a module. If chosen, the module name 402 will be da9150-gpadc. 403 404 To compile this driver as a module, choose M here: the module will be 405 called berlin2-adc. 406 407 config DLN2_ADC 408 tristate "Diolan DLN-2 ADC driver support" 409 depends on MFD_DLN2 410 select IIO_BUFFER 411 select IIO_TRIGGERED_BUFFER 412 help 413 Say yes here to build support for Diolan DLN-2 ADC. 414 415 This driver can also be built as a module. If so, the module will be 416 called adc_dln2. 417 418 config ENVELOPE_DETECTOR 419 tristate "Envelope detector using a DAC and a comparator" 420 depends on OF 421 help 422 Say yes here to build support for an envelope detector using a DAC 423 and a comparator. 424 425 To compile this driver as a module, choose M here: the module will be 426 called envelope-detector. 427 428 config EP93XX_ADC 429 tristate "Cirrus Logic EP93XX ADC driver" 430 depends on ARCH_EP93XX 431 help 432 Driver for the ADC module on the EP93XX series of SoC from Cirrus Logic. 433 It's recommended to switch on CONFIG_HIGH_RES_TIMERS option, in this 434 case driver will reduce its CPU usage by 90% in some use cases. 435 436 To compile this driver as a module, choose M here: the module will be 437 called ep93xx_adc. 438 439 config EXYNOS_ADC 440 tristate "Exynos ADC driver support" 441 depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210 || (OF && COMPILE_TEST) 442 depends on HAS_IOMEM 443 help 444 Driver for the ADC block found in the Samsung S3C (S3C2410, S3C2416, 445 S3C2440, S3C2443, S3C6410), S5Pv210 and Exynos SoCs. 446 Choose Y here only if you build for such Samsung SoC. 447 448 To compile this driver as a module, choose M here: the module will be 449 called exynos_adc. 450 451 config MXS_LRADC_ADC 452 tristate "Freescale i.MX23/i.MX28 LRADC ADC" 453 depends on MFD_MXS_LRADC 454 select IIO_BUFFER 455 select IIO_TRIGGERED_BUFFER 456 help 457 Say yes here to build support for the ADC functions of the 458 i.MX23/i.MX28 LRADC. This includes general-purpose ADC readings, 459 battery voltage measurement, and die temperature measurement. 460 461 This driver can also be built as a module. If so, the module will be 462 called mxs-lradc-adc. 463 464 config FSL_MX25_ADC 465 tristate "Freescale MX25 ADC driver" 466 depends on MFD_MX25_TSADC 467 help 468 Generic Conversion Queue driver used for general purpose ADC in the 469 MX25. This driver supports single measurements using the MX25 ADC. 470 471 config HI8435 472 tristate "Holt Integrated Circuits HI-8435 threshold detector" 473 select IIO_TRIGGERED_EVENT 474 depends on SPI 475 help 476 If you say yes here you get support for Holt Integrated Circuits 477 HI-8435 chip. 478 479 This driver can also be built as a module. If so, the module will be 480 called hi8435. 481 482 config HX711 483 tristate "AVIA HX711 ADC for weight cells" 484 depends on GPIOLIB 485 select IIO_BUFFER 486 select IIO_TRIGGERED_BUFFER 487 help 488 If you say yes here you get support for AVIA HX711 ADC which is used 489 for weigh cells 490 491 This driver uses two GPIOs, one acts as the clock and controls the 492 channel selection and gain, the other one is used for the measurement 493 data 494 495 Currently the raw value is read from the chip and delivered. 496 To get an actual weight one needs to subtract the 497 zero offset and multiply by a scale factor. 498 This should be done in userspace. 499 500 This driver can also be built as a module. If so, the module will be 501 called hx711. 502 503 config INA2XX_ADC 504 tristate "Texas Instruments INA2xx Power Monitors IIO driver" 505 depends on I2C && !SENSORS_INA2XX 506 select REGMAP_I2C 507 select IIO_BUFFER 508 select IIO_KFIFO_BUF 509 help 510 Say yes here to build support for TI INA2xx family of Power Monitors. 511 This driver is mutually exclusive with the HWMON version. 512 513 config INGENIC_ADC 514 tristate "Ingenic JZ47xx SoCs ADC driver" 515 depends on MIPS || COMPILE_TEST 516 select IIO_BUFFER 517 help 518 Say yes here to build support for the Ingenic JZ47xx SoCs ADC unit. 519 520 This driver can also be built as a module. If so, the module will be 521 called ingenic_adc. 522 523 config INTEL_MRFLD_ADC 524 tristate "Intel Merrifield Basin Cove ADC driver" 525 depends on INTEL_SOC_PMIC_MRFLD 526 help 527 Say yes here to have support for Basin Cove power management IC (PMIC) ADC 528 device. Depending on platform configuration, this general purpose ADC can 529 be used for sampling sensors such as thermal resistors. 530 531 To compile this driver as a module, choose M here: the module will be 532 called intel_mrfld_adc. 533 534 config IMX7D_ADC 535 tristate "Freescale IMX7D ADC driver" 536 depends on ARCH_MXC || COMPILE_TEST 537 depends on HAS_IOMEM 538 help 539 Say yes here to build support for IMX7D ADC. 540 541 This driver can also be built as a module. If so, the module will be 542 called imx7d_adc. 543 544 config IMX8QXP_ADC 545 tristate "NXP IMX8QXP ADC driver" 546 depends on ARCH_MXC || COMPILE_TEST 547 depends on HAS_IOMEM 548 help 549 Say yes here to build support for IMX8QXP ADC. 550 551 This driver can also be built as a module. If so, the module will be 552 called imx8qxp-adc. 553 554 config LP8788_ADC 555 tristate "LP8788 ADC driver" 556 depends on MFD_LP8788 557 help 558 Say yes here to build support for TI LP8788 ADC. 559 560 To compile this driver as a module, choose M here: the module will be 561 called lp8788_adc. 562 563 config LPC18XX_ADC 564 tristate "NXP LPC18xx ADC driver" 565 depends on ARCH_LPC18XX || COMPILE_TEST 566 depends on OF && HAS_IOMEM 567 help 568 Say yes here to build support for NXP LPC18XX ADC. 569 570 To compile this driver as a module, choose M here: the module will be 571 called lpc18xx_adc. 572 573 config LPC32XX_ADC 574 tristate "NXP LPC32XX ADC" 575 depends on ARCH_LPC32XX || COMPILE_TEST 576 depends on HAS_IOMEM 577 help 578 Say yes here to build support for the integrated ADC inside the 579 LPC32XX SoC. Note that this feature uses the same hardware as the 580 touchscreen driver, so you should either select only one of the two 581 drivers (lpc32xx_adc or lpc32xx_ts) or, in the OpenFirmware case, 582 activate only one via device tree selection. Provides direct access 583 via sysfs. 584 585 config LTC2471 586 tristate "Linear Technology LTC2471 and LTC2473 ADC driver" 587 depends on I2C 588 help 589 Say yes here to build support for Linear Technology LTC2471 and 590 LTC2473 16-bit I2C ADC. 591 592 This driver can also be built as a module. If so, the module will 593 be called ltc2471. 594 595 config LTC2485 596 tristate "Linear Technology LTC2485 ADC driver" 597 depends on I2C 598 help 599 Say yes here to build support for Linear Technology LTC2485 ADC. 600 601 To compile this driver as a module, choose M here: the module will be 602 called ltc2485. 603 604 config LTC2496 605 tristate "Linear Technology LTC2496 ADC driver" 606 depends on SPI 607 help 608 Say yes here to build support for Linear Technology LTC2496 609 16-Bit 8-/16-Channel Delta Sigma ADC. 610 611 To compile this driver as a module, choose M here: the module will be 612 called ltc2496. 613 614 config LTC2497 615 tristate "Linear Technology LTC2497 ADC driver" 616 depends on I2C 617 help 618 Say yes here to build support for Linear Technology LTC2497 619 16-Bit 8-/16-Channel Delta Sigma ADC. 620 621 To compile this driver as a module, choose M here: the module will be 622 called ltc2497. 623 624 config MAX1027 625 tristate "Maxim max1027 ADC driver" 626 depends on SPI 627 select IIO_BUFFER 628 select IIO_TRIGGERED_BUFFER 629 help 630 Say yes here to build support for Maxim SPI {10,12}-bit ADC models: 631 max1027, max1029, max1031, max1227, max1229 and max1231. 632 633 To compile this driver as a module, choose M here: the module will be 634 called max1027. 635 636 config MAX11100 637 tristate "Maxim max11100 ADC driver" 638 depends on SPI_MASTER 639 help 640 Say yes here to build support for Maxim max11100 SPI ADC 641 642 To compile this driver as a module, choose M here: the module will be 643 called max11100. 644 645 config MAX1118 646 tristate "Maxim max1117/max1118/max1119 ADCs driver" 647 depends on SPI 648 select IIO_BUFFER 649 select IIO_TRIGGERED_BUFFER 650 help 651 Say yes here to build support for Maxim max1117/max1118/max1119 652 8-bit, dual-channel ADCs. 653 654 To compile this driver as a module, choose M here: the module will be 655 called max1118. 656 657 config MAX1241 658 tristate "Maxim max1241 ADC driver" 659 depends on SPI_MASTER 660 help 661 Say yes here to build support for Maxim max1241 12-bit, single-channel 662 ADC. 663 664 To compile this driver as a module, choose M here: the module will be 665 called max1241. 666 667 config MAX1363 668 tristate "Maxim max1363 ADC driver" 669 depends on I2C 670 select IIO_BUFFER 671 select IIO_TRIGGERED_BUFFER 672 help 673 Say yes here to build support for many Maxim i2c analog to digital 674 converters (ADC). (max1361, max1362, max1363, max1364, max1036, 675 max1037, max1038, max1039, max1136, max1136, max1137, max1138, 676 max1139, max1236, max1237, max11238, max1239, max11600, max11601, 677 max11602, max11603, max11604, max11605, max11606, max11607, 678 max11608, max11609, max11610, max11611, max11612, max11613, 679 max11614, max11615, max11616, max11617, max11644, max11645, 680 max11646, max11647) Provides direct access via sysfs and buffered 681 data via the iio dev interface. 682 683 To compile this driver as a module, choose M here: the module will be 684 called max1363. 685 686 config MAX597X_IIO 687 tristate "Maxim 597x power switch and monitor" 688 depends on I2C 689 depends on OF 690 depends MFD_MAX597X > 691 help 692 This driver exposes Maxim 5970/5978 voltage/current monitoring 693 interface using iio framework. 694 -- 0-DAY CI Kernel Test Service https://01.org/lkp ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 5/5] leds: max597x: Add support for max597x 2022-07-07 13:41 [PATCH v2 0/5] mfd: max597x: Add support for max597x Naresh Solanki ` (3 preceding siblings ...) 2022-07-07 13:41 ` [PATCH v2 4/5] iio: max597x: Add support for max597x Naresh Solanki @ 2022-07-07 13:41 ` Naresh Solanki 4 siblings, 0 replies; 9+ messages in thread From: Naresh Solanki @ 2022-07-07 13:41 UTC (permalink / raw) To: linux-kernel, Pavel Machek; +Cc: Patrick Rudolph, Naresh Solanki From: Patrick Rudolph <patrick.rudolph@9elements.com> max597x is hot swap controller with indication led support. This driver uses DT property to configure led during boot time & also provide the led control in sysfs. Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> --- drivers/leds/Kconfig | 10 +++ drivers/leds/Makefile | 1 + drivers/leds/leds-max597x.c | 130 ++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 drivers/leds/leds-max597x.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index a49979f41eee..64070cadac31 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -598,6 +598,16 @@ config LEDS_ADP5520 To compile this driver as a module, choose M here: the module will be called leds-adp5520. +config LEDS_MAX597X + tristate "Maxim 597x leds" + depends on I2C + depends on OF + depends on LEDS_CLASS + depends MFD_MAX597X + help + This driver controls a Maxim 5970/5978 indication led via I2C bus. + The MAX5970/5978 is a smart switch with 4 indication leds + config LEDS_MC13783 tristate "LED Support for MC13XXX PMIC" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 4fd2f92cd198..c44b0e9559ab 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o +obj-$(CONFIG_LEDS_MAX597X) += leds-max597x.o obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o diff --git a/drivers/leds/leds-max597x.c b/drivers/leds/leds-max597x.c new file mode 100644 index 000000000000..645d6cdcfa34 --- /dev/null +++ b/drivers/leds/leds-max597x.c @@ -0,0 +1,130 @@ +// 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> + */ + +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/leds.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/i2c.h> +#include <linux/mfd/max597x.h> +#include <linux/regmap.h> +#include <linux/version.h> +#include <linux/platform_device.h> + +struct max597x_led { + struct regmap *regmap; + struct led_classdev led; + unsigned int index; +}; + +static int max597x_led_set_brightness(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct max597x_led *led = cdev->driver_data; + int ret; + + if (!led || !led->regmap) + return -1; + + ret = regmap_update_bits(led->regmap, MAX5970_REG_LED_FLASH, + 1 << led->index, ~brightness << led->index); + if (ret < 0) + dev_err(cdev->dev, "failed to set brightness %d\n", ret); + return ret; +} + +static int max597x_led(struct max597x_data *max597x, struct device_node *nc, u32 reg) +{ + struct max597x_led *led; + const char *state; + int ret = 0; + + led = devm_kzalloc(max597x->dev, sizeof(struct max597x_led), + GFP_KERNEL); + if (!led) + return -ENOMEM; + + if (of_property_read_string(nc, "label", &led->led.name)) + led->led.name = nc->name; + + led->led.max_brightness = 1; + led->led.brightness_set_blocking = max597x_led_set_brightness; + led->led.default_trigger = "none"; + led->index = reg; + led->regmap = max597x->regmap; + ret = led_classdev_register(max597x->dev, &led->led); + if (ret) { + dev_err(max597x->dev, "Error in initializing led %s", led->led.name); + devm_kfree(max597x->dev, led); + return ret; + } + led->led.driver_data = led; + led->led.dev = max597x->dev; + if (!of_property_read_string(nc, "default-state", &state)) { + if (!strcmp(state, "on")) { + led->led.brightness = 1; + led_set_brightness(&led->led, led->led.brightness); + } + } + return 0; +} + +static int max597x_led_probe(struct platform_device *pdev) +{ + + + struct max597x_data *max597x = dev_get_drvdata(pdev->dev.parent); + struct device_node *np = dev_of_node(pdev->dev.parent); + struct device_node *led_node; + struct device_node *child; + int ret = 0; + + + led_node = of_get_child_by_name(np, "leds"); + if (!led_node) + return -ENODEV; + + for_each_available_child_of_node(led_node, child) { + u32 reg; + + if (of_property_read_u32(child, "reg", ®)) + continue; + + if (reg >= MAX597X_NUM_LEDS) { + dev_err(max597x->dev, "invalid LED (%u >= %d)\n", reg, + MAX597X_NUM_LEDS); + continue; + } + + ret = max597x_led(max597x, child, reg); + if (ret < 0) { + of_node_put(child); + return ret; + } + } + + return ret; +} + +static struct platform_driver max597x_led_driver = { + .driver = { + .name = "max597x-led", + }, + .probe = max597x_led_probe, +}; + +module_platform_driver(max597x_led_driver); + + +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); +MODULE_DESCRIPTION("MAX5970_hot-swap controller driver"); +MODULE_LICENSE("GPL v2"); -- 2.35.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2022-08-08 13:55 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-07-07 13:41 [PATCH v2 0/5] mfd: max597x: Add support for max597x Naresh Solanki 2022-07-07 13:41 ` [PATCH v2 1/5] dt-bindings: mfd: Add bindings for MAX5970 and MAX5978 Naresh Solanki 2022-07-07 13:41 ` [PATCH v2 2/5] mfd: max597x: Add support " Naresh Solanki 2022-08-08 13:55 ` Lee Jones 2022-07-07 13:41 ` [PATCH v2 3/5] regulator: max597x: Add support for max597x regulator Naresh Solanki 2022-07-07 13:43 ` Mark Brown 2022-07-07 13:41 ` [PATCH v2 4/5] iio: max597x: Add support for max597x Naresh Solanki 2022-07-07 14:38 ` kernel test robot 2022-07-07 13:41 ` [PATCH v2 5/5] leds: " Naresh Solanki
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox