[PATCH 2/2] pinctrl: mcp23s08: support for PIN_CONFIG_OUTPUT.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
 .../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




[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux