From dbecccac97208bfe5a165aa15423bd4285e41980 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Sep 2025 17:05:04 +0200 Subject: mfd: altera-sysmgr: Enable compile testing Nothing seems to prevent this driver from being compile tested so allow that. Signed-off-by: Johan Hovold Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 219ee6ddf516..71790ea9f9a2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -45,7 +45,8 @@ config MFD_ALTERA_A10SR config MFD_ALTERA_SYSMGR bool "Altera SOCFPGA System Manager" - depends on ARCH_INTEL_SOCFPGA && OF + depends on ARCH_INTEL_SOCFPGA || COMPILE_TEST + depends on OF select MFD_SYSCON help Select this to get System Manager support for all Altera branded -- cgit v1.2.3 From d306cbbc34cc9aa6ed2235472110fe797f887db7 Mon Sep 17 00:00:00 2001 From: Atharva Tiwari Date: Tue, 7 Oct 2025 18:35:10 +0530 Subject: mfd: macsmc: Make SMC write buffers const Mark the write buffer arguments in apple_smc_write(), apple_smc_rw(), and apple_smc_write_atomic() as const. These functions do not modify the data provided by the caller, so the parameters should be const qualified. Signed-off-by: Atharva Tiwari Reviewed-by: Sven Peter Signed-off-by: Lee Jones --- drivers/mfd/macsmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/macsmc.c b/drivers/mfd/macsmc.c index e6cdae221f1d..e3893e255ce5 100644 --- a/drivers/mfd/macsmc.c +++ b/drivers/mfd/macsmc.c @@ -173,7 +173,7 @@ int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size) } EXPORT_SYMBOL(apple_smc_read); -int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size) +int apple_smc_write(struct apple_smc *smc, smc_key key, const void *buf, size_t size) { guard(mutex)(&smc->mutex); @@ -181,7 +181,7 @@ int apple_smc_write(struct apple_smc *smc, smc_key key, void *buf, size_t size) } EXPORT_SYMBOL(apple_smc_write); -int apple_smc_rw(struct apple_smc *smc, smc_key key, void *wbuf, size_t wsize, +int apple_smc_rw(struct apple_smc *smc, smc_key key, const void *wbuf, size_t wsize, void *rbuf, size_t rsize) { guard(mutex)(&smc->mutex); @@ -239,7 +239,7 @@ int apple_smc_enter_atomic(struct apple_smc *smc) } EXPORT_SYMBOL(apple_smc_enter_atomic); -int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, void *buf, size_t size) +int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, const void *buf, size_t size) { guard(spinlock_irqsave)(&smc->lock); u8 result; -- cgit v1.2.3 From ccb7cd3218e48665f3c7e19eede0da5f069c323d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 25 Sep 2025 17:02:19 +0200 Subject: mfd: altera-sysmgr: Fix device leak on sysmgr regmap lookup Make sure to drop the reference taken to the sysmgr platform device when retrieving its driver data. Note that holding a reference to a device does not prevent its driver data from going away. Fixes: f36e789a1f8d ("mfd: altera-sysmgr: Add SOCFPGA System Manager") Cc: stable@vger.kernel.org # 5.2 Signed-off-by: Johan Hovold Signed-off-by: Lee Jones --- drivers/mfd/altera-sysmgr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c index fb5f988e61f3..90c6902d537d 100644 --- a/drivers/mfd/altera-sysmgr.c +++ b/drivers/mfd/altera-sysmgr.c @@ -117,6 +117,8 @@ struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np, sysmgr = dev_get_drvdata(dev); + put_device(dev); + return sysmgr->regmap; } EXPORT_SYMBOL_GPL(altr_sysmgr_regmap_lookup_by_phandle); -- cgit v1.2.3 From 5b79c9b6e73546967d457ec3bba3efe0577195be Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 25 Jun 2025 14:32:57 +0100 Subject: mfd: wl1273-core: Remove unused driver The wl1273 FM radio is on Arnd's unused driver list: https://lore.kernel.org/lkml/a15bb180-401d-49ad-a212-0c81d613fbc8@app.fastmail.com/ Remove the core. Signed-off-by: Dr. David Alan Gilbert Acked-by: Arnd Bergmann Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 10 -- drivers/mfd/Makefile | 1 - drivers/mfd/wl1273-core.c | 262 ---------------------------------------------- 3 files changed, 273 deletions(-) delete mode 100644 drivers/mfd/wl1273-core.c (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 71790ea9f9a2..dbeac6825a10 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2003,16 +2003,6 @@ config MENELAUS and other features that are often used in portable devices like cell phones and PDAs. -config MFD_WL1273_CORE - tristate "TI WL1273 FM radio" - depends on I2C - select MFD_CORE - default n - help - This is the core driver for the TI WL1273 FM radio. This MFD - driver connects the radio-wl1273 V4L2 module and the wl1273 - audio codec. - config MFD_LM3533 tristate "TI/National Semiconductor LM3533 Lighting Power chip" depends on I2C diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 566952f191b5..e75e8045c28a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -207,7 +207,6 @@ obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o obj-$(CONFIG_MFD_TPS6586X) += tps6586x.o obj-$(CONFIG_MFD_VX855) += vx855.o -obj-$(CONFIG_MFD_WL1273_CORE) += wl1273-core.o si476x-core-y := si476x-cmd.o si476x-prop.o si476x-i2c.o obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c deleted file mode 100644 index 2f185e93318e..000000000000 --- a/drivers/mfd/wl1273-core.c +++ /dev/null @@ -1,262 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * MFD driver for wl1273 FM radio and audio codec submodules. - * - * Copyright (C) 2011 Nokia Corporation - * Author: Matti Aaltonen - */ - -#include -#include -#include - -#define DRIVER_DESC "WL1273 FM Radio Core" - -static const struct i2c_device_id wl1273_driver_id_table[] = { - { WL1273_FM_DRIVER_NAME }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table); - -static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value) -{ - struct i2c_client *client = core->client; - u8 b[2]; - int r; - - r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b); - if (r != 2) { - dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg); - return -EREMOTEIO; - } - - *value = (u16)b[0] << 8 | b[1]; - - return 0; -} - -static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param) -{ - struct i2c_client *client = core->client; - u8 buf[] = { (param >> 8) & 0xff, param & 0xff }; - int r; - - r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf); - if (r) { - dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd); - return r; - } - - return 0; -} - -static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len) -{ - struct i2c_client *client = core->client; - struct i2c_msg msg; - int r; - - msg.addr = client->addr; - msg.flags = 0; - msg.buf = data; - msg.len = len; - - r = i2c_transfer(client->adapter, &msg, 1); - if (r != 1) { - dev_err(&client->dev, "%s: write error.\n", __func__); - return -EREMOTEIO; - } - - return 0; -} - -/** - * wl1273_fm_set_audio() - Set audio mode. - * @core: A pointer to the device struct. - * @new_mode: The new audio mode. - * - * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG. - */ -static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode) -{ - int r = 0; - - if (core->mode == WL1273_MODE_OFF || - core->mode == WL1273_MODE_SUSPENDED) - return -EPERM; - - if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) { - r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET, - WL1273_PCM_DEF_MODE); - if (r) - goto out; - - r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, - core->i2s_mode); - if (r) - goto out; - - r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, - WL1273_AUDIO_ENABLE_I2S); - if (r) - goto out; - - } else if (core->mode == WL1273_MODE_RX && - new_mode == WL1273_AUDIO_ANALOG) { - r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE, - WL1273_AUDIO_ENABLE_ANALOG); - if (r) - goto out; - - } else if (core->mode == WL1273_MODE_TX && - new_mode == WL1273_AUDIO_DIGITAL) { - r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, - core->i2s_mode); - if (r) - goto out; - - r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, - WL1273_AUDIO_IO_SET_I2S); - if (r) - goto out; - - } else if (core->mode == WL1273_MODE_TX && - new_mode == WL1273_AUDIO_ANALOG) { - r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET, - WL1273_AUDIO_IO_SET_ANALOG); - if (r) - goto out; - } - - core->audio_mode = new_mode; -out: - return r; -} - -/** - * wl1273_fm_set_volume() - Set volume. - * @core: A pointer to the device struct. - * @volume: The new volume value. - */ -static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume) -{ - int r; - - if (volume > WL1273_MAX_VOLUME) - return -EINVAL; - - if (core->volume == volume) - return 0; - - r = wl1273_fm_write_cmd(core, WL1273_VOLUME_SET, volume); - if (r) - return r; - - core->volume = volume; - return 0; -} - -static int wl1273_core_probe(struct i2c_client *client) -{ - struct wl1273_fm_platform_data *pdata = dev_get_platdata(&client->dev); - struct wl1273_core *core; - struct mfd_cell *cell; - int children = 0; - int r = 0; - - dev_dbg(&client->dev, "%s\n", __func__); - - if (!pdata) { - dev_err(&client->dev, "No platform data.\n"); - return -EINVAL; - } - - if (!(pdata->children & WL1273_RADIO_CHILD)) { - dev_err(&client->dev, "Cannot function without radio child.\n"); - return -EINVAL; - } - - core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL); - if (!core) - return -ENOMEM; - - core->pdata = pdata; - core->client = client; - mutex_init(&core->lock); - - i2c_set_clientdata(client, core); - - dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__); - - cell = &core->cells[children]; - cell->name = "wl1273_fm_radio"; - cell->platform_data = &core; - cell->pdata_size = sizeof(core); - children++; - - core->read = wl1273_fm_read_reg; - core->write = wl1273_fm_write_cmd; - core->write_data = wl1273_fm_write_data; - core->set_audio = wl1273_fm_set_audio; - core->set_volume = wl1273_fm_set_volume; - - if (pdata->children & WL1273_CODEC_CHILD) { - cell = &core->cells[children]; - - dev_dbg(&client->dev, "%s: Have codec.\n", __func__); - cell->name = "wl1273-codec"; - cell->platform_data = &core; - cell->pdata_size = sizeof(core); - children++; - } - - dev_dbg(&client->dev, "%s: number of children: %d.\n", - __func__, children); - - r = devm_mfd_add_devices(&client->dev, -1, core->cells, - children, NULL, 0, NULL); - if (r) - goto err; - - return 0; - -err: - pdata->free_resources(); - - dev_dbg(&client->dev, "%s\n", __func__); - - return r; -} - -static struct i2c_driver wl1273_core_driver = { - .driver = { - .name = WL1273_FM_DRIVER_NAME, - }, - .probe = wl1273_core_probe, - .id_table = wl1273_driver_id_table, -}; - -static int __init wl1273_core_init(void) -{ - int r; - - r = i2c_add_driver(&wl1273_core_driver); - if (r) { - pr_err(WL1273_FM_DRIVER_NAME - ": driver registration failed\n"); - return r; - } - - return r; -} - -static void __exit wl1273_core_exit(void) -{ - i2c_del_driver(&wl1273_core_driver); -} -late_initcall(wl1273_core_init); -module_exit(wl1273_core_exit); - -MODULE_AUTHOR("Matti Aaltonen "); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 78bf081ddf39ba83b551f96d42fe2e4a8fda8718 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 7 Oct 2025 11:54:24 +0200 Subject: mfd: tqmx86: Add board definitions for TQMxCU1-HPCM and TQMxCU2-HPCM This adds support for 2 new TQMx86 COMs: - TQMxCU1-HPCM (COM-HPC Mini Module with Intel Core Ultra Processors [1]) - TQMxCU2-HPCM (in development) [1] https://www.tq-group.com/en/products/tq-embedded/x86-architecture/tqmxcu1-hpcm/ Signed-off-by: Matthias Schiffer Link: https://patch.msgid.link/20251007095424.138878-1-matthias.schiffer@ew.tq-group.com Signed-off-by: Lee Jones --- drivers/mfd/tqmx86.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/tqmx86.c b/drivers/mfd/tqmx86.c index 1cba3b67b0fb..1c2fe3f91238 100644 --- a/drivers/mfd/tqmx86.c +++ b/drivers/mfd/tqmx86.c @@ -43,6 +43,8 @@ #define TQMX86_REG_BOARD_ID_E40C2 15 #define TQMX86_REG_BOARD_ID_130UC 16 #define TQMX86_REG_BOARD_ID_E41S 19 +#define TQMX86_REG_BOARD_ID_CU1_HPCM 24 +#define TQMX86_REG_BOARD_ID_CU2_HPCM 25 #define TQMX86_REG_BOARD_REV 0x01 #define TQMX86_REG_IO_EXT_INT 0x06 #define TQMX86_REG_IO_EXT_INT_NONE 0 @@ -165,6 +167,10 @@ static const char *tqmx86_board_id_to_name(u8 board_id, u8 sauc) return "TQMx130UC"; case TQMX86_REG_BOARD_ID_E41S: return "TQMxE41S"; + case TQMX86_REG_BOARD_ID_CU1_HPCM: + return "TQMxCU1-HPCM"; + case TQMX86_REG_BOARD_ID_CU2_HPCM: + return "TQMxCU2-HPCM"; default: return "Unknown"; } @@ -185,6 +191,8 @@ static int tqmx86_board_id_to_clk_rate(struct device *dev, u8 board_id) case TQMX86_REG_BOARD_ID_E40C2: case TQMX86_REG_BOARD_ID_130UC: case TQMX86_REG_BOARD_ID_E41S: + case TQMX86_REG_BOARD_ID_CU1_HPCM: + case TQMX86_REG_BOARD_ID_CU2_HPCM: return 24000; case TQMX86_REG_BOARD_ID_E39MS: case TQMX86_REG_BOARD_ID_E39C1: -- cgit v1.2.3 From 18597dbccfa5a99ccb7278046234c0ae29ec7a19 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 23 Oct 2025 08:55:59 +0200 Subject: mfd: da9063: Occupy second I2C address The second address can be used as a shortcut to access register pages 2+3. The driver does not use this feature yet. The second address should still be marked as used, otherwise userspace could interfere with the driver. Signed-off-by: Wolfram Sang Reviewed-by: Peter Rosin Reviewed-by: Bartosz Golaszewski Reviewed-by: Kieran Bingham Link: https://patch.msgid.link/20251023065610.2855-2-wsa+renesas@sang-engineering.com Signed-off-by: Lee Jones --- drivers/mfd/da9063-i2c.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c index 1ec9ab56442d..a803b7440f09 100644 --- a/drivers/mfd/da9063-i2c.c +++ b/drivers/mfd/da9063-i2c.c @@ -469,6 +469,9 @@ static int da9063_i2c_probe(struct i2c_client *i2c) } } + /* Reserve our unused second address so userspace won't interfere */ + devm_i2c_new_dummy_device(&i2c->dev, i2c->adapter, i2c->addr + 1); + return da9063_device_init(da9063, i2c->irq); } -- cgit v1.2.3 From 1b58acfd067ca16116b9234cd6b2d30cc8ab7502 Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Fri, 10 Oct 2025 09:17:36 +0800 Subject: mfd: da9055: Fix missing regmap_del_irq_chip() in error path When da9055_device_init() fails after regmap_add_irq_chip() succeeds but mfd_add_devices() fails, the error handling path only calls mfd_remove_devices() but forgets to call regmap_del_irq_chip(). This results in a resource leak. Fix this by adding regmap_del_irq_chip() to the error path so that resources are released properly. Fixes: 2896434cf272 ("mfd: DA9055 core driver") Signed-off-by: Haotian Zhang Link: https://patch.msgid.link/20251010011737.1078-1-vulab@iscas.ac.cn Signed-off-by: Lee Jones --- drivers/mfd/da9055-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c index 1f727ef60d63..8c989b74f924 100644 --- a/drivers/mfd/da9055-core.c +++ b/drivers/mfd/da9055-core.c @@ -388,6 +388,7 @@ int da9055_device_init(struct da9055 *da9055) err: mfd_remove_devices(da9055->dev); + regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data); return ret; } -- cgit v1.2.3 From 2bac49bad1f3553cc3b3bfb22cc194e9bd9e8427 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 23 Oct 2025 12:19:40 +0200 Subject: mfd: max77620: Fix potential IRQ chip conflict when probing two devices MAX77620 is most likely always a single device on the board, however nothing stops board designers to have two of them, thus same device driver could probe twice. Or user could manually try to probing second time. Device driver is not ready for that case, because it allocates statically 'struct regmap_irq_chip' as non-const and stores during probe in 'irq_drv_data' member a pointer to per-probe state container ('struct max77620_chip'). devm_regmap_add_irq_chip() does not make a copy of 'struct regmap_irq_chip' but store the pointer. Second probe - either successful or failure - would overwrite the 'irq_drv_data' from previous device probe, so interrupts would be executed in a wrong context. Cc: stable@vger.kernel.org Fixes: 3df140d11c6d ("mfd: max77620: Mask/unmask interrupt before/after servicing it") Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20251023101939.67991-2-krzysztof.kozlowski@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/max77620.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index 21d2ab3db254..3af2974b3023 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -254,7 +254,7 @@ static int max77620_irq_global_unmask(void *irq_drv_data) return ret; } -static struct regmap_irq_chip max77620_top_irq_chip = { +static const struct regmap_irq_chip max77620_top_irq_chip = { .name = "max77620-top", .irqs = max77620_top_irqs, .num_irqs = ARRAY_SIZE(max77620_top_irqs), @@ -498,6 +498,7 @@ static int max77620_probe(struct i2c_client *client) const struct i2c_device_id *id = i2c_client_get_device_id(client); const struct regmap_config *rmap_config; struct max77620_chip *chip; + struct regmap_irq_chip *chip_desc; const struct mfd_cell *mfd_cells; int n_mfd_cells; bool pm_off; @@ -508,6 +509,14 @@ static int max77620_probe(struct i2c_client *client) return -ENOMEM; i2c_set_clientdata(client, chip); + + chip_desc = devm_kmemdup(&client->dev, &max77620_top_irq_chip, + sizeof(max77620_top_irq_chip), + GFP_KERNEL); + if (!chip_desc) + return -ENOMEM; + chip_desc->irq_drv_data = chip; + chip->dev = &client->dev; chip->chip_irq = client->irq; chip->chip_id = (enum max77620_chip_id)id->driver_data; @@ -544,11 +553,9 @@ static int max77620_probe(struct i2c_client *client) if (ret < 0) return ret; - max77620_top_irq_chip.irq_drv_data = chip; ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq, IRQF_ONESHOT | IRQF_SHARED, 0, - &max77620_top_irq_chip, - &chip->top_irq_data); + chip_desc, &chip->top_irq_data); if (ret < 0) { dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret); return ret; -- cgit v1.2.3 From 049929c5a159c8671b9b0c12a7da963fef535b00 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 25 Oct 2025 13:27:16 +0200 Subject: mfd: da9055: Simplify the error handling path in da9055_device_init() If mfd_add_devices() fails, there is no need to call mfd_remove_devices(). The needed clean-up is already done in the error handling path of mfd_add_devices(). So, remove the unneeded (and harmless) call. Signed-off-by: Christophe JAILLET Link: https://patch.msgid.link/871f52e7ab5d12853bc39f36ac78b5a8e484d863.1761391599.git.christophe.jaillet@wanadoo.fr Signed-off-by: Lee Jones --- drivers/mfd/da9055-core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c index 8c989b74f924..158590ad37d4 100644 --- a/drivers/mfd/da9055-core.c +++ b/drivers/mfd/da9055-core.c @@ -387,7 +387,6 @@ int da9055_device_init(struct da9055 *da9055) return 0; err: - mfd_remove_devices(da9055->dev); regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data); return ret; } -- cgit v1.2.3 From 1810b210872ffc9985febca0880702a7102aad31 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 27 Oct 2025 14:12:06 +0200 Subject: mfd: bd718x7: Use regmap_reg_range() for pmic_status_range Initializing the regmap_ranges using direct assignment to the range_min and range_max members is a slightly verbose. In general we can make it a tad cleaner when using the regmap_reg_range() macro. The rohm-bd718x7.c is doing this open-coded initialization. It's not really bad as there is only one range defined, but it is still worth converting it to use the regmap_reg_range() so no-one uses it as a bad example. Additionally, the regmap_access_table expects a pointer to an array of ranges. This is a tad more obvious when we use an array with single range, instead of claiming a pointer to a range struct being a single element array. Use regmap_reg_range() when initializing the regmap_range structure and use a real one-element array instead of a pointer to a struct. Signed-off-by: Matti Vaittinen Link: https://patch.msgid.link/aP9hlpRO-0vmEHBZ@mva-rohm Signed-off-by: Lee Jones --- drivers/mfd/rohm-bd718x7.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c index 25e494a93d48..ff714fd4f54d 100644 --- a/drivers/mfd/rohm-bd718x7.c +++ b/drivers/mfd/rohm-bd718x7.c @@ -72,14 +72,13 @@ static const struct regmap_irq_chip bd718xx_irq_chip = { .init_ack_masked = true, }; -static const struct regmap_range pmic_status_range = { - .range_min = BD718XX_REG_IRQ, - .range_max = BD718XX_REG_POW_STATE, +static const struct regmap_range pmic_status_range[] = { + regmap_reg_range(BD718XX_REG_IRQ, BD718XX_REG_POW_STATE), }; static const struct regmap_access_table volatile_regs = { - .yes_ranges = &pmic_status_range, - .n_yes_ranges = 1, + .yes_ranges = &pmic_status_range[0], + .n_yes_ranges = ARRAY_SIZE(pmic_status_range), }; static const struct regmap_config bd718xx_regmap_config = { -- cgit v1.2.3 From ecf6bc474ae97c404e2125b413eb0ef3627b03c5 Mon Sep 17 00:00:00 2001 From: Troy Mitchell Date: Mon, 27 Oct 2025 13:48:05 +0800 Subject: mfd: simple-mfd-i2c: Remove select I2C_K1 from MFD_SPACEMIT_P1 select will force a symbol to a specific value without considering its dependencies. As a result, the i2c-k1 driver will fail to build when OF or COMMON_CLK are disabled. The reason for removing I2C_K1 instead of adding a depends on condition is to keep the possibility for other SoCs to use this PMIC. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202510211523.sSEVqPUQ-lkp@intel.com/ Acked-by: Alex Elder Signed-off-by: Troy Mitchell Link: https://lore.kernel.org/all/20251022004830-GYB1522542@gentoo.org/ [1] Link: https://patch.msgid.link/20251027-p1-kconfig-fix-v2-1-49688f30bae8@linux.spacemit.com Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index dbeac6825a10..58bfe32453a2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1275,7 +1275,6 @@ config MFD_SPACEMIT_P1 tristate "SpacemiT P1 PMIC" depends on ARCH_SPACEMIT || COMPILE_TEST depends on I2C - select I2C_K1 select MFD_SIMPLE_MFD_I2C help This option supports the I2C-based SpacemiT P1 PMIC, which -- cgit v1.2.3 From 30ed024fb0768e9353f21d1d9e6960b7028acdfa Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 17 Sep 2025 09:32:32 +0300 Subject: mfd: bcm2835-pm: Add support for BCM2712 The BCM2712 SoC has PM block but lacks the "asb" and "rpivid_asb" register spaces, and doesn't need clock(s). Add a compatible string for bcm2712 to allow probe of bcm2835-wdt and bcm2835-power drivers. Signed-off-by: Stanimir Varbanov Reviewed-by: Florian Fainelli Link: https://patch.msgid.link/20250917063233.1270-4-svarbanov@suse.de Signed-off-by: Lee Jones --- drivers/mfd/bcm2835-pm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c index 3cb2b9423121..8bed59816e82 100644 --- a/drivers/mfd/bcm2835-pm.c +++ b/drivers/mfd/bcm2835-pm.c @@ -108,6 +108,7 @@ static const struct of_device_id bcm2835_pm_of_match[] = { { .compatible = "brcm,bcm2835-pm-wdt", }, { .compatible = "brcm,bcm2835-pm", }, { .compatible = "brcm,bcm2711-pm", }, + { .compatible = "brcm,bcm2712-pm", }, {}, }; MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match); -- cgit v1.2.3 From b73d5593bfde6bf570d55bcff3576e35cdf4ec9a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 2 Nov 2025 14:59:22 +0300 Subject: mfd: syscon: Return -EPROBE_DEFER if the syscon is not found These days we can register syscons with of_syscon_register_regmap() so when we can't find the syscon that probably means it hasn't been registered yet. Return -EPROBE_DEFER so the driver will try probing again. Signed-off-by: Dan Carpenter Reviewed-by: Arnd Bergmann Reviewed-by: Chen-Yu Tsai Acked-by: Rob Herring (Arm) Link: https://patch.msgid.link/aQdHmrchkmOr34r3@stanley.mountain Signed-off-by: Lee Jones --- drivers/mfd/syscon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index ae71a2710bed..e5d5def594f6 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -183,7 +183,7 @@ static struct regmap *device_node_get_regmap(struct device_node *np, if (create_regmap) syscon = of_syscon_register(np, check_res); else - syscon = ERR_PTR(-EINVAL); + syscon = ERR_PTR(-EPROBE_DEFER); } mutex_unlock(&syscon_list_lock); -- cgit v1.2.3 From 3696ac1d0db2461bd62f89ea8379bb0565fc58e6 Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Tue, 11 Nov 2025 13:24:51 +0800 Subject: mfd: ls2kbmc: Remove unneeded semicolon from ls2k_bmc_recover_pci_data() Remove unnecessary semicolons reported by Coccinelle/coccicheck and the semantic patch at scripts/coccinelle/misc/semicolon.cocci. Signed-off-by: Chen Ni Link: https://patch.msgid.link/20251111052451.3687740-1-nichen@iscas.ac.cn Signed-off-by: Lee Jones --- drivers/mfd/ls2k-bmc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/ls2k-bmc-core.c b/drivers/mfd/ls2k-bmc-core.c index e162b3c7c9f8..08d631d954ef 100644 --- a/drivers/mfd/ls2k-bmc-core.c +++ b/drivers/mfd/ls2k-bmc-core.c @@ -265,7 +265,7 @@ static int ls2k_bmc_recover_pci_data(void *data) if (!ls2k_bmc_bar0_addr_is_set(parent)) break; mdelay(1); - }; + } if (i == 0) return false; -- cgit v1.2.3 From b0ed6b6cce1abd1e57311584066e73d0ed877bef Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Nov 2025 11:53:20 +0100 Subject: mfd: Kconfig: Drop OF dependency on MFD_MAX5970 This is the only Kconfig symbol that depends on OF while selecting the common driver for several chips. Drop this unneeded dependency and make the component available on non-OF systems along with wider compile test. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20251111105320.750131-1-andriy.shevchenko@linux.intel.com Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 58bfe32453a2..aace5766b38a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -896,7 +896,7 @@ config MFD_88PM886_PMIC config MFD_MAX5970 tristate "Maxim 5970/5978 power switch and monitor" - depends on I2C && OF + depends on I2C select MFD_SIMPLE_MFD_I2C help This driver controls a Maxim 5970/5978 switch via I2C bus. -- cgit v1.2.3 From 81d2cc9272df8c01e36a963dd8b23ca585b68032 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Nov 2025 12:18:35 +0100 Subject: mfd: simple-mfd-i2c: Make ID table style consistent The lines in the OF ID table are written in three different styles. Choose the most common in the kernel and update accordingly. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20251111111930.796837-2-andriy.shevchenko@linux.intel.com Signed-off-by: Lee Jones --- drivers/mfd/simple-mfd-i2c.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c index 0a607a1e3ca1..5fd0ef3fa44a 100644 --- a/drivers/mfd/simple-mfd-i2c.c +++ b/drivers/mfd/simple-mfd-i2c.c @@ -114,11 +114,11 @@ static const struct of_device_id simple_mfd_i2c_of_match[] = { { .compatible = "fsl,lx2160aqds-fpga" }, { .compatible = "fsl,lx2160ardb-fpga" }, { .compatible = "kontron,sl28cpld" }, - { .compatible = "maxim,max5970", .data = &maxim_max5970}, - { .compatible = "maxim,max5978", .data = &maxim_max5970}, - { .compatible = "maxim,max77705-battery", .data = &maxim_mon_max77705}, - { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a}, - { .compatible = "spacemit,p1", .data = &spacemit_p1, }, + { .compatible = "maxim,max5970", .data = &maxim_max5970 }, + { .compatible = "maxim,max5978", .data = &maxim_max5970 }, + { .compatible = "maxim,max77705-battery", .data = &maxim_mon_max77705 }, + { .compatible = "silergy,sy7636a", .data = &silergy_sy7636a }, + { .compatible = "spacemit,p1", .data = &spacemit_p1 }, {} }; MODULE_DEVICE_TABLE(of, simple_mfd_i2c_of_match); -- cgit v1.2.3 From 46bddb5fbe7e3cb73204a952dbd4687cf0974ef5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 11 Nov 2025 12:18:36 +0100 Subject: mfd: simple-mfd-i2c: Don't use "proxy" headers Update header inclusions to follow IWYU (Include What You Use) principle. Signed-off-by: Andy Shevchenko Link: https://patch.msgid.link/20251111111930.796837-3-andriy.shevchenko@linux.intel.com Signed-off-by: Lee Jones --- drivers/mfd/simple-mfd-i2c.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/simple-mfd-i2c.c b/drivers/mfd/simple-mfd-i2c.c index 5fd0ef3fa44a..8b751d8e3b5a 100644 --- a/drivers/mfd/simple-mfd-i2c.c +++ b/drivers/mfd/simple-mfd-i2c.c @@ -15,12 +15,18 @@ * will be subsequently registered. */ +#include +#include +#include #include -#include #include +#include #include #include +#include +#include #include +#include #include "simple-mfd-i2c.h" -- cgit v1.2.3 From b4881070a02b017aea84592c424d5a980ed261c4 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 13 Nov 2025 17:52:15 +0100 Subject: mfd: qnap-mcu: Calculate the checksum on the actual number of bytes received In the case of an error message, the number of received bytes can be less than originally expected but still contain a valid message. If the transfer itself ended in an error we would exit earlier already. So calculate the checksum on the number of received bytes and not the number of expected bytes. Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20251113165218.449616-2-heiko@sntech.de Signed-off-by: Lee Jones --- drivers/mfd/qnap-mcu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/qnap-mcu.c b/drivers/mfd/qnap-mcu.c index 4ec1f4cf902f..4cd5319fc6cb 100644 --- a/drivers/mfd/qnap-mcu.c +++ b/drivers/mfd/qnap-mcu.c @@ -175,8 +175,8 @@ int qnap_mcu_exec(struct qnap_mcu *mcu, return -ETIMEDOUT; } - crc = qnap_mcu_csum(rx, reply_data_size); - if (crc != rx[reply_data_size]) { + crc = qnap_mcu_csum(rx, reply->received - QNAP_MCU_CHECKSUM_SIZE); + if (crc != rx[reply->received - QNAP_MCU_CHECKSUM_SIZE]) { dev_err(&mcu->serdev->dev, "Invalid Checksum received\n"); return -EIO; } -- cgit v1.2.3 From c94fce30e190555d74e2769b5fe4a932d0ad432e Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 13 Nov 2025 17:52:16 +0100 Subject: mfd: qnap-mcu: Use EPROTO in stead of EIO on checksum errors EPROTO stands for protocol error and a lot of driver already use it to designate errors in the sent or received data from a peripheral. So use it in the qnap-mcu as well for checksum errors. Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20251113165218.449616-3-heiko@sntech.de Signed-off-by: Lee Jones --- drivers/mfd/qnap-mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/qnap-mcu.c b/drivers/mfd/qnap-mcu.c index 4cd5319fc6cb..1f4741cad875 100644 --- a/drivers/mfd/qnap-mcu.c +++ b/drivers/mfd/qnap-mcu.c @@ -178,7 +178,7 @@ int qnap_mcu_exec(struct qnap_mcu *mcu, crc = qnap_mcu_csum(rx, reply->received - QNAP_MCU_CHECKSUM_SIZE); if (crc != rx[reply->received - QNAP_MCU_CHECKSUM_SIZE]) { dev_err(&mcu->serdev->dev, "Invalid Checksum received\n"); - return -EIO; + return -EPROTO; } memcpy(reply_data, rx, reply_data_size); -- cgit v1.2.3 From c3223f562586307b1bcb014475d0b71913972145 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 13 Nov 2025 17:52:17 +0100 Subject: mfd: qnap-mcu: Move checksum verification to its own function We'll need the checksum check in a second place in the future, so move the verification code to a separate function. Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20251113165218.449616-4-heiko@sntech.de Signed-off-by: Lee Jones --- drivers/mfd/qnap-mcu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/qnap-mcu.c b/drivers/mfd/qnap-mcu.c index 1f4741cad875..558c3bc07ed3 100644 --- a/drivers/mfd/qnap-mcu.c +++ b/drivers/mfd/qnap-mcu.c @@ -78,6 +78,13 @@ static u8 qnap_mcu_csum(const u8 *buf, size_t size) return csum; } +static bool qnap_mcu_verify_checksum(const u8 *buf, size_t size) +{ + u8 crc = qnap_mcu_csum(buf, size - QNAP_MCU_CHECKSUM_SIZE); + + return crc == buf[size - QNAP_MCU_CHECKSUM_SIZE]; +} + static int qnap_mcu_write(struct qnap_mcu *mcu, const u8 *data, u8 data_size) { unsigned char tx[QNAP_MCU_TX_BUFFER_SIZE]; @@ -150,7 +157,6 @@ int qnap_mcu_exec(struct qnap_mcu *mcu, size_t length = reply_data_size + QNAP_MCU_CHECKSUM_SIZE; struct qnap_mcu_reply *reply = &mcu->reply; int ret = 0; - u8 crc; if (length > sizeof(rx)) { dev_err(&mcu->serdev->dev, "expected data too big for receive buffer"); @@ -175,8 +181,7 @@ int qnap_mcu_exec(struct qnap_mcu *mcu, return -ETIMEDOUT; } - crc = qnap_mcu_csum(rx, reply->received - QNAP_MCU_CHECKSUM_SIZE); - if (crc != rx[reply->received - QNAP_MCU_CHECKSUM_SIZE]) { + if (!qnap_mcu_verify_checksum(rx, reply->received)) { dev_err(&mcu->serdev->dev, "Invalid Checksum received\n"); return -EPROTO; } -- cgit v1.2.3 From 56c1245d51faab70bf68cc3a5cd3925768e6375b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 13 Nov 2025 17:52:18 +0100 Subject: mfd: qnap-mcu: Add proper error handling for command errors Further investigation revealed that the MCU in QNAP devices may return two error states. One "@8" for a checksum error in the submitted command and one "@9" for any generic (and sadly unspecified) error. These error codes with 2 data character can of course also be shorter then the expected reply length for the submitted command, so we'll need to check the received data for error codes and exit the receive portion early in that case. Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20251113165218.449616-5-heiko@sntech.de Signed-off-by: Lee Jones --- drivers/mfd/qnap-mcu.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/qnap-mcu.c b/drivers/mfd/qnap-mcu.c index 558c3bc07ed3..6bbf8334caa4 100644 --- a/drivers/mfd/qnap-mcu.c +++ b/drivers/mfd/qnap-mcu.c @@ -19,6 +19,7 @@ /* The longest command found so far is 5 bytes long */ #define QNAP_MCU_MAX_CMD_SIZE 5 #define QNAP_MCU_MAX_DATA_SIZE 36 +#define QNAP_MCU_ERROR_SIZE 2 #define QNAP_MCU_CHECKSUM_SIZE 1 #define QNAP_MCU_RX_BUFFER_SIZE \ @@ -103,6 +104,48 @@ static int qnap_mcu_write(struct qnap_mcu *mcu, const u8 *data, u8 data_size) return serdev_device_write(mcu->serdev, tx, length, HZ); } +static bool qnap_mcu_is_error_msg(size_t size) +{ + return (size == QNAP_MCU_ERROR_SIZE + QNAP_MCU_CHECKSUM_SIZE); +} + +static bool qnap_mcu_reply_is_generic_error(unsigned char *buf, size_t size) +{ + if (!qnap_mcu_is_error_msg(size)) + return false; + + if (buf[0] == '@' && buf[1] == '9') + return true; + + return false; +} + +static bool qnap_mcu_reply_is_checksum_error(unsigned char *buf, size_t size) +{ + if (!qnap_mcu_is_error_msg(size)) + return false; + + if (buf[0] == '@' && buf[1] == '8') + return true; + + return false; +} + +static bool qnap_mcu_reply_is_any_error(struct qnap_mcu *mcu, unsigned char *buf, size_t size) +{ + if (qnap_mcu_reply_is_generic_error(buf, size)) { + dev_err(&mcu->serdev->dev, "Controller sent generic error response\n"); + return true; + } + + if (qnap_mcu_reply_is_checksum_error(buf, size)) { + dev_err(&mcu->serdev->dev, "Controller received invalid checksum for the command\n"); + return true; + } + + return false; +} + static size_t qnap_mcu_receive_buf(struct serdev_device *serdev, const u8 *buf, size_t size) { struct device *dev = &serdev->dev; @@ -136,6 +179,24 @@ static size_t qnap_mcu_receive_buf(struct serdev_device *serdev, const u8 *buf, } } + /* + * We received everything the uart had to offer for now. + * This could mean that either the uart will send more in a 2nd + * receive run, or that the MCU cut the reply short because it + * sent an error code instead of the expected reply. + * + * So check if the received data has the correct size for an error + * reply and if it matches, is an actual error code. + */ + if (qnap_mcu_is_error_msg(reply->received) && + qnap_mcu_verify_checksum(reply->data, reply->received) && + qnap_mcu_reply_is_any_error(mcu, reply->data, reply->received)) { + /* The reply was an error code, we're done */ + reply->length = 0; + + complete(&reply->done); + } + /* * The only way to get out of the above loop and end up here * is through consuming all of the supplied data, so here we @@ -182,10 +243,13 @@ int qnap_mcu_exec(struct qnap_mcu *mcu, } if (!qnap_mcu_verify_checksum(rx, reply->received)) { - dev_err(&mcu->serdev->dev, "Invalid Checksum received\n"); + dev_err(&mcu->serdev->dev, "Invalid Checksum received from controller\n"); return -EPROTO; } + if (qnap_mcu_reply_is_any_error(mcu, rx, reply->received)) + return -EPROTO; + memcpy(reply_data, rx, reply_data_size); return 0; -- cgit v1.2.3 From ee19b52c31b3b111f140c1affd88eca1ed11edd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Fri, 14 Nov 2025 14:10:59 +0000 Subject: mfd: sec: Use chained IRQs for s2mpg10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On S2MPG10 (and similar like S2MPG11), top-level interrupt status and mask registers exist which need to be unmasked to get the PMIC interrupts. This additional status doesn't seem to exist on other PMICs in the S2MP* family, and the S2MPG10 driver is manually dealing with masking and unmasking currently. The correct approach here is to register this hierarchy as chained interrupts, though, without any additional manual steps. Doing so will also simplify addition of other, similar, PMICs (like S2MPG11) in the future. Update the driver to do just that. Signed-off-by: André Draszik Link: https://patch.msgid.link/20251114-s2mpg10-chained-irq-v1-1-34ddfa49c4cd@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/sec-acpm.c | 23 +--------------- drivers/mfd/sec-irq.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 25 deletions(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-acpm.c b/drivers/mfd/sec-acpm.c index 8b31c816d65b..36622069a788 100644 --- a/drivers/mfd/sec-acpm.c +++ b/drivers/mfd/sec-acpm.c @@ -325,11 +325,6 @@ static struct regmap *sec_pmic_acpm_regmap_init(struct device *dev, 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; @@ -360,15 +355,10 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev) 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); + pdata->regmap_cfg_common, true); 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)) @@ -391,17 +381,6 @@ static int sec_pmic_acpm_probe(struct platform_device *pdev) 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; } diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index c5c80b1ba104..d992e41e716d 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -20,6 +20,12 @@ #include "sec-core.h" static const struct regmap_irq s2mpg10_irqs[] = { + REGMAP_IRQ_REG(S2MPG10_COMMON_IRQ_PMIC, 0, S2MPG10_COMMON_INT_SRC_PMIC), + /* No documentation or other reference for remaining bits */ + REGMAP_IRQ_REG(S2MPG10_COMMON_IRQ_UNUSED, 0, GENMASK(7, 1)), +}; + +static const struct regmap_irq s2mpg10_pmic_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), @@ -183,11 +189,20 @@ 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", + .status_base = S2MPG10_COMMON_INT, + .mask_base = S2MPG10_COMMON_INT_MASK, + .num_regs = 1, .irqs = s2mpg10_irqs, .num_irqs = ARRAY_SIZE(s2mpg10_irqs), - .num_regs = 6, +}; + +static const struct regmap_irq_chip s2mpg10_irq_chip_pmic = { + .name = "s2mpg10-pmic", .status_base = S2MPG10_PMIC_INT1, .mask_base = S2MPG10_PMIC_INT1M, + .num_regs = 6, + .irqs = s2mpg10_pmic_irqs, + .num_irqs = ARRAY_SIZE(s2mpg10_pmic_irqs), }; static const struct regmap_irq_chip s2mps11_irq_chip = { @@ -253,6 +268,59 @@ static const struct regmap_irq_chip s5m8767_irq_chip = { .ack_base = S5M8767_REG_INT1, }; +static int s2mpg1x_add_chained_irq_chip(struct device *dev, struct regmap *regmap, int pirq, + struct regmap_irq_chip_data *parent, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data) +{ + int irq, ret; + + irq = regmap_irq_get_virq(parent, pirq); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get parent vIRQ(%d) for chip %s\n", pirq, + chip->name); + + ret = devm_regmap_add_irq_chip(dev, regmap, irq, IRQF_ONESHOT | IRQF_SHARED, 0, chip, data); + if (ret) + return dev_err_probe(dev, ret, "Failed to add %s IRQ chip\n", chip->name); + + return 0; +} + +static int sec_irq_init_s2mpg1x(struct sec_pmic_dev *sec_pmic) +{ + const struct regmap_irq_chip *irq_chip, *chained_irq_chip; + struct regmap_irq_chip_data *irq_data; + struct regmap *regmap_common; + int chained_pirq; + int ret; + + switch (sec_pmic->device_type) { + case S2MPG10: + irq_chip = &s2mpg10_irq_chip; + chained_irq_chip = &s2mpg10_irq_chip_pmic; + chained_pirq = S2MPG10_COMMON_IRQ_PMIC; + break; + default: + return dev_err_probe(sec_pmic->dev, -EINVAL, "Unsupported device type %d\n", + sec_pmic->device_type); + }; + + regmap_common = dev_get_regmap(sec_pmic->dev, "common"); + if (!regmap_common) + return dev_err_probe(sec_pmic->dev, -EINVAL, "No 'common' regmap %d\n", + sec_pmic->device_type); + + ret = devm_regmap_add_irq_chip(sec_pmic->dev, regmap_common, sec_pmic->irq, IRQF_ONESHOT, 0, + irq_chip, &irq_data); + if (ret) + return dev_err_probe(sec_pmic->dev, ret, "Failed to add %s IRQ chip\n", + irq_chip->name); + + return s2mpg1x_add_chained_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, chained_pirq, + irq_data, chained_irq_chip, &sec_pmic->irq_data); +} + int sec_irq_init(struct sec_pmic_dev *sec_pmic) { const struct regmap_irq_chip *sec_irq_chip; @@ -268,8 +336,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) sec_irq_chip = &s2mps14_irq_chip; break; case S2MPG10: - sec_irq_chip = &s2mpg10_irq_chip; - break; + return sec_irq_init_s2mpg1x(sec_pmic); case S2MPS11X: sec_irq_chip = &s2mps11_irq_chip; break; -- cgit v1.2.3 From b4b1bd1f330fdd13706382be6c90ce9f58cee3f5 Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Tue, 18 Nov 2025 20:15:00 +0800 Subject: mfd: mt6397-irq: Fix missing irq_domain_remove() in error path If devm_request_threaded_irq() fails after irq_domain_create_linear() succeeds in mt6397_irq_init(), the function returns without removing the created IRQ domain, leading to a resource leak. Call irq_domain_remove() in the error path after a successful irq_domain_create_linear() to properly release the IRQ domain. Fixes: a4872e80ce7d ("mfd: mt6397: Extract IRQ related code from core driver") Signed-off-by: Haotian Zhang Link: https://patch.msgid.link/20251118121500.605-1-vulab@iscas.ac.cn Signed-off-by: Lee Jones --- drivers/mfd/mt6397-irq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c index 0e463026c5a9..5d2e5459f744 100644 --- a/drivers/mfd/mt6397-irq.c +++ b/drivers/mfd/mt6397-irq.c @@ -229,6 +229,7 @@ int mt6397_irq_init(struct mt6397_chip *chip) if (ret) { dev_err(chip->dev, "failed to register irq=%d; err: %d\n", chip->irq, ret); + irq_domain_remove(chip->irq_domain); return ret; } -- cgit v1.2.3 From 384bd58bf7095e4c4c8fcdbcede316ef342c630c Mon Sep 17 00:00:00 2001 From: Haotian Zhang Date: Tue, 18 Nov 2025 20:14:27 +0800 Subject: mfd: mt6358-irq: Fix missing irq_domain_remove() in error path If devm_request_threaded_irq() fails after irq_domain_add_linear() succeeds in mt6358_irq_init(), the function returns without removing the created IRQ domain, leading to a resource leak. Call irq_domain_remove() in the error path after a successful irq_domain_add_linear() to properly release the IRQ domain. Fixes: 2b91c28f2abd ("mfd: Add support for the MediaTek MT6358 PMIC") Signed-off-by: Haotian Zhang Link: https://patch.msgid.link/20251118121427.583-1-vulab@iscas.ac.cn Signed-off-by: Lee Jones --- drivers/mfd/mt6358-irq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/mt6358-irq.c b/drivers/mfd/mt6358-irq.c index f467b00d2366..74cf20843044 100644 --- a/drivers/mfd/mt6358-irq.c +++ b/drivers/mfd/mt6358-irq.c @@ -285,6 +285,7 @@ int mt6358_irq_init(struct mt6397_chip *chip) if (ret) { dev_err(chip->dev, "Failed to register IRQ=%d, ret=%d\n", chip->irq, ret); + irq_domain_remove(chip->irq_domain); return ret; } -- cgit v1.2.3 From 0e056211b8c92b9a051915afbc0409bc1cadc341 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 4 Nov 2025 00:29:42 +0100 Subject: mfd: qnap-mcu: Hook up the EEPROM sub-device Add the qnap-mcu-eeprom platform-driver as sub-device for the MCU. Signed-off-by: Heiko Stuebner Link: https://patch.msgid.link/20251103232942.410386-3-heiko@sntech.de Signed-off-by: Lee Jones --- drivers/mfd/qnap-mcu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/mfd') diff --git a/drivers/mfd/qnap-mcu.c b/drivers/mfd/qnap-mcu.c index 6bbf8334caa4..f81c69f22254 100644 --- a/drivers/mfd/qnap-mcu.c +++ b/drivers/mfd/qnap-mcu.c @@ -333,6 +333,7 @@ static const struct qnap_mcu_variant qnap_ts433_mcu = { }; static struct mfd_cell qnap_mcu_cells[] = { + { .name = "qnap-mcu-eeprom", }, { .name = "qnap-mcu-input", }, { .name = "qnap-mcu-leds", }, { .name = "qnap-mcu-hwmon", } -- cgit v1.2.3 From 44c603f35cad3f3b0f58fece99502d81620da9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Mon, 24 Nov 2025 06:47:18 +0000 Subject: mfd: sec: Drop a stray semicolon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A stray and unneeded semicolon was added here by accident, just drop it. Fixes: ee19b52c31b3 ("mfd: sec: Use chained IRQs for s2mpg10") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202511230909.zk7EkTnb-lkp@intel.com/ Signed-off-by: André Draszik Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20251124-s2mpg10-chained-irq-semicolon-v1-1-578ba2d7adca@linaro.org Signed-off-by: Lee Jones --- drivers/mfd/sec-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mfd') diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c index d992e41e716d..74ac70002d1f 100644 --- a/drivers/mfd/sec-irq.c +++ b/drivers/mfd/sec-irq.c @@ -304,7 +304,7 @@ static int sec_irq_init_s2mpg1x(struct sec_pmic_dev *sec_pmic) default: return dev_err_probe(sec_pmic->dev, -EINVAL, "Unsupported device type %d\n", sec_pmic->device_type); - }; + } regmap_common = dev_get_regmap(sec_pmic->dev, "common"); if (!regmap_common) -- cgit v1.2.3