mbox series

[v3,00/32] Samsung S2MPG10 PMIC MFD-based drivers

Message ID 20250403-s2mpg10-v3-0-b542b3505e68@linaro.org
Headers show
Series Samsung S2MPG10 PMIC MFD-based drivers | expand

Message

André Draszik April 3, 2025, 8:58 a.m. UTC
This series adds initial support for the Samsung S2MPG10 PMIC using the
MFD framework. This is a PMIC for mobile applications and is used on
the Google Pixel 6 and 6 Pro (oriole / raven).

*** dependency note ***

To compile, this depends on the Samsung ACPM driver in Linux next with
the following additional patches:
https://lore.kernel.org/all/20250324-acpm-atomic-v2-0-7d87746e1765@linaro.org/
https://lore.kernel.org/all/20250319-acpm-fixes-v2-0-ac2c1bcf322b@linaro.org/
https://lore.kernel.org/all/20250327-acpm-children-v1-0-0afe15ee2ff7@linaro.org/

*** dependency note end ***

+++ Kconfig update +++

There is a Kconfig symbol update in this series, because the existing
Samsung S2M driver has been split into core and transport (I2C & ACPM)
parts. CONFIG_MFD_SEC_CORE is now truly a core driver, and
the I2C code that was part of it is now enabled via CONFIG_MFD_SEC_I2C.

This was necessary because unlike the other S2M PMICs, S2MPG10 doesn't
talk via I2C, but via the Samsung ACPM firmware.

+++ Kconfig update end +++

This series must be applied in-order, due to interdependencies of some
of the patches. There are also various cleanup patches to the S2M
drivers. I've kept them ordered as:
  * DT bindings (patches 1 ... 3)
  * s2m mfd prep for adding S2MPG10 support (patches 4 ... 7)
  * split S2M mfd driver into s2m-core and s2m-i2c, including the
    kconfig symbol update (patch 8)
  * S2MPG10 core driver (patch 9)
  * s2m mfd driver cleanup patches (patches 10 ... 23)
  * S2MPG10 clock driver (patch 24)
  * s2m RTC prep for adding S2MPG10 (patch 25 ... 26)
  * S2MPG10 RTC driver (patch 27)
  * s2m RTC cleanup patches (patches 28 ... 31)

I realise these are many, but since some prep-work was required to be
able to add S2MPG anyway, I wanted to get the cleanup patches in as
well :-) Let me know if I should postpone them to a later date instead.

The S2MPG10 includes buck converters, various LDOs, power meters, RTC,
clock outputs, and additional GPIOs interfaces.

This series adds support in the top-level device driver, and for the
RTC and clock. Importantly, having the RTC driver allows to do a proper
reset of the system. Drivers or driver updates for the other components
will be added in future patches.

This will need a DT update for Oriole / Raven to enable this device. I
will send that out separately.

Cheers,
Andre'

Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
Changes in v3:
- Krzysztof:
  - keep 'regulators' subnode required even for s2mpg10
  - drop '$ref' and 'unevaluatedProperties' from pmic subnode, use
    'additionalProperties' instead
  - add some regulators to examples since s2mpg10 requires them as of
    v3
- sec-acpm:
  - use an enum for struct sec_acpm_bus_context::type
  - consistent name space for all functions sec_pmic_acpm_... to be
    similar to i2c and consistent in this file
- Link to v2: https://lore.kernel.org/r/20250328-s2mpg10-v2-0-b54dee33fb6b@linaro.org

Changes in v2:
- Rob:
  - make PMIC node a child of ACPM, and all related changes (binding,
    driver)
- Krzysztof:
  - merge defconfig updates into patch changing the symbols (patch 8)
  - split MODULE_AUTHOR update into a separate patch
  - better alignment fix (patch 11)
  - merge two s2dos05/s2mpu05 related patches into one (patch 14)
- myself:
  - keep PMIC DT parsing in core, not in transport driver
  - several updates in sec-acpm.c, see separate entries in patch 9
  - fix typo in patch 17
  - collect tags
- Link to v1: https://lore.kernel.org/r/20250323-s2mpg10-v1-0-d08943702707@linaro.org

---
André Draszik (32):
      dt-bindings: mfd: samsung,s2mps11: add s2mpg10
      dt-bindings: clock: samsung,s2mps11: add s2mpg10
      dt-bindings: firmware: google,gs101-acpm-ipc: add PMIC child node
      mfd: sec: drop non-existing forward declarations
      mfd: sec: sort includes alphabetically
      mfd: sec: update includes to add missing and remove superfluous ones
      mfd: sec: move private internal API to internal header
      mfd: sec: split into core and transport (i2c) drivers
      mfd: sec: add support for S2MPG10 PMIC
      mfd: sec: merge separate core and irq modules
      mfd: sec: fix open parenthesis alignment (multiple)
      mfd: sec: sort struct of_device_id entries and the device type switch
      mfd: sec: use dev_err_probe() where appropriate
      mfd: sec: s2dos05/s2mpu05: use explicit regmap config and drop default
      mfd: sec: s2dos05: doesn't support interrupts (it seems)
      mfd: sec: don't ignore errors from sec_irq_init()
      mfd: sec: rework platform data and regmap instantiating
      mfd: sec: change device_type to int
      mfd: sec: don't compare against NULL / 0 for errors, use !
      mfd: sec: use sizeof(*var), not sizeof(struct type_of_var)
      mfd: sec: convert to using MFD_CELL macros
      mfd: sec: convert to using REGMAP_IRQ_REG() macros
      mfd: sec: add myself as module author
      clk: s2mps11: add support for S2MPG10 PMIC clock
      rtc: s5m: cache value of platform_get_device_id() during probe
      rtc: s5m: prepare for external regmap
      rtc: s5m: add support for S2MPG10 RTC
      rtc: s5m: fix a typo: peding -> pending
      rtc: s5m: switch to devm_device_init_wakeup
      rtc: s5m: replace regmap_update_bits with regmap_clear/set_bits
      rtc: s5m: replace open-coded read/modify/write registers with regmap helpers
      MAINTAINERS: add myself as reviewer for Samsung S2M MFD

 .../devicetree/bindings/clock/samsung,s2mps11.yaml |   1 +
 .../bindings/firmware/google,gs101-acpm-ipc.yaml   |  35 ++
 .../devicetree/bindings/mfd/samsung,s2mps11.yaml   |  26 +-
 MAINTAINERS                                        |   3 +-
 arch/arm/configs/exynos_defconfig                  |   2 +-
 arch/arm/configs/multi_v7_defconfig                |   2 +-
 arch/arm/configs/pxa_defconfig                     |   2 +-
 arch/arm64/configs/defconfig                       |   2 +-
 drivers/clk/clk-s2mps11.c                          |   8 +
 drivers/mfd/Kconfig                                |  35 +-
 drivers/mfd/Makefile                               |   5 +-
 drivers/mfd/sec-acpm.c                             | 465 ++++++++++++++++++++
 drivers/mfd/sec-common.c                           | 301 +++++++++++++
 drivers/mfd/sec-core.c                             | 481 ---------------------
 drivers/mfd/sec-core.h                             |  23 +
 drivers/mfd/sec-i2c.c                              | 239 ++++++++++
 drivers/mfd/sec-irq.c                              | 460 +++++++-------------
 drivers/rtc/rtc-s5m.c                              | 197 ++++++---
 include/linux/mfd/samsung/core.h                   |   7 +-
 include/linux/mfd/samsung/irq.h                    | 103 +++++
 include/linux/mfd/samsung/rtc.h                    |  37 ++
 include/linux/mfd/samsung/s2mpg10.h                | 454 +++++++++++++++++++
 22 files changed, 2024 insertions(+), 864 deletions(-)
---
base-commit: f58dd835f82a5dda6c9d3895ee6f15016431fb1f
change-id: 20250321-s2mpg10-ef5d1ebd3043

Best regards,

Comments

Lee Jones April 4, 2025, 9:18 a.m. UTC | #1
On Thu, 03 Apr 2025, André Draszik wrote:

