2 * MIPS CI13320A EHCI Host Controller driver
3 * Based on "ehci-au1xxx.c" by K.Boge <karsten.boge@amd.com>
5 * Copyright (C) 2012 MIPS Technologies, Inc.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
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 Foundation,
19 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <linux/err.h>
23 #include <linux/platform_device.h>
25 static int ehci_sead3_setup(struct usb_hcd
*hcd
)
28 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
30 ehci
->caps
= hcd
->regs
+ 0x100;
33 ehci
->big_endian_mmio
= 1;
34 ehci
->big_endian_desc
= 1;
37 ret
= ehci_setup(hcd
);
41 ehci
->need_io_watchdog
= 0;
43 /* Set burst length to 16 words. */
44 ehci_writel(ehci
, 0x1010, &ehci
->regs
->reserved1
[1]);
49 const struct hc_driver ehci_sead3_hc_driver
= {
50 .description
= hcd_name
,
51 .product_desc
= "SEAD-3 EHCI",
52 .hcd_priv_size
= sizeof(struct ehci_hcd
),
55 * generic hardware linkage
58 .flags
= HCD_MEMORY
| HCD_USB2
| HCD_BH
,
61 * basic lifecycle operations
64 .reset
= ehci_sead3_setup
,
67 .shutdown
= ehci_shutdown
,
70 * managing i/o requests and associated device resources
72 .urb_enqueue
= ehci_urb_enqueue
,
73 .urb_dequeue
= ehci_urb_dequeue
,
74 .endpoint_disable
= ehci_endpoint_disable
,
75 .endpoint_reset
= ehci_endpoint_reset
,
80 .get_frame_number
= ehci_get_frame
,
85 .hub_status_data
= ehci_hub_status_data
,
86 .hub_control
= ehci_hub_control
,
87 .bus_suspend
= ehci_bus_suspend
,
88 .bus_resume
= ehci_bus_resume
,
89 .relinquish_port
= ehci_relinquish_port
,
90 .port_handed_over
= ehci_port_handed_over
,
92 .clear_tt_buffer_complete
= ehci_clear_tt_buffer_complete
,
95 static int ehci_hcd_sead3_drv_probe(struct platform_device
*pdev
)
104 if (pdev
->resource
[1].flags
!= IORESOURCE_IRQ
) {
105 pr_debug("resource[1] is not IORESOURCE_IRQ");
108 hcd
= usb_create_hcd(&ehci_sead3_hc_driver
, &pdev
->dev
, "SEAD-3");
112 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
113 hcd
->rsrc_start
= res
->start
;
114 hcd
->rsrc_len
= resource_size(res
);
116 hcd
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
117 if (IS_ERR(hcd
->regs
)) {
118 ret
= PTR_ERR(hcd
->regs
);
122 /* Root hub has integrated TT. */
125 ret
= usb_add_hcd(hcd
, pdev
->resource
[1].start
,
128 platform_set_drvdata(pdev
, hcd
);
129 device_wakeup_enable(hcd
->self
.controller
);
138 static int ehci_hcd_sead3_drv_remove(struct platform_device
*pdev
)
140 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
149 static int ehci_hcd_sead3_drv_suspend(struct device
*dev
)
151 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
152 bool do_wakeup
= device_may_wakeup(dev
);
154 return ehci_suspend(hcd
, do_wakeup
);
157 static int ehci_hcd_sead3_drv_resume(struct device
*dev
)
159 struct usb_hcd
*hcd
= dev_get_drvdata(dev
);
161 ehci_resume(hcd
, false);
165 static const struct dev_pm_ops sead3_ehci_pmops
= {
166 .suspend
= ehci_hcd_sead3_drv_suspend
,
167 .resume
= ehci_hcd_sead3_drv_resume
,
170 #define SEAD3_EHCI_PMOPS (&sead3_ehci_pmops)
173 #define SEAD3_EHCI_PMOPS NULL
176 static struct platform_driver ehci_hcd_sead3_driver
= {
177 .probe
= ehci_hcd_sead3_drv_probe
,
178 .remove
= ehci_hcd_sead3_drv_remove
,
179 .shutdown
= usb_hcd_platform_shutdown
,
181 .name
= "sead3-ehci",
182 .owner
= THIS_MODULE
,
183 .pm
= SEAD3_EHCI_PMOPS
,
187 MODULE_ALIAS("platform:sead3-ehci");