ehci-pci.c 10.2 KB
Newer Older
M
Matt Porter 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 * EHCI HCD (Host Controller Driver) PCI Bus Glue.
 *
 * Copyright (c) 2000-2004 by David Brownell
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef CONFIG_PCI
#error "This file is PCI bus glue.  CONFIG_PCI must be defined."
#endif

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

/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
 * off the controller (maybe it can boot from highspeed USB disks).
 */
30
static int bios_handoff(struct ehci_hcd *ehci, int where, u32 cap)
M
Matt Porter 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
{
	struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);

	/* always say Linux will own the hardware */
	pci_write_config_byte(pdev, where + 3, 1);

	/* maybe wait a while for BIOS to respond */
	if (cap & (1 << 16)) {
		int msec = 5000;

		do {
			msleep(10);
			msec -= 10;
			pci_read_config_dword(pdev, where, &cap);
		} while ((cap & (1 << 16)) && msec);
		if (cap & (1 << 16)) {
			ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n",
				where, cap);
			// some BIOS versions seem buggy...
			// return 1;
51
			ehci_warn(ehci, "continuing after BIOS bug...\n");
M
Matt Porter 已提交
52 53 54 55 56 57 58 59 60
			/* disable all SMIs, and clear "BIOS owns" flag */
			pci_write_config_dword(pdev, where + 4, 0);
			pci_write_config_byte(pdev, where + 2, 0);
		} else
			ehci_dbg(ehci, "BIOS handoff succeeded\n");
	}
	return 0;
}

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
/* called after powerup, by probe or system-pm "wakeup" */
static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
{
	u32			temp;
	int			retval;
	unsigned		count = 256/4;

	/* optional debug port, normally in the first BAR */
	temp = pci_find_capability(pdev, 0x0a);
	if (temp) {
		pci_read_config_dword(pdev, temp, &temp);
		temp >>= 16;
		if ((temp & (3 << 13)) == (1 << 13)) {
			temp &= 0x1fff;
			ehci->debug = ehci_to_hcd(ehci)->regs + temp;
			temp = readl(&ehci->debug->control);
			ehci_info(ehci, "debug port %d%s\n",
				HCS_DEBUG_PORT(ehci->hcs_params),
				(temp & DBGP_ENABLED)
					? " IN USE"
					: "");
			if (!(temp & DBGP_ENABLED))
				ehci->debug = NULL;
		}
	}

	temp = HCC_EXT_CAPS(readl(&ehci->caps->hcc_params));

	/* EHCI 0.96 and later may have "extended capabilities" */
	while (temp && count--) {
		u32		cap;

		pci_read_config_dword(pdev, temp, &cap);
		ehci_dbg(ehci, "capability %04x at %02x\n", cap, temp);
		switch (cap & 0xff) {
		case 1:			/* BIOS/SMM/... handoff */
			if (bios_handoff(ehci, temp, cap) != 0)
				return -EOPNOTSUPP;
			break;
		case 0:			/* illegal reserved capability */
			ehci_dbg(ehci, "illegal capability!\n");
			cap = 0;
			/* FALLTHROUGH */
		default:		/* unknown */
			break;
		}
		temp = (cap >> 8) & 0xff;
	}
	if (!count) {
		ehci_err(ehci, "bogus capabilities ... PCI problems!\n");
		return -EIO;
	}

	/* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */
	retval = pci_set_mwi(pdev);
	if (!retval)
		ehci_dbg(ehci, "MWI active\n");

	ehci_port_power(ehci, 0);

	return 0;
}

/* called by khubd or root hub (re)init threads; leaves HC in halt state */
125
static int ehci_pci_reset(struct usb_hcd *hcd)
M
Matt Porter 已提交
126
{
127 128
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
M
Matt Porter 已提交
129
	u32			temp;
130
	int			retval;
M
Matt Porter 已提交
131 132

	ehci->caps = hcd->regs;
133 134 135
	ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
	dbg_hcs_params(ehci, "reset");
	dbg_hcc_params(ehci, "reset");
M
Matt Porter 已提交
136 137

	/* cache this readonly data; minimize chip reads */
138
	ehci->hcs_params = readl(&ehci->caps->hcs_params);
M
Matt Porter 已提交
139

140 141 142 143
	retval = ehci_halt(ehci);
	if (retval)
		return retval;

144
	/* NOTE:  only the parts below this line are PCI-specific */
M
Matt Porter 已提交
145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
	switch (pdev->vendor) {
	case PCI_VENDOR_ID_TDI:
		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
			ehci->is_tdi_rh_tt = 1;
			tdi_reset(ehci);
		}
		break;
	case PCI_VENDOR_ID_AMD:
		/* AMD8111 EHCI doesn't work, according to AMD errata */
		if (pdev->device == 0x7463) {
			ehci_info(ehci, "ignoring AMD8111 (errata)\n");
			return -EIO;
		}
		break;
	case PCI_VENDOR_ID_NVIDIA:
		/* NVidia reports that certain chips don't handle
		 * QH, ITD, or SITD addresses above 2GB.  (But TD,
		 * data buffer, and periodic schedule are normal.)
		 */
		switch (pdev->device) {
		case 0x003c:	/* MCP04 */
		case 0x005b:	/* CK804 */
		case 0x00d8:	/* CK8 */
		case 0x00e8:	/* CK8S */
			if (pci_set_consistent_dma_mask(pdev,
						DMA_31BIT_MASK) < 0)
				ehci_warn(ehci, "can't enable NVidia "
					"workaround for >2GB RAM\n");
M
Matt Porter 已提交
174 175
			break;
		}
176 177
		break;
	}
