1c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch/*
2c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Sonics Silicon Backplane
3c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Broadcom USB-core OHCI driver
4c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch *
5eb032b9837a958e21ca000358a5bde5e17192ddbMichael Buesch * Copyright 2007 Michael Buesch <m@bues.ch>
6c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch *
7c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Derived from the OHCI-PCI driver
8c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Copyright 1999 Roman Weissgaerber
9c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Copyright 2000-2002 David Brownell
10c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Copyright 1999 Linus Torvalds
11c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Copyright 1999 Gregory P. Smith
12c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch *
13c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Derived from the USBcore related parts of Broadcom-SB
14c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Copyright 2005 Broadcom Corporation
15c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch *
16c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch * Licensed under the GNU/GPL. See COPYING for details.
17c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch */
18c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch#include <linux/ssb/ssb.h>
19c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
20c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
21c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch#define SSB_OHCI_TMSLOW_HOSTMODE	(1 << 29)
22c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
23c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstruct ssb_ohci_device {
24c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct ohci_hcd ohci; /* _must_ be at the beginning. */
25c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
26c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	u32 enable_flags;
27c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch};
28c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
29c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic inline
30c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstruct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd)
31c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
32c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	return (struct ssb_ohci_device *)(hcd->hcd_priv);
33c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
34c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
35c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
36c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic int ssb_ohci_reset(struct usb_hcd *hcd)
37c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
38c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
39c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct ohci_hcd *ohci = &ohcidev->ohci;
40c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	int err;
41c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
42c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ohci_hcd_init(ohci);
43c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	err = ohci_init(ohci);
44c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
45c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	return err;
46c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
47c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
48c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic int ssb_ohci_start(struct usb_hcd *hcd)
49c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
50c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
51c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct ohci_hcd *ohci = &ohcidev->ohci;
52c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	int err;
53c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
54c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	err = ohci_run(ohci);
55c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	if (err < 0) {
56c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch		ohci_err(ohci, "can't start\n");
57c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch		ohci_stop(hcd);
58c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	}
59c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
60c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	return err;
61c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
62c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
63c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic const struct hc_driver ssb_ohci_hc_driver = {
64c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.description		= "ssb-usb-ohci",
65c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.product_desc		= "SSB OHCI Controller",
66c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.hcd_priv_size		= sizeof(struct ssb_ohci_device),
67c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
68c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.irq			= ohci_irq,
69c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.flags			= HCD_MEMORY | HCD_USB11,
70c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
71c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.reset			= ssb_ohci_reset,
72c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.start			= ssb_ohci_start,
73c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.stop			= ohci_stop,
74c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.shutdown		= ohci_shutdown,
75c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
76c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.urb_enqueue		= ohci_urb_enqueue,
77c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.urb_dequeue		= ohci_urb_dequeue,
78c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.endpoint_disable	= ohci_endpoint_disable,
79c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
80c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.get_frame_number	= ohci_get_frame,
81c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
82c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.hub_status_data	= ohci_hub_status_data,
83c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.hub_control		= ohci_hub_control,
844735b37cf434175c2b7b36b3b68f1e60e8ec8527Al Viro#ifdef	CONFIG_PM
85c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.bus_suspend		= ohci_bus_suspend,
86c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.bus_resume		= ohci_bus_resume,
874735b37cf434175c2b7b36b3b68f1e60e8ec8527Al Viro#endif
88c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
89c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.start_port_reset	= ohci_start_port_reset,
90c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch};
91c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
92c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic void ssb_ohci_detach(struct ssb_device *dev)
93c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
94c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct usb_hcd *hcd = ssb_get_drvdata(dev);
95c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
96f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens	if (hcd->driver->shutdown)
97f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		hcd->driver->shutdown(hcd);
98c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	usb_remove_hcd(hcd);
99c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	iounmap(hcd->regs);
100f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
101c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	usb_put_hcd(hcd);
102c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ssb_device_disable(dev, 0);
103c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
104c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
105c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic int ssb_ohci_attach(struct ssb_device *dev)
106c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
107c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct ssb_ohci_device *ohcidev;
108c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct usb_hcd *hcd;
109c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	int err = -ENOMEM;
110c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	u32 tmp, flags = 0;
111c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
112f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens	if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
113f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens	    dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
114f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		return -EOPNOTSUPP;
115c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
116f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
117f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		/* Put the device into host-mode. */
118f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		flags |= SSB_OHCI_TMSLOW_HOSTMODE;
119f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		ssb_device_enable(dev, flags);
120f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens	} else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
121f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		/*
122f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		 * USB 2.0 special considerations:
123f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		 *
124f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		 * In addition to the standard SSB reset sequence, the Host
125f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		 * Control Register must be programmed to bring the USB core
126f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		 * and various phy components out of reset.
127f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		 */
128f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		ssb_device_enable(dev, 0);
129f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		ssb_write32(dev, 0x200, 0x7ff);
130f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens
131f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		/* Change Flush control reg */
132f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		tmp = ssb_read32(dev, 0x400);
133f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		tmp &= ~8;
134f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		ssb_write32(dev, 0x400, tmp);
135f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		tmp = ssb_read32(dev, 0x400);
136f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens
137f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		/* Change Shim control reg */
138f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		tmp = ssb_read32(dev, 0x304);
139f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		tmp &= ~0x100;
140f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		ssb_write32(dev, 0x304, tmp);
141f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		tmp = ssb_read32(dev, 0x304);
142f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens
143f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		udelay(1);
144f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens
145f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		/* Work around for 5354 failures */
146f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
147f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens			/* Change syn01 reg */
148f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens			tmp = 0x00fe00fe;
149f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens			ssb_write32(dev, 0x894, tmp);
150f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens
151f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens			/* Change syn03 reg */
152f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens			tmp = ssb_read32(dev, 0x89c);
153f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens			tmp |= 0x1;
154f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens			ssb_write32(dev, 0x89c, tmp);
155f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		}
156f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens	} else
157f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens		ssb_device_enable(dev, 0);
158c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
159c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
1607071a3ce0ca058ad2a9e3e8c33f30fb0bce62005Kay Sievers			dev_name(dev->dev));
161c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	if (!hcd)
162c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch		goto err_dev_disable;
163c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ohcidev = hcd_to_ssb_ohci(hcd);
164c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ohcidev->enable_flags = flags;
165c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
166c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	tmp = ssb_read32(dev, SSB_ADMATCH0);
167c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	hcd->rsrc_start = ssb_admatch_base(tmp);
168c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	hcd->rsrc_len = ssb_admatch_size(tmp);
169c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
170c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	if (!hcd->regs)
171c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch		goto err_put_hcd;
172b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang	err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
173c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	if (err)
174c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch		goto err_iounmap;
175c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
176c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ssb_set_drvdata(dev, hcd);
177c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
178c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	return err;
179c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
180c604e851486eabcbeb73e984279d436ce121fd5dMichael Buescherr_iounmap:
181c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	iounmap(hcd->regs);
182c604e851486eabcbeb73e984279d436ce121fd5dMichael Buescherr_put_hcd:
183c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	usb_put_hcd(hcd);
184c604e851486eabcbeb73e984279d436ce121fd5dMichael Buescherr_dev_disable:
185c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ssb_device_disable(dev, flags);
186c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	return err;
187c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
188c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
189c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic int ssb_ohci_probe(struct ssb_device *dev,
190c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch		const struct ssb_device_id *id)
191c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
192c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	int err;
193c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	u16 chipid_top;
194c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
195c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	/* USBcores are only connected on embedded devices. */
196c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	chipid_top = (dev->bus->chip_id & 0xFF00);
197c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	if (chipid_top != 0x4700 && chipid_top != 0x5300)
198c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch		return -ENODEV;
199c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
200c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	/* TODO: Probably need checks here; is the core connected? */
201c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
202c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	if (usb_disabled())
203c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch		return -ENODEV;
204c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
205c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	/* We currently always attach SSB_DEV_USB11_HOSTDEV
206c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	 * as HOST OHCI. If we want to attach it as Client device,
207c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	 * we must branch here and call into the (yet to
208c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	 * be written) Client mode driver. Same for remove(). */
209c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
210c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	err = ssb_ohci_attach(dev);
211c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
212c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	return err;
213c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
214c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
215c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic void ssb_ohci_remove(struct ssb_device *dev)
216c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
217c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ssb_ohci_detach(dev);
218c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
219c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
220c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch#ifdef CONFIG_PM
221c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
222c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state)
223c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
224c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ssb_device_disable(dev, 0);
225c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
226c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	return 0;
227c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
228c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
229c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic int ssb_ohci_resume(struct ssb_device *dev)
230c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch{
231c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct usb_hcd *hcd = ssb_get_drvdata(dev);
232c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
233c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
234c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	ssb_device_enable(dev, ohcidev->enable_flags);
235c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
23643bbb7e015c4380064796c5868b536437b165615Alan Stern	ohci_finish_controller_resume(hcd);
237c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	return 0;
238c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch}
239c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
240c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch#else /* !CONFIG_PM */
241c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch#define ssb_ohci_suspend	NULL
242c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch#define ssb_ohci_resume	NULL
243c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch#endif /* CONFIG_PM */
244c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
245c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic const struct ssb_device_id ssb_ohci_table[] = {
246c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
247c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
248f2402f21caba2aceebbf637458b777300669020fHauke Mehrtens	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
249c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	SSB_DEVTABLE_END
250c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch};
251c604e851486eabcbeb73e984279d436ce121fd5dMichael BueschMODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
252c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch
253c604e851486eabcbeb73e984279d436ce121fd5dMichael Bueschstatic struct ssb_driver ssb_ohci_driver = {
254c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.name		= KBUILD_MODNAME,
255c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.id_table	= ssb_ohci_table,
256c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.probe		= ssb_ohci_probe,
257c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.remove		= ssb_ohci_remove,
258c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.suspend	= ssb_ohci_suspend,
259c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch	.resume		= ssb_ohci_resume,
260c604e851486eabcbeb73e984279d436ce121fd5dMichael Buesch};
261