ohci-pci.c 8.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * OHCI HCD (Host Controller Driver) for USB.
 *
 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
6
 *
L
Linus Torvalds 已提交
7 8 9 10
 * [ Initialisation is based on Linus'  ]
 * [ uhci code and gregs ohci fragments ]
 * [ (C) Copyright 1999 Linus Torvalds  ]
 * [ (C) Copyright 1999 Gregory P. Smith]
11
 *
L
Linus Torvalds 已提交
12 13 14 15
 * PCI Bus Glue
 *
 * This file is licenced under the GPL.
 */
16

L
Linus Torvalds 已提交
17 18 19 20 21 22
#ifndef CONFIG_PCI
#error "This file is PCI bus glue.  CONFIG_PCI must be defined."
#endif

/*-------------------------------------------------------------------------*/

23 24 25 26 27 28
static int broken_suspend(struct usb_hcd *hcd)
{
	device_init_wakeup(&hcd->self.root_hub->dev, 0);
	return 0;
}

29 30 31
/* AMD 756, for most chips (early revs), corrupts register
 * values on read ... so enable the vendor workaround.
 */
32
static int ohci_quirk_amd756(struct usb_hcd *hcd)
L
Linus Torvalds 已提交
33 34 35
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);

36 37 38 39
	ohci->flags = OHCI_QUIRK_AMD756;
	ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");

	/* also erratum 10 (suspend/resume issues) */
40
	return broken_suspend(hcd);
L
Linus Torvalds 已提交
41 42
}

43 44 45 46
/* Apple's OHCI driver has a lot of bizarre workarounds
 * for this chip.  Evidently control and bulk lists
 * can get confused.  (B&W G3 models, and ...)
 */
47
static int ohci_quirk_opti(struct usb_hcd *hcd)
L
Linus Torvalds 已提交
48 49 50
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);

51 52 53 54 55 56 57 58 59
	ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n");

	return 0;
}

/* Check for NSC87560. We have to look at the bridge (fn1) to
 * identify the USB (fn2). This quirk might apply to more or
 * even all NSC stuff.
 */
60
static int ohci_quirk_ns(struct usb_hcd *hcd)
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
{
	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
	struct pci_dev	*b;

	b  = pci_get_slot (pdev->bus, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
	if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
	    && b->vendor == PCI_VENDOR_ID_NS) {
		struct ohci_hcd	*ohci = hcd_to_ohci (hcd);

		ohci->flags |= OHCI_QUIRK_SUPERIO;
		ohci_dbg (ohci, "Using NSC SuperIO setup\n");
	}
	pci_dev_put(b);

	return 0;
}

/* Check for Compaq's ZFMicro chipset, which needs short
 * delays before control or bulk queues get re-activated
 * in finish_unlinks()
 */
82
static int ohci_quirk_zfmicro(struct usb_hcd *hcd)
83 84 85 86 87 88 89 90 91
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);

	ohci->flags |= OHCI_QUIRK_ZFMICRO;
	ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n");

	return 0;
}

92 93 94
/* Check for Toshiba SCC OHCI which has big endian registers
 * and little endian in memory data structures
 */
95
static int ohci_quirk_toshiba_scc(struct usb_hcd *hcd)
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);

	/* That chip is only present in the southbridge of some
	 * cell based platforms which are supposed to select
	 * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO. We verify here if
	 * that was the case though.
	 */
#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
	ohci->flags |= OHCI_QUIRK_BE_MMIO;
	ohci_dbg (ohci, "enabled big endian Toshiba quirk\n");
	return 0;
#else
	ohci_err (ohci, "unsupported big endian Toshiba quirk\n");
	return -ENXIO;
#endif
}
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

/* List of quirks for OHCI */
static const struct pci_device_id ohci_pci_quirks[] = {
	{
		PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x740c),
		.driver_data = (unsigned long)ohci_quirk_amd756,
	},
	{
		PCI_DEVICE(PCI_VENDOR_ID_OPTI, 0xc861),
		.driver_data = (unsigned long)ohci_quirk_opti,
	},
	{
		PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_ANY_ID),
		.driver_data = (unsigned long)ohci_quirk_ns,
	},
	{
		PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8),
		.driver_data = (unsigned long)ohci_quirk_zfmicro,
	},
132 133 134 135
	{
		PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6),
		.driver_data = (unsigned long)ohci_quirk_toshiba_scc,
	},
136 137 138 139 140 141 142 143
	{
		/* Toshiba portege 4000 */
		.vendor		= PCI_VENDOR_ID_AL,
		.device		= 0x5237,
		.subvendor	= PCI_VENDOR_ID_TOSHIBA_2,
		.subdevice	= 0x0004,
		.driver_data	= (unsigned long) broken_suspend,
	},
144 145 146 147
	{
		PCI_DEVICE(PCI_VENDOR_ID_ITE, 0x8152),
		.driver_data = (unsigned long) broken_suspend,
	},
148 149
	/* FIXME for some of the early AMD 760 southbridges, OHCI
	 * won't work at all.  blacklist them.
150
	 */
151

152 153 154 155 156 157 158 159
	{},
};

static int ohci_pci_reset (struct usb_hcd *hcd)
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
	int ret = 0;

