/** * struct mtk_pcie_lane_efuse - eFuse data for each lane * @tx_pmos: TX PMOS impedance selection data * @tx_nmos: TX NMOS impedance selection data * @rx_data: RX impedance selection data * @lane_efuse_supported: software eFuse data is supported for this lane
*/ struct mtk_pcie_lane_efuse {
u32 tx_pmos;
u32 tx_nmos;
u32 rx_data; bool lane_efuse_supported;
};
/** * struct mtk_pcie_phy_data - phy data for each SoC * @num_lanes: supported lane numbers * @sw_efuse_supported: support software to load eFuse data
*/ struct mtk_pcie_phy_data { int num_lanes; bool sw_efuse_supported;
};
/** * struct mtk_pcie_phy - PCIe phy driver main structure * @dev: pointer to device * @phy: pointer to generic phy * @sif_base: IO mapped register base address of system interface * @data: pointer to SoC dependent data * @sw_efuse_en: software eFuse enable status * @efuse_glb_intr: internal resistor selection of TX bias current data * @efuse: pointer to eFuse data for each lane
*/ struct mtk_pcie_phy { struct device *dev; struct phy *phy; void __iomem *sif_base; conststruct mtk_pcie_phy_data *data;
/** * mtk_pcie_phy_init() - Initialize the phy * @phy: the phy to be initialized * * Initialize the phy by setting the efuse data. * The hardware settings will be reset during suspend, it should be * reinitialized when the consumer calls phy_init() again on resume.
*/ staticint mtk_pcie_phy_init(struct phy *phy)
{ struct mtk_pcie_phy *pcie_phy = phy_get_drvdata(phy); int i;
if (!pcie_phy->sw_efuse_en) return 0;
/* Set global data */
mtk_phy_update_field(pcie_phy->sif_base + PEXTP_ANA_GLB_00_REG,
EFUSE_GLB_INTR_SEL, pcie_phy->efuse_glb_intr);
for (i = 0; i < pcie_phy->data->num_lanes; i++)
mtk_pcie_efuse_set_lane(pcie_phy, i);
snprintf(efuse_id, sizeof(efuse_id), "tx_ln%d_pmos", lane);
ret = nvmem_cell_read_variable_le_u32(dev, efuse_id, &efuse->tx_pmos); if (ret) return dev_err_probe(dev, ret, "Failed to read %s\n", efuse_id);
snprintf(efuse_id, sizeof(efuse_id), "tx_ln%d_nmos", lane);
ret = nvmem_cell_read_variable_le_u32(dev, efuse_id, &efuse->tx_nmos); if (ret) return dev_err_probe(dev, ret, "Failed to read %s\n", efuse_id);
snprintf(efuse_id, sizeof(efuse_id), "rx_ln%d", lane);
ret = nvmem_cell_read_variable_le_u32(dev, efuse_id, &efuse->rx_data); if (ret) return dev_err_probe(dev, ret, "Failed to read %s\n", efuse_id);
if (!(efuse->tx_pmos || efuse->tx_nmos || efuse->rx_data)) return dev_err_probe(dev, -EINVAL, "No eFuse data found for lane%d, but dts enable it\n",
lane);
/* nvmem data is optional */
nvmem_enabled = device_property_present(dev, "nvmem-cells"); if (!nvmem_enabled) return 0;
ret = nvmem_cell_read_variable_le_u32(dev, "glb_intr",
&pcie_phy->efuse_glb_intr); if (ret) return dev_err_probe(dev, ret, "Failed to read glb_intr\n");
pcie_phy = devm_kzalloc(dev, sizeof(*pcie_phy), GFP_KERNEL); if (!pcie_phy) return -ENOMEM;
pcie_phy->sif_base = devm_platform_ioremap_resource_byname(pdev, "sif"); if (IS_ERR(pcie_phy->sif_base)) return dev_err_probe(dev, PTR_ERR(pcie_phy->sif_base), "Failed to map phy-sif base\n");
pcie_phy->phy = devm_phy_create(dev, dev->of_node, &mtk_pcie_phy_ops); if (IS_ERR(pcie_phy->phy)) return dev_err_probe(dev, PTR_ERR(pcie_phy->phy), "Failed to create PCIe phy\n");
pcie_phy->dev = dev;
pcie_phy->data = of_device_get_match_data(dev); if (!pcie_phy->data) return dev_err_probe(dev, -EINVAL, "Failed to get phy data\n");
if (pcie_phy->data->sw_efuse_supported) { /* * Failed to read the efuse data is not a fatal problem, * ignore the failure and keep going.
*/
ret = mtk_pcie_read_efuse(pcie_phy); if (ret == -EPROBE_DEFER || ret == -ENOMEM) return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.