Merge branch 'drm-fixes-3.11' of git://people.freedesktop.org/~agd5f/linux
[firefly-linux-kernel-4.4.55.git] / drivers / pcmcia / at91_cf.c
index 01463c781847d6b2bccd3afd03eca62b0239cd0b..b8f5acf02261ca6708b26692d420f9164d2ac046 100644 (file)
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/platform_data/atmel.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 #include <pcmcia/ss.h>
 
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -41,8 +42,6 @@
 
 /*--------------------------------------------------------------------------*/
 
-static const char driver_name[] = "at91_cf";
-
 struct at91_cf_socket {
        struct pcmcia_socket    socket;
 
@@ -76,7 +75,7 @@ static irqreturn_t at91_cf_irq(int irq, void *_cf)
                /* kick pccard as needed */
                if (present != cf->present) {
                        cf->present = present;
-                       pr_debug("%s: card %s\n", driver_name,
+                       dev_dbg(&cf->pdev->dev, "card %s\n",
                                        present ? "present" : "gone");
                        pcmcia_parse_events(&cf->socket, SS_DETECT);
                }
@@ -100,9 +99,9 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
                int vcc = gpio_is_valid(cf->board->vcc_pin);
 
                *sp = SS_DETECT | SS_3VCARD;
-               if (!rdy || gpio_get_value(rdy))
+               if (!rdy || gpio_get_value(cf->board->irq_pin))
                        *sp |= SS_READY;
-               if (!vcc || gpio_get_value(vcc))
+               if (!vcc || gpio_get_value(cf->board->vcc_pin))
                        *sp |= SS_POWERON;
        } else
                *sp = 0;
@@ -120,22 +119,22 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
        /* switch Vcc if needed and possible */
        if (gpio_is_valid(cf->board->vcc_pin)) {
                switch (s->Vcc) {
-                       case 0:
-                               gpio_set_value(cf->board->vcc_pin, 0);
-                               break;
-                       case 33:
-                               gpio_set_value(cf->board->vcc_pin, 1);
-                               break;
-                       default:
-                               return -EINVAL;
+               case 0:
+                       gpio_set_value(cf->board->vcc_pin, 0);
+                       break;
+               case 33:
+                       gpio_set_value(cf->board->vcc_pin, 1);
+                       break;
+               default:
+                       return -EINVAL;
                }
        }
 
        /* toggle reset if needed */
        gpio_set_value(cf->board->rst_pin, s->flags & SS_RESET);
 
-       pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
-               driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+       dev_dbg(&cf->pdev->dev, "Vcc %d, io_irq %d, flags %04x csc %04x\n",
+                               s->Vcc, s->io_irq, s->flags, s->csc_mask);
 
        return 0;
 }
@@ -171,10 +170,10 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
         */
        if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) {
                csr |= AT91_SMC_DBW_8;
-               pr_debug("%s: 8bit i/o bus\n", driver_name);
+               dev_dbg(&cf->pdev->dev, "8bit i/o bus\n");
        } else {
                csr |= AT91_SMC_DBW_16;
-               pr_debug("%s: 16bit i/o bus\n", driver_name);
+               dev_dbg(&cf->pdev->dev, "16bit i/o bus\n");
        }
        at91_ramc_write(0, AT91_SMC_CSR(cf->board->chipselect), csr);
 