M
Matt Porter 已提交
178 179

	if (ehci_is_TDI(ehci))
180
		ehci_reset(ehci);
M
Matt Porter 已提交
181 182 183 184 185

	/* at least the Genesys GL880S needs fixup here */
	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
	temp &= 0x0f;
	if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) {
186
		ehci_dbg(ehci, "bogus port configuration: "
M
Matt Porter 已提交
187 188 189 190 191
			"cc=%d x pcc=%d < ports=%d\n",
			HCS_N_CC(ehci->hcs_params),
			HCS_N_PCC(ehci->hcs_params),
			HCS_N_PORTS(ehci->hcs_params));

192 193 194 195 196 197 198 199 200
		switch (pdev->vendor) {
		case 0x17a0:		/* GENESYS */
			/* GL880S: should be PORTS=2 */
			temp |= (ehci->hcs_params & ~0xf);
			ehci->hcs_params = temp;
			break;
		case PCI_VENDOR_ID_NVIDIA:
			/* NF4: should be PCC=10 */
			break;
M
Matt Porter 已提交
201 202 203
		}
	}

204 205
	/* Serial Bus Release Number is at PCI 0x60 offset */
	pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
M
Matt Porter 已提交
206

207
	/* REVISIT:  per-port wake capability (PCI 0x62) currently unused */
M
Matt Porter 已提交
208

209
	retval = ehci_pci_reinit(ehci, pdev);
M
Matt Porter 已提交
210

211 212
	/* finish init */
	return ehci_init(hcd);
M
Matt Porter 已提交
213 214 215 216 217 218 219 220
}

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

#ifdef	CONFIG_PM

/* suspend/resume, section 4.3 */

D
David Brownell 已提交
221
/* These routines rely on the PCI bus glue
M
Matt Porter 已提交
222 223 224
 * to handle powerdown and wakeup, and currently also on
 * transceivers that don't need any software attention to set up
 * the right sort of wakeup.
D
David Brownell 已提交
225
 * Also they depend on separate root hub suspend/resume.
M
Matt Porter 已提交
226 227
 */

228
static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
M
Matt Porter 已提交
229
{
230
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
M
Matt Porter 已提交
231

232 233
	if (time_before(jiffies, ehci->next_statechange))
		msleep(10);
M
Matt Porter 已提交
234

D
David Brownell 已提交
235
	// could save FLADJ in case of Vaux power loss
M
Matt Porter 已提交
236 237 238 239 240
	// ... we'd only use it to handle clock skew

	return 0;
}

241
static int ehci_pci_resume(struct usb_hcd *hcd)
M
Matt Porter 已提交
242
{
243
	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
M
Matt Porter 已提交
244 245
	unsigned		port;
	struct usb_device	*root = hcd->self.root_hub;
246
	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
M
Matt Porter 已提交
247 248
	int			retval = -EINVAL;

D
David Brownell 已提交
249
	// maybe restore FLADJ
M
Matt Porter 已提交
250

251 252
	if (time_before(jiffies, ehci->next_statechange))
		msleep(100);
M
Matt Porter 已提交
253

D
David Brownell 已提交
254
	/* If CF is clear, we lost PCI Vaux power and need to restart.  */
255
	if (readl(&ehci->regs->configured_flag) != FLAG_CF)
D
David Brownell 已提交
256 257
		goto restart;

M
Matt Porter 已提交
258 259
	/* If any port is suspended (or owned by the companion),
	 * we know we can/must resume the HC (and mustn't reset it).
D
David Brownell 已提交
260
	 * We just defer that to the root hub code.
M
Matt Porter 已提交
261
	 */
262
	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
M
Matt Porter 已提交
263 264
		u32	status;
		port--;
265
		status = readl(&ehci->regs->port_status [port]);
M
Matt Porter 已提交
266 267
		if (!(status & PORT_POWER))
			continue;
D
David Brownell 已提交
268 269 270
		if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
			usb_hcd_resume_root_hub(hcd);
			return 0;
M
Matt Porter 已提交
271
		}
