Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9faa091a authored by Jan Andersson's avatar Jan Andersson Committed by Greg Kroah-Hartman
Browse files

USB: UHCI: Wrap I/O register accesses



This patch is part of a series that extend the UHCI HCD to support
non-PCI controllers.

This patch replaces in{b,w,l} and out{b,wl} with calls to local inline
functions. This is done so that the register access functions can be
extended to support register areas not mapped in PCI I/O space.

Signed-off-by: default avatarJan Andersson <jan@gaisler.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c31a65f8
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -285,7 +285,6 @@ static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len)
static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
{
	char *out = buf;
	unsigned long io_addr = uhci->io_addr;
	unsigned short usbcmd, usbstat, usbint, usbfrnum;
	unsigned int flbaseadd;
	unsigned char sof;
@@ -295,14 +294,14 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
	if (len < 80 * 9)
		return 0;

	usbcmd    = inw(io_addr + 0);
	usbstat   = inw(io_addr + 2);
	usbint    = inw(io_addr + 4);
	usbfrnum  = inw(io_addr + 6);
	flbaseadd = inl(io_addr + 8);
	sof       = inb(io_addr + 12);
	portsc1   = inw(io_addr + 16);
	portsc2   = inw(io_addr + 18);
	usbcmd    = uhci_readw(uhci, 0);
	usbstat   = uhci_readw(uhci, 2);
	usbint    = uhci_readw(uhci, 4);
	usbfrnum  = uhci_readw(uhci, 6);
	flbaseadd = uhci_readl(uhci, 8);
	sof       = uhci_readb(uhci, 12);
	portsc1   = uhci_readw(uhci, 16);
	portsc2   = uhci_readw(uhci, 18);

	out += sprintf(out, "  usbcmd    =     %04x   %s%s%s%s%s%s%s%s\n",
		usbcmd,
+21 −21
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ static void finish_reset(struct uhci_hcd *uhci)
	 * We have to clear them by hand.
	 */
	for (port = 0; port < uhci->rh_numports; ++port)
		outw(0, uhci->io_addr + USBPORTSC1 + (port * 2));
		uhci_writew(uhci, 0, USBPORTSC1 + (port * 2));

	uhci->port_c_suspend = uhci->resuming_ports = 0;
	uhci->rh_state = UHCI_RH_RESET;
@@ -173,14 +173,14 @@ static void check_and_reset_hc(struct uhci_hcd *uhci)
static void configure_hc(struct uhci_hcd *uhci)
{
	/* Set the frame length to the default: 1 ms exactly */
	outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
	uhci_writeb(uhci, USBSOF_DEFAULT, USBSOF);

	/* Store the frame list base address */
	outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
	uhci_writel(uhci, uhci->frame_dma_handle, USBFLBASEADD);

	/* Set the current frame number */
	outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER,
			uhci->io_addr + USBFRNUM);
	uhci_writew(uhci, uhci->frame_number & UHCI_MAX_SOF_NUMBER,
			USBFRNUM);

	/* perform any arch/bus specific configuration */
	if (uhci->configure_hc)
@@ -264,8 +264,8 @@ __acquires(uhci->lock)
			!int_enable)
		uhci->RD_enable = int_enable = 0;

	outw(int_enable, uhci->io_addr + USBINTR);
	outw(egsm_enable | USBCMD_CF, uhci->io_addr + USBCMD);
	uhci_writew(uhci, int_enable, USBINTR);
	uhci_writew(uhci, egsm_enable | USBCMD_CF, USBCMD);
	mb();
	udelay(5);

@@ -274,7 +274,7 @@ __acquires(uhci->lock)
	 * controller should stop after a few microseconds.  Otherwise
	 * we will give the controller one frame to stop.
	 */
	if (!auto_stop && !(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) {
	if (!auto_stop && !(uhci_readw(uhci, USBSTS) & USBSTS_HCH)) {
		uhci->rh_state = UHCI_RH_SUSPENDING;
		spin_unlock_irq(&uhci->lock);
		msleep(1);
@@ -282,7 +282,7 @@ __acquires(uhci->lock)
		if (uhci->dead)
			return;
	}
	if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
	if (!(uhci_readw(uhci, USBSTS) & USBSTS_HCH))
		dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");

	uhci_get_current_frame_number(uhci);
@@ -309,9 +309,9 @@ static void start_rh(struct uhci_hcd *uhci)
	/* Mark it configured and running with a 64-byte max packet.
	 * All interrupts are enabled, even though RESUME won't do anything.
	 */
	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD);
	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
			uhci->io_addr + USBINTR);
	uhci_writew(uhci, USBCMD_RS | USBCMD_CF | USBCMD_MAXP, USBCMD);
	uhci_writew(uhci, USBINTR_TIMEOUT | USBINTR_RESUME |
		USBINTR_IOC | USBINTR_SP, USBINTR);
	mb();
	uhci->rh_state = UHCI_RH_RUNNING;
	set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags);