> Add support for Samsung's S2MPG10 PMIC, which is a Power Management IC
> for mobile applications with buck converters, various LDOs, power
> meters, RTC, clock outputs, and additional GPIOs interfaces.
> 
> Contrary to existing Samsung S2M series PMICs supported, communication
> is not via I2C, but via the Samsung ACPM firmware.
> 
> This commit adds the core driver.
> 
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> 
> ---
> Checkpatch suggests to update MAINTAINERS, but the new file is covered
> already due to using a wildcard.
> 
> v3:
> * use an enum for struct sec_acpm_bus_context::type
> * consistent name space for all functions sec_pmic_acpm_... to be
>   similar to i2c and consistent in this file
> 
> v2:
> * update to using devm_acpm_get_by_node() instead of
>   devm_acpm_get_by_phandle() as this is now expected to be a child of
>   the ACPM node
> * use c-type file header
> * updates to error messages
> * drop s2mpg10_rtc_wr_table as everything in RTC is writeable
> * rename s2mpg10_volatile_registers -> s2mpg10_rtc_volatile_registers
> * fix incorrect regmap range in common block
> * add comments to regmap ranges
> * add all registers to header for all IP blocks
> ---
>  drivers/mfd/Kconfig                 |  17 ++
>  drivers/mfd/Makefile                |   1 +
>  drivers/mfd/sec-acpm.c              | 465 ++++++++++++++++++++++++++++++++++++
>  drivers/mfd/sec-core.c              |  16 ++
>  drivers/mfd/sec-irq.c               |  68 ++++++
>  include/linux/mfd/samsung/core.h    |   1 +
>  include/linux/mfd/samsung/irq.h     | 103 ++++++++
>  include/linux/mfd/samsung/rtc.h     |  37 +++
>  include/linux/mfd/samsung/s2mpg10.h | 454 +++++++++++++++++++++++++++++++++++
>  9 files changed, 1162 insertions(+)
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 62565dc89ec6d58611bbc1f31c65f757343b6453..e146b28240e731557f34ebe6dea99016b6d19f6b 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1296,6 +1296,23 @@ config MFD_SEC_CORE
>  	select MFD_CORE
>  	select REGMAP_IRQ
>  
> +config MFD_SEC_ACPM
> +	tristate "Samsung Electronics S2MPG1x PMICs"
> +	depends on EXYNOS_ACPM_PROTOCOL
> +	depends on OF
> +	select MFD_SEC_CORE
> +	help
> +	  Support for the Samsung Electronics PMICs with ACPM interface.
> +	  This is a Power Management IC for mobile applications with buck
> +	  converters, various LDOs, power meters, RTC, clock outputs, and
> +	  additional GPIOs interfaces.
> +	  This driver provides common support for accessing the device;
> +	  additional drivers must be enabled in order to use the functionality
> +	  of the device.
> +
> +	  To compile this driver as a module, choose M here: the module will be
> +	  called sec-acpm.
> +
>  config MFD_SEC_I2C
>  	tristate "Samsung Electronics S2MPA/S2MPS1X/S2MPU/S5M series PMICs"
>  	depends on I2C=y
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index ab6c4b17a391946d4c88f52ccbfee5424b4fb2d2..b617782eca436e34084a9cd24c309801c5680390 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -229,6 +229,7 @@ obj-$(CONFIG_MFD_RK8XX_I2C)	+= rk8xx-i2c.o
>  obj-$(CONFIG_MFD_RK8XX_SPI)	+= rk8xx-spi.o
>  obj-$(CONFIG_MFD_RN5T618)	+= rn5t618.o
>  obj-$(CONFIG_MFD_SEC_CORE)	+= sec-core.o sec-irq.o
> +obj-$(CONFIG_MFD_SEC_ACPM)	+= sec-acpm.o
>  obj-$(CONFIG_MFD_SEC_I2C)	+= sec-i2c.o
>  obj-$(CONFIG_MFD_SYSCON)	+= syscon.o
>  obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
> diff --git a/drivers/mfd/sec-acpm.c b/drivers/mfd/sec-acpm.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..39dbb968086ac835b96ed3e4efa68868fda63429
> --- /dev/null
> +++ b/drivers/mfd/sec-acpm.c
> @@ -0,0 +1,465 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright 2020 Google Inc
> + * Copyright 2025 Linaro Ltd.
> + *
> + * Samsung S2MPG1x ACPM driver
> + */
> +
> +#include <linux/array_size.h>
> +#include <linux/device.h>
> +#include <linux/firmware/samsung/exynos-acpm-protocol.h>
> +#include <linux/mfd/samsung/core.h>
> +#include <linux/mfd/samsung/rtc.h>
> +#include <linux/mfd/samsung/s2mpg10.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm.h>
> +#include <linux/property.h>
> +#include <linux/regmap.h>
> +#include "sec-core.h"
> +
> +#define ACPM_MAX_BULK_DATA   8
> +
> +struct sec_pmic_acpm_platform_data {

This isn't platform data.  It's driver data.

Platform data is passed in, driver data is derived.

See how the other drivers do this:

  $ git grep ddata -- drivers/mfd

> +	int device_type;
> +
> +	unsigned int acpm_chan_id;
> +	u8 speedy_channel;
> +
> +	const struct regmap_config *regmap_cfg_common;
> +	const struct regmap_config *regmap_cfg_pmic;
> +	const struct regmap_config *regmap_cfg_rtc;
> +	const struct regmap_config *regmap_cfg_meter;
> +};
> +
> +static const struct regmap_range s2mpg10_common_registers[] = {
> +	regmap_reg_range(0x00, 0x02), /* CHIP_ID_M, INT, INT_MASK */
> +	regmap_reg_range(0x0a, 0x0c), /* speedy control */
> +	regmap_reg_range(0x1a, 0x2a), /* debug */

Nit: I like comments to start with an upper-case char.

> +};
> +
> +static const struct regmap_range s2mpg10_common_ro_registers[] = {
> +	regmap_reg_range(0x00, 0x01),
> +	regmap_reg_range(0x28, 0x2a),

Why describe some, but not all ranges?

> +};
> +
> +static const struct regmap_range s2mpg10_common_nonvolatile_registers[] = {
> +	regmap_reg_range(0x00, 0x00),
> +	regmap_reg_range(0x02, 0x02),
> +	regmap_reg_range(0x0a, 0x0c),
> +};
> +
> +static const struct regmap_range s2mpg10_common_precious_registers[] = {
> +	regmap_reg_range(0x01, 0x01),
> +};
> +
> +static const struct regmap_access_table s2mpg10_common_wr_table = {
> +	.yes_ranges = s2mpg10_common_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers),
> +	.no_ranges = s2mpg10_common_ro_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg10_common_ro_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_common_rd_table = {
> +	.yes_ranges = s2mpg10_common_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_common_volatile_table = {
> +	.no_ranges = s2mpg10_common_nonvolatile_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg10_common_nonvolatile_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_common_precious_table = {
> +	.yes_ranges = s2mpg10_common_precious_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_precious_registers),
> +};
> +
> +static const struct regmap_config s2mpg10_regmap_config_common = {
> +	.name = "common",
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = S2MPG10_COMMON_SPD_DEBUG4,
> +	.wr_table = &s2mpg10_common_wr_table,
> +	.rd_table = &s2mpg10_common_rd_table,
> +	.volatile_table = &s2mpg10_common_volatile_table,
> +	.precious_table = &s2mpg10_common_precious_table,
> +	.num_reg_defaults_raw = S2MPG10_COMMON_SPD_DEBUG4 + 1,
> +	.cache_type = REGCACHE_FLAT,
> +};
> +
> +static const struct regmap_range s2mpg10_pmic_registers[] = {
> +	regmap_reg_range(0x00, 0xf6),
> +};
> +
> +static const struct regmap_range s2mpg10_pmic_ro_registers[] = {
> +	regmap_reg_range(0x00, 0x05), /* INTx */
> +	regmap_reg_range(0x0c, 0x0f), /* STATUSx PWRONSRC OFFSRC */
> +	regmap_reg_range(0xc7, 0xc7), /* GPIO input */
> +};
> +
> +static const struct regmap_range s2mpg10_pmic_nonvolatile_registers[] = {
> +	regmap_reg_range(0x06, 0x0b), /* INTxM */
> +};
> +
> +static const struct regmap_range s2mpg10_pmic_precious_registers[] = {
> +	regmap_reg_range(0x00, 0x05), /* INTx */
> +};
> +
> +static const struct regmap_access_table s2mpg10_pmic_wr_table = {
> +	.yes_ranges = s2mpg10_pmic_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers),
> +	.no_ranges = s2mpg10_pmic_ro_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_ro_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_pmic_rd_table = {
> +	.yes_ranges = s2mpg10_pmic_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_pmic_volatile_table = {
> +	.no_ranges = s2mpg10_pmic_nonvolatile_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_nonvolatile_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_pmic_precious_table = {
> +	.yes_ranges = s2mpg10_pmic_precious_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_precious_registers),
> +};
> +
> +static const struct regmap_config s2mpg10_regmap_config_pmic = {
> +	.name = "pmic",
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = S2MPG10_PMIC_LDO_SENSE4,
> +	.wr_table = &s2mpg10_pmic_wr_table,
> +	.rd_table = &s2mpg10_pmic_rd_table,
> +	.volatile_table = &s2mpg10_pmic_volatile_table,
> +	.precious_table = &s2mpg10_pmic_precious_table,
> +	.num_reg_defaults_raw = S2MPG10_PMIC_LDO_SENSE4 + 1,
> +	.cache_type = REGCACHE_FLAT,
> +};
> +
> +static const struct regmap_range s2mpg10_rtc_registers[] = {
> +	regmap_reg_range(0x00, 0x2b), /* RTC */
> +};
> +
> +static const struct regmap_range s2mpg10_rtc_volatile_registers[] = {
> +	regmap_reg_range(0x01, 0x01), /* RTC_UPDATE */
> +	regmap_reg_range(0x05, 0x0c), /* time / date */
> +};
> +
> +static const struct regmap_access_table s2mpg10_rtc_rd_table = {
> +	.yes_ranges = s2mpg10_rtc_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_rtc_volatile_table = {
> +	.yes_ranges = s2mpg10_rtc_volatile_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_volatile_registers),
> +};
> +
> +static const struct regmap_config s2mpg10_regmap_config_rtc = {
> +	.name = "rtc",
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.reg_stride = 1,
> +	.max_register = S2MPG10_RTC_OSC_CTRL,
> +	.rd_table = &s2mpg10_rtc_rd_table,
> +	.volatile_table = &s2mpg10_rtc_volatile_table,
> +	.num_reg_defaults_raw = S2MPG10_RTC_OSC_CTRL + 1,
> +	.cache_type = REGCACHE_FLAT,
> +};
> +
> +static const struct regmap_range s2mpg10_meter_registers[] = {
> +	regmap_reg_range(0x00, 0x21), /* meter config */
> +	regmap_reg_range(0x40, 0x8a), /* meter data */
> +	regmap_reg_range(0xee, 0xee), /* offset */
> +	regmap_reg_range(0xf1, 0xf1), /* trim */
> +};
> +
> +static const struct regmap_range s2mpg10_meter_ro_registers[] = {
> +	regmap_reg_range(0x40, 0x8a),
> +};
> +
> +static const struct regmap_access_table s2mpg10_meter_wr_table = {
> +	.yes_ranges = s2mpg10_meter_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers),
> +	.no_ranges = s2mpg10_meter_ro_registers,
> +	.n_no_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_meter_rd_table = {
> +	.yes_ranges = s2mpg10_meter_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers),
> +};
> +
> +static const struct regmap_access_table s2mpg10_meter_volatile_table = {
> +	.yes_ranges = s2mpg10_meter_ro_registers,
> +	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers),
> +};
> +
> +static const struct regmap_config s2mpg10_regmap_config_meter = {
> +	.name = "meter",
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.reg_stride = 1,
> +	.max_register = S2MPG10_METER_BUCK_METER_TRIM3,
> +	.wr_table = &s2mpg10_meter_wr_table,
> +	.rd_table = &s2mpg10_meter_rd_table,
> +	.volatile_table = &s2mpg10_meter_volatile_table,
> +	.num_reg_defaults_raw = S2MPG10_METER_BUCK_METER_TRIM3 + 1,
> +	.cache_type = REGCACHE_FLAT,
> +};
> +
> +struct sec_pmic_acpm_shared_bus_context {
> +	const struct acpm_handle *acpm;
> +	unsigned int acpm_chan_id;
> +	u8 speedy_channel;
> +};
> +
> +enum sec_pmic_acpm_accesstype {
> +	SEC_PMIC_ACPM_ACCESSTYPE_COMMON = 0x00,
> +	SEC_PMIC_ACPM_ACCESSTYPE_PMIC = 0x01,
> +	SEC_PMIC_ACPM_ACCESSTYPE_RTC = 0x02,
> +	SEC_PMIC_ACPM_ACCESSTYPE_METER = 0x0a,
> +	SEC_PMIC_ACPM_ACCESSTYPE_WLWP = 0x0b,
> +	SEC_PMIC_ACPM_ACCESSTYPE_TRIM = 0x0f,
> +};
> +
> +struct sec_pmic_acpm_bus_context {
> +	struct sec_pmic_acpm_shared_bus_context *shared;
> +	enum sec_pmic_acpm_accesstype type;
> +};
> +
> +static int sec_pmic_acpm_bus_write(void *context, const void *data,
> +				   size_t count)

