PM / devfreq: rk3399_dmc: rename driver and internals to rockchip
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpio-mxs.c
index f8e6af20dfbf1d0efc5fce0060b6ace3792cb1ad..a4288f428819a3175d2e74cb2feec138ffacb4dc 100644 (file)
@@ -154,10 +154,10 @@ static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio)
 }
 
 /* MXS has one interrupt *per* gpio port */
-static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+static void mxs_gpio_irq_handler(struct irq_desc *desc)
 {
        u32 irq_stat;
-       struct mxs_gpio_port *port = irq_get_handler_data(irq);
+       struct mxs_gpio_port *port = irq_desc_get_handler_data(desc);
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
 
@@ -196,13 +196,16 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
        return 0;
 }
 
-static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
+static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
 
        gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base,
                                    port->base, handle_level_irq);
+       if (!gc)
+               return -ENOMEM;
+
        gc->private = port;
 
        ct = gc->chip_types;
@@ -214,7 +217,10 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
        ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
        ct->regs.mask = PINCTRL_IRQEN(port);
 
-       irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+       irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
+                              IRQ_NOREQUEST, 0);
+
+       return 0;
 }
 
 static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
@@ -226,7 +232,19 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
        return irq_find_mapping(port->domain, offset);
 }
 
-static struct platform_device_id mxs_gpio_ids[] = {
+static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+       struct mxs_gpio_port *port =
+               container_of(bgc, struct mxs_gpio_port, bgc);
+       u32 mask = 1 << offset;
+       u32 dir;
+
+       dir = readl(port->base + PINCTRL_DOE(port));
+       return !(dir & mask);
+}
+
+static const struct platform_device_id mxs_gpio_ids[] = {
        {
                .name = "imx23-gpio",
                .driver_data = IMX23_GPIO,
@@ -254,7 +272,6 @@ static int mxs_gpio_probe(struct platform_device *pdev)
        struct device_node *parent;
        static void __iomem *base;
        struct mxs_gpio_port *port;
-       struct resource *iores = NULL;
        int irq_base;
        int err;
 
@@ -262,16 +279,10 @@ static int mxs_gpio_probe(struct platform_device *pdev)
        if (!port)
                return -ENOMEM;
 
-       if (np) {
-               port->id = of_alias_get_id(np, "gpio");
-               if (port->id < 0)
-                       return port->id;
-               port->devid = (enum mxs_gpio_id) of_id->data;
-       } else {
-               port->id = pdev->id;
-               port->devid = pdev->id_entry->driver_data;
-       }
-
+       port->id = of_alias_get_id(np, "gpio");
+       if (port->id < 0)
+               return port->id;
+       port->devid = (enum mxs_gpio_id) of_id->data;
        port->irq = platform_get_irq(pdev, 0);
        if (port->irq < 0)
                return port->irq;
@@ -281,18 +292,11 @@ static int mxs_gpio_probe(struct platform_device *pdev)
         * share the same one
         */
        if (!base) {
-               if (np) {
-                       parent = of_get_parent(np);
-                       base = of_iomap(parent, 0);
-                       of_node_put(parent);
-                       if (!base)
-                               return -EADDRNOTAVAIL;
-               } else {
-                       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-                       base = devm_ioremap_resource(&pdev->dev, iores);
-                       if (IS_ERR(base))
-                               return PTR_ERR(base);
-               }
+               parent = of_get_parent(np);
+               base = of_iomap(parent, 0);
+               of_node_put(parent);
+               if (!base)
+                       return -EADDRNOTAVAIL;
        }
        port->base = base;
 
@@ -318,11 +322,13 @@ static int mxs_gpio_probe(struct platform_device *pdev)
        }
 
        /* gpio-mxs can be a generic irq chip */
-       mxs_gpio_init_gc(port, irq_base);
+       err = mxs_gpio_init_gc(port, irq_base);
+       if (err < 0)
+               goto out_irqdomain_remove;
 
        /* setup one handler for each entry */
-       irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
-       irq_set_handler_data(port->irq, port);
+       irq_set_chained_handler_and_data(port->irq, mxs_gpio_irq_handler,
+                                        port);
 
        err = bgpio_init(&port->bgc, &pdev->dev, 4,
                         port->base + PINCTRL_DIN(port),
@@ -333,6 +339,7 @@ static int mxs_gpio_probe(struct platform_device *pdev)
                goto out_irqdesc_free;
 
        port->bgc.gc.to_irq = mxs_gpio_to_irq;
+       port->bgc.gc.get_direction = mxs_gpio_get_direction;
        port->bgc.gc.base = port->id * 32;
 
        err = gpiochip_add(&port->bgc.gc);
@@ -343,6 +350,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)
 
 out_bgpio_remove:
        bgpio_remove(&port->bgc);
+out_irqdomain_remove:
+       irq_domain_remove(port->domain);
 out_irqdesc_free:
        irq_free_descs(irq_base, 32);
        return err;
@@ -351,7 +360,6 @@ out_irqdesc_free:
 static struct platform_driver mxs_gpio_driver = {
        .driver         = {
                .name   = "gpio-mxs",
-               .owner  = THIS_MODULE,
                .of_match_table = mxs_gpio_dt_ids,
        },
        .probe          = mxs_gpio_probe,