1 /*
2  * EHCI HCD glue for Cavium Octeon II SOCs.
3  *
4  * Loosely based on ehci-au1xxx.c
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file "COPYING" in the main directory of this archive
8  * for more details.
9  *
10  * Copyright (C) 2010 Cavium Networks
11  *
12  */
13 
14 #include <linux/platform_device.h>
15 
16 #include <asm/octeon/octeon.h>
17 #include <asm/octeon/cvmx-uctlx-defs.h>
18 
19 #define OCTEON_EHCI_HCD_NAME "octeon-ehci"
20 
21 /* Common clock init code.  */
22 void octeon2_usb_clocks_start(void);
23 void octeon2_usb_clocks_stop(void);
24 
ehci_octeon_start(void)25 static void ehci_octeon_start(void)
26 {
27 	union cvmx_uctlx_ehci_ctl ehci_ctl;
28 
29 	octeon2_usb_clocks_start();
30 
31 	ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
32 	/* Use 64-bit addressing. */
33 	ehci_ctl.s.ehci_64b_addr_en = 1;
34 	ehci_ctl.s.l2c_addr_msb = 0;
35 	ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
36 	ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
37 	cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64);
38 }
39 
ehci_octeon_stop(void)40 static void ehci_octeon_stop(void)
41 {
42 	octeon2_usb_clocks_stop();
43 }
44 
45 static const struct hc_driver ehci_octeon_hc_driver = {
46 	.description		= hcd_name,
47 	.product_desc		= "Octeon EHCI",
48 	.hcd_priv_size		= sizeof(struct ehci_hcd),
49 
50 	/*
51 	 * generic hardware linkage
52 	 */
53 	.irq			= ehci_irq,
54 	.flags			= HCD_MEMORY | HCD_USB2,
55 
56 	/*
57 	 * basic lifecycle operations
58 	 */
59 	.reset			= ehci_init,
60 	.start			= ehci_run,
61 	.stop			= ehci_stop,
62 	.shutdown		= ehci_shutdown,
63 
64 	/*
65 	 * managing i/o requests and associated device resources
66 	 */
67 	.urb_enqueue		= ehci_urb_enqueue,
68 	.urb_dequeue		= ehci_urb_dequeue,
69 	.endpoint_disable	= ehci_endpoint_disable,
70 	.endpoint_reset		= ehci_endpoint_reset,
71 
72 	/*
73 	 * scheduling support
74 	 */
75 	.get_frame_number	= ehci_get_frame,
76 
77 	/*
78 	 * root hub support
79 	 */
80 	.hub_status_data	= ehci_hub_status_data,
81 	.hub_control		= ehci_hub_control,
82 	.bus_suspend		= ehci_bus_suspend,
83 	.bus_resume		= ehci_bus_resume,
84 	.relinquish_port	= ehci_relinquish_port,
85 	.port_handed_over	= ehci_port_handed_over,
86 
87 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
88 };
89 
90 static u64 ehci_octeon_dma_mask = DMA_BIT_MASK(64);
91 
ehci_octeon_drv_probe(struct platform_device * pdev)92 static int ehci_octeon_drv_probe(struct platform_device *pdev)
93 {
94 	struct usb_hcd *hcd;
95 	struct ehci_hcd *ehci;
96 	struct resource *res_mem;
97 	int irq;
98 	int ret;
99 
100 	if (usb_disabled())
101 		return -ENODEV;
102 
103 	irq = platform_get_irq(pdev, 0);
104 	if (irq < 0) {
105 		dev_err(&pdev->dev, "No irq assigned\n");
106 		return -ENODEV;
107 	}
108 
109 	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
110 	if (res_mem == NULL) {
111 		dev_err(&pdev->dev, "No register space assigned\n");
112 		return -ENODEV;
113 	}
114 
115 	/*
116 	 * We can DMA from anywhere. But the descriptors must be in
117 	 * the lower 4GB.
118 	 */
119 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
120 	pdev->dev.dma_mask = &ehci_octeon_dma_mask;
121 
122 	hcd = usb_create_hcd(&ehci_octeon_hc_driver, &pdev->dev, "octeon");
123 	if (!hcd)
124 		return -ENOMEM;
125 
126 	hcd->rsrc_start = res_mem->start;
127 	hcd->rsrc_len = res_mem->end - res_mem->start + 1;
128 
129 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
130 				OCTEON_EHCI_HCD_NAME)) {
131 		dev_err(&pdev->dev, "request_mem_region failed\n");
132 		ret = -EBUSY;
133 		goto err1;
134 	}
135 
136 	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
137 	if (!hcd->regs) {
138 		dev_err(&pdev->dev, "ioremap failed\n");
139 		ret = -ENOMEM;
140 		goto err2;
141 	}
142 
143 	ehci_octeon_start();
144 
145 	ehci = hcd_to_ehci(hcd);
146 
147 	/* Octeon EHCI matches CPU endianness. */
148 #ifdef __BIG_ENDIAN
149 	ehci->big_endian_mmio = 1;
150 #endif
151 
152 	ehci->caps = hcd->regs;
153 	ehci->regs = hcd->regs +
154 		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
155 	/* cache this readonly data; minimize chip reads */
156 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
157 
158 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
159 	if (ret) {
160 		dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
161 		goto err3;
162 	}
163 
164 	platform_set_drvdata(pdev, hcd);
165 
166 	/* root ports should always stay powered */
167 	ehci_port_power(ehci, 1);
168 
169 	return 0;
170 err3:
171 	ehci_octeon_stop();
172 
173 	iounmap(hcd->regs);
174 err2:
175 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
176 err1:
177 	usb_put_hcd(hcd);
178 	return ret;
179 }
180 
ehci_octeon_drv_remove(struct platform_device * pdev)181 static int ehci_octeon_drv_remove(struct platform_device *pdev)
182 {
183 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
184 
185 	usb_remove_hcd(hcd);
186 
187 	ehci_octeon_stop();
188 	iounmap(hcd->regs);
189 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
190 	usb_put_hcd(hcd);
191 
192 	platform_set_drvdata(pdev, NULL);
193 
194 	return 0;
195 }
196 
197 static struct platform_driver ehci_octeon_driver = {
198 	.probe		= ehci_octeon_drv_probe,
199 	.remove		= ehci_octeon_drv_remove,
200 	.shutdown	= usb_hcd_platform_shutdown,
201 	.driver = {
202 		.name	= OCTEON_EHCI_HCD_NAME,
203 		.owner	= THIS_MODULE,
204 	}
205 };
206 
207 MODULE_ALIAS("platform:" OCTEON_EHCI_HCD_NAME);
208