View | Details | Raw Unified | Return to bug 60099
Collapse All | Expand All

(-)sys/dev/usb/ohci.c (-1 / +134 lines)
Lines 1010-1016 Link Here
1010
	DPRINTF(("ohci_shutdown: stopping the HC\n"));
1010
	DPRINTF(("ohci_shutdown: stopping the HC\n"));
1011
	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
1011
	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
1012
}
1012
}
1013
1013
#endif
1014
/*
1014
/*
1015
 * Handle suspend/resume.
1015
 * Handle suspend/resume.
1016
 *
1016
 *
Lines 1018-1023 Link Here
1018
 * called from an intterupt context.  This is all right since we
1018
 * called from an intterupt context.  This is all right since we
1019
 * are almost suspended anyway.
1019
 * are almost suspended anyway.
1020
 */
1020
 */
1021
usbd_status
1022
ohci_resume(struct ohci_softc *sc)
1023
{
1024
	uint32_t ctl, ival, fm, per;
1025
#ifdef USB_DEBUG
1026
	uint32_t rev;
1027
#endif
1028
	int s;
1029
#ifdef USB_DEBUG		
1030
#if defined(__OpenBSD__)
1031
	DPRINTF((","));
1032
#else
1033
	DPRINTF(("%s:", USBDEVNAME(sc->sc_bus.bdev)));
1034
#endif
1035
	rev = OREAD4(sc, OHCI_REVISION);
1036
	DPRINTF((" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
1037
		OHCI_REV_LEGACY(rev) ? ", legacy support" : ""));
1038
	DPRINTF(("ohci_resume: controller state: "));
1039
	switch(OREAD4(sc, OHCI_CONTROL) & OHCI_HCFS_MASK) {
1040
		case OHCI_HCFS_SUSPEND:
1041
			DPRINTF(("SUSPEND"));
1042
			break;
1043
		case OHCI_HCFS_RESUME:
1044
			DPRINTF(("RESUME"));
1045
			break;
1046
		case OHCI_HCFS_RESET:
1047
			DPRINTF(("RESET"));
1048
			break;
1049
		case OHCI_HCFS_OPERATIONAL:
1050
			DPRINTF(("OPERATIONAL"));
1051
			break;
1052
	}
1053
	DPRINTF(("\n"));
1054
#endif
1055
	s = splhardusb();
1056
	/* The controller only responds to resume or reset writes at this point, so lets resume */
1057
	/* We are only supposed to enter resume state from a suspend state.  Should we check? */
1058
	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESUME);
1059
	usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);	
1060
#ifdef USB_DEBUG
1061
	/* check if the controller has resumed */
1062
	ctl = OREAD4(sc, OHCI_CONTROL);
1063
	if((ctl & OHCI_HCFS_RESUME) == OHCI_HCFS_RESUME) {
1064
		DPRINTF(("ohci_resume: controller state: RESUME\n"));
1065
	} else {
1066
		/* panic or abort? */
1067
		DPRINTF(("ohci_resume: ??? controller did not resume!\n"));
1068
		DPRINTF(("ohci_resume: OHCI_CONTROL: 0x%x\n",ctl));
1069
	}
1070
	
1071
	ohci_dumpregs(sc);
1072
#endif
1073
1074
	/* reset or controller may not start */
1075
	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
1076
	usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
1077
1078
	/* spec says save frame interrupt value, reset, then restore */
1079
	ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL));
1080
	OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR); /* Reset HC */
1081
	usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
1082
1083
	/* Some broken BIOSes do not recover these values */
1084
	OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
1085
	OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
1086
	OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
1087
	/* disable all interrupts and then switch on all desired interrupts */
1088
	OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
1089
	OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_intre | OHCI_MIE );
1090
1091
	fm = (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT;
1092
	fm |= OHCI_FSMPS(ival) | ival;
1093
	OWRITE4(sc, OHCI_FM_INTERVAL, fm);
1094
	per = OHCI_PERIODIC(ival);
1095
	OWRITE4(sc, OHCI_PERIODIC_START, per);
1096
1097
	/* start controller */
1098
	ctl = sc->sc_control;
1099
	OWRITE4(sc, OHCI_CONTROL, ctl);
1100
	usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
1101
1102
	/* power up ports */
1103
	OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC);
1104
	usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY);
1105
	splx(s);
1106
#ifdef USB_DEBUG
1107
	ohci_dumpregs(sc);
1108
#endif
1109
	return (USBD_NORMAL_COMPLETION);