Nit: You can tidy this, and similar line-feeds, up by using 100-chars here.

> +{
> +	struct sec_pmic_acpm_bus_context *ctx = context;
> +	const struct acpm_handle *acpm = ctx->shared->acpm;
> +	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
> +	u8 reg;
> +
> +	if (count < 2 || count > (ACPM_MAX_BULK_DATA + 1))

2 because?  Either comment or define magic numbers please.

> +		return -EINVAL;
> +
> +	reg = *(u8 *)data;

No API to conduct this raw read for you?  readl(), *_to_cpu() or similar?

> +	++data;
> +	--count;
> +
> +	return pmic_ops->bulk_write(acpm, ctx->shared->acpm_chan_id,
> +				    ctx->type, reg,
> +				    ctx->shared->speedy_channel, count, data);
> +}
> +
> +static int sec_pmic_acpm_bus_read(void *context, const void *reg_buf,
> +				  size_t reg_size, void *val_buf,
> +				  size_t val_size)
> +{
> +	struct sec_pmic_acpm_bus_context *ctx = context;
> +	const struct acpm_handle *acpm = ctx->shared->acpm;
> +	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
> +	u8 reg;
> +
> +	if (reg_size != 1 || !val_size || val_size > ACPM_MAX_BULK_DATA)
> +		return -EINVAL;
> +
> +	reg = *(u8 *)reg_buf;
> +
> +	return pmic_ops->bulk_read(acpm, ctx->shared->acpm_chan_id,
> +				   ctx->type, reg,
> +				   ctx->shared->speedy_channel,
> +				   val_size, val_buf);
> +}
> +
> +static int sec_pmic_acpm_bus_reg_update_bits(void *context, unsigned int reg,
> +					     unsigned int mask,
> +					     unsigned int val)
> +{
> +	struct sec_pmic_acpm_bus_context *ctx = context;
> +	const struct acpm_handle *acpm = ctx->shared->acpm;
> +	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
> +
> +	return pmic_ops->update_reg(acpm, ctx->shared->acpm_chan_id,
> +				    ctx->type, reg & 0xff,
> +				    ctx->shared->speedy_channel, val, mask);
> +}
> +
> +static const struct regmap_bus sec_pmic_acpm_regmap_bus = {
> +	.write = sec_pmic_acpm_bus_write,
> +	.read = sec_pmic_acpm_bus_read,
> +	.reg_update_bits = sec_pmic_acpm_bus_reg_update_bits,
> +	.max_raw_read = ACPM_MAX_BULK_DATA,
> +	.max_raw_write = ACPM_MAX_BULK_DATA,
> +};
> +
> +static struct regmap *
> +sec_pmic_acpm_regmap_init(struct device *dev,

Place both of these on the same line please.

> +			  struct sec_pmic_acpm_shared_bus_context *shared_ctx,
> +			  enum sec_pmic_acpm_accesstype type,
> +			  const struct regmap_config *cfg, bool do_attach)
> +{
> +	struct sec_pmic_acpm_bus_context *ctx;
> +	struct regmap *regmap;
> +
> +	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ctx->shared = shared_ctx;
> +	ctx->type = type;
> +
> +	regmap = devm_regmap_init(dev, &sec_pmic_acpm_regmap_bus, ctx, cfg);
> +	if (IS_ERR(regmap))
> +		return ERR_PTR(dev_err_probe(dev, PTR_ERR(regmap),

dev_err_cast_probe()

> +					     "regmap init (%s) failed\n",
> +					     cfg->name));
> +
> +	if (do_attach) {
> +		int ret;
> +
> +		ret = regmap_attach_dev(dev, regmap, cfg);
> +		if (ret)
> +			return ERR_PTR(dev_err_probe(dev, ret,

dev_err_ptr_probe()

> +						     "regmap attach (%s) failed\n",
> +						     cfg->name));
> +	}
> +
> +	return regmap;
> +}
> +
> +static void sec_pmic_acpm_mask_common_irqs(void *regmap_common)
> +{
> +	regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK,
> +		     S2MPG10_COMMON_INT_SRC);

Single line.  And others like it.

