xref: /openbmc/linux/drivers/usb/host/ehci-sh.c (revision c1e0774d74481fdc3082d2096a99a3aa411a71f1)
1 /*
2  * SuperH EHCI host controller driver
3  *
4  * Copyright (C) 2010  Paul Mundt
5  *
6  * Based on ohci-sh.c and ehci-atmel.c.
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11  */
12 #include <linux/platform_device.h>
13 #include <linux/clk.h>
14 
15 struct ehci_sh_priv {
16 	struct clk *iclk, *fclk;
17 	struct usb_hcd *hcd;
18 };
19 
20 static int ehci_sh_reset(struct usb_hcd *hcd)
21 {
22 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
23 	int ret;
24 
25 	ehci->caps = hcd->regs;
26 	ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci,
27 		&ehci->caps->hc_capbase));
28 
29 	dbg_hcs_params(ehci, "reset");
30 	dbg_hcc_params(ehci, "reset");
31 
32 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
33 
34 	ret = ehci_halt(ehci);
35 	if (unlikely(ret))
36 		return ret;
37 
38 	ret = ehci_init(hcd);
39 	if (unlikely(ret))
40 		return ret;
41 
42 	ehci->sbrn = 0x20;
43 
44 	ehci_reset(ehci);
45 	ehci_port_power(ehci, 0);
46 
47 	return ret;
48 }
49 
50 static const struct hc_driver ehci_sh_hc_driver = {
51 	.description			= hcd_name,
52 	.product_desc			= "SuperH EHCI",
53 	.hcd_priv_size			= sizeof(struct ehci_hcd),
54 
55 	/*
56 	 * generic hardware linkage
57 	 */
58 	.irq				= ehci_irq,
59 	.flags				= HCD_USB2 | HCD_MEMORY,
60 
61 	/*
62 	 * basic lifecycle operations
63 	 */
64 	.reset				= ehci_sh_reset,
65 	.start				= ehci_run,
66 	.stop				= ehci_stop,
67 	.shutdown			= ehci_shutdown,
68 
69 	/*
70 	 * managing i/o requests and associated device resources
71 	 */
72 	.urb_enqueue			= ehci_urb_enqueue,
73 	.urb_dequeue			= ehci_urb_dequeue,
74 	.endpoint_disable		= ehci_endpoint_disable,
75 
76 	/*
77 	 * scheduling support
78 	 */
79 	.get_frame_number		= ehci_get_frame,
80 
81 	/*
82 	 * root hub support
83 	 */
84 	.hub_status_data		= ehci_hub_status_data,
85 	.hub_control			= ehci_hub_control,
86 
87 #ifdef CONFIG_PM
88 	.bus_suspend			= ehci_bus_suspend,
89 	.bus_resume			= ehci_bus_resume,
90 #endif
91 
92 	.relinquish_port		= ehci_relinquish_port,
93 	.port_handed_over		= ehci_port_handed_over,
94 };
95 
96 static int ehci_hcd_sh_probe(struct platform_device *pdev)
97 {
98 	const struct hc_driver *driver = &ehci_sh_hc_driver;
99 	struct resource *res;
100 	struct ehci_sh_priv *priv;
101 	struct usb_hcd *hcd;
102 	int irq, ret;
103 
104 	if (usb_disabled())
105 		return -ENODEV;
106 
107 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
108 	if (!res) {
109 		dev_err(&pdev->dev,
110 			"Found HC with no register addr. Check %s setup!\n",
111 			dev_name(&pdev->dev));
112 		ret = -ENODEV;
113 		goto fail_create_hcd;
114 	}
115 
116 	irq = platform_get_irq(pdev, 0);
117 	if (irq <= 0) {
118 		dev_err(&pdev->dev,
119 			"Found HC with no IRQ. Check %s setup!\n",
120 			dev_name(&pdev->dev));
121 		ret = -ENODEV;
122 		goto fail_create_hcd;
123 	}
124 
125 	/* initialize hcd */
126 	hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev,
127 			     dev_name(&pdev->dev));
128 	if (!hcd) {
129 		ret = -ENOMEM;
130 		goto fail_create_hcd;
131 	}
132 
133 	hcd->rsrc_start = res->start;
134 	hcd->rsrc_len = resource_size(res);
135 
136 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
137 				driver->description)) {
138 		dev_dbg(&pdev->dev, "controller already in use\n");
139 		ret = -EBUSY;
140 		goto fail_request_resource;
141 	}
142 
143 	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
144 	if (hcd->regs == NULL) {
145 		dev_dbg(&pdev->dev, "error mapping memory\n");
146 		ret = -ENXIO;
147 		goto fail_ioremap;
148 	}
149 
150 	priv = kmalloc(sizeof(struct ehci_sh_priv), GFP_KERNEL);
151 	if (!priv) {
152 		dev_dbg(&pdev->dev, "error allocating priv data\n");
153 		ret = -ENOMEM;
154 		goto fail_alloc;
155 	}
156 
157 	/* These are optional, we don't care if they fail */
158 	priv->fclk = clk_get(&pdev->dev, "usb_fck");
159 	if (IS_ERR(priv->fclk))
160 		priv->fclk = NULL;
161 
162 	priv->iclk = clk_get(&pdev->dev, "usb_ick");
163 	if (IS_ERR(priv->iclk))
164 		priv->iclk = NULL;
165 
166 	clk_enable(priv->fclk);
167 	clk_enable(priv->iclk);
168 
169 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
170 	if (ret != 0) {
171 		dev_err(&pdev->dev, "Failed to add hcd");
172 		goto fail_add_hcd;
173 	}
174 
175 	priv->hcd = hcd;
176 	platform_set_drvdata(pdev, priv);
177 
178 	return ret;
179 
180 fail_add_hcd:
181 	clk_disable(priv->iclk);
182 	clk_disable(priv->fclk);
183 
184 	clk_put(priv->iclk);
185 	clk_put(priv->fclk);
186 
187 	kfree(priv);
188 fail_alloc:
189 	iounmap(hcd->regs);
190 fail_ioremap:
191 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
192 fail_request_resource:
193 	usb_put_hcd(hcd);
194 fail_create_hcd:
195 	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret);
196 
197 	return ret;
198 }
199 
200 static int __exit ehci_hcd_sh_remove(struct platform_device *pdev)
201 {
202 	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
203 	struct usb_hcd *hcd = priv->hcd;
204 
205 	usb_remove_hcd(hcd);
206 	iounmap(hcd->regs);
207 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
208 	usb_put_hcd(hcd);
209 	platform_set_drvdata(pdev, NULL);
210 
211 	clk_disable(priv->fclk);
212 	clk_disable(priv->iclk);
213 
214 	clk_put(priv->fclk);
215 	clk_put(priv->iclk);
216 
217 	kfree(priv);
218 
219 	return 0;
220 }
221 
222 static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
223 {
224 	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
225 	struct usb_hcd *hcd = priv->hcd;
226 
227 	if (hcd->driver->shutdown)
228 		hcd->driver->shutdown(hcd);
229 }
230 
231 static struct platform_driver ehci_hcd_sh_driver = {
232 	.probe		= ehci_hcd_sh_probe,
233 	.remove		= __exit_p(ehci_hcd_sh_remove),
234 	.shutdown	= ehci_hcd_sh_shutdown,
235 	.driver		= {
236 		.name	= "sh_ehci",
237 		.owner	= THIS_MODULE,
238 	},
239 };
240 
241 MODULE_ALIAS("platform:sh_ehci");
242