[ARM] tegra: Add USB PHY configuration

Configure board dependant phy settings from the board file.

Change-Id: I29f6ffe0b84a2a6eb55bade1379002f561d92d17
Signed-off-by: Benoit Goby <benoit@android.com>
This commit is contained in:
Benoit Goby
2010-07-28 00:10:13 -07:00
committed by Colin Cross
parent a0e0319691
commit ce3a041d2e
5 changed files with 60 additions and 16 deletions

View File

@@ -20,10 +20,21 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
struct tegra_utmip_config {
u8 hssync_start_delay;
u8 elastic_limit;
u8 idle_wait_delay;
u8 term_range_adj;
u8 xcvr_setup;
u8 xcvr_lsfslew;
u8 xcvr_lsrslew;
};
struct tegra_usb_phy {
int instance;
void __iomem *regs;
struct clk *pll_u;
struct tegra_utmip_config *config;
};
enum tegra_usb_phy_mode {
@@ -31,7 +42,8 @@ enum tegra_usb_phy_mode {
TEGRA_USB_PHY_MODE_HOST,
};
struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs);
struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
struct tegra_utmip_config *config);
int tegra_usb_phy_power_on(struct tegra_usb_phy *phy,
enum tegra_usb_phy_mode phy_mode);

View File

@@ -120,6 +120,27 @@ static const u16 udc_debounce_table[] = {
0xFDE8, /* 26 MHz */
};
static struct tegra_utmip_config utmip_default[] = {
[0] = {
.hssync_start_delay = 9,
.idle_wait_delay = 17,
.elastic_limit = 16,
.term_range_adj = 6,
.xcvr_setup = 9,
.xcvr_lsfslew = 1,
.xcvr_lsrslew = 1,
},
[2] = {
.hssync_start_delay = 9,
.idle_wait_delay = 17,
.elastic_limit = 16,
.term_range_adj = 6,
.xcvr_setup = 9,
.xcvr_lsfslew = 2,
.xcvr_lsrslew = 2,
},
};
static int utmi_phy_wait_stable(struct tegra_usb_phy *phy)
{
void __iomem *base = phy->regs;
@@ -141,6 +162,7 @@ static void utmi_phy_init(struct tegra_usb_phy *phy, int freq_sel)
{
unsigned long val;
void __iomem *base = phy->regs;
struct tegra_utmip_config *config = phy->config;
val = readl(base + USB_SUSP_CTRL);
val |= UTMIP_RESET;
@@ -154,12 +176,13 @@ static void utmi_phy_init(struct tegra_usb_phy *phy, int freq_sel)
val = readl(base + UTMIP_HSRX_CFG0);
val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
val |= UTMIP_IDLE_WAIT(17) | UTMIP_ELASTIC_LIMIT(16);
val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
writel(val, base + UTMIP_HSRX_CFG0);
val = readl(base + UTMIP_HSRX_CFG1);
val &= ~UTMIP_HS_SYNC_START_DLY(~0);
val |= UTMIP_HS_SYNC_START_DLY(9);
val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
writel(val, base + UTMIP_HSRX_CFG1);
val = readl(base + UTMIP_DEBOUNCE_CFG0);
@@ -189,6 +212,7 @@ void utmi_phy_power_on(struct tegra_usb_phy *phy,
{
unsigned long val;
void __iomem *base = phy->regs;
struct tegra_utmip_config *config = phy->config;
if (phy_mode == TEGRA_USB_PHY_MODE_DEVICE) {
val = readl(base + USB_SUSP_CTRL);
@@ -198,15 +222,12 @@ void utmi_phy_power_on(struct tegra_usb_phy *phy,
val = readl(base + UTMIP_XCVR_CFG0);
val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0));
if (phy_mode == TEGRA_USB_PHY_MODE_HOST) {
val &= ~(UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0));
val |= UTMIP_XCVR_LSFSLEW(2) | UTMIP_XCVR_LSRSLEW(2);
val |= UTMIP_XCVR_SETUP(0x9);
} else {
val &= ~(UTMIP_XCVR_HSSLEW_MSB(~0));
val |= UTMIP_XCVR_SETUP(0xF);
}
UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) |
UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) |
UTMIP_XCVR_HSSLEW_MSB(~0));
val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
writel(val, base + UTMIP_XCVR_CFG0);
val = readl(base + UTMIP_BIAS_CFG0);
@@ -216,7 +237,7 @@ void utmi_phy_power_on(struct tegra_usb_phy *phy,
val = readl(base + UTMIP_XCVR_CFG1);
val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
val |= UTMIP_XCVR_TERM_RANGE_ADJ(0x6);
val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
writel(val, base + UTMIP_XCVR_CFG1);
val = readl(base + UTMIP_BAT_CHRG_CFG0);
@@ -310,7 +331,8 @@ void utmi_phy_power_off(struct tegra_usb_phy *phy)
writel(val, base + UTMIP_XCVR_CFG1);
}
struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs)
struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
struct tegra_utmip_config *config)
{
struct tegra_usb_phy *phy;
unsigned long parent_rate;
@@ -323,6 +345,10 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs)
phy->instance = instance;
phy->regs = regs;
phy->config = config;
if (!phy->config)
phy->config = &utmip_default[instance];
phy->pll_u = clk_get_sys(NULL, "pll_u");
if (IS_ERR(phy->pll_u)) {

View File

@@ -22,6 +22,8 @@ int fsl_udc_clk_init(struct platform_device *pdev)
struct resource *res;
int err;
int instance;
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
udc_clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(udc_clk)) {
@@ -49,7 +51,7 @@ int fsl_udc_clk_init(struct platform_device *pdev)
if (instance == -1)
instance = 0;
phy = tegra_usb_phy_open(instance, udc_base);
phy = tegra_usb_phy_open(instance, udc_base, pdata->phy_config);
if (IS_ERR(phy)) {
dev_err(&pdev->dev, "Can't open phy\n");
err = PTR_ERR(phy);

View File

@@ -366,6 +366,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
struct tegra_ehci_hcd *tegra;
struct tegra_utmip_config *config;
int err = 0;
int irq;
unsigned int temp;
@@ -412,7 +413,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto fail_io;
}
tegra->phy = tegra_usb_phy_open(instance, hcd->regs);
config = pdev->dev.platform_data;
tegra->phy = tegra_usb_phy_open(instance, hcd->regs, config);
if (IS_ERR(tegra->phy)) {
dev_err(&pdev->dev, "Failed to open USB phy\n");
err = -ENXIO;

View File

@@ -63,6 +63,7 @@ struct fsl_usb2_platform_data {
enum fsl_usb2_operating_modes operating_mode;
enum fsl_usb2_phy_modes phy_mode;
unsigned int port_enables;
void *phy_config;
};
/* Flags in fsl_usb2_mph_platform_data */