Skip to content

Commit 51c4d5f

Browse files
committed
Merge tag 'usb-6.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH: "Here are a handful of small USB fixes for 6.11-rc7. Included in here are: - dwc3 driver fixes for two reported problems - two typec ucsi driver fixes - cdns2 controller reset fix All of these have been in linux-next this week with no reported problems" * tag 'usb-6.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: typec: ucsi: Fix cable registration usb: typec: ucsi: Fix the partner PD revision usb: cdns2: Fix controller reset issue usb: dwc3: core: update LC timer as per USB Spec V3.2 usb: dwc3: Avoid waking up gadget during startxfer
2 parents d1f2d51 + 87eb3cb commit 51c4d5f

File tree

7 files changed

+87
-73
lines changed

7 files changed

+87
-73
lines changed

drivers/usb/dwc3/core.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,21 @@ static int dwc3_core_init(struct dwc3 *dwc)
13861386
dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
13871387
}
13881388

1389+
/*
1390+
* STAR 9001285599: This issue affects DWC_usb3 version 3.20a
1391+
* only. If the PM TIMER ECM is enabled through GUCTL2[19], the
1392+
* link compliance test (TD7.21) may fail. If the ECN is not
1393+
* enabled (GUCTL2[19] = 0), the controller will use the old timer
1394+
* value (5us), which is still acceptable for the link compliance
1395+
* test. Therefore, do not enable PM TIMER ECM in 3.20a by
1396+
* setting GUCTL2[19] by default; instead, use GUCTL2[19] = 0.
1397+
*/
1398+
if (DWC3_VER_IS(DWC3, 320A)) {
1399+
reg = dwc3_readl(dwc->regs, DWC3_GUCTL2);
1400+
reg &= ~DWC3_GUCTL2_LC_TIMER;
1401+
dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
1402+
}
1403+
13891404
/*
13901405
* When configured in HOST mode, after issuing U3/L2 exit controller
13911406
* fails to send proper CRC checksum in CRC5 feild. Because of this

drivers/usb/dwc3/core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@
421421

422422
/* Global User Control Register 2 */
423423
#define DWC3_GUCTL2_RST_ACTBITLATER BIT(14)
424+
#define DWC3_GUCTL2_LC_TIMER BIT(19)
424425

425426
/* Global User Control Register 3 */
426427
#define DWC3_GUCTL3_SPLITDISABLE BIT(14)
@@ -1269,6 +1270,7 @@ struct dwc3 {
12691270
#define DWC3_REVISION_290A 0x5533290a
12701271
#define DWC3_REVISION_300A 0x5533300a
12711272
#define DWC3_REVISION_310A 0x5533310a
1273+
#define DWC3_REVISION_320A 0x5533320a
12721274
#define DWC3_REVISION_330A 0x5533330a
12731275

12741276
#define DWC31_REVISION_ANY 0x0

drivers/usb/dwc3/gadget.c

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,23 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc, bool async);
287287
*
288288
* Caller should handle locking. This function will issue @cmd with given
289289
* @params to @dep and wait for its completion.
290+
*
291+
* According to the programming guide, if the link state is in L1/L2/U3,
292+
* then sending the Start Transfer command may not complete. The
293+
* programming guide suggested to bring the link state back to ON/U0 by
294+
* performing remote wakeup prior to sending the command. However, don't
295+
* initiate remote wakeup when the user/function does not send wakeup
296+
* request via wakeup ops. Send the command when it's allowed.
297+
*
298+
* Notes:
299+
* For L1 link state, issuing a command requires the clearing of
300+
* GUSB2PHYCFG.SUSPENDUSB2, which turns on the signal required to complete
301+
* the given command (usually within 50us). This should happen within the
302+
* command timeout set by driver. No additional step is needed.
303+
*
304+
* For L2 or U3 link state, the gadget is in USB suspend. Care should be
305+
* taken when sending Start Transfer command to ensure that it's done after
306+
* USB resume.
290307
*/
291308
int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
292309
struct dwc3_gadget_ep_cmd_params *params)
@@ -327,30 +344,6 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
327344
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
328345
}
329346

