mirror of
https://github.com/torvalds/linux.git
synced 2026-06-10 07:32:29 +02:00
[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:
parent
a0e0319691
commit
ce3a041d2e
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user