@@ -334,9 +334,9 @@ __acquires(uhci->lock)
		unsigned egsm;

		/* Keep EGSM on if it was set before */
		egsm = inw(uhci->io_addr + USBCMD) & USBCMD_EGSM;
		egsm = uhci_readw(uhci, USBCMD) & USBCMD_EGSM;
		uhci->rh_state = UHCI_RH_RESUMING;
		outw(USBCMD_FGR | USBCMD_CF | egsm, uhci->io_addr + USBCMD);
		uhci_writew(uhci, USBCMD_FGR | USBCMD_CF | egsm, USBCMD);
		spin_unlock_irq(&uhci->lock);
		msleep(20);
		spin_lock_irq(&uhci->lock);
@@ -344,10 +344,10 @@ __acquires(uhci->lock)
			return;

		/* End Global Resume and wait for EOP to be sent */
		outw(USBCMD_CF, uhci->io_addr + USBCMD);
		uhci_writew(uhci, USBCMD_CF, USBCMD);
		mb();
		udelay(4);
		if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR)
		if (uhci_readw(uhci, USBCMD) & USBCMD_FGR)
			dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n");
	}

@@ -367,10 +367,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
	 * interrupt cause.  Contrary to the UHCI specification, the
	 * "HC Halted" status bit is persistent: it is RO, not R/WC.
	 */
	status = inw(uhci->io_addr + USBSTS);
	status = uhci_readw(uhci, USBSTS);
	if (!(status & ~USBSTS_HCH))	/* shared interrupt, not mine */
		return IRQ_NONE;
	outw(status, uhci->io_addr + USBSTS);		/* Clear it */
	uhci_writew(uhci, status, USBSTS);		/* Clear it */

	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
		if (status & USBSTS_HSE)
@@ -426,7 +426,7 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
	if (!uhci->is_stopped) {
		unsigned delta;

		delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) &
		delta = (uhci_readw(uhci, USBFRNUM) - uhci->frame_number) &
				(UHCI_NUMFRAMES - 1);
		uhci->frame_number += delta;
	}
@@ -716,7 +716,7 @@ static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
	/* Minimize latency by avoiding the spinlock */
	frame_number = uhci->frame_number;
	barrier();
	delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) &
	delta = (uhci_readw(uhci, USBFRNUM) - frame_number) &
			(UHCI_NUMFRAMES - 1);
	return frame_number + delta;
}
@@ -739,7 +739,7 @@ static int uhci_count_ports(struct usb_hcd *hcd)
	for (port = 0; port < (io_size - USBPORTSC1) / 2; port++) {
		unsigned int portstatus;

		portstatus = inw(uhci->io_addr + USBPORTSC1 + (port * 2));
		portstatus = uhci_readw(uhci, USBPORTSC1 + (port * 2));
		if (!(portstatus & 0x0080) || portstatus == 0xffff)
			break;
	}
+30 −0
Original line number Diff line number Diff line
@@ -481,4 +481,34 @@ struct urb_priv {
#define PCI_VENDOR_ID_GENESYS		0x17a0
#define PCI_DEVICE_ID_GL880S_UHCI	0x8083

static inline u32 uhci_readl(struct uhci_hcd *uhci, int reg)
{
	return inl(uhci->io_addr + reg);
}

static inline void uhci_writel(struct uhci_hcd *uhci, u32 val, int reg)
{
	outl(val, uhci->io_addr + reg);
}

static inline u16 uhci_readw(struct uhci_hcd *uhci, int reg)
{
	return inw(uhci->io_addr + reg);
}

static inline void uhci_writew(struct uhci_hcd *uhci, u16 val, int reg)
{
	outw(val, uhci->io_addr + reg);
}

static inline u8 uhci_readb(struct uhci_hcd *uhci, int reg)
{
	return inb(uhci->io_addr + reg);
}

static inline void uhci_writeb(struct uhci_hcd *uhci, u8 val, int reg)
{
	outb(val, uhci->io_addr + reg);
}

#endif
+18 −17
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ static int any_ports_active(struct uhci_hcd *uhci)
	int port;

	for (port = 0; port < uhci->rh_numports; ++port) {
		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) &
		if ((uhci_readw(uhci, USBPORTSC1 + port * 2) &
				(USBPORTSC_CCS | RWC_BITS)) ||
				test_bit(port, &uhci->port_c_suspend))
			return 1;
@@ -68,7 +68,7 @@ static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)

	*buf = 0;
	for (port = 0; port < uhci->rh_numports; ++port) {
		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) ||
		if ((uhci_readw(uhci, USBPORTSC1 + port * 2) & mask) ||
				test_bit(port, &uhci->port_c_suspend))
			*buf |= (1 << (port + 1));
	}