@@ -215,6 +214,37 @@ static struct pccard_operations at91_cf_ops = {
 
 /*--------------------------------------------------------------------------*/
 
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_cf_dt_ids[] = {
+       { .compatible = "atmel,at91rm9200-cf" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, at91_cf_dt_ids);
+
+static int at91_cf_dt_init(struct platform_device *pdev)
+{
+       struct at91_cf_data *board;
+
+       board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL);
+       if (!board)
+               return -ENOMEM;
+
+       board->irq_pin = of_get_gpio(pdev->dev.of_node, 0);
+       board->det_pin = of_get_gpio(pdev->dev.of_node, 1);
+       board->vcc_pin = of_get_gpio(pdev->dev.of_node, 2);
+       board->rst_pin = of_get_gpio(pdev->dev.of_node, 3);
+
+       pdev->dev.platform_data = board;
+
+       return 0;
+}
+#else
+static int at91_cf_dt_init(struct platform_device *pdev)
+{
+       return -ENODEV;
+}
+#endif
+
 static int __init at91_cf_probe(struct platform_device *pdev)
 {
        struct at91_cf_socket   *cf;
@@ -222,14 +252,22 @@ static int __init at91_cf_probe(struct platform_device *pdev)
        struct resource         *io;
        int                     status;
 
-       if (!board || !gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin))
+       if (!board) {
+               status = at91_cf_dt_init(pdev);
+               if (status)
+                       return status;
+
+               board = pdev->dev.platform_data;
+       }
+
+       if (!gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin))
                return -ENODEV;
 
        io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!io)
                return -ENODEV;
 
-       cf = kzalloc(sizeof *cf, GFP_KERNEL);
+       cf = devm_kzalloc(&pdev->dev, sizeof(*cf), GFP_KERNEL);
        if (!cf)
                return -ENOMEM;
 
@@ -239,22 +277,25 @@ static int __init at91_cf_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, cf);
 
        /* must be a GPIO; ergo must trigger on both edges */
-       status = gpio_request(board->det_pin, "cf_det");
+       status = devm_gpio_request(&pdev->dev, board->det_pin, "cf_det");
        if (status < 0)
-               goto fail0;
-       status = request_irq(gpio_to_irq(board->det_pin), at91_cf_irq, 0, driver_name, cf);
+               return status;
+
+       status = devm_request_irq(&pdev->dev, gpio_to_irq(board->det_pin),
+                                       at91_cf_irq, 0, "at91_cf detect", cf);
        if (status < 0)
-               goto fail00;
+               return status;
+
        device_init_wakeup(&pdev->dev, 1);
 
-       status = gpio_request(board->rst_pin, "cf_rst");
+       status = devm_gpio_request(&pdev->dev, board->rst_pin, "cf_rst");
        if (status < 0)
                goto fail0a;
 
        if (gpio_is_valid(board->vcc_pin)) {
-               status = gpio_request(board->vcc_pin, "cf_vcc");
+               status = devm_gpio_request(&pdev->dev, board->vcc_pin, "cf_vcc");
                if (status < 0)
-                       goto fail0b;
+                       goto fail0a;
        }
 
        /*
@@ -264,32 +305,33 @@ static int __init at91_cf_probe(struct platform_device *pdev)
         * (Note:  DK board doesn't wire the IRQ pin...)
         */
        if (gpio_is_valid(board->irq_pin)) {
-               status = gpio_request(board->irq_pin, "cf_irq");
+               status = devm_gpio_request(&pdev->dev, board->irq_pin, "cf_irq");
                if (status < 0)
-                       goto fail0c;
-               status = request_irq(gpio_to_irq(board->irq_pin), at91_cf_irq,
-                               IRQF_SHARED, driver_name, cf);
+                       goto fail0a;
+
+               status = devm_request_irq(&pdev->dev, gpio_to_irq(board->irq_pin),
+                                       at91_cf_irq, IRQF_SHARED, "at91_cf", cf);
                if (status < 0)
-                       goto fail0d;
+                       goto fail0a;
                cf->socket.pci_irq = gpio_to_irq(board->irq_pin);
        } else
                cf->socket.pci_irq = nr_irqs + 1;
 
        /* pcmcia layer only remaps "real" memory not iospace */
