usb: remove use of __devexit
[linux-2.6-block.git] / drivers / usb / musb / ux500.c
1 /*
2  * Copyright (C) 2010 ST-Ericsson AB
3  * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
4  *
5  * Based on omap2430.c
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/init.h>
25 #include <linux/clk.h>
26 #include <linux/err.h>
27 #include <linux/io.h>
28 #include <linux/platform_device.h>
29
30 #include "musb_core.h"
31
32 struct ux500_glue {
33         struct device           *dev;
34         struct platform_device  *musb;
35         struct clk              *clk;
36 };
37 #define glue_to_musb(g) platform_get_drvdata(g->musb)
38
39 static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
40 {
41         unsigned long   flags;
42         irqreturn_t     retval = IRQ_NONE;
43         struct musb     *musb = __hci;
44
45         spin_lock_irqsave(&musb->lock, flags);
46
47         musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
48         musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
49         musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
50
51         if (musb->int_usb || musb->int_tx || musb->int_rx)
52                 retval = musb_interrupt(musb);
53
54         spin_unlock_irqrestore(&musb->lock, flags);
55
56         return retval;
57 }
58
59 static int ux500_musb_init(struct musb *musb)
60 {
61         musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
62         if (IS_ERR_OR_NULL(musb->xceiv)) {
63                 pr_err("HS USB OTG: no transceiver configured\n");
64                 return -ENODEV;
65         }
66
67         musb->isr = ux500_musb_interrupt;
68
69         return 0;
70 }
71
72 static int ux500_musb_exit(struct musb *musb)
73 {
74         usb_put_phy(musb->xceiv);
75
76         return 0;
77 }
78
79 static const struct musb_platform_ops ux500_ops = {
80         .init           = ux500_musb_init,
81         .exit           = ux500_musb_exit,
82 };
83
84 static int ux500_probe(struct platform_device *pdev)
85 {
86         struct musb_hdrc_platform_data  *pdata = pdev->dev.platform_data;
87         struct platform_device          *musb;
88         struct ux500_glue               *glue;
89         struct clk                      *clk;
90         int                             ret = -ENOMEM;
91
92         glue = kzalloc(sizeof(*glue), GFP_KERNEL);
93         if (!glue) {
94                 dev_err(&pdev->dev, "failed to allocate glue context\n");
95                 goto err0;
96         }
97
98         musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
99         if (!musb) {
100                 dev_err(&pdev->dev, "failed to allocate musb device\n");
101                 goto err1;
102         }
103
104         clk = clk_get(&pdev->dev, "usb");
105         if (IS_ERR(clk)) {
106                 dev_err(&pdev->dev, "failed to get clock\n");
107                 ret = PTR_ERR(clk);
108                 goto err3;
109         }
110
111         ret = clk_enable(clk);
112         if (ret) {
113                 dev_err(&pdev->dev, "failed to enable clock\n");
114                 goto err4;
115         }
116
117         musb->dev.parent                = &pdev->dev;
118         musb->dev.dma_mask              = pdev->dev.dma_mask;
119         musb->dev.coherent_dma_mask     = pdev->dev.coherent_dma_mask;
120
121         glue->dev                       = &pdev->dev;
122         glue->musb                      = musb;
123         glue->clk                       = clk;
124
125         pdata->platform_ops             = &ux500_ops;
126
127         platform_set_drvdata(pdev, glue);
128
129         ret = platform_device_add_resources(musb, pdev->resource,
130                         pdev->num_resources);
131         if (ret) {
132                 dev_err(&pdev->dev, "failed to add resources\n");
133                 goto err5;
134         }
135
136         ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
137         if (ret) {
138                 dev_err(&pdev->dev, "failed to add platform_data\n");
139                 goto err5;
140         }
141
142         ret = platform_device_add(musb);
143         if (ret) {
144                 dev_err(&pdev->dev, "failed to register musb device\n");
145                 goto err5;
146         }
147
148         return 0;
149
150 err5:
151         clk_disable(clk);
152
153 err4:
154         clk_put(clk);
155
156 err3:
157         platform_device_put(musb);
158
159 err1:
160         kfree(glue);
161
162 err0:
163         return ret;
164 }
165
166 static int ux500_remove(struct platform_device *pdev)
167 {
168         struct ux500_glue       *glue = platform_get_drvdata(pdev);
169
170         platform_device_unregister(glue->musb);
171         clk_disable(glue->clk);
172         clk_put(glue->clk);
173         kfree(glue);
174
175         return 0;
176 }
177
178 #ifdef CONFIG_PM
179 static int ux500_suspend(struct device *dev)
180 {
181         struct ux500_glue       *glue = dev_get_drvdata(dev);
182         struct musb             *musb = glue_to_musb(glue);
183
184         usb_phy_set_suspend(musb->xceiv, 1);
185         clk_disable(glue->clk);
186
187         return 0;
188 }
189
190 static int ux500_resume(struct device *dev)
191 {
192         struct ux500_glue       *glue = dev_get_drvdata(dev);
193         struct musb             *musb = glue_to_musb(glue);
194         int                     ret;
195
196         ret = clk_enable(glue->clk);
197         if (ret) {
198                 dev_err(dev, "failed to enable clock\n");
199                 return ret;
200         }
201
202         usb_phy_set_suspend(musb->xceiv, 0);
203
204         return 0;
205 }
206
207 static const struct dev_pm_ops ux500_pm_ops = {
208         .suspend        = ux500_suspend,
209         .resume         = ux500_resume,
210 };
211
212 #define DEV_PM_OPS      (&ux500_pm_ops)
213 #else
214 #define DEV_PM_OPS      NULL
215 #endif
216
217 static struct platform_driver ux500_driver = {
218         .probe          = ux500_probe,
219         .remove         = ux500_remove,
220         .driver         = {
221                 .name   = "musb-ux500",
222                 .pm     = DEV_PM_OPS,
223         },
224 };
225
226 MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
227 MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
228 MODULE_LICENSE("GPL v2");
229 module_platform_driver(ux500_driver);