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 #include <linux/of_platform.h>
19 /* interface and function clocks */
20 static struct clk
*iclk
, *fclk
;
23 /*-------------------------------------------------------------------------*/
25 static void atmel_start_clock(void)
32 static void atmel_stop_clock(void)
39 static void atmel_start_ehci(struct platform_device
*pdev
)
41 dev_dbg(&pdev
->dev
, "start\n");
45 static void atmel_stop_ehci(struct platform_device
*pdev
)
47 dev_dbg(&pdev
->dev
, "stop\n");
51 /*-------------------------------------------------------------------------*/
53 static int ehci_atmel_setup(struct usb_hcd
*hcd
)
55 struct ehci_hcd
*ehci
= hcd_to_ehci(hcd
);
58 /* registers start at offset 0x0 */
59 ehci
->caps
= hcd
->regs
;
61 retval
= ehci_setup(hcd
);
65 ehci_port_power(ehci
, 0);
70 static const struct hc_driver ehci_atmel_hc_driver
= {
71 .description
= hcd_name
,
72 .product_desc
= "Atmel EHCI UHP HS",
73 .hcd_priv_size
= sizeof(struct ehci_hcd
),
75 /* generic hardware linkage */
77 .flags
= HCD_MEMORY
| HCD_USB2
,
79 /* basic lifecycle operations */
80 .reset
= ehci_atmel_setup
,
83 .shutdown
= ehci_shutdown
,
85 /* managing i/o requests and associated device resources */
86 .urb_enqueue
= ehci_urb_enqueue
,
87 .urb_dequeue
= ehci_urb_dequeue
,
88 .endpoint_disable
= ehci_endpoint_disable
,
89 .endpoint_reset
= ehci_endpoint_reset
,
91 /* scheduling support */
92 .get_frame_number
= ehci_get_frame
,
94 /* root hub support */
95 .hub_status_data
= ehci_hub_status_data
,
96 .hub_control
= ehci_hub_control
,
97 .bus_suspend
= ehci_bus_suspend
,
98 .bus_resume
= ehci_bus_resume
,
99 .relinquish_port
= ehci_relinquish_port
,
100 .port_handed_over
= ehci_port_handed_over
,
102 .clear_tt_buffer_complete
= ehci_clear_tt_buffer_complete
,
105 static u64 at91_ehci_dma_mask
= DMA_BIT_MASK(32);
107 static int __devinit
ehci_atmel_drv_probe(struct platform_device
*pdev
)
110 const struct hc_driver
*driver
= &ehci_atmel_hc_driver
;
111 struct resource
*res
;
118 pr_debug("Initializing Atmel-SoC USB Host Controller\n");
120 irq
= platform_get_irq(pdev
, 0);
123 "Found HC with no IRQ. Check %s setup!\n",
124 dev_name(&pdev
->dev
));
126 goto fail_create_hcd
;
129 /* Right now device-tree probed devices don't get dma_mask set.
130 * Since shared usb code relies on it, set it here for now.
131 * Once we have dma capability bindings this can go away.
133 if (!pdev
->dev
.dma_mask
)
134 pdev
->dev
.dma_mask
= &at91_ehci_dma_mask
;
136 hcd
= usb_create_hcd(driver
, &pdev
->dev
, dev_name(&pdev
->dev
));
139 goto fail_create_hcd
;
142 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
145 "Found HC with no register addr. Check %s setup!\n",
146 dev_name(&pdev
->dev
));
148 goto fail_request_resource
;
150 hcd
->rsrc_start
= res
->start
;
151 hcd
->rsrc_len
= resource_size(res
);
153 hcd
->regs
= devm_request_and_ioremap(&pdev
->dev
, res
);
154 if (hcd
->regs
== NULL
) {
155 dev_dbg(&pdev
->dev
, "error mapping memory\n");
157 goto fail_request_resource
;
160 iclk
= devm_clk_get(&pdev
->dev
, "ehci_clk");
162 dev_err(&pdev
->dev
, "Error getting interface clock\n");
164 goto fail_request_resource
;
166 fclk
= devm_clk_get(&pdev
->dev
, "uhpck");
168 dev_err(&pdev
->dev
, "Error getting function clock\n");
170 goto fail_request_resource
;
173 atmel_start_ehci(pdev
);
175 retval
= usb_add_hcd(hcd
, irq
, IRQF_SHARED
);
182 atmel_stop_ehci(pdev
);
183 fail_request_resource
:
186 dev_err(&pdev
->dev
, "init %s fail, %d\n",
187 dev_name(&pdev
->dev
), retval
);
192 static int __devexit
ehci_atmel_drv_remove(struct platform_device
*pdev
)
194 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
200 atmel_stop_ehci(pdev
);
207 static const struct of_device_id atmel_ehci_dt_ids
[] = {
208 { .compatible
= "atmel,at91sam9g45-ehci" },
212 MODULE_DEVICE_TABLE(of
, atmel_ehci_dt_ids
);
215 static struct platform_driver ehci_atmel_driver
= {
216 .probe
= ehci_atmel_drv_probe
,
217 .remove
= __devexit_p(ehci_atmel_drv_remove
),
218 .shutdown
= usb_hcd_platform_shutdown
,
220 .name
= "atmel-ehci",
221 .of_match_table
= of_match_ptr(atmel_ehci_dt_ids
),