~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/usb/musb/ux500.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/io.h>
 
27
#include <linux/platform_device.h>
 
28
 
 
29
#include "musb_core.h"
 
30
 
 
31
struct ux500_glue {
 
32
        struct device           *dev;
 
33
        struct platform_device  *musb;
 
34
        struct clk              *clk;
 
35
};
 
36
#define glue_to_musb(g) platform_get_drvdata(g->musb)
 
37
 
 
38
static int ux500_musb_init(struct musb *musb)
 
39
{
 
40
        musb->xceiv = otg_get_transceiver();
 
41
        if (!musb->xceiv) {
 
42
                pr_err("HS USB OTG: no transceiver configured\n");
 
43
                return -ENODEV;
 
44
        }
 
45
 
 
46
        return 0;
 
47
}
 
48
 
 
49
static int ux500_musb_exit(struct musb *musb)
 
50
{
 
51
        otg_put_transceiver(musb->xceiv);
 
52
 
 
53
        return 0;
 
54
}
 
55
 
 
56
static const struct musb_platform_ops ux500_ops = {
 
57
        .init           = ux500_musb_init,
 
58
        .exit           = ux500_musb_exit,
 
59
};
 
60
 
 
61
static int __init ux500_probe(struct platform_device *pdev)
 
62
{
 
63
        struct musb_hdrc_platform_data  *pdata = pdev->dev.platform_data;
 
64
        struct platform_device          *musb;
 
65
        struct ux500_glue               *glue;
 
66
        struct clk                      *clk;
 
67
 
 
68
        int                             ret = -ENOMEM;
 
69
 
 
70
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
 
71
        if (!glue) {
 
72
                dev_err(&pdev->dev, "failed to allocate glue context\n");
 
73
                goto err0;
 
74
        }
 
75
 
 
76
        musb = platform_device_alloc("musb-hdrc", -1);
 
77
        if (!musb) {
 
78
                dev_err(&pdev->dev, "failed to allocate musb device\n");
 
79
                goto err1;
 
80
        }
 
81
 
 
82
        clk = clk_get(&pdev->dev, "usb");
 
83
        if (IS_ERR(clk)) {
 
84
                dev_err(&pdev->dev, "failed to get clock\n");
 
85
                ret = PTR_ERR(clk);
 
86
                goto err2;
 
87
        }
 
88
 
 
89
        ret = clk_enable(clk);
 
90
        if (ret) {
 
91
                dev_err(&pdev->dev, "failed to enable clock\n");
 
92
                goto err3;
 
93
        }
 
94
 
 
95
        musb->dev.parent                = &pdev->dev;
 
96
 
 
97
        glue->dev                       = &pdev->dev;
 
98
        glue->musb                      = musb;
 
99
        glue->clk                       = clk;
 
100
 
 
101
        pdata->platform_ops             = &ux500_ops;
 
102
 
 
103
        platform_set_drvdata(pdev, glue);
 
104
 
 
105
        ret = platform_device_add_resources(musb, pdev->resource,
 
106
                        pdev->num_resources);
 
107
        if (ret) {
 
108
                dev_err(&pdev->dev, "failed to add resources\n");
 
109
                goto err4;
 
110
        }
 
111
 
 
112
        ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 
113
        if (ret) {
 
114
                dev_err(&pdev->dev, "failed to add platform_data\n");
 
115
                goto err4;
 
116
        }
 
117
 
 
118
        ret = platform_device_add(musb);
 
119
        if (ret) {
 
120
                dev_err(&pdev->dev, "failed to register musb device\n");
 
121
                goto err4;
 
122
        }
 
123
 
 
124
        return 0;
 
125
 
 
126
err4:
 
127
        clk_disable(clk);
 
128
 
 
129
err3:
 
130
        clk_put(clk);
 
131
 
 
132
err2:
 
133
        platform_device_put(musb);
 
134
 
 
135
err1:
 
136
        kfree(glue);
 
137
 
 
138
err0:
 
139
        return ret;
 
140
}
 
141
 
 
142
static int __exit ux500_remove(struct platform_device *pdev)
 
143
{
 
144
        struct ux500_glue       *glue = platform_get_drvdata(pdev);
 
145
 
 
146
        platform_device_del(glue->musb);
 
147
        platform_device_put(glue->musb);
 
148
        clk_disable(glue->clk);
 
149
        clk_put(glue->clk);
 
150
        kfree(glue);
 
151
 
 
152
        return 0;
 
153
}
 
154
 
 
155
#ifdef CONFIG_PM
 
156
static int ux500_suspend(struct device *dev)
 
157
{
 
158
        struct ux500_glue       *glue = dev_get_drvdata(dev);
 
159
        struct musb             *musb = glue_to_musb(glue);
 
160
 
 
161
        otg_set_suspend(musb->xceiv, 1);
 
162
        clk_disable(glue->clk);
 
163
 
 
164
        return 0;
 
165
}
 
166
 
 
167
static int ux500_resume(struct device *dev)
 
168
{
 
169
        struct ux500_glue       *glue = dev_get_drvdata(dev);
 
170
        struct musb             *musb = glue_to_musb(glue);
 
171
        int                     ret;
 
172
 
 
173
        ret = clk_enable(glue->clk);
 
174
        if (ret) {
 
175
                dev_err(dev, "failed to enable clock\n");
 
176
                return ret;
 
177
        }
 
178
 
 
179
        otg_set_suspend(musb->xceiv, 0);
 
180
 
 
181
        return 0;
 
182
}
 
183
 
 
184
static const struct dev_pm_ops ux500_pm_ops = {
 
185
        .suspend        = ux500_suspend,
 
186
        .resume         = ux500_resume,
 
187
};
 
188
 
 
189
#define DEV_PM_OPS      (&ux500_pm_ops)
 
190
#else
 
191
#define DEV_PM_OPS      NULL
 
192
#endif
 
193
 
 
194
static struct platform_driver ux500_driver = {
 
195
        .remove         = __exit_p(ux500_remove),
 
196
        .driver         = {
 
197
                .name   = "musb-ux500",
 
198
                .pm     = DEV_PM_OPS,
 
199
        },
 
200
};
 
201
 
 
202
MODULE_DESCRIPTION("UX500 MUSB Glue Layer");
 
203
MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>");
 
204
MODULE_LICENSE("GPL v2");
 
205
 
 
206
static int __init ux500_init(void)
 
207
{
 
208
        return platform_driver_probe(&ux500_driver, ux500_probe);
 
209
}
 
210
subsys_initcall(ux500_init);
 
211
 
 
212
static void __exit ux500_exit(void)
 
213
{
 
214
        platform_driver_unregister(&ux500_driver);
 
215
}
 
216
module_exit(ux500_exit);