330-
if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
331-
int link_state;
332-
333-
/*
334-
* Initiate remote wakeup if the link state is in U3 when
335-
* operating in SS/SSP or L1/L2 when operating in HS/FS. If the
336-
* link state is in U1/U2, no remote wakeup is needed. The Start
337-
* Transfer command will initiate the link recovery.
338-
*/
339-
link_state = dwc3_gadget_get_link_state(dwc);
340-
switch (link_state) {
341-
case DWC3_LINK_STATE_U2:
342-
if (dwc->gadget->speed >= USB_SPEED_SUPER)
343-
break;
344-
345-
fallthrough;
346-
case DWC3_LINK_STATE_U3:
347-
ret = __dwc3_gadget_wakeup(dwc, false);
348-
dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n",
349-
ret);
350-
break;
351-
}
352-
}
353-
354347
/*
355348
* For some commands such as Update Transfer command, DEPCMDPARn
356349
* registers are reserved. Since the driver often sends Update Transfer

drivers/usb/gadget/udc/cdns2/cdns2-gadget.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,7 +2251,6 @@ static int cdns2_gadget_start(struct cdns2_device *pdev)
22512251
{
22522252
u32 max_speed;
22532253
void *buf;
2254-
int val;
22552254
int ret;
22562255

22572256
pdev->usb_regs = pdev->regs;
@@ -2261,14 +2260,9 @@ static int cdns2_gadget_start(struct cdns2_device *pdev)
22612260
pdev->adma_regs = pdev->regs + CDNS2_ADMA_REGS_OFFSET;
22622261

22632262
/* Reset controller. */
2264-
set_reg_bit_8(&pdev->usb_regs->cpuctrl, CPUCTRL_SW_RST);
2265-
2266-
ret = readl_poll_timeout_atomic(&pdev->usb_regs->cpuctrl, val,
2267-
!(val & CPUCTRL_SW_RST), 1, 10000);
2268-
if (ret) {
2269-
dev_err(pdev->dev, "Error: reset controller timeout\n");
2270-
return -EINVAL;
2271-
}
2263+
writeb(CPUCTRL_SW_RST | CPUCTRL_UPCLK | CPUCTRL_WUEN,
2264+
&pdev->usb_regs->cpuctrl);
2265+
usleep_range(5, 10);
22722266

22732267
usb_initialize_gadget(pdev->dev, &pdev->gadget, NULL);
22742268

