* Re: (subset) [PATCH v13 0/5] PolarFire SoC GPIO interrupt support
From: Conor Dooley @ 2026-03-31 13:14 UTC (permalink / raw)
To: linux-gpio, Conor Dooley
Cc: Conor Dooley, Herve Codina, Daire McNamara, Rob Herring,
Krzysztof Kozlowski, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Alexandre Ghiti, Linus Walleij, Bartosz Golaszewski, linux-riscv,
devicetree, linux-kernel, Thomas Gleixner
In-Reply-To: <20260318-gift-nearest-fd3ef3e4819b@spud>
From: Conor Dooley <conor.dooley@microchip.com>
On Wed, 18 Mar 2026 11:04:31 +0000, Conor Dooley wrote:
> From: Conor Dooley <conor.dooley@microchip.com>
>
> Yo,
>
> Here's a v3 with an extra patch updating the gpio binding from fished
> out from my old branch, fixing the examples and setting the permitted
> values of gpios for the controllers on polarfire soc and the existing
> binding patch's example fixed.
>
> [...]
Gonna interpret the ack and lack of response to me asking if the gpio
change was mine to take as it being the case.
Applied to riscv-soc-for-next, thanks!
[2/5] gpio: mpfs: Add interrupt support
https://git.kernel.org/conor/c/e57b53f0f36a
[3/5] dt-bindings: soc: microchip: document PolarFire SoC's gpio interrupt mux
https://git.kernel.org/conor/c/5f3575cc73dc
[4/5] soc: microchip: add mpfs gpio interrupt mux driver
https://git.kernel.org/conor/c/bd34cdd6d214
Thanks,
Conor.
^ permalink raw reply
* [PATCH net-next v2] net: macb: fix use of at91_default_usrio without CONFIG_OF
From: Conor Dooley @ 2026-03-31 13:10 UTC (permalink / raw)
To: netdev
Cc: conor, Conor Dooley, kernel test robot, Jiawen Wu, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Nicolas Ferre, Claudiu Beznea, devicetree, linux-kernel,
linux-riscv
From: Conor Dooley <conor.dooley@microchip.com>
If CONFIG_OF is not enabled, at91_default_usrio is used undeclared in
gem_default_config. Move at91_default_usrio back above the CONFIG_OF
section where macb_default_usrio used to be, so that it is unconditionally
defined and defined prior to any of the users.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202603280028.wQjUrIvv-lkp@intel.com/
Reported-by: Jiawen Wu <jiawenwu@trustnetic.com>
Closes: https://lore.kernel.org/all/06a701dcc014$86def5b0$949ce110$@trustnetic.com/
Fixes: a17871778ee28 ("net: macb: rename macb_default_usrio to at91_default_usrio as not all platforms have mii mode control in usrio")
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
lkp also reported this over the weekend, but against the dev copy in my
tree. I had thought that CONFIG_OF was standard off on x86, but I guess
it isn't, given lkp didn't catch it until randconfigs.
Seem to have come down with some sort of bug, hopefully I haven't cocked
this v2 up somehow in my addled state.
v2:
- Do the boring thing that works... Probably worth a revisit later, cos
there's a bunch of confusing naming here still - "default_gem_config"
is used for cdns,macb and of course "at91_default_usrio" is used on
things where I am reasonably confident it shouldn't, like the Xilinx
boards.
CC: Andrew Lunn <andrew+netdev@lunn.ch>
CC: David S. Miller <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jakub Kicinski <kuba@kernel.org>
CC: Paolo Abeni <pabeni@redhat.com>
CC: Nicolas Ferre <nicolas.ferre@microchip.com>
CC: Claudiu Beznea <claudiu.beznea@tuxon.dev>
CC: netdev@vger.kernel.org
CC: devicetree@vger.kernel.org
CC: linux-kernel@vger.kernel.org
CC: linux-riscv@lists.infradead.org
---
drivers/net/ethernet/cadence/macb_main.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index 12e2b2f4aaf88..3e37b0a3e7e4b 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -4949,6 +4949,13 @@ static int macb_init(struct platform_device *pdev,
return macb_init_dflt(pdev);
}
+static const struct macb_usrio_config at91_default_usrio = {
+ .mii = MACB_BIT(MII),
+ .rmii = MACB_BIT(RMII),
+ .rgmii = GEM_BIT(RGMII),
+ .clken = MACB_BIT(CLKEN),
+};
+
#if defined(CONFIG_OF)
/* 1518 rounded up */
#define AT91ETHER_MAX_RBUFF_SZ 0x600
@@ -5523,13 +5530,6 @@ static int eyeq5_init(struct platform_device *pdev)
return ret;
}
-static const struct macb_usrio_config at91_default_usrio = {
- .mii = MACB_BIT(MII),
- .rmii = MACB_BIT(RMII),
- .rgmii = GEM_BIT(RGMII),
- .clken = MACB_BIT(CLKEN),
-};
-
static const struct macb_usrio_config mpfs_usrio = {
.tsu_source = 0,
};
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v4 3/5] mfd: aaeon: Add SRG-IMX8P MCU driver
From: Lee Jones @ 2026-03-31 13:08 UTC (permalink / raw)
To: Thomas Perrot (Schneider Electric)
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
Bartosz Golaszewski, Shawn Guo, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam,
Jérémie Dautheribes, Wim Van Sebroeck, Guenter Roeck,
devicetree, linux-kernel, linux-gpio, imx, linux-arm-kernel,
linux-watchdog, Thomas Petazzoni, Miquel Raynal
In-Reply-To: <20260324-dev-b4-aaeon-mcu-driver-v4-3-afb011df4794@bootlin.com>
On Tue, 24 Mar 2026, Thomas Perrot (Schneider Electric) wrote:
> Add Multi-Function Device (MFD) driver for the Aaeon SRG-IMX8P
> embedded controller. This driver provides the core I2C communication
> interface and registers child devices (GPIO and watchdog controllers).
>
> The driver implements a custom regmap bus over I2C to match the MCU's
> fixed 3-byte command format [opcode, arg, value]. Register addresses
> are encoded as 16-bit values (opcode << 8 | arg) using the
> AAEON_MCU_REG() macro defined in the shared header. The regmap
> instance is shared with child drivers via dev_get_regmap(). Concurrent
> I2C accesses from child drivers are serialized by regmap's built-in
> locking.
>
> Co-developed-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Jérémie Dautheribes (Schneider Electric) <jeremie.dautheribes@bootlin.com>
> Signed-off-by: Thomas Perrot (Schneider Electric) <thomas.perrot@bootlin.com>
> ---
> MAINTAINERS | 2 +
> drivers/mfd/Kconfig | 10 +++
> drivers/mfd/Makefile | 1 +
> drivers/mfd/aaeon-mcu.c | 155 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/aaeon-mcu.h | 20 ++++++
> 5 files changed, 188 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ea9d55f76f3509c7f6ba6d1bc86ca2e2e71aa954..f91b6a1826d04bef8a0f88221f6c8e8a3652cd77 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -191,6 +191,8 @@ M: Thomas Perrot <thomas.perrot@bootlin.com>
> R: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
> S: Maintained
> F: Documentation/devicetree/bindings/mfd/aaeon,srg-imx8p-mcu.yaml
> +F: drivers/mfd/aaeon-mcu.c
> +F: include/linux/mfd/aaeon-mcu.h
>
> AAEON UPBOARD FPGA MFD DRIVER
> M: Thomas Richard <thomas.richard@bootlin.com>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index aace5766b38aa5e46e32a8a7b42eea238159fbcf..7a1ceedece899faad7a03a1fe7b1c91b72253c05 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1574,6 +1574,16 @@ config AB8500_CORE
> the irq_chip parts for handling the Mixed Signal chip events.
> This chip embeds various other multimedia functionalities as well.
>
> +config MFD_AAEON_MCU
> + tristate "Aaeon SRG-IMX8P MCU Driver"
> + depends on I2C || COMPILE_TEST
> + select MFD_CORE
> + help
> + Select this option to enable support for the Aaeon SRG-IMX8P
> + onboard microcontroller (MCU). This driver provides the core
> + functionality to communicate with the MCU over I2C. The MCU
> + provides GPIO and watchdog functionality.
> +
> config MFD_DB8500_PRCMU
> bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
> depends on UX500_SOC_DB8500
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index e75e8045c28afae975ac61d282b3b85af5440119..34db5b033584368b7a269b1eef12528a74baf8f5 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o
> obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o
> obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
> obj-$(CONFIG_MFD_88PM886_PMIC) += 88pm886.o
> +obj-$(CONFIG_MFD_AAEON_MCU) += aaeon-mcu.o
> obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
> obj-$(CONFIG_MFD_SM501) += sm501.o
> obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
> diff --git a/drivers/mfd/aaeon-mcu.c b/drivers/mfd/aaeon-mcu.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..5a969890d201c027eb25c324b4d4d89b1f8c563e
> --- /dev/null
> +++ b/drivers/mfd/aaeon-mcu.c
> @@ -0,0 +1,155 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Aaeon MCU driver
> + *
> + * Copyright (C) 2025 Bootlin
> + * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
> + * Author: Thomas Perrot <thomas.perrot@bootlin.com>
> + */
Consider updating the Copyright date - we're pretty deep into 2026 at this point.
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/mfd/core.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +static const struct mfd_cell aaeon_mcu_devs[] = {
> + {
> + .name = "aaeon-mcu-wdt",
> + },
> + {
> + .name = "aaeon-mcu-gpio",
> + },
> +};
MFD_CELL_BASIC()
> +/*
> + * Custom regmap bus for the Aaeon MCU I2C protocol.
> + *
> + * The MCU uses a fixed 3-byte command format [opcode, arg, value] followed
> + * by a 1-byte response. It requires a STOP condition between the command
> + * write and the response read, so two separate i2c_transfer() calls are
> + * issued. The regmap lock serialises concurrent accesses from the GPIO
> + * and watchdog child drivers.
> + *
> + * Register addresses are encoded as a 16-bit big-endian value where the
> + * high byte is the opcode and the low byte is the argument, matching the
> + * wire layout produced by regmap for reg_bits=16.
> + */
> +
> +static int aaeon_mcu_regmap_write(void *context, const void *data, size_t count)
> +{
> + struct i2c_client *client = context;
> + /* data = [opcode, arg, value] as formatted by regmap */
> + struct i2c_msg write_msg = {
> + .addr = client->addr,
> + .flags = 0,
> + .buf = (u8 *)data,
> + .len = count,
> + };
> + u8 rsp;
> + /* The MCU always sends a response byte after each command; discard it. */
> + struct i2c_msg rsp_msg = {
Assuming 'rsp' means response, let's just write that out in full.
Readability wins over brevity every time.
> + .addr = client->addr,
> + .flags = I2C_M_RD,
> + .buf = &rsp,
> + .len = 1,
> + };
> + int ret;
Since some I2C host controllers might use DMA, should we ensure that the
'rsp' buffer is allocated in DMA-safe memory rather than on the stack to
prevent potential cache-line corruption?
Also allocation of structs during in declaration statements is rough!
And adding that u8 in the middle is just rubbing it in.
> + ret = i2c_transfer(client->adapter, &write_msg, 1);
> + if (ret < 0)
> + return ret;
> + if (ret != 1)
> + return -EIO;
> +
> + ret = i2c_transfer(client->adapter, &rsp_msg, 1);
> + if (ret < 0)
> + return ret;
> + if (ret != 1)
> + return -EIO;
> +
> + return 0;
> +}
> +
> +static int aaeon_mcu_regmap_read(void *context, const void *reg_buf,
> + size_t reg_size, void *val_buf, size_t val_size)
> +{
> + struct i2c_client *client = context;
> + /*
> + * reg_buf holds the 2-byte big-endian register address [opcode, arg].
> + * Append a trailing 0x00 to form the full 3-byte MCU command.
> + */
> + u8 cmd[3] = { ((u8 *)reg_buf)[0], ((u8 *)reg_buf)[1], 0x00 };
> + struct i2c_msg write_msg = {
> + .addr = client->addr,
> + .flags = 0,
> + .buf = cmd,
> + .len = sizeof(cmd),
> + };
> + struct i2c_msg read_msg = {
> + .addr = client->addr,
> + .flags = I2C_M_RD,
> + .buf = val_buf,
> + .len = val_size,
> + };
> + int ret;
> +
> + ret = i2c_transfer(client->adapter, &write_msg, 1);
> + if (ret < 0)
> + return ret;
> + if (ret != 1)
> + return -EIO;
> +
> + ret = i2c_transfer(client->adapter, &read_msg, 1);
> + if (ret < 0)
> + return ret;
> + if (ret != 1)
> + return -EIO;
> +
> + return 0;
> +}
> +
> +static const struct regmap_bus aaeon_mcu_regmap_bus = {
> + .write = aaeon_mcu_regmap_write,
> + .read = aaeon_mcu_regmap_read,
> +};
> +
> +static const struct regmap_config aaeon_mcu_regmap_config = {
> + .reg_bits = 16,
> + .val_bits = 8,
> + .reg_format_endian = REGMAP_ENDIAN_BIG,
> + .cache_type = REGCACHE_NONE,
Are you sure? Why none?
> +};
> +
> +static int aaeon_mcu_probe(struct i2c_client *client)
> +{
> + struct regmap *regmap;
> +
> + regmap = devm_regmap_init(&client->dev, &aaeon_mcu_regmap_bus,
> + client, &aaeon_mcu_regmap_config);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
dev_err_probe()
> +
> + return devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
> + aaeon_mcu_devs, ARRAY_SIZE(aaeon_mcu_devs),
> + NULL, 0, NULL);
Why PLATFORM_DEVID_NONE over AUTO here?
> +}
> +
> +static const struct of_device_id aaeon_mcu_of_match[] = {
> + { .compatible = "aaeon,srg-imx8p-mcu" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, aaeon_mcu_of_match);
> +
> +static struct i2c_driver aaeon_mcu_driver = {
> + .driver = {
> + .name = "aaeon_mcu",
> + .of_match_table = aaeon_mcu_of_match,
> + },
> + .probe = aaeon_mcu_probe,
> +};
> +module_i2c_driver(aaeon_mcu_driver);
> +
> +MODULE_DESCRIPTION("Aaeon MCU Driver");
> +MODULE_AUTHOR("Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/aaeon-mcu.h b/include/linux/mfd/aaeon-mcu.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..861003f6dfd20424c3785008bd2cf89aaa1715b9
> --- /dev/null
> +++ b/include/linux/mfd/aaeon-mcu.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Aaeon MCU driver definitions
> + *
> + * Copyright (C) 2025 Bootlin
> + * Author: Jérémie Dautheribes <jeremie.dautheribes@bootlin.com>
> + * Author: Thomas Perrot <thomas.perrot@bootlin.com>
> + */
As above.
> +
> +#ifndef __LINUX_MFD_AAEON_MCU_H
> +#define __LINUX_MFD_AAEON_MCU_H
> +
> +/*
> + * MCU register address: the high byte is the command opcode, the low
> + * byte is the argument. This matches the 3-byte wire format
> + * [opcode, arg, value] used by the MCU I2C protocol.
> + */
> +#define AAEON_MCU_REG(op, arg) (((op) << 8) | (arg))
Where else is this used?
> +#endif /* __LINUX_MFD_AAEON_MCU_H */
>
> --
> 2.53.0
>
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH v9 2/9] lib: vsprintf: export simple_strntoull() in a safe prototype
From: Rodrigo Alencar @ 2026-03-31 13:01 UTC (permalink / raw)
To: Rodrigo Alencar, Andy Shevchenko
Cc: Petr Mladek, rodrigo.alencar, linux-kernel, linux-iio, devicetree,
linux-doc, Jonathan Cameron, David Lechner, Andy Shevchenko,
Lars-Peter Clausen, Michael Hennerich, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet, Andrew Morton,
Steven Rostedt, Rasmus Villemoes, Sergey Senozhatsky, Shuah Khan
In-Reply-To: <qnb3ozrhrq5n4zkh2luitkpwr5oj4omgcuo5vnvy2gatdfdqlg@cgsgux7etcql>
On 26/03/30 01:49PM, Rodrigo Alencar wrote:
> On 26/03/27 03:17PM, Rodrigo Alencar wrote:
> > On 26/03/27 12:21PM, Andy Shevchenko wrote:
> > > On Fri, Mar 27, 2026 at 10:11:56AM +0000, Rodrigo Alencar wrote:
> > > > On 26/03/27 11:17AM, Andy Shevchenko wrote:
> > > > > On Fri, Mar 27, 2026 at 09:45:17AM +0100, Petr Mladek wrote:
> > > > > > On Fri 2026-03-20 16:27:27, Rodrigo Alencar via B4 Relay wrote:
>
> ...
>
> > > > > Maybe we want to have kstrtof32() and kstrtof64() for these two cases?
> > > > >
> > > > > With that we will always consider the fraction part as 32- or 64-bit,
> > > > > imply floor() on the fraction for the sake of simplicity and require
> > > > > it to be NUL-terminated with possible trailing '\n'.
> > > >
> > > > I think this is a good idea, but calling it float or fixed point itself
> > > > is a bit confusing as float often refers to the IEEE 754 standard and
> > > > fixed point types is often expressed in Q-format.
> > >
> > > Yeah... I am lack of better naming.
> >
> > decimals is the name, but they are often represented as:
> >
> > DECIMAL = INT * 10^X + FRAC
> >
> > in a single 64-bit number, which would be fine for my end use case.
> > However IIO decimal fixed point parsing is out there for quite some time a
> > lot of drivers use that. The interface often relies on breaking parsed values
> > into an integer array (for standard attributes int val and int val2 are expected).
>
> Thinking about this again and in IIO drivers we end up doing something like:
>
> val64 = (u64)val * MICRO + val2;
>
> so that drivers often work with scaled versions of the decimal value.
> then, would it make sense to have a function that already outputs such value?
> That would allow to have more freedom over the 64-bit split between integer
> and fractional parts.
> As a draft:
>
> static int _kstrtodec64(const char *s, unsigned int scale, u64 *res)
> {
> u64 _res = 0, _frac = 0;
> unsigned int rv;
>
> if (*s != '.') {
> rv = _parse_integer(s, 10, &_res);
> if (rv & KSTRTOX_OVERFLOW)
> return -ERANGE;
> if (rv == 0)
> return -EINVAL;
> s += rv;
> }
>
> if (*s == '.') {
> s++;
> rv = _parse_integer_limit(s, 10, &_frac, scale);
> if (rv & KSTRTOX_OVERFLOW)
> return -ERANGE;
> if (rv == 0)
> return -EINVAL;
> s += rv;
> if (rv < scale)
> _frac *= int_pow(10, scale - rv);
> while (isdigit(*s)) /* truncate */
> s++;
> }
>
> if (*s == '\n')
> s++;
> if (*s)
> return -EINVAL;
>
> if (check_mul_overflow(_res, int_pow(10, scale), &_res) ||
> check_add_overflow(_res, _frac, &_res))
> return -ERANGE;
>
> *res = _res;
> return 0;
> }
>
> noinline
> int kstrtoudec64(const char *s, unsigned int scale, u64 *res)
> {
> if (s[0] == '+')
> s++;
> return _kstrtodec64(s, scale, res);
> }
> EXPORT_SYMBOL(kstrtoudec64);
>
> noinline
> int kstrtosdec64(const char *s, unsigned int scale, s64 *res)
> {
> u64 tmp;
> int rv;
>
> if (s[0] == '-') {
> rv = _kstrtodec64(s + 1, scale, &tmp);
> if (rv < 0)
> return rv;
> if ((s64)-tmp > 0)
> return -ERANGE;
> *res = -tmp;
> } else {
> rv = kstrtoudec64(s, scale, &tmp);
> if (rv < 0)
> return rv;
> if ((s64)tmp < 0)
> return -ERANGE;
> *res = tmp;
> }
> return 0;
> }
> EXPORT_SYMBOL(kstrtosdec64);
>
> e.g., kstrtosdec64() or kstrtoudec64() parses "3.1415" with scale 3 into 3141
Hi Jonathan,
developing more on that, I wouldn't need to create a iio_str_to_fixpoint64(),
what do you think on new format types:
#define IIO_VAL_DECIMAL64_1 101
#define IIO_VAL_DECIMAL64_2 102
#define IIO_VAL_DECIMAL64_3 103
#define IIO_VAL_DECIMAL64_4 104
#define IIO_VAL_DECIMAL64_5 105
#define IIO_VAL_DECIMAL64_6 106
#define IIO_VAL_DECIMAL64_7 107
#define IIO_VAL_DECIMAL64_8 108
#define IIO_VAL_DECIMAL64_9 109
#define IIO_VAL_DECIMAL64_10 110
#define IIO_VAL_DECIMAL64_11 111
#define IIO_VAL_DECIMAL64_12 112
#define IIO_VAL_DECIMAL64_13 113
#define IIO_VAL_DECIMAL64_14 114
#define IIO_VAL_DECIMAL64_15 115
#define IIO_VAL_DECIMAL64_MILLI IIO_VAL_DECIMAL64_3
#define IIO_VAL_DECIMAL64_MICRO IIO_VAL_DECIMAL64_6
#define IIO_VAL_DECIMAL64_NANO IIO_VAL_DECIMAL64_9
#define IIO_VAL_DECIMAL64_PICO IIO_VAL_DECIMAL64_12
#define IIO_VAL_DECIMAL64_FEMTO IIO_VAL_DECIMAL64_15
which gets stored as 64-bit, and represent the decimal scaled value.
That would also work for the PLL driver (using IIO_VAL_DECIMAL64_MICRO):
- It supports frequency range from 1 to 26 GHz with micro Hz resolution
- In the driver a 64-bit value: (val * MICRO + val2) is already created
anyways.
I would leverage something like kstrtodec64() in iio_write_channel_info().
That way, I would drop the changes on the iio fixpoint parse, which I think
it would do better with something like kstrntoull() to be able to handle that
"dB" suffix.
So for now, I may have the following approaches:
- new kstrntoull() function: to have control over the parsing, whithout
requiring NUL-termination, avoiding unecessary string scanning or copying.
covered in v8.
- expose a "safe" simple_strntoull(): minimal changes to vsprintf.c, this
is covered by this patch series (v9), and it similar solution to kstrntoull().
- new kstrtodec64() function: parse decimal numbers as 64-bit with NUL-termination.
Might be covered in a v10, if it is a good idea.
let me know your thoughts.
--
Kind regards,
Rodrigo Alencar
^ permalink raw reply
* Re: [PATCH v2 2/2] ARM: dts: nxp: imx51-ts4800: Rename wdt node to watchdog
From: Daniel Baluta @ 2026-03-31 13:00 UTC (permalink / raw)
To: Eduard Bostina, daniel.baluta, simona.toaca, d-gole, m-chawdhry,
Wim Van Sebroeck, Guenter Roeck, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Mark Brown, linux-watchdog, devicetree,
linux-kernel, imx, linux-arm-kernel
In-Reply-To: <20260323175948.302441-3-egbostina@gmail.com>
On 3/23/26 19:59, Eduard Bostina wrote:
> The Technologic Systems TS-4800 watchdog node was previously named 'wdt',
> which violates the core watchdog.yaml schema expecting generic node names.
>
> Rename the node to 'watchdog' to fix the following dtbs_check warning:
> 'wdt' does not match '^(pmic|timer|watchdog)(@.*|-([0-9]|[1-9][0-9]+))?$'
>
> Signed-off-by: Eduard Bostina <egbostina@gmail.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
^ permalink raw reply
* Re: [PATCH v8 4/7] mfd: p3h2x4x: Add driver for NXP P3H2x4x i3c hub and on-die regulator
From: Lee Jones @ 2026-03-31 12:52 UTC (permalink / raw)
To: Lakshay Piplani
Cc: linux-kernel, linux-i3c, alexandre.belloni, krzk+dt, robh,
conor+dt, devicetree, broonie, Frank.Li, lgirdwood, vikash.bansal,
priyanka.jain, aman.kumarpandey
In-Reply-To: <20260331112918.GD3795166@google.com>
On Tue, 31 Mar 2026, Lee Jones wrote:
> On Mon, 23 Mar 2026, Lakshay Piplani wrote:
>
> > From: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
> >
> > Add core MFD support for the NXP P3H2x4x (P3H2440/P3H2441/P3H2840/P3H2841)
> > family of multiport I3C hub devices. These devices connect to a host via
> > I3C/I2C/SMBus and expose multiple downstream target ports.
> >
> > Signed-off-by: Aman Kumar Pandey <aman.kumarpandey@nxp.com>
> > Signed-off-by: Vikash Bansal <vikash.bansal@nxp.com>
> >
> > ---
> > Changes in v8:
> > - No change
> >
> > Changes in v7:
> > - Use new config I3C_OR_I2C
> >
> > Changes in v6:
> > - No change
> >
> > Changes in v5:
> > - Corrected the ordering in the Makefile and Kconfig for MFD_P3H2X4X
> > - Updated dev_err_probe() for regmap_init failure.
> > - Updated module description
> >
> > Changes in v4:
> > - Split the driver into three separate patches(mfd, regulator and I3C hub)
> > - Added support for NXP P3H2x4x MFD functionality
> > ---
> > ---
> > MAINTAINERS | 2 +
> > drivers/mfd/Kconfig | 13 ++++
> > drivers/mfd/Makefile | 1 +
> > drivers/mfd/p3h2840.c | 125 ++++++++++++++++++++++++++++++++++++
> > include/linux/mfd/p3h2840.h | 27 ++++++++
> > 5 files changed, 168 insertions(+)
> > create mode 100644 drivers/mfd/p3h2840.c
> > create mode 100644 include/linux/mfd/p3h2840.h
[...]
> > diff --git a/include/linux/mfd/p3h2840.h b/include/linux/mfd/p3h2840.h
> > new file mode 100644
> > index 000000000000..cba6fa516d1e
> > --- /dev/null
> > +++ b/include/linux/mfd/p3h2840.h
> > @@ -0,0 +1,27 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
>
> These should use // in header files.
Ignore this. I've lead you astray there.
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH 0/2] memory: tegra: Add Tegra238 memory controller support
From: Krzysztof Kozlowski @ 2026-03-31 12:52 UTC (permalink / raw)
To: Ashish Mhetre, robh, conor+dt, jonathanh, sumitg
Cc: linux-kernel, devicetree, linux-tegra
In-Reply-To: <cf8e568b-c349-44c6-95b4-d1b586c32805@kernel.org>
On 31/03/2026 13:39, Krzysztof Kozlowski wrote:
> On 31/03/2026 13:23, Ashish Mhetre wrote:
>> This series adds Memory Controller driver support for the Tegra238 SoC.
>>
>> Tegra238 is similar to Tegra234 but with a reduced memory controller
>> configuration featuring 8 channels instead of 16. The driver reuses
>> Tegra234 memory client IDs and ICC operations, with Tegra238-specific
>> stream IDs for SMMU configuration.
>>
>
> Thank you for the patch/patchset. My tree is currently closed for new
> features till the end of the merge window. I will review and/or apply
> the patch after the merge window. No need to resend it, I will keep this
> in my mailbox.
>
> If I misjudged this patch and this is a fix, please let me know.
And FWIW, I did take a quick look and code seemed fine, so I don't have
immediate objections.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: reset: imx8mq: Add _N suffix to IMX8MQ_RESET_MIPI_CSI*_RESET
From: Philipp Zabel @ 2026-03-31 12:45 UTC (permalink / raw)
To: Robby Cai, robh, krzk+dt, conor+dt, Frank.Li, s.hauer, festevam
Cc: devicetree, kernel, imx, linux-arm-kernel, linux-kernel,
aisheng.dong
In-Reply-To: <20260331101331.1405588-2-robby.cai@nxp.com>
On Di, 2026-03-31 at 18:13 +0800, Robby Cai wrote:
> The assert logic of the MIPI CSI reset signals is active-low on i.MX8MQ,
> but the existing names do not indicate this explicitly. To improve
> consistency and clarity, append the _N suffix to all
> IMX8MQ_RESET_MIPI_CSI*_RESET definitions. The deprecated
> IMX8MQ_RESET_MIPI_CSI*_RESET versions remain temporarily for DT ABI
> compatibility and will be removed at an appropriate time in the future.
The register description in the latest reference manual I can download,
IMX8MDQLQRM Rev. 3.1 (06/2021), still call these bits
MIPI_CSI1_CORE_RESET and so on (without _N). There is no mention of
polarity in the bitfield description. Is a documentation update
planned?
Right now I'd say this improves clarity, but reduces consistency with
existing documentation.
Are these bits self-clearing, or can the reset be asserted by writing
0? As it stands, the CSI driver using these resets, imx8mq-mipi-csi2.c,
only calls reset_control_assert() in imx8mq_mipi_csi_sw_reset():
/*
* these are most likely self-clearing reset bits. to make it
* more clear, the reset-imx7 driver should implement the
* .reset() operation.
*/
ret = reset_control_assert(state->rst);
This will probably have to be turned into a deassert together with the
reset driver change.
regards
Philipp
^ permalink raw reply
* [PATCH net-next v3 1/2] dt-bindings: net: document Microchip PIC64-HPSC/HX MDIO controller
From: Charles Perry @ 2026-03-31 12:38 UTC (permalink / raw)
To: netdev
Cc: Charles Perry, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, devicetree, linux-kernel
In-Reply-To: <20260331123858.1912449-1-charles.perry@microchip.com>
This MDIO hardware is based on a Microsemi design supported in Linux by
mdio-mscc-miim.c. However, The register interface is completely different
with pic64hpsc, hence the need for separate documentation.
The hardware supports C22 and C45.
The documentation recommends an input clock of 156.25MHz and a prescaler
of 39, which yields an MDIO clock of 1.95MHz.
The hardware supports an interrupt pin to signal transaction completion
which is not strictly needed as the software can also poll a "TRIGGER"
bit for this.
Signed-off-by: Charles Perry <charles.perry@microchip.com>
---
Notes:
Changes in v3: none
Changes in v2:
- Make "clocks" and "interrupts" required (Andrew)
- Add a default value to "clock-frequency" (Andrew)
.../net/microchip,pic64hpsc-mdio.yaml | 68 +++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/microchip,pic64hpsc-mdio.yaml
diff --git a/Documentation/devicetree/bindings/net/microchip,pic64hpsc-mdio.yaml b/Documentation/devicetree/bindings/net/microchip,pic64hpsc-mdio.yaml
new file mode 100644
index 000000000000..d690afe3d3cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/microchip,pic64hpsc-mdio.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/microchip,pic64hpsc-mdio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip PIC64-HPSC/HX MDIO controller
+
+maintainers:
+ - Charles Perry <charles.perry@microchip.com>
+
+description: |
+ Microchip PIC64-HPSC/HX SoCs have two MDIO bus controller. This MDIO bus
+ controller supports C22 and C45 register access. It is named "MDIO Initiator"
+ in the documentation.
+
+allOf:
+ - $ref: mdio.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - const: microchip,pic64hpsc-mdio
+ - items:
+ - const: microchip,pic64hx-mdio
+ - const: microchip,pic64hpsc-mdio
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-frequency:
+ default: 2500000
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ mdio@4000C21E000 {
+ compatible = "microchip,pic64hpsc-mdio";
+ reg = <0x400 0x0C21E000 0x0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&svc_clk>;
+ interrupt-parent = <&saplic0>;
+ interrupts = <168 IRQ_TYPE_LEVEL_HIGH>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+ };
+ };
--
2.47.3
^ permalink raw reply related
* [PATCH net-next v3 0/2] Add support for PIC64-HPSC/HX MDIO controller
From: Charles Perry @ 2026-03-31 12:38 UTC (permalink / raw)
To: netdev
Cc: Charles Perry, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Heiner Kallweit, Russell King, devicetree
Hello,
This series adds a driver for the two MDIO controllers of PIC64-HPSC/HX.
The hardware supports C22 and C45 but only C22 is implemented for now.
This MDIO hardware is based on a Microsemi design supported in Linux by
mdio-mscc-miim.c. However, The register interface is completely different
with pic64hpsc, hence the need for a separate driver.
The documentation recommends an input clock of 156.25MHz and a prescaler of
39, which yields an MDIO clock of 1.95MHz.
This was tested on Microchip HB1301 evalkit which has a VSC8574 and a
VSC8541 with clock frequencies of 0.6, 1.95 and 2.5 MHz.
Thanks,
Charles
Changes in v3:
- 2/2: Add a MAINTAINERS entry (Jakub)
Changes in v2:
- 1/2: Make "clocks" and "interrupts" required (Andrew)
- 1/2: Add a default value to "clock-frequency" (Andrew)
- 2/2: Remove #define for unused registers (Maxime)
- 2/2: Add "c22" to clause 22 read/write ops (Maxime)
- 2/2: Remove the call to platform_set_drvdata() (Andrew)
- 2/2: Make the clock mandatory (Andrew)
- 2/2: Use 2.5MHz if no clock-frequency was specified (Andrew)
- 2/2: Change the error message for bad clock-frequency (Andrew)
- 2/2: Fix a use without initialization on bus_freq (Andrew)
CC: Andrew Lunn <andrew+netdev@lunn.ch>
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jakub Kicinski <kuba@kernel.org>
CC: Paolo Abeni <pabeni@redhat.com>
CC: Rob Herring <robh@kernel.org>
CC: Krzysztof Kozlowski <krzk+dt@kernel.org>
CC: Conor Dooley <conor+dt@kernel.org>
CC: Heiner Kallweit <hkallweit1@gmail.com>
CC: Russell King <linux@armlinux.org.uk>
CC: netdev@vger.kernel.org
CC: devicetree@vger.kernel.org
Charles Perry (2):
dt-bindings: net: document Microchip PIC64-HPSC/HX MDIO controller
net: mdio: add a driver for PIC64-HPSC/HX MDIO controller
.../net/microchip,pic64hpsc-mdio.yaml | 68 +++++++
MAINTAINERS | 6 +
drivers/net/mdio/Kconfig | 7 +
drivers/net/mdio/Makefile | 1 +
drivers/net/mdio/mdio-pic64hpsc.c | 192 ++++++++++++++++++
5 files changed, 274 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/microchip,pic64hpsc-mdio.yaml
create mode 100644 drivers/net/mdio/mdio-pic64hpsc.c
--
2.47.3
^ permalink raw reply
* Re: [PATCH v5 09/11] mfd: bq257xx: Add BQ25792 support
From: Alexey Charkov @ 2026-03-31 12:37 UTC (permalink / raw)
To: Lee Jones
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chris Morgan,
Liam Girdwood, Mark Brown, Sebastian Reichel, devicetree,
linux-kernel, Sebastian Reichel, linux-pm
In-Reply-To: <20260331102710.GB3795166@google.com>
On Tue, Mar 31, 2026 at 2:27 PM Lee Jones <lee@kernel.org> wrote:
>
> On Tue, 24 Mar 2026, Alexey Charkov wrote:
>
> > Add register definitions and a new 'type' enum to be passed via MFD
> > private data to support the BQ25792, which is a newer variant of the
> > BQ257xx family.
> >
> > BQ25792 shares similar logic of operation with the already supported
> > BQ25703A but has a completely different register map and different
> > electrical constraints.
> >
> > Tested-by: Chris Morgan <macromorgan@hotmail.com>
> > Signed-off-by: Alexey Charkov <alchark@flipper.net>
> > ---
> > drivers/mfd/bq257xx.c | 54 +++++-
> > include/linux/mfd/bq257xx.h | 412 ++++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 463 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/mfd/bq257xx.c b/drivers/mfd/bq257xx.c
> > index e9d49dac0a16..31654925afa5 100644
> > --- a/drivers/mfd/bq257xx.c
> > +++ b/drivers/mfd/bq257xx.c
> > @@ -39,6 +39,39 @@ static const struct regmap_config bq25703_regmap_config = {
> > .val_format_endian = REGMAP_ENDIAN_LITTLE,
> > };
> >
> > +static const struct regmap_range bq25792_writeable_reg_ranges[] = {
> > + regmap_reg_range(BQ25792_REG00_MIN_SYS_VOLTAGE,
> > + BQ25792_REG18_NTC_CONTROL_1),
> > + regmap_reg_range(BQ25792_REG28_CHARGER_MASK_0,
> > + BQ25792_REG30_ADC_FUNCTION_DISABLE_1),
> > +};
> > +
> > +static const struct regmap_access_table bq25792_writeable_regs = {
> > + .yes_ranges = bq25792_writeable_reg_ranges,
> > + .n_yes_ranges = ARRAY_SIZE(bq25792_writeable_reg_ranges),
> > +};
> > +
> > +static const struct regmap_range bq25792_volatile_reg_ranges[] = {
> > + regmap_reg_range(BQ25792_REG19_ICO_CURRENT_LIMIT,
> > + BQ25792_REG27_FAULT_FLAG_1),
> > + regmap_reg_range(BQ25792_REG31_IBUS_ADC,
> > + BQ25792_REG47_DPDM_DRIVER),
> > +};
> > +
> > +static const struct regmap_access_table bq25792_volatile_regs = {
> > + .yes_ranges = bq25792_volatile_reg_ranges,
> > + .n_yes_ranges = ARRAY_SIZE(bq25792_volatile_reg_ranges),
> > +};
> > +
> > +static const struct regmap_config bq25792_regmap_config = {
> > + .reg_bits = 8,
> > + .val_bits = 8,
> > + .max_register = BQ25792_REG48_PART_INFORMATION,
> > + .cache_type = REGCACHE_MAPLE,
> > + .wr_table = &bq25792_writeable_regs,
> > + .volatile_table = &bq25792_volatile_regs,
> > +};
> > +
> > static const struct mfd_cell cells[] = {
> > MFD_CELL_NAME("bq257xx-regulator"),
> > MFD_CELL_NAME("bq257xx-charger"),
> > @@ -46,6 +79,7 @@ static const struct mfd_cell cells[] = {
> >
> > static int bq257xx_probe(struct i2c_client *client)
> > {
> > + const struct regmap_config *rcfg;
> > struct bq257xx_device *ddata;
> > int ret;
> >
> > @@ -53,9 +87,21 @@ static int bq257xx_probe(struct i2c_client *client)
> > if (!ddata)
> > return -ENOMEM;
> >
> > + ddata->type = (uintptr_t)i2c_get_match_data(client);
> > ddata->client = client;
> >
> > - ddata->regmap = devm_regmap_init_i2c(client, &bq25703_regmap_config);
> > + switch (ddata->type) {
> > + case BQ25703A:
> > + rcfg = &bq25703_regmap_config;
> > + break;
> > + case BQ25792:
> > + rcfg = &bq25792_regmap_config;
> > + break;
> > + default:
> > + return dev_err_probe(&client->dev, -EINVAL, "Unsupported device type\n");
>
> Nit: Shouldn't we be returning '-ENODEV' here for an unsupported device?
Hi Lee,
Indeed, I've had a quick look and other drivers seem to return -ENODEV
in similar situations. Shall I respin a new version with that change?
Thanks a lot,
Alexey
^ permalink raw reply
* Re: [PATCH 2/2] dt-bindings: memory: tegra: Add nvidia,tegra238-mc compatible
From: Jon Hunter @ 2026-03-31 12:32 UTC (permalink / raw)
To: Ashish Mhetre, krzk, robh, conor+dt, =thierry.reding, sumitg
Cc: linux-kernel, devicetree, linux-tegra
In-Reply-To: <20260331112347.3897841-3-amhetre@nvidia.com>
On 31/03/2026 12:23, Ashish Mhetre wrote:
> Document the device tree binding for the Tegra238 memory controller.
> Tegra238 has 8 memory controller channels plus broadcast and stream-id
> registers.
>
> Add the stream ID header (nvidia,tegra238-mc.h) defining ISO and NISO
> stream IDs for SMMU configuration.
>
> Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
> ---
> .../nvidia,tegra186-mc.yaml | 31 ++++++++
> .../dt-bindings/memory/nvidia,tegra238-mc.h | 74 +++++++++++++++++++
> 2 files changed, 105 insertions(+)
> create mode 100644 include/dt-bindings/memory/nvidia,tegra238-mc.h
>
> diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
> index 7b03b589168b..e008cb1ccd28 100644
> --- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
> +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml
> @@ -32,6 +32,7 @@ properties:
> - nvidia,tegra186-mc
> - nvidia,tegra194-mc
> - nvidia,tegra234-mc
> + - nvidia,tegra238-mc
> - nvidia,tegra264-mc
>
> reg:
> @@ -266,6 +267,36 @@ allOf:
>
> interrupt-names: false
>
> + - if:
> + properties:
> + compatible:
> + const: nvidia,tegra238-mc
> + then:
> + properties:
> + reg:
> + minItems: 10
> + maxItems: 10
> + description: 8 memory controller channels, 1 broadcast, and 1 for stream-id registers
To be consistent with existing bindings, this should be "9 memory
controller channels and 1 for stream-id registers". It appears that the
broadcast is just consider to be a memory controller channel.
Jon
--
nvpublic
^ permalink raw reply
* Re: [PATCH v9 3/6] mfd: max77759: add register bitmasks and modify irq configs for charger
From: Lee Jones @ 2026-03-31 12:31 UTC (permalink / raw)
To: amitsd
Cc: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
André Draszik, Greg Kroah-Hartman, Badhri Jagan Sridharan,
Heikki Krogerus, Peter Griffin, Tudor Ambarus, Alim Akhtar,
Mark Brown, Matti Vaittinen, Andrew Morton, linux-kernel,
linux-pm, devicetree, linux-usb, linux-arm-kernel,
linux-samsung-soc, RD Babiera, Kyle Tso
In-Reply-To: <20260325-max77759-charger-v9-3-4486dd297adc@google.com>
On Wed, 25 Mar 2026, Amit Sunil Dhamne via B4 Relay wrote:
> From: Amit Sunil Dhamne <amitsd@google.com>
>
> Add register bitmasks for charger function.
> In addition split the charger IRQs further such that each bit represents
> an IRQ downstream of charger regmap irq chip. In addition populate the
> ack_base to offload irq ack to the regmap irq chip framework.
>
> Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
> Reviewed-by: André Draszik <andre.draszik@linaro.org>
> ---
> drivers/mfd/max77759.c | 95 ++++++++++++++++++++++---
> include/linux/mfd/max77759.h | 166 +++++++++++++++++++++++++++++++++++--------
> 2 files changed, 222 insertions(+), 39 deletions(-)
>
[...]
> +/*
> + * enum max77759_chgr_chgin_dtls_status - Charger Input Status
> + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_UNDERVOLTAGE:
> + * Charger input voltage (Vchgin) < Under Voltage Threshold (Vuvlo)
> + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE: Vchgin > Vuvlo and
> + * Vchgin < (Battery Voltage (Vbatt) + system voltage (Vsys))
> + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_OVERVOLTAGE:
> + * Vchgin > Over Voltage threshold (Vovlo)
> + * @MAX77759_CHGR_CHGIN_DTLS_VBUS_VALID:
> + * Vchgin > Vuvlo, Vchgin < Vovlo and Vchgin > (Vsys + Vbatt)
> + */
This comment is masquerading as a kernel-doc header, but isn't actually
kernel-doc. Either change the formatting or adapt the formatting to use
/** and use W=1 to check it.
> +enum max77759_chgr_chgin_dtls_status {
> + MAX77759_CHGR_CHGIN_DTLS_VBUS_UNDERVOLTAGE,
> + MAX77759_CHGR_CHGIN_DTLS_VBUS_MARGINAL_VOLTAGE,
> + MAX77759_CHGR_CHGIN_DTLS_VBUS_OVERVOLTAGE,
> + MAX77759_CHGR_CHGIN_DTLS_VBUS_VALID,
> +};
--
Lee Jones [李琼斯]
^ permalink raw reply
* Re: [PATCH net-next v2 4/4] net: dsa: initial support for MT7628 embedded switch
From: Andrew Lunn @ 2026-03-31 12:30 UTC (permalink / raw)
To: Joris Vaisvila
Cc: netdev, horms, pabeni, kuba, edumazet, davem, olteanv, devicetree,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
In-Reply-To: <20260330184017.766200-5-joey@tinyisr.com>
On Mon, Mar 30, 2026 at 09:40:17PM +0300, Joris Vaisvila wrote:
> Add support for the MT7628 embedded switch.
>
> The switch has 5 built-in 100Mbps user ports (ports 0-4) and one 1Gbps
> port that is internally attached to the SoCs CPU MAC and serves as the
> CPU port.
>
> The switch hardware has a very limited 16 entry VLAN table. Configuring
> VLANs is the only way to control switch forwarding. Currently 6 entries
> are used by tag_8021q to isolate the ports. Double tag feature is
> enabled to force the switch to append the VLAN tag even if the incoming
> packet is already tagged, this simulates VLAN-unaware functionality and
> simplifies the tagger implementation.
>
> Signed-off-by: Joris Vaisvila <joey@tinyisr.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH net-next v2 3/4] net: dsa: initial MT7628 tagging driver
From: Andrew Lunn @ 2026-03-31 12:23 UTC (permalink / raw)
To: Joris Vaisvila
Cc: netdev, horms, pabeni, kuba, edumazet, davem, olteanv, devicetree,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
In-Reply-To: <20260330184017.766200-4-joey@tinyisr.com>
On Mon, Mar 30, 2026 at 09:40:16PM +0300, Joris Vaisvila wrote:
> Add support for the MT7628 embedded switch's tag.
>
> The MT7628 tag is merged with the VLAN TPID field when a VLAN is
> appended by the switch hardware. It is not installed if the VLAN tag is
> already there on ingress. Due to this hardware quirk the tag cannot be
> trusted for port 0 if we don't know that the VLAN was added by the
> hardware. As a workaround for this the switch is configured to always
> append the port PVID tag even if the incoming packet is already tagged.
> The tagging driver can then trust that the tag is always accurate and
> the whole VLAN tag can be removed on ingress as it's only metadata for
> the tagger.
>
> On egress the MT7628 tag allows precise TX, but the correct VLAN tag
> from tag_8021q is still appended or the switch will not forward the
> packet.
>
> Signed-off-by: Joris Vaisvila <joey@tinyisr.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply
* Re: [PATCH] arm64: dts: ti: k3-j721e-main: Update delay select values for MMC1/2 subsystems
From: Moteen Shah @ 2026-03-31 12:19 UTC (permalink / raw)
To: Romain Naour, devicetree, linux-arm-kernel, linux-omap
Cc: conor+dt, krzk+dt, robh, kristo, vigneshr, nm, stable
In-Reply-To: <20260218203823.1825554-1-romain.naour@smile.fr>
Hey Romain,
Thanks for the patch
On 19/02/26 02:08, Romain Naour wrote:
> The previous SPRSP36J datasheet recommends to set ti,otap-del-sel-sd-hs
> value to 0 for MMC1 and MMC2 interfaces. These values were updated in
> kernel 6.5. As a result we have some occasional regression with ultra
> high speed DDR50 SDXC cards while mounting the rootfs:
This error shouldn't be limited to just DDR50, were you seeing similar
behavior with other speed modes?
>
> mmc1: error -110 whilst initialising SD card
>
> A similar issue may occur with u-boot after a reboot while
> initialising the SD card:
>
> mmc_init: -110, time 67
>
> Update the delay values for legacy and high speed modes, based on
> the latest revised datasheet SPRSP36K released in April 2024 [1].
>
> (MMC1/2 - SD/SDIO Interface): Updated/Changed the
> "OTAPDLYENA, DELAY ENABLE" and "OTAPDLYSEL, DELAY VALUE" for the
> Default Speed and High Speed modes from "0x0" to "0x1"
>
> [1] Table 6-86. MMC1/2 DLL Delay Mapping for All Timing Modes, in
> https://www.ti.com/lit/ds/symlink/tda4vm.pdf,
> (SPRSP36K – SEPTEMBER 2021 – REVISED APRIL 2024)
>
> Cc: stable@vger.kernel.org # 6.5+
> Fixes: af398252d68e ("arm64: dts: ti: k3-j721e-main: Update delay select values for MMC subsystems")
> Signed-off-by: Romain Naour <romain.naour@smile.fr>
> ---
> arch/arm64/boot/dts/ti/k3-j721e-main.dtsi | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
> index d5fd30a01032..418e6010ef1f 100644
> --- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
> +++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
> @@ -1643,8 +1643,8 @@ main_sdhci1: mmc@4fb0000 {
> clocks = <&k3_clks 92 5>, <&k3_clks 92 0>;
> assigned-clocks = <&k3_clks 92 0>;
> assigned-clock-parents = <&k3_clks 92 1>;
> - ti,otap-del-sel-legacy = <0x0>;
> - ti,otap-del-sel-sd-hs = <0x0>;
> + ti,otap-del-sel-legacy = <0x1>;
> + ti,otap-del-sel-sd-hs = <0x1>;
> ti,otap-del-sel-sdr12 = <0xf>;
> ti,otap-del-sel-sdr25 = <0xf>;
> ti,otap-del-sel-sdr50 = <0xc>;
> @@ -1671,8 +1671,8 @@ main_sdhci2: mmc@4f98000 {
> clocks = <&k3_clks 93 5>, <&k3_clks 93 0>;
> assigned-clocks = <&k3_clks 93 0>;
> assigned-clock-parents = <&k3_clks 93 1>;
> - ti,otap-del-sel-legacy = <0x0>;
> - ti,otap-del-sel-sd-hs = <0x0>;
> + ti,otap-del-sel-legacy = <0x1>;
> + ti,otap-del-sel-sd-hs = <0x1>;
> ti,otap-del-sel-sdr12 = <0xf>;
> ti,otap-del-sel-sdr25 = <0xf>;
> ti,otap-del-sel-sdr50 = <0xc>;
Reviewed-by: Moteen Shah <m-shah@ti.com>
Regards,
Moteen
^ permalink raw reply
* Re: [PATCH 3/3] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC
From: Bartosz Golaszewski @ 2026-03-31 12:15 UTC (permalink / raw)
To: Yu-Chun Lin
Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, cy.huang, stanley_chang, james.tai, linusw,
brgl, robh, krzk+dt, conor+dt, afaerber, tychang
In-Reply-To: <20260331113835.3510341-4-eleanor.lin@realtek.com>
On Tue, 31 Mar 2026 13:38:35 +0200, Yu-Chun Lin <eleanor.lin@realtek.com> said:
> From: Tzuyi Chang <tychang@realtek.com>
>
> Add support for the GPIO controller found on Realtek DHC RTD1625 SoCs.
>
> Unlike the existing Realtek GPIO driver (drivers/gpio/gpio-rtd.c),
> which manages pins via shared bank registers, the RTD1625 introduces
> a per-pin register architecture. Each GPIO line now has its own
> dedicated 32-bit control register to manage configuration independently,
> including direction, output value, input value, interrupt enable, and
> debounce. Therefore, this distinct hardware design requires a separate
> driver.
>
> Signed-off-by: Tzuyi Chang <tychang@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> drivers/gpio/Kconfig | 12 +
> drivers/gpio/Makefile | 1 +
> drivers/gpio/gpio-rtd1625.c | 581 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 594 insertions(+)
> create mode 100644 drivers/gpio/gpio-rtd1625.c
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index b45fb799e36c..6ffc95e02cb9 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -639,6 +639,18 @@ config GPIO_RTD
> Say yes here to support GPIO functionality and GPIO interrupt on
> Realtek DHC SoCs.
>
> +config GPIO_RTD1625
> + tristate "Realtek DHC RTD1625 GPIO support"
> + depends on ARCH_REALTEK || COMPILE_TEST
> + default y
Don't default to y for COMPILE_TEST. If you need this for ARCH_REALTEK then
limit it to it. Though seeing as it's a module_initcall() anyway, maybe you
don't need it at all?
> + select GPIOLIB_IRQCHIP
> + help
> + This option enables support for the GPIO controller on Realtek
> + DHC (Digital Home Center) RTD1625 SoC.
> +
> + Say yes here to support both basic GPIO line functionality
> + and GPIO interrupt handling capabilities for this platform.
> +
Other than that looks really nice!
Bart
^ permalink raw reply
* [PATCH v2] ARM: dts: aspeed: yosemite5: Add MP5998 power monitor
From: Daniel Hsu @ 2026-03-31 12:07 UTC (permalink / raw)
To: andrew
Cc: robh, krzk+dt, conor+dt, joel, devicetree, linux-arm-kernel,
linux-aspeed, linux-kernel, Daniel Hsu
Add an MP5998 power monitor used to monitor the power consumption
of the Paddle_P12V_HSC rail on the Yosemite5 paddle board.
[v2]
- Describe the purpose of the power monitor
- Remove software/driver related description
Signed-off-by: Daniel Hsu <Daniel-Hsu@quantatw.com>
---
arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite5.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite5.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite5.dts
index 2486981f3d6b..6287f80d70d9 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite5.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-yosemite5.dts
@@ -422,6 +422,11 @@ power-sensor@45 {
shunt-resistor = <1000>;
};
+ power-monitor@46 {
+ compatible = "mps,mp5998";
+ reg = <0x46>;
+ };
+
power-monitor@47 {
compatible = "ti,tps25990";
reg = <0x47>;
--
2.53.0
^ permalink raw reply related
* [PATCH v6 4/4] i2c: qcom-geni: Support multi-owner controllers in GPI mode
From: Mukesh Kumar Savaliya @ 2026-03-31 11:47 UTC (permalink / raw)
To: viken.dadhaniya, andi.shyti, robh, krzk+dt, conor+dt, vkoul,
Frank.Li, andersson, konradybcio, dmitry.baryshkov, linmq006,
quic_jseerapu, agross, linux-arm-msm, linux-i2c, devicetree,
linux-kernel, dmaengine
Cc: krzysztof.kozlowski, bartosz.golaszewski, bjorn.andersson,
konrad.dybcio, Mukesh Kumar Savaliya
In-Reply-To: <20260331114742.2896317-1-mukesh.savaliya@oss.qualcomm.com>
Some platforms use a QUP-based I2C controller in a configuration where the
controller is shared with another system processor. In this setup the
operating system must not assume exclusive ownership of the controller or
its associated pins.
Add support for enabling multi-owner operation when DeviceTree specifies
qcom,qup-multi-owner. When enabled, mark the underlying serial engine as
shared so the common GENI resource handling avoids selecting the "sleep"
pinctrl state, which could disrupt transfers initiated by the other
processor.
For GPI mode transfers, request lock/unlock TRE sequencing from the GPI
driver by setting a single lock_action selector per message, emitting lock
before the first message and unlock after the last message (handling the
single-message case as well). This serializes access to the shared
controller without requiring message-position flags to be passed into the
DMA engine layer.
Signed-off-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
---
drivers/i2c/busses/i2c-qcom-geni.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index ae609bdd2ec4..1925e4ec9842 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -815,6 +815,14 @@ static int geni_i2c_gpi_xfer(struct geni_i2c_dev *gi2c, struct i2c_msg msgs[], i
if (i < num - 1)
peripheral.stretch = 1;
+ peripheral.lock_action = GPI_LOCK_NONE;
+ if (gi2c->se.multi_owner) {
+ if (i == 0)
+ peripheral.lock_action = GPI_LOCK_ACQUIRE;
+ else if (i == num - 1)
+ peripheral.lock_action = GPI_LOCK_RELEASE;
+ }
+
peripheral.addr = msgs[i].addr;
if (i > 0 && (!(msgs[i].flags & I2C_M_RD)))
peripheral.multi_msg = false;
@@ -1014,6 +1022,17 @@ static int geni_i2c_probe(struct platform_device *pdev)
gi2c->clk_freq_out = I2C_MAX_STANDARD_MODE_FREQ;
}
+ if (of_property_read_bool(pdev->dev.of_node, "qcom,qup-multi-owner")) {
+ /*
+ * Multi-owner controller configuration: the controller may be
+ * used by another system processor. Mark the SE as shared so
+ * common GENI resource handling can avoid pin state changes
+ * that would disrupt the other user.
+ */
+ gi2c->se.multi_owner = true;
+ dev_dbg(&pdev->dev, "I2C controller is shared with another system processor\n");
+ }
+
if (has_acpi_companion(dev))
ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(dev));
@@ -1089,7 +1108,9 @@ static int geni_i2c_probe(struct platform_device *pdev)
}
if (fifo_disable) {
- /* FIFO is disabled, so we can only use GPI DMA */
+ /* FIFO is disabled, so we can only use GPI DMA.
+ * SE can be shared in GSI mode between subsystems, each SS owns a GPII.
+ */
gi2c->gpi_mode = true;
ret = setup_gpi_dma(gi2c);
if (ret)
@@ -1098,6 +1119,10 @@ static int geni_i2c_probe(struct platform_device *pdev)
dev_dbg(dev, "Using GPI DMA mode for I2C\n");
} else {
gi2c->gpi_mode = false;
+
+ if (gi2c->se.multi_owner)
+ dev_err_probe(dev, -EINVAL, "I2C sharing not supported in non GSI mode\n");
+
tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se);
/* I2C Master Hub Serial Elements doesn't have the HW_PARAM_0 register */
--
2.25.1
^ permalink raw reply related
* [PATCH v6 3/4] soc: qcom: geni-se: Keep pinctrl active for multi-owner controllers
From: Mukesh Kumar Savaliya @ 2026-03-31 11:47 UTC (permalink / raw)
To: viken.dadhaniya, andi.shyti, robh, krzk+dt, conor+dt, vkoul,
Frank.Li, andersson, konradybcio, dmitry.baryshkov, linmq006,
quic_jseerapu, agross, linux-arm-msm, linux-i2c, devicetree,
linux-kernel, dmaengine
Cc: krzysztof.kozlowski, bartosz.golaszewski, bjorn.andersson,
konrad.dybcio, Mukesh Kumar Savaliya
In-Reply-To: <20260331114742.2896317-1-mukesh.savaliya@oss.qualcomm.com>
On platforms where a GENI Serial Engine is shared with another system
processor, selecting the "sleep" pinctrl state can disrupt ongoing
transfers initiated by the other processor.
Teach geni_se_resources_off() to skip selecting the pinctrl sleep state
when the Serial Engine is marked as shared, while still allowing the
rest of the resource shutdown sequence to proceed.
This is required for multi-owner configurations (described via DeviceTree
with qcom,qup-multi-owner on the protocol controller node).
Signed-off-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
---
drivers/soc/qcom/qcom-geni-se.c | 15 +++++++++++----
include/linux/soc/qcom/geni-se.h | 2 ++
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index cd1779b6a91a..1a60832ace16 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -597,10 +597,17 @@ int geni_se_resources_off(struct geni_se *se)
if (has_acpi_companion(se->dev))
return 0;
-
- ret = pinctrl_pm_select_sleep_state(se->dev);
- if (ret)
- return ret;
+ /*
+ * Select the "sleep" pinctrl state only when the serial engine is
+ * exclusively owned by this system processor. For shared controller
+ * configurations, another system processor may still be using the pins,
+ * and switching them to "sleep" can disrupt ongoing transfers.
+ */
+ if (!se->multi_owner) {
+ ret = pinctrl_pm_select_sleep_state(se->dev);
+ if (ret)
+ return ret;
+ }
geni_se_clks_off(se);
return 0;
diff --git a/include/linux/soc/qcom/geni-se.h b/include/linux/soc/qcom/geni-se.h
index 0a984e2579fe..326744e311ce 100644
--- a/include/linux/soc/qcom/geni-se.h
+++ b/include/linux/soc/qcom/geni-se.h
@@ -63,6 +63,7 @@ struct geni_icc_path {
* @num_clk_levels: Number of valid clock levels in clk_perf_tbl
* @clk_perf_tbl: Table of clock frequency input to serial engine clock
* @icc_paths: Array of ICC paths for SE
+ * @multi_owner: True if SE is shared between multiprocessors.
*/
struct geni_se {
void __iomem *base;
@@ -72,6 +73,7 @@ struct geni_se {
unsigned int num_clk_levels;
unsigned long *clk_perf_tbl;
struct geni_icc_path icc_paths[3];
+ bool multi_owner;
};
/* Common SE registers */
--
2.25.1
^ permalink raw reply related
* [PATCH v6 2/4] dmaengine: qcom: gpi: Add lock/unlock TREs for multi-owner I2C transfers
From: Mukesh Kumar Savaliya @ 2026-03-31 11:47 UTC (permalink / raw)
To: viken.dadhaniya, andi.shyti, robh, krzk+dt, conor+dt, vkoul,
Frank.Li, andersson, konradybcio, dmitry.baryshkov, linmq006,
quic_jseerapu, agross, linux-arm-msm, linux-i2c, devicetree,
linux-kernel, dmaengine
Cc: krzysztof.kozlowski, bartosz.golaszewski, bjorn.andersson,
konrad.dybcio, Mukesh Kumar Savaliya
In-Reply-To: <20260331114742.2896317-1-mukesh.savaliya@oss.qualcomm.com>
Some platforms use a QUP-based I2C controller in a configuration where the
controller is shared with another system processor (described in DT using
qcom,qup-multi-owner). In such setups, GPI hardware lock/unlock TREs can be
used to serialize access to the controller.
Add support to emit lock and unlock TREs around I2C transfers and increase
the maximum TRE count to account for the additional elements.
Also simplify the client interface by replacing multiple boolean fields
(shared flag and message position tracking) with a single lock_action
selector (acquire/release/none), as the GPI driver only needs to know
whether to emit lock/unlock TREs for a given transfer.
Signed-off-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
---
drivers/dma/qcom/gpi.c | 44 +++++++++++++++++++++++++++++++-
include/linux/dma/qcom-gpi-dma.h | 18 +++++++++++++
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c
index 6e30f3aa401e..a1f391dd1747 100644
--- a/drivers/dma/qcom/gpi.c
+++ b/drivers/dma/qcom/gpi.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2020, Linaro Limited
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <dt-bindings/dma/qcom-gpi.h>
@@ -67,6 +68,14 @@
#define TRE_DMA_LEN GENMASK(23, 0)
#define TRE_DMA_IMMEDIATE_LEN GENMASK(3, 0)
+/* Lock TRE */
+#define TRE_LOCK BIT(0)
+#define TRE_MINOR_TYPE GENMASK(19, 16)
+#define TRE_MAJOR_TYPE GENMASK(23, 20)
+
+/* Unlock TRE */
+#define TRE_UNLOCK BIT(8)
+
/* Register offsets from gpi-top */
#define GPII_n_CH_k_CNTXT_0_OFFS(n, k) (0x20000 + (0x4000 * (n)) + (0x80 * (k)))
#define GPII_n_CH_k_CNTXT_0_EL_SIZE GENMASK(31, 24)
@@ -518,7 +527,7 @@ struct gpii {
bool ieob_set;
};
-#define MAX_TRE 3
+#define MAX_TRE 5
struct gpi_desc {
struct virt_dma_desc vd;
@@ -1625,12 +1634,27 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc,
unsigned long flags)
{
struct gpi_i2c_config *i2c = chan->config;
+ enum gpi_lock_action lock_action = i2c->lock_action;
struct device *dev = chan->gpii->gpi_dev->dev;
unsigned int tre_idx = 0;
dma_addr_t address;
struct gpi_tre *tre;
unsigned int i;
+ /* Optional lock TRE before transfer */
+ if (lock_action == GPI_LOCK_ACQUIRE) {
+ tre = &desc->tre[tre_idx];
+ tre_idx++;
+
+ tre->dword[0] = 0;
+ tre->dword[1] = 0;
+ tre->dword[2] = 0;
+ tre->dword[3] = u32_encode_bits(1, TRE_LOCK);
+ tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB);
+ tre->dword[3] |= u32_encode_bits(0, TRE_MINOR_TYPE);
+ tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE);
+ }
+
/* first create config tre if applicable */
if (i2c->set_config) {
tre = &desc->tre[tre_idx];
@@ -1690,6 +1714,24 @@ static int gpi_create_i2c_tre(struct gchan *chan, struct gpi_desc *desc,
if (!(flags & DMA_PREP_INTERRUPT))
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_BEI);
+
+ /* If multi-owner and this is the release boundary, chain it */
+ if (i2c->lock_action == GPI_LOCK_RELEASE)
+ tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_CHAIN);
+ }
+
+ /* Optional unlock TRE after transfer */
+ if (lock_action == GPI_LOCK_RELEASE && i2c->op != I2C_READ) {
+ tre = &desc->tre[tre_idx];
+ tre_idx++;
+
+ tre->dword[0] = 0;
+ tre->dword[1] = 0;
+ tre->dword[2] = 0;
+ tre->dword[3] = u32_encode_bits(1, TRE_UNLOCK);
+ tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOB);
+ tre->dword[3] |= u32_encode_bits(1, TRE_MINOR_TYPE);
+ tre->dword[3] |= u32_encode_bits(3, TRE_MAJOR_TYPE);
}
for (i = 0; i < tre_idx; i++)
diff --git a/include/linux/dma/qcom-gpi-dma.h b/include/linux/dma/qcom-gpi-dma.h
index 6680dd1a43c6..36cbb85499b4 100644
--- a/include/linux/dma/qcom-gpi-dma.h
+++ b/include/linux/dma/qcom-gpi-dma.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2020, Linaro Limited
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOM_GPI_DMA_H
@@ -51,6 +52,21 @@ enum i2c_op {
I2C_READ,
};
+/**
+ * enum gpi_lock_action - request lock/unlock TRE sequencing
+ * @GPI_LOCK_NONE: No lock/unlock TRE requested for this transfer
+ * @GPI_LOCK_ACQUIRE: Emit a lock TRE before the transfer
+ * @GPI_LOCK_RELEASE: Emit an unlock TRE after the transfer
+ *
+ * Used by protocol drivers for multi-owner controller setups (e.g. when
+ * DeviceTree indicates the controller is shared via qcom,qup-multi-owner).
+ */
+enum gpi_lock_action {
+ GPI_LOCK_NONE = 0,
+ GPI_LOCK_ACQUIRE,
+ GPI_LOCK_RELEASE,
+};
+
/**
* struct gpi_i2c_config - i2c config for peripheral
*
@@ -65,6 +81,7 @@ enum i2c_op {
* @rx_len: receive length for buffer
* @op: i2c cmd
* @muli-msg: is part of multi i2c r-w msgs
+ * @lock_action: request lock/unlock TRE sequencing for this transfer
*/
struct gpi_i2c_config {
u8 set_config;
@@ -78,6 +95,7 @@ struct gpi_i2c_config {
u32 rx_len;
enum i2c_op op;
bool multi_msg;
+ enum gpi_lock_action lock_action;
};
#endif /* QCOM_GPI_DMA_H */
--
2.25.1
^ permalink raw reply related
* [PATCH v6 1/4] dt-bindings: i2c: qcom,i2c-geni: Document multi-owner controller support
From: Mukesh Kumar Savaliya @ 2026-03-31 11:47 UTC (permalink / raw)
To: viken.dadhaniya, andi.shyti, robh, krzk+dt, conor+dt, vkoul,
Frank.Li, andersson, konradybcio, dmitry.baryshkov, linmq006,
quic_jseerapu, agross, linux-arm-msm, linux-i2c, devicetree,
linux-kernel, dmaengine
Cc: krzysztof.kozlowski, bartosz.golaszewski, bjorn.andersson,
konrad.dybcio, Mukesh Kumar Savaliya
In-Reply-To: <20260331114742.2896317-1-mukesh.savaliya@oss.qualcomm.com>
Document a DeviceTree property to describe QUP-based I2C controllers that
are shared with one or more other system processors.
On some Qualcomm platforms, a QUP-based I2C controller may be accessed by
multiple system processors (for example, APPS and DSP). In such
configurations, the operating system must not assume exclusive ownership
of the controller or its associated hardware resources.
The new qcom,qup-multi-owner property indicates that the controller is
externally shared and that the operating system must avoid operations
which rely on sole control of the hardware.
Signed-off-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
---
.../devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml
index 51534953a69c..9401dc2d5052 100644
--- a/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml
+++ b/Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml
@@ -60,6 +60,13 @@ properties:
power-domains:
maxItems: 1
+ qcom,qup-multi-owner:
+ type: boolean
+ description:
+ Indicates that the QUP-based controller is shared with one or more
+ other system processors and must not be assumed to have exclusive
+ ownership by the operating system.
+
reg:
maxItems: 1
--
2.25.1
^ permalink raw reply related
* [PATCH v6 0/4] Enable multi-owner I2C support for QCOM GENI controllers
From: Mukesh Kumar Savaliya @ 2026-03-31 11:47 UTC (permalink / raw)
To: viken.dadhaniya, andi.shyti, robh, krzk+dt, conor+dt, vkoul,
Frank.Li, andersson, konradybcio, dmitry.baryshkov, linmq006,
quic_jseerapu, agross, linux-arm-msm, linux-i2c, devicetree,
linux-kernel, dmaengine
Cc: krzysztof.kozlowski, bartosz.golaszewski, bjorn.andersson,
konrad.dybcio, Mukesh Kumar Savaliya
The QUP-based GENI I2C controller driver currently assumes exclusive
ownership of the controller by a single system processor. This prevents
safe use of a single I2C controller by multiple system processors
(e.g. APPS and a DSP) running the same or different operating systems.
One practical example is an EEPROM connected to an I2C controller that
needs to be accessed independently by firmware running on a DSP and by
Linux running on the application processor, without causing bus-level
interference during transfers.
This series adds support for operating a QUP GENI I2C Serial Engine in a
multi-owner configuration. Each system processor uses its own dedicated
GPI instance (GPII) as the data path between the Serial Engine and the
GSI DMA engine. As a result, controller sharing is supported only when
the I2C controller operates in GPI mode; FIFO/CPU DMA modes are not
supported for this configuration.
To serialize access at the hardware level, the GPI DMA engine is used to
emit lock and unlock Transfer Ring Elements (TREs) around I2C transfers.
The lock is acquired before the first transfer and released after the
last transfer, ensuring uninterrupted access to the controller while a
processor owns it.
In addition, when a controller is shared, the GENI common layer avoids
placing the associated GPIOs into the pinctrl "sleep" state during
runtime suspend. This prevents disruption of transfers that may still
be in progress on another system processor using the same controller
pins.
The multi-owner behavior is enabled via a DeviceTree property,
`qcom,qup-multi-owner`, on the I2C controller node. This property must be
used only when the hardware configuration requires controller sharing
and when GPI mode is enabled.
Patch overview:
1. Document the `qcom,qup-multi-owner` DeviceTree property for GENI I2C.
2. Extend the QCOM GPI DMA driver to support lock and unlock TREs with a
simplified single-field API.
3. Update the GENI common layer to keep pinctrl active for shared
controllers during runtime suspend.
4. Enable multi-owner operation in the GENI I2C driver using the new
DeviceTree property and GPI lock/unlock support.
Signed-off-by: Mukesh Kumar Savaliya <mukesh.savaliya@oss.qualcomm.com>
---
Link to V5 : https://lore.kernel.org/lkml/20241129144357.2008465-2-mukesh.savaliya@oss.qualcomm.com/
Changes in V6:
- Addressed review feedback from Krzysztof Kozlowski and other reviewers, primarily
around clarifying the feature semantics and improving the DeviceTree flag naming.
- Renamed the DeviceTree property from qcom,shared-se to qcom,qup-multi-owner to
better describe the multi-owner controller use case.
- Updated the cover letter to clearly describe the multi-owner I2C design, the
GPI-only limitation, and the role of the new qcom,qup-multi-owner flag.
- Updated the DeviceTree binding documentation to reflect the new qcom,qup-multi-owner
property and refined its description for clarity and correctness.
- [Patch 2/4] Simplify the GPI I2C interface by replacing multiple shared SE related
state flags with a single internal lock/unlock control managed entirely in the GPI
driver - Suggested by Vinod Koul.
- [Patch 3/4] Updated the GENI common layer to avoid selecting the pinctrl “sleep”
state for multi-owner controllers, preventing disruption of transfers initiated by
another system processor during runtime suspend.
- [Patch 4/4] Updated the GENI I2C driver to:
- Detect the qcom,qup-multi-owner DeviceTree property.
- Mark the underlying serial engine as shared.
- Request GPI lock and unlock TRE sequencing around I2C transfers using the
simplified single field API.
- Clarified commit messages across all patches to avoid ambiguous terminology
(such as “subsystem”), expand abbreviations, and better explain functional
requirements rather than optimizations.
- Updated copyright headers across all files wherever applicable.
- Renamed variable shared_geni_se to multi_owner to match the DT property naming.
- Changed dev_err(print_log) during probe() to dev_err_probe().
---
Mukesh Kumar Savaliya (4):
dt-bindings: i2c: qcom,i2c-geni: Document multi-owner controller
support
dmaengine: qcom: gpi: Add lock/unlock TREs for multi-owner I2C
transfers
soc: qcom: geni-se: Keep pinctrl active for multi-owner controllers
i2c: qcom-geni: Support multi-owner controllers in GPI mode
.../bindings/i2c/qcom,i2c-geni-qcom.yaml | 7 +++
drivers/dma/qcom/gpi.c | 44 ++++++++++++++++++-
drivers/i2c/busses/i2c-qcom-geni.c | 27 +++++++++++-
drivers/soc/qcom/qcom-geni-se.c | 15 +++++--
include/linux/dma/qcom-gpi-dma.h | 18 ++++++++
include/linux/soc/qcom/geni-se.h | 2 +
6 files changed, 107 insertions(+), 6 deletions(-)
--
2.25.1
^ permalink raw reply
* [PATCH 1/3] dt-bindings: gpio: realtek: Add realtek,rtd1625-gpio
From: Yu-Chun Lin @ 2026-03-31 11:38 UTC (permalink / raw)
To: linusw, brgl, robh, krzk+dt, conor+dt, afaerber, tychang
Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, cy.huang, stanley_chang, eleanor.lin,
james.tai
In-Reply-To: <20260331113835.3510341-1-eleanor.lin@realtek.com>
From: Tzuyi Chang <tychang@realtek.com>
Add the device tree bindings for the Realtek DHC (Digital Home Center)
RTD1625 GPIO controllers.
The RTD1625 GPIO controller features a per-pin register architecture
that differs significantly from previous generations. It utilizes
separate register blocks for GPIO configuration and interrupt control.
Signed-off-by: Tzuyi Chang <tychang@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
.../bindings/gpio/realtek,rtd1625-gpio.yaml | 74 +++++++++++++++++++
1 file changed, 74 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml
diff --git a/Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml b/Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml
new file mode 100644
index 000000000000..e81d13dfefc2
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/realtek,rtd1625-gpio.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2023 Realtek Semiconductor Corporation
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/realtek,rtd1625-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Realtek DHC RTD1625 GPIO controller
+
+maintainers:
+ - Tzuyi Chang <tychang@realtek.com>
+
+description: |
+ GPIO controller for the Realtek RTD1625 SoC, featuring a per-pin register
+ architecture that differs significantly from earlier RTD series controllers.
+ Each GPIO has dedicated registers for configuration (direction, input/output
+ values, debounce), and interrupt control supporting edge and level detection
+ modes.
+
+properties:
+ compatible:
+ enum:
+ - realtek,rtd1625-iso-gpio
+ - realtek,rtd1625-isom-gpio
+
+ reg:
+ items:
+ - description: GPIO controller registers
+ - description: GPIO interrupt registers
+
+ interrupts:
+ items:
+ - description: Interrupt number of the assert GPIO interrupt, which is
+ triggered when there is a rising edge.
+ - description: Interrupt number of the deassert GPIO interrupt, which is
+ triggered when there is a falling edge.
+ - description: Interrupt number of the level-sensitive GPIO interrupt,
+ triggered by a configured logic level.
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+ gpio-ranges: true
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - gpio-ranges
+ - gpio-controller
+ - "#gpio-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ gpio@89120 {
+ compatible = "realtek,rtd1625-isom-gpio";
+ reg = <0x89120 0x10>,
+ <0x89100 0x20>;
+ interrupt-parent = <&iso_m_irq_mux>;
+ interrupts = <0>, <1>, <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&isom_pinctrl 0 0 4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
--
2.34.1
^ permalink raw reply related
* [PATCH 3/3] gpio: realtek: Add driver for Realtek DHC RTD1625 SoC
From: Yu-Chun Lin @ 2026-03-31 11:38 UTC (permalink / raw)
To: linusw, brgl, robh, krzk+dt, conor+dt, afaerber, tychang
Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-realtek-soc, cy.huang, stanley_chang, eleanor.lin,
james.tai
In-Reply-To: <20260331113835.3510341-1-eleanor.lin@realtek.com>
From: Tzuyi Chang <tychang@realtek.com>
Add support for the GPIO controller found on Realtek DHC RTD1625 SoCs.
Unlike the existing Realtek GPIO driver (drivers/gpio/gpio-rtd.c),
which manages pins via shared bank registers, the RTD1625 introduces
a per-pin register architecture. Each GPIO line now has its own
dedicated 32-bit control register to manage configuration independently,
including direction, output value, input value, interrupt enable, and
debounce. Therefore, this distinct hardware design requires a separate
driver.
Signed-off-by: Tzuyi Chang <tychang@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
---
drivers/gpio/Kconfig | 12 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-rtd1625.c | 581 ++++++++++++++++++++++++++++++++++++
3 files changed, 594 insertions(+)
create mode 100644 drivers/gpio/gpio-rtd1625.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b45fb799e36c..6ffc95e02cb9 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -639,6 +639,18 @@ config GPIO_RTD
Say yes here to support GPIO functionality and GPIO interrupt on
Realtek DHC SoCs.
+config GPIO_RTD1625
+ tristate "Realtek DHC RTD1625 GPIO support"
+ depends on ARCH_REALTEK || COMPILE_TEST
+ default y
+ select GPIOLIB_IRQCHIP
+ help
+ This option enables support for the GPIO controller on Realtek
+ DHC (Digital Home Center) RTD1625 SoC.
+
+ Say yes here to support both basic GPIO line functionality
+ and GPIO interrupt handling capabilities for this platform.
+
config GPIO_SAMA5D2_PIOBU
tristate "SAMA5D2 PIOBU GPIO support"
depends on MFD_SYSCON
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index c05f7d795c43..c95ba218d53a 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -159,6 +159,7 @@ obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
obj-$(CONFIG_GPIO_REG) += gpio-reg.o
obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o
obj-$(CONFIG_GPIO_RTD) += gpio-rtd.o
+obj-$(CONFIG_GPIO_RTD1625) += gpio-rtd1625.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
diff --git a/drivers/gpio/gpio-rtd1625.c b/drivers/gpio/gpio-rtd1625.c
new file mode 100644
index 000000000000..10559a892c06
--- /dev/null
+++ b/drivers/gpio/gpio-rtd1625.c
@@ -0,0 +1,581 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Realtek DHC RTD1625 gpio driver
+ *
+ * Copyright (c) 2023 Realtek Semiconductor Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define RTD1625_GPIO_DIR BIT(0)
+#define RTD1625_GPIO_OUT BIT(2)
+#define RTD1625_GPIO_IN BIT(4)
+#define RTD1625_GPIO_EDGE_INT_DP BIT(6)
+#define RTD1625_GPIO_EDGE_INT_EN BIT(8)
+#define RTD1625_GPIO_LEVEL_INT_EN BIT(16)
+#define RTD1625_GPIO_LEVEL_INT_DP BIT(18)
+#define RTD1625_GPIO_DEBOUNCE GENMASK(30, 28)
+#define RTD1625_GPIO_DEBOUNCE_WREN BIT(31)
+
+#define RTD1625_GPIO_WREN(x) ((x) << 1)
+
+/* Write-enable masks for all GPIO configs and reserved hardware bits */
+#define RTD1625_ISO_GPIO_WREN_ALL 0x8000aa8a
+#define RTD1625_ISOM_GPIO_WREN_ALL 0x800aaa8a
+
+#define RTD1625_GPIO_DEBOUNCE_1US 0
+#define RTD1625_GPIO_DEBOUNCE_10US 1
+#define RTD1625_GPIO_DEBOUNCE_100US 2
+#define RTD1625_GPIO_DEBOUNCE_1MS 3
+#define RTD1625_GPIO_DEBOUNCE_10MS 4
+#define RTD1625_GPIO_DEBOUNCE_20MS 5
+#define RTD1625_GPIO_DEBOUNCE_30MS 6
+#define RTD1625_GPIO_DEBOUNCE_50MS 7
+
+#define GPIO_CONTROL(gpio) ((gpio) * 4)
+
+/**
+ * struct rtd1625_gpio_info - Specific GPIO register information
+ * @num_gpios: The number of GPIOs
+ * @irq_type_support: Supported IRQ types
+ * @gpa_offset: Offset for GPIO assert interrupt status registers
+ * @gpda_offset: Offset for GPIO deassert interrupt status registers
+ * @level_offset: Offset of level interrupt status register
+ * @write_en_all: Write-enable mask for all configurable bits
+ */
+struct rtd1625_gpio_info {
+ unsigned int num_gpios;
+ unsigned int irq_type_support;
+ unsigned int gpa_offset;
+ unsigned int gpda_offset;
+ unsigned int level_offset;
+ unsigned int write_en_all;
+};
+
+struct rtd1625_gpio {
+ struct gpio_chip gpio_chip;
+ const struct rtd1625_gpio_info *info;
+ void __iomem *base;
+ void __iomem *irq_base;
+ unsigned int irqs[3];
+ raw_spinlock_t lock;
+ unsigned int *save_regs;
+};
+
+static unsigned int rtd1625_gpio_gpa_offset(struct rtd1625_gpio *data, unsigned int offset)
+{
+ return data->info->gpa_offset + ((offset / 32) * 4);
+}
+
+static unsigned int rtd1625_gpio_gpda_offset(struct rtd1625_gpio *data, unsigned int offset)
+{
+ return data->info->gpda_offset + ((offset / 32) * 4);
+}
+
+static unsigned int rtd1625_gpio_level_offset(struct rtd1625_gpio *data, unsigned int offset)
+{
+ return data->info->level_offset + ((offset / 32) * 4);
+}
+
+static unsigned int rtd1625_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
+ unsigned int debounce)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u8 deb_val;
+ u32 val;
+
+ switch (debounce) {
+ case 1:
+ deb_val = RTD1625_GPIO_DEBOUNCE_1US;
+ break;
+ case 10:
+ deb_val = RTD1625_GPIO_DEBOUNCE_10US;
+ break;
+ case 100:
+ deb_val = RTD1625_GPIO_DEBOUNCE_100US;
+ break;
+ case 1000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_1MS;
+ break;
+ case 10000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_10MS;
+ break;
+ case 20000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_20MS;
+ break;
+ case 30000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_30MS;
+ break;
+ case 50000:
+ deb_val = RTD1625_GPIO_DEBOUNCE_50MS;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ val = FIELD_PREP(RTD1625_GPIO_DEBOUNCE, deb_val) | RTD1625_GPIO_DEBOUNCE_WREN;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ writel_relaxed(val, data->base + GPIO_CONTROL(offset));
+
+ return 0;
+}
+
+static int rtd1625_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
+{
+ int debounce;
+
+ if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) {
+ debounce = pinconf_to_config_argument(config);
+ return rtd1625_gpio_set_debounce(chip, offset, debounce);
+ }
+
+ return gpiochip_generic_config(chip, offset, config);
+}
+
+static int rtd1625_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_OUT);
+
+ if (value)
+ val |= RTD1625_GPIO_OUT;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ writel_relaxed(val, data->base + GPIO_CONTROL(offset));
+
+ return 0;
+}
+
+static int rtd1625_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ val = readl_relaxed(data->base + GPIO_CONTROL(offset));
+
+ if (val & RTD1625_GPIO_DIR)
+ return !!(val & RTD1625_GPIO_OUT);
+ else
+ return !!(val & RTD1625_GPIO_IN);
+}
+
+static int rtd1625_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ val = readl_relaxed(data->base + GPIO_CONTROL(offset));
+
+ if (val & RTD1625_GPIO_DIR)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
+static int rtd1625_gpio_set_direction(struct gpio_chip *chip, unsigned int offset, bool out)
+{
+ struct rtd1625_gpio *data = gpiochip_get_data(chip);
+ u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_DIR);
+
+ if (out)
+ val |= RTD1625_GPIO_DIR;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ writel_relaxed(val, data->base + GPIO_CONTROL(offset));
+
+ return 0;
+}
+
+static int rtd1625_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+ return rtd1625_gpio_set_direction(chip, offset, false);
+}
+
+static int rtd1625_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ rtd1625_gpio_set(chip, offset, value);
+
+ return rtd1625_gpio_set_direction(chip, offset, true);
+}
+
+static void rtd1625_gpio_irq_handle(struct irq_desc *desc)
+{
+ unsigned int (*get_reg_offset)(struct rtd1625_gpio *gpio, unsigned int offset);
+ struct rtd1625_gpio *data = irq_desc_get_handler_data(desc);
+ struct irq_domain *domain = data->gpio_chip.irq.domain;
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned int irq = irq_desc_get_irq(desc);
+ unsigned long status;
+ unsigned int reg_offset, i, j;
+ unsigned int girq;
+ irq_hw_number_t hwirq;
+ u32 irq_type;
+
+ if (irq == data->irqs[0])
+ get_reg_offset = &rtd1625_gpio_gpa_offset;
+ else if (irq == data->irqs[1])
+ get_reg_offset = &rtd1625_gpio_gpda_offset;
+ else if (irq == data->irqs[2])
+ get_reg_offset = &rtd1625_gpio_level_offset;
+ else
+ return;
+
+ chained_irq_enter(chip, desc);
+
+ for (i = 0; i < data->info->num_gpios; i += 32) {
+ reg_offset = get_reg_offset(data, i);
+ status = readl_relaxed(data->irq_base + reg_offset);
+
+ /* Clear edge interrupts; level interrupts are cleared in ->irq_ack() */
+ if (irq != data->irqs[2])
+ writel_relaxed(status, data->irq_base + reg_offset);
+
+ for_each_set_bit(j, &status, 32) {
+ hwirq = i + j;
+ girq = irq_find_mapping(domain, hwirq);
+ irq_type = irq_get_trigger_type(girq);
+
+ if (irq == data->irqs[1] && irq_type != IRQ_TYPE_EDGE_BOTH)
+ continue;
+
+ generic_handle_domain_irq(domain, hwirq);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void rtd1625_gpio_ack_irq(struct irq_data *d)
+{
+ struct rtd1625_gpio *data = irq_data_get_irq_chip_data(d);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 irq_type = irqd_get_trigger_type(d);
+ u32 bit_mask = BIT(hwirq % 32);
+ int reg_offset;
+
+ if (irq_type & IRQ_TYPE_LEVEL_MASK) {
+ reg_offset = rtd1625_gpio_level_offset(data, hwirq);
+ writel_relaxed(bit_mask, data->irq_base + reg_offset);
+ }
+}
+
+static void rtd1625_gpio_enable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
+{
+ int gpda_reg_offset = rtd1625_gpio_gpda_offset(data, hwirq);
+ int gpa_reg_offset = rtd1625_gpio_gpa_offset(data, hwirq);
+ u32 clr_mask = BIT(hwirq % 32);
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ writel_relaxed(clr_mask, data->irq_base + gpa_reg_offset);
+ writel_relaxed(clr_mask, data->irq_base + gpda_reg_offset);
+ val = RTD1625_GPIO_EDGE_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+}
+
+static void rtd1625_gpio_disable_edge_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
+{
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ val = RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_EN);
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+}
+
+static void rtd1625_gpio_enable_level_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
+{
+ int level_reg_offset = rtd1625_gpio_level_offset(data, hwirq);
+ u32 clr_mask = BIT(hwirq % 32);
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ writel_relaxed(clr_mask, data->irq_base + level_reg_offset);
+ val = RTD1625_GPIO_LEVEL_INT_EN | RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN);
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+}
+
+static void rtd1625_gpio_disable_level_irq(struct rtd1625_gpio *data, irq_hw_number_t hwirq)
+{
+ u32 val;
+
+ guard(raw_spinlock_irqsave)(&data->lock);
+ val = RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_EN);
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+}
+
+static void rtd1625_gpio_enable_irq(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rtd1625_gpio *data = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 irq_type = irqd_get_trigger_type(d);
+
+ gpiochip_enable_irq(gc, hwirq);
+
+ if (irq_type & IRQ_TYPE_EDGE_BOTH)
+ rtd1625_gpio_enable_edge_irq(data, hwirq);
+ else if (irq_type & IRQ_TYPE_LEVEL_MASK)
+ rtd1625_gpio_enable_level_irq(data, hwirq);
+}
+
+static void rtd1625_gpio_disable_irq(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rtd1625_gpio *data = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 irq_type = irqd_get_trigger_type(d);
+
+ if (irq_type & IRQ_TYPE_EDGE_BOTH)
+ rtd1625_gpio_disable_edge_irq(data, hwirq);
+ else if (irq_type & IRQ_TYPE_LEVEL_MASK)
+ rtd1625_gpio_disable_level_irq(data, hwirq);
+
+ gpiochip_disable_irq(gc, hwirq);
+}
+
+static int rtd1625_gpio_irq_set_level_type(struct irq_data *d, bool level)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rtd1625_gpio *data = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_LEVEL_INT_DP);
+
+ if (!(data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK))
+ return -EINVAL;
+
+ scoped_guard(raw_spinlock_irqsave, &data->lock) {
+ if (level)
+ val |= RTD1625_GPIO_LEVEL_INT_DP;
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+ }
+
+ irq_set_handler_locked(d, handle_level_irq);
+
+ return 0;
+}
+
+static int rtd1625_gpio_irq_set_edge_type(struct irq_data *d, bool polarity)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct rtd1625_gpio *data = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 val = RTD1625_GPIO_WREN(RTD1625_GPIO_EDGE_INT_DP);
+
+ if (!(data->info->irq_type_support & IRQ_TYPE_EDGE_BOTH))
+ return -EINVAL;
+
+ scoped_guard(raw_spinlock_irqsave, &data->lock) {
+ if (polarity)
+ val |= RTD1625_GPIO_EDGE_INT_DP;
+ writel_relaxed(val, data->base + GPIO_CONTROL(hwirq));
+ }
+
+ irq_set_handler_locked(d, handle_edge_irq);
+
+ return 0;
+}
+
+static int rtd1625_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ int ret;
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_RISING:
+ ret = rtd1625_gpio_irq_set_edge_type(d, 1);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ ret = rtd1625_gpio_irq_set_edge_type(d, 0);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ ret = rtd1625_gpio_irq_set_edge_type(d, 1);
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ ret = rtd1625_gpio_irq_set_level_type(d, 0);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ ret = rtd1625_gpio_irq_set_level_type(d, 1);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static struct irq_chip rtd1625_iso_gpio_irq_chip = {
+ .name = "rtd1625-gpio",
+ .irq_ack = rtd1625_gpio_ack_irq,
+ .irq_mask = rtd1625_gpio_disable_irq,
+ .irq_unmask = rtd1625_gpio_enable_irq,
+ .irq_set_type = rtd1625_gpio_irq_set_type,
+ .flags = IRQCHIP_IMMUTABLE | IRQCHIP_SKIP_SET_WAKE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static int rtd1625_gpio_setup_irq(struct platform_device *pdev, struct rtd1625_gpio *data)
+{
+ struct gpio_irq_chip *irq_chip;
+ int num_irqs;
+ int irq;
+ int i;
+
+ irq = platform_get_irq_optional(pdev, 0);
+ if (irq == -ENXIO)
+ return 0;
+ if (irq < 0)
+ return irq;
+
+ num_irqs = (data->info->irq_type_support & IRQ_TYPE_LEVEL_MASK) ? 3 : 2;
+ data->irqs[0] = irq;
+
+ for (i = 1; i < num_irqs; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ return irq;
+ data->irqs[i] = irq;
+ }
+
+ irq_chip = &data->gpio_chip.irq;
+ irq_chip->handler = handle_bad_irq;
+ irq_chip->default_type = IRQ_TYPE_NONE;
+ irq_chip->parent_handler = rtd1625_gpio_irq_handle;
+ irq_chip->parent_handler_data = data;
+ irq_chip->num_parents = num_irqs;
+ irq_chip->parents = data->irqs;
+
+ gpio_irq_chip_set_chip(irq_chip, &rtd1625_iso_gpio_irq_chip);
+
+ return 0;
+}
+
+static int rtd1625_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rtd1625_gpio *data;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->info = device_get_match_data(dev);
+ if (!data->info)
+ return -EINVAL;
+
+ raw_spin_lock_init(&data->lock);
+
+ data->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(data->base))
+ return PTR_ERR(data->base);
+
+ data->irq_base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(data->irq_base))
+ return PTR_ERR(data->irq_base);
+
+ data->save_regs = devm_kzalloc(dev, data->info->num_gpios *
+ sizeof(*data->save_regs), GFP_KERNEL);
+ if (!data->save_regs)
+ return -ENOMEM;
+
+ data->gpio_chip.label = dev_name(dev);
+ data->gpio_chip.base = -1;
+ data->gpio_chip.ngpio = data->info->num_gpios;
+ data->gpio_chip.request = gpiochip_generic_request;
+ data->gpio_chip.free = gpiochip_generic_free;
+ data->gpio_chip.get_direction = rtd1625_gpio_get_direction;
+ data->gpio_chip.direction_input = rtd1625_gpio_direction_input;
+ data->gpio_chip.direction_output = rtd1625_gpio_direction_output;
+ data->gpio_chip.set = rtd1625_gpio_set;
+ data->gpio_chip.get = rtd1625_gpio_get;
+ data->gpio_chip.set_config = rtd1625_gpio_set_config;
+ data->gpio_chip.parent = dev;
+
+ ret = rtd1625_gpio_setup_irq(pdev, data);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, data);
+
+ return devm_gpiochip_add_data(dev, &data->gpio_chip, data);
+}
+
+static const struct rtd1625_gpio_info rtd1625_iso_gpio_info = {
+ .num_gpios = 166,
+ .irq_type_support = IRQ_TYPE_EDGE_BOTH,
+ .gpa_offset = 0x0,
+ .gpda_offset = 0x20,
+ .write_en_all = RTD1625_ISO_GPIO_WREN_ALL,
+};
+
+static const struct rtd1625_gpio_info rtd1625_isom_gpio_info = {
+ .num_gpios = 4,
+ .irq_type_support = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_LOW |
+ IRQ_TYPE_LEVEL_HIGH,
+ .gpa_offset = 0x0,
+ .gpda_offset = 0x4,
+ .level_offset = 0x18,
+ .write_en_all = RTD1625_ISOM_GPIO_WREN_ALL,
+};
+
+static const struct of_device_id rtd1625_gpio_of_matches[] = {
+ { .compatible = "realtek,rtd1625-iso-gpio", .data = &rtd1625_iso_gpio_info },
+ { .compatible = "realtek,rtd1625-isom-gpio", .data = &rtd1625_isom_gpio_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, rtd1625_gpio_of_matches);
+
+static int rtd1625_gpio_suspend(struct device *dev)
+{
+ struct rtd1625_gpio *data = dev_get_drvdata(dev);
+ const struct rtd1625_gpio_info *info = data->info;
+ int i;
+
+ for (i = 0; i < info->num_gpios; i++)
+ data->save_regs[i] = readl_relaxed(data->base + GPIO_CONTROL(i));
+
+ return 0;
+}
+
+static int rtd1625_gpio_resume(struct device *dev)
+{
+ struct rtd1625_gpio *data = dev_get_drvdata(dev);
+ const struct rtd1625_gpio_info *info = data->info;
+ int i;
+
+ for (i = 0; i < info->num_gpios; i++)
+ writel_relaxed(data->save_regs[i] | info->write_en_all,
+ data->base + GPIO_CONTROL(i));
+
+ return 0;
+}
+
+DEFINE_NOIRQ_DEV_PM_OPS(rtd1625_gpio_pm_ops, rtd1625_gpio_suspend, rtd1625_gpio_resume);
+
+static struct platform_driver rtd1625_gpio_platform_driver = {
+ .driver = {
+ .name = "gpio-rtd1625",
+ .of_match_table = rtd1625_gpio_of_matches,
+ .pm = pm_sleep_ptr(&rtd1625_gpio_pm_ops),
+ },
+ .probe = rtd1625_gpio_probe,
+};
+module_platform_driver(rtd1625_gpio_platform_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Realtek Semiconductor Corporation");
+MODULE_DESCRIPTION("Realtek DHC SoC RTD1625 gpio driver");
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox