]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
usb: host: tegra: get usb phy configuration from phy node
authorSvyatoslav Ryhel <clamor95@gmail.com>
Thu, 17 Aug 2023 17:15:18 +0000 (20:15 +0300)
committerSvyatoslav Ryhel <clamor95@gmail.com>
Sun, 13 Oct 2024 14:33:39 +0000 (17:33 +0300)
Obtain USB phy configuration from phy node if such exists
and is enabled. If no, set default values.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
arch/arm/include/asm/arch-tegra/usb.h
drivers/usb/host/ehci-tegra.c

index 6e6ea1443cb0558fcf4b7df65daa55019bb429bc..2ae109ab6c189a060224ba4027f0e4685e88979f 100644 (file)
@@ -336,10 +336,13 @@ struct usb_ctlr {
 #define UTMIP_XCVR_HSSLEW_MSB_SHIFT            25
 #define UTMIP_XCVR_HSSLEW_MSB_MASK             \
                        (0x7f << UTMIP_XCVR_HSSLEW_MSB_SHIFT)
-#define UTMIP_XCVR_SETUP_MSB_SHIFT     22
-#define UTMIP_XCVR_SETUP_MSB_MASK      (0x7 << UTMIP_XCVR_SETUP_MSB_SHIFT)
-#define UTMIP_XCVR_SETUP_SHIFT         0
-#define UTMIP_XCVR_SETUP_MASK          (0xf << UTMIP_XCVR_SETUP_SHIFT)
+
+#define UTMIP_XCVR_SETUP(x)                    (((x) & 0xf) << 0)
+#define UTMIP_XCVR_SETUP_MSB(x)                        ((((x) & 0x70) >> 4) << 22)
+#define UTMIP_XCVR_LSRSLEW(x)                  (((x) & 0x3) << 8)
+#define UTMIP_XCVR_LSFSLEW(x)                  (((x) & 0x3) << 10)
+#define UTMIP_XCVR_HSSLEW(x)                   (((x) & 0x3) << 4)
+#define UTMIP_XCVR_HSSLEW_MSB(x)               ((((x) & 0x1fc) >> 2) << 25)
 
 /* USBx_UTMIP_XCVR_CFG1_0 */
 #define UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT                18
index 343893b9f19acba389263fade3ccc11a89a03adb..7c73eb66b6056bc4d879c64fcf004b990204a7e5 100644 (file)
@@ -66,9 +66,24 @@ enum usb_ctlr_type {
        USB_CTRL_COUNT,
 };
 
+struct tegra_utmip_config {
+       u32 hssync_start_delay;
+       u32 elastic_limit;
+       u32 idle_wait_delay;
+       u32 term_range_adj;
+       bool xcvr_setup_use_fuses;
+       u32 xcvr_setup;
+       u32 xcvr_lsfslew;
+       u32 xcvr_lsrslew;
+       u32 xcvr_hsslew;
+       u32 hssquelch_level;
+       u32 hsdiscon_level;
+};
+
 /* Information about a USB port */
 struct fdt_usb {
        struct ehci_ctrl ehci;
+       struct tegra_utmip_config utmip_config;
        struct usb_ctlr *reg;   /* address of registers in physical memory */
        unsigned utmi:1;        /* 1 if port has external tranceiver, else 0 */
        unsigned ulpi:1;        /* 1 if port has external ULPI transceiver */
@@ -192,15 +207,6 @@ static const unsigned T210_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = {
        { 0x028, 0x01, 0x01, 0x0,   0,  0x02, 0x2F, 0x08, 0x76,  65000,  5 }
 };
 
-/* UTMIP Idle Wait Delay */
-static const u8 utmip_idle_wait_delay = 17;
-
-/* UTMIP Elastic limit */
-static const u8 utmip_elastic_limit = 16;
-
-/* UTMIP High Speed Sync Start Delay */
-static const u8 utmip_hs_sync_start_delay = 9;
-
 struct fdt_usb_controller {
        /* flag to determine whether controller supports hostpc register */
        u32 has_hostpc:1;
@@ -377,6 +383,7 @@ static int init_utmi_usb_controller(struct fdt_usb *config,
        u32 b_sess_valid_mask, val;
        int loop_count;
        const unsigned *timing;
+       struct tegra_utmip_config *utmip_config = &config->utmip_config;
        struct usb_ctlr *usbctlr = config->reg;
        struct clk_rst_ctlr *clkrst;
        struct usb_ctlr *usb1ctlr;
@@ -463,16 +470,29 @@ static int init_utmi_usb_controller(struct fdt_usb *config,
 
                /* Recommended PHY settings for EYE diagram */
                val = readl(&usbctlr->utmip_xcvr_cfg0);
-               clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MASK,
-                               0x4 << UTMIP_XCVR_SETUP_SHIFT);
-               clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB_MASK,
-                               0x3 << UTMIP_XCVR_SETUP_MSB_SHIFT);
-               clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB_MASK,
-                               0x8 << UTMIP_XCVR_HSSLEW_MSB_SHIFT);
+
+               if (!utmip_config->xcvr_setup_use_fuses) {
+                       clrsetbits_le32(&val, UTMIP_XCVR_SETUP(~0),
+                                       UTMIP_XCVR_SETUP(utmip_config->xcvr_setup));
+                       clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB(~0),
+                                       UTMIP_XCVR_SETUP_MSB(utmip_config->xcvr_setup));
+               }
+
+               clrsetbits_le32(&val, UTMIP_XCVR_LSFSLEW(~0),
+                               UTMIP_XCVR_LSFSLEW(utmip_config->xcvr_lsfslew));
+               clrsetbits_le32(&val, UTMIP_XCVR_LSRSLEW(~0),
+                               UTMIP_XCVR_LSRSLEW(utmip_config->xcvr_lsrslew));
+
+               clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW(~0),
+                               UTMIP_XCVR_HSSLEW(utmip_config->xcvr_hsslew));
+               clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB(~0),
+                               UTMIP_XCVR_HSSLEW_MSB(utmip_config->xcvr_hsslew));
                writel(val, &usbctlr->utmip_xcvr_cfg0);
