linux/drivers/mfd/simple-mfd-i2c.c
Patrick Rudolph 0742c2a633 mfd: max597x: Add support for MAX5970 and MAX5978
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

...
Changes in V12:
- Use simple_mfd_i2c driver and remove previous implementation.
- Remove newline
- Use _MFD_MAX597X_H in header file
- Successfull build need following patch from regulator:
https://lore.kernel.org/r/20230216075302.68935-1-Naresh.Solanki@9elements.com
https://lore.kernel.org/r/20230210163225.1208035-1-Naresh.Solanki@9elements.com

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>
Signed-off-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20230307121246.127425-2-Naresh.Solanki@9elements.com
2023-04-26 11:40:29 +01:00

107 lines
3 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Simple MFD - I2C
*
* Author(s):
* Michael Walle <michael@walle.cc>
* Lee Jones <lee.jones@linaro.org>
*
* This driver creates a single register map with the intention for it to be
* shared by all sub-devices. Children can use their parent's device structure
* (dev.parent) in order to reference it.
*
* Once the register map has been successfully initialised, any sub-devices
* represented by child nodes in Device Tree or via the MFD cells in this file
* will be subsequently registered.
*/
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
#include "simple-mfd-i2c.h"
static const struct regmap_config regmap_config_8r_8v = {
.reg_bits = 8,
.val_bits = 8,
};
static int simple_mfd_i2c_probe(struct i2c_client *i2c)
{
const struct simple_mfd_data *simple_mfd_data;
const struct regmap_config *regmap_config;
struct regmap *regmap;
int ret;
simple_mfd_data = device_get_match_data(&i2c->dev);
/* If no regmap_config is specified, use the default 8reg and 8val bits */
if (!simple_mfd_data || !simple_mfd_data->regmap_config)
regmap_config = &regmap_config_8r_8v;
else
regmap_config = simple_mfd_data->regmap_config;
regmap = devm_regmap_init_i2c(i2c, regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
/* If no MFD cells are specified, register using the DT child nodes instead */
if (!simple_mfd_data || !simple_mfd_data->mfd_cell)
return devm_of_platform_populate(&i2c->dev);
ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
simple_mfd_data->mfd_cell,
simple_mfd_data->mfd_cell_size,
NULL, 0, NULL);
if (ret)
dev_err(&i2c->dev, "Failed to add child devices\n");
return ret;
}
static const struct mfd_cell sy7636a_cells[] = {
{ .name = "sy7636a-regulator", },
{ .name = "sy7636a-temperature", },
};
static const struct simple_mfd_data silergy_sy7636a = {
.mfd_cell = sy7636a_cells,
.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);
static struct i2c_driver simple_mfd_i2c_driver = {
.probe_new = simple_mfd_i2c_probe,
.driver = {
.name = "simple-mfd-i2c",
.of_match_table = simple_mfd_i2c_of_match,
},
};
module_i2c_driver(simple_mfd_i2c_driver);
MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
MODULE_DESCRIPTION("Simple MFD - I2C driver");
MODULE_LICENSE("GPL v2");