mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
usb: host: tegra: get usb phy configuration from phy node
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>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user