@@ -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;
@@ -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
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(-)