These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / pinctrl / sunxi / pinctrl-sunxi.c
index f8e171b..dead97d 100644 (file)
@@ -446,16 +446,6 @@ static const struct pinmux_ops sunxi_pmx_ops = {
        .gpio_set_direction     = sunxi_pmx_gpio_set_direction,
 };
 
-static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       return pinctrl_request_gpio(chip->base + offset);
-}
-
-static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       pinctrl_free_gpio(chip->base + offset);
-}
-
 static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
                                        unsigned offset)
 {
@@ -588,7 +578,6 @@ static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
 static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
 {
        struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
-       struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);
        u32 reg = sunxi_irq_cfg_reg(d->hwirq);
        u8 index = sunxi_irq_cfg_offset(d->hwirq);
        unsigned long flags;
@@ -615,16 +604,15 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
                return -EINVAL;
        }
 
-       if (type & IRQ_TYPE_LEVEL_MASK) {
-               d->chip = &sunxi_pinctrl_level_irq_chip;
-               desc->handle_irq = handle_fasteoi_irq;
-       } else {
-               d->chip = &sunxi_pinctrl_edge_irq_chip;
-               desc->handle_irq = handle_edge_irq;
-       }
-
        spin_lock_irqsave(&pctl->lock, flags);
 
+       if (type & IRQ_TYPE_LEVEL_MASK)
+               irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_level_irq_chip,
+                                                handle_fasteoi_irq, NULL);
+       else
+               irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_edge_irq_chip,
+                                                handle_edge_irq, NULL);
+
        regval = readl(pctl->membase + reg);
        regval &= ~(IRQ_CFG_IRQ_MASK << index);
        writel(regval | (mode << index), pctl->membase + reg);
@@ -685,6 +673,7 @@ static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d)
 }
 
 static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
+       .name           = "sunxi_pio_edge",
        .irq_ack        = sunxi_pinctrl_irq_ack,
        .irq_mask       = sunxi_pinctrl_irq_mask,
        .irq_unmask     = sunxi_pinctrl_irq_unmask,
@@ -695,6 +684,7 @@ static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
 };
 
 static struct irq_chip sunxi_pinctrl_level_irq_chip = {
+       .name           = "sunxi_pio_level",
        .irq_eoi        = sunxi_pinctrl_irq_ack,
        .irq_mask       = sunxi_pinctrl_irq_mask,
        .irq_unmask     = sunxi_pinctrl_irq_unmask,
@@ -709,10 +699,42 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = {
                          IRQCHIP_EOI_IF_HANDLED,
 };
 
-static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
+static int sunxi_pinctrl_irq_of_xlate(struct irq_domain *d,
+                                     struct device_node *node,
+                                     const u32 *intspec,
+                                     unsigned int intsize,
+                                     unsigned long *out_hwirq,
+                                     unsigned int *out_type)
 {
-       struct irq_chip *chip = irq_get_chip(irq);
-       struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
+       struct sunxi_pinctrl *pctl = d->host_data;
+       struct sunxi_desc_function *desc;
+       int pin, base;
+
+       if (intsize < 3)
+               return -EINVAL;
+
+       base = PINS_PER_BANK * intspec[0];
+       pin = pctl->desc->pin_base + base + intspec[1];
+
+       desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pin, "irq");
+       if (!desc)
+               return -EINVAL;
+
+       *out_hwirq = desc->irqbank * PINS_PER_BANK + desc->irqnum;
+       *out_type = intspec[2];
+
+       return 0;
+}
+
+static struct irq_domain_ops sunxi_pinctrl_irq_domain_ops = {
+       .xlate          = sunxi_pinctrl_irq_of_xlate,
+};
+
+static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
+{
+       unsigned int irq = irq_desc_get_irq(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct sunxi_pinctrl *pctl = irq_desc_get_handler_data(desc);
        unsigned long bank, reg, val;
 
        for (bank = 0; bank < pctl->desc->irq_banks; bank++)
@@ -911,9 +933,9 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
 
        pctl->pctl_dev = pinctrl_register(pctrl_desc,
                                          &pdev->dev, pctl);
-       if (!pctl->pctl_dev) {
+       if (IS_ERR(pctl->pctl_dev)) {
                dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
-               return -EINVAL;
+               return PTR_ERR(pctl->pctl_dev);
        }
 
        pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
@@ -924,8 +946,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
 
        last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number;
        pctl->chip->owner = THIS_MODULE;
-       pctl->chip->request = sunxi_pinctrl_gpio_request,
-       pctl->chip->free = sunxi_pinctrl_gpio_free,
+       pctl->chip->request = gpiochip_generic_request,
+       pctl->chip->free = gpiochip_generic_free,
        pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input,
        pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output,
        pctl->chip->get = sunxi_pinctrl_gpio_get,
@@ -983,8 +1005,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
 
        pctl->domain = irq_domain_add_linear(node,
                                             pctl->desc->irq_banks * IRQ_PER_BANK,
-                                            &irq_domain_simple_ops,
-                                            NULL);
+                                            &sunxi_pinctrl_irq_domain_ops,
+                                            pctl);
        if (!pctl->domain) {
                dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
                ret = -ENOMEM;
@@ -997,7 +1019,7 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
                irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip,
                                         handle_edge_irq);
                irq_set_chip_data(irqno, pctl);
-       };
+       }
 
        for (i = 0; i < pctl->desc->irq_banks; i++) {
                /* Mask and clear all IRQs before registering a handler */
@@ -1005,9 +1027,9 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
                writel(0xffffffff,
                        pctl->membase + sunxi_irq_status_reg_from_bank(i));
 
-               irq_set_chained_handler(pctl->irq[i],
-                                       sunxi_pinctrl_irq_handler);
-               irq_set_handler_data(pctl->irq[i], pctl);
+               irq_set_chained_handler_and_data(pctl->irq[i],
+                                                sunxi_pinctrl_irq_handler,
+                                                pctl);
        }
 
        dev_info(&pdev->dev, "initialized sunXi PIO driver\n");