> +}
> +
> +static int sec_pmic_acpm_probe(struct platform_device *pdev)
> +{
> +	struct regmap *regmap_common, *regmap_pmic, *regmap;
> +	const struct sec_pmic_acpm_platform_data *pdata;
> +	struct sec_pmic_acpm_shared_bus_context *shared_ctx;
> +	const struct acpm_handle *acpm;
> +	struct device *dev;
> +	int ret, irq;
> +
> +	dev = &pdev->dev;

You can do this during the declaration.

> +	pdata = device_get_match_data(dev);
> +	if (!pdata)
> +		return dev_err_probe(dev, -ENODEV,
> +				     "unsupported device type\n");
> +
> +	acpm = devm_acpm_get_by_node(dev, pdev->dev.parent->of_node);

You have 'dev' now.  Please use it.

> +	if (IS_ERR(acpm))
> +		return dev_err_probe(dev, PTR_ERR(acpm),
> +				     "failed to get acpm (2)\n");
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return irq;
> +
> +	shared_ctx = devm_kzalloc(dev, sizeof(*shared_ctx), GFP_KERNEL);
> +	if (!shared_ctx)
> +		return -ENOMEM;
> +
> +	shared_ctx->acpm = acpm;
> +	shared_ctx->acpm_chan_id = pdata->acpm_chan_id;
> +	shared_ctx->speedy_channel = pdata->speedy_channel;
> +
> +	regmap_common = sec_pmic_acpm_regmap_init(dev, shared_ctx,
> +						  SEC_PMIC_ACPM_ACCESSTYPE_COMMON,
> +						  pdata->regmap_cfg_common, false);
> +	if (IS_ERR(regmap_common))
> +		return PTR_ERR(regmap_common);
> +
> +	/* Mask all interrupts from 'common' block, until successful init */
> +	ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK,
> +			   S2MPG10_COMMON_INT_SRC);
> +	if (ret)
> +		return dev_err_probe(dev, ret,
> +				     "failed to mask common block interrupts\n");
> +
> +	regmap_pmic = sec_pmic_acpm_regmap_init(dev, shared_ctx,
> +						SEC_PMIC_ACPM_ACCESSTYPE_PMIC,
> +						pdata->regmap_cfg_pmic, false);
> +	if (IS_ERR(regmap_pmic))
> +		return PTR_ERR(regmap_pmic);
> +
> +	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx,
> +					   SEC_PMIC_ACPM_ACCESSTYPE_RTC,
> +					   pdata->regmap_cfg_rtc, true);
> +	if (IS_ERR(regmap))
> +		return PTR_ERR(regmap);
> +
> +	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx,
> +					   SEC_PMIC_ACPM_ACCESSTYPE_METER,
> +					   pdata->regmap_cfg_meter, true);
> +	if (IS_ERR(regmap))
> +		return PTR_ERR(regmap);
> +
> +	ret = sec_pmic_probe(dev, pdata->device_type, irq, regmap_pmic, NULL);
> +	if (ret)
> +		return ret;
> +
> +	if (device_property_read_bool(dev, "wakeup-source"))
> +		devm_device_init_wakeup(dev);
> +
> +	/*
> +	 * Unmask PMIC interrupt from 'common' block, now that everything is in
> +	 * place.
> +	 */
> +	ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
> +				S2MPG10_COMMON_INT_SRC_PMIC);
> +	if (ret)
> +		return dev_err_probe(dev, ret,
> +				     "failed to unmask PMIC interrupt\n");
> +
> +	/* Mask all interrupts from 'common' block on shutdown */
> +	ret = devm_add_action_or_reset(dev, sec_pmic_acpm_mask_common_irqs,
> +				       regmap_common);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static void sec_pmic_acpm_shutdown(struct platform_device *pdev)
> +{
> +	sec_pmic_shutdown(&pdev->dev);

sec_pmic_shutdown() takes a pointer to i2c_client (unless you changed it
somewhere else).  If the later is true, then why not make it take a
pointer to platform_device and omit this abstraction?

> +}
> +
> +static const struct sec_pmic_acpm_platform_data s2mpg10_data = {
> +	.device_type = S2MPG10,
> +	.acpm_chan_id = 2,
> +	.speedy_channel = 0,
> +	.regmap_cfg_common = &s2mpg10_regmap_config_common,
> +	.regmap_cfg_pmic = &s2mpg10_regmap_config_pmic,
> +	.regmap_cfg_rtc = &s2mpg10_regmap_config_rtc,
> +	.regmap_cfg_meter = &s2mpg10_regmap_config_meter,
> +};
> +
> +static const struct of_device_id sec_pmic_acpm_of_match[] = {
> +	{ .compatible = "samsung,s2mpg10-pmic", .data = &s2mpg10_data, },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, sec_pmic_acpm_of_match);
> +
> +static struct platform_driver sec_pmic_acpm_driver = {
> +	.driver = {
> +		.name = "sec-pmic-acpm",
> +		.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
> +		.of_match_table = sec_pmic_acpm_of_match,
> +	},
> +	.probe = sec_pmic_acpm_probe,
> +	.shutdown = sec_pmic_acpm_shutdown,
> +};
> +module_platform_driver(sec_pmic_acpm_driver);
> +
> +MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");
> +MODULE_DESCRIPTION("ACPM driver for the Samsung S2MPG1x");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
> index bb664e052bf5198f2fc83a86bd6e1e72364fb8df..c4b7abe511090d8f5ff2eb501f325cc8173b9bf5 100644
> --- a/drivers/mfd/sec-core.c
> +++ b/drivers/mfd/sec-core.c
> @@ -36,6 +36,14 @@ static const struct mfd_cell s2dos05_devs[] = {
>  	{ .name = "s2dos05-regulator", },
>  };
>  
> +static const struct mfd_cell s2mpg10_devs[] = {
> +	MFD_CELL_NAME("s2mpg10-meter"),
> +	MFD_CELL_NAME("s2mpg10-regulator"),
> +	MFD_CELL_NAME("s2mpg10-rtc"),
> +	MFD_CELL_OF("s2mpg10-clk", NULL, NULL, 0, 0, "samsung,s2mpg10-clk"),
> +	MFD_CELL_OF("s2mpg10-gpio", NULL, NULL, 0, 0, "samsung,s2mpg10-gpio"),
> +};
> +
>  static const struct mfd_cell s2mps11_devs[] = {
>  	{ .name = "s2mps11-regulator", },
>  	{ .name = "s2mps14-rtc", },
> @@ -90,6 +98,10 @@ static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
>  {
>  	unsigned int val;
>  
> +	/* For s2mpg1x, the revision is in a different regmap */

Nice, thanks for that.

> +	if (sec_pmic->device_type == S2MPG10)
> +		return;
> +
>  	/* For each device type, the REG_ID is always the first register */
>  	if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
>  		dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);
> @@ -188,6 +200,10 @@ int sec_pmic_probe(struct device *dev, unsigned long device_type,
>  		sec_devs = s2mpa01_devs;
>  		num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
>  		break;
> +	case S2MPG10:
> +		sec_devs = s2mpg10_devs;
> +		num_sec_devs = ARRAY_SIZE(s2mpg10_devs);
> +		break;
>  	case S2MPS11X:
>  		sec_devs = s2mps11_devs;
>  		num_sec_devs = ARRAY_SIZE(s2mps11_devs);
> diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
> index 4d49bb42bd0d109263f485c8b58e88cdd8d598d9..bf86281401ac6ff05c90c2d71c84744709ed79cb 100644
> --- a/drivers/mfd/sec-irq.c
> +++ b/drivers/mfd/sec-irq.c
> @@ -11,6 +11,7 @@
>  #include <linux/irq.h>
>  #include <linux/mfd/samsung/core.h>
>  #include <linux/mfd/samsung/irq.h>
> +#include <linux/mfd/samsung/s2mpg10.h>
>  #include <linux/mfd/samsung/s2mps11.h>
>  #include <linux/mfd/samsung/s2mps14.h>
>  #include <linux/mfd/samsung/s2mpu02.h>
> @@ -20,6 +21,60 @@
>  #include <linux/regmap.h>
>  #include "sec-core.h"
>  
> +static const struct regmap_irq s2mpg10_irqs[] = {
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONF, 0, S2MPG10_IRQ_PWRONF_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWRONR, 0, S2MPG10_IRQ_PWRONR_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBF, 0, S2MPG10_IRQ_JIGONBF_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_JIGONBR, 0, S2MPG10_IRQ_JIGONBR_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_ACOKBF, 0, S2MPG10_IRQ_ACOKBF_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_ACOKBR, 0, S2MPG10_IRQ_ACOKBR_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWRON1S, 0, S2MPG10_IRQ_PWRON1S_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_MRB, 0, S2MPG10_IRQ_MRB_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_RTC60S, 1, S2MPG10_IRQ_RTC60S_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_RTCA1, 1, S2MPG10_IRQ_RTCA1_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_RTCA0, 1, S2MPG10_IRQ_RTCA0_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_RTC1S, 1, S2MPG10_IRQ_RTC1S_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR_COLDRST, 1, S2MPG10_IRQ_WTSR_COLDRST_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR, 1, S2MPG10_IRQ_WTSR_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_WRST, 1, S2MPG10_IRQ_WRST_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_SMPL, 1, S2MPG10_IRQ_SMPL_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_120C, 2, S2MPG10_IRQ_INT120C_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_140C, 2, S2MPG10_IRQ_INT140C_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_TSD, 2, S2MPG10_IRQ_TSD_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PIF_TIMEOUT1, 2, S2MPG10_IRQ_PIF_TIMEOUT1_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PIF_TIMEOUT2, 2, S2MPG10_IRQ_PIF_TIMEOUT2_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_PARITY_ERR, 2, S2MPG10_IRQ_SPD_PARITY_ERR_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_ABNORMAL_STOP, 2, S2MPG10_IRQ_SPD_ABNORMAL_STOP_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PMETER_OVERF, 2, S2MPG10_IRQ_PMETER_OVERF_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B1M, 3, S2MPG10_IRQ_OCP_B1M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B2M, 3, S2MPG10_IRQ_OCP_B2M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B3M, 3, S2MPG10_IRQ_OCP_B3M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B4M, 3, S2MPG10_IRQ_OCP_B4M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B5M, 3, S2MPG10_IRQ_OCP_B5M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B6M, 3, S2MPG10_IRQ_OCP_B6M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B7M, 3, S2MPG10_IRQ_OCP_B7M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B8M, 3, S2MPG10_IRQ_OCP_B8M_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B9M, 4, S2MPG10_IRQ_OCP_B9M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_OCP_B10M, 4, S2MPG10_IRQ_OCP_B10M_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_WLWP_ACC, 4, S2MPG10_IRQ_WLWP_ACC_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_SMPL_TIMEOUT, 4, S2MPG10_IRQ_SMPL_TIMEOUT_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_WTSR_TIMEOUT, 4, S2MPG10_IRQ_WTSR_TIMEOUT_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_SPD_SRP_PKT_RST, 4, S2MPG10_IRQ_SPD_SRP_PKT_RST_MASK),
> +
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH0, 5, S2MPG10_IRQ_PWR_WARN_CH0_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH1, 5, S2MPG10_IRQ_PWR_WARN_CH1_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH2, 5, S2MPG10_IRQ_PWR_WARN_CH2_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH3, 5, S2MPG10_IRQ_PWR_WARN_CH3_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH4, 5, S2MPG10_IRQ_PWR_WARN_CH4_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH5, 5, S2MPG10_IRQ_PWR_WARN_CH5_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH6, 5, S2MPG10_IRQ_PWR_WARN_CH6_MASK),
> +	REGMAP_IRQ_REG(S2MPG10_IRQ_PWR_WARN_CH7, 5, S2MPG10_IRQ_PWR_WARN_CH7_MASK),
> +};
> +
>  static const struct regmap_irq s2mps11_irqs[] = {
>  	[S2MPS11_IRQ_PWRONF] = {
>  		.reg_offset = 0,
> @@ -320,6 +375,16 @@ static const struct regmap_irq s5m8767_irqs[] = {
>  	},
>  };
>  
> +static const struct regmap_irq_chip s2mpg10_irq_chip = {
> +	.name = "s2mpg10",
> +	.irqs = s2mpg10_irqs,
> +	.num_irqs = ARRAY_SIZE(s2mpg10_irqs),
> +	.num_regs = 6,
> +	.status_base = S2MPG10_PMIC_INT1,
> +	.mask_base = S2MPG10_PMIC_INT1M,
> +	/* all interrupt sources are read-to-clear */

TOUPPER(a);

Comments usually go on-top of the thing they're commenting on.

> +};
> +
>  static const struct regmap_irq_chip s2mps11_irq_chip = {
>  	.name = "s2mps11",
>  	.irqs = s2mps11_irqs,
> @@ -402,6 +467,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
>  	case S2MPA01:
>  		sec_irq_chip = &s2mps14_irq_chip;
>  		break;
> +	case S2MPG10:
> +		sec_irq_chip = &s2mpg10_irq_chip;
> +		break;
>  	case S2MPS11X:
>  		sec_irq_chip = &s2mps11_irq_chip;
>  		break;
> diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
> index 8a4e660854bbc955b812b4d61d4a52a0fc2f2899..c1102324172a9b6bd6072b5929a4866d6c9653fa 100644
> --- a/include/linux/mfd/samsung/core.h
> +++ b/include/linux/mfd/samsung/core.h
> @@ -39,6 +39,7 @@ enum sec_device_type {
>  	S5M8767X,
>  	S2DOS05,
>  	S2MPA01,
> +	S2MPG10,
>  	S2MPS11X,
>  	S2MPS13X,
>  	S2MPS14X,
> diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
> index 978f7af66f74842c4f8dd62c0f58a7a45aba7c34..b4805cbd949bd605004bd88cf361109d1cbbc3bf 100644
> --- a/include/linux/mfd/samsung/irq.h
> +++ b/include/linux/mfd/samsung/irq.h
> @@ -57,6 +57,109 @@ enum s2mpa01_irq {
>  #define S2MPA01_IRQ_B24_TSD_MASK	(1 << 4)
>  #define S2MPA01_IRQ_B35_TSD_MASK	(1 << 5)
>  
> +enum s2mpg10_irq {
> +	/* PMIC */
> +	S2MPG10_IRQ_PWRONF,
> +	S2MPG10_IRQ_PWRONR,
> +	S2MPG10_IRQ_JIGONBF,
> +	S2MPG10_IRQ_JIGONBR,
> +	S2MPG10_IRQ_ACOKBF,
> +	S2MPG10_IRQ_ACOKBR,
> +	S2MPG10_IRQ_PWRON1S,
> +	S2MPG10_IRQ_MRB,
> +#define S2MPG10_IRQ_PWRONF_MASK		BIT(0)
> +#define S2MPG10_IRQ_PWRONR_MASK		BIT(1)
> +#define S2MPG10_IRQ_JIGONBF_MASK	BIT(2)
> +#define S2MPG10_IRQ_JIGONBR_MASK	BIT(3)
> +#define S2MPG10_IRQ_ACOKBF_MASK		BIT(4)
> +#define S2MPG10_IRQ_ACOKBR_MASK		BIT(5)
> +#define S2MPG10_IRQ_PWRON1S_MASK	BIT(6)
> +#define S2MPG10_IRQ_MRB_MASK		BIT(7)
> +
> +	S2MPG10_IRQ_RTC60S,
> +	S2MPG10_IRQ_RTCA1,
> +	S2MPG10_IRQ_RTCA0,
> +	S2MPG10_IRQ_RTC1S,
> +	S2MPG10_IRQ_WTSR_COLDRST,
> +	S2MPG10_IRQ_WTSR,
> +	S2MPG10_IRQ_WRST,
> +	S2MPG10_IRQ_SMPL,
> +#define S2MPG10_IRQ_RTC60S_MASK		BIT(0)
> +#define S2MPG10_IRQ_RTCA1_MASK		BIT(1)
> +#define S2MPG10_IRQ_RTCA0_MASK		BIT(2)
> +#define S2MPG10_IRQ_RTC1S_MASK		BIT(3)
> +#define S2MPG10_IRQ_WTSR_COLDRST_MASK	BIT(4)
> +#define S2MPG10_IRQ_WTSR_MASK		BIT(5)
> +#define S2MPG10_IRQ_WRST_MASK		BIT(6)
> +#define S2MPG10_IRQ_SMPL_MASK		BIT(7)
> +
> +	S2MPG10_IRQ_120C,
> +	S2MPG10_IRQ_140C,
> +	S2MPG10_IRQ_TSD,
> +	S2MPG10_IRQ_PIF_TIMEOUT1,
> +	S2MPG10_IRQ_PIF_TIMEOUT2,
> +	S2MPG10_IRQ_SPD_PARITY_ERR,
> +	S2MPG10_IRQ_SPD_ABNORMAL_STOP,
> +	S2MPG10_IRQ_PMETER_OVERF,
> +#define S2MPG10_IRQ_INT120C_MASK		BIT(0)
> +#define S2MPG10_IRQ_INT140C_MASK		BIT(1)
> +#define S2MPG10_IRQ_TSD_MASK			BIT(2)
> +#define S2MPG10_IRQ_PIF_TIMEOUT1_MASK		BIT(3)
> +#define S2MPG10_IRQ_PIF_TIMEOUT2_MASK		BIT(4)
> +#define S2MPG10_IRQ_SPD_PARITY_ERR_MASK		BIT(5)
> +#define S2MPG10_IRQ_SPD_ABNORMAL_STOP_MASK	BIT(6)
> +#define S2MPG10_IRQ_PMETER_OVERF_MASK		BIT(7)
> +
> +	S2MPG10_IRQ_OCP_B1M,
> +	S2MPG10_IRQ_OCP_B2M,
> +	S2MPG10_IRQ_OCP_B3M,
> +	S2MPG10_IRQ_OCP_B4M,
> +	S2MPG10_IRQ_OCP_B5M,
> +	S2MPG10_IRQ_OCP_B6M,
> +	S2MPG10_IRQ_OCP_B7M,
> +	S2MPG10_IRQ_OCP_B8M,
> +#define S2MPG10_IRQ_OCP_B1M_MASK	BIT(0)
> +#define S2MPG10_IRQ_OCP_B2M_MASK	BIT(1)
> +#define S2MPG10_IRQ_OCP_B3M_MASK	BIT(2)
> +#define S2MPG10_IRQ_OCP_B4M_MASK	BIT(3)
> +#define S2MPG10_IRQ_OCP_B5M_MASK	BIT(4)
> +#define S2MPG10_IRQ_OCP_B6M_MASK	BIT(5)
> +#define S2MPG10_IRQ_OCP_B7M_MASK	BIT(6)
> +#define S2MPG10_IRQ_OCP_B8M_MASK	BIT(7)
> +
> +	S2MPG10_IRQ_OCP_B9M,
> +	S2MPG10_IRQ_OCP_B10M,
> +	S2MPG10_IRQ_WLWP_ACC,
> +	S2MPG10_IRQ_SMPL_TIMEOUT,
> +	S2MPG10_IRQ_WTSR_TIMEOUT,
> +	S2MPG10_IRQ_SPD_SRP_PKT_RST,
> +#define S2MPG10_IRQ_OCP_B9M_MASK		BIT(0)
> +#define S2MPG10_IRQ_OCP_B10M_MASK		BIT(1)
> +#define S2MPG10_IRQ_WLWP_ACC_MASK		BIT(2)
> +#define S2MPG10_IRQ_SMPL_TIMEOUT_MASK		BIT(5)
> +#define S2MPG10_IRQ_WTSR_TIMEOUT_MASK		BIT(6)
> +#define S2MPG10_IRQ_SPD_SRP_PKT_RST_MASK	BIT(7)
> +
> +	S2MPG10_IRQ_PWR_WARN_CH0,
> +	S2MPG10_IRQ_PWR_WARN_CH1,
> +	S2MPG10_IRQ_PWR_WARN_CH2,
> +	S2MPG10_IRQ_PWR_WARN_CH3,
> +	S2MPG10_IRQ_PWR_WARN_CH4,
> +	S2MPG10_IRQ_PWR_WARN_CH5,
> +	S2MPG10_IRQ_PWR_WARN_CH6,
> +	S2MPG10_IRQ_PWR_WARN_CH7,
> +#define S2MPG10_IRQ_PWR_WARN_CH0_MASK	BIT(0)
> +#define S2MPG10_IRQ_PWR_WARN_CH1_MASK	BIT(1)
> +#define S2MPG10_IRQ_PWR_WARN_CH2_MASK	BIT(2)
> +#define S2MPG10_IRQ_PWR_WARN_CH3_MASK	BIT(3)
> +#define S2MPG10_IRQ_PWR_WARN_CH4_MASK	BIT(4)
> +#define S2MPG10_IRQ_PWR_WARN_CH5_MASK	BIT(5)
> +#define S2MPG10_IRQ_PWR_WARN_CH6_MASK	BIT(6)
> +#define S2MPG10_IRQ_PWR_WARN_CH7_MASK	BIT(7)
> +
> +	S2MPG10_IRQ_NR,
> +};
> +
>  enum s2mps11_irq {
>  	S2MPS11_IRQ_PWRONF,
>  	S2MPS11_IRQ_PWRONR,
> diff --git a/include/linux/mfd/samsung/rtc.h b/include/linux/mfd/samsung/rtc.h
> index 0204decfc9aacbf4bc93d98a256f1d956bbcd19c..51c4239a1fa6f28155711a0756b0e071b010d848 100644
> --- a/include/linux/mfd/samsung/rtc.h
> +++ b/include/linux/mfd/samsung/rtc.h
> @@ -72,6 +72,37 @@ enum s2mps_rtc_reg {
>  	S2MPS_RTC_REG_MAX,
>  };
>  
> +enum s2mpg10_rtc_reg {
> +	S2MPG10_RTC_CTRL,
> +	S2MPG10_RTC_UPDATE,
> +	S2MPG10_RTC_SMPL,
> +	S2MPG10_RTC_WTSR,
> +	S2MPG10_RTC_CAP_SEL,
> +	S2MPG10_RTC_MSEC,
> +	S2MPG10_RTC_SEC,
> +	S2MPG10_RTC_MIN,
> +	S2MPG10_RTC_HOUR,
> +	S2MPG10_RTC_WEEK,
> +	S2MPG10_RTC_DAY,
> +	S2MPG10_RTC_MON,
> +	S2MPG10_RTC_YEAR,
> +	S2MPG10_RTC_A0SEC,
> +	S2MPG10_RTC_A0MIN,
> +	S2MPG10_RTC_A0HOUR,
> +	S2MPG10_RTC_A0WEEK,
> +	S2MPG10_RTC_A0DAY,
> +	S2MPG10_RTC_A0MON,
> +	S2MPG10_RTC_A0YEAR,
> +	S2MPG10_RTC_A1SEC,
> +	S2MPG10_RTC_A1MIN,
> +	S2MPG10_RTC_A1HOUR,
> +	S2MPG10_RTC_A1WEEK,
> +	S2MPG10_RTC_A1DAY,
> +	S2MPG10_RTC_A1MON,
> +	S2MPG10_RTC_A1YEAR,
> +	S2MPG10_RTC_OSC_CTRL,
> +};
> +
>  #define RTC_I2C_ADDR		(0x0C >> 1)
>  
>  #define HOUR_12			(1 << 7)
> @@ -124,10 +155,16 @@ enum s2mps_rtc_reg {
>  #define ALARM_ENABLE_SHIFT	7
>  #define ALARM_ENABLE_MASK	(1 << ALARM_ENABLE_SHIFT)
>  
> +/* WTSR & SMPL registers */
>  #define SMPL_ENABLE_SHIFT	7
>  #define SMPL_ENABLE_MASK	(1 << SMPL_ENABLE_SHIFT)
>  
>  #define WTSR_ENABLE_SHIFT	6
>  #define WTSR_ENABLE_MASK	(1 << WTSR_ENABLE_SHIFT)
>  
> +#define S2MPG10_WTSR_COLDTIMER	GENMASK(6, 5)
> +#define S2MPG10_WTSR_COLDRST	BIT(4)
> +#define S2MPG10_WTSR_WTSRT	GENMASK(3, 1)
> +#define S2MPG10_WTSR_WTSR_EN	BIT(0)
> +
>  #endif /*  __LINUX_MFD_SEC_RTC_H */
> diff --git a/include/linux/mfd/samsung/s2mpg10.h b/include/linux/mfd/samsung/s2mpg10.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..778ff16ef6668ded514e8dc7242f369cb9c2d0e6
> --- /dev/null
> +++ b/include/linux/mfd/samsung/s2mpg10.h
> @@ -0,0 +1,454 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright 2015 Samsung Electronics
> + * Copyright 2020 Google Inc
> + * Copyright 2025 Linaro Ltd.
> + */
> +
> +#ifndef __LINUX_MFD_S2MPG10_H
> +#define __LINUX_MFD_S2MPG10_H
> +
> +/* Common registers (type 0x000) */
> +enum s2mpg10_common_reg {
> +	S2MPG10_COMMON_CHIPID,
> +	S2MPG10_COMMON_INT,
> +	S2MPG10_COMMON_INT_MASK,
> +	S2MPG10_COMMON_SPD_CTRL1 = 0x0a,
> +	S2MPG10_COMMON_SPD_CTRL2,
> +	S2MPG10_COMMON_SPD_CTRL3,
> +	S2MPG10_COMMON_MON1SEL = 0x1a,
> +	S2MPG10_COMMON_MON2SEL,
> +	S2MPG10_COMMON_MONR,
> +	S2MPG10_COMMON_DEBUG_CTRL1,
> +	S2MPG10_COMMON_DEBUG_CTRL2,
> +	S2MPG10_COMMON_DEBUG_CTRL3,
> +	S2MPG10_COMMON_DEBUG_CTRL4,
> +	S2MPG10_COMMON_DEBUG_CTRL5,
> +	S2MPG10_COMMON_DEBUG_CTRL6,
> +	S2MPG10_COMMON_DEBUG_CTRL7,
> +	S2MPG10_COMMON_DEBUG_CTRL8,
> +	S2MPG10_COMMON_TEST_MODE1,
> +	S2MPG10_COMMON_TEST_MODE2,
> +	S2MPG10_COMMON_SPD_DEBUG1,
> +	S2MPG10_COMMON_SPD_DEBUG2,
> +	S2MPG10_COMMON_SPD_DEBUG3,
> +	S2MPG10_COMMON_SPD_DEBUG4,
> +};
> +
> +/* for S2MPG10_COMMON_INT and S2MPG10_COMMON_INT_MASK */

TOUPPER(f), etc.

> +#define S2MPG10_COMMON_INT_SRC       GENMASK(7, 0)
> +#define S2MPG10_COMMON_INT_SRC_PMIC  BIT(0)
> +
> +/* PMIC registers (type 0x100) */
> +enum s2mpg10_pmic_reg {
> +	S2MPG10_PMIC_INT1,
> +	S2MPG10_PMIC_INT2,
> +	S2MPG10_PMIC_INT3,
> +	S2MPG10_PMIC_INT4,
> +	S2MPG10_PMIC_INT5,
> +	S2MPG10_PMIC_INT6,
> +	S2MPG10_PMIC_INT1M,
> +	S2MPG10_PMIC_INT2M,
> +	S2MPG10_PMIC_INT3M,
> +	S2MPG10_PMIC_INT4M,
> +	S2MPG10_PMIC_INT5M,
> +	S2MPG10_PMIC_INT6M,
> +	S2MPG10_PMIC_STATUS1,
> +	S2MPG10_PMIC_STATUS2,
> +	S2MPG10_PMIC_PWRONSRC,
> +	S2MPG10_PMIC_OFFSRC,
> +	S2MPG10_PMIC_BU_CHG,
> +	S2MPG10_PMIC_RTCBUF,
> +	S2MPG10_PMIC_COMMON_CTRL1,
> +	S2MPG10_PMIC_COMMON_CTRL2,
> +	S2MPG10_PMIC_COMMON_CTRL3,
> +	S2MPG10_PMIC_COMMON_CTRL4,
> +	S2MPG10_PMIC_SMPL_WARN_CTRL,
> +	S2MPG10_PMIC_MIMICKING_CTRL,
> +	S2MPG10_PMIC_B1M_CTRL,
> +	S2MPG10_PMIC_B1M_OUT1,
> +	S2MPG10_PMIC_B1M_OUT2,
> +	S2MPG10_PMIC_B2M_CTRL,
> +	S2MPG10_PMIC_B2M_OUT1,
> +	S2MPG10_PMIC_B2M_OUT2,
> +	S2MPG10_PMIC_B3M_CTRL,
> +	S2MPG10_PMIC_B3M_OUT1,
> +	S2MPG10_PMIC_B3M_OUT2,
> +	S2MPG10_PMIC_B4M_CTRL,
> +	S2MPG10_PMIC_B4M_OUT1,
> +	S2MPG10_PMIC_B4M_OUT2,
> +	S2MPG10_PMIC_B5M_CTRL,
> +	S2MPG10_PMIC_B5M_OUT1,
> +	S2MPG10_PMIC_B5M_OUT2,
> +	S2MPG10_PMIC_B6M_CTRL,
> +	S2MPG10_PMIC_B6M_OUT1,
> +	S2MPG10_PMIC_B6M_OUT2,
> +	S2MPG10_PMIC_B7M_CTRL,
> +	S2MPG10_PMIC_B7M_OUT1,
> +	S2MPG10_PMIC_B7M_OUT2,
> +	S2MPG10_PMIC_B8M_CTRL,
> +	S2MPG10_PMIC_B8M_OUT1,
> +	S2MPG10_PMIC_B8M_OUT2,
> +	S2MPG10_PMIC_B9M_CTRL,
> +	S2MPG10_PMIC_B9M_OUT1,
> +	S2MPG10_PMIC_B9M_OUT2,
> +	S2MPG10_PMIC_B10M_CTRL,
> +	S2MPG10_PMIC_B10M_OUT1,
> +	S2MPG10_PMIC_B10M_OUT2,
> +	S2MPG10_PMIC_BUCK1M_USONIC,
> +	S2MPG10_PMIC_BUCK2M_USONIC,
> +	S2MPG10_PMIC_BUCK3M_USONIC,
> +	S2MPG10_PMIC_BUCK4M_USONIC,
> +	S2MPG10_PMIC_BUCK5M_USONIC,
> +	S2MPG10_PMIC_BUCK6M_USONIC,
> +	S2MPG10_PMIC_BUCK7M_USONIC,
> +	S2MPG10_PMIC_BUCK8M_USONIC,
> +	S2MPG10_PMIC_BUCK9M_USONIC,
> +	S2MPG10_PMIC_BUCK10M_USONIC,
> +	S2MPG10_PMIC_L1M_CTRL,
> +	S2MPG10_PMIC_L2M_CTRL,
> +	S2MPG10_PMIC_L3M_CTRL,
> +	S2MPG10_PMIC_L4M_CTRL,
> +	S2MPG10_PMIC_L5M_CTRL,
> +	S2MPG10_PMIC_L6M_CTRL,
> +	S2MPG10_PMIC_L7M_CTRL,
> +	S2MPG10_PMIC_L8M_CTRL,
> +	S2MPG10_PMIC_L9M_CTRL,
> +	S2MPG10_PMIC_L10M_CTRL,
> +	S2MPG10_PMIC_L11M_CTRL1,
> +	S2MPG10_PMIC_L11M_CTRL2,
> +	S2MPG10_PMIC_L12M_CTRL1,
> +	S2MPG10_PMIC_L12M_CTRL2,
> +	S2MPG10_PMIC_L13M_CTRL1,
> +	S2MPG10_PMIC_L13M_CTRL2,
> +	S2MPG10_PMIC_L14M_CTRL,
> +	S2MPG10_PMIC_L15M_CTRL1,
> +	S2MPG10_PMIC_L15M_CTRL2,
> +	S2MPG10_PMIC_L16M_CTRL,
> +	S2MPG10_PMIC_L17M_CTRL,
> +	S2MPG10_PMIC_L18M_CTRL,
> +	S2MPG10_PMIC_L19M_CTRL,
> +	S2MPG10_PMIC_L20M_CTRL,
> +	S2MPG10_PMIC_L21M_CTRL,
> +	S2MPG10_PMIC_L22M_CTRL,
> +	S2MPG10_PMIC_L23M_CTRL,
> +	S2MPG10_PMIC_L24M_CTRL,
> +	S2MPG10_PMIC_L25M_CTRL,
> +	S2MPG10_PMIC_L26M_CTRL,
> +	S2MPG10_PMIC_L27M_CTRL,
> +	S2MPG10_PMIC_L28M_CTRL,
> +	S2MPG10_PMIC_L29M_CTRL,
> +	S2MPG10_PMIC_L30M_CTRL,
> +	S2MPG10_PMIC_L31M_CTRL,
> +	S2MPG10_PMIC_LDO_CTRL1,
> +	S2MPG10_PMIC_LDO_CTRL2,
> +	S2MPG10_PMIC_LDO_DSCH1,
> +	S2MPG10_PMIC_LDO_DSCH2,
> +	S2MPG10_PMIC_LDO_DSCH3,
> +	S2MPG10_PMIC_LDO_DSCH4,
> +	S2MPG10_PMIC_LDO_BUCK7M_HLIMIT,
> +	S2MPG10_PMIC_LDO_BUCK7M_LLIMIT,
> +	S2MPG10_PMIC_LDO_LDO21M_HLIMIT,
> +	S2MPG10_PMIC_LDO_LDO21M_LLIMIT,
> +	S2MPG10_PMIC_LDO_LDO11M_HLIMIT,
> +	S2MPG10_PMIC_DVS_RAMP1,
> +	S2MPG10_PMIC_DVS_RAMP2,
> +	S2MPG10_PMIC_DVS_RAMP3,
> +	S2MPG10_PMIC_DVS_RAMP4,
> +	S2MPG10_PMIC_DVS_RAMP5,
> +	S2MPG10_PMIC_DVS_RAMP6,
> +	S2MPG10_PMIC_DVS_SYNC_CTRL1,
> +	S2MPG10_PMIC_DVS_SYNC_CTRL2,
> +	S2MPG10_PMIC_DVS_SYNC_CTRL3,
> +	S2MPG10_PMIC_DVS_SYNC_CTRL4,
> +	S2MPG10_PMIC_DVS_SYNC_CTRL5,
> +	S2MPG10_PMIC_DVS_SYNC_CTRL6,
> +	S2MPG10_PMIC_OFF_CTRL1,
> +	S2MPG10_PMIC_OFF_CTRL2,
> +	S2MPG10_PMIC_OFF_CTRL3,
> +	S2MPG10_PMIC_OFF_CTRL4,
> +	S2MPG10_PMIC_SEQ_CTRL1,
> +	S2MPG10_PMIC_SEQ_CTRL2,
> +	S2MPG10_PMIC_SEQ_CTRL3,
> +	S2MPG10_PMIC_SEQ_CTRL4,
> +	S2MPG10_PMIC_SEQ_CTRL5,
> +	S2MPG10_PMIC_SEQ_CTRL6,
> +	S2MPG10_PMIC_SEQ_CTRL7,
> +	S2MPG10_PMIC_SEQ_CTRL8,
> +	S2MPG10_PMIC_SEQ_CTRL9,
> +	S2MPG10_PMIC_SEQ_CTRL10,
> +	S2MPG10_PMIC_SEQ_CTRL11,
> +	S2MPG10_PMIC_SEQ_CTRL12,
> +	S2MPG10_PMIC_SEQ_CTRL13,
> +	S2MPG10_PMIC_SEQ_CTRL14,
> +	S2MPG10_PMIC_SEQ_CTRL15,
> +	S2MPG10_PMIC_SEQ_CTRL16,
> +	S2MPG10_PMIC_SEQ_CTRL17,
> +	S2MPG10_PMIC_SEQ_CTRL18,
> +	S2MPG10_PMIC_SEQ_CTRL19,
> +	S2MPG10_PMIC_SEQ_CTRL20,
> +	S2MPG10_PMIC_SEQ_CTRL21,
> +	S2MPG10_PMIC_SEQ_CTRL22,
> +	S2MPG10_PMIC_SEQ_CTRL23,
> +	S2MPG10_PMIC_SEQ_CTRL24,
> +	S2MPG10_PMIC_SEQ_CTRL25,
> +	S2MPG10_PMIC_SEQ_CTRL26,
> +	S2MPG10_PMIC_SEQ_CTRL27,
> +	S2MPG10_PMIC_SEQ_CTRL28,
> +	S2MPG10_PMIC_SEQ_CTRL29,
> +	S2MPG10_PMIC_SEQ_CTRL30,
> +	S2MPG10_PMIC_SEQ_CTRL31,
> +	S2MPG10_PMIC_SEQ_CTRL32,
> +	S2MPG10_PMIC_SEQ_CTRL33,
> +	S2MPG10_PMIC_SEQ_CTRL34,
> +	S2MPG10_PMIC_SEQ_CTRL35,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL1,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL2,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL3,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL4,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL5,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL6,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL7,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL8,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL9,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL10,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL11,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL12,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL13,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL14,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL15,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL16,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL17,
> +	S2MPG10_PMIC_OFF_SEQ_CTRL18,
> +	S2MPG10_PMIC_PCTRLSEL1,
> +	S2MPG10_PMIC_PCTRLSEL2,
> +	S2MPG10_PMIC_PCTRLSEL3,
> +	S2MPG10_PMIC_PCTRLSEL4,
> +	S2MPG10_PMIC_PCTRLSEL5,
> +	S2MPG10_PMIC_PCTRLSEL6,
> +	S2MPG10_PMIC_PCTRLSEL7,
> +	S2MPG10_PMIC_PCTRLSEL8,
> +	S2MPG10_PMIC_PCTRLSEL9,
> +	S2MPG10_PMIC_PCTRLSEL10,
> +	S2MPG10_PMIC_PCTRLSEL11,
> +	S2MPG10_PMIC_PCTRLSEL12,
> +	S2MPG10_PMIC_PCTRLSEL13,
> +	S2MPG10_PMIC_DCTRLSEL1,
> +	S2MPG10_PMIC_DCTRLSEL2,
> +	S2MPG10_PMIC_DCTRLSEL3,
> +	S2MPG10_PMIC_DCTRLSEL4,
> +	S2MPG10_PMIC_DCTRLSEL5,
> +	S2MPG10_PMIC_DCTRLSEL6,
> +	S2MPG10_PMIC_DCTRLSEL7,
> +	S2MPG10_PMIC_GPIO_CTRL1,
> +	S2MPG10_PMIC_GPIO_CTRL2,
> +	S2MPG10_PMIC_GPIO_CTRL3,
> +	S2MPG10_PMIC_GPIO_CTRL4,
> +	S2MPG10_PMIC_GPIO_CTRL5,
> +	S2MPG10_PMIC_GPIO_CTRL6,
> +	S2MPG10_PMIC_GPIO_CTRL7,
> +	S2MPG10_PMIC_B2M_OCP_WARN,
> +	S2MPG10_PMIC_B2M_OCP_WARN_X,
> +	S2MPG10_PMIC_B2M_OCP_WARN_Y,
> +	S2MPG10_PMIC_B2M_OCP_WARN_Z,
> +	S2MPG10_PMIC_B3M_OCP_WARN,
> +	S2MPG10_PMIC_B3M_OCP_WARN_X,
> +	S2MPG10_PMIC_B3M_OCP_WARN_Y,
> +	S2MPG10_PMIC_B3M_OCP_WARN_Z,
> +	S2MPG10_PMIC_B10M_OCP_WARN,
> +	S2MPG10_PMIC_B10M_OCP_WARN_X,
> +	S2MPG10_PMIC_B10M_OCP_WARN_Y,
> +	S2MPG10_PMIC_B10M_OCP_WARN_Z,
> +	S2MPG10_PMIC_B2M_SOFT_OCP_WARN,
> +	S2MPG10_PMIC_B2M_SOFT_OCP_WARN_X,
> +	S2MPG10_PMIC_B2M_SOFT_OCP_WARN_Y,
> +	S2MPG10_PMIC_B2M_SOFT_OCP_WARN_Z,
> +	S2MPG10_PMIC_B3M_SOFT_OCP_WARN,
> +	S2MPG10_PMIC_B3M_SOFT_OCP_WARN_X,
> +	S2MPG10_PMIC_B3M_SOFT_OCP_WARN_Y,
> +	S2MPG10_PMIC_B3M_SOFT_OCP_WARN_Z,
> +	S2MPG10_PMIC_B10M_SOFT_OCP_WARN,
> +	S2MPG10_PMIC_B10M_SOFT_OCP_WARN_X,
> +	S2MPG10_PMIC_B10M_SOFT_OCP_WARN_Y,
> +	S2MPG10_PMIC_B10M_SOFT_OCP_WARN_Z,
> +	S2MPG10_PMIC_BUCK_OCP_EN1,
> +	S2MPG10_PMIC_BUCK_OCP_EN2,
> +	S2MPG10_PMIC_BUCK_OCP_PD_EN1,
> +	S2MPG10_PMIC_BUCK_OCP_PD_EN2,
> +	S2MPG10_PMIC_BUCK_OCP_CTRL1,
> +	S2MPG10_PMIC_BUCK_OCP_CTRL2,
> +	S2MPG10_PMIC_BUCK_OCP_CTRL3,
> +	S2MPG10_PMIC_BUCK_OCP_CTRL4,
> +	S2MPG10_PMIC_BUCK_OCP_CTRL5,
> +	S2MPG10_PMIC_PIF_CTRL,
> +	S2MPG10_PMIC_BUCK_HR_MODE1,
> +	S2MPG10_PMIC_BUCK_HR_MODE2,
> +	S2MPG10_PMIC_FAULTOUT_CTRL,
> +	S2MPG10_PMIC_LDO_SENSE1,
> +	S2MPG10_PMIC_LDO_SENSE2,
> +	S2MPG10_PMIC_LDO_SENSE3,
> +	S2MPG10_PMIC_LDO_SENSE4,
> +};
> +
> +/* Meter registers (type 0xa00) */
> +enum s2mpg10_meter_reg {
> +	S2MPG10_METER_CTRL1,
> +	S2MPG10_METER_CTRL2,
> +	S2MPG10_METER_CTRL3,
> +	S2MPG10_METER_CTRL4,
> +	S2MPG10_METER_BUCKEN1,
> +	S2MPG10_METER_BUCKEN2,
> +	S2MPG10_METER_MUXSEL0,
> +	S2MPG10_METER_MUXSEL1,
> +	S2MPG10_METER_MUXSEL2,
> +	S2MPG10_METER_MUXSEL3,
> +	S2MPG10_METER_MUXSEL4,
> +	S2MPG10_METER_MUXSEL5,
> +	S2MPG10_METER_MUXSEL6,
> +	S2MPG10_METER_MUXSEL7,
> +	S2MPG10_METER_LPF_C0_0,
> +	S2MPG10_METER_LPF_C0_1,
> +	S2MPG10_METER_LPF_C0_2,
> +	S2MPG10_METER_LPF_C0_3,
> +	S2MPG10_METER_LPF_C0_4,
> +	S2MPG10_METER_LPF_C0_5,
> +	S2MPG10_METER_LPF_C0_6,
> +	S2MPG10_METER_LPF_C0_7,
> +	S2MPG10_METER_PWR_WARN0,
> +	S2MPG10_METER_PWR_WARN1,
> +	S2MPG10_METER_PWR_WARN2,
> +	S2MPG10_METER_PWR_WARN3,
> +	S2MPG10_METER_PWR_WARN4,
> +	S2MPG10_METER_PWR_WARN5,
> +	S2MPG10_METER_PWR_WARN6,
> +	S2MPG10_METER_PWR_WARN7,
> +	S2MPG10_METER_PWR_HYS1,
> +	S2MPG10_METER_PWR_HYS2,
> +	S2MPG10_METER_PWR_HYS3,
> +	S2MPG10_METER_PWR_HYS4,
> +	S2MPG10_METER_ACC_DATA_CH0_1 = 0x40,
> +	S2MPG10_METER_ACC_DATA_CH0_2,
> +	S2MPG10_METER_ACC_DATA_CH0_3,
> +	S2MPG10_METER_ACC_DATA_CH0_4,
> +	S2MPG10_METER_ACC_DATA_CH0_5,
> +	S2MPG10_METER_ACC_DATA_CH0_6,
> +	S2MPG10_METER_ACC_DATA_CH1_1,
> +	S2MPG10_METER_ACC_DATA_CH1_2,
> +	S2MPG10_METER_ACC_DATA_CH1_3,
> +	S2MPG10_METER_ACC_DATA_CH1_4,
> +	S2MPG10_METER_ACC_DATA_CH1_5,
> +	S2MPG10_METER_ACC_DATA_CH1_6,
> +	S2MPG10_METER_ACC_DATA_CH2_1,
> +	S2MPG10_METER_ACC_DATA_CH2_2,
> +	S2MPG10_METER_ACC_DATA_CH2_3,
> +	S2MPG10_METER_ACC_DATA_CH2_4,
> +	S2MPG10_METER_ACC_DATA_CH2_5,
> +	S2MPG10_METER_ACC_DATA_CH2_6,
> +	S2MPG10_METER_ACC_DATA_CH3_1,
> +	S2MPG10_METER_ACC_DATA_CH3_2,
> +	S2MPG10_METER_ACC_DATA_CH3_3,
> +	S2MPG10_METER_ACC_DATA_CH3_4,
> +	S2MPG10_METER_ACC_DATA_CH3_5,
> +	S2MPG10_METER_ACC_DATA_CH3_6,
> +	S2MPG10_METER_ACC_DATA_CH4_1,
> +	S2MPG10_METER_ACC_DATA_CH4_2,
> +	S2MPG10_METER_ACC_DATA_CH4_3,
> +	S2MPG10_METER_ACC_DATA_CH4_4,
> +	S2MPG10_METER_ACC_DATA_CH4_5,
> +	S2MPG10_METER_ACC_DATA_CH4_6,
> +	S2MPG10_METER_ACC_DATA_CH5_1,
> +	S2MPG10_METER_ACC_DATA_CH5_2,
> +	S2MPG10_METER_ACC_DATA_CH5_3,
> +	S2MPG10_METER_ACC_DATA_CH5_4,
> +	S2MPG10_METER_ACC_DATA_CH5_5,
> +	S2MPG10_METER_ACC_DATA_CH5_6,
> +	S2MPG10_METER_ACC_DATA_CH6_1,
> +	S2MPG10_METER_ACC_DATA_CH6_2,
> +	S2MPG10_METER_ACC_DATA_CH6_3,
> +	S2MPG10_METER_ACC_DATA_CH6_4,
> +	S2MPG10_METER_ACC_DATA_CH6_5,
> +	S2MPG10_METER_ACC_DATA_CH6_6,
> +	S2MPG10_METER_ACC_DATA_CH7_1,
> +	S2MPG10_METER_ACC_DATA_CH7_2,
> +	S2MPG10_METER_ACC_DATA_CH7_3,
> +	S2MPG10_METER_ACC_DATA_CH7_4,
> +	S2MPG10_METER_ACC_DATA_CH7_5,
> +	S2MPG10_METER_ACC_DATA_CH7_6,
> +	S2MPG10_METER_ACC_COUNT_1,
> +	S2MPG10_METER_ACC_COUNT_2,
> +	S2MPG10_METER_ACC_COUNT_3,
> +	S2MPG10_METER_LPF_DATA_CH0_1,
> +	S2MPG10_METER_LPF_DATA_CH0_2,
> +	S2MPG10_METER_LPF_DATA_CH0_3,
> +	S2MPG10_METER_LPF_DATA_CH1_1,
> +	S2MPG10_METER_LPF_DATA_CH1_2,
> +	S2MPG10_METER_LPF_DATA_CH1_3,
> +	S2MPG10_METER_LPF_DATA_CH2_1,
> +	S2MPG10_METER_LPF_DATA_CH2_2,
> +	S2MPG10_METER_LPF_DATA_CH2_3,
> +	S2MPG10_METER_LPF_DATA_CH3_1,
> +	S2MPG10_METER_LPF_DATA_CH3_2,
> +	S2MPG10_METER_LPF_DATA_CH3_3,
> +	S2MPG10_METER_LPF_DATA_CH4_1,
> +	S2MPG10_METER_LPF_DATA_CH4_2,
> +	S2MPG10_METER_LPF_DATA_CH4_3,
> +	S2MPG10_METER_LPF_DATA_CH5_1,
> +	S2MPG10_METER_LPF_DATA_CH5_2,
> +	S2MPG10_METER_LPF_DATA_CH5_3,
> +	S2MPG10_METER_LPF_DATA_CH6_1,
> +	S2MPG10_METER_LPF_DATA_CH6_2,
> +	S2MPG10_METER_LPF_DATA_CH6_3,
> +	S2MPG10_METER_LPF_DATA_CH7_1,
> +	S2MPG10_METER_LPF_DATA_CH7_2,
> +	S2MPG10_METER_LPF_DATA_CH7_3,
> +	S2MPG10_METER_DSM_TRIM_OFFSET = 0xee,
> +	S2MPG10_METER_BUCK_METER_TRIM3 = 0xf1,
> +};
> +
> +/* S2MPG10 regulator IDs */
> +enum s2mpg10_regulators {
> +	S2MPG10_LDO1,
> +	S2MPG10_LDO2,
> +	S2MPG10_LDO3,
> +	S2MPG10_LDO4,
> +	S2MPG10_LDO5,
> +	S2MPG10_LDO6,
> +	S2MPG10_LDO7,
> +	S2MPG10_LDO8,
> +	S2MPG10_LDO9,
> +	S2MPG10_LDO10,
> +	S2MPG10_LDO11,
> +	S2MPG10_LDO12,
> +	S2MPG10_LDO13,
> +	S2MPG10_LDO14,
> +	S2MPG10_LDO15,
> +	S2MPG10_LDO16,
> +	S2MPG10_LDO17,
> +	S2MPG10_LDO18,
> +	S2MPG10_LDO19,
> +	S2MPG10_LDO20,
> +	S2MPG10_LDO21,
> +	S2MPG10_LDO22,
> +	S2MPG10_LDO23,
> +	S2MPG10_LDO24,
> +	S2MPG10_LDO25,
> +	S2MPG10_LDO26,
> +	S2MPG10_LDO27,
> +	S2MPG10_LDO28,
> +	S2MPG10_LDO29,
> +	S2MPG10_LDO30,
> +	S2MPG10_LDO31,
> +	S2MPG10_BUCK1,
> +	S2MPG10_BUCK2,
> +	S2MPG10_BUCK3,
> +	S2MPG10_BUCK4,
> +	S2MPG10_BUCK5,
> +	S2MPG10_BUCK6,
> +	S2MPG10_BUCK7,
> +	S2MPG10_BUCK8,
> +	S2MPG10_BUCK9,
> +	S2MPG10_BUCK10,
> +	S2MPG10_REGULATOR_MAX,
> +};
> +
> +#endif /* __LINUX_MFD_S2MPG10_H */
> 
> -- 
> 2.49.0.472.ge94155a9ec-goog
>
Lee Jones April 4, 2025, 9:27 a.m. UTC | #2
On Thu, 03 Apr 2025, André Draszik wrote:

> checkpatch complains about unexpected alignment issues in this file -

Fine, but either call it by it's name 'Checkpatch' or the command 'checkpatch.pl'.

> update the code accordingly.

This phrasing and grammar is odd.  How about?

  Subject: mfd: sec-common: Fix multiple trivial whitespace issues

  Rectify a couple of alignment problems reported by Checkpatch.

> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> 
> ---
> v2:
> * make new alignment more readable (Krzysztof)
> ---
>  drivers/mfd/sec-common.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
> index 782dec1956a5fd7bf0dbb2159f9d222ad3fea942..1a6f14dda825adeaeee1a677459c7399c144d553 100644
> --- a/drivers/mfd/sec-common.c
> +++ b/drivers/mfd/sec-common.c
> @@ -149,9 +149,9 @@ sec_pmic_parse_dt_pdata(struct device *dev)
>  		return ERR_PTR(-ENOMEM);
>  
>  	pd->manual_poweroff = of_property_read_bool(dev->of_node,
> -						"samsung,s2mps11-acokb-ground");
> +						    "samsung,s2mps11-acokb-ground");
>  	pd->disable_wrstbi = of_property_read_bool(dev->of_node,
> -						"samsung,s2mps11-wrstbi-ground");
> +						   "samsung,s2mps11-wrstbi-ground");
>  	return pd;
>  }
>  
> @@ -264,8 +264,8 @@ void sec_pmic_shutdown(struct device *dev)
>  		 * ignore the rest.
>  		 */
>  		dev_warn(sec_pmic->dev,
> -			"Unsupported device %lu for manual power off\n",
> -			sec_pmic->device_type);
> +			 "Unsupported device %lu for manual power off\n",
> +			 sec_pmic->device_type);
>  		return;
>  	}
>  
> 
> -- 
> 2.49.0.472.ge94155a9ec-goog
>
Lee Jones April 4, 2025, 9:34 a.m. UTC | #3
Patch is fine, but the subject line should be more assertive.

Also, there is seldom any need for sub-sentences in ()'s in them.

IOW, drop the "(it seems)" part.

> The commit bf231e5febcf ("mfd: sec-core: Add support for the Samsung
> s2dos05") adding s2dos05 support didn't add anything related to IRQ
> support, so I assume this works without IRQs.
> 
> Rather than printing a warning message in sec_irq_init() due to the
> missing IRQ number, or returning an error due to a missing irq chip
> regmap, just return early explicitly.
> 
> This will become particularly important once errors from sec_irq_init()
> aren't ignored anymore in an upcoming patch and helps the reader of
> this code while reasoning about what the intention might be here.
> 
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> ---
>  drivers/mfd/sec-irq.c | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
> index 9f0173c48b0c8186a2cdc1d2179db081ef2e09c4..79a3b33441fa5ab48b4b233eb8d89b4c20c142ed 100644
> --- a/drivers/mfd/sec-irq.c
> +++ b/drivers/mfd/sec-irq.c
> @@ -452,16 +452,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
>  	int type = sec_pmic->device_type;
>  	const struct regmap_irq_chip *sec_irq_chip;
>  
> -	if (!sec_pmic->irq) {
> -		dev_warn(sec_pmic->dev,
> -			 "No interrupt specified, no interrupts\n");
> -		return 0;
> -	}
> -
>  	switch (type) {
>  	case S5M8767X:
>  		sec_irq_chip = &s5m8767_irq_chip;
>  		break;
> +	case S2DOS05:
> +		return 0;
>  	case S2MPA01:
>  		sec_irq_chip = &s2mps14_irq_chip;
>  		break;
> @@ -492,6 +488,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
>  				     sec_pmic->device_type);
>  	}
>  
> +	if (!sec_pmic->irq) {
> +		dev_warn(sec_pmic->dev,
> +			 "No interrupt specified, no interrupts\n");
> +		return 0;
> +	}
> +
>  	ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
>  				       sec_pmic->irq, IRQF_ONESHOT,
>  				       0, sec_irq_chip, &sec_pmic->irq_data);
> 
> -- 
> 2.49.0.472.ge94155a9ec-goog
>
Lee Jones April 4, 2025, 9:43 a.m. UTC | #4
On Thu, 03 Apr 2025, André Draszik wrote:

> This series adds initial support for the Samsung S2MPG10 PMIC using the
> MFD framework. This is a PMIC for mobile applications and is used on
> the Google Pixel 6 and 6 Pro (oriole / raven).

Okay, review complete.

If I didn't comment on a patch, it means I didn't see any issues with it.

However, saying that, it doesn't mean I won't spot something next time.  :)
Krzysztof Kozlowski April 4, 2025, 12:09 p.m. UTC | #5
On Thu, Apr 03, 2025 at 09:58:55AM GMT, André Draszik wrote:
> The PMIC is supposed to be a child of ACPM, add it here to describe the
> connection.
> 
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> 
> ---
> v3:
> - drop '$ref' and 'unevaluatedProperties' from pmic subnode, use
>   'additionalProperties' instead (Krzysztof)
> - add some regulators to examples since s2mpg10 requires them as of v3
> ---
>  .../bindings/firmware/google,gs101-acpm-ipc.yaml   | 35 ++++++++++++++++++++++
>  1 file changed, 35 insertions(+)

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof