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

Commit 29fab0cd authored by Yoshihiro Shimoda's avatar Yoshihiro Shimoda Committed by Greg Kroah-Hartman
Browse files

USB: r8a66597-hcd: fix usb device connection timing



Fix the problem that enumeration of a USB device was slow.

Signed-off-by: default avatarYoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 6d879107
Loading
Loading
Loading
Loading
+32 −24
Original line number Diff line number Diff line
@@ -900,10 +900,19 @@ static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
}

/* this function must be called with interrupt disabled */
static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port)
static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
					u16 syssts)
{
	r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
					 | (1 << USB_PORT_FEAT_C_CONNECTION);
	if (syssts == SE0) {
		r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
		return;
	}

	if (syssts == FS_JSTS)
		r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
	else if (syssts == LS_JSTS)
		r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));

	r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
	r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
}
@@ -1478,13 +1487,21 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
	}
}

static void r8a66597_root_hub_start_polling(struct r8a66597 *r8a66597)
{
	mod_timer(&r8a66597->rh_timer,
			jiffies + msecs_to_jiffies(R8A66597_RH_POLL_TIME));
}

static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port)
{
	struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];

	rh->old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
	rh->scount = R8A66597_MAX_SAMPLING;
	mod_timer(&r8a66597->rh_timer, jiffies + msecs_to_jiffies(50));
	r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
					 | (1 << USB_PORT_FEAT_C_CONNECTION);
	r8a66597_root_hub_start_polling(r8a66597);
}

static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
@@ -1571,37 +1588,28 @@ static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
		if ((tmp & USBRST) == USBRST) {
			r8a66597_mdfy(r8a66597, UACT, USBRST | UACT,
				      dvstctr_reg);
			mod_timer(&r8a66597->rh_timer,
				  jiffies + msecs_to_jiffies(50));
			r8a66597_root_hub_start_polling(r8a66597);
		} else
			r8a66597_usb_connect(r8a66597, port);
	}

	if (!(rh->port & (1 << USB_PORT_FEAT_CONNECTION))) {
		r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
		r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
	}

	if (rh->scount > 0) {
		tmp = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
		if (tmp == rh->old_syssts) {
			rh->scount--;
			if (rh->scount == 0) {
				if (tmp == FS_JSTS) {
					r8a66597_bset(r8a66597, HSE,
						      get_syscfg_reg(port));
					r8a66597_usb_preconnect(r8a66597, port);
				} else if (tmp == LS_JSTS) {
					r8a66597_bclr(r8a66597, HSE,
						      get_syscfg_reg(port));
					r8a66597_usb_preconnect(r8a66597, port);
				} else if (tmp == SE0)
					r8a66597_bset(r8a66597, ATTCHE,
						      get_intenb_reg(port));
			} else {
				mod_timer(&r8a66597->rh_timer,
					  jiffies + msecs_to_jiffies(50));
			}
			if (rh->scount == 0)
				r8a66597_check_syssts(r8a66597, port, tmp);
			else
				r8a66597_root_hub_start_polling(r8a66597);
		} else {
			rh->scount = R8A66597_MAX_SAMPLING;
			rh->old_syssts = tmp;
			mod_timer(&r8a66597->rh_timer,
				  jiffies + msecs_to_jiffies(50));
			r8a66597_root_hub_start_polling(r8a66597);
		}
	}
}
+2 −1
Original line number Diff line number Diff line
@@ -396,7 +396,8 @@
#define R8A66597_BUF_BSIZE		8
#define R8A66597_MAX_DEVICE		10
#define R8A66597_MAX_ROOT_HUB		2
#define R8A66597_MAX_SAMPLING		10
#define R8A66597_MAX_SAMPLING		5
#define R8A66597_RH_POLL_TIME		10
#define R8A66597_MAX_DMA_CHANNEL	2
#define R8A66597_PIPE_NO_DMA		R8A66597_MAX_DMA_CHANNEL
#define check_bulk_or_isoc(pipenum)	((pipenum >= 1 && pipenum <= 5))