-       cf->socket.io_offset = (unsigned long)
-                       ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
+       cf->socket.io_offset = (unsigned long) devm_ioremap(&pdev->dev,
+                                       cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
        if (!cf->socket.io_offset) {
                status = -ENXIO;
-               goto fail1;
+               goto fail0a;
        }
 
        /* reserve chip-select regions */
-       if (!request_mem_region(io->start, resource_size(io), driver_name)) {
+       if (!devm_request_mem_region(&pdev->dev, io->start, resource_size(io), "at91_cf")) {
                status = -ENXIO;
-               goto fail1;
+               goto fail0a;
        }
 
-       pr_info("%s: irqs det #%d, io #%d\n", driver_name,
+       dev_info(&pdev->dev, "irqs det #%d, io #%d\n",
                gpio_to_irq(board->det_pin), gpio_to_irq(board->irq_pin));
 
        cf->socket.owner = THIS_MODULE;
@@ -303,55 +345,22 @@ static int __init at91_cf_probe(struct platform_device *pdev)
 
        status = pcmcia_register_socket(&cf->socket);
        if (status < 0)
-               goto fail2;
+               goto fail0a;
 
        return 0;
 
-fail2:
-       release_mem_region(io->start, resource_size(io));
-fail1:
-       if (cf->socket.io_offset)
-               iounmap((void __iomem *) cf->socket.io_offset);
-       if (gpio_is_valid(board->irq_pin)) {
-               free_irq(gpio_to_irq(board->irq_pin), cf);
-fail0d:
-               gpio_free(board->irq_pin);
-       }
-fail0c:
-       if (gpio_is_valid(board->vcc_pin))
-               gpio_free(board->vcc_pin);
-fail0b:
-       gpio_free(board->rst_pin);
 fail0a:
        device_init_wakeup(&pdev->dev, 0);
-       free_irq(gpio_to_irq(board->det_pin), cf);
-fail00:
-       gpio_free(board->det_pin);
-fail0:
-       kfree(cf);
        return status;
 }
 
 static int __exit at91_cf_remove(struct platform_device *pdev)
 {
        struct at91_cf_socket   *cf = platform_get_drvdata(pdev);
-       struct at91_cf_data     *board = cf->board;
-       struct resource         *io = cf->socket.io[0].res;
 
        pcmcia_unregister_socket(&cf->socket);
-       release_mem_region(io->start, resource_size(io));
-       iounmap((void __iomem *) cf->socket.io_offset);
-       if (gpio_is_valid(board->irq_pin)) {
-               free_irq(gpio_to_irq(board->irq_pin), cf);
-               gpio_free(board->irq_pin);
-       }
-       if (gpio_is_valid(board->vcc_pin))
-               gpio_free(board->vcc_pin);
-       gpio_free(board->rst_pin);
        device_init_wakeup(&pdev->dev, 0);
-       free_irq(gpio_to_irq(board->det_pin), cf);
-       gpio_free(board->det_pin);
-       kfree(cf);
+
        return 0;
 }
 
@@ -391,8 +400,9 @@ static int at91_cf_resume(struct platform_device *pdev)
 
 static struct platform_driver at91_cf_driver = {
        .driver = {
-               .name           = (char *) driver_name,
+               .name           = "at91_cf",
                .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91_cf_dt_ids),
        },
        .remove         = __exit_p(at91_cf_remove),
        .suspend        = at91_cf_suspend,
@@ -401,17 +411,7 @@ static struct platform_driver at91_cf_driver = {
 
 /*--------------------------------------------------------------------------*/
 
-static int __init at91_cf_init(void)
-{
-       return platform_driver_probe(&at91_cf_driver, at91_cf_probe);
-}
-module_init(at91_cf_init);
-
-static void __exit at91_cf_exit(void)
-{
-       platform_driver_unregister(&at91_cf_driver);
-}
-module_exit(at91_cf_exit);
+module_platform_driver_probe(at91_cf_driver, at91_cf_probe);
 
 MODULE_DESCRIPTION("AT91 Compact Flash Driver");
 MODULE_AUTHOR("David Brownell");