diff --git a/patches/28-dwc3-otg-no-live-reinit.patch b/patches/28-dwc3-otg-no-live-reinit.patch deleted file mode 100644 index 386076d..0000000 --- a/patches/28-dwc3-otg-no-live-reinit.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c ---- a/drivers/usb/dwc3/drd.c -+++ b/drivers/usb/dwc3/drd.c -@@ -55,7 +55,17 @@ - - spin_lock(&dwc->lock); - if (dwc->otg_restart_host) { -- dwc3_otg_host_init(dwc); -+ /* -+ * flare-edge#160: dwc3_otg_host_init() is documented as "should be -+ * called before Host controller driver is started" but this path -+ * only ever runs while current_otg_role is already HOST. Skip it -+ * on a live host and record that we did. -+ */ -+ if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) -+ dev_warn_ratelimited(dwc->dev, -+ "OTGDIAG skipped host re-init on live host\n"); -+ else -+ dwc3_otg_host_init(dwc); - dwc->otg_restart_host = false; - } - -@@ -83,6 +93,10 @@ - if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST && - !(reg & DWC3_OEVT_DEVICEMODE)) - dwc->otg_restart_host = true; -+ /* flare-edge#160 diagnostic: is the OTG event path active at all? */ -+ dev_warn_ratelimited(dwc->dev, -+ "OTGDIAG irq OEVT=0x%08x role=%u restart=%d\n", -+ reg, dwc->current_otg_role, dwc->otg_restart_host); - dwc3_writel(dwc, DWC3_OEVT, reg); - ret = IRQ_WAKE_THREAD; - } diff --git a/patches/29-usb2phy-no-otg-sm-in-host.patch b/patches/29-usb2phy-no-otg-sm-in-host.patch new file mode 100644 index 0000000..932a12b --- /dev/null +++ b/patches/29-usb2phy-no-otg-sm-in-host.patch @@ -0,0 +1,94 @@ +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -203,6 +203,7 @@ + * @event_nb: hold event notification callback. + * @state: define OTG enumeration states before device reset. + * @mode: the dr_mode of the controller. ++ * @host_mode: the port is currently acting as a USB host. + */ + struct rockchip_usb2phy_port { + struct phy *phy; +@@ -222,6 +223,7 @@ + struct notifier_block event_nb; + enum usb_otg_state state; + enum usb_dr_mode mode; ++ bool host_mode; + }; + + /** +@@ -649,11 +651,52 @@ + return 0; + } + ++/* ++ * The OTG port's state machines only make sense while the port is a ++ * peripheral. In host role their inputs are meaningless on a board with no ++ * ID source: charger detection drives the analog front end of a port that is ++ * already enumerating a device, and its DCP verdict ends in ++ * rockchip_usb2phy_power_off(), which suspends the phy and drops the 480M ++ * clkout that the host controller's core runs on. The controller then stops ++ * clocking with its registers still readable, so it reports itself healthy ++ * while no transfer ever completes. ++ * ++ * dwc3 already calls phy_set_mode() on every role change, but this driver ++ * implemented no .set_mode, so the phy never learned the role. Track it and ++ * keep both state machines out of host role. ++ */ ++static int rockchip_usb2phy_set_mode(struct phy *phy, enum phy_mode mode, ++ int submode) ++{ ++ struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); ++ ++ if (rport->port_id != USB2PHY_PORT_OTG) ++ return 0; ++ ++ switch (mode) { ++ case PHY_MODE_USB_HOST: ++ if (!rport->host_mode) { ++ rport->host_mode = true; ++ cancel_delayed_work_sync(&rport->otg_sm_work); ++ cancel_delayed_work_sync(&rport->chg_work); ++ } ++ break; ++ case PHY_MODE_USB_DEVICE: ++ rport->host_mode = false; ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ + static const struct phy_ops rockchip_usb2phy_ops = { + .init = rockchip_usb2phy_init, + .exit = rockchip_usb2phy_exit, + .power_on = rockchip_usb2phy_power_on, + .power_off = rockchip_usb2phy_power_off, ++ .set_mode = rockchip_usb2phy_set_mode, + .owner = THIS_MODULE, + }; + +@@ -667,6 +710,10 @@ + unsigned long delay; + bool vbus_attach, sch_work, notify_charger; + ++ /* In host role this machine can only get the answer wrong. */ ++ if (rport->host_mode) ++ return; ++ + vbus_attach = property_enabled(rphy->grf, + &rport->port_cfg->utmi_bvalid); + +@@ -825,6 +872,10 @@ + bool is_dcd, tmout, vout, vbus_attach; + unsigned long delay; + ++ /* Never probe the front end of a port that is hosting a device. */ ++ if (rport->host_mode) ++ return; ++ + vbus_attach = property_enabled(rphy->grf, &rport->port_cfg->utmi_bvalid); + + dev_dbg(&rport->phy->dev, "chg detection work state = %d\n", diff --git a/patches/README.md b/patches/README.md index db08dc1..14f1e34 100644 --- a/patches/README.md +++ b/patches/README.md @@ -18,6 +18,8 @@ with `../build/warden_defconfig` -> `zImage` + `rv1106-warden.dtb`). | `15-pinctrl.patch` | `pinctrl-rockchip` RV1106 iomux | | `20-arch-dts-bindings.patch` | `arch/arm` DTs (`rv1106.dtsi`, `rv1106-warden.dts`, pinctrl), mach, configs, `include/dt-bindings` | | `25-usb-phy.patch` | inno-usb2 phy | +| `27-usb-phy-tuning.patch` | inno-usb2 phy: RV1106 signal-quality register tuning | +| `29-usb2phy-no-otg-sm-in-host.patch` | inno-usb2 phy: keep the OTG/charger state machines out of host role | | `30-drm-vop-panel-rgb.patch` | VOP (`rgb_dclk_pol`=0 + WIN1 scanout), panel-simple bus-format, rockchip_rgb | | `35-mailbox-hpmcu.patch` | rockchip-mailbox (rv1106 num_chans=1) | | `40-pvtm-soc.patch` | PVTM (core+pmu) + `include/soc/rockchip/pvtm.h` |