diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-stmfx.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-stmfx.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 16723797fa7c..ab4dde40d3ed 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -134,10 +134,14 @@ static int stmfx_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) ret = regmap_read(pctl->stmfx->map, reg, &val); /* * On stmfx, gpio pins direction is (0)input, (1)output. - * .get_direction returns 0=out, 1=in */ + if (ret) + return ret; - return ret ? ret : !(val & mask); + if (val & mask) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; } static int stmfx_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) @@ -223,6 +227,13 @@ static int stmfx_pinconf_get(struct pinctrl_dev *pctldev, dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin); if (dir < 0) return dir; + + /* + * Currently the gpiolib IN is 1 and OUT is 0 but let's not count + * on it just to be on the safe side also in the future :) + */ + dir = (dir == GPIO_LINE_DIRECTION_IN) ? 1 : 0; + type = stmfx_pinconf_get_type(pctl, pin); if (type < 0) return type; @@ -277,7 +288,7 @@ static int stmfx_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, struct pinctrl_gpio_range *range; enum pin_config_param param; u32 arg; - int dir, i, ret; + int i, ret; range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); if (!range) { @@ -285,10 +296,6 @@ static int stmfx_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, return -EINVAL; } - dir = stmfx_gpio_get_direction(&pctl->gpio_chip, pin); - if (dir < 0) - return dir; - for (i = 0; i < num_configs; i++) { param = pinconf_to_config_param(configs[i]); arg = pinconf_to_config_argument(configs[i]); @@ -360,7 +367,7 @@ static void stmfx_pinconf_dbg_show(struct pinctrl_dev *pctldev, if (val < 0) return; - if (!dir) { + if (dir == GPIO_LINE_DIRECTION_OUT) { seq_printf(s, "output %s ", val ? "high" : "low"); if (type) seq_printf(s, "open drain %s internal pull-up ", @@ -559,7 +566,7 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id) u8 pending[NR_GPIO_REGS]; u8 src[NR_GPIO_REGS] = {0, 0, 0}; unsigned long n, status; - int ret; + int i, ret; ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_IRQ_GPI_PENDING, &pending, NR_GPIO_REGS); @@ -569,7 +576,9 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id) regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC, src, NR_GPIO_REGS); - status = *(unsigned long *)pending; + BUILD_BUG_ON(NR_GPIO_REGS > sizeof(status)); + for (i = 0, status = 0; i < NR_GPIO_REGS; i++) + status |= (unsigned long)pending[i] << (i * 8); for_each_set_bit(n, &status, gc->ngpio) { handle_nested_irq(irq_find_mapping(gc->irq.domain, n)); stmfx_pinctrl_irq_toggle_trigger(pctl, n); @@ -609,6 +618,7 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) struct stmfx *stmfx = dev_get_drvdata(pdev->dev.parent); struct device_node *np = pdev->dev.of_node; struct stmfx_pinctrl *pctl; + struct gpio_irq_chip *girq; int irq, ret; pctl = devm_kzalloc(stmfx->dev, sizeof(*pctl), GFP_KERNEL); @@ -665,17 +675,6 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) pctl->gpio_chip.base = -1; pctl->gpio_chip.ngpio = pctl->pctl_desc.npins; pctl->gpio_chip.can_sleep = true; - pctl->gpio_chip.of_node = np; - - ret = devm_gpiochip_add_data(pctl->dev, &pctl->gpio_chip, pctl); - if (ret) { - dev_err(pctl->dev, "gpio_chip registration failed\n"); - return ret; - } - - ret = stmfx_pinctrl_gpio_function_enable(pctl); - if (ret) - return ret; pctl->irq_chip.name = dev_name(pctl->dev); pctl->irq_chip.irq_mask = stmfx_pinctrl_irq_mask; @@ -686,13 +685,26 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) pctl->irq_chip.irq_request_resources = stmfx_gpio_irq_request_resources; pctl->irq_chip.irq_release_resources = stmfx_gpio_irq_release_resources; - ret = gpiochip_irqchip_add_nested(&pctl->gpio_chip, &pctl->irq_chip, - 0, handle_bad_irq, IRQ_TYPE_NONE); + girq = &pctl->gpio_chip.irq; + girq->chip = &pctl->irq_chip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + girq->threaded = true; + + ret = devm_gpiochip_add_data(pctl->dev, &pctl->gpio_chip, pctl); if (ret) { - dev_err(pctl->dev, "cannot add irqchip to gpiochip\n"); + dev_err(pctl->dev, "gpio_chip registration failed\n"); return ret; } + ret = stmfx_pinctrl_gpio_function_enable(pctl); + if (ret) + return ret; + ret = devm_request_threaded_irq(pctl->dev, irq, NULL, stmfx_pinctrl_irq_thread_fn, IRQF_ONESHOT, @@ -702,8 +714,6 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) return ret; } - gpiochip_set_nested_irqchip(&pctl->gpio_chip, &pctl->irq_chip, irq); - dev_info(pctl->dev, "%ld GPIOs available\n", hweight_long(pctl->gpio_valid_mask)); |