diff options
author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2019-05-04 02:12:39 +0300 |
---|---|---|
committer | Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> | 2021-11-05 10:22:05 +0300 |
commit | 75d4878154e969a6a07a028c4780e8c65ebfe428 (patch) | |
tree | 1d2d22a5b3e7c81b14d2e04fe73df9e1e3a7aab5 | |
parent | bda134ac56c65e4f45a1c930dfab43e1e5987987 (diff) | |
download | linux-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.c | 17 | ||||
-rw-r--r-- | drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c | 17 | ||||
-rw-r--r-- | drivers/pinctrl/aspeed/pinctrl-aspeed.c | 53 | ||||
-rw-r--r-- | drivers/pinctrl/aspeed/pinctrl-aspeed.h | 3 |
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); |