* [PATCH 0/2] mcp23s08: add get_direction and PIN_CONFIG_OUTPUT support.
@ 2021-10-19 10:52 Tomaz Solc
2021-10-19 10:52 ` [PATCH 1/2] pinctrl: mcp23s08: implement get_direction() Tomaz Solc
2021-10-19 10:52 ` [PATCH 2/2] pinctrl: mcp23s08: support for PIN_CONFIG_OUTPUT Tomaz Solc
0 siblings, 2 replies; 3+ messages in thread
From: Tomaz Solc @ 2021-10-19 10:52 UTC (permalink / raw)
To: linux-gpio; +Cc: Tomaz Solc
Motivation for these two patches is setting mcp23s08 outputs on boot from the
device tree.
gpio-hog was already functional with mcp23s08, however libgpio incorrectly
showed pins with output-high or output-low hogs as inputs since the driver did
not implement gpio_chip->get_direction().
Many other drivers also support setting pins to output-high or output-low via
pinmux. In contrast to gpio-hog, using pinmux to set the pin state on boot
allows the state to be changed later from user space. mcp23s08 did not support
this since PIN_CONFIG_OUTPUT was not implemented in
pinconf_ops->pin_config_set().
One issue with the second patch is that pins set to output-high or output-low
via pinmux still show up as inputs in libgpio after boot. This is because the
pin direction gets cached in gpio_desc.flags in devm_gpiochip_add_data().
However output-high/-low in pimux only gets applied after that. I am not sure
what would be the best approach to fix this.
Tomaz Solc (2):
pinctrl: mcp23s08: implement get_direction()
pinctrl: mcp23s08: support for PIN_CONFIG_OUTPUT.
.../bindings/pinctrl/pinctrl-mcp23s08.txt | 12 ++--
drivers/pinctrl/pinctrl-mcp23s08.c | 72 ++++++++++++++++---
2 files changed, 68 insertions(+), 16 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] pinctrl: mcp23s08: implement get_direction()
2021-10-19 10:52 [PATCH 0/2] mcp23s08: add get_direction and PIN_CONFIG_OUTPUT support Tomaz Solc
@ 2021-10-19 10:52 ` Tomaz Solc
2021-10-19 10:52 ` [PATCH 2/2] pinctrl: mcp23s08: support for PIN_CONFIG_OUTPUT Tomaz Solc
1 sibling, 0 replies; 3+ messages in thread
From: Tomaz Solc @ 2021-10-19 10:52 UTC (permalink / raw)
To: linux-gpio; +Cc: Tomaz Solc
Signed-off-by: Tomaz Solc <tomaz.solc@tablix.org>
---
drivers/pinctrl/pinctrl-mcp23s08.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index bccebe43dd6a..764c93dfd277 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -339,6 +339,29 @@ mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
return status;
}
+static int
+mcp23s08_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+ struct mcp23s08 *mcp = gpiochip_get_data(chip);
+ unsigned mask = BIT(offset);
+ int status, ret;
+
+ mutex_lock(&mcp->lock);
+
+ ret = mcp_read(mcp, MCP_IODIR, &status);
+ if (ret == 0) {
+ if(status & mask) {
+ ret = GPIO_LINE_DIRECTION_IN;
+ } else {
+ ret = GPIO_LINE_DIRECTION_OUT;
+ }
+ }
+
+ mutex_unlock(&mcp->lock);
+
+ return ret;
+}
+
/*----------------------------------------------------------------------*/
static irqreturn_t mcp23s08_irq(int irq, void *data)
{
@@ -545,6 +568,7 @@ int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
mcp->irq_chip.irq_bus_lock = mcp23s08_irq_bus_lock;
mcp->irq_chip.irq_bus_sync_unlock = mcp23s08_irq_bus_unlock;
+ mcp->chip.get_direction = mcp23s08_get_direction;
mcp->chip.direction_input = mcp23s08_direction_input;
mcp->chip.get = mcp23s08_get;
mcp->chip.direction_output = mcp23s08_direction_output;
--
2.20.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] pinctrl: mcp23s08: support for PIN_CONFIG_OUTPUT.
2021-10-19 10:52 [PATCH 0/2] mcp23s08: add get_direction and PIN_CONFIG_OUTPUT support Tomaz Solc
2021-10-19 10:52 ` [PATCH 1/2] pinctrl: mcp23s08: implement get_direction() Tomaz Solc
@ 2021-10-19 10:52 ` Tomaz Solc
1 sibling, 0 replies; 3+ messages in thread
From: Tomaz Solc @ 2021-10-19 10:52 UTC (permalink / raw)
To: linux-gpio; +Cc: Tomaz Solc
Adds support for setting mcp23s08 pins to output-high or output-low via pinmux
in the device tree.
Signed-off-by: Tomaz Solc <tomaz.solc@tablix.org>
---
.../bindings/pinctrl/pinctrl-mcp23s08.txt | 12 ++--
drivers/pinctrl/pinctrl-mcp23s08.c | 58 ++++++++++++++-----
2 files changed, 49 insertions(+), 21 deletions(-)
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
index 2fa5edac7a35..483ac9f719a1 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
@@ -88,11 +88,11 @@ gpiom1: gpio@0 {
spi-max-frequency = <1000000>;
};
-Pull-up configuration
-=====================
+Pin configuration
+=================
-If pins are used as output, they can also be configured with pull-ups. This is
-done with pinctrl.
+If pins are used as inputs, they can also be configured with pull-ups. Pins
+used as outputs can have their default states set. This is done with pinctrl.
Please refer file <devicetree/bindings/pinctrl/pinctrl-bindings.txt>
for details of the common pinctrl bindings used by client devices,
@@ -121,8 +121,10 @@ The following optional property is defined in the pinmux DT binding document
<pinctrl-bindings.txt>. Absence of this property will leave the configuration
in its default state.
bias-pull-up
+ output-high
+ output-low
-Example with pinctrl to pull-up output pins:
+Example with pinctrl to pull-up input pins:
gpio21: gpio@21 {
compatible = "microchip,mcp23017";
gpio-controller;
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index 764c93dfd277..81fc7fcef8ec 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -159,6 +159,26 @@ static int mcp_set_bit(struct mcp23s08 *mcp, unsigned int reg,
return mcp_set_mask(mcp, reg, mask, enabled);
}
+static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, bool value)
+{
+ return mcp_set_mask(mcp, MCP_OLAT, mask, value);
+}
+
+static int mcp_direction_output(struct mcp23s08 *mcp, unsigned offset,
+ int value)
+{
+ unsigned mask = BIT(offset);
+ int status;
+
+ mutex_lock(&mcp->lock);
+ status = __mcp23s08_set(mcp, mask, value);
+ if (status == 0) {
+ status = mcp_set_mask(mcp, MCP_IODIR, mask, false);
+ }
+ mutex_unlock(&mcp->lock);
+ return status;
+}
+
static const struct pinctrl_pin_desc mcp23x08_pins[] = {
PINCTRL_PIN(0, "gpio0"),
PINCTRL_PIN(1, "gpio1"),
@@ -225,6 +245,7 @@ static int mcp_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
enum pin_config_param param = pinconf_to_config_param(*config);
unsigned int data, status;
int ret;
+ u16 arg;
switch (param) {
case PIN_CONFIG_BIAS_PULL_UP:
@@ -232,12 +253,28 @@ static int mcp_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
if (ret < 0)
return ret;
status = (data & BIT(pin)) ? 1 : 0;
+ arg = 1;
+ break;
+ case PIN_CONFIG_OUTPUT:
+ ret = mcp_read(mcp, MCP_IODIR, &data);
+ if (ret < 0) {
+ return ret;
+ }
+
+ status = (data & BIT(pin)) ? 0 : 1;
+
+ ret = mcp_read(mcp, MCP_OLAT, &data);
+ if (ret < 0) {
+ return ret;
+ }
+
+ arg = (data & BIT(pin)) ? 1 : 0;
break;
default:
return -ENOTSUPP;
}
- *config = 0;
+ *config = pinconf_to_config_packed(param, arg);
return status ? 0 : -EINVAL;
}
@@ -259,6 +296,9 @@ static int mcp_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
case PIN_CONFIG_BIAS_PULL_UP:
ret = mcp_set_bit(mcp, MCP_GPPU, pin, arg);
break;
+ case PIN_CONFIG_OUTPUT:
+ ret = mcp_direction_output(mcp, pin, arg);
+ break;
default:
dev_dbg(mcp->dev, "Invalid config param %04x\n", param);
return -ENOTSUPP;
@@ -308,11 +348,6 @@ static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
return status;
}
-static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, bool value)
-{
- return mcp_set_mask(mcp, MCP_OLAT, mask, value);
-}
-
static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct mcp23s08 *mcp = gpiochip_get_data(chip);
@@ -327,16 +362,7 @@ static int
mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
{
struct mcp23s08 *mcp = gpiochip_get_data(chip);
- unsigned mask = BIT(offset);
- int status;
-
- mutex_lock(&mcp->lock);
- status = __mcp23s08_set(mcp, mask, value);
- if (status == 0) {
- status = mcp_set_mask(mcp, MCP_IODIR, mask, false);
- }
- mutex_unlock(&mcp->lock);
- return status;
+ return mcp_direction_output(mcp, offset, value);
}
static int
--
2.20.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-10-19 11:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-19 10:52 [PATCH 0/2] mcp23s08: add get_direction and PIN_CONFIG_OUTPUT support Tomaz Solc
2021-10-19 10:52 ` [PATCH 1/2] pinctrl: mcp23s08: implement get_direction() Tomaz Solc
2021-10-19 10:52 ` [PATCH 2/2] pinctrl: mcp23s08: support for PIN_CONFIG_OUTPUT Tomaz Solc
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.