diff mbox series

[v2,8/8] mfd: max77658: Add ADI MAX77643/54/58/59 MFD Support

Message ID 20230322055628.4441-9-Zeynep.Arslanbenzer@analog.com
State New
Headers show
Series Add MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support | expand

Commit Message

Arslanbenzer, Zeynep March 22, 2023, 5:56 a.m. UTC
MFD driver for MAX77643/MAX77654/MAX77658/MAX77659 to enable its sub
devices.

The MAX77643 is a multi-function devices. It includes
regulator.

The MAX77654 is a multi-function devices. It includes
regulator and charger.

The MAX77658 is a multi-function devices. It includes
regulator, charger and battery.

The MAX77659 is a multi-function devices. It includes
regulator and charger.

Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
---
 drivers/mfd/Kconfig          |  15 ++
 drivers/mfd/Makefile         |   1 +
 drivers/mfd/max77658.c       | 448 +++++++++++++++++++++++++++++++++++
 include/linux/mfd/max77658.h |  88 +++++++
 4 files changed, 552 insertions(+)
 create mode 100644 drivers/mfd/max77658.c
 create mode 100644 include/linux/mfd/max77658.h

Comments

Arslanbenzer, Zeynep April 17, 2023, 9:44 a.m. UTC | #1
>On Wed, 22 Mar 2023, Zeynep Arslanbenzer wrote:
>
>> MFD driver for MAX77643/MAX77654/MAX77658/MAX77659 to enable its sub
>
>Please drop all references to 'MFD'.
>
>What are these devices, really?  I suspect they are PMICs?

Hi Lee,

Thank you for your review. Yes, all devices covered by this patch are PMIC.

>
>> devices.
>>
>> The MAX77643 is a multi-function devices. It includes regulator.
>>
>> The MAX77654 is a multi-function devices. It includes regulator and 
>> charger.
>>
>> The MAX77658 is a multi-function devices. It includes regulator, 
>> charger and battery.
>>
>> The MAX77659 is a multi-function devices. It includes regulator and 
>> charger.
>>
>> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>>
>> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>>
>> ---
>>  drivers/mfd/Kconfig          |  15 ++
>>  drivers/mfd/Makefile         |   1 +
>>  drivers/mfd/max77658.c       | 448 +++++++++++++++++++++++++++++++++++
>>  include/linux/mfd/max77658.h |  88 +++++++
>>  4 files changed, 552 insertions(+)
>>  create mode 100644 drivers/mfd/max77658.c  create mode 100644 
>> include/linux/mfd/max77658.h
>>
>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 
>> 8b93856de432..7b4be7fb8662 100644
>> --- a/drivers/mfd/Kconfig
>> +++ b/drivers/mfd/Kconfig
>> @@ -821,6 +821,21 @@ config MFD_MAX77650
>>  	  the following functionalities of the device: GPIO, regulator,
>>  	  charger, LED, onkey.
>>
>> +config MFD_MAX77658
>> +	tristate "Analog Devices MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support"
>> +	depends on I2C
>> +	depends on OF
>> +	select MFD_CORE
>> +	select REGMAP_I2C
>> +	select REGMAP_IRQ
>> +	help
>> +	  Say Y here to add support for Analog Devices
>> +	  MAX77643/MAX77654/MAX77658/MAX77659 Power Management IC.
>
>"MAX776xx series"?

I will update the patch to be compatible with the MAX776xx.

>
>> +	  This is the core multifunction
>
>Just "core driver" is fine.
>
>Odd place to line wrap?
>
>> +	  driver for interacting with the device. Additional drivers can be
>
>"can be"?  It's probably pretty useless if you don't, no?
>
>> +	  enabled in order to use the following functionalities of the device:
>> +	  regulator, charger.
>
>"... in order to use the regular and charger functionality of the device".
>
>>  config MFD_MAX77686
>>  	tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
>>  	depends on I2C
>> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 
>> 7ed3ef4a698c..f52aff45878f 100644
>> --- a/drivers/mfd/Makefile
>> +++ b/drivers/mfd/Makefile
>> @@ -163,6 +163,7 @@ obj-$(CONFIG_MFD_DA9150)	+= da9150-core.o
>>  obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
>>  obj-$(CONFIG_MFD_MAX77620)	+= max77620.o
>>  obj-$(CONFIG_MFD_MAX77650)	+= max77650.o
>> +obj-$(CONFIG_MFD_MAX77658)	+= max77658.o
>>  obj-$(CONFIG_MFD_MAX77686)	+= max77686.o
>>  obj-$(CONFIG_MFD_MAX77693)	+= max77693.o
>>  obj-$(CONFIG_MFD_MAX77714)	+= max77714.o
>> diff --git a/drivers/mfd/max77658.c b/drivers/mfd/max77658.c new file 
>> mode 100644 index 000000000000..a1c6db48eb08
>> --- /dev/null
>> +++ b/drivers/mfd/max77658.c
>> @@ -0,0 +1,448 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (c) 2023 Analog Devices, Inc.
>> + * ADI driver for the MAX77643/MAX77654/MAX77658/MAX77659
>> + */
>
>No need to list every device.
>
>"MAX776xx series"?
>
>> +#include <linux/i2c.h>>
>> +#include <linux/mfd/core.h>>
>> +#include <linux/mfd/max77658.h>>
>> +#include <linux/mod_devicetable.h>>
>> +#include <linux/of_device.h>>
>> +#include <linux/regmap.h>>
>> +
>> +#define I2C_ADDR_FUEL_GAUGE (0x6C >>>> 1)
>> +
>> +static const struct regmap_config max77658_regmap_config = {
>> +	.reg_bits   = 8,
>> +	.val_bits   = 8,
>> +};
>> +
>> +static const struct regmap_config max77658_regmap_config_fg = {
>> +	.reg_bits   = 8,
>> +	.val_bits   = 16,
>> +	.cache_type = REGCACHE_NONE,
>> +	.val_format_endian = REGMAP_ENDIAN_LITTLE, };
>> +
>> +static const struct regmap_irq max77643_glbl0_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
>> +	{ .mask = MAX77643_BIT_INT_GLBL0_DOD0_R, }, };
>> +
>> +static const struct regmap_irq_chip max77643_glbl0_irq_chip = {
>> +	.name           = "max77643_glbl0",
>> +	.status_base    = MAX77658_REG_INT_GLBL0,
>> +	.mask_base      = MAX77643_REG_INTM_GLBL0,
>> +	.num_regs       = 1,
>> +	.irqs           = max77643_glbl0_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77643_glbl0_irqs),
>> +};
>> +
>> +static const struct regmap_irq max77658_glbl0_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_DOD1_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_DOD0_R, }, };
>> +
>> +static const struct regmap_irq_chip max77654_glbl0_irq_chip = {
>> +	.name           = "max77654_glbl0",
>> +	.status_base    = MAX77658_REG_INT_GLBL0,
>> +	.mask_base      = MAX77654_REG_INTM_GLBL0,
>> +	.num_regs       = 1,
>> +	.irqs           = max77658_glbl0_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77658_glbl0_irqs),
>> +};
>> +
>> +static const struct regmap_irq_chip max77658_glbl0_irq_chip = {
>> +	.name           = "max77658_glbl0",
>> +	.status_base    = MAX77658_REG_INT_GLBL0,
>> +	.mask_base      = MAX77658_REG_INTM_GLBL0,
>> +	.num_regs       = 1,
>> +	.irqs           = max77658_glbl0_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77658_glbl0_irqs),
>> +};
>> +
>> +static const struct regmap_irq max77659_glbl0_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL0_DOD0_R, }, };
>> +
>> +static const struct regmap_irq_chip max77659_glbl0_irq_chip = {
>> +	.name           = "max77659_glbl0",
>> +	.status_base    = MAX77658_REG_INT_GLBL0,
>> +	.mask_base      = MAX77654_REG_INTM_GLBL0,
>> +	.num_regs       = 1,
>> +	.irqs           = max77659_glbl0_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77659_glbl0_irqs),
>> +};
>> +
>> +static const struct regmap_irq max77643_glbl1_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_SBB0_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_SBB1_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_SBB2_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, }, };
>> +
>> +static const struct regmap_irq_chip max77643_glbl1_irq_chip = {
>> +	.name           = "max77643_glbl1",
>> +	.status_base    = MAX77658_REG_INT_GLBL1,
>> +	.mask_base      = MAX77643_REG_INTM_GLBL1,
>> +	.num_regs       = 1,
>> +	.irqs           = max77643_glbl1_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77643_glbl1_irqs),
>> +};
>> +
>> +static const struct regmap_irq max77654_glbl1_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
>> +	{ .mask = MAX77654_BIT_INT_GLBL1_GPI2_F, },
>> +	{ .mask = MAX77654_BIT_INT_GLBL1_GPI2_R, },
>> +	{ .mask = MAX77654_BIT_INT_GLBL1_SBB_TO, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_LDO1_F, }, };
>> +
>> +static const struct regmap_irq_chip max77654_glbl1_irq_chip = {
>> +	.name           = "max77654_glbl1",
>> +	.status_base    = MAX77658_REG_INT_GLBL1,
>> +	.mask_base      = MAX77654_REG_INTM_GLBL1,
>> +	.num_regs       = 1,
>> +	.irqs           = max77654_glbl1_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77654_glbl1_irqs),
>> +};
>> +
>> +static const struct regmap_irq max77658_glbl1_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_SBB0_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_SBB1_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_SBB2_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_LDO1_F, }, };
>> +
>> +static const struct regmap_irq_chip max77658_glbl1_irq_chip = {
>> +	.name           = "max77658_glbl1",
>> +	.status_base    = MAX77658_REG_INT_GLBL1,
>> +	.mask_base      = MAX77658_REG_INTM_GLBL1,
>> +	.num_regs       = 1,
>> +	.irqs           = max77658_glbl1_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77658_glbl1_irqs),
>> +};
>> +
>> +static const struct regmap_irq max77659_glbl1_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
>> +	{ .mask = MAX77659_BIT_INT_GLBL1_SBB_TO, },
>> +	{ .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, }, };
>> +
>> +static const struct regmap_irq_chip max77659_glbl1_irq_chip = {
>> +	.name           = "max77659_glbl1",
>> +	.status_base    = MAX77658_REG_INT_GLBL1,
>> +	.mask_base      = MAX77658_REG_INTM_GLBL1,
>> +	.num_regs       = 1,
>> +	.irqs           = max77659_glbl1_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77659_glbl1_irqs),
>> +};
>> +
>> +static const struct regmap_irq max77658_chg_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_THM, },
>> +	{ .mask = MAX77658_BIT_INT_CHG, },
>> +	{ .mask = MAX77658_BIT_INT_CHGIN, },
>> +	{ .mask = MAX77658_BIT_INT_TJ_REG, },
>> +	{ .mask = MAX77658_BIT_INT_CHGIN_CTRL, },
>> +	{ .mask = MAX77658_BIT_INT_SYS_CTRL, },
>> +	{ .mask = MAX77658_BIT_INT_SYS_CNFG, }, };
>> +
>> +static const struct regmap_irq_chip max77654_chg_irq_chip = {
>> +	.name           = "max77654_chg",
>> +	.status_base    = MAX77658_REG_INT_CHG,
>> +	.mask_base      = MAX77658_REG_INTM_CHG,
>> +	.num_regs       = 1,
>> +	.irqs           = max77658_chg_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77658_chg_irqs),
>> +};
>> +
>> +static const struct regmap_irq_chip max77658_chg_irq_chip = {
>> +	.name           = "max77658_chg",
>> +	.status_base    = MAX77658_REG_INT_CHG,
>> +	.mask_base      = MAX77658_REG_INTM_CHG,
>> +	.num_regs       = 1,
>> +	.irqs           = max77658_chg_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77658_chg_irqs),
>> +};
>> +
>> +static const struct regmap_irq max77659_chg_irqs[] = {
>> +	{ .mask = MAX77658_BIT_INT_THM, },
>> +	{ .mask = MAX77658_BIT_INT_CHG, },
>> +	{ .mask = MAX77658_BIT_INT_CHGIN, },
>> +	{ .mask = MAX77658_BIT_INT_TJ_REG, },
>> +	{ .mask = MAX776569_BIT_INT_SYS_CTRL, }, };
>> +
>> +static const struct regmap_irq_chip max77659_chg_irq_chip = {
>> +	.name           = "max77659_chg",
>> +	.status_base    = MAX77658_REG_INT_CHG,
>> +	.mask_base      = MAX77658_REG_INTM_CHG,
>> +	.num_regs       = 1,
>> +	.irqs           = max77659_chg_irqs,
>> +	.num_irqs       = ARRAY_SIZE(max77659_chg_irqs),
>> +};
>> +
>> +static const struct mfd_cell max77643_devs[] = {
>> +	MFD_CELL_OF("max77643-regulator", NULL, NULL, 0, 0,
>> +		    "adi,max77643-regulator"),
>> +};
>> +
>> +static const struct mfd_cell max77654_devs[] = {
>> +	MFD_CELL_OF("max77654-regulator", NULL, NULL, 0, 0,
>> +		    "adi,max77654-regulator"),
>> +	MFD_CELL_OF("max77654-charger", NULL, NULL, 0, 0,
>> +		    "adi,max77654-charger"),
>> +};
>> +
>> +static const struct mfd_cell max77658_devs[] = {
>> +	MFD_CELL_OF("max77658-regulator", NULL, NULL, 0, 0,
>> +		    "adi,max77658-regulator"),
>> +	MFD_CELL_OF("max77658-charger", NULL, NULL, 0, 0,
>> +		    "adi,max77658-charger"),
>> +	MFD_CELL_OF("max77658-battery", NULL, NULL, 0, 0,
>> +		    "adi,max77658-battery"),
>> +};
>> +
>> +static const struct mfd_cell max77659_devs[] = {
>> +	MFD_CELL_OF("max77659-regulator", NULL, NULL, 0, 0,
>> +		    "adi,max77659-regulator"),
>> +	MFD_CELL_OF("max77659-charger", NULL, NULL, 0, 0,
>> +		    "adi,max77659-charger"),
>> +};
>
>You can unwrap all of these, you have 100-chars to play with.

Based on other maintainers' reviews, I limited the number of characters per line to 80. 
Here is the link for the related review -> https://lore.kernel.org/lkml/9915e079-c6b5-a8f4-734e-f0325809efd0@linaro.org/
I can continue according to the joint decision.

