Add rkcomphy(3), a driver for the "naneng" combo PHY found on the RK356x
authorkettenis <kettenis@openbsd.org>
Sun, 12 Mar 2023 14:29:50 +0000 (14:29 +0000)
committerkettenis <kettenis@openbsd.org>
Sun, 12 Mar 2023 14:29:50 +0000 (14:29 +0000)
(and RK3588).  This is a PIPE PHY with support for PCIe, SATA, USB3, SGMII
and QSGMII.  For now only PCIe, SATA and USB3 support are implemented.
SATA support has not been tested.

Also add the refernce clocks needed by the PHYs to rkclock(4).

ok mlarkin@

sys/arch/arm64/conf/GENERIC
sys/arch/arm64/conf/RAMDISK
sys/dev/fdt/files.fdt
sys/dev/fdt/rkclock.c
sys/dev/fdt/rkclock_clocks.h
sys/dev/fdt/rkcomphy.c [new file with mode: 0644]

index 4063fcc..d810a15 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.260 2023/03/04 22:36:15 kettenis Exp $
+# $OpenBSD: GENERIC,v 1.261 2023/03/12 14:29:50 kettenis Exp $
 #
 # GENERIC machine description file
 #
@@ -290,6 +290,7 @@ sfp*                at fdt?
 rkclock*       at fdt? early 1
 rkgrf*         at fdt? early 1
 rkpinctrl*     at fdt? early 1
+rkcomphy*      at fdt? early 1
 rktcphy*       at fdt? early 1
 rkanxdp*       at fdt?
 rkdrm*         at fdt?
index f0cd794..214391d 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.191 2023/03/04 22:48:00 kettenis Exp $
+# $OpenBSD: RAMDISK,v 1.192 2023/03/12 14:29:50 kettenis Exp $
 
 machine                arm64
 maxusers       4
@@ -221,6 +221,7 @@ sfp*                at fdt?
 rkclock*       at fdt? early 1
 rkgrf*         at fdt? early 1
 rkpinctrl*     at fdt? early 1
+rkcomphy*      at fdt? early 1
 rktcphy*       at fdt? early 1
 rkemmcphy*     at fdt?
 rkgpio*                at fdt?
index f1dfa0e..26663e9 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.fdt,v 1.179 2023/02/14 08:26:59 kettenis Exp $
+#      $OpenBSD: files.fdt,v 1.180 2023/03/12 14:29:50 kettenis Exp $
 #
 # Config file and device description for machine-independent FDT code.
 # Included by ports that need it.
@@ -341,6 +341,10 @@ device     rkclock
 attach rkclock at fdt
 file   dev/fdt/rkclock.c               rkclock
 
+device rkcomphy
+attach rkcomphy at fdt
+file   dev/fdt/rkcomphy.c
+
 device rkdrm: drmbase, wsemuldisplaydev, rasops15, rasops16, rasops24, rasops32
 attach rkdrm at fdt
 file   dev/fdt/rkdrm.c                         rkdrm
index 28cbddf..223b2a4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rkclock.c,v 1.67 2023/03/10 10:54:29 kettenis Exp $   */
+/*     $OpenBSD: rkclock.c,v 1.68 2023/03/12 14:29:50 kettenis Exp $   */
 /*
  * Copyright (c) 2017, 2018 Mark Kettenis <kettenis@openbsd.org>
  *
 #define RK3568_PMUCRU_HPLL_CON(i)      (0x0040 + (i) * 4)
 #define RK3568_PMUCRU_MODE_CON         0x0080
 #define RK3568_PMUCRU_CLKSEL_CON(i)    (0x0100 + (i) * 4)
+#define RK3568_PMUCRU_GATE_CON(i)      (0x0180 + (i) * 4)
 
 /* RK3588 registers */
 #define RK3588_CRU_AUPLL_CON(i)                (0x00180 + (i) * 4)
@@ -3563,6 +3564,51 @@ const struct rkclock rk3568_pmu_clocks[] = {
                SEL(11, 10), 0,
                { 0, 0, RK3568_XIN24M }
        },
