From cf5c739af8ff024a211ece4381ea71874428607b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 7 Apr 2025 09:24:15 +0200 Subject: [PATCH 01/16] mfd: ucb1x00: Use new GPIO line value setter callbacks struct gpio_chip now has callbacks for setting line values that return an integer, allowing to indicate failures. Convert the driver to using them. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20250407-gpiochip-set-rv-mfd-v1-3-43f4d86d01d1@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/ucb1x00-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index fc4d4c844a81..fd71ba29f6b5 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -104,7 +104,8 @@ unsigned int ucb1x00_io_read(struct ucb1x00 *ucb) return ucb1x00_reg_read(ucb, UCB_IO_DATA); } -static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int ucb1x00_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct ucb1x00 *ucb = gpiochip_get_data(chip); unsigned long flags; @@ -119,6 +120,8 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out); ucb1x00_disable(ucb); spin_unlock_irqrestore(&ucb->io_lock, flags); + + return 0; } static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -567,7 +570,7 @@ static int ucb1x00_probe(struct mcp *mcp) ucb->gpio.owner = THIS_MODULE; ucb->gpio.base = pdata->gpio_base; ucb->gpio.ngpio = 10; - ucb->gpio.set = ucb1x00_gpio_set; + ucb->gpio.set_rv = ucb1x00_gpio_set; ucb->gpio.get = ucb1x00_gpio_get; ucb->gpio.direction_input = ucb1x00_gpio_direction_input; ucb->gpio.direction_output = ucb1x00_gpio_direction_output; -- 2.50.1 From 9c998b9d3128d6def5f0517342714c0721042462 Mon Sep 17 00:00:00 2001 From: Ryan Wanner Date: Mon, 14 Apr 2025 14:41:23 -0700 Subject: [PATCH 02/16] dt-bindings: mfd: atmel: Add microchip,sama7d65-gpbr Add SAMA7D65 GPBR compatible to DT bindings documentation. Signed-off-by: Ryan Wanner Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/ddbcb306699b8c09f3210d714c0701afa1a7cb96.1744666011.git.Ryan.Wanner@microchip.com Signed-off-by: Lee Jones --- .../devicetree/bindings/mfd/atmel,at91sam9260-gpbr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/atmel,at91sam9260-gpbr.yaml b/Documentation/devicetree/bindings/mfd/atmel,at91sam9260-gpbr.yaml index f805545aa62a..f6f47999c6c1 100644 --- a/Documentation/devicetree/bindings/mfd/atmel,at91sam9260-gpbr.yaml +++ b/Documentation/devicetree/bindings/mfd/atmel,at91sam9260-gpbr.yaml @@ -19,6 +19,7 @@ properties: - items: - enum: - atmel,at91sam9260-gpbr + - microchip,sama7d65-gpbr - const: syscon - items: - enum: -- 2.50.1 From f7c636be96a151ce86f9291bed31145b61e50261 Mon Sep 17 00:00:00 2001 From: Ryan Wanner Date: Mon, 14 Apr 2025 14:41:24 -0700 Subject: [PATCH 03/16] dt-bindings: mfd: syscon: atmel,sama5d2-secumod: Convert to yaml Convert Microchip AT91 secumod to YAML format. Signed-off-by: Ryan Wanner Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/a999a719a652ec834f1176d69a3e9b207cbd63e6.1744666011.git.Ryan.Wanner@microchip.com Signed-off-by: Lee Jones --- .../bindings/arm/atmel,sama5d2-secumod.yaml | 48 +++++++++++++++++++ .../devicetree/bindings/arm/atmel-sysregs.txt | 25 ---------- 2 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml diff --git a/Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml b/Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml new file mode 100644 index 000000000000..b1f766e333d4 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/atmel,sama5d2-secumod.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip AT91 Security Module (SECUMOD) + +maintainers: + - Nicolas Ferre + +description: + The Security Module also offers the PIOBU pins which can be used as GPIO pins. + Note that they maintain their voltage during Backup/Self-refresh. + +properties: + compatible: + oneOf: + - items: + - const: atmel,sama5d2-secumod + - const: syscon + - items: + - enum: + - microchip,sama7g5-secumod + - const: atmel,sama5d2-secumod + - const: syscon + reg: + maxItems: 1 + + gpio-controller: true + + "#gpio-cells": + const: 2 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + security-module@fc040000 { + compatible = "atmel,sama5d2-secumod", "syscon"; + reg = <0xfc040000 0x100>; + gpio-controller; + #gpio-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt index d3821f651e72..5ce54f9befe6 100644 --- a/Documentation/devicetree/bindings/arm/atmel-sysregs.txt +++ b/Documentation/devicetree/bindings/arm/atmel-sysregs.txt @@ -46,28 +46,3 @@ Examples: reg = <0xffffe800 0x200>; }; -Security Module (SECUMOD) - -The Security Module macrocell provides all necessary secure functions to avoid -voltage, temperature, frequency and mechanical attacks on the chip. It also -embeds secure memories that can be scrambled. - -The Security Module also offers the PIOBU pins which can be used as GPIO pins. -Note that they maintain their voltage during Backup/Self-refresh. - -required properties: -- compatible: Should be "atmel,-secumod", "syscon". - can be "sama5d2". -- reg: Should contain registers location and length -- gpio-controller: Marks the port as GPIO controller. -- #gpio-cells: There are 2. The pin number is the - first, the second represents additional - parameters such as GPIO_ACTIVE_HIGH/LOW. - - - secumod@fc040000 { - compatible = "atmel,sama5d2-secumod", "syscon"; - reg = <0xfc040000 0x100>; - gpio-controller; - #gpio-cells = <2>; - }; -- 2.50.1 From 20e805cec0641697079a5d41f732573d7eb9be01 Mon Sep 17 00:00:00 2001 From: Ryan Wanner Date: Mon, 14 Apr 2025 14:41:25 -0700 Subject: [PATCH 04/16] dt-bindings: mfd: syscon: Add microchip,sama7d65-secumod Add SAMA7D65 SECUMOD compatible string to DT bindings documentation. Signed-off-by: Ryan Wanner Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/2fdd14313d9cf008dbc4a63a91ba0cb5cf372ad6.1744666011.git.Ryan.Wanner@microchip.com Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml b/Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml index b1f766e333d4..ad4a98a4ee67 100644 --- a/Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml +++ b/Documentation/devicetree/bindings/arm/atmel,sama5d2-secumod.yaml @@ -21,6 +21,7 @@ properties: - const: syscon - items: - enum: + - microchip,sama7d65-secumod - microchip,sama7g5-secumod - const: atmel,sama5d2-secumod - const: syscon -- 2.50.1 From 72d856ee1927442cefe97a159fde347e59555f88 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:22 +0100 Subject: [PATCH 05/16] dt-bindings: mfd: samsung,s2mps11: add s2mpg10 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The Samsung S2MPG10 PMIC is similar to the existing PMICs supported by this binding. It is a Power Management IC for mobile applications with buck converters, various LDOs, power meters, RTC, clock outputs, and additional GPIOs interfaces. Unlike other Samsung PMICs, communication is not via I2C, but via the Samsung ACPM firmware, it therefore doesn't need a 'reg' property but needs to be a child of the ACPM firmware node instead. S2MPG10 can also act as a system power controller allowing implementation of a true cold-reset of the system. Support for the other components like regulators and power meters will be added in subsequent future patches. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-1-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- .../bindings/mfd/samsung,s2mps11.yaml | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml index ac5d0c149796..d6b9e2914796 100644 --- a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml +++ b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml @@ -20,6 +20,7 @@ description: | properties: compatible: enum: + - samsung,s2mpg10-pmic - samsung,s2mps11-pmic - samsung,s2mps13-pmic - samsung,s2mps14-pmic @@ -58,16 +59,39 @@ properties: reset (setting buck voltages to default values). type: boolean + system-power-controller: true + wakeup-source: true required: - compatible - - reg - regulators additionalProperties: false allOf: + - if: + properties: + compatible: + contains: + const: samsung,s2mpg10-pmic + then: + properties: + reg: false + samsung,s2mps11-acokb-ground: false + samsung,s2mps11-wrstbi-ground: false + + oneOf: + - required: [interrupts] + - required: [interrupts-extended] + + else: + properties: + system-power-controller: false + + required: + - reg + - if: properties: compatible: -- 2.50.1 From b3379422b460ea8c0556df300d547d63e5569cda Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:25 +0100 Subject: [PATCH 06/16] mfd: sec-core: Drop non-existing forward declarations MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit sec_irq_resume() was removed in commit 6445b84abf91 ("mfd: Add s2mps11 irq driver") and sec_irq_exit() in commit 3dc6f4aaafbe ("mfd: sec: Use devm_mfd_add_devices and devm_regmap_add_irq_chip") while the prototypes were left. They should be removed. Do so. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-4-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- include/linux/mfd/samsung/core.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index f35314458fd2..b7008b50392a 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -72,8 +72,6 @@ struct sec_pmic_dev { }; int sec_irq_init(struct sec_pmic_dev *sec_pmic); -void sec_irq_exit(struct sec_pmic_dev *sec_pmic); -int sec_irq_resume(struct sec_pmic_dev *sec_pmic); struct sec_platform_data { struct sec_regulator_data *regulators; -- 2.50.1 From 271dc4fbede4274d0729eec10a33bd772df2837a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:26 +0100 Subject: [PATCH 07/16] mfd: sec: Sort includes alphabetically MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Sorting headers alphabetically helps locating duplicates, and makes it easier to figure out where to insert new headers. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-5-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 14 +++++++------- drivers/mfd/sec-irq.c | 5 ++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 3e9b65c988a7..e31b3a6fbc89 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -3,16 +3,10 @@ // Copyright (c) 2012 Samsung Electronics Co., Ltd // http://www.samsung.com -#include -#include -#include #include -#include #include -#include +#include #include -#include -#include #include #include #include @@ -23,7 +17,13 @@ #include #include #include +#include +#include +#include +#include +#include #include +#include static const struct mfd_cell s5m8767_devs[] = { { .name = "s5m8767-pmic", }, diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index 047fc065fcf1..5c0d949aa1a2 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -6,9 +6,6 @@ #include #include #include -#include -#include - #include #include #include @@ -16,6 +13,8 @@ #include #include #include +#include +#include static const struct regmap_irq s2mps11_irqs[] = { [S2MPS11_IRQ_PWRONF] = { -- 2.50.1 From 5bef1b7f10a81b61863f11aaa146a773cbc64e61 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:27 +0100 Subject: [PATCH 08/16] mfd: sec: Update includes to add missing and remove superfluous ones MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This driver misses to include some of the respective headers of some of the APIs used. It also includes headers that aren't needed (e.g. due to previous driver rework where includes weren't updated). It is good practice to directly include all headers used, which avoids implicit dependencies and spurious build breakage if someone rearranged headers, as this could cause the implicit includes to be dropped. Include the relevant headers explicitly and drop superfluous ones. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-6-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/sec-core.c | 7 +++---- drivers/mfd/sec-irq.c | 5 ++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index e31b3a6fbc89..b12020c416aa 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -3,9 +3,9 @@ // Copyright (c) 2012 Samsung Electronics Co., Ltd // http://www.samsung.com +#include #include #include -#include #include #include #include @@ -17,13 +17,12 @@ #include #include #include +#include #include -#include -#include #include +#include #include #include -#include static const struct mfd_cell s5m8767_devs[] = { { .name = "s5m8767-pmic", }, diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index 5c0d949aa1a2..3ed2902c3a26 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -3,7 +3,10 @@ // Copyright (c) 2011-2014 Samsung Electronics Co., Ltd // http://www.samsung.com -#include +#include +#include +#include +#include #include #include #include -- 2.50.1 From 8b88b5e4d58151d8a37250afc978f253cd8cc4fb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:28 +0100 Subject: [PATCH 09/16] mfd: sec: Move private internal API to internal header MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit sec_irq_init() is an internal API for the core driver, and doesn't belong into the public header. Due to an upcoming split of the driver into a core and i2c driver, we'll also be adding more internal APIs, which again shouldn't be in the public header. Move it into a new internal include. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-7-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- MAINTAINERS | 2 +- drivers/mfd/sec-core.c | 1 + drivers/mfd/sec-core.h | 15 +++++++++++++++ drivers/mfd/sec-irq.c | 1 + include/linux/mfd/samsung/core.h | 2 -- 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 drivers/mfd/sec-core.h diff --git a/MAINTAINERS b/MAINTAINERS index f4af323fe84f..b173fcca2b94 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21457,7 +21457,7 @@ F: Documentation/devicetree/bindings/mfd/samsung,s5m*.yaml F: Documentation/devicetree/bindings/regulator/samsung,s2m*.yaml F: Documentation/devicetree/bindings/regulator/samsung,s5m*.yaml F: drivers/clk/clk-s2mps11.c -F: drivers/mfd/sec*.c +F: drivers/mfd/sec*.[ch] F: drivers/regulator/s2m*.c F: drivers/regulator/s5m*.c F: drivers/rtc/rtc-s5m.c diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index b12020c416aa..83693686567d 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -23,6 +23,7 @@ #include #include #include +#include "sec-core.h" static const struct mfd_cell s5m8767_devs[] = { { .name = "s5m8767-pmic", }, diff --git a/drivers/mfd/sec-core.h b/drivers/mfd/sec-core.h new file mode 100644 index 000000000000..b3fded5f02a0 --- /dev/null +++ b/drivers/mfd/sec-core.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * http://www.samsung.com + * Copyright 2025 Linaro Ltd. + * + * Samsung SxM core driver internal data + */ + +#ifndef __SEC_CORE_INT_H +#define __SEC_CORE_INT_H + +int sec_irq_init(struct sec_pmic_dev *sec_pmic); + +#endif /* __SEC_CORE_INT_H */ diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index 3ed2902c3a26..4d49bb42bd0d 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -18,6 +18,7 @@ #include #include #include +#include "sec-core.h" static const struct regmap_irq s2mps11_irqs[] = { [S2MPS11_IRQ_PWRONF] = { diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index b7008b50392a..8a4e660854bb 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -71,8 +71,6 @@ struct sec_pmic_dev { struct regmap_irq_chip_data *irq_data; }; -int sec_irq_init(struct sec_pmic_dev *sec_pmic); - struct sec_platform_data { struct sec_regulator_data *regulators; struct sec_opmode_data *opmode; -- 2.50.1 From 680ef57915db0f715e99a683c15f0f9f7c700e64 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:29 +0100 Subject: [PATCH 10/16] mfd: sec: Split into core and transport (i2c) drivers MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit As a preparation for adding support for Samsung's S2MPG10, which is connected via SPEEDY / ACPM rather than I2C, split out (move) all I2C-specific driver code into its own kernel module, sec-i2c, and make the existing sec-core module be just the transport-agnostic core driver kernel module. At the same time, update all defconfigs that reference the old kconfig symbol name. While at it, also update file header comments and module description(s) to drop references to 'mfd', and update comments to be C-style, not C++. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-8-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- 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/mfd/Kconfig | 18 +- drivers/mfd/Makefile | 1 + drivers/mfd/sec-core.c | 247 ++++------------------------ drivers/mfd/sec-core.h | 9 + drivers/mfd/sec-i2c.c | 231 ++++++++++++++++++++++++++ 9 files changed, 287 insertions(+), 227 deletions(-) create mode 100644 drivers/mfd/sec-i2c.c diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 7ad48fdda1da..251f45be6c14 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -167,7 +167,7 @@ CONFIG_MFD_MAX77686=y CONFIG_MFD_MAX77693=y CONFIG_MFD_MAX8997=y CONFIG_MFD_MAX8998=y -CONFIG_MFD_SEC_CORE=y +CONFIG_MFD_SEC_I2C=y CONFIG_MFD_STMPE=y CONFIG_STMPE_I2C=y CONFIG_MFD_TPS65090=y diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index ad037c175fdb..7d06ac5369b1 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -612,7 +612,7 @@ CONFIG_MFD_QCOM_RPM=y CONFIG_MFD_SPMI_PMIC=y CONFIG_MFD_RK8XX_I2C=y CONFIG_MFD_RN5T618=y -CONFIG_MFD_SEC_CORE=y +CONFIG_MFD_SEC_I2C=y CONFIG_MFD_STMPE=y CONFIG_MFD_PALMAS=y CONFIG_MFD_TPS65090=y diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig index de0ac8f521d7..064e79baf20d 100644 --- a/arch/arm/configs/pxa_defconfig +++ b/arch/arm/configs/pxa_defconfig @@ -335,7 +335,7 @@ CONFIG_MFD_MAX77693=y CONFIG_MFD_MAX8907=m CONFIG_EZX_PCAP=y CONFIG_UCB1400_CORE=m -CONFIG_MFD_SEC_CORE=y +CONFIG_MFD_SEC_I2C=y CONFIG_MFD_PALMAS=y CONFIG_MFD_TPS65090=y CONFIG_MFD_TPS6586X=y diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 5bb8f09422a2..f021fb29683b 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -769,7 +769,7 @@ CONFIG_MFD_MT6397=y CONFIG_MFD_SPMI_PMIC=y CONFIG_MFD_RK8XX_I2C=y CONFIG_MFD_RK8XX_SPI=y -CONFIG_MFD_SEC_CORE=y +CONFIG_MFD_SEC_I2C=y CONFIG_MFD_SL28CPLD=y CONFIG_RZ_MTU3=y CONFIG_MFD_TI_AM335X_TSCADC=m diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 96992af22565..3cde836b3799 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1312,21 +1312,25 @@ config MFD_RN5T618 functionality of the device. config MFD_SEC_CORE - tristate "Samsung Electronics PMIC Series Support" + tristate + select MFD_CORE + select REGMAP_IRQ + +config MFD_SEC_I2C + tristate "Samsung Electronics S2MPA/S2MPS1X/S2MPU/S5M series PMICs" depends on I2C=y depends on OF - select MFD_CORE + select MFD_SEC_CORE select REGMAP_I2C - select REGMAP_IRQ help - Support for the Samsung Electronics PMIC devices coming - usually along with Samsung Exynos SoC chipset. + Support for the Samsung Electronics PMIC devices with I2C interface + coming usually along with Samsung Exynos SoC chipset. This driver provides common support for accessing the device, additional drivers must be enabled in order to use the functionality - of the device + of the device. To compile this driver as a module, choose M here: the - module will be called sec-core. + module will be called sec-i2c. Have in mind that important core drivers (like regulators) depend on this driver so building this as a module might require proper initial ramdisk or might not boot up as well in certain scenarios. diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 5e5cc279af60..363ec7eb827a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -230,6 +230,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_I2C) += sec-i2c.o obj-$(CONFIG_MFD_SYSCON) += syscon.o obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o obj-$(CONFIG_MFD_VEXPRESS_SYSREG) += vexpress-sysreg.o diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 83693686567d..bb664e052bf5 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -1,23 +1,21 @@ // SPDX-License-Identifier: GPL-2.0+ -// -// Copyright (c) 2012 Samsung Electronics Co., Ltd -// http://www.samsung.com +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * http://www.samsung.com + * Copyright 2025 Linaro Ltd. + * + * Samsung SxM core driver + */ #include #include -#include +#include #include #include #include #include -#include #include #include -#include -#include -#include -#include -#include #include #include #include @@ -88,144 +86,6 @@ static const struct mfd_cell s2mpu05_devs[] = { { .name = "s2mps15-rtc", }, }; -static const struct of_device_id sec_dt_match[] = { - { - .compatible = "samsung,s5m8767-pmic", - .data = (void *)S5M8767X, - }, { - .compatible = "samsung,s2dos05", - .data = (void *)S2DOS05, - }, { - .compatible = "samsung,s2mps11-pmic", - .data = (void *)S2MPS11X, - }, { - .compatible = "samsung,s2mps13-pmic", - .data = (void *)S2MPS13X, - }, { - .compatible = "samsung,s2mps14-pmic", - .data = (void *)S2MPS14X, - }, { - .compatible = "samsung,s2mps15-pmic", - .data = (void *)S2MPS15X, - }, { - .compatible = "samsung,s2mpa01-pmic", - .data = (void *)S2MPA01, - }, { - .compatible = "samsung,s2mpu02-pmic", - .data = (void *)S2MPU02, - }, { - .compatible = "samsung,s2mpu05-pmic", - .data = (void *)S2MPU05, - }, { - /* Sentinel */ - }, -}; -MODULE_DEVICE_TABLE(of, sec_dt_match); - -static bool s2mpa01_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case S2MPA01_REG_INT1M: - case S2MPA01_REG_INT2M: - case S2MPA01_REG_INT3M: - return false; - default: - return true; - } -} - -static bool s2mps11_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case S2MPS11_REG_INT1M: - case S2MPS11_REG_INT2M: - case S2MPS11_REG_INT3M: - return false; - default: - return true; - } -} - -static bool s2mpu02_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case S2MPU02_REG_INT1M: - case S2MPU02_REG_INT2M: - case S2MPU02_REG_INT3M: - return false; - default: - return true; - } -} - -static const struct regmap_config sec_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -}; - -static const struct regmap_config s2mpa01_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = S2MPA01_REG_LDO_OVCB4, - .volatile_reg = s2mpa01_volatile, - .cache_type = REGCACHE_FLAT, -}; - -static const struct regmap_config s2mps11_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = S2MPS11_REG_L38CTRL, - .volatile_reg = s2mps11_volatile, - .cache_type = REGCACHE_FLAT, -}; - -static const struct regmap_config s2mps13_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = S2MPS13_REG_LDODSCH5, - .volatile_reg = s2mps11_volatile, - .cache_type = REGCACHE_FLAT, -}; - -static const struct regmap_config s2mps14_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = S2MPS14_REG_LDODSCH3, - .volatile_reg = s2mps11_volatile, - .cache_type = REGCACHE_FLAT, -}; - -static const struct regmap_config s2mps15_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = S2MPS15_REG_LDODSCH4, - .volatile_reg = s2mps11_volatile, - .cache_type = REGCACHE_FLAT, -}; - -static const struct regmap_config s2mpu02_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = S2MPU02_REG_DVSDATA, - .volatile_reg = s2mpu02_volatile, - .cache_type = REGCACHE_FLAT, -}; - -static const struct regmap_config s5m8767_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = S5M8767_REG_LDO28CTRL, - .volatile_reg = s2mps11_volatile, - .cache_type = REGCACHE_FLAT, -}; - static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic) { unsigned int val; @@ -268,7 +128,7 @@ static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic) * platform data. */ static struct sec_platform_data * -sec_pmic_i2c_parse_dt_pdata(struct device *dev) +sec_pmic_parse_dt_pdata(struct device *dev) { struct sec_platform_data *pd; @@ -283,68 +143,34 @@ sec_pmic_i2c_parse_dt_pdata(struct device *dev) return pd; } -static int sec_pmic_probe(struct i2c_client *i2c) +int sec_pmic_probe(struct device *dev, unsigned long device_type, + unsigned int irq, struct regmap *regmap, + struct i2c_client *client) { - const struct regmap_config *regmap; struct sec_platform_data *pdata; const struct mfd_cell *sec_devs; struct sec_pmic_dev *sec_pmic; int ret, num_sec_devs; - sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev), - GFP_KERNEL); + sec_pmic = devm_kzalloc(dev, sizeof(struct sec_pmic_dev), GFP_KERNEL); if (sec_pmic == NULL) return -ENOMEM; - i2c_set_clientdata(i2c, sec_pmic); - sec_pmic->dev = &i2c->dev; - sec_pmic->i2c = i2c; - sec_pmic->irq = i2c->irq; + dev_set_drvdata(dev, sec_pmic); + sec_pmic->dev = dev; + sec_pmic->device_type = device_type; + sec_pmic->i2c = client; + sec_pmic->irq = irq; + sec_pmic->regmap_pmic = regmap; - pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev); + pdata = sec_pmic_parse_dt_pdata(sec_pmic->dev); if (IS_ERR(pdata)) { ret = PTR_ERR(pdata); return ret; } - sec_pmic->device_type = (unsigned long)of_device_get_match_data(sec_pmic->dev); sec_pmic->pdata = pdata; - switch (sec_pmic->device_type) { - case S2MPA01: - regmap = &s2mpa01_regmap_config; - break; - case S2MPS11X: - regmap = &s2mps11_regmap_config; - break; - case S2MPS13X: - regmap = &s2mps13_regmap_config; - break; - case S2MPS14X: - regmap = &s2mps14_regmap_config; - break; - case S2MPS15X: - regmap = &s2mps15_regmap_config; - break; - case S5M8767X: - regmap = &s5m8767_regmap_config; - break; - case S2MPU02: - regmap = &s2mpu02_regmap_config; - break; - default: - regmap = &sec_regmap_config; - break; - } - - sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap); - if (IS_ERR(sec_pmic->regmap_pmic)) { - ret = PTR_ERR(sec_pmic->regmap_pmic); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - sec_irq_init(sec_pmic); pm_runtime_set_active(sec_pmic->dev); @@ -387,9 +213,9 @@ static int sec_pmic_probe(struct i2c_client *i2c) num_sec_devs = ARRAY_SIZE(s2mpu05_devs); break; default: - dev_err(&i2c->dev, "Unsupported device type (%lu)\n", + dev_err(sec_pmic->dev, "Unsupported device type %lu\n", sec_pmic->device_type); - return -ENODEV; + return -EINVAL; } ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL, 0, NULL); @@ -401,10 +227,11 @@ static int sec_pmic_probe(struct i2c_client *i2c) return ret; } +EXPORT_SYMBOL_GPL(sec_pmic_probe); -static void sec_pmic_shutdown(struct i2c_client *i2c) +void sec_pmic_shutdown(struct device *dev) { - struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev); unsigned int reg, mask; if (!sec_pmic->pdata->manual_poweroff) @@ -428,11 +255,11 @@ static void sec_pmic_shutdown(struct i2c_client *i2c) regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0); } +EXPORT_SYMBOL_GPL(sec_pmic_shutdown); static int sec_pmic_suspend(struct device *dev) { - struct i2c_client *i2c = to_i2c_client(dev); - struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev); if (device_may_wakeup(dev)) enable_irq_wake(sec_pmic->irq); @@ -452,8 +279,7 @@ static int sec_pmic_suspend(struct device *dev) static int sec_pmic_resume(struct device *dev) { - struct i2c_client *i2c = to_i2c_client(dev); - struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + struct sec_pmic_dev *sec_pmic = dev_get_drvdata(dev); if (device_may_wakeup(dev)) disable_irq_wake(sec_pmic->irq); @@ -462,20 +288,9 @@ static int sec_pmic_resume(struct device *dev) return 0; } -static DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, - sec_pmic_suspend, sec_pmic_resume); - -static struct i2c_driver sec_pmic_driver = { - .driver = { - .name = "sec_pmic", - .pm = pm_sleep_ptr(&sec_pmic_pm_ops), - .of_match_table = sec_dt_match, - }, - .probe = sec_pmic_probe, - .shutdown = sec_pmic_shutdown, -}; -module_i2c_driver(sec_pmic_driver); +DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); +EXPORT_SYMBOL_GPL(sec_pmic_pm_ops); MODULE_AUTHOR("Sangbeom Kim "); -MODULE_DESCRIPTION("Core support for the S5M MFD"); +MODULE_DESCRIPTION("Core driver for the Samsung S5M"); MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/sec-core.h b/drivers/mfd/sec-core.h index b3fded5f02a0..a0a3488924d9 100644 --- a/drivers/mfd/sec-core.h +++ b/drivers/mfd/sec-core.h @@ -10,6 +10,15 @@ #ifndef __SEC_CORE_INT_H #define __SEC_CORE_INT_H +struct i2c_client; + +extern const struct dev_pm_ops sec_pmic_pm_ops; + +int sec_pmic_probe(struct device *dev, unsigned long device_type, + unsigned int irq, struct regmap *regmap, + struct i2c_client *client); +void sec_pmic_shutdown(struct device *dev); + int sec_irq_init(struct sec_pmic_dev *sec_pmic); #endif /* __SEC_CORE_INT_H */ diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c new file mode 100644 index 000000000000..8e3a365ff3e5 --- /dev/null +++ b/drivers/mfd/sec-i2c.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * http://www.samsung.com + * Copyright 2025 Linaro Ltd. + * + * Samsung SxM I2C driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sec-core.h" + +static bool s2mpa01_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case S2MPA01_REG_INT1M: + case S2MPA01_REG_INT2M: + case S2MPA01_REG_INT3M: + return false; + default: + return true; + } +} + +static bool s2mps11_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case S2MPS11_REG_INT1M: + case S2MPS11_REG_INT2M: + case S2MPS11_REG_INT3M: + return false; + default: + return true; + } +} + +static bool s2mpu02_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case S2MPU02_REG_INT1M: + case S2MPU02_REG_INT2M: + case S2MPU02_REG_INT3M: + return false; + default: + return true; + } +} + +static const struct regmap_config sec_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static const struct regmap_config s2mpa01_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPA01_REG_LDO_OVCB4, + .volatile_reg = s2mpa01_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config s2mps11_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS11_REG_L38CTRL, + .volatile_reg = s2mps11_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config s2mps13_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS13_REG_LDODSCH5, + .volatile_reg = s2mps11_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config s2mps14_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS14_REG_LDODSCH3, + .volatile_reg = s2mps11_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config s2mps15_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS15_REG_LDODSCH4, + .volatile_reg = s2mps11_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config s2mpu02_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPU02_REG_DVSDATA, + .volatile_reg = s2mpu02_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static const struct regmap_config s5m8767_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S5M8767_REG_LDO28CTRL, + .volatile_reg = s2mps11_volatile, + .cache_type = REGCACHE_FLAT, +}; + +static int sec_pmic_i2c_probe(struct i2c_client *client) +{ + const struct regmap_config *regmap; + unsigned long device_type; + struct regmap *regmap_pmic; + int ret; + + device_type = (unsigned long)of_device_get_match_data(&client->dev); + + switch (device_type) { + case S2MPA01: + regmap = &s2mpa01_regmap_config; + break; + case S2MPS11X: + regmap = &s2mps11_regmap_config; + break; + case S2MPS13X: + regmap = &s2mps13_regmap_config; + break; + case S2MPS14X: + regmap = &s2mps14_regmap_config; + break; + case S2MPS15X: + regmap = &s2mps15_regmap_config; + break; + case S5M8767X: + regmap = &s5m8767_regmap_config; + break; + case S2MPU02: + regmap = &s2mpu02_regmap_config; + break; + default: + regmap = &sec_regmap_config; + break; + } + + regmap_pmic = devm_regmap_init_i2c(client, regmap); + if (IS_ERR(regmap_pmic)) { + ret = PTR_ERR(regmap_pmic); + dev_err(&client->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + return sec_pmic_probe(&client->dev, device_type, client->irq, + regmap_pmic, client); +} + +static void sec_pmic_i2c_shutdown(struct i2c_client *i2c) +{ + sec_pmic_shutdown(&i2c->dev); +} + +static const struct of_device_id sec_pmic_i2c_of_match[] = { + { + .compatible = "samsung,s5m8767-pmic", + .data = (void *)S5M8767X, + }, { + .compatible = "samsung,s2dos05", + .data = (void *)S2DOS05, + }, { + .compatible = "samsung,s2mps11-pmic", + .data = (void *)S2MPS11X, + }, { + .compatible = "samsung,s2mps13-pmic", + .data = (void *)S2MPS13X, + }, { + .compatible = "samsung,s2mps14-pmic", + .data = (void *)S2MPS14X, + }, { + .compatible = "samsung,s2mps15-pmic", + .data = (void *)S2MPS15X, + }, { + .compatible = "samsung,s2mpa01-pmic", + .data = (void *)S2MPA01, + }, { + .compatible = "samsung,s2mpu02-pmic", + .data = (void *)S2MPU02, + }, { + .compatible = "samsung,s2mpu05-pmic", + .data = (void *)S2MPU05, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, sec_pmic_i2c_of_match); + +static struct i2c_driver sec_pmic_i2c_driver = { + .driver = { + .name = "sec-pmic-i2c", + .pm = pm_sleep_ptr(&sec_pmic_pm_ops), + .of_match_table = sec_pmic_i2c_of_match, + }, + .probe = sec_pmic_i2c_probe, + .shutdown = sec_pmic_i2c_shutdown, +}; +module_i2c_driver(sec_pmic_i2c_driver); + +MODULE_AUTHOR("Sangbeom Kim "); +MODULE_DESCRIPTION("I2C driver for the Samsung S5M"); +MODULE_LICENSE("GPL"); -- 2.50.1 From 5338709089b75f57a9b3b7b17a0424ecab5f2fd8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:30 +0100 Subject: [PATCH 11/16] mfd: sec: Add support for S2MPG10 PMIC MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-9-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 17 ++ drivers/mfd/Makefile | 1 + drivers/mfd/sec-acpm.c | 442 +++++++++++++++++++++++++++ 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, 1139 insertions(+) create mode 100644 drivers/mfd/sec-acpm.c create mode 100644 include/linux/mfd/samsung/s2mpg10.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3cde836b3799..6fb3768e3d71 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1316,6 +1316,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 363ec7eb827a..6c35be5ade74 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -230,6 +230,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 000000000000..8b31c816d65b --- /dev/null +++ b/drivers/mfd/sec-acpm.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2020 Google Inc + * Copyright 2025 Linaro Ltd. + * + * Samsung S2MPG1x ACPM driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sec-core.h" + +#define ACPM_ADDR_BITS 8 +#define ACPM_MAX_BULK_DATA 8 + +struct sec_pmic_acpm_platform_data { + 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 */ +}; + +static const struct regmap_range s2mpg10_common_ro_registers[] = { + regmap_reg_range(0x00, 0x01), /* CHIP_ID_M, INT */ + regmap_reg_range(0x28, 0x2a), /* Debug */ +}; + +static const struct regmap_range s2mpg10_common_nonvolatile_registers[] = { + regmap_reg_range(0x00, 0x00), /* CHIP_ID_M */ + regmap_reg_range(0x02, 0x02), /* INT_MASK */ + regmap_reg_range(0x0a, 0x0c), /* Speedy control */ +}; + +static const struct regmap_range s2mpg10_common_precious_registers[] = { + regmap_reg_range(0x01, 0x01), /* INT */ +}; + +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 = ACPM_ADDR_BITS, + .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), /* All PMIC registers */ +}; + +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 = ACPM_ADDR_BITS, + .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), /* All RTC registers */ +}; + +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 = ACPM_ADDR_BITS, + .val_bits = 8, + .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), /* Meter data */ +}; + +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 = ACPM_ADDR_BITS, + .val_bits = 8, + .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) +{ + 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; + size_t val_count = count - BITS_TO_BYTES(ACPM_ADDR_BITS); + const u8 *d = data; + const u8 *vals = &d[BITS_TO_BYTES(ACPM_ADDR_BITS)]; + u8 reg; + + if (val_count < 1 || val_count > ACPM_MAX_BULK_DATA) + return -EINVAL; + + reg = d[0]; + + return pmic_ops->bulk_write(acpm, ctx->shared->acpm_chan_id, ctx->type, reg, + ctx->shared->speedy_channel, val_count, vals); +} + +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; + const u8 *r = reg_buf; + u8 reg; + + if (reg_size != BITS_TO_BYTES(ACPM_ADDR_BITS) || !val_size || + val_size > ACPM_MAX_BULK_DATA) + return -EINVAL; + + reg = r[0]; + + 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, + 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 dev_err_cast_probe(dev, regmap, "regmap init (%s) failed\n", cfg->name); + + if (do_attach) { + int ret; + + ret = regmap_attach_dev(dev, regmap, cfg); + if (ret) + return dev_err_ptr_probe(dev, ret, "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); +} + +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 = &pdev->dev; + int ret, irq; + + 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, dev->parent->of_node); + if (IS_ERR(acpm)) + return dev_err_probe(dev, PTR_ERR(acpm), "failed to get acpm\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); +} + +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 "); +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 bb664e052bf5..c4b7abe51109 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 */ + 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 4d49bb42bd0d..e9beaa2a53fb 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,60 @@ #include #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[] = { }, }; +/* All S2MPG10 interrupt sources are read-only and don't require clearing */ +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, +}; + 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 8a4e660854bb..c1102324172a 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 978f7af66f74..b4805cbd949b 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 0204decfc9aa..51c4239a1fa6 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 000000000000..9f5919b89a3c --- /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 */ +#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.50.1 From b355f0cb92bd5e48d850e32960ac18fb1394cf8e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:31 +0100 Subject: [PATCH 12/16] mfd: sec: Merge separate core and irq modules MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit There is no reason to have these two kernel modules separate. Having them merged into one kernel module also slightly reduces memory consumption and module load times a little. mapped size (lsmod): before: after: sec_core 20480 sec_core 24576 sec_irq 16384 ---------------- total 36864 Section sizes (size -A): before: after: sec_core 6780 sec_core 13239 sec_irq 8046 ---------------- Total 14826 Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-10-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/Makefile | 3 ++- drivers/mfd/{sec-core.c => sec-common.c} | 2 ++ drivers/mfd/sec-irq.c | 9 --------- 3 files changed, 4 insertions(+), 10 deletions(-) rename drivers/mfd/{sec-core.c => sec-common.c} (98%) diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 6c35be5ade74..79495f9f3457 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -229,7 +229,8 @@ obj-$(CONFIG_MFD_RK8XX) += rk8xx-core.o 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 +sec-core-objs := sec-common.o sec-irq.o +obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o obj-$(CONFIG_MFD_SEC_ACPM) += sec-acpm.o obj-$(CONFIG_MFD_SEC_I2C) += sec-i2c.o obj-$(CONFIG_MFD_SYSCON) += syscon.o diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-common.c similarity index 98% rename from drivers/mfd/sec-core.c rename to drivers/mfd/sec-common.c index c4b7abe51109..782dec1956a5 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-common.c @@ -307,6 +307,8 @@ static int sec_pmic_resume(struct device *dev) DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); EXPORT_SYMBOL_GPL(sec_pmic_pm_ops); +MODULE_AUTHOR("Chanwoo Choi "); +MODULE_AUTHOR("Krzysztof Kozlowski "); MODULE_AUTHOR("Sangbeom Kim "); MODULE_DESCRIPTION("Core driver for the Samsung S5M"); MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index e9beaa2a53fb..b75d7fe86253 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -17,7 +16,6 @@ #include #include #include -#include #include #include "sec-core.h" @@ -510,10 +508,3 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) return 0; } -EXPORT_SYMBOL_GPL(sec_irq_init); - -MODULE_AUTHOR("Sangbeom Kim "); -MODULE_AUTHOR("Chanwoo Choi "); -MODULE_AUTHOR("Krzysztof Kozlowski "); -MODULE_DESCRIPTION("Interrupt support for the S5M MFD"); -MODULE_LICENSE("GPL"); -- 2.50.1 From d58b81c436f00259019ad11f2a9af19d84496de3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:32 +0100 Subject: [PATCH 13/16] mfd: sec-common: Fix multiple trivial whitespace issues MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Rectify a couple of alignment problems reported by Checkpatch. Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-11-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- 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 782dec1956a5..1a6f14dda825 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.50.1 From ada2b490c72bf6521aab135ba6e866639f9b0220 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:33 +0100 Subject: [PATCH 14/16] mfd: sec-i2c: Sort struct of_device_id entries and the device type switch MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Sort struct of_device_id entries and the device type switch in _probe() alphabetically, which makes it easier to find the right place where to insert new entries in the future. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-12-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/sec-i2c.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c index 8e3a365ff3e5..966d116dd781 100644 --- a/drivers/mfd/sec-i2c.c +++ b/drivers/mfd/sec-i2c.c @@ -154,12 +154,12 @@ static int sec_pmic_i2c_probe(struct i2c_client *client) case S2MPS15X: regmap = &s2mps15_regmap_config; break; - case S5M8767X: - regmap = &s5m8767_regmap_config; - break; case S2MPU02: regmap = &s2mpu02_regmap_config; break; + case S5M8767X: + regmap = &s5m8767_regmap_config; + break; default: regmap = &sec_regmap_config; break; @@ -184,11 +184,11 @@ static void sec_pmic_i2c_shutdown(struct i2c_client *i2c) static const struct of_device_id sec_pmic_i2c_of_match[] = { { - .compatible = "samsung,s5m8767-pmic", - .data = (void *)S5M8767X, - }, { .compatible = "samsung,s2dos05", .data = (void *)S2DOS05, + }, { + .compatible = "samsung,s2mpa01-pmic", + .data = (void *)S2MPA01, }, { .compatible = "samsung,s2mps11-pmic", .data = (void *)S2MPS11X, @@ -201,15 +201,15 @@ static const struct of_device_id sec_pmic_i2c_of_match[] = { }, { .compatible = "samsung,s2mps15-pmic", .data = (void *)S2MPS15X, - }, { - .compatible = "samsung,s2mpa01-pmic", - .data = (void *)S2MPA01, }, { .compatible = "samsung,s2mpu02-pmic", .data = (void *)S2MPU02, }, { .compatible = "samsung,s2mpu05-pmic", .data = (void *)S2MPU05, + }, { + .compatible = "samsung,s5m8767-pmic", + .data = (void *)S5M8767X, }, { }, }; -- 2.50.1 From 176a30687bb5bd5c401ee1142381841988386e6e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:34 +0100 Subject: [PATCH 15/16] mfd: sec: Use dev_err_probe() where appropriate MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit dev_err_probe() exists to simplify code and harmonise error messages, there's no reason not to use it here. While at it, harmonise some error messages. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-13-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/sec-common.c | 6 +++--- drivers/mfd/sec-i2c.c | 10 +++------- drivers/mfd/sec-irq.c | 14 +++++++------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c index 1a6f14dda825..f4c606c5ee5a 100644 --- a/drivers/mfd/sec-common.c +++ b/drivers/mfd/sec-common.c @@ -229,9 +229,9 @@ int sec_pmic_probe(struct device *dev, unsigned long device_type, num_sec_devs = ARRAY_SIZE(s2mpu05_devs); break; default: - dev_err(sec_pmic->dev, "Unsupported device type %lu\n", - sec_pmic->device_type); - return -EINVAL; + return dev_err_probe(sec_pmic->dev, -EINVAL, + "Unsupported device type %lu\n", + sec_pmic->device_type); } ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL, 0, NULL); diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c index 966d116dd781..a107a9c1e760 100644 --- a/drivers/mfd/sec-i2c.c +++ b/drivers/mfd/sec-i2c.c @@ -134,7 +134,6 @@ static int sec_pmic_i2c_probe(struct i2c_client *client) const struct regmap_config *regmap; unsigned long device_type; struct regmap *regmap_pmic; - int ret; device_type = (unsigned long)of_device_get_match_data(&client->dev); @@ -166,12 +165,9 @@ static int sec_pmic_i2c_probe(struct i2c_client *client) } regmap_pmic = devm_regmap_init_i2c(client, regmap); - if (IS_ERR(regmap_pmic)) { - ret = PTR_ERR(regmap_pmic); - dev_err(&client->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } + if (IS_ERR(regmap_pmic)) + return dev_err_probe(&client->dev, PTR_ERR(regmap_pmic), + "regmap init failed\n"); return sec_pmic_probe(&client->dev, device_type, client->irq, regmap_pmic, client); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index b75d7fe86253..340f5f14eba3 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -487,18 +487,18 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) sec_irq_chip = &s2mpu05_irq_chip; break; default: - dev_err(sec_pmic->dev, "Unknown device type %lu\n", - sec_pmic->device_type); - return -EINVAL; + return dev_err_probe(sec_pmic->dev, -EINVAL, + "Unsupported device type %lu\n", + sec_pmic->device_type); } 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); - if (ret != 0) { - dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); - return ret; - } + if (ret != 0) + return dev_err_probe(sec_pmic->dev, ret, + "Failed to add %s IRQ chip\n", + sec_irq_chip->name); /* * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11 -- 2.50.1 From 1cea1b6b2c89ef67ebd09e43d85d7308f86a538c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Wed, 9 Apr 2025 21:37:35 +0100 Subject: [PATCH 16/16] mfd: sec-i2c: s2dos05/s2mpu05: Use explicit regmap config and drop default MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When support for PMICs without compatibles was removed in commit f736d2c0caa8 ("mfd: sec: Remove PMICs without compatibles"), sec_regmap_config effectively became an orphan, because S5M8763X was the only user left of it before removal, using the default: case of the switch statement. When s2dos05 and s2mpu05 support was added in commit bf231e5febcf ("mfd: sec-core: Add support for the Samsung s2dos05") and commit ed33479b7beb ("mfd: sec: Add support for S2MPU05 PMIC"), they ended up using that orphaned regmap_config in a non-obvious way due to the default: case of the device type switch matching statement taking effect again. To make things more obvious, and to help the reader of this code while reasoning about what the intention might be here, and to ensure future additions to support new devices in this driver don't forget to add a regmap config, add an explicit regmap config for these two devices, and completely remove the generic regmap config as it becomes an orphan again that shouldn't be used by any device. Note that this commit doesn't fix the issue that s2dos05_regmap_config ands2mpu05_regmap_config really are incomplete, but I have no documentation on them. Reviewed-by: Krzysztof Kozlowski Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20250409-s2mpg10-v4-14-d66d5f39b6bf@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/sec-i2c.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c index a107a9c1e760..81f90003eea2 100644 --- a/drivers/mfd/sec-i2c.c +++ b/drivers/mfd/sec-i2c.c @@ -61,7 +61,7 @@ static bool s2mpu02_volatile(struct device *dev, unsigned int reg) } } -static const struct regmap_config sec_regmap_config = { +static const struct regmap_config s2dos05_regmap_config = { .reg_bits = 8, .val_bits = 8, }; @@ -120,6 +120,11 @@ static const struct regmap_config s2mpu02_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static const struct regmap_config s2mpu05_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + static const struct regmap_config s5m8767_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -138,6 +143,9 @@ static int sec_pmic_i2c_probe(struct i2c_client *client) device_type = (unsigned long)of_device_get_match_data(&client->dev); switch (device_type) { + case S2DOS05: + regmap = &s2dos05_regmap_config; + break; case S2MPA01: regmap = &s2mpa01_regmap_config; break; @@ -156,12 +164,16 @@ static int sec_pmic_i2c_probe(struct i2c_client *client) case S2MPU02: regmap = &s2mpu02_regmap_config; break; + case S2MPU05: + regmap = &s2mpu05_regmap_config; + break; case S5M8767X: regmap = &s5m8767_regmap_config; break; default: - regmap = &sec_regmap_config; - break; + return dev_err_probe(&client->dev, -ENODEV, + "Unsupported device type %lu\n", + device_type); } regmap_pmic = devm_regmap_init_i2c(client, regmap); -- 2.50.1