>
>> +static const struct chip_info chip[] = {
>> +	[ID_MAX77643] = {
>> +		.id = ID_MAX77643,
>> +		.n_devs = ARRAY_SIZE(max77643_devs),
>> +		.devs = max77643_devs,
>> +	},
>> +	[ID_MAX77654] = {
>> +		.id = ID_MAX77654,
>> +		.n_devs = ARRAY_SIZE(max77654_devs),
>> +		.devs = max77654_devs,
>> +	},
>> +	[ID_MAX77658] = {
>> +		.id = ID_MAX77658,
>> +		.n_devs = ARRAY_SIZE(max77658_devs),
>> +		.devs = max77658_devs,
>> +	},
>> +	[ID_MAX77659] = {
>> +		.id = ID_MAX77659,
>> +		.n_devs = ARRAY_SIZE(max77659_devs),
>> +		.devs = max77659_devs,
>> +	},
>> +};
>> +
>> +static int max77658_pmic_irq_init(struct device *dev) {
>> +	const struct regmap_irq_chip *glbl0_chip, *glbl1_chip, *chg_chip;
>> +	struct max77658_dev *max77658 = dev_get_drvdata(dev);
>> +	int ret, i;
>> +
>> +	switch (max77658->>chip->>id) {
>> +	case ID_MAX77643:
>> +		glbl0_chip = &max77643_glbl0_irq_chip;
>> +		glbl1_chip = &max77643_glbl1_irq_chip;
>> +		break;
>> +	case ID_MAX77654:
>> +		glbl0_chip = &max77654_glbl0_irq_chip;
>> +		glbl1_chip = &max77654_glbl1_irq_chip;
>> +		chg_chip = &max77654_chg_irq_chip;
>> +		break;
>> +	case ID_MAX77658:
>> +		glbl0_chip = &max77658_glbl0_irq_chip;
>> +		glbl1_chip = &max77658_glbl1_irq_chip;
>> +		chg_chip = &max77658_chg_irq_chip;
>> +		break;
>> +	case ID_MAX77659:
>> +		glbl0_chip = &max77659_glbl0_irq_chip;
>> +		glbl1_chip = &max77659_glbl1_irq_chip;
>> +		chg_chip = &max77659_chg_irq_chip;
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +
>> +	for (i = 0; i < glbl0_chip->>num_regs; i++) {
>> +		ret = regmap_update_bits(max77658->>regmap,
>> +					 glbl0_chip->>mask_base,
>> +					 (1 << glbl0_chip->>irqs[i].reg_offset),
>> +					 1);
>> +		if (ret)
>> +			return dev_err_probe(dev, ret,
>> +					     "Unable to write Global0 Interrupt Masking register\n");
>> +	}
>> +
>> +	for (i = 0; i < glbl1_chip->>num_regs; i++) {
>> +		ret = regmap_update_bits(max77658->>regmap,
>> +					 glbl1_chip->>mask_base,
>> +					 (1 << glbl1_chip->>irqs[i].reg_offset),
>> +					 1);
>> +		if (ret)
>> +			return dev_err_probe(dev, ret,
>> +					     "Unable to write Global1 Interrupt Masking register\n");
>> +	}
>> +
>> +	if (max77658->>chip->>id != ID_MAX77643) {
>> +		for (i = 0; i < chg_chip->>num_regs; i++) {
>> +			ret = regmap_update_bits(max77658->>regmap,
>> +						 chg_chip->>mask_base,
>> +						 (1 <<
>> +						 chg_chip->>irqs[i].reg_offset),
>> +						 1);
>> +			if (ret)
>> +				return dev_err_probe(dev, ret,
>> +						     "Unable to write Charger Interrupt Masking register\n");
>> +		}
>> +
>> +		ret = devm_regmap_add_irq_chip(dev, max77658->>regmap,
>> +					       max77658->>irq,
>> +					       IRQF_ONESHOT | IRQF_SHARED, 0,
>> +					       chg_chip, &max77658->>irqc_chg);
>> +		if (ret)
>> +			return dev_err_probe(dev, ret,
>> +					     "Failed to add charger IRQ chip\n");
>> +	}
>> +
>> +	ret = devm_regmap_add_irq_chip(dev, max77658->>regmap, max77658->>irq,
>> +				       IRQF_ONESHOT | IRQF_SHARED, 0,
>> +				       glbl0_chip, &max77658->>irqc_glbl0);
>> +	if (ret)
>> +		return dev_err_probe(dev, ret,
>> +				     "Failed to add global0 IRQ chip\n");
>> +
>> +	return devm_regmap_add_irq_chip(dev, max77658->>regmap, max77658->>irq,
>> +					IRQF_ONESHOT | IRQF_SHARED, 0,
>> +					glbl1_chip, &max77658->>irqc_glbl1);
>
>This function is hectic.
>
>What exactly are you doing here?

I mask all interrupts of global0, global1, and charger inside the loops. 

>
>> +}
>> +
>> +static int max77658_pmic_setup(struct device *dev) {
>> +	struct max77658_dev *max77658 = dev_get_drvdata(dev);
>> +	int ret;
>> +
>> +	ret = max77658_pmic_irq_init(max77658->>dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
>> +				   max77658->>chip->>devs, max77658->>chip->>n_devs,
>> +				   NULL, 0, NULL);
>> +
>
>These are usually placed in probe.
>
>> +	if (ret)
>> +		return dev_err_probe(dev, ret, "Failed to add sub-devices\n");
>> +
>> +	ret = device_init_wakeup(dev, true);
>> +	if (ret)
>> +		return dev_err_probe(dev, ret, "Unable to init wakeup\n");
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct i2c_device_id max77658_i2c_id[];
>
>What on earth is this?  A struct forward declaration?
>
>If you need this, just move the original code block to here.
>
>> +static int max77658_i2c_probe(struct i2c_client *client) {
>> +	struct max77658_dev *max77658;
>> +	struct i2c_client *fuel;
>> +
>> +	max77658 = devm_kzalloc(&client->>dev, sizeof(*max77658), GFP_KERNEL);
>> +	if (!max77658)
>> +		return -ENOMEM;
>> +
>> +	i2c_set_clientdata(client, max77658);
>> +	max77658->>dev = &client->>dev;
>
>How do you fetch back max77658?
>
>Don't you need access to the device structs?
>
>If so, you already have a reference, no?
>
>> +	max77658->>irq = client->>irq;
>> +
>> +	if (max77658->>dev->>of_node)
>> +		max77658->>chip  = of_device_get_match_data(max77658->>dev);
>> +	else
>> +		max77658->>chip  = (struct chip_info *)
>
>Cast from void * shouldn't be required.
>
>> +					i2c_match_id(max77658_i2c_id,
>> +						     client)->>driver_data;
>
>100-chars everywhere.
>
>> +	if (!max77658->>chip)
>> +		return -EINVAL;
>> +
>> +	max77658->>regmap = devm_regmap_init_i2c(client,
>> +						&max77658_regmap_config);
>> +	if (IS_ERR(max77658->>regmap))
>> +		return dev_err_probe(max77658->>dev, PTR_ERR(max77658->>regmap),
>> +				     "Failed to allocate register map\n");
>
>s/allocate/initialise/
>
>"regmap" is fine.
>
>> +	fuel = i2c_new_dummy_device(client->>adapter, I2C_ADDR_FUEL_GAUGE);
>> +	if (IS_ERR(fuel))
>> +		return dev_err_probe(max77658->>dev, PTR_ERR(fuel),
>> +				     "failed add i2c device[0x%Xh]\n",
>
>"Failed to create I2C device"
>
>> +				      I2C_ADDR_FUEL_GAUGE);
>> +
>> +	i2c_set_clientdata(fuel, max77658);
>> +
>> +	max77658->>regmap_fg = devm_regmap_init_i2c(fuel,
>> +						   &max77658_regmap_config_fg);
>> +	if (IS_ERR(max77658->>regmap_fg))
>> +		return dev_err_probe(max77658->>dev,
>> +				     PTR_ERR(max77658->>regmap_fg),
>> +				     "failed to initialize i2c device[0x%Xh]\n",
>
>"Failed"
>
>"I2C"
>
>> +				     I2C_ADDR_FUEL_GAUGE);
>> +
>> +	return max77658_pmic_setup(max77658->>dev);
>> +}
>> +
>> +static const struct of_device_id max77658_of_id[] = {
>> +	{ .compatible = "adi,max77643", .data = &chip[ID_MAX77643] },
>> +	{ .compatible = "adi,max77654", .data = &chip[ID_MAX77654] },
>> +	{ .compatible = "adi,max77658", .data = &chip[ID_MAX77658] },
>> +	{ .compatible = "adi,max77659", .data = &chip[ID_MAX77659] },
>> +	{ /* sentinel */ }
>> +};
>> +MODULE_DEVICE_TABLE(of, max77658_of_id);
>> +
>> +static const struct i2c_device_id max77658_i2c_id[] = {
>> +	{ "max77643", (kernel_ulong_t)&chip[ID_MAX77643] },
>> +	{ "max77654", (kernel_ulong_t)&chip[ID_MAX77654] },
>> +	{ "max77658", (kernel_ulong_t)&chip[ID_MAX77658] },
>> +	{ "max77659", (kernel_ulong_t)&chip[ID_MAX77659] },
>> +	{ /* sentinel */ }
>> +};
>> +MODULE_DEVICE_TABLE(i2c, max77658_i2c_id);
>
>Please don't pass MFD data through the DT platform initialisation API.
>
>Pass the Chip ID and match in C-code.
>
>> +static struct i2c_driver max77658_driver = {
>> +	.driver = {
>> +		.name = "max77658",
>> +		.of_match_table = max77658_of_id,
>> +	},
>> +	.probe_new = max77658_i2c_probe,
>> +	.id_table = max77658_i2c_id,
>> +};
>> +module_i2c_driver(max77658_driver);
>> +
>> +MODULE_DESCRIPTION("MAX77658 MFD Driver"); 
>> +MODULE_AUTHOR("Nurettin.Bolucu@analog.com, 
>> +Zeynep.Arslanbenzer@analog.com"); MODULE_LICENSE("GPL");
>> diff --git a/include/linux/mfd/max77658.h 
>> b/include/linux/mfd/max77658.h new file mode 100644 index 
>> 000000000000..471a8474513e
>> --- /dev/null
>> +++ b/include/linux/mfd/max77658.h
>> @@ -0,0 +1,88 @@
>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>> +
>> +#ifndef __MAX77658_MFD_H__
>> +#define __MAX77658_MFD_H__
>> +
>> +#include <linux/bits.h>>
>> +#include <linux/types.h>>
>> +
>> +#define MAX77658_REG_INT_GLBL0	0x00
>> +#define MAX77658_REG_INT_CHG	0x01
>> +#define MAX77658_REG_INT_GLBL1	0x04
>> +#define MAX77658_REG_INTM_CHG	0x07
>> +#define MAX77658_REG_INTM_GLBL0	0x08
>> +#define MAX77658_REG_INTM_GLBL1	0x09
>> +
>> +#define MAX77654_REG_INTM_GLBL1	0x08
>> +#define MAX77654_REG_INTM_GLBL0	0x09
>> +
>> +#define MAX77643_REG_INT_GLBL1	0x01
>> +#define MAX77643_REG_INTM_GLBL0	0x04
>> +#define MAX77643_REG_INTM_GLBL1	0x05
>> +
>> +#define MAX77658_BIT_INT_GLBL0_GPIO0_F	BIT(0)
>> +#define MAX77658_BIT_INT_GLBL0_GPIO0_R	BIT(1)
>> +#define MAX77658_BIT_INT_GLBL0_EN_F	BIT(2)
>> +#define MAX77658_BIT_INT_GLBL0_EN_R	BIT(3)
>> +#define MAX77658_BIT_INT_GLBL0_TJAL1_R	BIT(4)
>> +#define MAX77658_BIT_INT_GLBL0_TJAL2_R	BIT(5)
>> +#define MAX77658_BIT_INT_GLBL0_DOD1_R	BIT(6)
>> +#define MAX77658_BIT_INT_GLBL0_DOD0_R	BIT(7)
>> +
>> +#define MAX77643_BIT_INT_GLBL0_DOD0_R	BIT(6)
>> +
>> +#define MAX77658_BIT_INT_GLBL1_GPI1_F	BIT(0)
>> +#define MAX77658_BIT_INT_GLBL1_GPI1_R	BIT(1)
>> +#define MAX77658_BIT_INT_GLBL1_SBB0_F	BIT(2)
>> +#define MAX77658_BIT_INT_GLBL1_SBB1_F	BIT(3)
>> +#define MAX77658_BIT_INT_GLBL1_SBB2_F	BIT(4)
>> +#define MAX77658_BIT_INT_GLBL1_LDO0_F	BIT(5)
>> +#define MAX77658_BIT_INT_GLBL1_LDO1_F	BIT(6)
>> +
>> +#define MAX77659_BIT_INT_GLBL1_SBB_TO	BIT(4)
>> +
>> +#define MAX77654_BIT_INT_GLBL1_GPI2_F	BIT(2)
>> +#define MAX77654_BIT_INT_GLBL1_GPI2_R	BIT(3)
>> +#define MAX77654_BIT_INT_GLBL1_SBB_TO	BIT(4)
>> +
>> +#define MAX77658_BIT_INT_THM		BIT(0)
>> +#define MAX77658_BIT_INT_CHG		BIT(1)
>> +#define MAX77658_BIT_INT_CHGIN		BIT(2)
>> +#define MAX77658_BIT_INT_TJ_REG		BIT(3)
>> +#define MAX77658_BIT_INT_CHGIN_CTRL	BIT(4)
>> +#define MAX77658_BIT_INT_SYS_CTRL	BIT(5)
>> +#define MAX77658_BIT_INT_SYS_CNFG	BIT(6)
>> +
>> +#define MAX776569_BIT_INT_SYS_CTRL	BIT(4)
>> +
>> +enum max77658_ids {
>> +	ID_MAX77643,
>> +	ID_MAX77654,
>> +	ID_MAX77658,
>> +	ID_MAX77659
>> +};
>> +
>> +struct chip_info {
>> +	enum max77658_ids id;
>> +	int n_devs;
>> +	const struct mfd_cell *devs;
>> +};
>> +
>> +struct device;
>> +struct regmap;
>> +struct regmap_irq_chip_data;
>> +
>> +struct max77658_dev {
>> +	struct device *dev;
>> +	const struct chip_info *chip;
>> +
>> +	int irq;
>> +	struct regmap_irq_chip_data *irqc_glbl0;
>> +	struct regmap_irq_chip_data *irqc_glbl1;
>> +	struct regmap_irq_chip_data *irqc_chg;
>> +
>> +	struct regmap *regmap;
>> +	struct regmap *regmap_fg;
>> +};
>> +
>> +#endif /* __MAX77658_MFD_H__ */
>> --
>> 2.25.1
>>
>
>--
>Lee Jones [李琼斯]

Best regards,
Zeynep
Arslanbenzer, Zeynep April 23, 2023, 9:16 p.m. UTC | #2
On Thu, 30 Mar 2023, Lee Jones wrote:

>On Wed, 22 Mar 2023, Zeynep Arslanbenzer wrote:
>
>> MFD driver for MAX77643/MAX77654/MAX77658/MAX77659 to enable its sub
>
>Please drop all references to 'MFD'.
>
>What are these devices, really?  I suspect they are PMICs?
>
>> devices.
>>
>> The MAX77643 is a multi-function devices. It includes regulator.
>>
>> The MAX77654 is a multi-function devices. It includes regulator and 
>> charger.
>>
>> The MAX77658 is a multi-function devices. It includes regulator, 
>> charger and battery.
>>
>> The MAX77659 is a multi-function devices. It includes regulator and 
>> charger.
>>
>> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
>> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
>> ---
>>  drivers/mfd/Kconfig          |  15 ++
>>  drivers/mfd/Makefile         |   1 +
>>  drivers/mfd/max77658.c       | 448 +++++++++++++++++++++++++++++++++++
>>  include/linux/mfd/max77658.h |  88 +++++++
>>  4 files changed, 552 insertions(+)
>>  create mode 100644 drivers/mfd/max77658.c  create mode 100644 
>> include/linux/mfd/max77658.h
>>
>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 
>> 8b93856de432..7b4be7fb8662 100644
>> --- a/drivers/mfd/Kconfig
>> +++ b/drivers/mfd/Kconfig
>> @@ -821,6 +821,21 @@ config MFD_MAX77650
>>  	  the following functionalities of the device: GPIO, regulator,
>>  	  charger, LED, onkey.
>>
>> +config MFD_MAX77658
>> +	tristate "Analog Devices MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support"
>> +	depends on I2C
>> +	depends on OF
>> +	select MFD_CORE
>> +	select REGMAP_I2C
>> +	select REGMAP_IRQ
>> +	help
>> +	  Say Y here to add support for Analog Devices
>> +	  MAX77643/MAX77654/MAX77658/MAX77659 Power Management IC.
>
>"MAX776xx series"?

As I realized later, max77620, max77650, max77686, and max77693 drivers were merged to Linux before our patch. They are also PMIC devices and our patch does not cover them. Therefore, I think it would not be appropriate to use MAX776xx.

>
>> +	  This is the core multifunction
>
>Just "core driver" is fine.
>
>Odd place to line wrap?
>
>> +	  driver for interacting with the device. Additional drivers can be
>
>"can be"?  It's probably pretty useless if you don't, no?
>
>> +	  enabled in order to use the following functionalities of the device:
>> +	  regulator, charger.
>
>"... in order to use the regular and charger functionality of the device".
>
>>  config MFD_MAX77686
>>  	tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
>>  	depends on I2C
>> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 
>> 7ed3ef4a698c..f52aff45878f 100644
>> --- a/drivers/mfd/Makefile
>> +++ b/drivers/mfd/Makefile
>> @@ -163,6 +163,7 @@ obj-$(CONFIG_MFD_DA9150)	+= da9150-core.o
>>  obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
>>  obj-$(CONFIG_MFD_MAX77620)	+= max77620.o
>>  obj-$(CONFIG_MFD_MAX77650)	+= max77650.o
>> +obj-$(CONFIG_MFD_MAX77658)	+= max77658.o
>>  obj-$(CONFIG_MFD_MAX77686)	+= max77686.o
>>  obj-$(CONFIG_MFD_MAX77693)	+= max77693.o
>>  obj-$(CONFIG_MFD_MAX77714)	+= max77714.o
>> diff --git a/drivers/mfd/max77658.c b/drivers/mfd/max77658.c new file 
>> mode 100644 index 000000000000..a1c6db48eb08
>> --- /dev/null
>> +++ b/drivers/mfd/max77658.c
>> @@ -0,0 +1,448 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (c) 2023 Analog Devices, Inc.
>> + * ADI driver for the MAX77643/MAX77654/MAX77658/MAX77659
>> + */
>
>No need to list every device.
>
>"MAX776xx series"?
>

Best regards,
Zeynep
Arslanbenzer, Zeynep April 25, 2023, 10:03 p.m. UTC | #3
On Mon, 24 Apr 2023, Lee Jones wrote:
>
>On Sun, 23 Apr 2023, Arslanbenzer, Zeynep wrote:
>
>> On Thu, 30 Mar 2023, Lee Jones wrote:
>> 
>> >On Wed, 22 Mar 2023, Zeynep Arslanbenzer wrote:
>> >
>> >> MFD driver for MAX77643/MAX77654/MAX77658/MAX77659 to enable its 
>> >> sub
>> >
>> >Please drop all references to 'MFD'.
>> >
>> >What are these devices, really?  I suspect they are PMICs?
>> >
>> >> devices.
>> >>
>> >> The MAX77643 is a multi-function devices. It includes regulator.
>> >>
>> >> The MAX77654 is a multi-function devices. It includes regulator and 
>> >> charger.
>> >>
>> >> The MAX77658 is a multi-function devices. It includes regulator, 
>> >> charger and battery.
>> >>
>> >> The MAX77659 is a multi-function devices. It includes regulator and 
>> >> charger.
>> >>
>> >> Signed-off-by: Nurettin Bolucu <Nurettin.Bolucu@analog.com>
>> >> Signed-off-by: Zeynep Arslanbenzer <Zeynep.Arslanbenzer@analog.com>
>> >> ---
>> >>  drivers/mfd/Kconfig          |  15 ++
>> >>  drivers/mfd/Makefile         |   1 +
>> >>  drivers/mfd/max77658.c       | 448 +++++++++++++++++++++++++++++++++++
>> >>  include/linux/mfd/max77658.h |  88 +++++++
>> >>  4 files changed, 552 insertions(+)  create mode 100644 
>> >> drivers/mfd/max77658.c  create mode 100644 
>> >> include/linux/mfd/max77658.h
>> >>
>> >> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index
>> >> 8b93856de432..7b4be7fb8662 100644
>> >> --- a/drivers/mfd/Kconfig
>> >> +++ b/drivers/mfd/Kconfig
>> >> @@ -821,6 +821,21 @@ config MFD_MAX77650
>> >>  	  the following functionalities of the device: GPIO, regulator,
>> >>  	  charger, LED, onkey.
>> >>
>> >> +config MFD_MAX77658
>> >> +	tristate "Analog Devices MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support"
>> >> +	depends on I2C
>> >> +	depends on OF
>> >> +	select MFD_CORE
>> >> +	select REGMAP_I2C
>> >> +	select REGMAP_IRQ
>> >> +	help
>> >> +	  Say Y here to add support for Analog Devices
>> >> +	  MAX77643/MAX77654/MAX77658/MAX77659 Power Management IC.
>> >
>> >"MAX776xx series"?
>> 
>> As I realized later, max77620, max77650, max77686, and max77693 drivers were merged to Linux before our patch. They are also PMIC devices and our patch does not cover them. Therefore, I think it would not be appropriate to use MAX776xx.
>
>Perhaps you can come up with something a little more scalable then.
>
>What if you added support for another 10 devices?
>
For now, we have no plans to add any new device support to this driver. We named the driver max77658 because it has the most inclusive feature among the supported devices. We can shorten it to MAX77643/54/58/59 or just type max77658 in Kconfig and specify other supported devices in the device tree. Would one of these be a more suitable solution?

Best regards,
Zeynep
diff mbox series

Patch

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8b93856de432..7b4be7fb8662 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -821,6 +821,21 @@  config MFD_MAX77650
 	  the following functionalities of the device: GPIO, regulator,
 	  charger, LED, onkey.
 
+config MFD_MAX77658
+	tristate "Analog Devices MAX77643/MAX77654/MAX77658/MAX77659 PMIC Support"
+	depends on I2C
+	depends on OF
+	select MFD_CORE
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	help
+	  Say Y here to add support for Analog Devices
+	  MAX77643/MAX77654/MAX77658/MAX77659 Power Management IC.
+	  This is the core multifunction
+	  driver for interacting with the device. Additional drivers can be
+	  enabled in order to use the following functionalities of the device:
+	  regulator, charger.
+
 config MFD_MAX77686
 	tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
 	depends on I2C
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 7ed3ef4a698c..f52aff45878f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -163,6 +163,7 @@  obj-$(CONFIG_MFD_DA9150)	+= da9150-core.o
 obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
 obj-$(CONFIG_MFD_MAX77620)	+= max77620.o
 obj-$(CONFIG_MFD_MAX77650)	+= max77650.o
+obj-$(CONFIG_MFD_MAX77658)	+= max77658.o
 obj-$(CONFIG_MFD_MAX77686)	+= max77686.o
 obj-$(CONFIG_MFD_MAX77693)	+= max77693.o
 obj-$(CONFIG_MFD_MAX77714)	+= max77714.o
diff --git a/drivers/mfd/max77658.c b/drivers/mfd/max77658.c
new file mode 100644
index 000000000000..a1c6db48eb08
--- /dev/null
+++ b/drivers/mfd/max77658.c
@@ -0,0 +1,448 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Analog Devices, Inc.
+ * ADI driver for the MAX77643/MAX77654/MAX77658/MAX77659
+ */
+
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max77658.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#define I2C_ADDR_FUEL_GAUGE (0x6C >> 1)
+
+static const struct regmap_config max77658_regmap_config = {
+	.reg_bits   = 8,
+	.val_bits   = 8,
+};
+
+static const struct regmap_config max77658_regmap_config_fg = {
+	.reg_bits   = 8,
+	.val_bits   = 16,
+	.cache_type = REGCACHE_NONE,
+	.val_format_endian = REGMAP_ENDIAN_LITTLE,
+};
+
+static const struct regmap_irq max77643_glbl0_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
+	{ .mask = MAX77643_BIT_INT_GLBL0_DOD0_R, },
+};
+
+static const struct regmap_irq_chip max77643_glbl0_irq_chip = {
+	.name           = "max77643_glbl0",
+	.status_base    = MAX77658_REG_INT_GLBL0,
+	.mask_base      = MAX77643_REG_INTM_GLBL0,
+	.num_regs       = 1,
+	.irqs           = max77643_glbl0_irqs,
+	.num_irqs       = ARRAY_SIZE(max77643_glbl0_irqs),
+};
+
+static const struct regmap_irq max77658_glbl0_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_DOD1_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_DOD0_R, },
+};
+
+static const struct regmap_irq_chip max77654_glbl0_irq_chip = {
+	.name           = "max77654_glbl0",
+	.status_base    = MAX77658_REG_INT_GLBL0,
+	.mask_base      = MAX77654_REG_INTM_GLBL0,
+	.num_regs       = 1,
+	.irqs           = max77658_glbl0_irqs,
+	.num_irqs       = ARRAY_SIZE(max77658_glbl0_irqs),
+};
+
+static const struct regmap_irq_chip max77658_glbl0_irq_chip = {
+	.name           = "max77658_glbl0",
+	.status_base    = MAX77658_REG_INT_GLBL0,
+	.mask_base      = MAX77658_REG_INTM_GLBL0,
+	.num_regs       = 1,
+	.irqs           = max77658_glbl0_irqs,
+	.num_irqs       = ARRAY_SIZE(max77658_glbl0_irqs),
+};
+
+static const struct regmap_irq max77659_glbl0_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_GPIO0_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_EN_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_EN_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL1_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_TJAL2_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL0_DOD0_R, },
+};
+
+static const struct regmap_irq_chip max77659_glbl0_irq_chip = {
+	.name           = "max77659_glbl0",
+	.status_base    = MAX77658_REG_INT_GLBL0,
+	.mask_base      = MAX77654_REG_INTM_GLBL0,
+	.num_regs       = 1,
+	.irqs           = max77659_glbl0_irqs,
+	.num_irqs       = ARRAY_SIZE(max77659_glbl0_irqs),
+};
+
+static const struct regmap_irq max77643_glbl1_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_SBB0_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_SBB1_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_SBB2_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
+};
+
+static const struct regmap_irq_chip max77643_glbl1_irq_chip = {
+	.name           = "max77643_glbl1",
+	.status_base    = MAX77658_REG_INT_GLBL1,
+	.mask_base      = MAX77643_REG_INTM_GLBL1,
+	.num_regs       = 1,
+	.irqs           = max77643_glbl1_irqs,
+	.num_irqs       = ARRAY_SIZE(max77643_glbl1_irqs),
+};
+
+static const struct regmap_irq max77654_glbl1_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
+	{ .mask = MAX77654_BIT_INT_GLBL1_GPI2_F, },
+	{ .mask = MAX77654_BIT_INT_GLBL1_GPI2_R, },
+	{ .mask = MAX77654_BIT_INT_GLBL1_SBB_TO, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_LDO1_F, },
+};
+
+static const struct regmap_irq_chip max77654_glbl1_irq_chip = {
+	.name           = "max77654_glbl1",
+	.status_base    = MAX77658_REG_INT_GLBL1,
+	.mask_base      = MAX77654_REG_INTM_GLBL1,
+	.num_regs       = 1,
+	.irqs           = max77654_glbl1_irqs,
+	.num_irqs       = ARRAY_SIZE(max77654_glbl1_irqs),
+};
+
+static const struct regmap_irq max77658_glbl1_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_SBB0_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_SBB1_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_SBB2_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_LDO1_F, },
+};
+
+static const struct regmap_irq_chip max77658_glbl1_irq_chip = {
+	.name           = "max77658_glbl1",
+	.status_base    = MAX77658_REG_INT_GLBL1,
+	.mask_base      = MAX77658_REG_INTM_GLBL1,
+	.num_regs       = 1,
+	.irqs           = max77658_glbl1_irqs,
+	.num_irqs       = ARRAY_SIZE(max77658_glbl1_irqs),
+};
+
+static const struct regmap_irq max77659_glbl1_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_F, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_GPI1_R, },
+	{ .mask = MAX77659_BIT_INT_GLBL1_SBB_TO, },
+	{ .mask = MAX77658_BIT_INT_GLBL1_LDO0_F, },
+};
+
+static const struct regmap_irq_chip max77659_glbl1_irq_chip = {
+	.name           = "max77659_glbl1",
+	.status_base    = MAX77658_REG_INT_GLBL1,
+	.mask_base      = MAX77658_REG_INTM_GLBL1,
+	.num_regs       = 1,
+	.irqs           = max77659_glbl1_irqs,
+	.num_irqs       = ARRAY_SIZE(max77659_glbl1_irqs),
+};
+
+static const struct regmap_irq max77658_chg_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_THM, },
+	{ .mask = MAX77658_BIT_INT_CHG, },
+	{ .mask = MAX77658_BIT_INT_CHGIN, },
+	{ .mask = MAX77658_BIT_INT_TJ_REG, },
+	{ .mask = MAX77658_BIT_INT_CHGIN_CTRL, },
+	{ .mask = MAX77658_BIT_INT_SYS_CTRL, },
+	{ .mask = MAX77658_BIT_INT_SYS_CNFG, },
+};
+
+static const struct regmap_irq_chip max77654_chg_irq_chip = {
+	.name           = "max77654_chg",
+	.status_base    = MAX77658_REG_INT_CHG,
+	.mask_base      = MAX77658_REG_INTM_CHG,
+	.num_regs       = 1,
+	.irqs           = max77658_chg_irqs,
+	.num_irqs       = ARRAY_SIZE(max77658_chg_irqs),
+};
+
+static const struct regmap_irq_chip max77658_chg_irq_chip = {
+	.name           = "max77658_chg",
+	.status_base    = MAX77658_REG_INT_CHG,
+	.mask_base      = MAX77658_REG_INTM_CHG,
+	.num_regs       = 1,
+	.irqs           = max77658_chg_irqs,
+	.num_irqs       = ARRAY_SIZE(max77658_chg_irqs),
+};
+
+static const struct regmap_irq max77659_chg_irqs[] = {
+	{ .mask = MAX77658_BIT_INT_THM, },
+	{ .mask = MAX77658_BIT_INT_CHG, },
+	{ .mask = MAX77658_BIT_INT_CHGIN, },
+	{ .mask = MAX77658_BIT_INT_TJ_REG, },
+	{ .mask = MAX776569_BIT_INT_SYS_CTRL, },
+};
+
+static const struct regmap_irq_chip max77659_chg_irq_chip = {
+	.name           = "max77659_chg",
+	.status_base    = MAX77658_REG_INT_CHG,
+	.mask_base      = MAX77658_REG_INTM_CHG,
+	.num_regs       = 1,
+	.irqs           = max77659_chg_irqs,
+	.num_irqs       = ARRAY_SIZE(max77659_chg_irqs),
+};
+
+static const struct mfd_cell max77643_devs[] = {
+	MFD_CELL_OF("max77643-regulator", NULL, NULL, 0, 0,
+		    "adi,max77643-regulator"),
+};
+
+static const struct mfd_cell max77654_devs[] = {
+	MFD_CELL_OF("max77654-regulator", NULL, NULL, 0, 0,
+		    "adi,max77654-regulator"),
+	MFD_CELL_OF("max77654-charger", NULL, NULL, 0, 0,
+		    "adi,max77654-charger"),
+};
+
+static const struct mfd_cell max77658_devs[] = {
+	MFD_CELL_OF("max77658-regulator", NULL, NULL, 0, 0,
+		    "adi,max77658-regulator"),
+	MFD_CELL_OF("max77658-charger", NULL, NULL, 0, 0,
+		    "adi,max77658-charger"),
+	MFD_CELL_OF("max77658-battery", NULL, NULL, 0, 0,
+		    "adi,max77658-battery"),
+};
+
+static const struct mfd_cell max77659_devs[] = {
+	MFD_CELL_OF("max77659-regulator", NULL, NULL, 0, 0,
+		    "adi,max77659-regulator"),
+	MFD_CELL_OF("max77659-charger", NULL, NULL, 0, 0,
+		    "adi,max77659-charger"),
+};
+
+static const struct chip_info chip[] = {
+	[ID_MAX77643] = {
+		.id = ID_MAX77643,
+		.n_devs = ARRAY_SIZE(max77643_devs),
+		.devs = max77643_devs,
+	},
+	[ID_MAX77654] = {
+		.id = ID_MAX77654,
+		.n_devs = ARRAY_SIZE(max77654_devs),
+		.devs = max77654_devs,
+	},
+	[ID_MAX77658] = {
+		.id = ID_MAX77658,
+		.n_devs = ARRAY_SIZE(max77658_devs),
+		.devs = max77658_devs,
+	},
+	[ID_MAX77659] = {
+		.id = ID_MAX77659,
+		.n_devs = ARRAY_SIZE(max77659_devs),
+		.devs = max77659_devs,
+	},
+};
+
+static int max77658_pmic_irq_init(struct device *dev)
+{
+	const struct regmap_irq_chip *glbl0_chip, *glbl1_chip, *chg_chip;
+	struct max77658_dev *max77658 = dev_get_drvdata(dev);
+	int ret, i;
+
+	switch (max77658->chip->id) {
+	case ID_MAX77643:
+		glbl0_chip = &max77643_glbl0_irq_chip;
+		glbl1_chip = &max77643_glbl1_irq_chip;
+		break;
+	case ID_MAX77654:
+		glbl0_chip = &max77654_glbl0_irq_chip;
+		glbl1_chip = &max77654_glbl1_irq_chip;
+		chg_chip = &max77654_chg_irq_chip;
+		break;
+	case ID_MAX77658:
+		glbl0_chip = &max77658_glbl0_irq_chip;
+		glbl1_chip = &max77658_glbl1_irq_chip;
+		chg_chip = &max77658_chg_irq_chip;
+		break;
+	case ID_MAX77659:
+		glbl0_chip = &max77659_glbl0_irq_chip;
+		glbl1_chip = &max77659_glbl1_irq_chip;
+		chg_chip = &max77659_chg_irq_chip;
+		break;
+	default:
+		break;
+	}
+
+	for (i = 0; i < glbl0_chip->num_regs; i++) {
+		ret = regmap_update_bits(max77658->regmap,
+					 glbl0_chip->mask_base,
+					 (1 << glbl0_chip->irqs[i].reg_offset),
+					 1);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "Unable to write Global0 Interrupt Masking register\n");
+	}
+
+	for (i = 0; i < glbl1_chip->num_regs; i++) {
+		ret = regmap_update_bits(max77658->regmap,
+					 glbl1_chip->mask_base,
+					 (1 << glbl1_chip->irqs[i].reg_offset),
+					 1);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "Unable to write Global1 Interrupt Masking register\n");
+	}
+
+	if (max77658->chip->id != ID_MAX77643) {
+		for (i = 0; i < chg_chip->num_regs; i++) {
+			ret = regmap_update_bits(max77658->regmap,
+						 chg_chip->mask_base,
+						 (1 <<
+						 chg_chip->irqs[i].reg_offset),
+						 1);
+			if (ret)
+				return dev_err_probe(dev, ret,
+						     "Unable to write Charger Interrupt Masking register\n");
+		}
+
+		ret = devm_regmap_add_irq_chip(dev, max77658->regmap,
+					       max77658->irq,
+					       IRQF_ONESHOT | IRQF_SHARED, 0,
+					       chg_chip, &max77658->irqc_chg);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "Failed to add charger IRQ chip\n");
+	}
+
+	ret = devm_regmap_add_irq_chip(dev, max77658->regmap, max77658->irq,
+				       IRQF_ONESHOT | IRQF_SHARED, 0,
+				       glbl0_chip, &max77658->irqc_glbl0);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to add global0 IRQ chip\n");
+
+	return devm_regmap_add_irq_chip(dev, max77658->regmap, max77658->irq,
+					IRQF_ONESHOT | IRQF_SHARED, 0,
+					glbl1_chip, &max77658->irqc_glbl1);
+}
+
+static int max77658_pmic_setup(struct device *dev)
+{
+	struct max77658_dev *max77658 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = max77658_pmic_irq_init(max77658->dev);
+	if (ret)
+		return ret;
+
+	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+				   max77658->chip->devs, max77658->chip->n_devs,
+				   NULL, 0, NULL);
+
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add sub-devices\n");
+
+	ret = device_init_wakeup(dev, true);
+	if (ret)
+		return dev_err_probe(dev, ret, "Unable to init wakeup\n");
+
+	return 0;
+}
+
+static const struct i2c_device_id max77658_i2c_id[];
+
+static int max77658_i2c_probe(struct i2c_client *client)
+{
+	struct max77658_dev *max77658;
+	struct i2c_client *fuel;
+
+	max77658 = devm_kzalloc(&client->dev, sizeof(*max77658), GFP_KERNEL);
+	if (!max77658)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, max77658);
+	max77658->dev = &client->dev;
+	max77658->irq = client->irq;
+
+	if (max77658->dev->of_node)
+		max77658->chip  = of_device_get_match_data(max77658->dev);
+	else
+		max77658->chip  = (struct chip_info *)
+					i2c_match_id(max77658_i2c_id,
+						     client)->driver_data;
+	if (!max77658->chip)
+		return -EINVAL;
+
+	max77658->regmap = devm_regmap_init_i2c(client,
+						&max77658_regmap_config);
+	if (IS_ERR(max77658->regmap))
+		return dev_err_probe(max77658->dev, PTR_ERR(max77658->regmap),
+				     "Failed to allocate register map\n");
+
+	fuel = i2c_new_dummy_device(client->adapter, I2C_ADDR_FUEL_GAUGE);
+	if (IS_ERR(fuel))
+		return dev_err_probe(max77658->dev, PTR_ERR(fuel),
+				     "failed add i2c device[0x%Xh]\n",
+				      I2C_ADDR_FUEL_GAUGE);
+
+	i2c_set_clientdata(fuel, max77658);
+
+	max77658->regmap_fg = devm_regmap_init_i2c(fuel,
+						   &max77658_regmap_config_fg);
+	if (IS_ERR(max77658->regmap_fg))
+		return dev_err_probe(max77658->dev,
+				     PTR_ERR(max77658->regmap_fg),
+				     "failed to initialize i2c device[0x%Xh]\n",
+				     I2C_ADDR_FUEL_GAUGE);
+
+	return max77658_pmic_setup(max77658->dev);
+}
+
+static const struct of_device_id max77658_of_id[] = {
+	{ .compatible = "adi,max77643", .data = &chip[ID_MAX77643] },
+	{ .compatible = "adi,max77654", .data = &chip[ID_MAX77654] },
+	{ .compatible = "adi,max77658", .data = &chip[ID_MAX77658] },
+	{ .compatible = "adi,max77659", .data = &chip[ID_MAX77659] },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, max77658_of_id);
+
+static const struct i2c_device_id max77658_i2c_id[] = {
+	{ "max77643", (kernel_ulong_t)&chip[ID_MAX77643] },
+	{ "max77654", (kernel_ulong_t)&chip[ID_MAX77654] },
+	{ "max77658", (kernel_ulong_t)&chip[ID_MAX77658] },
+	{ "max77659", (kernel_ulong_t)&chip[ID_MAX77659] },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, max77658_i2c_id);
+
+static struct i2c_driver max77658_driver = {
+	.driver = {
+		.name = "max77658",
+		.of_match_table = max77658_of_id,
+	},
+	.probe_new = max77658_i2c_probe,
+	.id_table = max77658_i2c_id,
+};
+module_i2c_driver(max77658_driver);
+
+MODULE_DESCRIPTION("MAX77658 MFD Driver");
+MODULE_AUTHOR("Nurettin.Bolucu@analog.com, Zeynep.Arslanbenzer@analog.com");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/max77658.h b/include/linux/mfd/max77658.h
new file mode 100644
index 000000000000..471a8474513e
--- /dev/null
+++ b/include/linux/mfd/max77658.h
@@ -0,0 +1,88 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __MAX77658_MFD_H__
+#define __MAX77658_MFD_H__
+
+#include <linux/bits.h>
+#include <linux/types.h>
+
+#define MAX77658_REG_INT_GLBL0	0x00
+#define MAX77658_REG_INT_CHG	0x01
+#define MAX77658_REG_INT_GLBL1	0x04
+#define MAX77658_REG_INTM_CHG	0x07
+#define MAX77658_REG_INTM_GLBL0	0x08
+#define MAX77658_REG_INTM_GLBL1	0x09
+
+#define MAX77654_REG_INTM_GLBL1	0x08
+#define MAX77654_REG_INTM_GLBL0	0x09
+
+#define MAX77643_REG_INT_GLBL1	0x01
+#define MAX77643_REG_INTM_GLBL0	0x04
+#define MAX77643_REG_INTM_GLBL1	0x05
+
+#define MAX77658_BIT_INT_GLBL0_GPIO0_F	BIT(0)
+#define MAX77658_BIT_INT_GLBL0_GPIO0_R	BIT(1)
+#define MAX77658_BIT_INT_GLBL0_EN_F	BIT(2)
+#define MAX77658_BIT_INT_GLBL0_EN_R	BIT(3)
+#define MAX77658_BIT_INT_GLBL0_TJAL1_R	BIT(4)
+#define MAX77658_BIT_INT_GLBL0_TJAL2_R	BIT(5)
+#define MAX77658_BIT_INT_GLBL0_DOD1_R	BIT(6)
+#define MAX77658_BIT_INT_GLBL0_DOD0_R	BIT(7)
+
+#define MAX77643_BIT_INT_GLBL0_DOD0_R	BIT(6)
+
+#define MAX77658_BIT_INT_GLBL1_GPI1_F	BIT(0)
+#define MAX77658_BIT_INT_GLBL1_GPI1_R	BIT(1)
+#define MAX77658_BIT_INT_GLBL1_SBB0_F	BIT(2)
+#define MAX77658_BIT_INT_GLBL1_SBB1_F	BIT(3)
+#define MAX77658_BIT_INT_GLBL1_SBB2_F	BIT(4)
+#define MAX77658_BIT_INT_GLBL1_LDO0_F	BIT(5)
+#define MAX77658_BIT_INT_GLBL1_LDO1_F	BIT(6)
+
+#define MAX77659_BIT_INT_GLBL1_SBB_TO	BIT(4)
+
+#define MAX77654_BIT_INT_GLBL1_GPI2_F	BIT(2)
+#define MAX77654_BIT_INT_GLBL1_GPI2_R	BIT(3)
+#define MAX77654_BIT_INT_GLBL1_SBB_TO	BIT(4)
+
+#define MAX77658_BIT_INT_THM		BIT(0)
+#define MAX77658_BIT_INT_CHG		BIT(1)
+#define MAX77658_BIT_INT_CHGIN		BIT(2)
+#define MAX77658_BIT_INT_TJ_REG		BIT(3)
+#define MAX77658_BIT_INT_CHGIN_CTRL	BIT(4)
+#define MAX77658_BIT_INT_SYS_CTRL	BIT(5)
+#define MAX77658_BIT_INT_SYS_CNFG	BIT(6)
+
+#define MAX776569_BIT_INT_SYS_CTRL	BIT(4)
+
+enum max77658_ids {
+	ID_MAX77643,
+	ID_MAX77654,
+	ID_MAX77658,
+	ID_MAX77659
+};
+
+struct chip_info {
+	enum max77658_ids id;
+	int n_devs;
+	const struct mfd_cell *devs;
+};
+
+struct device;
+struct regmap;
+struct regmap_irq_chip_data;
+
+struct max77658_dev {
+	struct device *dev;
+	const struct chip_info *chip;
+
+	int irq;
+	struct regmap_irq_chip_data *irqc_glbl0;
+	struct regmap_irq_chip_data *irqc_glbl1;
+	struct regmap_irq_chip_data *irqc_chg;
+
+	struct regmap *regmap;
+	struct regmap *regmap_fg;
+};
+
+#endif /* __MAX77658_MFD_H__ */