D
David Brownell 已提交
272 273 274 275
	}

restart:
	ehci_dbg(ehci, "lost power, restarting\n");
276
	for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
D
David Brownell 已提交
277
		port--;
M
Matt Porter 已提交
278 279
		if (!root->children [port])
			continue;
280
		usb_set_device_state(root->children[port],
M
Matt Porter 已提交
281 282 283 284
					USB_STATE_NOTATTACHED);
	}

	/* Else reset, to cope with power loss or flush-to-storage
D
David Brownell 已提交
285
	 * style "resume" having let BIOS kick in during reboot.
M
Matt Porter 已提交
286
	 */
287 288
	(void) ehci_halt(ehci);
	(void) ehci_reset(ehci);
289
	(void) ehci_pci_reinit(ehci, pdev);
D
David Brownell 已提交
290 291

	/* emptying the schedule aborts any urbs */
292
	spin_lock_irq(&ehci->lock);
D
David Brownell 已提交
293 294
	if (ehci->reclaim)
		ehci->reclaim_ready = 1;
295 296
	ehci_work(ehci, NULL);
	spin_unlock_irq(&ehci->lock);
D
David Brownell 已提交
297 298

	/* restart; khubd will disconnect devices */
299
	retval = ehci_run(hcd);
D
David Brownell 已提交
300

301
	/* here we "know" root ports should always stay powered */
302
	ehci_port_power(ehci, 1);
M
Matt Porter 已提交
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

	return retval;
}
#endif

static const struct hc_driver ehci_pci_hc_driver = {
	.description =		hcd_name,
	.product_desc =		"EHCI Host Controller",
	.hcd_priv_size =	sizeof(struct ehci_hcd),

	/*
	 * generic hardware linkage
	 */
	.irq =			ehci_irq,
	.flags =		HCD_MEMORY | HCD_USB2,

	/*
	 * basic lifecycle operations
	 */
	.reset =		ehci_pci_reset,
323
	.start =		ehci_run,
M
Matt Porter 已提交
324 325 326 327
#ifdef	CONFIG_PM
	.suspend =		ehci_pci_suspend,
	.resume =		ehci_pci_resume,
#endif
328
	.stop =			ehci_stop,
M
Matt Porter 已提交
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346

	/*
	 * managing i/o requests and associated device resources
	 */
	.urb_enqueue =		ehci_urb_enqueue,
	.urb_dequeue =		ehci_urb_dequeue,
	.endpoint_disable =	ehci_endpoint_disable,

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

	/*
	 * root hub support
	 */
	.hub_status_data =	ehci_hub_status_data,
	.hub_control =		ehci_hub_control,
347 348
	.bus_suspend =		ehci_bus_suspend,
	.bus_resume =		ehci_bus_resume,
M
Matt Porter 已提交
349 350 351 352 353 354 355 356 357 358 359 360
};

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

/* PCI driver selection metadata; PCI hotplugging uses this */
static const struct pci_device_id pci_ids [] = { {
	/* handle any USB 2.0 EHCI controller */
	PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),
	.driver_data =	(unsigned long) &ehci_pci_hc_driver,
	},
	{ /* end: all zeroes */ }
};
361
MODULE_DEVICE_TABLE(pci, pci_ids);
M
Matt Porter 已提交
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376

/* pci driver glue; this is a "new style" PCI driver module */
static struct pci_driver ehci_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
};

377
static int __init ehci_hcd_pci_init(void)
M
Matt Porter 已提交
378 379 380 381
{
	if (usb_disabled())
		return -ENODEV;

382
	pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
M
Matt Porter 已提交
383
		hcd_name,
384 385
		sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
		sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
M
Matt Porter 已提交
386

387
	return pci_register_driver(&ehci_pci_driver);
M
Matt Porter 已提交
388
}
389
module_init(ehci_hcd_pci_init);
M
Matt Porter 已提交
390

391
static void __exit ehci_hcd_pci_cleanup(void)
M
Matt Porter 已提交
392
{
393
	pci_unregister_driver(&ehci_pci_driver);
M
Matt Porter 已提交
394
}
395
module_exit(ehci_hcd_pci_cleanup);