drivers/usb/gadget/udc/cdns2/cdns2-gadget.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,17 @@ struct cdns2_usb_regs {
292292
#define SPEEDCTRL_HSDISABLE BIT(7)
293293

294294
/* CPUCTRL- bitmasks. */
295+
/* UP clock enable */
296+
#define CPUCTRL_UPCLK BIT(0)
295297
/* Controller reset bit. */
296298
#define CPUCTRL_SW_RST BIT(1)
299+
/**
300+
* If the wuen bit is ‘1’, the upclken is automatically set to ‘1’ after
301+
* detecting rising edge of wuintereq interrupt. If the wuen bit is ‘0’,
302+
* the wuintereq interrupt is ignored.
303+
*/
304+
#define CPUCTRL_WUEN BIT(7)
305+
297306

298307
/**
299308
* struct cdns2_adma_regs - ADMA controller registers.

drivers/usb/typec/ucsi/ucsi.c

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -965,10 +965,20 @@ static void ucsi_unregister_plug(struct ucsi_connector *con)
965965

966966
static int ucsi_register_cable(struct ucsi_connector *con)
967967
{
968+
struct ucsi_cable_property cable_prop;
968969
struct typec_cable *cable;
969970
struct typec_cable_desc desc = {};
971+
u64 command;
972+
int ret;
973+
974+
command = UCSI_GET_CABLE_PROPERTY | UCSI_CONNECTOR_NUMBER(con->num);
975+
ret = ucsi_send_command(con->ucsi, command, &cable_prop, sizeof(cable_prop));
976+
if (ret < 0) {
977+
dev_err(con->ucsi->dev, "GET_CABLE_PROPERTY failed (%d)\n", ret);
978+
return ret;
979+
}
970980

971-
switch (UCSI_CABLE_PROP_FLAG_PLUG_TYPE(con->cable_prop.flags)) {
981+
switch (UCSI_CABLE_PROP_FLAG_PLUG_TYPE(cable_prop.flags)) {
972982
case UCSI_CABLE_PROPERTY_PLUG_TYPE_A:
973983
desc.type = USB_PLUG_TYPE_A;
974984
break;
@@ -984,10 +994,10 @@ static int ucsi_register_cable(struct ucsi_connector *con)
984994
}
985995

986996
desc.identity = &con->cable_identity;
987-
desc.active = !!(UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE &
988-
con->cable_prop.flags);
989-
desc.pd_revision = UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV_AS_BCD(
990-
con->cable_prop.flags);
997+
desc.active = !!(UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE & cable_prop.flags);
998+
999+
if (con->ucsi->version >= UCSI_VERSION_2_1)
1000+
desc.pd_revision = UCSI_CABLE_PROP_FLAG_PD_MAJOR_REV_AS_BCD(cable_prop.flags);
9911001

9921002
cable = typec_register_cable(con->port, &desc);
9931003
if (IS_ERR(cable)) {
@@ -1012,6 +1022,27 @@ static void ucsi_unregister_cable(struct ucsi_connector *con)
10121022
con->cable = NULL;
10131023
}
10141024

1025+
static int ucsi_check_connector_capability(struct ucsi_connector *con)
1026+
{
1027+
u64 command;
1028+
int ret;
1029+
1030+
if (!con->partner || con->ucsi->version < UCSI_VERSION_2_1)
1031+
return 0;
1032+
1033+
command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num);
1034+
ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap));
1035+
if (ret < 0) {
1036+
dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret);
1037+
return ret;
1038+
}
1039+
1040+
typec_partner_set_pd_revision(con->partner,
1041+
UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));
1042+
1043+
return ret;
1044+
}
1045+
10151046
static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
10161047
{
10171048
switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
@@ -1021,6 +1052,7 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
10211052
ucsi_partner_task(con, ucsi_get_src_pdos, 30, 0);
10221053
ucsi_partner_task(con, ucsi_check_altmodes, 30, HZ);
10231054
ucsi_partner_task(con, ucsi_register_partner_pdos, 1, HZ);
1055+
ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
10241056
break;
10251057
case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5:
10261058
con->rdo = 0;
@@ -1064,7 +1096,6 @@ static int ucsi_register_partner(struct ucsi_connector *con)
10641096

10651097
desc.identity = &con->partner_identity;
10661098
desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
1067-
desc.pd_revision = UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags);
10681099

10691100
partner = typec_register_partner(con->port, &desc);
10701101
if (IS_ERR(partner)) {
@@ -1141,27 +1172,6 @@ static void ucsi_partner_change(struct ucsi_connector *con)
11411172
con->num, u_role);
11421173
}
11431174

1144-
static int ucsi_check_connector_capability(struct ucsi_connector *con)
1145-
{
1146-
u64 command;
1147-
int ret;
1148-
1149-
if (!con->partner || con->ucsi->version < UCSI_VERSION_2_0)
1150-
return 0;
1151-
1152-
command = UCSI_GET_CONNECTOR_CAPABILITY | UCSI_CONNECTOR_NUMBER(con->num);
1153-
ret = ucsi_send_command(con->ucsi, command, &con->cap, sizeof(con->cap));
1154-
if (ret < 0) {
1155-
dev_err(con->ucsi->dev, "GET_CONNECTOR_CAPABILITY failed (%d)\n", ret);
1156-
return ret;
1157-
}
1158-
1159-
typec_partner_set_pd_revision(con->partner,
1160-
UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));
1161-
1162-
return ret;
1163-
}
1164-
11651175
static int ucsi_check_connection(struct ucsi_connector *con)
11661176
{
11671177
u8 prev_flags = con->status.flags;
@@ -1193,21 +1203,11 @@ static int ucsi_check_connection(struct ucsi_connector *con)
11931203

11941204
static int ucsi_check_cable(struct ucsi_connector *con)
11951205
{
1196-
u64 command;
11971206
int ret, num_plug_am;
11981207

11991208
if (con->cable)
12001209
return 0;
12011210

1202-
command = UCSI_GET_CABLE_PROPERTY | UCSI_CONNECTOR_NUMBER(con->num);
1203-
ret = ucsi_send_command(con->ucsi, command, &con->cable_prop,
1204-
sizeof(con->cable_prop));
1205-
if (ret < 0) {
1206-
dev_err(con->ucsi->dev, "GET_CABLE_PROPERTY failed (%d)\n",
1207-
ret);
1208-
return ret;
1209-
}
1210-
12111211
ret = ucsi_register_cable(con);
12121212
if (ret < 0)
12131213
return ret;
@@ -1283,15 +1283,16 @@ static void ucsi_handle_connector_change(struct work_struct *work)
12831283
if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
12841284
ucsi_register_partner(con);
12851285
ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
1286-
ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
12871286
if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
12881287
ucsi_partner_task(con, ucsi_get_partner_identity, 1, HZ);
12891288
if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
12901289
ucsi_partner_task(con, ucsi_check_cable, 1, HZ);
12911290

12921291
if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
1293-
UCSI_CONSTAT_PWR_OPMODE_PD)
1292+
UCSI_CONSTAT_PWR_OPMODE_PD) {
12941293
ucsi_partner_task(con, ucsi_register_partner_pdos, 1, HZ);
1294+
ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
1295+
}
12951296
} else {
12961297
ucsi_unregister_partner(con);
12971298
}
@@ -1706,6 +1707,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
17061707
ucsi_register_device_pdos(con);
17071708
ucsi_get_src_pdos(con);
17081709
ucsi_check_altmodes(con);
1710+
ucsi_check_connector_capability(con);
17091711
}
17101712

17111713
trace_ucsi_register_port(con->num, &con->status);

drivers/usb/typec/ucsi/ucsi.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,6 @@ struct ucsi_connector {
465465

466466
struct ucsi_connector_status status;
467467
struct ucsi_connector_capability cap;
468-
struct ucsi_cable_property cable_prop;
469468
struct power_supply *psy;
470469
struct power_supply_desc psy_desc;
471470
u32 rdo;

0 commit comments

Comments
 (0)