phy: pipe3: insert delay to enumerate in GEN2 mode

8-bit delay value (0xF1) is required for GEN2 devices to be enumerated
consistently. Added an API to be called from PHY drivers to set this delay
value and called it from PIPE3 driver to set the delay value.

Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Reviewed-by: Roger Quadros <[email protected]>
This commit is contained in:
Kishon Vijay Abraham I 2014-06-25 23:22:57 +05:30
commit f0e2cf7b91
4 changed files with 71 additions and 7 deletions

View file

@ -26,6 +26,41 @@
#include <linux/clk.h>
#include <linux/phy/omap_control_phy.h>
/**
* omap_control_pcie_pcs - set the PCS delay count
* @dev: the control module device
* @id: index of the pcie PHY (should be 1 or 2)
* @delay: 8 bit delay value
*/
void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay)
{
u32 val;
struct omap_control_phy *control_phy;
if (IS_ERR(dev) || !dev) {
pr_err("%s: invalid device\n", __func__);
return;
}
control_phy = dev_get_drvdata(dev);
if (!control_phy) {
dev_err(dev, "%s: invalid control phy device\n", __func__);
return;
}
if (control_phy->type != OMAP_CTRL_TYPE_PCIE) {
dev_err(dev, "%s: unsupported operation\n", __func__);
return;
}
val = readl(control_phy->pcie_pcs);
val &= ~(OMAP_CTRL_PCIE_PCS_MASK <<
(id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT));
val |= delay << (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
writel(val, control_phy->pcie_pcs);
}
EXPORT_SYMBOL_GPL(omap_control_pcie_pcs);
/**
* omap_control_phy_power - power on/off the phy using control module reg
* @dev: the control module device
@ -61,6 +96,7 @@ void omap_control_phy_power(struct device *dev, int on)
val |= OMAP_CTRL_DEV_PHY_PD;
break;
case OMAP_CTRL_TYPE_PCIE:
case OMAP_CTRL_TYPE_PIPE3:
rate = clk_get_rate(control_phy->sys_clk);
rate = rate/1000000;
@ -211,6 +247,7 @@ EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE;
static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
@ -227,6 +264,10 @@ static const struct of_device_id omap_control_phy_id_table[] = {
.compatible = "ti,control-phy-pipe3",
.data = &pipe3_data,
},
{
.compatible = "ti,control-phy-pcie",
.data = &pcie_data,
},
{
.compatible = "ti,control-phy-usb2-dra7",
.data = &dra7usb2_data,
@ -279,7 +320,8 @@ static int omap_control_phy_probe(struct platform_device *pdev)
}
}
if (control_phy->type == OMAP_CTRL_TYPE_PIPE3) {
if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 ||
control_phy->type == OMAP_CTRL_TYPE_PCIE) {
control_phy->sys_clk = devm_clk_get(control_phy->dev,
"sys_clkin");
if (IS_ERR(control_phy->sys_clk)) {
@ -288,6 +330,14 @@ static int omap_control_phy_probe(struct platform_device *pdev)
}
}
if (control_phy->type == OMAP_CTRL_TYPE_PCIE) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"pcie_pcs");
control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(control_phy->pcie_pcs))
return PTR_ERR(control_phy->pcie_pcs);
}
dev_set_drvdata(control_phy->dev, control_phy);
return 0;

View file

@ -217,8 +217,10 @@ static int ti_pipe3_init(struct phy *x)
u32 val;
int ret = 0;
if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
omap_control_pcie_pcs(phy->control_dev, phy->id, 0xF1);
return 0;
}
/* Bring it out of IDLE if it is IDLE */
val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);