+       {
+               RK3568_CLK_PCIEPHY0_OSC0, 0, 0, 0,
+               { RK3568_XIN24M }
+       },
+       {
+               RK3568_CLK_PCIEPHY0_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
+               0, DIV(2, 0),
+               { RK3568_PPLL_PH0 }
+       },
+       {
+               RK3568_CLK_PCIEPHY0_REF, RK3568_PMUCRU_CLKSEL_CON(9),
+               SEL(3, 3), 0,
+               { RK3568_CLK_PCIEPHY0_OSC0, RK3568_CLK_PCIEPHY0_DIV },
+               SET_PARENT
+       },
+       {
+               RK3568_CLK_PCIEPHY1_OSC0, 0, 0, 0,
+               { RK3568_XIN24M }
+       },
+       {
+               RK3568_CLK_PCIEPHY1_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
+               0, DIV(6, 4),
+               { RK3568_PPLL_PH0 }
+       },
+       {
+               RK3568_CLK_PCIEPHY1_REF, RK3568_PMUCRU_CLKSEL_CON(9),
+               SEL(7, 7), 0,
+               { RK3568_CLK_PCIEPHY1_OSC0, RK3568_CLK_PCIEPHY1_DIV },
+               SET_PARENT
+       },
+       {
+               RK3568_CLK_PCIEPHY2_OSC0, 0, 0, 0,
+               { RK3568_XIN24M }
+       },
+       {
+               RK3568_CLK_PCIEPHY2_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
+               0, DIV(10, 8),
+               { RK3568_PPLL_PH0 }
+       },
+       {
+               RK3568_CLK_PCIEPHY2_REF, RK3568_PMUCRU_CLKSEL_CON(9),
+               SEL(11, 11), 0,
+               { RK3568_CLK_PCIEPHY2_OSC0, RK3568_CLK_PCIEPHY2_DIV },
+               SET_PARENT
+       },
        {
                RK3568_CLK_PDPMU, RK3568_PMUCRU_CLKSEL_CON(2),
                SEL(15, 15), 0,
@@ -3576,6 +3622,16 @@ const struct rkclock rk3568_pmu_clocks[] = {
 void
 rk3568_pmu_init(struct rkclock_softc *sc)
 {
+       int i;
+
+       /* The code below assumes all clocks are enabled.  Check this!. */
+       for (i = 0; i <= 2; i++) {
+               if (HREAD4(sc, RK3568_PMUCRU_GATE_CON(i)) != 0x00000000) {
+                       printf("CRU_GATE_CON%d: 0x%08x\n", i,
+                           HREAD4(sc, RK3568_CRU_GATE_CON(i)));
+               }
+       }
+
        sc->sc_clocks = rk3568_pmu_clocks;
 }
 
@@ -3656,6 +3712,9 @@ rk3568_pmu_get_frequency(void *cookie, uint32_t *cells)
                return rk3328_get_pll(sc, RK3568_PMUCRU_PPLL_CON(0));
        case RK3568_PLL_HPLL:
                return rk3328_get_pll(sc, RK3568_PMUCRU_HPLL_CON(0));
+       case RK3568_PPLL_PH0:
+               idx = RK3568_PLL_PPLL;
+               return rk3568_get_frequency(sc, &idx) / 2;
        case RK3568_XIN24M:
                return 24000000;
        default:
@@ -3689,6 +3748,9 @@ rk3568_pmu_enable(void *cookie, uint32_t *cells, int on)
        uint32_t idx = cells[0];
 
        switch (idx) {
+       case RK3568_CLK_PCIEPHY0_REF:
+       case RK3568_CLK_PCIEPHY1_REF:
+       case RK3568_CLK_PCIEPHY2_REF:
        case RK3568_CLK_I2C0:
        case RK3568_SCLK_UART0:
        case RK3568_PCLK_I2C0:
index ae01215..7233a1b 100644 (file)
 
 #define RK3568_CLK_I2C0                        7
 #define RK3568_SCLK_UART0              11
-#define RK3568_PCLK_I2C0                       45
+#define RK3568_CLK_PCIEPHY0_DIV                29
+#define RK3568_CLK_PCIEPHY0_OSC0       30
+#define RK3568_CLK_PCIEPHY0_REF                31
+#define RK3568_CLK_PCIEPHY1_DIV                32
+#define RK3568_CLK_PCIEPHY1_OSC0       33
+#define RK3568_CLK_PCIEPHY1_REF                34
+#define RK3568_CLK_PCIEPHY2_DIV                35
+#define RK3568_CLK_PCIEPHY2_OSC0       36
+#define RK3568_CLK_PCIEPHY2_REF                37
+#define RK3568_PCLK_I2C0               45
 #define RK3568_CLK_PDPMU               49
 
+#define RK3568_PPLL_PH0                        1022
+
 /*
  * RK3588 clocks.
  */
diff --git a/sys/dev/fdt/rkcomphy.c b/sys/dev/fdt/rkcomphy.c
new file mode 100644 (file)
index 0000000..16920e9
--- /dev/null
@@ -0,0 +1,310 @@
+/*     $OpenBSD: rkcomphy.c,v 1.1 2023/03/12 14:29:50 kettenis Exp $   */
+/*
+ * Copyright (c) 2023 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/ofw_misc.h>
+#include <dev/ofw/fdt.h>
+
+/* Combo PHY registers */
+#define COMBO_PIPE_PHY_REG(idx)                        ((idx) * 4)
+/* REG_005 */
+#define  COMBO_PIPE_PHY_PLL_DIV_MASK           (0x3 << 6)
+#define  COMBO_PIPE_PHY_PLL_DIV_2              (0x1 << 6)
+/* REG_006 */
+#define  COMBO_PIPE_PHY_TX_RTERM_50OHM         (0x8 << 4)
+#define  COMBO_PIPE_PHY_RX_RTERM_44OHM         (0xf << 4)
+/* REG_010 */
+#define  COMBO_PIPE_PHY_SU_TRIM_0_7            0xf0
+/* REG_011 */
+#define  COMBO_PIPE_PHY_PLL_LPF_ADJ_VALUE      4
+/* REG_014 */
+#define  COMBO_PIPE_PHY_SSC_CNT_LO_MASK                (0x3 << 6)
+#define  COMBO_PIPE_PHY_SSC_CNT_LO_VALUE       (0x1 << 6)
+#define  COMBO_PIPE_PHY_CTLE_EN                        (1 << 0)
+/* REG_015 */
+#define  COMBO_PIPE_PHY_SSC_CNT_HI_MASK                (0xff << 0)
+#define  COMBO_PIPE_PHY_SSC_CNT_HI_VALUE       (0x5f << 0)
+/* REG_017 */
+#define  COMBO_PIPE_PHY_PLL_LOOP               0x32
+/* REG_031 */
+#define  COMBO_PIPE_PHY_SSC_DIR_MASK           (0x3 << 4)
+#define  COMBO_PIPE_PHY_SSC_DIR_DOWN           (0x1 << 4)
+#define  COMBO_PIPE_PHY_SSC_OFFSET_MASK                (0x3 << 6)
+#define  COMBO_PIPE_PHY_SSC_OFFSET_500PPM      (0x1 << 6)
+/* REG_032 */
+#define  COMBO_PIPE_PHY_PLL_KVCO_MASK          (0x7 << 2)
+#define  COMBO_PIPE_PHY_PLL_KVCO_VALUE         (0x2 << 2)
+
+/* GRF registers */
+#define PIPE_GRF_PIPE_CON0                     0x0000
+
+/* PHY GRF registers */
+#define PIPE_PHY_GRF_PIPE_CON(idx)             ((idx) * 4)
+/* CON0 */
+#define  PIPE_PHY_GRF_PIPE_MODE_PCIE           0x003f0000
+#define  PIPE_PHY_GRF_PIPE_MODE_USB            0x003f0004
+#define  PIPE_PHY_GRF_PIPE_MODE_SATA           0x003f0019
+/* CON1 */
+#define  PIPE_PHY_GRF_PIPE_CLK_24M             0x60000000
+#define  PIPE_PHY_GRF_PIPE_CLK_25M             0x60002000
+#define  PIPE_PHY_GRF_PIPE_CLK_100M            0x60004000
+/* CON2 */
+#define  PIPE_PHY_GRF_PIPE_TXCOMP_SEL_CTRL     0x80000000
+#define  PIPE_PHY_GRF_PIPE_TXCOMP_SEL_GRF      0x80008000
+#define  PIPE_PHY_GRF_PIPE_TXELEC_SEL_CTRL     0x10000000
+#define  PIPE_PHY_GRF_PIPE_TXELEC_SEL_GRF      0x10001000
+/* CON3 */
+#define  PIPE_PHY_GRF_PIPE_SEL_PCIE            0x60000000
+#define  PIPE_PHY_GRF_PIPE_SEL_USB             0x60002000
+#define  PIPE_PHY_GRF_PIPE_SEL_SATA            0x60004000
+/* STATUS1 */
+#define PIPE_PHY_GRF_PIPE_STATUS1              0x34
+#define  PIPE_PHY_GRF_PIPE_PHYSTATUS           (1 << 6)
+
+#define HREAD4(sc, reg)                                                        \
+       (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
+#define HWRITE4(sc, reg, val)                                          \
+       bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define HSET4(sc, reg, bits)                                           \
+       HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
+#define HCLR4(sc, reg, bits)                                           \
+       HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
+
+struct rkcomphy_softc {
+       struct device           sc_dev;
+       bus_space_tag_t         sc_iot;
+       bus_space_handle_t      sc_ioh;
+
+       struct phy_device       sc_pd;
+};
+
+int    rkcomphy_match(struct device *, void *, void *);
+void   rkcomphy_attach(struct device *, struct device *, void *);
+
+const struct cfattach rkcomphy_ca = {
+       sizeof (struct rkcomphy_softc), rkcomphy_match, rkcomphy_attach
+};
+
+struct cfdriver rkcomphy_cd = {
+       NULL, "rkcomphy", DV_DULL
+};
+
+int    rkcomphy_enable(void *, uint32_t *);
+
+int
+rkcomphy_match(struct device *parent, void *match, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+
+       return OF_is_compatible(faa->fa_node,
+           "rockchip,rk3568-naneng-combphy");
+}
+
+void
+rkcomphy_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct rkcomphy_softc *sc = (struct rkcomphy_softc *)self;
+       struct fdt_attach_args *faa = aux;
+
+       if (faa->fa_nreg < 1) {
+               printf(": no registers\n");
+               return;
+       }
+
+       sc->sc_iot = faa->fa_iot;
+       if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
+           faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
+               printf(": can't map registers\n");
+               return;
+       }
+
+       reset_assert_all(faa->fa_node);
+
+       printf("\n");
+
+       sc->sc_pd.pd_node = faa->fa_node;
+       sc->sc_pd.pd_cookie = sc;
+       sc->sc_pd.pd_enable = rkcomphy_enable;
+       phy_register(&sc->sc_pd);
+}
+
+void
+rkcomphy_pll_tune(struct rkcomphy_softc *sc)
+{
+       uint32_t reg;
+
+       reg = HREAD4(sc, COMBO_PIPE_PHY_REG(32));
+       reg &= ~COMBO_PIPE_PHY_PLL_KVCO_MASK;
+       reg |= COMBO_PIPE_PHY_PLL_KVCO_VALUE;
+       HWRITE4(sc, COMBO_PIPE_PHY_REG(32), reg);
+
+       HWRITE4(sc, COMBO_PIPE_PHY_REG(11), COMBO_PIPE_PHY_PLL_LPF_ADJ_VALUE);
+
+       reg = HREAD4(sc, COMBO_PIPE_PHY_REG(5));
+       reg &= ~COMBO_PIPE_PHY_PLL_DIV_MASK;
+       reg |= COMBO_PIPE_PHY_PLL_DIV_2;
+       HWRITE4(sc, COMBO_PIPE_PHY_REG(5), reg);
+
+       HWRITE4(sc, COMBO_PIPE_PHY_REG(17), COMBO_PIPE_PHY_PLL_LOOP);
+       HWRITE4(sc, COMBO_PIPE_PHY_REG(10), COMBO_PIPE_PHY_SU_TRIM_0_7);
+}
+
+int
+rkcomphy_enable(void *cookie, uint32_t *cells)
+{
+       struct rkcomphy_softc *sc = cookie;
+       struct regmap *rm, *phy_rm;
+       int node = sc->sc_pd.pd_node;
+       uint32_t type = cells[0];
+       uint32_t freq, grf, phy_grf, reg;
+       int stat, timo;
+
+       /* We only support PCIe, SATA and USB 3 for now. */
+       switch (type) {
+       case PHY_TYPE_PCIE:
+       case PHY_TYPE_SATA:
+       case PHY_TYPE_USB3:
+               break;
+       default:
+               return EINVAL;
+       }
+
+       grf = OF_getpropint(node, "rockchip,pipe-grf", 0);
+       rm = regmap_byphandle(grf);
+       if (rm == NULL)
+               return ENXIO;
+
+       phy_grf = OF_getpropint(node, "rockchip,pipe-phy-grf", 0);
+       phy_rm = regmap_byphandle(phy_grf);
+       if (phy_rm == NULL)
+               return ENXIO;
+
+       clock_set_assigned(node);
+       clock_enable_all(node);
+
+       if (type == PHY_TYPE_PCIE || type == PHY_TYPE_USB3) {
+               reg = HREAD4(sc, COMBO_PIPE_PHY_REG(31));
+               reg &= ~COMBO_PIPE_PHY_SSC_OFFSET_MASK;
+               reg &= ~COMBO_PIPE_PHY_SSC_DIR_MASK;
+               reg |= COMBO_PIPE_PHY_SSC_DIR_DOWN;
+               HWRITE4(sc, COMBO_PIPE_PHY_REG(31), reg);
+       }
+
+       if (type == PHY_TYPE_SATA || type == PHY_TYPE_USB3) {
+               reg = HREAD4(sc, COMBO_PIPE_PHY_REG(14));
+               reg |= COMBO_PIPE_PHY_CTLE_EN;
+               HWRITE4(sc, COMBO_PIPE_PHY_REG(14), reg);
+       }
+
+       switch (type) {
+       case PHY_TYPE_PCIE:
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 0xffff1000);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 0xffff0000);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 0xffff0101);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 0xffff0200);
+               break;
+       case PHY_TYPE_SATA:
+               HWRITE4(sc, COMBO_PIPE_PHY_REG(6),
+                   COMBO_PIPE_PHY_TX_RTERM_50OHM |
+                   COMBO_PIPE_PHY_RX_RTERM_44OHM);
+
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 0xffff0119);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 0xffff0040);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 0xffff80c3);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 0xffff4407);
+               regmap_write_4(rm, PIPE_GRF_PIPE_CON0, 0xffff2220);
+               break;
+       case PHY_TYPE_USB3:
+               rkcomphy_pll_tune(sc);
+
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0),
+                   PIPE_PHY_GRF_PIPE_MODE_USB);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2),
+                   PIPE_PHY_GRF_PIPE_TXCOMP_SEL_CTRL);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2),
+                   PIPE_PHY_GRF_PIPE_TXELEC_SEL_CTRL);
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3),
+                   PIPE_PHY_GRF_PIPE_SEL_USB);
+               break;
+       }
+
+       freq = clock_get_frequency(node, "ref");
+       switch (freq) {
+       case 24000000:
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1),
+                   PIPE_PHY_GRF_PIPE_CLK_24M);
+               if (type == PHY_TYPE_SATA || type == PHY_TYPE_USB3) {
+                       reg = HREAD4(sc, COMBO_PIPE_PHY_REG(14));
+                       reg &= ~COMBO_PIPE_PHY_SSC_CNT_LO_MASK;
+                       reg |= COMBO_PIPE_PHY_SSC_CNT_LO_VALUE;
+                       HWRITE4(sc, COMBO_PIPE_PHY_REG(14), reg);
+                       reg = HREAD4(sc, COMBO_PIPE_PHY_REG(15));
+                       reg &= ~COMBO_PIPE_PHY_SSC_CNT_HI_MASK;
+                       reg |= COMBO_PIPE_PHY_SSC_CNT_HI_VALUE;
+                       HWRITE4(sc, COMBO_PIPE_PHY_REG(15), reg);
+               }
+               break;
+       case 25000000:
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1),
+                   PIPE_PHY_GRF_PIPE_CLK_25M);
+               break;
+       case 100000000:
+               regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1),
+                   PIPE_PHY_GRF_PIPE_CLK_100M);
+               switch (type) {
+               case PHY_TYPE_PCIE:
+                       rkcomphy_pll_tune(sc);
+                       break;
+               case PHY_TYPE_SATA:
+                       reg = HREAD4(sc, COMBO_PIPE_PHY_REG(31));
+                       reg &= ~COMBO_PIPE_PHY_SSC_OFFSET_MASK;
+                       reg |= COMBO_PIPE_PHY_SSC_OFFSET_500PPM;
+                       reg &= ~COMBO_PIPE_PHY_SSC_DIR_MASK;
+                       reg |= COMBO_PIPE_PHY_SSC_DIR_DOWN;
+                       HWRITE4(sc, COMBO_PIPE_PHY_REG(31), reg);
+                       break;
+               }
+               break;
+       }
+
+       reset_deassert_all(node);
+
+       if (type == PHY_TYPE_USB3) {
+               for (timo = 100; timo > 0; timo--) {
+                       stat = regmap_read_4(phy_rm,
+                           PIPE_PHY_GRF_PIPE_STATUS1);
+                       if ((stat & PIPE_PHY_GRF_PIPE_PHYSTATUS) == 0)
+                               break;
+                       delay(10);
+               }
+               if (timo == 0) {
+                       printf("%s: timeout\n", sc->sc_dev.dv_xname);
+                       return ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}