Skip to content

Commit

Permalink
usb: host: tegra: get usb phy configuration from phy node
Browse files Browse the repository at this point in the history
Obtain USB phy configuration from phy node is such exists
and is enabled. If no, set default values.

Signed-off-by: Svyatoslav Ryhel <[email protected]>
  • Loading branch information
clamor-s committed Oct 3, 2023
1 parent 6923eae commit e063ef2
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 26 deletions.
11 changes: 7 additions & 4 deletions arch/arm/include/asm/arch-tegra/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
127 changes: 105 additions & 22 deletions drivers/usb/host/ehci-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,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 */
Expand Down Expand Up @@ -193,15 +208,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;
Expand Down Expand Up @@ -378,6 +384,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;
Expand Down Expand Up @@ -464,16 +471,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) {
Expand All @@ -486,9 +506,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 */
Expand Down Expand Up @@ -522,7 +544,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
Expand All @@ -536,15 +562,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);
Expand Down Expand Up @@ -764,6 +791,60 @@ 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;
Expand Down Expand Up @@ -851,6 +932,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;
}

Expand Down

0 comments on commit e063ef2

Please sign in to comment.