@@ -78,17 +78,17 @@ static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
#define OK(x)			len = (x); break

#define CLR_RH_PORTSTAT(x) \
	status = inw(port_addr); \
	status = uhci_readw(uhci, port_addr);	\
	status &= ~(RWC_BITS|WZ_BITS); \
	status &= ~(x); \
	status |= RWC_BITS & (x); \
	outw(status, port_addr)
	uhci_writew(uhci, status, port_addr)

#define SET_RH_PORTSTAT(x) \
	status = inw(port_addr); \
	status = uhci_readw(uhci, port_addr);	\
	status |= (x); \
	status &= ~(RWC_BITS|WZ_BITS); \
	outw(status, port_addr)
	uhci_writew(uhci, status, port_addr)

/* UHCI controllers don't automatically stop resume signalling after 20 msec,
 * so we have to poll and check timeouts in order to take care of it.
@@ -99,7 +99,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
	int status;
	int i;

	if (inw(port_addr) & SUSPEND_BITS) {
	if (uhci_readw(uhci, port_addr) & SUSPEND_BITS) {
		CLR_RH_PORTSTAT(SUSPEND_BITS);
		if (test_bit(port, &uhci->resuming_ports))
			set_bit(port, &uhci->port_c_suspend);
@@ -110,7 +110,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
		 * Experiments show that some controllers take longer, so
		 * we'll poll for completion. */
		for (i = 0; i < 10; ++i) {
			if (!(inw(port_addr) & SUSPEND_BITS))
			if (!(uhci_readw(uhci, port_addr) & SUSPEND_BITS))
				break;
			udelay(1);
		}
@@ -121,12 +121,12 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
/* Wait for the UHCI controller in HP's iLO2 server management chip.
 * It can take up to 250 us to finish a reset and set the CSC bit.
 */
static void wait_for_HP(unsigned long port_addr)
static void wait_for_HP(struct uhci_hcd *uhci, unsigned long port_addr)
{
	int i;

	for (i = 10; i < 250; i += 10) {
		if (inw(port_addr) & USBPORTSC_CSC)
		if (uhci_readw(uhci, port_addr) & USBPORTSC_CSC)
			return;
		udelay(10);
	}
@@ -140,8 +140,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
	int status;

	for (port = 0; port < uhci->rh_numports; ++port) {
		port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
		status = inw(port_addr);
		port_addr = USBPORTSC1 + 2 * port;
		status = uhci_readw(uhci, port_addr);
		if (unlikely(status & USBPORTSC_PR)) {
			if (time_after_eq(jiffies, uhci->ports_timeout)) {
				CLR_RH_PORTSTAT(USBPORTSC_PR);
@@ -150,7 +150,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
				/* HP's server management chip requires
				 * a longer delay. */
				if (uhci->wait_for_hp)
					wait_for_HP(port_addr);
					wait_for_HP(uhci, port_addr);

				/* If the port was enabled before, turning
				 * reset on caused a port enable change.
@@ -241,7 +241,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
	int status, lstatus, retval = 0, len = 0;
	unsigned int port = wIndex - 1;
	unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
	unsigned long port_addr = USBPORTSC1 + 2 * port;
	u16 wPortChange, wPortStatus;
	unsigned long flags;

@@ -259,7 +259,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			goto err;

		uhci_check_ports(uhci);
		status = inw(port_addr);
		status = uhci_readw(uhci, port_addr);

		/* Intel controllers report the OverCurrent bit active on.
		 * VIA controllers report it active off, so we'll adjust the
@@ -356,7 +356,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
			CLR_RH_PORTSTAT(USBPORTSC_PEC);
			OK(0);
		case USB_PORT_FEAT_SUSPEND:
			if (!(inw(port_addr) & USBPORTSC_SUSP)) {
			if (!(uhci_readw(uhci, port_addr) & USBPORTSC_SUSP)) {

				/* Make certain the port isn't suspended */
				uhci_finish_suspend(uhci, port, port_addr);
@@ -368,7 +368,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
				 * if the port is disabled.  When this happens
				 * just skip the Resume signalling.
				 */
				if (!(inw(port_addr) & USBPORTSC_RD))
				if (!(uhci_readw(uhci, port_addr) &
						USBPORTSC_RD))
					uhci_finish_suspend(uhci, port,
							port_addr);
				else