160
	if (hcd->self.controller) {
L
Linus Torvalds 已提交
161
		struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
162
		const struct pci_device_id *quirk_id;
L
Linus Torvalds 已提交
163

164 165 166 167 168
		quirk_id = pci_match_id(ohci_pci_quirks, pdev);
		if (quirk_id != NULL) {
			int (*quirk)(struct usb_hcd *ohci);
			quirk = (void *)quirk_id->driver_data;
			ret = quirk(hcd);
L
Linus Torvalds 已提交
169
		}
170 171 172 173 174 175 176
	}
	if (ret == 0) {
		ohci_hcd_init (ohci);
		return ohci_init (ohci);
	}
	return ret;
}
L
Linus Torvalds 已提交
177 178


179 180 181 182
static int __devinit ohci_pci_start (struct usb_hcd *hcd)
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
	int		ret;
183

184 185 186
#ifdef CONFIG_PM /* avoid warnings about unused pdev */
	if (hcd->self.controller) {
		struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
187 188 189 190 191 192 193

		/* RWC may not be set for add-in PCI cards, since boot
		 * firmware probably ignored them.  This transfers PCI
		 * PM wakeup capabilities (once the PCI layer is fixed).
		 */
		if (device_may_wakeup(&pdev->dev))
			ohci->hc_control |= OHCI_CTRL_RWC;
L
Linus Torvalds 已提交
194
	}
195
#endif /* CONFIG_PM */
L
Linus Torvalds 已提交
196

197 198
	ret = ohci_run (ohci);
	if (ret < 0) {
L
Linus Torvalds 已提交
199 200 201
		ohci_err (ohci, "can't start\n");
		ohci_stop (hcd);
	}
202
	return ret;
L
Linus Torvalds 已提交
203 204 205 206
}

#ifdef	CONFIG_PM

207
static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
L
Linus Torvalds 已提交
208
{
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
	unsigned long	flags;
	int		rc = 0;

	/* Root hub was already suspended. Disable irq emission and
	 * mark HW unaccessible, bail out if RH has been resumed. Use
	 * the spinlock to properly synchronize with possible pending
	 * RH suspend or resume activity.
	 *
	 * This is still racy as hcd->state is manipulated outside of
	 * any locks =P But that will be a different fix.
	 */
	spin_lock_irqsave (&ohci->lock, flags);
	if (hcd->state != HC_STATE_SUSPENDED) {
		rc = -EINVAL;
		goto bail;
	}
	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
	(void)ohci_readl(ohci, &ohci->regs->intrdisable);
228 229 230 231 232

	/* make sure snapshot being resumed re-enumerates everything */
	if (message.event == PM_EVENT_PRETHAW)
		ohci_usb_reset(ohci);

233 234 235 236 237
	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 bail:
	spin_unlock_irqrestore (&ohci->lock, flags);

	return rc;
L
Linus Torvalds 已提交
238 239 240 241 242
}


static int ohci_pci_resume (struct usb_hcd *hcd)
{
243
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
D
David Brownell 已提交
244 245
	usb_hcd_resume_root_hub(hcd);
	return 0;
L
Linus Torvalds 已提交
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
}

#endif	/* CONFIG_PM */


/*-------------------------------------------------------------------------*/

static const struct hc_driver ohci_pci_hc_driver = {
	.description =		hcd_name,
	.product_desc =		"OHCI Host Controller",
	.hcd_priv_size =	sizeof(struct ohci_hcd),

	/*
	 * generic hardware linkage
	 */
	.irq =			ohci_irq,
	.flags =		HCD_MEMORY | HCD_USB11,

	/*
	 * basic lifecycle operations
	 */
	.reset =		ohci_pci_reset,
	.start =		ohci_pci_start,
269
	.stop =			ohci_stop,
270
	.shutdown =		ohci_shutdown,
271

L
Linus Torvalds 已提交
272
#ifdef	CONFIG_PM
273
	/* these suspend/resume entries are for upstream PCI glue ONLY */
L
Linus Torvalds 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
	.suspend =		ohci_pci_suspend,
	.resume =		ohci_pci_resume,
#endif

	/*
	 * managing i/o requests and associated device resources
	 */
	.urb_enqueue =		ohci_urb_enqueue,
	.urb_dequeue =		ohci_urb_dequeue,
	.endpoint_disable =	ohci_endpoint_disable,

	/*
	 * scheduling support
	 */
	.get_frame_number =	ohci_get_frame,

	/*
	 * root hub support
	 */
	.hub_status_data =	ohci_hub_status_data,
	.hub_control =		ohci_hub_control,
295
	.hub_irq_enable =	ohci_rhsc_enable,
296
#ifdef	CONFIG_PM
297 298
	.bus_suspend =		ohci_bus_suspend,
	.bus_resume =		ohci_bus_resume,
L
Linus Torvalds 已提交
299 300 301 302 303 304 305 306 307
#endif
	.start_port_reset =	ohci_start_port_reset,
};

/*-------------------------------------------------------------------------*/


static const struct pci_device_id pci_ids [] = { {
	/* handle any USB OHCI controller */
308
	PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0),
L
Linus Torvalds 已提交
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
	.driver_data =	(unsigned long) &ohci_pci_hc_driver,
	}, { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE (pci, pci_ids);

/* pci driver glue; this is a "new style" PCI driver module */
static struct pci_driver ohci_pci_driver = {
	.name =		(char *) hcd_name,
	.id_table =	pci_ids,

	.probe =	usb_hcd_pci_probe,
	.remove =	usb_hcd_pci_remove,

#ifdef	CONFIG_PM
	.suspend =	usb_hcd_pci_suspend,
	.resume =	usb_hcd_pci_resume,
#endif
326 327

	.shutdown =	usb_hcd_pci_shutdown,
L
Linus Torvalds 已提交
328 329
};