2 * Driver for EHCI UHP on Atmel chips
4 * Copyright (C) 2009 Atmel Corporation,
5 * Nicolas Ferre <nicolas.ferre@atmel.com>
7 * Based on various ehci-*.c drivers
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
14 #include <linux/clk.h>
15 #include <linux/platform_device.h>
17 /* interface and function clocks */
18 static struct clk
*iclk
, *fclk
;
21 /*-------------------------------------------------------------------------*/
23 static void atmel_start_clock(void)
30 static void atmel_stop_clock(void)
37 static void atmel_start_ehci(struct platform_device
*pdev
)
39 dev_dbg(&pdev
->dev
, "start\n");
43 static void atmel_stop_ehci(struct platform_device
*pdev
)
45 dev_dbg(&pdev
->dev
, "stop\n");
49 /*-------------------------------------------------------------------------*/
51 static int ehci_atmel_setup(struct usb_hcd
*hcd
)
53 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
56 /* registers start at offset 0x0 */
57 ehci
->caps
= hcd
->regs
;
58 ehci
->regs
= hcd
->regs
+
59 HC_LENGTH(ehci_readl(ehci
, &ehci
->caps
->hc_capbase
));
60 dbg_hcs_params(ehci
, "reset");
61 dbg_hcc_params(ehci
, "reset");
63 /* cache this readonly data; minimize chip reads */
64 ehci
->hcs_params
= ehci_readl(ehci
, &ehci
->caps
->hcs_params
);
66 retval
= ehci_halt(ehci
);
70 /* data structure init */
71 retval
= ehci_init(hcd
);
78 ehci_port_power(ehci
, 0);
83 static const struct hc_driver ehci_atmel_hc_driver
= {
84 .description
= hcd_name
,
85 .product_desc
= "Atmel EHCI UHP HS",
86 .hcd_priv_size
= sizeof(struct ehci_hcd
),
88 /* generic hardware linkage */
90 .flags
= HCD_MEMORY
| HCD_USB2
,
92 /* basic lifecycle operations */
93 .reset
= ehci_atmel_setup
,
96 .shutdown
= ehci_shutdown
,
98 /* managing i/o requests and associated device resources */
99 .urb_enqueue
= ehci_urb_enqueue
,
100 .urb_dequeue
= ehci_urb_dequeue
,
101 .endpoint_disable
= ehci_endpoint_disable
,
102 .endpoint_reset
= ehci_endpoint_reset
,
104 /* scheduling support */
105 .get_frame_number
= ehci_get_frame
,
107 /* root hub support */
108 .hub_status_data
= ehci_hub_status_data
,
109 .hub_control
= ehci_hub_control
,
110 .bus_suspend
= ehci_bus_suspend
,
111 .bus_resume
= ehci_bus_resume
,
112 .relinquish_port
= ehci_relinquish_port
,
113 .port_handed_over
= ehci_port_handed_over
,
115 .clear_tt_buffer_complete
= ehci_clear_tt_buffer_complete
,
118 static int __devinit
ehci_atmel_drv_probe(struct platform_device
*pdev
)
121 const struct hc_driver
*driver
= &ehci_atmel_hc_driver
;
122 struct resource
*res
;
129 pr_debug("Initializing Atmel-SoC USB Host Controller\n");
131 irq
= platform_get_irq(pdev
, 0);
134 "Found HC with no IRQ. Check %s setup!\n",
135 dev_name(&pdev
->dev
));
137 goto fail_create_hcd
;
140 hcd
= usb_create_hcd(driver
, &pdev
->dev
, dev_name(&pdev
->dev
));
143 goto fail_create_hcd
;
146 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
149 "Found HC with no register addr. Check %s setup!\n",
150 dev_name(&pdev
->dev
));
152 goto fail_request_resource
;
154 hcd
->rsrc_start
= res
->start
;
155 hcd
->rsrc_len
= resource_size(res
);
157 if (!request_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
,
158 driver
->description
)) {
159 dev_dbg(&pdev
->dev
, "controller already in use\n");
161 goto fail_request_resource
;
164 hcd
->regs
= ioremap_nocache(hcd
->rsrc_start
, hcd
->rsrc_len
);
165 if (hcd
->regs
== NULL
) {
166 dev_dbg(&pdev
->dev
, "error mapping memory\n");
171 iclk
= clk_get(&pdev
->dev
, "ehci_clk");
173 dev_err(&pdev
->dev
, "Error getting interface clock\n");
177 fclk
= clk_get(&pdev
->dev
, "uhpck");
179 dev_err(&pdev
->dev
, "Error getting function clock\n");
184 atmel_start_ehci(pdev
);
186 retval
= usb_add_hcd(hcd
, irq
, IRQF_SHARED
);
193 atmel_stop_ehci(pdev
);
200 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
201 fail_request_resource
:
204 dev_err(&pdev
->dev
, "init %s fail, %d\n",
205 dev_name(&pdev
->dev
), retval
);
210 static int __devexit
ehci_atmel_drv_remove(struct platform_device
*pdev
)
212 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
217 release_mem_region(hcd
->rsrc_start
, hcd
->rsrc_len
);
220 atmel_stop_ehci(pdev
);
228 static struct platform_driver ehci_atmel_driver
= {
229 .probe
= ehci_atmel_drv_probe
,
230 .remove
= __devexit_p(ehci_atmel_drv_remove
),
231 .shutdown
= usb_hcd_platform_shutdown
,
232 .driver
.name
= "atmel-ehci",