Skip to content

Commit a0450ec

Browse files
claudiubezneajfvogel
authored andcommitted
phy: renesas: rcar-gen3-usb2: Fix role detection on unbind/bind
commit 54c4c58713aaff76c2422ff5750e557ab3b100d7 upstream. It has been observed on the Renesas RZ/G3S SoC that unbinding and binding the PHY driver leads to role autodetection failures. This issue occurs when PHY 3 is the first initialized PHY. PHY 3 does not have an interrupt associated with the USB2_INT_ENABLE register (as rcar_gen3_int_enable[3] = 0). As a result, rcar_gen3_init_otg() is called to initialize OTG without enabling PHY interrupts. To resolve this, add rcar_gen3_is_any_otg_rphy_initialized() and call it in role_store(), role_show(), and rcar_gen3_init_otg(). At the same time, rcar_gen3_init_otg() is only called when initialization for a PHY with interrupt bits is in progress. As a result, the struct rcar_gen3_phy::otg_initialized is no longer needed. Fixes: 549b6b5 ("phy: renesas: rcar-gen3-usb2: enable/disable independent irqs") Cc: [email protected] Reviewed-by: Yoshihiro Shimoda <[email protected]> Tested-by: Yoshihiro Shimoda <[email protected]> Reviewed-by: Lad Prabhakar <[email protected]> Signed-off-by: Claudiu Beznea <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> (cherry picked from commit c78a5693bd15f7a5f62f6c8621140fc646e73b89) Signed-off-by: Jack Vogel <[email protected]>
1 parent b369f98 commit a0450ec

File tree

1 file changed

+14
-19
lines changed

1 file changed

+14
-19
lines changed

drivers/phy/renesas/phy-rcar-gen3-usb2.c

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ struct rcar_gen3_phy {
107107
struct rcar_gen3_chan *ch;
108108
u32 int_enable_bits;
109109
bool initialized;
110-
bool otg_initialized;
111110
bool powered;
112111
};
113112

@@ -320,16 +319,15 @@ static bool rcar_gen3_is_any_rphy_initialized(struct rcar_gen3_chan *ch)
320319
return false;
321320
}
322321

323-
static bool rcar_gen3_needs_init_otg(struct rcar_gen3_chan *ch)
322+
static bool rcar_gen3_is_any_otg_rphy_initialized(struct rcar_gen3_chan *ch)
324323
{
325-
int i;
326-
327-
for (i = 0; i < NUM_OF_PHYS; i++) {
328-
if (ch->rphys[i].otg_initialized)
329-
return false;
324+
for (enum rcar_gen3_phy_index i = PHY_INDEX_BOTH_HC; i <= PHY_INDEX_EHCI;
325+
i++) {
326+
if (ch->rphys[i].initialized)
327+
return true;
330328
}
331329

332-
return true;
330+
return false;
333331
}
334332

335333
static bool rcar_gen3_are_all_rphys_power_off(struct rcar_gen3_chan *ch)
@@ -351,7 +349,7 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
351349
bool is_b_device;
352350
enum phy_mode cur_mode, new_mode;
353351

354-
if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch))
352+
if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch))
355353
return -EIO;
356354

357355
if (sysfs_streq(buf, "host"))
@@ -389,7 +387,7 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr,
389387
{
390388
struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
391389

392-
if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch))
390+
if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch))
393391
return -EIO;
394392

395393
return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" :
@@ -402,6 +400,9 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
402400
void __iomem *usb2_base = ch->base;
403401
u32 val;
404402

403+
if (!ch->is_otg_channel || rcar_gen3_is_any_otg_rphy_initialized(ch))
404+
return;
405+
405406
/* Should not use functions of read-modify-write a register */
406407
val = readl(usb2_base + USB2_LINECTRL1);
407408
val = (val & ~USB2_LINECTRL1_DP_RPD) | USB2_LINECTRL1_DPRPD_EN |
@@ -465,12 +466,9 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
465466
writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET);
466467
writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
467468

468-
/* Initialize otg part */
469-
if (channel->is_otg_channel) {
470-
if (rcar_gen3_needs_init_otg(channel))
471-
rcar_gen3_init_otg(channel);
472-
rphy->otg_initialized = true;
473-
}
469+
/* Initialize otg part (only if we initialize a PHY with IRQs). */
470+
if (rphy->int_enable_bits)
471+
rcar_gen3_init_otg(channel);
474472

475473
rphy->initialized = true;
476474

@@ -486,9 +484,6 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p)
486484

487485
rphy->initialized = false;
488486

489-
if (channel->is_otg_channel)
490-
rphy->otg_initialized = false;
491-
492487
val = readl(usb2_base + USB2_INT_ENABLE);
493488
val &= ~rphy->int_enable_bits;
494489
if (!rcar_gen3_is_any_rphy_initialized(channel))

0 commit comments

Comments
 (0)