aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/phy/phy-tegra-usb.c
diff options
context:
space:
mode:
authorTuomas Tynkkynen <ttynkkynen@nvidia.com>2013-08-12 09:06:53 -0400
committerFelipe Balbi <balbi@ti.com>2013-08-12 14:29:52 -0400
commite497a24d8e18af510879b2ae059ee20a4a58eae8 (patch)
tree43e213a25bd02b22194b8fa1409a27feeb25fccb /drivers/usb/phy/phy-tegra-usb.c
parent91e66700029d71d2938e1341172331c58b6bd8b3 (diff)
usb: phy: tegra: Program new PHY parameters
The Tegra30 TRM recommends configuration of certain PHY parameters for optimal quality. Program the following registers based on device tree parameters: - UTMIP_XCVR_HSSLEW: HS slew rate control. - UTMIP_HSSQUELCH_LEVEL: HS squelch detector level - UTMIP_HSDISCON_LEVEL: HS disconnect detector level. These registers exist in Tegra20, but programming them hasn't been necessary, so these parameters won't be set on Tegra20 to keep the device trees backward compatible. Additionally, the UTMIP_XCVR_SETUP parameter can be set from fuses instead of a software-programmed value, as the optimal value can vary between invidual boards. The boolean property nvidia,xcvr-setup-use-fuses can be used to enable this behaviour. Signed-off-by: Tuomas Tynkkynen <ttynkkynen@nvidia.com> Tested-by: Stephen Warren <swarren@nvidia.com> Reviewed-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/phy/phy-tegra-usb.c')
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c81
1 files changed, 63 insertions, 18 deletions
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 1ad184af7601..3bfb3d1957c1 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -99,11 +99,15 @@
99#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) 99#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
100#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) 100#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
101#define UTMIP_XCVR_LSBIAS_SEL (1 << 21) 101#define UTMIP_XCVR_LSBIAS_SEL (1 << 21)
102#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25) 102#define UTMIP_XCVR_HSSLEW(x) (((x) & 0x3) << 4)
103#define UTMIP_XCVR_HSSLEW_MSB(x) ((((x) & 0x1fc) >> 2) << 25)
103 104
104#define UTMIP_BIAS_CFG0 0x80c 105#define UTMIP_BIAS_CFG0 0x80c
105#define UTMIP_OTGPD (1 << 11) 106#define UTMIP_OTGPD (1 << 11)
106#define UTMIP_BIASPD (1 << 10) 107#define UTMIP_BIASPD (1 << 10)
108#define UTMIP_HSSQUELCH_LEVEL(x) (((x) & 0x3) << 0)
109#define UTMIP_HSDISCON_LEVEL(x) (((x) & 0x3) << 2)
110#define UTMIP_HSDISCON_LEVEL_MSB(x) ((((x) & 0x4) >> 2) << 24)
107 111
108#define UTMIP_HSRX_CFG0 0x810 112#define UTMIP_HSRX_CFG0 0x810
109#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10) 113#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
@@ -255,6 +259,7 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy)
255{ 259{
256 unsigned long val, flags; 260 unsigned long val, flags;
257 void __iomem *base = phy->pad_regs; 261 void __iomem *base = phy->pad_regs;
262 struct tegra_utmip_config *config = phy->config;
258 263
259 clk_prepare_enable(phy->pad_clk); 264 clk_prepare_enable(phy->pad_clk);
260 265
@@ -263,6 +268,16 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy)
263 if (utmip_pad_count++ == 0) { 268 if (utmip_pad_count++ == 0) {
264 val = readl(base + UTMIP_BIAS_CFG0); 269 val = readl(base + UTMIP_BIAS_CFG0);
265 val &= ~(UTMIP_OTGPD | UTMIP_BIASPD); 270 val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
271
272 if (phy->soc_config->requires_extra_tuning_parameters) {
273 val &= ~(UTMIP_HSSQUELCH_LEVEL(~0) |
274 UTMIP_HSDISCON_LEVEL(~0) |
275 UTMIP_HSDISCON_LEVEL_MSB(~0));
276
277 val |= UTMIP_HSSQUELCH_LEVEL(config->hssquelch_level);
278 val |= UTMIP_HSDISCON_LEVEL(config->hsdiscon_level);
279 val |= UTMIP_HSDISCON_LEVEL_MSB(config->hsdiscon_level);
280 }
266 writel(val, base + UTMIP_BIAS_CFG0); 281 writel(val, base + UTMIP_BIAS_CFG0);
267 } 282 }
268 283
@@ -431,12 +446,20 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
431 val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | 446 val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
432 UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_LSBIAS_SEL | 447 UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_LSBIAS_SEL |
433 UTMIP_XCVR_SETUP(~0) | UTMIP_XCVR_SETUP_MSB(~0) | 448 UTMIP_XCVR_SETUP(~0) | UTMIP_XCVR_SETUP_MSB(~0) |
434 UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) | 449 UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0));
435 UTMIP_XCVR_HSSLEW_MSB(~0)); 450
436 val |= UTMIP_XCVR_SETUP(config->xcvr_setup); 451 if (!config->xcvr_setup_use_fuses) {
437 val |= UTMIP_XCVR_SETUP_MSB(config->xcvr_setup); 452 val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
453 val |= UTMIP_XCVR_SETUP_MSB(config->xcvr_setup);
454 }
438 val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew); 455 val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
439 val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew); 456 val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
457
458 if (phy->soc_config->requires_extra_tuning_parameters) {
459 val &= ~(UTMIP_XCVR_HSSLEW(~0) | UTMIP_XCVR_HSSLEW_MSB(~0));
460 val |= UTMIP_XCVR_HSSLEW(config->xcvr_hsslew);
461 val |= UTMIP_XCVR_HSSLEW_MSB(config->xcvr_hsslew);
462 }
440 writel(val, base + UTMIP_XCVR_CFG0); 463 writel(val, base + UTMIP_XCVR_CFG0);
441 464
442 val = readl(base + UTMIP_XCVR_CFG1); 465 val = readl(base + UTMIP_XCVR_CFG1);
@@ -450,14 +473,14 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
450 val |= UTMIP_BIAS_PDTRK_COUNT(0x5); 473 val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
451 writel(val, base + UTMIP_BIAS_CFG1); 474 writel(val, base + UTMIP_BIAS_CFG1);
452 475
453 if (phy->is_legacy_phy) { 476 val = readl(base + UTMIP_SPARE_CFG0);
454 val = readl(base + UTMIP_SPARE_CFG0); 477 if (config->xcvr_setup_use_fuses)
455 if (phy->mode == USB_DR_MODE_PERIPHERAL) 478 val |= FUSE_SETUP_SEL;
456 val &= ~FUSE_SETUP_SEL; 479 else
457 else 480 val &= ~FUSE_SETUP_SEL;
458 val |= FUSE_SETUP_SEL; 481 writel(val, base + UTMIP_SPARE_CFG0);
459 writel(val, base + UTMIP_SPARE_CFG0); 482
460 } else { 483 if (!phy->is_legacy_phy) {
461 val = readl(base + USB_SUSP_CTRL); 484 val = readl(base + USB_SUSP_CTRL);
462 val |= UTMIP_PHY_ENABLE; 485 val |= UTMIP_PHY_ENABLE;
463 writel(val, base + USB_SUSP_CTRL); 486 writel(val, base + USB_SUSP_CTRL);
@@ -888,11 +911,6 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
888 if (err < 0) 911 if (err < 0)
889 return err; 912 return err;
890 913
891 err = read_utmi_param(pdev, "nvidia,xcvr-setup",
892 &config->xcvr_setup);
893 if (err < 0)
894 return err;
895
896 err = read_utmi_param(pdev, "nvidia,xcvr-lsfslew", 914 err = read_utmi_param(pdev, "nvidia,xcvr-lsfslew",
897 &config->xcvr_lsfslew); 915 &config->xcvr_lsfslew);
898 if (err < 0) 916 if (err < 0)
@@ -903,6 +921,33 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
903 if (err < 0) 921 if (err < 0)
904 return err; 922 return err;
905 923
924 if (tegra_phy->soc_config->requires_extra_tuning_parameters) {
925 err = read_utmi_param(pdev, "nvidia,xcvr-hsslew",
926 &config->xcvr_hsslew);
927 if (err < 0)
928 return err;
929
930 err = read_utmi_param(pdev, "nvidia,hssquelch-level",
931 &config->hssquelch_level);
932 if (err < 0)
933 return err;
934
935 err = read_utmi_param(pdev, "nvidia,hsdiscon-level",
936 &config->hsdiscon_level);
937 if (err < 0)
938 return err;
939 }
940
941 config->xcvr_setup_use_fuses = of_property_read_bool(
942 pdev->dev.of_node, "nvidia,xcvr-setup-use-fuses");
943
944 if (!config->xcvr_setup_use_fuses) {
945 err = read_utmi_param(pdev, "nvidia,xcvr-setup",
946 &config->xcvr_setup);
947 if (err < 0)
948 return err;
949 }
950
906 return 0; 951 return 0;
907} 952}
908 953