1da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak/*
2da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * EHCI HCD (Host Controller Driver) for USB.
3da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak *
4da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
5da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * Tested on AMCC PPC 440EPx
6da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak *
7da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * Valentine Barshak <vbarshak@ru.mvista.com>
8da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak *
9da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
10da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
11da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak *
12da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * This file is licenced under the GPL.
13da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak */
14da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
15da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak#include <linux/signal.h>
16da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
17da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak#include <linux/of.h>
18da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak#include <linux/of_platform.h>
19da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
20da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak/* called during probe() after chip reset completes */
21da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshakstatic int ehci_ppc_of_setup(struct usb_hcd *hcd)
22da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak{
23da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
24da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	int		retval;
25da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
26da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	retval = ehci_halt(ehci);
27da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (retval)
28da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		return retval;
29da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
30da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	retval = ehci_init(hcd);
31da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (retval)
32da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		return retval;
33da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
34da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	ehci->sbrn = 0x20;
35da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	return ehci_reset(ehci);
36da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak}
37da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
38da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
39da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshakstatic const struct hc_driver ehci_ppc_of_hc_driver = {
40da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.description		= hcd_name,
41da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.product_desc		= "OF EHCI",
42da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.hcd_priv_size		= sizeof(struct ehci_hcd),
43da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
44da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	/*
45da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 * generic hardware linkage
46da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 */
47da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.irq			= ehci_irq,
48da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.flags			= HCD_MEMORY | HCD_USB2,
49da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
50da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	/*
51da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 * basic lifecycle operations
52da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 */
53da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.reset			= ehci_ppc_of_setup,
54da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.start			= ehci_run,
55da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.stop			= ehci_stop,
56da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.shutdown		= ehci_shutdown,
57da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
58da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	/*
59da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 * managing i/o requests and associated device resources
60da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 */
61da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.urb_enqueue		= ehci_urb_enqueue,
62da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.urb_dequeue		= ehci_urb_dequeue,
63da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.endpoint_disable	= ehci_endpoint_disable,
64b18ffd49e86102a9ed0a1cc83fdafe3891e844e5Alan Stern	.endpoint_reset		= ehci_endpoint_reset,
65da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
66da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	/*
67da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 * scheduling support
68da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 */
69da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.get_frame_number	= ehci_get_frame,
70da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
71da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	/*
72da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 * root hub support
73da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	 */
74da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.hub_status_data	= ehci_hub_status_data,
75da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.hub_control		= ehci_hub_control,
76da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak#ifdef	CONFIG_PM
77da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.bus_suspend		= ehci_bus_suspend,
78da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.bus_resume		= ehci_bus_resume,
79da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak#endif
80a8e5177583e975fc1f7c621c93956f494df9b979Alan Stern	.relinquish_port	= ehci_relinquish_port,
813a31155cfff0935e4b178f3dca733d2d60d2eb8dAlan Stern	.port_handed_over	= ehci_port_handed_over,
82914b701280a76f96890ad63eb0fa99bf204b961cAlan Stern
83914b701280a76f96890ad63eb0fa99bf204b961cAlan Stern	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
84da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak};
85da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
86da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
87da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak/*
88da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * 440EPx Errata USBH_3
89da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
90da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak */
91da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak#define PPC440EPX_EHCI0_INSREG_BMT	(0x1 << 0)
92da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshakstatic int __devinit
93da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshakppc44x_enable_bmt(struct device_node *dn)
94da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak{
95da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	__iomem u32 *insreg_virt;
96da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
97da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	insreg_virt = of_iomap(dn, 1);
98da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (!insreg_virt)
99da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		return  -EINVAL;
100da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
101da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
102da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
103da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	iounmap(insreg_virt);
104da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	return 0;
105da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak}
106da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
107da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
108d35fb6417655ebf6de93e2135dc386c3c470f545Grant Likelystatic int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
109da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak{
11061c7a080a5a061c976988fd4b844dfb468dda255Grant Likely	struct device_node *dn = op->dev.of_node;
111da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	struct usb_hcd *hcd;
112796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	struct ehci_hcd	*ehci = NULL;
113da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	struct resource res;
114da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	int irq;
115da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	int rv;
116da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
117796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	struct device_node *np;
118796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug
119da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (usb_disabled())
120da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		return -ENODEV;
121da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
122da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
123da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
124da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	rv = of_address_to_resource(dn, 0, &res);
125da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (rv)
126da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		return rv;
127da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
128da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
129da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (!hcd)
130da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		return -ENOMEM;
131da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
132da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	hcd->rsrc_start = res.start;
13328f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches	hcd->rsrc_len = resource_size(&res);
134da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
135da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
136f45ba776da4fe6c9a9eddd42b0fd5d1f15c260f3Joe Perches		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
137da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		rv = -EBUSY;
138da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		goto err_rmr;
139da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	}
140da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
141da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	irq = irq_of_parse_and_map(dn, 0);
142da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (irq == NO_IRQ) {
143f45ba776da4fe6c9a9eddd42b0fd5d1f15c260f3Joe Perches		printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
144da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		rv = -EBUSY;
145da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		goto err_irq;
146da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	}
147da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
148da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
149da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (!hcd->regs) {
150f45ba776da4fe6c9a9eddd42b0fd5d1f15c260f3Joe Perches		printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
151da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		rv = -ENOMEM;
152da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		goto err_ioremap;
153da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	}
154da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
155da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	ehci = hcd_to_ehci(hcd);
156796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
157796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	if (np != NULL) {
158796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		/* claim we really affected by usb23 erratum */
159796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		if (!of_address_to_resource(np, 0, &res))
160796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug			ehci->ohci_hcctrl_reg = ioremap(res.start +
161796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug					OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN);
162796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		else
163f45ba776da4fe6c9a9eddd42b0fd5d1f15c260f3Joe Perches			pr_debug("%s: no ohci offset in fdt\n", __FILE__);
164796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		if (!ehci->ohci_hcctrl_reg) {
165f45ba776da4fe6c9a9eddd42b0fd5d1f15c260f3Joe Perches			pr_debug("%s: ioremap for ohci hcctrl failed\n", __FILE__);
166796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		} else {
167796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug			ehci->has_amcc_usb23 = 1;
168796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		}
169796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	}
170da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
171da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (of_get_property(dn, "big-endian", NULL)) {
172da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		ehci->big_endian_mmio = 1;
173da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		ehci->big_endian_desc = 1;
174da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	}
175da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (of_get_property(dn, "big-endian-regs", NULL))
176da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		ehci->big_endian_mmio = 1;
177da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (of_get_property(dn, "big-endian-desc", NULL))
178da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		ehci->big_endian_desc = 1;
179da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
180da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	ehci->caps = hcd->regs;
181da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	ehci->regs = hcd->regs +
182c430131a02d677aa708f56342c1565edfdacb3c0Jan Andersson		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
183da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
184da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	/* cache this readonly data; minimize chip reads */
185da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
186da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
187da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
188da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		rv = ppc44x_enable_bmt(dn);
189da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
190da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak				rv ? "NOT ": "");
191da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	}
192da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
193da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	rv = usb_add_hcd(hcd, irq, 0);
19408a3b3b1c2e622e378d9086aee9e2e42ce37591dDan Carpenter	if (rv)
19508a3b3b1c2e622e378d9086aee9e2e42ce37591dDan Carpenter		goto err_ehci;
19608a3b3b1c2e622e378d9086aee9e2e42ce37591dDan Carpenter
19708a3b3b1c2e622e378d9086aee9e2e42ce37591dDan Carpenter	return 0;
198da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
19908a3b3b1c2e622e378d9086aee9e2e42ce37591dDan Carpentererr_ehci:
20008a3b3b1c2e622e378d9086aee9e2e42ce37591dDan Carpenter	if (ehci->has_amcc_usb23)
20108a3b3b1c2e622e378d9086aee9e2e42ce37591dDan Carpenter		iounmap(ehci->ohci_hcctrl_reg);
202da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	iounmap(hcd->regs);
203da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshakerr_ioremap:
204da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	irq_dispose_mapping(irq);
205da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshakerr_irq:
206da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
207da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshakerr_rmr:
208da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	usb_put_hcd(hcd);
209da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
210da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	return rv;
211da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak}
212da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
213da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
2142dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int ehci_hcd_ppc_of_remove(struct platform_device *op)
215da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak{
216da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
217796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
218796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug
219796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	struct device_node *np;
220796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	struct resource res;
221796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug
222da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	dev_set_drvdata(&op->dev, NULL);
223da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
224da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
225da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
226da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	usb_remove_hcd(hcd);
227da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
228da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	iounmap(hcd->regs);
229da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	irq_dispose_mapping(hcd->irq);
230da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
231da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
232796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	/* use request_mem_region to test if the ohci driver is loaded.  if so
233796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	 * ensure the ohci core is operational.
234796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	 */
235796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	if (ehci->has_amcc_usb23) {
236796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
237796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		if (np != NULL) {
238796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug			if (!of_address_to_resource(np, 0, &res))
239796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug				if (!request_mem_region(res.start,
240796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug							    0x4, hcd_name))
241796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug					set_ohci_hcfs(ehci, 1);
242796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug				else
243796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug					release_mem_region(res.start, 0x4);
244796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug			else
245f45ba776da4fe6c9a9eddd42b0fd5d1f15c260f3Joe Perches				pr_debug("%s: no ohci offset in fdt\n", __FILE__);
246796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug			of_node_put(np);
247796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		}
248796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug
249796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug		iounmap(ehci->ohci_hcctrl_reg);
250796bcae7361c28cf825780f6f1aac9dd3411394eVitaly Bordug	}
251da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	usb_put_hcd(hcd);
252da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
253da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	return 0;
254da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak}
255da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
256da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
257d35fb6417655ebf6de93e2135dc386c3c470f545Grant Likelystatic void ehci_hcd_ppc_of_shutdown(struct platform_device *op)
258da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak{
259da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
260da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
261da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	if (hcd->driver->shutdown)
262da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		hcd->driver->shutdown(hcd);
263da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak}
264da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
265da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
266c4386ad07c318ae6188190e63b517ecc5ee3c883Németh Mártonstatic const struct of_device_id ehci_hcd_ppc_of_match[] = {
267da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	{
268da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak		.compatible = "usb-ehci",
269da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	},
270da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	{},
271da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak};
272da0e8fb00b862aa10265f0c64930b432cd44420bValentine BarshakMODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
273da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
274da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak
275d35fb6417655ebf6de93e2135dc386c3c470f545Grant Likelystatic struct platform_driver ehci_hcd_ppc_of_driver = {
276da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.probe		= ehci_hcd_ppc_of_probe,
277da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.remove		= ehci_hcd_ppc_of_remove,
278da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	.shutdown	= ehci_hcd_ppc_of_shutdown,
2794018294b53d1dae026880e45f174c1cc63b5d435Grant Likely	.driver = {
2804018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.name = "ppc-of-ehci",
2814018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.owner = THIS_MODULE,
2824018294b53d1dae026880e45f174c1cc63b5d435Grant Likely		.of_match_table = ehci_hcd_ppc_of_match,
283da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak	},
284da0e8fb00b862aa10265f0c64930b432cd44420bValentine Barshak};
285