1110
}
1111
1112
usbd_status
1113
ohci_suspend(struct ohci_softc *sc)
1114
{
1115
	uint32_t ctl;
1116
	int s;
1117
1118
#ifdef USB_DEBUG
1119
	ohci_dumpregs(sc);
1120
#endif
1121
1122
	/*
1123
	 * Preserve register values, in case that APM BIOS
1124
	 * does not recover them.
1125
	 */
1126
	sc->sc_control = OREAD4(sc, OHCI_CONTROL);
1127
	sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE);
1128
	s = splhardusb();
1129
	/* disable interrupts */
1130
	OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
1131
	splx(s);
1132
	/* Reset to stop processing frames or the controller might not suspend */
1133
	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
1134
	usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
1135
	/* now suspend */
1136
	ctl = OHCI_HCFS_SUSPEND;
1137
	OWRITE4(sc, OHCI_CONTROL, ctl);
1138
	usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
1139
#ifdef USB_DEBUG
1140
	/* check if the controller is suspended */
1141
	ctl = OREAD4(sc, OHCI_CONTROL);
1142
	if((ctl & OHCI_HCFS_SUSPEND) == OHCI_HCFS_SUSPEND) {
1143
		DPRINTF(("ohci_suspend: controller state: SUSPEND.\n"));
1144
	} else {
1145
		/* panic or abort? */
1146
		DPRINTF(("ohci_suspend: ??? controller did not suspend!\n"));
1147
		DPRINTF(("ohci_suspend: OHCI_CONTROL: 0x%x\n", ctl));
1148
	}
1149
#endif
1150
	return (USBD_NORMAL_COMPLETION);
1151
}
1152
1153
#if defined(__NetBSD__) || defined(__OpenBSD__)
1021
void
1154
void
1022
ohci_power(int why, void *v)
1155
ohci_power(int why, void *v)
1023
{
1156
{
(-)sys/dev/usb/ohci_pci.c (+28 lines)
Lines 304-313 Link Here
304
	return 0;
304
	return 0;
305
}
305
}
306
306
307
/* implement suspend and resume */
308
static int
309
ohci_pci_suspend(device_t self)
310
{
311
	int err;
312
	ohci_softc_t *sc = device_get_softc(self);
313
	err = bus_generic_suspend(self);
314
	if (err)
315
		return err;
316
	ohci_suspend(sc);
317
	return 0;
318
}
319
320
static int
321
ohci_pci_resume(device_t self)
322
{
323
	ohci_softc_t *sc = device_get_softc(self);
324
	pci_set_powerstate(self, PCI_POWERSTATE_D0);
325
	if(ohci_resume(sc) != USBD_NORMAL_COMPLETION) {
326
		return ENXIO;
327
	}
328
	bus_generic_resume(self);
329
	return 0;
330
}
331
307
static device_method_t ohci_methods[] = {
332
static device_method_t ohci_methods[] = {
308
	/* Device interface */
333
	/* Device interface */
309
	DEVMETHOD(device_probe, ohci_pci_probe),
334
	DEVMETHOD(device_probe, ohci_pci_probe),
310
	DEVMETHOD(device_attach, ohci_pci_attach),
335
	DEVMETHOD(device_attach, ohci_pci_attach),
336
	DEVMETHOD(device_detach, bus_generic_detach),
337
	DEVMETHOD(device_suspend, ohci_pci_suspend),
338
	DEVMETHOD(device_resume, ohci_pci_resume),
311
	DEVMETHOD(device_shutdown, bus_generic_shutdown),
339
	DEVMETHOD(device_shutdown, bus_generic_shutdown),
312
340
313
	/* Bus interface */
341
	/* Bus interface */
(-)sys/dev/usb/ohcivar.h (+2 lines)
Lines 158-163 Link Here
158
#define OXFER(xfer) ((struct ohci_xfer *)(xfer))
158
#define OXFER(xfer) ((struct ohci_xfer *)(xfer))
159
159
160
usbd_status	ohci_init(ohci_softc_t *);
160
usbd_status	ohci_init(ohci_softc_t *);
161
usbd_status	ohci_suspend(ohci_softc_t *);
162
usbd_status	ohci_resume(ohci_softc_t *);
161
int		ohci_intr(void *);
163
int		ohci_intr(void *);
162
#if defined(__NetBSD__) || defined(__OpenBSD__)
164
#if defined(__NetBSD__) || defined(__OpenBSD__)
163
int		ohci_detach(ohci_softc_t *, int);
165
int		ohci_detach(ohci_softc_t *, int);

Return to bug 60099