* [PATCH] HID: mcp2221: set gpio pin mode
@ 2025-06-08 16:33 Heiko Schocher
2025-06-19 4:42 ` Heiko Schocher
2025-06-20 6:48 ` Jiri Kosina
0 siblings, 2 replies; 3+ messages in thread
From: Heiko Schocher @ 2025-06-08 16:33 UTC (permalink / raw)
To: linux-kernel
Cc: Heiko Schocher, Benjamin Tissoires, Jiri Kosina, Rishi Gupta,
linux-i2c, linux-input
in case we have GPIOLIB enabled the gpio pins are used
from the current driver as gpio pins. But may the gpio
functions of this pins are not enabled in the flash
of the chip and so gpio access fails.
In case CONFIG_IIO is not enabled we can prevent this
issue of the driver simply by enabling the gpio mode
for all pins.
Signed-off-by: Heiko Schocher <hs@denx.de>
---
drivers/hid/hid-mcp2221.c | 97 +++++++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
index 0f93c22a479f..f693e920dffe 100644
--- a/drivers/hid/hid-mcp2221.c
+++ b/drivers/hid/hid-mcp2221.c
@@ -55,6 +55,27 @@ enum {
MCP2221_ALT_F_NOT_GPIOD = 0xEF,
};
+/* MCP SRAM read offsets cmd: MCP2221_GET_SRAM_SETTINGS */
+enum {
+ MCP2221_SRAM_RD_GP0 = 22,
+ MCP2221_SRAM_RD_GP1 = 23,
+ MCP2221_SRAM_RD_GP2 = 24,
+ MCP2221_SRAM_RD_GP3 = 25,
+};
+
+/* MCP SRAM write offsets cmd: MCP2221_SET_SRAM_SETTINGS */
+enum {
+ MCP2221_SRAM_WR_GP_ENA_ALTER = 7,
+ MCP2221_SRAM_WR_GP0 = 8,
+ MCP2221_SRAM_WR_GP1 = 9,
+ MCP2221_SRAM_WR_GP2 = 10,
+ MCP2221_SRAM_WR_GP3 = 11,
+};
+
+#define MCP2221_SRAM_GP_DESIGN_MASK 0x07
+#define MCP2221_SRAM_GP_DIRECTION_MASK 0x08
+#define MCP2221_SRAM_GP_VALUE_MASK 0x10
+
/* MCP GPIO direction encoding */
enum {
MCP2221_DIR_OUT = 0x00,
@@ -607,6 +628,80 @@ static const struct i2c_algorithm mcp_i2c_algo = {
};
#if IS_REACHABLE(CONFIG_GPIOLIB)
+static int mcp_gpio_read_sram(struct mcp2221 *mcp)
+{
+ int ret;
+
+ memset(mcp->txbuf, 0, 64);
+ mcp->txbuf[0] = MCP2221_GET_SRAM_SETTINGS;
+
+ mutex_lock(&mcp->lock);
+ ret = mcp_send_data_req_status(mcp, mcp->txbuf, 64);
+ mutex_unlock(&mcp->lock);
+
+ return ret;
+}
+
+/*
+ * If CONFIG_IIO is not enabled, check for the gpio pins
+ * if they are in gpio mode. For the ones which are not
+ * in gpio mode, set them into gpio mode.
+ */
+static int mcp2221_check_gpio_pinfunc(struct mcp2221 *mcp)
+{
+ int i;
+ int needgpiofix = 0;
+ int ret;
+
+ if (IS_ENABLED(CONFIG_IIO))
+ return 0;
+
+ ret = mcp_gpio_read_sram(mcp);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < MCP_NGPIO; i++) {
+ if ((mcp->mode[i] & MCP2221_SRAM_GP_DESIGN_MASK) != 0x0) {
+ dev_warn(&mcp->hdev->dev,
+ "GPIO %d not in gpio mode\n", i);
+ needgpiofix = 1;
+ }
+ }
+
+ if (!needgpiofix)
+ return 0;
+
+ /*
+ * Set all bytes to 0, so Bit 7 is not set. The chip
+ * only changes content of a register when bit 7 is set.
+ */
+ memset(mcp->txbuf, 0, 64);
+ mcp->txbuf[0] = MCP2221_SET_SRAM_SETTINGS;
+
+ /*
+ * Set bit 7 in MCP2221_SRAM_WR_GP_ENA_ALTER to enable
+ * loading of a new set of gpio settings to GP SRAM
+ */
+ mcp->txbuf[MCP2221_SRAM_WR_GP_ENA_ALTER] = 0x80;
+ for (i = 0; i < MCP_NGPIO; i++) {
+ if ((mcp->mode[i] & MCP2221_SRAM_GP_DESIGN_MASK) == 0x0) {
+ /* write current GPIO mode */
+ mcp->txbuf[MCP2221_SRAM_WR_GP0 + i] = mcp->mode[i];
+ } else {
+ /* pin is not in gpio mode, set it to input mode */
+ mcp->txbuf[MCP2221_SRAM_WR_GP0 + i] = 0x08;
+ dev_warn(&mcp->hdev->dev,
+ "Set GPIO mode for gpio pin %d!\n", i);
+ }
+ }
+
+ mutex_lock(&mcp->lock);
+ ret = mcp_send_data_req_status(mcp, mcp->txbuf, 64);
+ mutex_unlock(&mcp->lock);
+
+ return ret;
+}
+
static int mcp_gpio_get(struct gpio_chip *gc,
unsigned int offset)
{
@@ -1216,6 +1311,8 @@ static int mcp2221_probe(struct hid_device *hdev,
ret = devm_gpiochip_add_data(&hdev->dev, mcp->gc, mcp);
if (ret)
return ret;
+
+ mcp2221_check_gpio_pinfunc(mcp);
#endif
#if IS_REACHABLE(CONFIG_IIO)
--
2.20.1
base-commit: 546b1c9e93c2bb8cf5ed24e0be1c86bb089b3253
branch: abb-mcp2221-v1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] HID: mcp2221: set gpio pin mode
2025-06-08 16:33 [PATCH] HID: mcp2221: set gpio pin mode Heiko Schocher
@ 2025-06-19 4:42 ` Heiko Schocher
2025-06-20 6:48 ` Jiri Kosina
1 sibling, 0 replies; 3+ messages in thread
From: Heiko Schocher @ 2025-06-19 4:42 UTC (permalink / raw)
To: linux-kernel
Cc: Benjamin Tissoires, Jiri Kosina, Rishi Gupta, linux-i2c,
linux-input
Hi all,
On 08.06.25 18:33, Heiko Schocher wrote:
> in case we have GPIOLIB enabled the gpio pins are used
> from the current driver as gpio pins. But may the gpio
> functions of this pins are not enabled in the flash
> of the chip and so gpio access fails.
>
> In case CONFIG_IIO is not enabled we can prevent this
> issue of the driver simply by enabling the gpio mode
> for all pins.
>
> Signed-off-by: Heiko Schocher <hs@denx.de>
> ---
>
> drivers/hid/hid-mcp2221.c | 97 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 97 insertions(+)
Got message from patchwork:
The following patch (submitted by you) has been updated in Patchwork:
"""
* linux-i2c: HID: mcp2221: set gpio pin mode
- http://patchwork.ozlabs.org/project/linux-i2c/patch/20250608163315.24842-1-hs@denx.de/
- for: Linux I2C development
was: New
now: Not Applicable
"""
May I ask to which tree I should rebase my patch, so I can
resend? Just rebased my local patch to:
* fb4d33ab452e - (origin/master, origin/HEAD, master) Merge tag '6.16-rc2-ksmbd-server-fixes' of
git://git.samba.org/ksmbd
and it worked without problems.
And while at it, are there any issues with this patch or is it ready for
picking up?
Thanks!
bye,
Heiko
>
> diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
> index 0f93c22a479f..f693e920dffe 100644
> --- a/drivers/hid/hid-mcp2221.c
> +++ b/drivers/hid/hid-mcp2221.c
> @@ -55,6 +55,27 @@ enum {
> MCP2221_ALT_F_NOT_GPIOD = 0xEF,
> };
>
> +/* MCP SRAM read offsets cmd: MCP2221_GET_SRAM_SETTINGS */
> +enum {
> + MCP2221_SRAM_RD_GP0 = 22,
> + MCP2221_SRAM_RD_GP1 = 23,
> + MCP2221_SRAM_RD_GP2 = 24,
> + MCP2221_SRAM_RD_GP3 = 25,
> +};
> +
> +/* MCP SRAM write offsets cmd: MCP2221_SET_SRAM_SETTINGS */
> +enum {
> + MCP2221_SRAM_WR_GP_ENA_ALTER = 7,
> + MCP2221_SRAM_WR_GP0 = 8,
> + MCP2221_SRAM_WR_GP1 = 9,
> + MCP2221_SRAM_WR_GP2 = 10,
> + MCP2221_SRAM_WR_GP3 = 11,
> +};
> +
> +#define MCP2221_SRAM_GP_DESIGN_MASK 0x07
> +#define MCP2221_SRAM_GP_DIRECTION_MASK 0x08
> +#define MCP2221_SRAM_GP_VALUE_MASK 0x10
> +
> /* MCP GPIO direction encoding */
> enum {
> MCP2221_DIR_OUT = 0x00,
> @@ -607,6 +628,80 @@ static const struct i2c_algorithm mcp_i2c_algo = {
> };
>
> #if IS_REACHABLE(CONFIG_GPIOLIB)
> +static int mcp_gpio_read_sram(struct mcp2221 *mcp)
> +{
> + int ret;
> +
> + memset(mcp->txbuf, 0, 64);
> + mcp->txbuf[0] = MCP2221_GET_SRAM_SETTINGS;
> +
> + mutex_lock(&mcp->lock);
> + ret = mcp_send_data_req_status(mcp, mcp->txbuf, 64);
> + mutex_unlock(&mcp->lock);
> +
> + return ret;
> +}
> +
> +/*
> + * If CONFIG_IIO is not enabled, check for the gpio pins
> + * if they are in gpio mode. For the ones which are not
> + * in gpio mode, set them into gpio mode.
> + */
> +static int mcp2221_check_gpio_pinfunc(struct mcp2221 *mcp)
> +{
> + int i;
> + int needgpiofix = 0;
> + int ret;
> +
> + if (IS_ENABLED(CONFIG_IIO))
> + return 0;
> +
> + ret = mcp_gpio_read_sram(mcp);
> + if (ret)
> + return ret;
> +
> + for (i = 0; i < MCP_NGPIO; i++) {
> + if ((mcp->mode[i] & MCP2221_SRAM_GP_DESIGN_MASK) != 0x0) {
> + dev_warn(&mcp->hdev->dev,
> + "GPIO %d not in gpio mode\n", i);
> + needgpiofix = 1;
> + }
> + }
> +
> + if (!needgpiofix)
> + return 0;
> +
> + /*
> + * Set all bytes to 0, so Bit 7 is not set. The chip
> + * only changes content of a register when bit 7 is set.
> + */
> + memset(mcp->txbuf, 0, 64);
> + mcp->txbuf[0] = MCP2221_SET_SRAM_SETTINGS;
> +
> + /*
> + * Set bit 7 in MCP2221_SRAM_WR_GP_ENA_ALTER to enable
> + * loading of a new set of gpio settings to GP SRAM
> + */
> + mcp->txbuf[MCP2221_SRAM_WR_GP_ENA_ALTER] = 0x80;
> + for (i = 0; i < MCP_NGPIO; i++) {
> + if ((mcp->mode[i] & MCP2221_SRAM_GP_DESIGN_MASK) == 0x0) {
> + /* write current GPIO mode */
> + mcp->txbuf[MCP2221_SRAM_WR_GP0 + i] = mcp->mode[i];
> + } else {
> + /* pin is not in gpio mode, set it to input mode */
> + mcp->txbuf[MCP2221_SRAM_WR_GP0 + i] = 0x08;
> + dev_warn(&mcp->hdev->dev,
> + "Set GPIO mode for gpio pin %d!\n", i);
> + }
> + }
> +
> + mutex_lock(&mcp->lock);
> + ret = mcp_send_data_req_status(mcp, mcp->txbuf, 64);
> + mutex_unlock(&mcp->lock);
> +
> + return ret;
> +}
> +
> static int mcp_gpio_get(struct gpio_chip *gc,
> unsigned int offset)
> {
> @@ -1216,6 +1311,8 @@ static int mcp2221_probe(struct hid_device *hdev,
> ret = devm_gpiochip_add_data(&hdev->dev, mcp->gc, mcp);
> if (ret)
> return ret;
> +
> + mcp2221_check_gpio_pinfunc(mcp);
> #endif
>
> #if IS_REACHABLE(CONFIG_IIO)
>
--
DENX Software Engineering GmbH, Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52 Fax: +49-8142-66989-80 Email: hs@denx.de
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] HID: mcp2221: set gpio pin mode
2025-06-08 16:33 [PATCH] HID: mcp2221: set gpio pin mode Heiko Schocher
2025-06-19 4:42 ` Heiko Schocher
@ 2025-06-20 6:48 ` Jiri Kosina
1 sibling, 0 replies; 3+ messages in thread
From: Jiri Kosina @ 2025-06-20 6:48 UTC (permalink / raw)
To: Heiko Schocher
Cc: linux-kernel, Benjamin Tissoires, Rishi Gupta, linux-i2c,
linux-input
On Sun, 8 Jun 2025, Heiko Schocher wrote:
> in case we have GPIOLIB enabled the gpio pins are used
> from the current driver as gpio pins. But may the gpio
> functions of this pins are not enabled in the flash
> of the chip and so gpio access fails.
>
> In case CONFIG_IIO is not enabled we can prevent this
> issue of the driver simply by enabling the gpio mode
> for all pins.
>
> Signed-off-by: Heiko Schocher <hs@denx.de>
Now applied to hid.git#for-6.17/mcp2221. Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-06-20 6:48 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-08 16:33 [PATCH] HID: mcp2221: set gpio pin mode Heiko Schocher
2025-06-19 4:42 ` Heiko Schocher
2025-06-20 6:48 ` Jiri Kosina
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).