From 28362673129e7d4510a5a92a8b68ee47f282210b Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Thu, 18 Jun 2015 11:51:53 +0800 Subject: [PATCH] usb: chipidea: add ttctrl.ttha control interface The register of ttctrl.ttha describes like below: - Internal TT Hub Address Representation - RW - Default = 0000000b This field is used to match against the Hub Address field in QH & siTD to determine if the packet is routed to the internal TT for directly attached FS/LS devices. If the Hub Address in the QH or siTD does not match this address then the packet will be broadcast on the High Speed ports destined for a downstream High Speed hub with the address in the QH/siTD. In silicon RTL, this entry only affects QH and siTD, and the hub.addr at both QH and siTD are 0 in ehci core for chipidea (with hcd->has_tt = 1). So, for QH, if the "usage_tt" flag at RTL is 0, set CI_HDRC_SET_NON_ZERO_TTHA will not affect QH (with non-hs device); for siTD, set this flag will change remaining space requirement for the last transaction from 1023 bytes to 188 bytes, it can increase the number of transactions within one frame, ehci periodic schedule code will not queue the packet if the frame space is full, so it is safe to set this flag for siTD. With this flag, it can fix the problem Alan Stern reported below: http://www.spinics.net/lists/linux-usb/msg123125.html And may fix Michael Tessier's problem too. http://www.spinics.net/lists/linux-usb/msg118679.html CC: stern@rowland.harvard.edu CC: michael.tessier@axiontech.ca Signed-off-by: Peter Chen --- drivers/usb/chipidea/bits.h | 5 +++++ drivers/usb/chipidea/ci.h | 1 + drivers/usb/chipidea/core.c | 2 ++ drivers/usb/chipidea/host.c | 3 +++ include/linux/usb/chipidea.h | 1 + 5 files changed, 12 insertions(+) diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h index 3cb9bda51ddf..831a8f645ea5 100644 --- a/drivers/usb/chipidea/bits.h +++ b/drivers/usb/chipidea/bits.h @@ -53,6 +53,11 @@ #define DEVICEADDR_USBADRA BIT(24) #define DEVICEADDR_USBADR (0x7FUL << 25) +/* TTCTRL */ +#define TTCTRL_TTHA_MASK (0x7fUL << 24) +/* Set non-zero value for internal TT Hub address representation */ +#define TTCTRL_TTHA (0x7fUL << 24) + /* PORTSC */ #define PORTSC_CCS BIT(0) #define PORTSC_CSC BIT(1) diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 6d6200e37b71..df57e49ed4ef 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -50,6 +50,7 @@ enum ci_hw_regs { OP_USBINTR, OP_DEVICEADDR, OP_ENDPTLISTADDR, + OP_TTCTRL, OP_PORTSC, OP_DEVLC, OP_OTGSC, diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3ad48e1c0c57..b0d01f26cd5e 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -84,6 +84,7 @@ static const u8 ci_regs_nolpm[] = { [OP_USBINTR] = 0x08U, [OP_DEVICEADDR] = 0x14U, [OP_ENDPTLISTADDR] = 0x18U, + [OP_TTCTRL] = 0x1CU, [OP_PORTSC] = 0x44U, [OP_DEVLC] = 0x84U, [OP_OTGSC] = 0x64U, @@ -106,6 +107,7 @@ static const u8 ci_regs_lpm[] = { [OP_USBINTR] = 0x08U, [OP_DEVICEADDR] = 0x14U, [OP_ENDPTLISTADDR] = 0x18U, + [OP_TTCTRL] = 0x1CU, [OP_PORTSC] = 0x44U, [OP_DEVLC] = 0x84U, [OP_OTGSC] = 0xC4U, diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 7161439def19..b01716c8c66b 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -159,6 +159,9 @@ static int host_start(struct ci_hdrc *ci) if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC); + if (ci->platdata->flags & CI_HDRC_SET_NON_ZERO_TTHA) + hw_write(ci, OP_TTCTRL, TTCTRL_TTHA_MASK, TTCTRL_TTHA); + return ret; disable_reg: diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index ab94f78c4dd1..d1e1285a971d 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -29,6 +29,7 @@ struct ci_hdrc_platform_data { #define CI_HDRC_IMX28_WRITE_FIX BIT(5) #define CI_HDRC_FORCE_FULLSPEED BIT(6) #define CI_HDRC_TURN_VBUS_EARLY_ON BIT(7) +#define CI_HDRC_SET_NON_ZERO_TTHA BIT(8) enum usb_dr_mode dr_mode; #define CI_HDRC_CONTROLLER_RESET_EVENT 0 #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 -- 2.20.1