atmel_spi: fix warning In function 'atmel_spi_dma_map_xfer'
[pandora-kernel.git] / drivers / spi / dw_spi_mmio.c
1 /*
2  * dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core
3  *
4  * Copyright (c) 2010, Octasic semiconductor.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  */
10
11 #include <linux/clk.h>
12 #include <linux/interrupt.h>
13 #include <linux/platform_device.h>
14 #include <linux/slab.h>
15 #include <linux/spi/dw_spi.h>
16 #include <linux/spi/spi.h>
17
18 #define DRIVER_NAME "dw_spi_mmio"
19
20 struct dw_spi_mmio {
21         struct dw_spi  dws;
22         struct clk     *clk;
23 };
24
25 static int __devinit dw_spi_mmio_probe(struct platform_device *pdev)
26 {
27         struct dw_spi_mmio *dwsmmio;
28         struct dw_spi *dws;
29         struct resource *mem, *ioarea;
30         int ret;
31
32         dwsmmio = kzalloc(sizeof(struct dw_spi_mmio), GFP_KERNEL);
33         if (!dwsmmio) {
34                 ret = -ENOMEM;
35                 goto err_end;
36         }
37
38         dws = &dwsmmio->dws;
39
40         /* Get basic io resource and map it */
41         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
42         if (!mem) {
43                 dev_err(&pdev->dev, "no mem resource?\n");
44                 ret = -EINVAL;
45                 goto err_kfree;
46         }
47
48         ioarea = request_mem_region(mem->start, resource_size(mem),
49                         pdev->name);
50         if (!ioarea) {
51                 dev_err(&pdev->dev, "SPI region already claimed\n");
52                 ret = -EBUSY;
53                 goto err_kfree;
54         }
55
56         dws->regs = ioremap_nocache(mem->start, resource_size(mem));
57         if (!dws->regs) {
58                 dev_err(&pdev->dev, "SPI region already mapped\n");
59                 ret = -ENOMEM;
60                 goto err_release_reg;
61         }
62
63         dws->irq = platform_get_irq(pdev, 0);
64         if (dws->irq < 0) {
65                 dev_err(&pdev->dev, "no irq resource?\n");
66                 ret = dws->irq; /* -ENXIO */
67                 goto err_unmap;
68         }
69
70         dwsmmio->clk = clk_get(&pdev->dev, NULL);
71         if (!dwsmmio->clk) {
72                 ret = -ENODEV;
73                 goto err_irq;
74         }
75         clk_enable(dwsmmio->clk);
76
77         dws->parent_dev = &pdev->dev;
78         dws->bus_num = 0;
79         dws->num_cs = 4;
80         dws->max_freq = clk_get_rate(dwsmmio->clk);
81
82         ret = dw_spi_add_host(dws);
83         if (ret)
84                 goto err_clk;
85
86         platform_set_drvdata(pdev, dwsmmio);
87         return 0;
88
89 err_clk:
90         clk_disable(dwsmmio->clk);
91         clk_put(dwsmmio->clk);
92         dwsmmio->clk = NULL;
93 err_irq:
94         free_irq(dws->irq, dws);
95 err_unmap:
96         iounmap(dws->regs);
97 err_release_reg:
98         release_mem_region(mem->start, resource_size(mem));
99 err_kfree:
100         kfree(dwsmmio);
101 err_end:
102         return ret;
103 }
104
105 static int __devexit dw_spi_mmio_remove(struct platform_device *pdev)
106 {
107         struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev);
108         struct resource *mem;
109
110         platform_set_drvdata(pdev, NULL);
111
112         clk_disable(dwsmmio->clk);
113         clk_put(dwsmmio->clk);
114         dwsmmio->clk = NULL;
115
116         free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
117         dw_spi_remove_host(&dwsmmio->dws);
118         iounmap(dwsmmio->dws.regs);
119         kfree(dwsmmio);
120
121         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
122         release_mem_region(mem->start, resource_size(mem));
123         return 0;
124 }
125
126 static struct platform_driver dw_spi_mmio_driver = {
127         .remove         = __devexit_p(dw_spi_mmio_remove),
128         .driver         = {
129                 .name   = DRIVER_NAME,
130                 .owner  = THIS_MODULE,
131         },
132 };
133
134 static int __init dw_spi_mmio_init(void)
135 {
136         return platform_driver_probe(&dw_spi_mmio_driver, dw_spi_mmio_probe);
137 }
138 module_init(dw_spi_mmio_init);
139
140 static void __exit dw_spi_mmio_exit(void)
141 {
142         platform_driver_unregister(&dw_spi_mmio_driver);
143 }
144 module_exit(dw_spi_mmio_exit);
145
146 MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
147 MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
148 MODULE_LICENSE("GPL v2");