+
                clrsetbits_le32(&usbctlr->utmip_xcvr_cfg1,
                                UTMIP_XCVR_TERM_RANGE_ADJ_MASK,
-                               0x7 << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT);
+                               utmip_config->term_range_adj <<
+                               UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT);
 
                /* Some registers can be controlled from USB1 only. */
                if (config->periph_id != PERIPH_ID_USBD) {
@@ -485,9 +505,11 @@ static int init_utmi_usb_controller(struct fdt_usb *config,
                val = readl(&usb1ctlr->utmip_bias_cfg0);
                setbits_le32(&val, UTMIP_HSDISCON_LEVEL_MSB);
                clrsetbits_le32(&val, UTMIP_HSDISCON_LEVEL_MASK,
-                               0x1 << UTMIP_HSDISCON_LEVEL_SHIFT);
+                               utmip_config->hsdiscon_level <<
+                               UTMIP_HSDISCON_LEVEL_SHIFT);
                clrsetbits_le32(&val, UTMIP_HSSQUELCH_LEVEL_MASK,
-                               0x2 << UTMIP_HSSQUELCH_LEVEL_SHIFT);
+                               utmip_config->hssquelch_level <<
+                               UTMIP_HSSQUELCH_LEVEL_SHIFT);
                writel(val, &usb1ctlr->utmip_bias_cfg0);
 
                /* Miscellaneous setting mentioned in Programming Guide */
@@ -521,7 +543,11 @@ static int init_utmi_usb_controller(struct fdt_usb *config,
        setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG);
 
        clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE);
-       setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL);
+
+       if (utmip_config->xcvr_setup_use_fuses)
+               setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL);
+       else
+               clrbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL);
 
        /*
         * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT
@@ -535,15 +561,16 @@ static int init_utmi_usb_controller(struct fdt_usb *config,
        /* Set PLL enable delay count and Crystal frequency count */
        val = readl(&usbctlr->utmip_hsrx_cfg0);
        clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK,
-               utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT);
+               utmip_config->idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT);
        clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK,
-               utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT);
+               utmip_config->elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT);
        writel(val, &usbctlr->utmip_hsrx_cfg0);
 
        /* Configure the UTMIP_HS_SYNC_START_DLY */
        clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1,
                UTMIP_HS_SYNC_START_DLY_MASK,
-               utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT);
+               utmip_config->hssync_start_delay <<
+               UTMIP_HS_SYNC_START_DLY_SHIFT);
 
        /* Preceed the crystal clock disable by >100ns delay. */
        udelay(1);
@@ -763,6 +790,69 @@ static int fdt_decode_usb(struct udevice *dev, struct fdt_usb *config)
        return 0;
 }
 
+static void fdt_decode_usb_phy(struct udevice *dev)
+{
+       struct fdt_usb *priv = dev_get_priv(dev);
+       struct tegra_utmip_config *utmip_config = &priv->utmip_config;
+       u32 usb_phy_phandle;
+       ofnode usb_phy_node;
+       int ret;
+
+       ret = ofnode_read_u32(dev_ofnode(dev), "nvidia,phy", &usb_phy_phandle);
+       if (ret)
+               log_debug("%s: required usb phy node isn't provided\n", __func__);
+
+       usb_phy_node = ofnode_get_by_phandle(usb_phy_phandle);
+       if (!ofnode_valid(usb_phy_node) || !ofnode_is_enabled(usb_phy_node)) {
+               log_debug("%s: failed to find usb phy node or it is disabled\n", __func__);
+               utmip_config->xcvr_setup_use_fuses = true;
+       } else {
+               utmip_config->xcvr_setup_use_fuses =
+                       ofnode_read_bool(usb_phy_node, "nvidia,xcvr-setup-use-fuses");
+       }
+
+       utmip_config->hssync_start_delay =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,hssync-start-delay", 0x9);
+
+       utmip_config->elastic_limit =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,elastic-limit", 0x10);
+
+       utmip_config->idle_wait_delay =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,idle-wait-delay", 0x11);
+
+       utmip_config->term_range_adj =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,term-range-adj", 0x7);
+
+       utmip_config->xcvr_lsfslew =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,xcvr-lsfslew", 0x0);
+
+       utmip_config->xcvr_lsrslew =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,xcvr-lsrslew", 0x3);
+
+       utmip_config->xcvr_hsslew =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,xcvr-hsslew", 0x8);
+
+       utmip_config->hssquelch_level =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,hssquelch-level", 0x2);
+
+       utmip_config->hsdiscon_level =
+               ofnode_read_u32_default(usb_phy_node,
+                                       "nvidia,hsdiscon-level", 0x1);
+
+       if (!utmip_config->xcvr_setup_use_fuses) {
+               ofnode_read_u32(usb_phy_node, "nvidia,xcvr-setup",
+                               &utmip_config->xcvr_setup);
+       }
+}
+
 int usb_common_init(struct fdt_usb *config, enum usb_init_type init)
 {
        int ret = 0;
@@ -850,6 +940,8 @@ static int ehci_usb_of_to_plat(struct udevice *dev)
 
        priv->type = dev_get_driver_data(dev);
 
+       fdt_decode_usb_phy(dev);
+
        return 0;
 }