brintos

brintos / linux-shallow public Read only

0
0
Text · 7.1 KiB · a2f69d6 Raw
267 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2022 MediaTek Inc.4 * Author: Jianjun Wang <jianjun.wang@mediatek.com>5 */6 7#include <linux/bitfield.h>8#include <linux/module.h>9#include <linux/nvmem-consumer.h>10#include <linux/of.h>11#include <linux/phy/phy.h>12#include <linux/platform_device.h>13#include <linux/slab.h>14 15#include "phy-mtk-io.h"16 17#define PEXTP_ANA_GLB_00_REG		0x900018/* Internal Resistor Selection of TX Bias Current */19#define EFUSE_GLB_INTR_SEL		GENMASK(28, 24)20 21#define PEXTP_ANA_LN0_TRX_REG		0xa00022 23#define PEXTP_ANA_TX_REG		0x0424/* TX PMOS impedance selection */25#define EFUSE_LN_TX_PMOS_SEL		GENMASK(5, 2)26/* TX NMOS impedance selection */27#define EFUSE_LN_TX_NMOS_SEL		GENMASK(11, 8)28 29#define PEXTP_ANA_RX_REG		0x3c30/* RX impedance selection */31#define EFUSE_LN_RX_SEL			GENMASK(3, 0)32 33#define PEXTP_ANA_LANE_OFFSET		0x10034 35/**36 * struct mtk_pcie_lane_efuse - eFuse data for each lane37 * @tx_pmos: TX PMOS impedance selection data38 * @tx_nmos: TX NMOS impedance selection data39 * @rx_data: RX impedance selection data40 * @lane_efuse_supported: software eFuse data is supported for this lane41 */42struct mtk_pcie_lane_efuse {43	u32 tx_pmos;44	u32 tx_nmos;45	u32 rx_data;46	bool lane_efuse_supported;47};48 49/**50 * struct mtk_pcie_phy_data - phy data for each SoC51 * @num_lanes: supported lane numbers52 * @sw_efuse_supported: support software to load eFuse data53 */54struct mtk_pcie_phy_data {55	int num_lanes;56	bool sw_efuse_supported;57};58 59/**60 * struct mtk_pcie_phy - PCIe phy driver main structure61 * @dev: pointer to device62 * @phy: pointer to generic phy63 * @sif_base: IO mapped register base address of system interface64 * @data: pointer to SoC dependent data65 * @sw_efuse_en: software eFuse enable status66 * @efuse_glb_intr: internal resistor selection of TX bias current data67 * @efuse: pointer to eFuse data for each lane68 */69struct mtk_pcie_phy {70	struct device *dev;71	struct phy *phy;72	void __iomem *sif_base;73	const struct mtk_pcie_phy_data *data;74 75	bool sw_efuse_en;76	u32 efuse_glb_intr;77	struct mtk_pcie_lane_efuse *efuse;78};79 80static void mtk_pcie_efuse_set_lane(struct mtk_pcie_phy *pcie_phy,81				    unsigned int lane)82{83	struct mtk_pcie_lane_efuse *data = &pcie_phy->efuse[lane];84	void __iomem *addr;85 86	if (!data->lane_efuse_supported)87		return;88 89	addr = pcie_phy->sif_base + PEXTP_ANA_LN0_TRX_REG +90	       lane * PEXTP_ANA_LANE_OFFSET;91 92	mtk_phy_update_field(addr + PEXTP_ANA_TX_REG, EFUSE_LN_TX_PMOS_SEL,93			     data->tx_pmos);94 95	mtk_phy_update_field(addr + PEXTP_ANA_TX_REG, EFUSE_LN_TX_NMOS_SEL,96			     data->tx_nmos);97 98	mtk_phy_update_field(addr + PEXTP_ANA_RX_REG, EFUSE_LN_RX_SEL,99			     data->rx_data);100}101 102/**103 * mtk_pcie_phy_init() - Initialize the phy104 * @phy: the phy to be initialized105 *106 * Initialize the phy by setting the efuse data.107 * The hardware settings will be reset during suspend, it should be108 * reinitialized when the consumer calls phy_init() again on resume.109 */110static int mtk_pcie_phy_init(struct phy *phy)111{112	struct mtk_pcie_phy *pcie_phy = phy_get_drvdata(phy);113	int i;114 115	if (!pcie_phy->sw_efuse_en)116		return 0;117 118	/* Set global data */119	mtk_phy_update_field(pcie_phy->sif_base + PEXTP_ANA_GLB_00_REG,120			     EFUSE_GLB_INTR_SEL, pcie_phy->efuse_glb_intr);121 122	for (i = 0; i < pcie_phy->data->num_lanes; i++)123		mtk_pcie_efuse_set_lane(pcie_phy, i);124 125	return 0;126}127 128static const struct phy_ops mtk_pcie_phy_ops = {129	.init	= mtk_pcie_phy_init,130	.owner	= THIS_MODULE,131};132 133static int mtk_pcie_efuse_read_for_lane(struct mtk_pcie_phy *pcie_phy,134					unsigned int lane)135{136	struct mtk_pcie_lane_efuse *efuse = &pcie_phy->efuse[lane];137	struct device *dev = pcie_phy->dev;138	char efuse_id[16];139	int ret;140 141	snprintf(efuse_id, sizeof(efuse_id), "tx_ln%d_pmos", lane);142	ret = nvmem_cell_read_variable_le_u32(dev, efuse_id, &efuse->tx_pmos);143	if (ret)144		return dev_err_probe(dev, ret, "Failed to read %s\n", efuse_id);145 146	snprintf(efuse_id, sizeof(efuse_id), "tx_ln%d_nmos", lane);147	ret = nvmem_cell_read_variable_le_u32(dev, efuse_id, &efuse->tx_nmos);148	if (ret)149		return dev_err_probe(dev, ret, "Failed to read %s\n", efuse_id);150 151	snprintf(efuse_id, sizeof(efuse_id), "rx_ln%d", lane);152	ret = nvmem_cell_read_variable_le_u32(dev, efuse_id, &efuse->rx_data);153	if (ret)154		return dev_err_probe(dev, ret, "Failed to read %s\n", efuse_id);155 156	if (!(efuse->tx_pmos || efuse->tx_nmos || efuse->rx_data))157		return dev_err_probe(dev, -EINVAL,158				     "No eFuse data found for lane%d, but dts enable it\n",159				     lane);160 161	efuse->lane_efuse_supported = true;162 163	return 0;164}165 166static int mtk_pcie_read_efuse(struct mtk_pcie_phy *pcie_phy)167{168	struct device *dev = pcie_phy->dev;169	bool nvmem_enabled;170	int ret, i;171 172	/* nvmem data is optional */173	nvmem_enabled = device_property_present(dev, "nvmem-cells");174	if (!nvmem_enabled)175		return 0;176 177	ret = nvmem_cell_read_variable_le_u32(dev, "glb_intr",178					      &pcie_phy->efuse_glb_intr);179	if (ret)180		return dev_err_probe(dev, ret, "Failed to read glb_intr\n");181 182	pcie_phy->sw_efuse_en = true;183 184	pcie_phy->efuse = devm_kzalloc(dev, pcie_phy->data->num_lanes *185				       sizeof(*pcie_phy->efuse), GFP_KERNEL);186	if (!pcie_phy->efuse)187		return -ENOMEM;188 189	for (i = 0; i < pcie_phy->data->num_lanes; i++) {190		ret = mtk_pcie_efuse_read_for_lane(pcie_phy, i);191		if (ret)192			return ret;193	}194 195	return 0;196}197 198static int mtk_pcie_phy_probe(struct platform_device *pdev)199{200	struct device *dev = &pdev->dev;201	struct phy_provider *provider;202	struct mtk_pcie_phy *pcie_phy;203	int ret;204 205	pcie_phy = devm_kzalloc(dev, sizeof(*pcie_phy), GFP_KERNEL);206	if (!pcie_phy)207		return -ENOMEM;208 209	pcie_phy->sif_base = devm_platform_ioremap_resource_byname(pdev, "sif");210	if (IS_ERR(pcie_phy->sif_base))211		return dev_err_probe(dev, PTR_ERR(pcie_phy->sif_base),212				     "Failed to map phy-sif base\n");213 214	pcie_phy->phy = devm_phy_create(dev, dev->of_node, &mtk_pcie_phy_ops);215	if (IS_ERR(pcie_phy->phy))216		return dev_err_probe(dev, PTR_ERR(pcie_phy->phy),217				     "Failed to create PCIe phy\n");218 219	pcie_phy->dev = dev;220	pcie_phy->data = of_device_get_match_data(dev);221	if (!pcie_phy->data)222		return dev_err_probe(dev, -EINVAL, "Failed to get phy data\n");223 224	if (pcie_phy->data->sw_efuse_supported) {225		/*226		 * Failed to read the efuse data is not a fatal problem,227		 * ignore the failure and keep going.228		 */229		ret = mtk_pcie_read_efuse(pcie_phy);230		if (ret == -EPROBE_DEFER || ret == -ENOMEM)231			return ret;232	}233 234	phy_set_drvdata(pcie_phy->phy, pcie_phy);235 236	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);237	if (IS_ERR(provider))238		return dev_err_probe(dev, PTR_ERR(provider),239				     "PCIe phy probe failed\n");240 241	return 0;242}243 244static const struct mtk_pcie_phy_data mt8195_data = {245	.num_lanes = 2,246	.sw_efuse_supported = true,247};248 249static const struct of_device_id mtk_pcie_phy_of_match[] = {250	{ .compatible = "mediatek,mt8195-pcie-phy", .data = &mt8195_data },251	{ },252};253MODULE_DEVICE_TABLE(of, mtk_pcie_phy_of_match);254 255static struct platform_driver mtk_pcie_phy_driver = {256	.probe	= mtk_pcie_phy_probe,257	.driver	= {258		.name = "mtk-pcie-phy",259		.of_match_table = mtk_pcie_phy_of_match,260	},261};262module_platform_driver(mtk_pcie_phy_driver);263 264MODULE_DESCRIPTION("MediaTek PCIe PHY driver");265MODULE_AUTHOR("Jianjun Wang <jianjun.wang@mediatek.com>");266MODULE_LICENSE("GPL");267