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
);
57 /* registers start at offset 0x0 */
58 ehci
->caps
= hcd
->regs
;
60 return ehci_setup(hcd
);
63 static const struct hc_driver ehci_atmel_hc_driver
= {
64 .description
= hcd_name
,
65 .product_desc
= "Atmel EHCI UHP HS",
66 .hcd_priv_size
= sizeof(struct ehci_hcd
),
68 /* generic hardware linkage */
70 .flags
= HCD_MEMORY
| HCD_USB2
,
72 /* basic lifecycle operations */
73 .reset
= ehci_atmel_setup
,
76 .shutdown
= ehci_shutdown
,
78 /* managing i/o requests and associated device resources */
79 .urb_enqueue
= ehci_urb_enqueue
,
80 .urb_dequeue
= ehci_urb_dequeue
,
81 .endpoint_disable
= ehci_endpoint_disable
,
82 .endpoint_reset
= ehci_endpoint_reset
,
84 /* scheduling support */
85 .get_frame_number
= ehci_get_frame
,
87 /* root hub support */
88 .hub_status_data
= ehci_hub_status_data
,
89 .hub_control
= ehci_hub_control
,
90 .bus_suspend
= ehci_bus_suspend
,
91 .bus_resume
= ehci_bus_resume
,
92 .relinquish_port
= ehci_relinquish_port
,
93 .port_handed_over
= ehci_port_handed_over
,
95 .clear_tt_buffer_complete
= ehci_clear_tt_buffer_complete
,
98 static u64 at91_ehci_dma_mask
= DMA_BIT_MASK(32);
100 static int ehci_atmel_drv_probe(struct platform_device
*pdev
)
103 const struct hc_driver
*driver
= &ehci_atmel_hc_driver
;
104 struct resource
*res
;
111 pr_debug("Initializing Atmel-SoC USB Host Controller\n");
113 irq
= platform_get_irq(pdev
, 0);
116 "Found HC with no IRQ. Check %s setup!\n",
117 dev_name(&pdev
->dev
));
119 goto fail_create_hcd
;
122 /* Right now device-tree probed devices don't get dma_mask set.
123 * Since shared usb code relies on it, set it here for now.
124 * Once we have dma capability bindings this can go away.
126 if (!pdev
->dev
.dma_mask
)
127 pdev
->dev
.dma_mask
= &at91_ehci_dma_mask
;
129 hcd
= usb_create_hcd(driver
, &pdev
->dev
, dev_name(&pdev
->dev
));
132 goto fail_create_hcd
;
135 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
138 "Found HC with no register addr. Check %s setup!\n",
139 dev_name(&pdev
->dev
));
141 goto fail_request_resource
;
143 hcd
->rsrc_start
= res
->start
;
144 hcd
->rsrc_len
= resource_size(res
);
146 hcd
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
147 if (IS_ERR(hcd
->regs
)) {
148 retval
= PTR_ERR(hcd
->regs
);
149 goto fail_request_resource
;
152 iclk
= devm_clk_get(&pdev
->dev
, "ehci_clk");
154 dev_err(&pdev
->dev
, "Error getting interface clock\n");
156 goto fail_request_resource
;
158 fclk
= devm_clk_get(&pdev
->dev
, "uhpck");
160 dev_err(&pdev
->dev
, "Error getting function clock\n");
162 goto fail_request_resource
;
165 atmel_start_ehci(pdev
);
167 retval
= usb_add_hcd(hcd
, irq
, IRQF_SHARED
);
174 atmel_stop_ehci(pdev
);
175 fail_request_resource
:
178 dev_err(&pdev
->dev
, "init %s fail, %d\n",
179 dev_name(&pdev
->dev
), retval
);
184 static int ehci_atmel_drv_remove(struct platform_device
*pdev
)
186 struct usb_hcd
*hcd
= platform_get_drvdata(pdev
);
192 atmel_stop_ehci(pdev
);
199 static const struct of_device_id atmel_ehci_dt_ids
[] = {
200 { .compatible
= "atmel,at91sam9g45-ehci" },
204 MODULE_DEVICE_TABLE(of
, atmel_ehci_dt_ids
);
207 static struct platform_driver ehci_atmel_driver
= {
208 .probe
= ehci_atmel_drv_probe
,
209 .remove
= ehci_atmel_drv_remove
,
210 .shutdown
= usb_hcd_platform_shutdown
,
212 .name
= "atmel-ehci",
213 .of_match_table
= of_match_ptr(atmel_ehci_dt_ids
),