Merge branch 'remotes/lorenzo/pci/armada'

- Add Armada8k PHYs support (Miquel Raynal)

* remotes/lorenzo/pci/armada:
  PCI: armada8k: Add PHYs support
This commit is contained in:
Bjorn Helgaas 2019-07-12 17:08:31 -05:00
commit 8e7bc41cdc

View File

@ -25,10 +25,14 @@
#include "pcie-designware.h"
#define ARMADA8K_PCIE_MAX_LANES PCIE_LNK_X4
struct armada8k_pcie {
struct dw_pcie *pci;
struct clk *clk;
struct clk *clk_reg;
struct phy *phy[ARMADA8K_PCIE_MAX_LANES];
unsigned int phy_count;
};
#define PCIE_VENDOR_REGS_OFFSET 0x8000
@ -67,6 +71,76 @@ struct armada8k_pcie {
#define to_armada8k_pcie(x) dev_get_drvdata((x)->dev)
static void armada8k_pcie_disable_phys(struct armada8k_pcie *pcie)
{
int i;
for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) {
phy_power_off(pcie->phy[i]);
phy_exit(pcie->phy[i]);
}
}
static int armada8k_pcie_enable_phys(struct armada8k_pcie *pcie)
{
int ret;
int i;
for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) {
ret = phy_init(pcie->phy[i]);
if (ret)
return ret;
ret = phy_set_mode_ext(pcie->phy[i], PHY_MODE_PCIE,
pcie->phy_count);
if (ret) {
phy_exit(pcie->phy[i]);
return ret;
}
ret = phy_power_on(pcie->phy[i]);
if (ret) {
phy_exit(pcie->phy[i]);
return ret;
}
}
return 0;
}
static int armada8k_pcie_setup_phys(struct armada8k_pcie *pcie)
{
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
struct device_node *node = dev->of_node;
int ret = 0;
int i;
for (i = 0; i < ARMADA8K_PCIE_MAX_LANES; i++) {
pcie->phy[i] = devm_of_phy_get_by_index(dev, node, i);
if (IS_ERR(pcie->phy[i]) &&
(PTR_ERR(pcie->phy[i]) == -EPROBE_DEFER))
return PTR_ERR(pcie->phy[i]);
if (IS_ERR(pcie->phy[i])) {
pcie->phy[i] = NULL;
continue;
}
pcie->phy_count++;
}
/* Old bindings miss the PHY handle, so just warn if there is no PHY */
if (!pcie->phy_count)
dev_warn(dev, "No available PHY\n");
ret = armada8k_pcie_enable_phys(pcie);
if (ret)
dev_err(dev, "Failed to initialize PHY(s) (%d)\n", ret);
return ret;
}
static int armada8k_pcie_link_up(struct dw_pcie *pci)
{
u32 reg;
@ -249,14 +323,20 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
goto fail_clkreg;
}
ret = armada8k_pcie_setup_phys(pcie);
if (ret)
goto fail_clkreg;
platform_set_drvdata(pdev, pcie);
ret = armada8k_add_pcie_port(pcie, pdev);
if (ret)
goto fail_clkreg;
goto disable_phy;
return 0;
disable_phy:
armada8k_pcie_disable_phys(pcie);
fail_clkreg:
clk_disable_unprepare(pcie->clk_reg);
fail: