summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2019-05-04 02:12:39 +0300
committerJae Hyun Yoo <jae.hyun.yoo@linux.intel.com>2021-11-05 10:22:05 +0300
commit75d4878154e969a6a07a028c4780e8c65ebfe428 (patch)
tree1d2d22a5b3e7c81b14d2e04fe73df9e1e3a7aab5
parentbda134ac56c65e4f45a1c930dfab43e1e5987987 (diff)
downloadlinux-75d4878154e969a6a07a028c4780e8c65ebfe428.tar.xz
Enable pass-through on GPIOE1 and GPIOE3 free
This change adds a gpio_disable_free() implementation that checks if the GPIO being freed is GPIOE1 (33) or GPIOE3 (35) and will re-enable the pass-through mux. Tested: Requested GPIOs 33 and 35 and used devmem to check that pass-through was disabled. Then freed them and checked that pass-through was enabled again. Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c17
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c17
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed.c53
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed.h3
4 files changed, 90 insertions, 0 deletions
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
index 4c0d26606b6c..6ab3473cbba6 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
@@ -2785,6 +2785,22 @@ static int aspeed_g5_sig_expr_set(struct aspeed_pinmux_data *ctx,
return 0;
}
+#define GPIOE1 33
+#define GPIOE3 35
+static void aspeed_g5_gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ /*
+ * If we're freeing GPIOE1 (33) or GPIOE3 (35) then re-enable the
+ * pass-through mux setting; otherwise, do nothing.
+ */
+ if (offset != GPIOE1 && offset != GPIOE3)
+ return;
+
+ aspeed_gpio_disable_free(pctldev, range, offset);
+}
+
static const struct aspeed_pin_config_map aspeed_g5_pin_config_map[] = {
{ PIN_CONFIG_BIAS_PULL_DOWN, 0, 1, BIT_MASK(0)},
{ PIN_CONFIG_BIAS_PULL_DOWN, -1, 0, BIT_MASK(0)},
@@ -2820,6 +2836,7 @@ static const struct pinmux_ops aspeed_g5_pinmux_ops = {
.get_function_groups = aspeed_pinmux_get_fn_groups,
.set_mux = aspeed_pinmux_set_mux,
.gpio_request_enable = aspeed_gpio_request_enable,
+ .gpio_disable_free = aspeed_g5_gpio_disable_free,
.strict = true,
};
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
index a3fa03bcd9a3..ffc72168ef7b 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
@@ -2693,6 +2693,22 @@ static int aspeed_g6_sig_expr_set(struct aspeed_pinmux_data *ctx,
return 0;
}
+#define GPIOP1 121
+#define GPIOP3 123
+static void aspeed_g6_gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ /*
+ * If we're freeing GPIOP1 (121) or GPIOP3 (123) then re-enable the
+ * pass-through mux setting; otherwise, do nothing.
+ */
+ if (offset != GPIOP1 && offset != GPIOP3)
+ return;
+
+ aspeed_gpio_disable_free(pctldev, range, offset);
+}
+
static const struct aspeed_pin_config_map aspeed_g6_pin_config_map[] = {
{ PIN_CONFIG_BIAS_PULL_DOWN, 0, 1, BIT_MASK(0)},
{ PIN_CONFIG_BIAS_PULL_DOWN, -1, 0, BIT_MASK(0)},
@@ -2733,6 +2749,7 @@ static const struct pinmux_ops aspeed_g6_pinmux_ops = {
.get_function_groups = aspeed_pinmux_get_fn_groups,
.set_mux = aspeed_pinmux_set_mux,
.gpio_request_enable = aspeed_gpio_request_enable,
+ .gpio_disable_free = aspeed_g6_gpio_disable_free,
.strict = true,
};
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
index c94e24aadf92..ade658af580b 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
@@ -439,6 +439,59 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
return 0;
}
+void aspeed_gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+ const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
+ const struct aspeed_sig_expr ***prios, **funcs, *expr;
+ int ret;
+
+ if (!pdesc)
+ return;
+
+ dev_dbg(pctldev->dev,
+ "Freeing pass-through pin %s (%d). Re-enabling pass-through.\n",
+ pdesc->name, offset);
+
+ prios = pdesc->prios;
+
+ if (!prios)
+ return;
+
+ /* Disable any functions of higher priority than GPIO just in case */
+ while ((funcs = *prios)) {
+ if (aspeed_gpio_in_exprs(funcs))
+ break;
+
+ ret = aspeed_disable_sig(&pdata->pinmux, funcs);
+ if (ret)
+ return;
+
+ prios++;
+ }
+
+ if (!funcs) {
+ char *signals = get_defined_signals(pdesc);
+
+ pr_warn("No GPIO signal type found on pin %s (%d). Found: %s\n",
+ pdesc->name, offset, signals);
+ kfree(signals);
+
+ return;
+ }
+
+ /*
+ * Pass-through should be one priority higher than the GPIO function,
+ * so decrement our prios and enable that function
+ */
+ prios--;
+ funcs = *prios;
+ expr = *funcs;
+ aspeed_sig_expr_enable(&pdata->pinmux, expr);
+}
+
int aspeed_pinctrl_probe(struct platform_device *pdev,
struct pinctrl_desc *pdesc,
struct aspeed_pinctrl_data *pdata)
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.h b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
index 4dcde3bc29c8..bd497c20a15f 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
@@ -101,6 +101,9 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned int offset);
+void aspeed_gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset);
int aspeed_pinctrl_probe(struct platform_device *pdev,
struct pinctrl_desc *pdesc,
struct aspeed_pinctrl_data *pdata);