diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-abx500.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-abx500.c | 299 |
1 files changed, 3 insertions, 296 deletions
diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c index 0b3aa1c28fba..b8f6c7597d53 100644 --- a/drivers/pinctrl/pinctrl-abx500.c +++ b/drivers/pinctrl/pinctrl-abx500.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/interrupt.h> #include <linux/bitops.h> #include <linux/mfd/abx500.h> @@ -87,20 +88,11 @@ #define AB8540_GPIO_VINSEL_REG 0x47 #define AB8540_GPIO_PULL_UPDOWN_REG 0x48 #define AB8500_GPIO_ALTFUN_REG 0x50 -#define AB8500_NUM_VIR_GPIO_IRQ 16 #define AB8540_GPIO_PULL_UPDOWN_MASK 0x03 #define AB8540_GPIO_VINSEL_MASK 0x03 #define AB8540_GPIOX_VBAT_START 51 #define AB8540_GPIOX_VBAT_END 54 -enum abx500_gpio_action { - NONE, - STARTUP, - SHUTDOWN, - MASK, - UNMASK -}; - struct abx500_pinctrl { struct device *dev; struct pinctrl_dev *pctldev; @@ -109,14 +101,8 @@ struct abx500_pinctrl { struct ab8500 *parent; struct mutex lock; u32 irq_base; - enum abx500_gpio_action irq_action; - u16 rising; - u16 falling; struct abx500_gpio_irq_cluster *irq_cluster; int irq_cluster_size; - int irq_gpio_rising_offset; - int irq_gpio_falling_offset; - int irq_gpio_factor; }; /** @@ -473,7 +459,6 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip, unsigned offset, unsigned gpio) { - struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); const char *label = gpiochip_is_requested(chip, offset - 1); u8 gpio_offset = offset - 1; int mode = -1; @@ -502,25 +487,6 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s, : "? ") : (pull ? "pull up" : "pull down"), (mode < 0) ? "unknown" : modes[mode]); - - if (label && !is_out) { - int irq = gpio_to_irq(gpio); - struct irq_desc *desc = irq_to_desc(irq); - - if (irq >= 0 && desc->action) { - char *trigger; - int irq_offset = irq - pct->irq_base; - - if (pct->rising & BIT(irq_offset)) - trigger = "edge-rising"; - else if (pct->falling & BIT(irq_offset)) - trigger = "edge-falling"; - else - trigger = "edge-undefined"; - - seq_printf(s, " irq-%d %s", irq, trigger); - } - } } static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) @@ -574,219 +540,6 @@ static struct gpio_chip abx500gpio_chip = { .dbg_show = abx500_gpio_dbg_show, }; -static unsigned int irq_to_rising(unsigned int irq) -{ - struct abx500_pinctrl *pct = irq_get_chip_data(irq); - int offset = irq - pct->irq_base; - int new_irq; - - new_irq = offset * pct->irq_gpio_factor - + pct->irq_gpio_rising_offset - + pct->parent->irq_base; - - return new_irq; -} - -static unsigned int irq_to_falling(unsigned int irq) -{ - struct abx500_pinctrl *pct = irq_get_chip_data(irq); - int offset = irq - pct->irq_base; - int new_irq; - - new_irq = offset * pct->irq_gpio_factor - + pct->irq_gpio_falling_offset - + pct->parent->irq_base; - return new_irq; - -} - -static unsigned int rising_to_irq(unsigned int irq, void *dev) -{ - struct abx500_pinctrl *pct = dev; - int offset, new_irq; - - offset = irq - pct->irq_gpio_rising_offset - - pct->parent->irq_base; - new_irq = (offset / pct->irq_gpio_factor) - + pct->irq_base; - - return new_irq; -} - -static unsigned int falling_to_irq(unsigned int irq, void *dev) -{ - struct abx500_pinctrl *pct = dev; - int offset, new_irq; - - offset = irq - pct->irq_gpio_falling_offset - - pct->parent->irq_base; - new_irq = (offset / pct->irq_gpio_factor) - + pct->irq_base; - - return new_irq; -} - -/* - * IRQ handler - */ - -static irqreturn_t handle_rising(int irq, void *dev) -{ - - handle_nested_irq(rising_to_irq(irq , dev)); - return IRQ_HANDLED; -} - -static irqreturn_t handle_falling(int irq, void *dev) -{ - - handle_nested_irq(falling_to_irq(irq, dev)); - return IRQ_HANDLED; -} - -static void abx500_gpio_irq_lock(struct irq_data *data) -{ - struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data); - mutex_lock(&pct->lock); -} - -static void abx500_gpio_irq_sync_unlock(struct irq_data *data) -{ - struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data); - unsigned int irq = data->irq; - int offset = irq - pct->irq_base; - bool rising = pct->rising & BIT(offset); - bool falling = pct->falling & BIT(offset); - int ret; - - switch (pct->irq_action) { - case STARTUP: - if (rising) - ret = request_threaded_irq(irq_to_rising(irq), - NULL, handle_rising, - IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, - "abx500-gpio-r", pct); - if (falling) - ret = request_threaded_irq(irq_to_falling(irq), - NULL, handle_falling, - IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND, - "abx500-gpio-f", pct); - break; - case SHUTDOWN: - if (rising) - free_irq(irq_to_rising(irq), pct); - if (falling) - free_irq(irq_to_falling(irq), pct); - break; - case MASK: - if (rising) - disable_irq(irq_to_rising(irq)); - if (falling) - disable_irq(irq_to_falling(irq)); - break; - case UNMASK: - if (rising) - enable_irq(irq_to_rising(irq)); - if (falling) - enable_irq(irq_to_falling(irq)); - break; - case NONE: - break; - } - pct->irq_action = NONE; - pct->rising &= ~(BIT(offset)); - pct->falling &= ~(BIT(offset)); - mutex_unlock(&pct->lock); -} - - -static void abx500_gpio_irq_mask(struct irq_data *data) -{ - struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data); - pct->irq_action = MASK; -} - -static void abx500_gpio_irq_unmask(struct irq_data *data) -{ - struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data); - pct->irq_action = UNMASK; -} - -static int abx500_gpio_irq_set_type(struct irq_data *data, unsigned int type) -{ - struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data); - unsigned int irq = data->irq; - int offset = irq - pct->irq_base; - - if (type == IRQ_TYPE_EDGE_BOTH) { - pct->rising = BIT(offset); - pct->falling = BIT(offset); - } else if (type == IRQ_TYPE_EDGE_RISING) { - pct->rising = BIT(offset); - } else { - pct->falling = BIT(offset); - } - return 0; -} - -static unsigned int abx500_gpio_irq_startup(struct irq_data *data) -{ - struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data); - pct->irq_action = STARTUP; - return 0; -} - -static void abx500_gpio_irq_shutdown(struct irq_data *data) -{ - struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data); - pct->irq_action = SHUTDOWN; -} - -static struct irq_chip abx500_gpio_irq_chip = { - .name = "abx500-gpio", - .irq_startup = abx500_gpio_irq_startup, - .irq_shutdown = abx500_gpio_irq_shutdown, - .irq_bus_lock = abx500_gpio_irq_lock, - .irq_bus_sync_unlock = abx500_gpio_irq_sync_unlock, - .irq_mask = abx500_gpio_irq_mask, - .irq_unmask = abx500_gpio_irq_unmask, - .irq_set_type = abx500_gpio_irq_set_type, -}; - -static int abx500_gpio_irq_init(struct abx500_pinctrl *pct) -{ - u32 base = pct->irq_base; - int irq; - - for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) { - irq_set_chip_data(irq, pct); - irq_set_chip_and_handler(irq, &abx500_gpio_irq_chip, - handle_simple_irq); - irq_set_nested_thread(irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); -#else - irq_set_noprobe(irq); -#endif - } - - return 0; -} - -static void abx500_gpio_irq_remove(struct abx500_pinctrl *pct) -{ - int base = pct->irq_base; - int irq; - - for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) { -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif - irq_set_chip_and_handler(irq, NULL, NULL); - irq_set_chip_data(irq, NULL); - } -} - static int abx500_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); @@ -815,43 +568,6 @@ static int abx500_pmx_get_func_groups(struct pinctrl_dev *pctldev, return 0; } -static void abx500_disable_lazy_irq(struct gpio_chip *chip, unsigned gpio) -{ - struct abx500_pinctrl *pct = to_abx500_pinctrl(chip); - int irq; - int offset; - bool rising; - bool falling; - - /* - * check if gpio has interrupt capability and convert - * gpio number to irq - * On ABx5xx, there is no GPIO0, GPIO1 is the - * first one, so adjust gpio number - */ - gpio--; - irq = gpio_to_irq(gpio + chip->base); - if (irq < 0) - return; - - offset = irq - pct->irq_base; - rising = pct->rising & BIT(offset); - falling = pct->falling & BIT(offset); - - /* nothing to do ?*/ - if (!rising && !falling) - return; - - if (rising) { - disable_irq(irq_to_rising(irq)); - free_irq(irq_to_rising(irq), pct); - } - if (falling) { - disable_irq(irq_to_falling(irq)); - free_irq(irq_to_falling(irq), pct); - } -} - static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function, unsigned group) { @@ -871,7 +587,6 @@ static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function, dev_dbg(pct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting); - abx500_disable_lazy_irq(chip, g->pins[i]); ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting); } @@ -1197,18 +912,12 @@ static int abx500_gpio_probe(struct platform_device *pdev) pct->chip.ngpio = abx500_get_gpio_num(pct->soc); pct->irq_cluster = pct->soc->gpio_irq_cluster; pct->irq_cluster_size = pct->soc->ngpio_irq_cluster; - pct->irq_gpio_rising_offset = pct->soc->irq_gpio_rising_offset; - pct->irq_gpio_falling_offset = pct->soc->irq_gpio_falling_offset; - pct->irq_gpio_factor = pct->soc->irq_gpio_factor; - ret = abx500_gpio_irq_init(pct); - if (ret) - goto out_free; ret = gpiochip_add(&pct->chip); if (ret) { dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); mutex_destroy(&pct->lock); - goto out_rem_irq; + return ret; } dev_info(&pdev->dev, "added gpiochip\n"); @@ -1243,9 +952,7 @@ out_rem_chip: err = gpiochip_remove(&pct->chip); if (err) dev_info(&pdev->dev, "failed to remove gpiochip\n"); -out_rem_irq: - abx500_gpio_irq_remove(pct); -out_free: + mutex_destroy(&pct->lock); return ret; } |