Date:2010-04-24 17:18:49 (12 years 5 months ago)
Author:Lars C.
Commit:4156baedc8714fe18491afc5d569401683847523
Message:Add jz4740 ohci driver

Files: drivers/usb/Kconfig (1 diff)
drivers/usb/host/ohci-hcd.c (1 diff)
drivers/usb/host/ohci-jz4740.c (1 diff)

Change Details

drivers/usb/Kconfig
4646    default y if PPC_MPC52xx
4747    # MIPS:
4848    default y if SOC_AU1X00
49    default y if SOC_JZ4740
4950    # SH:
5051    default y if CPU_SUBTYPE_SH7720
5152    default y if CPU_SUBTYPE_SH7721
drivers/usb/host/ohci-hcd.c
10901090#define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver
10911091#endif
10921092
1093#ifdef CONFIG_SOC_JZ4740
1094#include "ohci-jz4740.c"
1095#define PLATFORM_DRIVER ohci_hcd_jz4740_driver
1096#endif
1097
10931098#if !defined(PCI_DRIVER) && \
10941099    !defined(PLATFORM_DRIVER) && \
10951100    !defined(OF_PLATFORM_DRIVER) && \
drivers/usb/host/ohci-jz4740.c
1
2#include <linux/platform_device.h>
3#include <linux/clk.h>
4#include <linux/regulator/consumer.h>
5
6struct jz4740_ohci_hcd {
7    struct ohci_hcd ohci_hcd;
8
9    struct regulator *vbus;
10    struct clk *clk;
11};
12
13static inline struct jz4740_ohci_hcd *hcd_to_jz4740_hcd(struct usb_hcd *hcd)
14{
15    return (struct jz4740_ohci_hcd *)(hcd->hcd_priv);
16}
17
18static int ohci_jz4740_start(struct usb_hcd *hcd)
19{
20    struct ohci_hcd *ohci = hcd_to_ohci(hcd);
21    int ret;
22
23    ret = ohci_init(ohci);
24    if (ret < 0)
25        return ret;
26
27    ohci->num_ports = 1;
28
29    ret = ohci_run(ohci);
30    if (ret < 0) {
31        dev_err(hcd->self.controller, "Can not start %s",
32            hcd->self.bus_name);
33        ohci_stop(hcd);
34        return ret;
35    }
36    return 0;
37}
38
39static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
40    u16 wIndex, char *buf, u16 wLength)
41{
42    struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
43
44    if (jz4740_ohci->vbus) {
45        switch (typeReq) {
46        case SetHubFeature:
47            if (wValue == USB_PORT_FEAT_POWER)
48                regulator_enable(jz4740_ohci->vbus);
49            break;
50        case ClearHubFeature:
51            if (wValue == USB_PORT_FEAT_POWER)
52                regulator_disable(jz4740_ohci->vbus);
53            break;
54        }
55    }
56    return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
57}
58
59
60static const struct hc_driver ohci_jz4740_hc_driver = {
61    .description = hcd_name,
62    .product_desc = "JZ4740 OHCI",
63    .hcd_priv_size = sizeof(struct jz4740_ohci_hcd),
64
65    /*
66     * generic hardware linkage
67     */
68    .irq = ohci_irq,
69    .flags = HCD_USB11 | HCD_MEMORY,
70
71    /*
72     * basic lifecycle operations
73     */
74    .start = ohci_jz4740_start,
75    .stop = ohci_stop,
76    .shutdown = ohci_shutdown,
77
78    /*
79     * managing i/o requests and associated device resources
80     */
81    .urb_enqueue = ohci_urb_enqueue,
82    .urb_dequeue = ohci_urb_dequeue,
83    .endpoint_disable = ohci_endpoint_disable,
84
85    /*
86     * scheduling support
87     */
88    .get_frame_number = ohci_get_frame,
89
90    /*
91     * root hub support
92     */
93    .hub_status_data = ohci_hub_status_data,
94    .hub_control = ohci_jz4740_hub_control,
95#ifdef CONFIG_PM
96    .bus_suspend = ohci_bus_suspend,
97    .bus_resume = ohci_bus_resume,
98#endif
99    .start_port_reset = ohci_start_port_reset,
100};
101
102
103static __devinit int jz4740_ohci_probe(struct platform_device *pdev)
104{
105    int ret;
106    struct usb_hcd *hcd;
107    struct jz4740_ohci_hcd *jz4740_ohci;
108    struct resource *res;
109    int irq;
110
111    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
112
113    if (!res) {
114        dev_err(&pdev->dev, "Failed to get platform resource\n");
115        return -ENOENT;
116    }
117
118    irq = platform_get_irq(pdev, 0);
119    if (irq < 0) {
120        dev_err(&pdev->dev, "Failed to get platform irq\n");
121        return irq;
122    }
123
124    hcd = usb_create_hcd(&ohci_jz4740_hc_driver, &pdev->dev, "jz4740");
125    if (!hcd) {
126        dev_err(&pdev->dev, "Failed to create hcd.\n");
127        return -ENOMEM;
128    }
129
130    jz4740_ohci = hcd_to_jz4740_hcd(hcd);
131
132    res = request_mem_region(res->start, resource_size(res), hcd_name);
133
134    if (!res) {
135        dev_err(&pdev->dev, "Failed to request mem region.\n");
136        ret = -EBUSY;
137        goto err_free;
138    }
139
140    hcd->rsrc_start = res->start;
141    hcd->rsrc_len = resource_size(res);
142    hcd->regs = ioremap(res->start, resource_size(res));
143
144    if (!hcd->regs) {
145        dev_err(&pdev->dev, "Failed to ioremap registers.\n");
146        ret = -EBUSY;
147        goto err_release_mem;
148    }
149
150    jz4740_ohci->clk = clk_get(&pdev->dev, "uhc");
151    if (IS_ERR(jz4740_ohci->clk)) {
152        ret = PTR_ERR(jz4740_ohci->clk);
153        dev_err(&pdev->dev, "Failed to get clock: %d\n", ret);
154        goto err_iounmap;
155    }
156
157    jz4740_ohci->vbus = regulator_get_exclusive(&pdev->dev, "vbus");
158    if (IS_ERR(jz4740_ohci->vbus))
159        jz4740_ohci->vbus = NULL;
160
161
162    clk_set_rate(jz4740_ohci->clk, 48000000);
163    clk_enable(jz4740_ohci->clk);
164    if (jz4740_ohci->vbus)
165        regulator_enable(jz4740_ohci->vbus);
166
167    platform_set_drvdata(pdev, hcd);
168
169    ohci_hcd_init(hcd_to_ohci(hcd));
170
171    ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
172    if (ret) {
173        dev_err(&pdev->dev, "Failed to add hcd: %d\n", ret);
174        goto err_disable;
175    }
176
177    return 0;
178
179err_disable:
180    platform_set_drvdata(pdev, NULL);
181    if (jz4740_ohci->vbus) {
182        regulator_disable(jz4740_ohci->vbus);
183        regulator_put(jz4740_ohci->vbus);
184    }
185    clk_disable(jz4740_ohci->clk);
186
187    clk_put(jz4740_ohci->clk);
188err_iounmap:
189    iounmap(hcd->regs);
190err_release_mem:
191    release_mem_region(res->start, resource_size(res));
192err_free:
193    usb_put_hcd(hcd);
194
195    return ret;
196}
197
198static __devexit int jz4740_ohci_remove(struct platform_device *pdev)
199{
200    struct usb_hcd *hcd = platform_get_drvdata(pdev);
201    struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd);
202
203    usb_remove_hcd(hcd);
204
205    platform_set_drvdata(pdev, NULL);
206
207    if (jz4740_ohci->vbus) {
208        regulator_disable(jz4740_ohci->vbus);
209        regulator_put(jz4740_ohci->vbus);
210    }
211
212    clk_disable(jz4740_ohci->clk);
213    clk_put(jz4740_ohci->clk);
214
215    iounmap(hcd->regs);
216    release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
217
218    usb_put_hcd(hcd);
219
220    return 0;
221}
222
223static struct platform_driver ohci_hcd_jz4740_driver = {
224    .probe = jz4740_ohci_probe,
225    .remove = __devexit_p(jz4740_ohci_remove),
226    .driver = {
227        .name = "jz4740-ohci",
228        .owner = THIS_MODULE,
229    },
230};
231
232MODULE_ALIAS("platfrom:jz4740-ohci");

Archive Download the corresponding diff file



interactive