Re: [PATCH v3 3/7] mfd: Add MFD driver for ATC260x PMICs

From: Lee Jones
Date: Wed Dec 16 2020 - 05:11:18 EST


On Sun, 06 Dec 2020, Cristian Ciocaltea wrote:

> Add initial support for the Actions Semi ATC260x PMICs. ATC260x series
> PMICs integrates Audio Codec, Power management, Clock generation and

"which integrates"

> GPIO controller blocks.
>
> For the moment this driver only supports Regulator, Poweroff and Onkey
> functionalities for the ATC2603C and ATC2609A chip variants.
>
> Since the PMICs can be accessed using both I2C and SPI buses, the
> following driver structure has been adopted:
>
> -----> atc260x-core.c (Implements core functionalities)
> /
> ATC260x --------> atc260x-i2c.c (Implements I2C interface)
> \
> -----> atc260x-spi.c (Implements SPI interface - TODO)
>
> Co-developed-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>
> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@xxxxxxxxx>
> ---
> Changes in v3:
> - Fixed the issues reported by Lee's kernel test robot:
> WARNING: modpost: missing MODULE_LICENSE() in drivers/mfd/atc260x-core.o
> >> FATAL: modpost: drivers/mfd/atc260x-i2c: sizeof(struct i2c_device_id)=24 is
> not a modulo of the size of section __mod_i2c__<identifier>_device_table=588.
> >> Fix definition of struct i2c_device_id in mod_devicetable.h
> - Dropped the usage of '.of_compatible' fields in {atc2603c,atc2609a}_mfd_cells[]
> - Added 'Co-developed-by' tag in commit message and dropped [cristian: ...] line
>
> drivers/mfd/Kconfig | 18 ++
> drivers/mfd/Makefile | 3 +
> drivers/mfd/atc260x-core.c | 290 +++++++++++++++++++++++++
> drivers/mfd/atc260x-i2c.c | 73 +++++++
> include/linux/mfd/atc260x/atc2603c.h | 281 ++++++++++++++++++++++++
> include/linux/mfd/atc260x/atc2609a.h | 308 +++++++++++++++++++++++++++
> include/linux/mfd/atc260x/core.h | 86 ++++++++
> 7 files changed, 1059 insertions(+)
> create mode 100644 drivers/mfd/atc260x-core.c
> create mode 100644 drivers/mfd/atc260x-i2c.c
> create mode 100644 include/linux/mfd/atc260x/atc2603c.h
> create mode 100644 include/linux/mfd/atc260x/atc2609a.h
> create mode 100644 include/linux/mfd/atc260x/core.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 8b99a13669bf..5556182af41c 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -2076,6 +2076,24 @@ config MFD_WCD934X
> This driver provides common support WCD934x audio codec and its
> associated Pin Controller, Soundwire Controller and Audio codec.
>
> +config MFD_ATC260X
> + tristate
> + select MFD_CORE
> + select REGMAP
> + select REGMAP_IRQ
> +
> +config MFD_ATC260X_I2C
> + tristate "Actions Semi ATC260x PMICs with I2C"
> + select MFD_ATC260X
> + select REGMAP_I2C
> + depends on I2C
> + help
> + Support for the Actions Semi ATC260x PMICs controlled via I2C.
> +
> + This driver provides common support for accessing the ATC2603C
> + and ATC2609A chip variants, additional drivers must be enabled
> + in order to use the functionality of the device.
> +
> config MFD_KHADAS_MCU
> tristate "Support for Khadas System control Microcontroller"
> depends on I2C
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 1780019d2474..d10362670ac3 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -267,3 +267,6 @@ obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o
> obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
> obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
> obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
> +
> +obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o
> +obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
> diff --git a/drivers/mfd/atc260x-core.c b/drivers/mfd/atc260x-core.c
> new file mode 100644
> index 000000000000..fd3a43b4030d
> --- /dev/null
> +++ b/drivers/mfd/atc260x-core.c
> @@ -0,0 +1,290 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Core MFD support for ATC260x PMICs

Drop the MFD part please.

> + * Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>
> + * Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@xxxxxxxxx>
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/mfd/atc260x/core.h>
> +#include <linux/mfd/core.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/regmap.h>
> +
> +static void regmap_lock_mutex(void *__mutex)
> +{
> + struct mutex *mutex = __mutex;
> +
> + /*
> + * Using regmap within an atomic context (e.g. accessing a PMIC when
> + * powering system down) is normally allowed only if the regmap type
> + * is MMIO and the regcache type is either REGCACHE_NONE or
> + * REGCACHE_FLAT. For slow buses like I2C and SPI, the regmap is
> + * internally protected by a mutex which is acquired non-atomically.
> + *
> + * Let's improve this by using a customized locking scheme inspired
> + * from I2C atomic transfer. See i2c_in_atomic_xfer_mode() for a
> + * starting point.
> + */
> + if (system_state > SYSTEM_RUNNING && irqs_disabled())

Were does system_state come from?

> + mutex_trylock(mutex);
> + else
> + mutex_lock(mutex);
> +}
> +
> +static void regmap_unlock_mutex(void *__mutex)
> +{
> + struct mutex *mutex = __mutex;
> +
> + mutex_unlock(mutex);
> +}
> +
> +static const struct regmap_config atc2603c_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 16,
> + .max_register = ATC2603C_SADDR,
> + .cache_type = REGCACHE_NONE,
> +};
> +
> +static const struct regmap_config atc2609a_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 16,
> + .max_register = ATC2609A_SADDR,
> + .cache_type = REGCACHE_NONE,
> +};
> +
> +static const struct regmap_irq atc2603c_regmap_irqs[] = {
> + REGMAP_IRQ_REG(ATC2603C_IRQ_AUDIO, 0, ATC2603C_INTS_MSK_AUDIO),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_OV, 0, ATC2603C_INTS_MSK_OV),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_OC, 0, ATC2603C_INTS_MSK_OC),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_OT, 0, ATC2603C_INTS_MSK_OT),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_UV, 0, ATC2603C_INTS_MSK_UV),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_ALARM, 0, ATC2603C_INTS_MSK_ALARM),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_ONOFF, 0, ATC2603C_INTS_MSK_ONOFF),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_SGPIO, 0, ATC2603C_INTS_MSK_SGPIO),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_IR, 0, ATC2603C_INTS_MSK_IR),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_REMCON, 0, ATC2603C_INTS_MSK_REMCON),
> + REGMAP_IRQ_REG(ATC2603C_IRQ_POWER_IN, 0, ATC2603C_INTS_MSK_POWERIN),
> +};
> +
> +static const struct regmap_irq atc2609a_regmap_irqs[] = {
> + REGMAP_IRQ_REG(ATC2609A_IRQ_AUDIO, 0, ATC2609A_INTS_MSK_AUDIO),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_OV, 0, ATC2609A_INTS_MSK_OV),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_OC, 0, ATC2609A_INTS_MSK_OC),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_OT, 0, ATC2609A_INTS_MSK_OT),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_UV, 0, ATC2609A_INTS_MSK_UV),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_ALARM, 0, ATC2609A_INTS_MSK_ALARM),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_ONOFF, 0, ATC2609A_INTS_MSK_ONOFF),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_WKUP, 0, ATC2609A_INTS_MSK_WKUP),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_IR, 0, ATC2609A_INTS_MSK_IR),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_REMCON, 0, ATC2609A_INTS_MSK_REMCON),
> + REGMAP_IRQ_REG(ATC2609A_IRQ_POWER_IN, 0, ATC2609A_INTS_MSK_POWERIN),
> +};
> +
> +static const struct regmap_irq_chip atc2603c_regmap_irq_chip = {
> + .name = "atc2603c",
> + .irqs = atc2603c_regmap_irqs,
> + .num_irqs = ARRAY_SIZE(atc2603c_regmap_irqs),
> + .num_regs = 1,
> + .status_base = ATC2603C_INTS_PD,
> + .mask_base = ATC2603C_INTS_MSK,
> + .mask_invert = true,
> +};
> +
> +static const struct regmap_irq_chip atc2609a_regmap_irq_chip = {
> + .name = "atc2609a",
> + .irqs = atc2609a_regmap_irqs,
> + .num_irqs = ARRAY_SIZE(atc2609a_regmap_irqs),
> + .num_regs = 1,
> + .status_base = ATC2609A_INTS_PD,
> + .mask_base = ATC2609A_INTS_MSK,
> + .mask_invert = true,
> +};
> +
> +static const struct resource atc2603c_onkey_resources[] = {
> + DEFINE_RES_IRQ(ATC2603C_IRQ_ONOFF),
> +};
> +
> +static const struct resource atc2609a_onkey_resources[] = {
> + DEFINE_RES_IRQ(ATC2609A_IRQ_ONOFF),
> +};
> +
> +static const struct mfd_cell atc2603c_mfd_cells[] = {
> + {
> + .name = "atc260x-regulator",
> + }, {
> + .name = "atc260x-pwrc",
> + }, {

Please place single line entries on one line:

{ .name = "atc260x-regulator" },
{ .name = "atc260x-pwrc" },

> + {
> + .name = "atc260x-onkey",
> + .num_resources = ARRAY_SIZE(atc2603c_onkey_resources),
> + .resources = atc2603c_onkey_resources,
> + },
> +};
> +
> +static const struct mfd_cell atc2609a_mfd_cells[] = {
> + {
> + .name = "atc260x-regulator",
> + }, {
> + .name = "atc260x-pwrc",

As above.

> + }, {
> + .name = "atc260x-onkey",
> + .num_resources = ARRAY_SIZE(atc2609a_onkey_resources),
> + .resources = atc2609a_onkey_resources,
> + },
> +};
> +
> +static void atc260x_cmu_reset(struct atc260x *atc260x, u32 reg, u8 mask, u32 bit)
> +{
> + /* Assert reset */
> + regmap_update_bits(atc260x->regmap, reg, mask, ~bit);
> +
> + /* De-assert reset */
> + regmap_update_bits(atc260x->regmap, reg, mask, bit);
> +}
> +
> +static int atc2603c_dev_init(struct atc260x *atc260x)
> +{
> + /* Initialize interrupt block */
> + atc260x_cmu_reset(atc260x, ATC2603C_CMU_DEVRST,
> + ATC2603C_CMU_DEVRST_INTS, ATC2603C_CMU_DEVRST_INTS);
> +
> + /* Disable all interrupt sources */
> + regmap_write(atc260x->regmap, ATC2603C_INTS_MSK, 0);
> +
> + /* Enable EXTIRQ pad */
> + return regmap_update_bits(atc260x->regmap, ATC2603C_PAD_EN,
> + ATC2603C_PAD_EN_EXTIRQ, ATC2603C_PAD_EN_EXTIRQ);
> +}
> +
> +static int atc2609a_dev_init(struct atc260x *atc260x)
> +{
> + /* Initialize interrupt block */
> + atc260x_cmu_reset(atc260x, ATC2609A_CMU_DEVRST,
> + ATC2609A_CMU_DEVRST_INTS, ATC2609A_CMU_DEVRST_INTS);
> +
> + /* Disable all interrupt sources */
> + regmap_write(atc260x->regmap, ATC2609A_INTS_MSK, 0);
> +
> + /* Enable EXTIRQ pad */
> + return regmap_update_bits(atc260x->regmap, ATC2609A_PAD_EN,
> + ATC2609A_PAD_EN_EXTIRQ, ATC2609A_PAD_EN_EXTIRQ);
> +}
> +
> +int atc260x_match_device(struct atc260x *atc260x, struct regmap_config *regmap_cfg)
> +{
> + struct device *dev = atc260x->dev;
> + const void *of_data;
> +
> + of_data = of_device_get_match_data(dev);
> + if (!of_data)
> + return -ENODEV;
> +
> + atc260x->ic_type = (unsigned long)of_data;
> +
> + switch (atc260x->ic_type) {
> + case ATC2603C:
> + *regmap_cfg = atc2603c_regmap_config;
> + atc260x->regmap_irq_chip = &atc2603c_regmap_irq_chip;
> + atc260x->cells = atc2603c_mfd_cells;
> + atc260x->nr_cells = ARRAY_SIZE(atc2603c_mfd_cells);
> + atc260x->type_name = "atc2603c";
> + atc260x->rev_reg = ATC2603C_CHIP_VER;
> + atc260x->dev_init = atc2603c_dev_init;
> + break;
> + case ATC2609A:
> + *regmap_cfg = atc2609a_regmap_config;
> + atc260x->regmap_irq_chip = &atc2609a_regmap_irq_chip;
> + atc260x->cells = atc2609a_mfd_cells;
> + atc260x->nr_cells = ARRAY_SIZE(atc2609a_mfd_cells);
> + atc260x->type_name = "atc2609a";
> + atc260x->rev_reg = ATC2609A_CHIP_VER;
> + atc260x->dev_init = atc2609a_dev_init;
> + break;
> + default:
> + dev_err(dev, "Unsupported ATC260x device type: %u\n",
> + atc260x->ic_type);
> + return -EINVAL;
> + }
> +
> + atc260x->regmap_mutex = devm_kzalloc(dev, sizeof(*atc260x->regmap_mutex),
> + GFP_KERNEL);
> + if (!atc260x->regmap_mutex)
> + return -ENOMEM;
> +
> + mutex_init(atc260x->regmap_mutex);
> +
> + regmap_cfg->lock = regmap_lock_mutex,
> + regmap_cfg->unlock = regmap_unlock_mutex,
> + regmap_cfg->lock_arg = atc260x->regmap_mutex;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(atc260x_match_device);
> +
> +int atc260x_device_probe(struct atc260x *atc260x)
> +{
> + struct device *dev = atc260x->dev;
> + unsigned int chip_rev;
> + int ret;
> +
> + if (!atc260x->irq) {
> + dev_err(dev, "No interrupt support\n");
> + return -EINVAL;
> + }
> +
> + /* Initialize the hardware */
> + if (atc260x->dev_init)
> + atc260x->dev_init(atc260x);

Will this ever not be required?

If it will always be required, you can drop the if().

> + ret = regmap_read(atc260x->regmap, atc260x->rev_reg, &chip_rev);
> + if (ret) {
> + dev_err(dev, "Failed to get chip revision\n");
> + return ret;
> + }
> +
> + if (chip_rev < 0 || chip_rev > 31) {
> + dev_err(dev, "Unknown chip revision: %d\n", ret);
> + return -EINVAL;
> + }

This still seems limiting.

> + atc260x->ic_ver = __ffs(chip_rev + 1U);

This is still inefficient.

> + dev_info(dev, "Detected chip type %s rev.%c\n",
> + atc260x->type_name, 'A' + atc260x->ic_ver);
> +
> + ret = regmap_add_irq_chip(atc260x->regmap, atc260x->irq, IRQF_ONESHOT, -1,
> + atc260x->regmap_irq_chip, &atc260x->irq_data);

Why not use devm_*?

> + if (ret) {
> + dev_err(dev, "Failed to add IRQ chip: %d\n", ret);
> + return ret;
> + }
> +
> + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
> + atc260x->cells, atc260x->nr_cells, NULL, 0,
> + regmap_irq_get_domain(atc260x->irq_data));
> + if (ret) {
> + dev_err(dev, "Failed to add child devices: %d\n", ret);
> + regmap_del_irq_chip(atc260x->irq, atc260x->irq_data);
> + return ret;

Drop this return and always return ret at the end.

> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(atc260x_device_probe);
> +
> +int atc260x_device_remove(struct atc260x *atc260x)
> +{
> + mfd_remove_devices(atc260x->dev);

No need to do this, since you used devm_*.

> + regmap_del_irq_chip(atc260x->irq, atc260x->irq_data);

If you use devm_* you can omit this too.

> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(atc260x_device_remove);
> +
> +MODULE_DESCRIPTION("ATC260x PMICs Core MFD support");

Drop "MFD" please.

> +MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>");
> +MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@xxxxxxxxx>");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/mfd/atc260x-i2c.c b/drivers/mfd/atc260x-i2c.c
> new file mode 100644
> index 000000000000..40136a47feda
> --- /dev/null
> +++ b/drivers/mfd/atc260x-i2c.c
> @@ -0,0 +1,73 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * I2C bus interface for ATC260x PMICs
> + *
> + * Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>
> + * Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@xxxxxxxxx>
> + */
> +
> +#include <linux/i2c.h>
> +#include <linux/mfd/atc260x/core.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/regmap.h>
> +
> +static int atc260x_i2c_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct atc260x *atc260x;
> + struct regmap_config regmap_cfg;
> + int ret;
> +
> + atc260x = devm_kzalloc(&client->dev, sizeof(*atc260x), GFP_KERNEL);
> + if (!atc260x)
> + return -ENOMEM;
> +
> + atc260x->dev = &client->dev;
> + atc260x->irq = client->irq;
> +
> + ret = atc260x_match_device(atc260x, &regmap_cfg);
> + if (ret)
> + return ret;
> +
> + i2c_set_clientdata(client, atc260x);
> +
> + atc260x->regmap = devm_regmap_init_i2c(client, &regmap_cfg);
> + if (IS_ERR(atc260x->regmap)) {
> + ret = PTR_ERR(atc260x->regmap);
> + dev_err(&client->dev, "failed to init regmap: %d\n", ret);
> + return ret;
> + }
> +
> + return atc260x_device_probe(atc260x);
> +}
> +
> +static int atc260x_i2c_remove(struct i2c_client *client)
> +{
> + struct atc260x *atc260x = i2c_get_clientdata(client)
> +
> + return atc260x_device_remove(atc260x);
> +}
> +
> +const struct of_device_id atc260x_i2c_of_match[] = {
> + { .compatible = "actions,atc2603c", .data = (void *)ATC2603C },
> + { .compatible = "actions,atc2609a", .data = (void *)ATC2609A },
> + { /* sentinel */ }

I think you can drop the (void *) casts.

Please remove the /* sentinel */ comment, we know what NULL
terminators do.

> +};
> +MODULE_DEVICE_TABLE(of, atc260x_i2c_of_match);
> +
> +static struct i2c_driver atc260x_i2c_driver = {
> + .driver = {
> + .name = "atc260x",
> + .of_match_table = of_match_ptr(atc260x_i2c_of_match),
> + },
> + .probe = atc260x_i2c_probe,
> + .remove = atc260x_i2c_remove,
> +};
> +

Nit: Remove this line.

> +module_i2c_driver(atc260x_i2c_driver);
> +
> +MODULE_DESCRIPTION("ATC260x PMICs I2C bus interface");
> +MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>");
> +MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@xxxxxxxxx>");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/atc260x/atc2603c.h b/include/linux/mfd/atc260x/atc2603c.h
> new file mode 100644
> index 000000000000..07ac640ef3e1
> --- /dev/null
> +++ b/include/linux/mfd/atc260x/atc2603c.h
> @@ -0,0 +1,281 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * ATC2603C PMIC register definitions
> + *
> + * Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@xxxxxxxxx>
> + */
> +
> +#ifndef __LINUX_MFD_ATC260X_ATC2603C_H
> +#define __LINUX_MFD_ATC260X_ATC2603C_H
> +
> +enum atc2603c_irq_def {
> + ATC2603C_IRQ_AUDIO = 0,
> + ATC2603C_IRQ_OV,
> + ATC2603C_IRQ_OC,
> + ATC2603C_IRQ_OT,
> + ATC2603C_IRQ_UV,
> + ATC2603C_IRQ_ALARM,
> + ATC2603C_IRQ_ONOFF,
> + ATC2603C_IRQ_SGPIO,
> + ATC2603C_IRQ_IR,
> + ATC2603C_IRQ_REMCON,
> + ATC2603C_IRQ_POWER_IN,
> +};
> +
> +/* PMU Registers */
> +#define ATC2603C_PMU_SYS_CTL0 0x00
> +#define ATC2603C_PMU_SYS_CTL1 0x01
> +#define ATC2603C_PMU_SYS_CTL2 0x02
> +#define ATC2603C_PMU_SYS_CTL3 0x03
> +#define ATC2603C_PMU_SYS_CTL4 0x04
> +#define ATC2603C_PMU_SYS_CTL5 0x05
> +#define ATC2603C_PMU_SYS_CTL6 0x06
> +#define ATC2603C_PMU_SYS_CTL7 0x07
> +#define ATC2603C_PMU_SYS_CTL8 0x08
> +#define ATC2603C_PMU_SYS_CTL9 0x09
> +#define ATC2603C_PMU_BAT_CTL0 0x0A
> +#define ATC2603C_PMU_BAT_CTL1 0x0B
> +#define ATC2603C_PMU_VBUS_CTL0 0x0C
> +#define ATC2603C_PMU_VBUS_CTL1 0x0D
> +#define ATC2603C_PMU_WALL_CTL0 0x0E
> +#define ATC2603C_PMU_WALL_CTL1 0x0F
> +#define ATC2603C_PMU_SYS_PENDING 0x10
> +#define ATC2603C_PMU_DC1_CTL0 0x11
> +#define ATC2603C_PMU_DC1_CTL1 0x12 // Undocumented
> +#define ATC2603C_PMU_DC1_CTL2 0x13 // Undocumented
> +#define ATC2603C_PMU_DC2_CTL0 0x14
> +#define ATC2603C_PMU_DC2_CTL1 0x15 // Undocumented
> +#define ATC2603C_PMU_DC2_CTL2 0x16 // Undocumented
> +#define ATC2603C_PMU_DC3_CTL0 0x17
> +#define ATC2603C_PMU_DC3_CTL1 0x18 // Undocumented
> +#define ATC2603C_PMU_DC3_CTL2 0x19 // Undocumented
> +#define ATC2603C_PMU_DC4_CTL0 0x1A // Undocumented
> +#define ATC2603C_PMU_DC4_CTL1 0x1B // Undocumented
> +#define ATC2603C_PMU_DC5_CTL0 0x1C // Undocumented
> +#define ATC2603C_PMU_DC5_CTL1 0x1D // Undocumented
> +#define ATC2603C_PMU_LDO1_CTL 0x1E
> +#define ATC2603C_PMU_LDO2_CTL 0x1F
> +#define ATC2603C_PMU_LDO3_CTL 0x20
> +#define ATC2603C_PMU_LDO4_CTL 0x21 // Undocumented
> +#define ATC2603C_PMU_LDO5_CTL 0x22
> +#define ATC2603C_PMU_LDO6_CTL 0x23
> +#define ATC2603C_PMU_LDO7_CTL 0x24
> +#define ATC2603C_PMU_LDO8_CTL 0x25 // Undocumented
> +#define ATC2603C_PMU_LDO9_CTL 0x26 // Undocumented
> +#define ATC2603C_PMU_LDO10_CTL 0x27 // Undocumented
> +#define ATC2603C_PMU_LDO11_CTL 0x28
> +#define ATC2603C_PMU_SWITCH_CTL 0x29
> +#define ATC2603C_PMU_OV_CTL0 0x2A
> +#define ATC2603C_PMU_OV_CTL1 0x2B
> +#define ATC2603C_PMU_OV_STATUS 0x2C
> +#define ATC2603C_PMU_OV_EN 0x2D
> +#define ATC2603C_PMU_OV_INT_EN 0x2E
> +#define ATC2603C_PMU_OC_CTL 0x2F
> +#define ATC2603C_PMU_OC_STATUS 0x30
> +#define ATC2603C_PMU_OC_EN 0x31
> +#define ATC2603C_PMU_OC_INT_EN 0x32
> +#define ATC2603C_PMU_UV_CTL0 0x33
> +#define ATC2603C_PMU_UV_CTL1 0x34
> +#define ATC2603C_PMU_UV_STATUS 0x35
> +#define ATC2603C_PMU_UV_EN 0x36
> +#define ATC2603C_PMU_UV_INT_EN 0x37
> +#define ATC2603C_PMU_OT_CTL 0x38
> +#define ATC2603C_PMU_CHARGER_CTL0 0x39
> +#define ATC2603C_PMU_CHARGER_CTL1 0x3A
> +#define ATC2603C_PMU_CHARGER_CTL2 0x3B
> +#define ATC2603C_PMU_BAKCHARGER_CTL 0x3C // Undocumented
> +#define ATC2603C_PMU_APDS_CTL 0x3D
> +#define ATC2603C_PMU_AUXADC_CTL0 0x3E
> +#define ATC2603C_PMU_AUXADC_CTL1 0x3F
> +#define ATC2603C_PMU_BATVADC 0x40
> +#define ATC2603C_PMU_BATIADC 0x41
> +#define ATC2603C_PMU_WALLVADC 0x42
> +#define ATC2603C_PMU_WALLIADC 0x43
> +#define ATC2603C_PMU_VBUSVADC 0x44
> +#define ATC2603C_PMU_VBUSIADC 0x45
> +#define ATC2603C_PMU_SYSPWRADC 0x46
> +#define ATC2603C_PMU_REMCONADC 0x47
> +#define ATC2603C_PMU_SVCCADC 0x48
> +#define ATC2603C_PMU_CHGIADC 0x49
> +#define ATC2603C_PMU_IREFADC 0x4A
> +#define ATC2603C_PMU_BAKBATADC 0x4B
> +#define ATC2603C_PMU_ICTEMPADC 0x4C
> +#define ATC2603C_PMU_AUXADC0 0x4D
> +#define ATC2603C_PMU_AUXADC1 0x4E
> +#define ATC2603C_PMU_AUXADC2 0x4F
> +#define ATC2603C_PMU_ICMADC 0x50
> +#define ATC2603C_PMU_BDG_CTL 0x51 // Undocumented
> +#define ATC2603C_RTC_CTL 0x52
> +#define ATC2603C_RTC_MSALM 0x53
> +#define ATC2603C_RTC_HALM 0x54
> +#define ATC2603C_RTC_YMDALM 0x55
> +#define ATC2603C_RTC_MS 0x56
> +#define ATC2603C_RTC_H 0x57
> +#define ATC2603C_RTC_DC 0x58
> +#define ATC2603C_RTC_YMD 0x59
> +#define ATC2603C_EFUSE_DAT 0x5A // Undocumented
> +#define ATC2603C_EFUSECRTL1 0x5B // Undocumented
> +#define ATC2603C_EFUSECRTL2 0x5C // Undocumented
> +#define ATC2603C_PMU_FW_USE0 0x5D // Undocumented
> +#define ATC2603C_PMU_FW_USE1 0x5E // Undocumented
> +#define ATC2603C_PMU_FW_USE2 0x5F // Undocumented
> +#define ATC2603C_PMU_FW_USE3 0x60 // Undocumented
> +#define ATC2603C_PMU_FW_USE4 0x61 // Undocumented
> +#define ATC2603C_PMU_ABNORMAL_STATUS 0x62
> +#define ATC2603C_PMU_WALL_APDS_CTL 0x63
> +#define ATC2603C_PMU_REMCON_CTL0 0x64
> +#define ATC2603C_PMU_REMCON_CTL1 0x65
> +#define ATC2603C_PMU_MUX_CTL0 0x66
> +#define ATC2603C_PMU_SGPIO_CTL0 0x67
> +#define ATC2603C_PMU_SGPIO_CTL1 0x68
> +#define ATC2603C_PMU_SGPIO_CTL2 0x69
> +#define ATC2603C_PMU_SGPIO_CTL3 0x6A
> +#define ATC2603C_PMU_SGPIO_CTL4 0x6B
> +#define ATC2603C_PWMCLK_CTL 0x6C
> +#define ATC2603C_PWM0_CTL 0x6D
> +#define ATC2603C_PWM1_CTL 0x6E
> +#define ATC2603C_PMU_ADC_DBG0 0x70
> +#define ATC2603C_PMU_ADC_DBG1 0x71
> +#define ATC2603C_PMU_ADC_DBG2 0x72
> +#define ATC2603C_PMU_ADC_DBG3 0x73
> +#define ATC2603C_PMU_ADC_DBG4 0x74
> +#define ATC2603C_IRC_CTL 0x80
> +#define ATC2603C_IRC_STAT 0x81
> +#define ATC2603C_IRC_CC 0x82
> +#define ATC2603C_IRC_KDC 0x83
> +#define ATC2603C_IRC_WK 0x84
> +#define ATC2603C_IRC_RCC 0x85
> +#define ATC2603C_IRC_FILTER 0x86
> +
> +/* AUDIO_OUT Registers */
> +#define ATC2603C_AUDIOINOUT_CTL 0xA0
> +#define ATC2603C_AUDIO_DEBUGOUTCTL 0xA1
> +#define ATC2603C_DAC_DIGITALCTL 0xA2
> +#define ATC2603C_DAC_VOLUMECTL0 0xA3
> +#define ATC2603C_DAC_ANALOG0 0xA4
> +#define ATC2603C_DAC_ANALOG1 0xA5
> +#define ATC2603C_DAC_ANALOG2 0xA6
> +#define ATC2603C_DAC_ANALOG3 0xA7
> +
> +/* AUDIO_IN Registers */
> +#define ATC2603C_ADC_DIGITALCTL 0xA8
> +#define ATC2603C_ADC_HPFCTL 0xA9
> +#define ATC2603C_ADC_CTL 0xAA
> +#define ATC2603C_AGC_CTL0 0xAB
> +#define ATC2603C_AGC_CTL1 0xAC // Undocumented
> +#define ATC2603C_AGC_CTL2 0xAD
> +#define ATC2603C_ADC_ANALOG0 0xAE
> +#define ATC2603C_ADC_ANALOG1 0xAF
> +
> +/* PCM_IF Registers */
> +#define ATC2603C_PCM0_CTL 0xB0 // Undocumented
> +#define ATC2603C_PCM1_CTL 0xB1 // Undocumented
> +#define ATC2603C_PCM2_CTL 0xB2 // Undocumented
> +#define ATC2603C_PCMIF_CTL 0xB3 // Undocumented
> +
> +/* CMU_CONTROL Registers */
> +#define ATC2603C_CMU_DEVRST 0xC1 // Undocumented
> +
> +/* INTS Registers */
> +#define ATC2603C_INTS_PD 0xC8
> +#define ATC2603C_INTS_MSK 0xC9
> +
> +/* MFP Registers */
> +#define ATC2603C_MFP_CTL 0xD0
> +#define ATC2603C_PAD_VSEL 0xD1 // Undocumented
> +#define ATC2603C_GPIO_OUTEN 0xD2
> +#define ATC2603C_GPIO_INEN 0xD3
> +#define ATC2603C_GPIO_DAT 0xD4
> +#define ATC2603C_PAD_DRV 0xD5
> +#define ATC2603C_PAD_EN 0xD6
> +#define ATC2603C_DEBUG_SEL 0xD7 // Undocumented
> +#define ATC2603C_DEBUG_IE 0xD8 // Undocumented
> +#define ATC2603C_DEBUG_OE 0xD9 // Undocumented
> +#define ATC2603C_BIST_START 0x0A // Undocumented
> +#define ATC2603C_BIST_RESULT 0x0B // Undocumented
> +#define ATC2603C_CHIP_VER 0xDC
> +
> +/* TWSI Registers */
> +#define ATC2603C_SADDR 0xFF
> +
> +/* PMU_SYS_CTL0 Register Mask Bits */
> +#define ATC2603C_PMU_SYS_CTL0_IR_WK_EN BIT(5)
> +#define ATC2603C_PMU_SYS_CTL0_RESET_WK_EN BIT(6)
> +#define ATC2603C_PMU_SYS_CTL0_HDSW_WK_EN BIT(7)
> +#define ATC2603C_PMU_SYS_CTL0_ALARM_WK_EN BIT(8)
> +#define ATC2603C_PMU_SYS_CTL0_REM_CON_WK_EN BIT(9)
> +#define ATC2603C_PMU_SYS_CTL0_RESTART_EN BIT(10)
> +#define ATC2603C_PMU_SYS_CTL0_SGPIOIRQ_WK_EN BIT(11)
> +#define ATC2603C_PMU_SYS_CTL0_ONOFF_SHORT_WK_EN BIT(12)
> +#define ATC2603C_PMU_SYS_CTL0_ONOFF_LONG_WK_EN BIT(13)
> +#define ATC2603C_PMU_SYS_CTL0_WALL_WK_EN BIT(14)
> +#define ATC2603C_PMU_SYS_CTL0_USB_WK_EN BIT(15)
> +#define ATC2603C_PMU_SYS_CTL0_WK_ALL (GENMASK(15, 5) & (~BIT(10)))
> +
> +/* PMU_SYS_CTL1 Register Mask Bits */
> +#define ATC2603C_PMU_SYS_CTL1_EN_S1 BIT(0)
> +#define ATC2603C_PMU_SYS_CTL1_LB_S4_EN BIT(2)
> +#define ATC2603C_PMU_SYS_CTL1_LB_S4 GENMASK(4, 3)
> +#define ATC2603C_PMU_SYS_CTL1_LB_S4_3_1V BIT(4)
> +#define ATC2603C_PMU_SYS_CTL1_IR_WK_FLAG BIT(5)
> +#define ATC2603C_PMU_SYS_CTL1_RESET_WK_FLAG BIT(6)
> +#define ATC2603C_PMU_SYS_CTL1_HDSW_WK_FLAG BIT(7)
> +#define ATC2603C_PMU_SYS_CTL1_ALARM_WK_FLAG BIT(8)
> +#define ATC2603C_PMU_SYS_CTL1_REM_CON_WK_FLAG BIT(9)
> +#define ATC2603C_PMU_SYS_CTL1_ONOFF_PRESS_RESET_IRQ_PD BIT(10)
> +#define ATC2603C_PMU_SYS_CTL1_SGPIOIRQ_WK_FLAG BIT(11)
> +#define ATC2603C_PMU_SYS_CTL1_ONOFF_SHORT_WK_FLAG BIT(12)
> +#define ATC2603C_PMU_SYS_CTL1_ONOFF_LONG_WK_FLAG BIT(13)
> +#define ATC2603C_PMU_SYS_CTL1_WALL_WK_FLAG BIT(14)
> +#define ATC2603C_PMU_SYS_CTL1_USB_WK_FLAG BIT(15)
> +
> +/* PMU_SYS_CTL2 Register Mask Bits */
> +#define ATC2603C_PMU_SYS_CTL2_PMU_A_EN BIT(0)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_INT_EN BIT(1)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_PD BIT(2)
> +#define ATC2603C_PMU_SYS_CTL2_S2TIMER GENMASK(5, 3)
> +#define ATC2603C_PMU_SYS_CTL2_S2_TIMER_EN BIT(6)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL GENMASK(8, 7)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_RESET_EN BIT(9)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS_TIME GENMASK(11, 10)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_INT_EN BIT(12)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_LONG_PRESS BIT(13)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_SHORT_PRESS BIT(14)
> +#define ATC2603C_PMU_SYS_CTL2_ONOFF_PRESS BIT(15)
> +
> +/* PMU_SYS_CTL3 Register Mask Bits */
> +#define ATC2603C_PMU_SYS_CTL3_S2S3TOS1_TIMER GENMASK(8, 7)
> +#define ATC2603C_PMU_SYS_CTL3_S2S3TOS1_TIMER_EN BIT(9)
> +#define ATC2603C_PMU_SYS_CTL3_S3_TIMER GENMASK(12, 10)
> +#define ATC2603C_PMU_SYS_CTL3_S3_TIMER_EN BIT(13)
> +#define ATC2603C_PMU_SYS_CTL3_EN_S3 BIT(14)
> +#define ATC2603C_PMU_SYS_CTL3_EN_S2 BIT(15)
> +
> +/* PMU_SYS_CTL5 Register Mask Bits */
> +#define ATC2603C_PMU_SYS_CTL5_WALLWKDTEN BIT(7)
> +#define ATC2603C_PMU_SYS_CTL5_VBUSWKDTEN BIT(8)
> +#define ATC2603C_PMU_SYS_CTL5_REMCON_DECT_EN BIT(9)
> +#define ATC2603C_PMU_SYS_CTL5_ONOFF_8S_SEL BIT(10)
> +
> +/* INTS_MSK Register Mask Bits */
> +#define ATC2603C_INTS_MSK_AUDIO BIT(0)
> +#define ATC2603C_INTS_MSK_OV BIT(1)
> +#define ATC2603C_INTS_MSK_OC BIT(2)
> +#define ATC2603C_INTS_MSK_OT BIT(3)
> +#define ATC2603C_INTS_MSK_UV BIT(4)
> +#define ATC2603C_INTS_MSK_ALARM BIT(5)
> +#define ATC2603C_INTS_MSK_ONOFF BIT(6)
> +#define ATC2603C_INTS_MSK_SGPIO BIT(7)
> +#define ATC2603C_INTS_MSK_IR BIT(8)
> +#define ATC2603C_INTS_MSK_REMCON BIT(9)
> +#define ATC2603C_INTS_MSK_POWERIN BIT(10)
> +
> +/* CMU_DEVRST Register Mask Bits */
> +#define ATC2603C_CMU_DEVRST_MFP BIT(1)
> +#define ATC2603C_CMU_DEVRST_INTS BIT(2)
> +#define ATC2603C_CMU_DEVRST_AUDIO BIT(4)
> +
> +/* PAD_EN Register Mask Bits */
> +#define ATC2603C_PAD_EN_EXTIRQ BIT(0)
> +
> +#endif /* __LINUX_MFD_ATC260X_ATC2603C_H */
> diff --git a/include/linux/mfd/atc260x/atc2609a.h b/include/linux/mfd/atc260x/atc2609a.h
> new file mode 100644
> index 000000000000..b957d7bd73e9
> --- /dev/null
> +++ b/include/linux/mfd/atc260x/atc2609a.h
> @@ -0,0 +1,308 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * ATC2609A PMIC register definitions
> + *
> + * Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>
> + */
> +
> +#ifndef __LINUX_MFD_ATC260X_ATC2609A_H
> +#define __LINUX_MFD_ATC260X_ATC2609A_H
> +
> +enum atc2609a_irq_def {
> + ATC2609A_IRQ_AUDIO = 0,
> + ATC2609A_IRQ_OV,
> + ATC2609A_IRQ_OC,
> + ATC2609A_IRQ_OT,
> + ATC2609A_IRQ_UV,
> + ATC2609A_IRQ_ALARM,
> + ATC2609A_IRQ_ONOFF,
> + ATC2609A_IRQ_WKUP,
> + ATC2609A_IRQ_IR,
> + ATC2609A_IRQ_REMCON,
> + ATC2609A_IRQ_POWER_IN,
> +};
> +
> +/* PMU Registers */
> +#define ATC2609A_PMU_SYS_CTL0 0x00
> +#define ATC2609A_PMU_SYS_CTL1 0x01
> +#define ATC2609A_PMU_SYS_CTL2 0x02
> +#define ATC2609A_PMU_SYS_CTL3 0x03
> +#define ATC2609A_PMU_SYS_CTL4 0x04
> +#define ATC2609A_PMU_SYS_CTL5 0x05
> +#define ATC2609A_PMU_SYS_CTL6 0x06
> +#define ATC2609A_PMU_SYS_CTL7 0x07
> +#define ATC2609A_PMU_SYS_CTL8 0x08
> +#define ATC2609A_PMU_SYS_CTL9 0x09
> +#define ATC2609A_PMU_BAT_CTL0 0x0A
> +#define ATC2609A_PMU_BAT_CTL1 0x0B
> +#define ATC2609A_PMU_VBUS_CTL0 0x0C
> +#define ATC2609A_PMU_VBUS_CTL1 0x0D
> +#define ATC2609A_PMU_WALL_CTL0 0x0E
> +#define ATC2609A_PMU_WALL_CTL1 0x0F
> +#define ATC2609A_PMU_SYS_PENDING 0x10
> +#define ATC2609A_PMU_APDS_CTL0 0x11
> +#define ATC2609A_PMU_APDS_CTL1 0x12
> +#define ATC2609A_PMU_APDS_CTL2 0x13
> +#define ATC2609A_PMU_CHARGER_CTL 0x14
> +#define ATC2609A_PMU_BAKCHARGER_CTL 0x15
> +#define ATC2609A_PMU_SWCHG_CTL0 0x16
> +#define ATC2609A_PMU_SWCHG_CTL1 0x17
> +#define ATC2609A_PMU_SWCHG_CTL2 0x18
> +#define ATC2609A_PMU_SWCHG_CTL3 0x19
> +#define ATC2609A_PMU_SWCHG_CTL4 0x1A
> +#define ATC2609A_PMU_DC_OSC 0x1B
> +#define ATC2609A_PMU_DC0_CTL0 0x1C
> +#define ATC2609A_PMU_DC0_CTL1 0x1D
> +#define ATC2609A_PMU_DC0_CTL2 0x1E
> +#define ATC2609A_PMU_DC0_CTL3 0x1F
> +#define ATC2609A_PMU_DC0_CTL4 0x20
> +#define ATC2609A_PMU_DC0_CTL5 0x21
> +#define ATC2609A_PMU_DC0_CTL6 0x22
> +#define ATC2609A_PMU_DC1_CTL0 0x23
> +#define ATC2609A_PMU_DC1_CTL1 0x24
> +#define ATC2609A_PMU_DC1_CTL2 0x25
> +#define ATC2609A_PMU_DC1_CTL3 0x26
> +#define ATC2609A_PMU_DC1_CTL4 0x27
> +#define ATC2609A_PMU_DC1_CTL5 0x28
> +#define ATC2609A_PMU_DC1_CTL6 0x29
> +#define ATC2609A_PMU_DC2_CTL0 0x2A
> +#define ATC2609A_PMU_DC2_CTL1 0x2B
> +#define ATC2609A_PMU_DC2_CTL2 0x2C
> +#define ATC2609A_PMU_DC2_CTL3 0x2D
> +#define ATC2609A_PMU_DC2_CTL4 0x2E
> +#define ATC2609A_PMU_DC2_CTL5 0x2F
> +#define ATC2609A_PMU_DC2_CTL6 0x30
> +#define ATC2609A_PMU_DC3_CTL0 0x31
> +#define ATC2609A_PMU_DC3_CTL1 0x32
> +#define ATC2609A_PMU_DC3_CTL2 0x33
> +#define ATC2609A_PMU_DC3_CTL3 0x34
> +#define ATC2609A_PMU_DC3_CTL4 0x35
> +#define ATC2609A_PMU_DC3_CTL5 0x36
> +#define ATC2609A_PMU_DC3_CTL6 0x37
> +#define ATC2609A_PMU_DC_ZR 0x38
> +#define ATC2609A_PMU_LDO0_CTL0 0x39
> +#define ATC2609A_PMU_LDO0_CTL1 0x3A
> +#define ATC2609A_PMU_LDO1_CTL0 0x3B
> +#define ATC2609A_PMU_LDO1_CTL1 0x3C
> +#define ATC2609A_PMU_LDO2_CTL0 0x3D
> +#define ATC2609A_PMU_LDO2_CTL1 0x3E
> +#define ATC2609A_PMU_LDO3_CTL0 0x3F
> +#define ATC2609A_PMU_LDO3_CTL1 0x40
> +#define ATC2609A_PMU_LDO4_CTL0 0x41
> +#define ATC2609A_PMU_LDO4_CTL1 0x42
> +#define ATC2609A_PMU_LDO5_CTL0 0x43
> +#define ATC2609A_PMU_LDO5_CTL1 0x44
> +#define ATC2609A_PMU_LDO6_CTL0 0x45
> +#define ATC2609A_PMU_LDO6_CTL1 0x46
> +#define ATC2609A_PMU_LDO7_CTL0 0x47
> +#define ATC2609A_PMU_LDO7_CTL1 0x48
> +#define ATC2609A_PMU_LDO8_CTL0 0x49
> +#define ATC2609A_PMU_LDO8_CTL1 0x4A
> +#define ATC2609A_PMU_LDO9_CTL 0x4B
> +#define ATC2609A_PMU_OV_INT_EN 0x4C
> +#define ATC2609A_PMU_OV_STATUS 0x4D
> +#define ATC2609A_PMU_UV_INT_EN 0x4E
> +#define ATC2609A_PMU_UV_STATUS 0x4F
> +#define ATC2609A_PMU_OC_INT_EN 0x50
> +#define ATC2609A_PMU_OC_STATUS 0x51
> +#define ATC2609A_PMU_OT_CTL 0x52
> +#define ATC2609A_PMU_CM_CTL0 0x53
> +#define ATC2609A_PMU_FW_USE0 0x54
> +#define ATC2609A_PMU_FW_USE1 0x55
> +#define ATC2609A_PMU_ADC12B_I 0x56
> +#define ATC2609A_PMU_ADC12B_V 0x57
> +#define ATC2609A_PMU_ADC12B_DUMMY 0x58
> +#define ATC2609A_PMU_AUXADC_CTL0 0x59
> +#define ATC2609A_PMU_AUXADC_CTL1 0x5A
> +#define ATC2609A_PMU_BATVADC 0x5B
> +#define ATC2609A_PMU_BATIADC 0x5C
> +#define ATC2609A_PMU_WALLVADC 0x5D
> +#define ATC2609A_PMU_WALLIADC 0x5E
> +#define ATC2609A_PMU_VBUSVADC 0x5F
> +#define ATC2609A_PMU_VBUSIADC 0x60
> +#define ATC2609A_PMU_SYSPWRADC 0x61
> +#define ATC2609A_PMU_REMCONADC 0x62
> +#define ATC2609A_PMU_SVCCADC 0x63
> +#define ATC2609A_PMU_CHGIADC 0x64
> +#define ATC2609A_PMU_IREFADC 0x65
> +#define ATC2609A_PMU_BAKBATADC 0x66
> +#define ATC2609A_PMU_ICTEMPADC 0x67
> +#define ATC2609A_PMU_AUXADC0 0x68
> +#define ATC2609A_PMU_AUXADC1 0x69
> +#define ATC2609A_PMU_AUXADC2 0x6A
> +#define ATC2609A_PMU_AUXADC3 0x6B
> +#define ATC2609A_PMU_ICTEMPADC_ADJ 0x6C
> +#define ATC2609A_PMU_BDG_CTL 0x6D
> +#define ATC2609A_RTC_CTL 0x6E
> +#define ATC2609A_RTC_MSALM 0x6F
> +#define ATC2609A_RTC_HALM 0x70
> +#define ATC2609A_RTC_YMDALM 0x71
> +#define ATC2609A_RTC_MS 0x72
> +#define ATC2609A_RTC_H 0x73
> +#define ATC2609A_RTC_DC 0x74
> +#define ATC2609A_RTC_YMD 0x75
> +#define ATC2609A_EFUSE_DAT 0x76
> +#define ATC2609A_EFUSECRTL1 0x77
> +#define ATC2609A_EFUSECRTL2 0x78
> +#define ATC2609A_PMU_DC4_CTL0 0x79
> +#define ATC2609A_PMU_DC4_CTL1 0x7A
> +#define ATC2609A_PMU_DC4_CTL2 0x7B
> +#define ATC2609A_PMU_DC4_CTL3 0x7C
> +#define ATC2609A_PMU_DC4_CTL4 0x7D
> +#define ATC2609A_PMU_DC4_CTL5 0x7E
> +#define ATC2609A_PMU_DC4_CTL6 0x7F
> +#define ATC2609A_PMU_PWR_STATUS 0x80
> +#define ATC2609A_PMU_S2_PWR 0x81
> +#define ATC2609A_CLMT_CTL0 0x82
> +#define ATC2609A_CLMT_DATA0 0x83
> +#define ATC2609A_CLMT_DATA1 0x84
> +#define ATC2609A_CLMT_DATA2 0x85
> +#define ATC2609A_CLMT_DATA3 0x86
> +#define ATC2609A_CLMT_ADD0 0x87
> +#define ATC2609A_CLMT_ADD1 0x88
> +#define ATC2609A_CLMT_OCV_TABLE 0x89
> +#define ATC2609A_CLMT_R_TABLE 0x8A
> +#define ATC2609A_PMU_PWRON_CTL0 0x8D
> +#define ATC2609A_PMU_PWRON_CTL1 0x8E
> +#define ATC2609A_PMU_PWRON_CTL2 0x8F
> +#define ATC2609A_IRC_CTL 0x90
> +#define ATC2609A_IRC_STAT 0x91
> +#define ATC2609A_IRC_CC 0x92
> +#define ATC2609A_IRC_KDC 0x93
> +#define ATC2609A_IRC_WK 0x94
> +#define ATC2609A_IRC_RCC 0x95
> +
> +/* AUDIO_OUT Registers */
> +#define ATC2609A_AUDIOINOUT_CTL 0xA0
> +#define ATC2609A_AUDIO_DEBUGOUTCTL 0xA1
> +#define ATC2609A_DAC_DIGITALCTL 0xA2
> +#define ATC2609A_DAC_VOLUMECTL0 0xA3
> +#define ATC2609A_DAC_ANALOG0 0xA4
> +#define ATC2609A_DAC_ANALOG1 0xA5
> +#define ATC2609A_DAC_ANALOG2 0xA6
> +#define ATC2609A_DAC_ANALOG3 0xA7
> +
> +/* AUDIO_IN Registers */
> +#define ATC2609A_ADC_DIGITALCTL 0xA8
> +#define ATC2609A_ADC_HPFCTL 0xA9
> +#define ATC2609A_ADC_CTL 0xAA
> +#define ATC2609A_AGC_CTL0 0xAB
> +#define ATC2609A_AGC_CTL1 0xAC
> +#define ATC2609A_AGC_CTL2 0xAD
> +#define ATC2609A_ADC_ANALOG0 0xAE
> +#define ATC2609A_ADC_ANALOG1 0xAF
> +
> +/* PCM_IF Registers */
> +#define ATC2609A_PCM0_CTL 0xB0
> +#define ATC2609A_PCM1_CTL 0xB1
> +#define ATC2609A_PCM2_CTL 0xB2
> +#define ATC2609A_PCMIF_CTL 0xB3
> +
> +/* CMU_CONTROL Registers */
> +#define ATC2609A_CMU_DEVRST 0xC1
> +
> +/* INTS Registers */
> +#define ATC2609A_INTS_PD 0xC8
> +#define ATC2609A_INTS_MSK 0xC9
> +
> +/* MFP Registers */
> +#define ATC2609A_MFP_CTL 0xD0
> +#define ATC2609A_PAD_VSEL 0xD1
> +#define ATC2609A_GPIO_OUTEN 0xD2
> +#define ATC2609A_GPIO_INEN 0xD3
> +#define ATC2609A_GPIO_DAT 0xD4
> +#define ATC2609A_PAD_DRV 0xD5
> +#define ATC2609A_PAD_EN 0xD6
> +#define ATC2609A_DEBUG_SEL 0xD7
> +#define ATC2609A_DEBUG_IE 0xD8
> +#define ATC2609A_DEBUG_OE 0xD9
> +#define ATC2609A_CHIP_VER 0xDC
> +
> +/* PWSI Registers */
> +#define ATC2609A_PWSI_CTL 0xF0
> +#define ATC2609A_PWSI_STATUS 0xF1
> +
> +/* TWSI Registers */
> +#define ATC2609A_SADDR 0xFF
> +
> +/* PMU_SYS_CTL0 Register Mask Bits */
> +#define ATC2609A_PMU_SYS_CTL0_IR_WK_EN BIT(5)
> +#define ATC2609A_PMU_SYS_CTL0_RESET_WK_EN BIT(6)
> +#define ATC2609A_PMU_SYS_CTL0_HDSW_WK_EN BIT(7)
> +#define ATC2609A_PMU_SYS_CTL0_ALARM_WK_EN BIT(8)
> +#define ATC2609A_PMU_SYS_CTL0_REM_CON_WK_EN BIT(9)
> +#define ATC2609A_PMU_SYS_CTL0_RESTART_EN BIT(10)
> +#define ATC2609A_PMU_SYS_CTL0_WKIRQ_WK_EN BIT(11)
> +#define ATC2609A_PMU_SYS_CTL0_ONOFF_SHORT_WK_EN BIT(12)
> +#define ATC2609A_PMU_SYS_CTL0_ONOFF_LONG_WK_EN BIT(13)
> +#define ATC2609A_PMU_SYS_CTL0_WALL_WK_EN BIT(14)
> +#define ATC2609A_PMU_SYS_CTL0_USB_WK_EN BIT(15)
> +#define ATC2609A_PMU_SYS_CTL0_WK_ALL (GENMASK(15, 5) & (~BIT(10)))
> +
> +/* PMU_SYS_CTL1 Register Mask Bits */
> +#define ATC2609A_PMU_SYS_CTL1_EN_S1 BIT(0)
> +#define ATC2609A_PMU_SYS_CTL1_LB_S4_EN BIT(2)
> +#define ATC2609A_PMU_SYS_CTL1_LB_S4 GENMASK(4, 3)
> +#define ATC2609A_PMU_SYS_CTL1_LB_S4_3_1V BIT(4)
> +#define ATC2609A_PMU_SYS_CTL1_IR_WK_FLAG BIT(5)
> +#define ATC2609A_PMU_SYS_CTL1_RESET_WK_FLAG BIT(6)
> +#define ATC2609A_PMU_SYS_CTL1_HDSW_WK_FLAG BIT(7)
> +#define ATC2609A_PMU_SYS_CTL1_ALARM_WK_FLAG BIT(8)
> +#define ATC2609A_PMU_SYS_CTL1_REM_CON_WK_FLAG BIT(9)
> +#define ATC2609A_PMU_SYS_CTL1_RESTART_WK_FLAG BIT(10)
> +#define ATC2609A_PMU_SYS_CTL1_WKIRQ_WK_FLAG BIT(11)
> +#define ATC2609A_PMU_SYS_CTL1_ONOFF_SHORT_WK_FLAG BIT(12)
> +#define ATC2609A_PMU_SYS_CTL1_ONOFF_LONG_WK_FLAG BIT(13)
> +#define ATC2609A_PMU_SYS_CTL1_WALL_WK_FLAG BIT(14)
> +#define ATC2609A_PMU_SYS_CTL1_USB_WK_FLAG BIT(15)
> +
> +/* PMU_SYS_CTL2 Register Mask Bits */
> +#define ATC2609A_PMU_SYS_CTL2_PMU_A_EN BIT(0)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_INT_EN BIT(1)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_PD BIT(2)
> +#define ATC2609A_PMU_SYS_CTL2_S2TIMER GENMASK(5, 3)
> +#define ATC2609A_PMU_SYS_CTL2_S2_TIMER_EN BIT(6)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_RESET_TIME_SEL GENMASK(8, 7)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_RESET_EN BIT(9)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS_TIME GENMASK(11, 10)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_LSP_INT_EN BIT(12)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_LONG_PRESS BIT(13)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_SHORT_PRESS BIT(14)
> +#define ATC2609A_PMU_SYS_CTL2_ONOFF_PRESS BIT(15)
> +
> +/* PMU_SYS_CTL3 Register Mask Bits */
> +#define ATC2609A_PMU_SYS_CTL3_S2S3TOS1_TIMER GENMASK(8, 7)
> +#define ATC2609A_PMU_SYS_CTL3_S2S3TOS1_TIMER_EN BIT(9)
> +#define ATC2609A_PMU_SYS_CTL3_S3_TIMER GENMASK(12, 10)
> +#define ATC2609A_PMU_SYS_CTL3_S3_TIMER_EN BIT(13)
> +#define ATC2609A_PMU_SYS_CTL3_EN_S3 BIT(14)
> +#define ATC2609A_PMU_SYS_CTL3_EN_S2 BIT(15)
> +
> +/* PMU_SYS_CTL5 Register Mask Bits */
> +#define ATC2609A_PMU_SYS_CTL5_WALLWKDTEN BIT(7)
> +#define ATC2609A_PMU_SYS_CTL5_VBUSWKDTEN BIT(8)
> +#define ATC2609A_PMU_SYS_CTL5_REMCON_DECT_EN BIT(9)
> +#define ATC2609A_PMU_SYS_CTL5_ONOFF_8S_SEL BIT(10)
> +
> +/* INTS_MSK Register Mask Bits */
> +#define ATC2609A_INTS_MSK_AUDIO BIT(0)
> +#define ATC2609A_INTS_MSK_OV BIT(1)
> +#define ATC2609A_INTS_MSK_OC BIT(2)
> +#define ATC2609A_INTS_MSK_OT BIT(3)
> +#define ATC2609A_INTS_MSK_UV BIT(4)
> +#define ATC2609A_INTS_MSK_ALARM BIT(5)
> +#define ATC2609A_INTS_MSK_ONOFF BIT(6)
> +#define ATC2609A_INTS_MSK_WKUP BIT(7)
> +#define ATC2609A_INTS_MSK_IR BIT(8)
> +#define ATC2609A_INTS_MSK_REMCON BIT(9)
> +#define ATC2609A_INTS_MSK_POWERIN BIT(10)
> +
> +/* CMU_DEVRST Register Mask Bits */
> +#define ATC2609A_CMU_DEVRST_AUDIO BIT(0)
> +#define ATC2609A_CMU_DEVRST_MFP BIT(1)
> +#define ATC2609A_CMU_DEVRST_INTS BIT(2)
> +
> +/* PAD_EN Register Mask Bits */
> +#define ATC2609A_PAD_EN_EXTIRQ BIT(0)
> +
> +#endif /* __LINUX_MFD_ATC260X_ATC2609A_H */
> diff --git a/include/linux/mfd/atc260x/core.h b/include/linux/mfd/atc260x/core.h
> new file mode 100644
> index 000000000000..a87b976f48e3
> --- /dev/null
> +++ b/include/linux/mfd/atc260x/core.h
> @@ -0,0 +1,86 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Core MFD defines for ATC260x PMICs
> + *
> + * Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx>
> + * Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@xxxxxxxxx>
> + */
> +
> +#ifndef __LINUX_MFD_ATC260X_CORE_H
> +#define __LINUX_MFD_ATC260X_CORE_H
> +
> +#include <linux/mfd/atc260x/atc2603c.h>
> +#include <linux/mfd/atc260x/atc2609a.h>
> +
> +enum atc260x_type {
> + ATC2603A = 0,
> + ATC2603C,
> + ATC2609A,
> +};
> +
> +enum atc260x_ver {
> + ATC260X_A = 0,
> + ATC260X_B,
> + ATC260X_C,
> + ATC260X_D,
> + ATC260X_E,
> + ATC260X_F,
> + ATC260X_G,
> + ATC260X_H,
> +};
> +
> +struct atc260x {
> + struct device *dev;
> +
> + struct regmap *regmap;
> + const struct regmap_irq_chip *regmap_irq_chip;
> + struct regmap_irq_chip_data *irq_data;
> +
> + struct mutex *regmap_mutex; /* mutex for custom regmap locking */
> +
> + const struct mfd_cell *cells;
> + int nr_cells;
> + int irq;
> +
> + enum atc260x_type ic_type;
> + enum atc260x_ver ic_ver;
> + const char *type_name;
> + unsigned int rev_reg;
> +
> + int (*dev_init)(struct atc260x *atc260x);
> +};
> +
> +struct regmap_config;
> +
> +/**
> + * atc260x_match_device(): Setup atc260x variant related fields
> + *
> + * @atc260x: atc260x device to setup (.dev field must be set)
> + * @regmap_cfg: regmap config associated with this atc260x device
> + *
> + * This lets the atc260x core configure the mfd cells and register maps

Please capitalise abbreviations and model names:

"MFD"
"ATC260x"
"IRQChip"
"IRQ"

> + * for later use.
> + */
> +int atc260x_match_device(struct atc260x *atc260x, struct regmap_config *regmap_cfg);
> +
> +/**
> + * atc260x_device_probe(): Probe a configured atc260x device
> + *
> + * @atc260x: atc260x device to probe (must be configured)
> + *
> + * This function lets the atc260x core register the atc260x mfd devices
> + * and irqchip. The atc260x device passed in must be fully configured
> + * with atc260x_match_device, its irq set, and regmap created.
> + */
> +int atc260x_device_probe(struct atc260x *atc260x);
> +
> +/**
> + * atc260x_device_remove(): Remove a atc260x device

"an"

> + *
> + * @atc260x: atc260x device to remove
> + *
> + * This tells the atc260x core to remove the associated mfd devices
> + */
> +int atc260x_device_remove(struct atc260x *atc260x);

Not sure I've seen kerneldoc used on prototypes before.

Probably better to move them onto the real functions.

> +#endif /* __LINUX_MFD_ATC260X_CORE_H */

--
Lee Jones [李琼斯]
Senior Technical Lead - Developer Services
Linaro.org │ Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog