lkml.org 
[lkml]   [2022]   [Nov]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4/6] phy: tesla-pcie: Add PCIe PHY driver support for FSD
    Date
    This patch adds PHY driver support for PCIe controller
    found in Tesla FSD SoC.

    Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
    Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
    Signed-off-by: Shradha Todi <shradha.t@samsung.com>
    Signed-off-by: Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
    ---
    drivers/phy/samsung/Kconfig | 10 +
    drivers/phy/samsung/Makefile | 1 +
    drivers/phy/samsung/phy-tesla-pcie.c | 397 +++++++++++++++++++++++++++
    3 files changed, 408 insertions(+)
    create mode 100644 drivers/phy/samsung/phy-tesla-pcie.c

    diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig
    index 3ccaabf2850a..8c108b974c09 100644
    --- a/drivers/phy/samsung/Kconfig
    +++ b/drivers/phy/samsung/Kconfig
    @@ -38,6 +38,16 @@ config PHY_SAMSUNG_UFS
    Samsung Exynos SoCs. This driver provides the interface for UFS host
    controller to do PHY related programming.

    +config PHY_TESLA_FSD_PCIE
    + bool "TESLA FSD PCIe PHY driver"
    + depends on OF && (ARCH_TESLA_FSD || COMPILE_TEST)
    + select GENERIC_PHY
    + help
    + Enable PCIe PHY support for TESLA FSD SoC series.
    + This driver provides PHY interface for TESLA FSD PCIe controller.
    + It will do basic initialisation of the PHY and make it available
    + for use.
    +
    config PHY_SAMSUNG_USB2
    tristate "S5P/Exynos SoC series USB 2.0 PHY driver"
    depends on HAS_IOMEM
    diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile
    index afb34a153e34..f1fc0db84eab 100644
    --- a/drivers/phy/samsung/Makefile
    +++ b/drivers/phy/samsung/Makefile
    @@ -15,3 +15,4 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
    phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
    obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
    obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
    +obj-$(CONFIG_PHY_TESLA_FSD_PCIE) += phy-tesla-pcie.o
    diff --git a/drivers/phy/samsung/phy-tesla-pcie.c b/drivers/phy/samsung/phy-tesla-pcie.c
    new file mode 100644
    index 000000000000..448579f53840
    --- /dev/null
    +++ b/drivers/phy/samsung/phy-tesla-pcie.c
    @@ -0,0 +1,397 @@
    +// SPDX-License-Identifier: GPL-2.0
    +/*
    + * TESLA FSD SoC series PCIe PHY driver
    + *
    + * Phy provider for PCIe controller on TESLA FSD SoC series
    + *
    + * Copyright (C) 2018-2021 Samsung Electronics Co., Ltd.
    + *
    + * This program is free software; you can redistribute it and/or modify
    + * it under the terms of the GNU General Public License version 2 as
    + * published by the Free Software Foundation.
    + */
    +
    +#include <linux/delay.h>
    +#include <linux/io.h>
    +#include <linux/iopoll.h>
    +#include <linux/init.h>
    +#include <linux/mfd/syscon.h>
    +#include <linux/of.h>
    +#include <linux/of_address.h>
    +#include <linux/of_platform.h>
    +#include <linux/platform_device.h>
    +#include <linux/phy/phy.h>
    +#include <linux/regmap.h>
    +
    +#define FSD_LANE_OFFSET 0x400
    +#define BRF_NONE 0
    +#define BRF_L4 1
    +#define BRF_L2 2
    +
    +/* TESLA FSD: PCIe PHY registers */
    +#define PCIE_PHY_AGG_BIF_RESET 0x0200
    +#define PCIE_PHY_AGG_BIF_CLOCK 0x0208
    +
    +#define FSD_PCIE_PHY_TRSV_REG01_LN_N 0x5EC
    +#define FSD_PCIE_PHY_TRSV_REG02_LN_N 0x548
    +#define FSD_PCIE_PHY_TRSV_REG03_LN_N 0x4E4
    +#define FSD_PCIE_PHY_TRSV_REG04_LN_N 0x4EC
    +#define FSD_PCIE_PHY_TRSV_REG05_LN_N 0x4F0
    +#define FSD_PCIE_PHY_TRSV_REG06_LN_N 0x4F8
    +#define FSD_PCIE_PHY_TRSV_REG07_LN_N 0x4FC
    +#define FSD_PCIE_PHY_TRSV_REG08_LN_N 0x50C
    +#define FSD_PCIE_PHY_TRSV_REG09_LN_N 0x520
    +#define FSD_PCIE_PHY_TRSV_REG10_LN_N 0x5AC
    +#define FSD_PCIE_PHY_TRSV_REG11_LN_N 0x60C
    +#define FSD_PCIE_PHY_TRSV_REG12_LN_N 0x618
    +#define FSD_PCIE_PHY_TRSV_REG13_LN_N 0x61C
    +#define FSD_PCIE_PHY_TRSV_REG14_LN_N 0x678
    +#define FSD_PCIE_PHY_TRSV_REG15_LN_N 0x67C
    +#define FSD_PCIE_PHY_TRSV_REG16_LN_N 0x404
    +#define FSD_PCIE_PHY_TRSV_REG17_LN_N 0x408
    +#define FSD_PCIE_PHY_TRSV_REG18_LN_N 0x414
    +#define FSD_PCIE_PHY_TRSV_REG19_LN_N 0x418
    +#define FSD_PCIE_PHY_TRSV_REG20_LN_N 0x41C
    +#define FSD_PCIE_PHY_TRSV_REG21_LN_N 0x424
    +#define FSD_PCIE_PHY_TRSV_REG22_LN_N 0x428
    +#define FSD_PCIE_PHY_TRSV_REG23_LN_N 0x430
    +#define FSD_PCIE_PHY_TRSV_REG24_LN_N 0x448
    +#define FSD_PCIE_PHY_TRSV_REG25_LN_N 0x44C
    +#define FSD_PCIE_PHY_TRSV_REG26_LN_N 0x450
    +#define FSD_PCIE_PHY_TRSV_REG27_LN_N 0x454
    +#define FSD_PCIE_PHY_TRSV_REG28_LN_N 0x458
    +#define FSD_PCIE_PHY_TRSV_REG29_LN_N 0x7F0
    +#define FSD_PCIE_PHY_TRSV_REG30_LN_N 0x7F4
    +
    +/* TESLA FSD PCIe PCS registers */
    +#define PCIE_PCS_BRF_0 0x0004
    +#define PCIE_PCS_BRF_1 0x0804
    +#define PCIE_PCS_CLK 0x0180
    +
    +/* TESLA FSD SYS REG registers */
    +#define PCIE_PHY_0_CON 0x042C
    +#define PCIE_PHY_1_CON 0x0500
    +
    +#define PHY_0_CON_MASK 0x3FF
    +#define PHY_0_REF_SEL_MASK 0x3
    +#define PHY_0_REF_SEL (0x2 << 0)
    +#define PHY_0_SSC_EN_MASK 0x8
    +#define PHY_0_SSC_EN BIT(3)
    +#define PHY_0_AUX_EN_MASK 0x10
    +#define PHY_0_AUX_EN BIT(4)
    +#define PHY_0_CMN_RSTN_MASK 0x100
    +#define PHY_0_CMN_RSTN BIT(8)
    +#define PHY_0_INIT_RSTN_MASK 0x200
    +#define PHY_0_INIT_RSTN BIT(9)
    +
    +#define PHY_1_CON_MASK 0x1FF
    +#define PHY_1_AUX_EN_MASK 0x1
    +#define PHY_1_AUX_EN BIT(0)
    +#define PHY_1_CMN_RSTN_MASK 0x2
    +#define PHY_1_CMN_RSTN BIT(1)
    +#define PHY_1_INIT_RSTN_MASK 0x8
    +#define PHY_1_INIT_RSTN BIT(3)
    +#define PHY_1_REF_SEL_MASK 0x30
    +#define PHY_1_REF_SEL (0x2 << 4)
    +#define PHY_1_SSC_EN_MASK 0x80
    +#define PHY_1_SSC_EN BIT(7)
    +
    +struct fsd_pcie_phy_n_pdata {
    + u32 phy_con;
    + u32 phy_con_mask;
    + u32 phy_ref_sel_mask;
    + u32 phy_ref_sel;
    + u32 phy_ssc_en_mask;
    + u32 phy_ssc_en;
    + u32 phy_aux_en_mask;
    + u32 phy_aux_en;
    + u32 phy_cmn_rstn_mask;
    + u32 phy_cmn_rstn;
    + u32 phy_init_rstn_mask;
    + u32 phy_init_rstn;
    + u32 phy_trsv_reg19_val;
    + u32 phy_trsv_reg29_val;
    + u32 num_lanes;
    + u32 lane_offset;
    +};
    +
    +struct fsd_pcie_phy_data {
    + const struct phy_ops *ops;
    + struct fsd_pcie_phy_n_pdata *phy0_pdata;
    + struct fsd_pcie_phy_n_pdata *phy1_pdata;
    +};
    +
    +struct fsd_pcie_phy {
    + void __iomem *phy_base;
    + void __iomem *pcs_base;
    +
    + struct regmap *sysreg;
    + const struct fsd_pcie_phy_data *drv_data;
    + struct fsd_pcie_phy_n_pdata *pdata;
    +
    + u32 lane_sel;
    + u32 bifurcation_mode;
    + int phy_id;
    +};
    +
    +struct fsd_pcie_phy_n_pdata fsd_phy0_con = {
    + .num_lanes = 0x4,
    + .lane_offset = FSD_LANE_OFFSET,
    + .phy_con = PCIE_PHY_0_CON,
    + .phy_con_mask = PHY_0_CON_MASK,
    + .phy_ref_sel_mask = PHY_0_REF_SEL_MASK,
    + .phy_ref_sel = PHY_0_REF_SEL,
    + .phy_ssc_en_mask = PHY_0_SSC_EN_MASK,
    + .phy_ssc_en = PHY_0_SSC_EN,
    + .phy_aux_en_mask = PHY_0_AUX_EN_MASK,
    + .phy_aux_en = PHY_0_AUX_EN,
    + .phy_cmn_rstn_mask = PHY_0_CMN_RSTN_MASK,
    + .phy_cmn_rstn = PHY_0_CMN_RSTN,
    + .phy_init_rstn_mask = PHY_0_INIT_RSTN_MASK,
    + .phy_init_rstn = PHY_0_INIT_RSTN,
    + .phy_trsv_reg19_val = 0x0,
    + .phy_trsv_reg29_val = 0x7,
    +};
    +
    +struct fsd_pcie_phy_n_pdata fsd_phy1_con = {
    + .num_lanes = 0x4,
    + .lane_offset = FSD_LANE_OFFSET,
    + .phy_con = PCIE_PHY_1_CON,
    + .phy_con_mask = PHY_1_CON_MASK,
    + .phy_ref_sel_mask = PHY_1_REF_SEL_MASK,
    + .phy_ref_sel = PHY_1_REF_SEL,
    + .phy_ssc_en_mask = PHY_1_SSC_EN_MASK,
    + .phy_ssc_en = PHY_1_SSC_EN,
    + .phy_aux_en_mask = PHY_1_AUX_EN_MASK,
    + .phy_aux_en = PHY_1_AUX_EN,
    + .phy_cmn_rstn_mask = PHY_1_CMN_RSTN_MASK,
    + .phy_cmn_rstn = PHY_1_CMN_RSTN,
    + .phy_init_rstn_mask = PHY_1_INIT_RSTN_MASK,
    + .phy_init_rstn = PHY_1_INIT_RSTN,
    + .phy_trsv_reg19_val = 0x3,
    + .phy_trsv_reg29_val = 0x80,
    +};
    +
    +static void fsd_pcie_phy_writel(struct fsd_pcie_phy *phy_ctrl,
    + u32 val, u32 offset)
    +{
    + u32 i;
    + void __iomem *phy_base = phy_ctrl->phy_base;
    + struct fsd_pcie_phy_n_pdata *pdata = phy_ctrl->pdata;
    +
    + for (i = 0; i < pdata->num_lanes; i++)
    + writel(val, phy_base + (offset + i * pdata->lane_offset));
    +}
    +
    +static int fsd_pcie_phy_init(struct phy *phy)
    +{
    + struct fsd_pcie_phy *phy_ctrl = phy_get_drvdata(phy);
    + void __iomem *phy_base = phy_ctrl->phy_base;
    + struct fsd_pcie_phy_n_pdata *pdata = phy_ctrl->pdata;
    +
    + if (phy_ctrl->bifurcation_mode == BRF_NONE) {
    + writel(0x00, phy_ctrl->pcs_base + PCIE_PCS_BRF_0);
    + writel(0x00, phy_ctrl->pcs_base + PCIE_PCS_BRF_1);
    + writel(0x00, phy_base + PCIE_PHY_AGG_BIF_RESET);
    + writel(0x00, phy_base + PCIE_PHY_AGG_BIF_CLOCK);
    + } else if (phy_ctrl->bifurcation_mode == BRF_L4) {
    + writel(0xF, phy_ctrl->pcs_base + PCIE_PCS_BRF_0);
    + writel(0xF, phy_ctrl->pcs_base + PCIE_PCS_BRF_1);
    + writel(0x55, phy_base + PCIE_PHY_AGG_BIF_RESET);
    + writel(0x00, phy_base + PCIE_PHY_AGG_BIF_CLOCK);
    + } else if (phy_ctrl->bifurcation_mode == BRF_L2) {
    + writel(0xC, phy_ctrl->pcs_base + PCIE_PCS_BRF_0);
    + writel(0xC, phy_ctrl->pcs_base + PCIE_PCS_BRF_1);
    + writel(0x50, phy_base + PCIE_PHY_AGG_BIF_RESET);
    + writel(0xA0, phy_base + PCIE_PHY_AGG_BIF_CLOCK);
    + }
    +
    + fsd_pcie_phy_writel(phy_ctrl, 0x20, FSD_PCIE_PHY_TRSV_REG01_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x01, FSD_PCIE_PHY_TRSV_REG02_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0xF, FSD_PCIE_PHY_TRSV_REG03_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x13, FSD_PCIE_PHY_TRSV_REG04_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0xFB, FSD_PCIE_PHY_TRSV_REG05_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x10, FSD_PCIE_PHY_TRSV_REG06_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x4, FSD_PCIE_PHY_TRSV_REG07_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x11, FSD_PCIE_PHY_TRSV_REG08_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x11, FSD_PCIE_PHY_TRSV_REG09_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x78, FSD_PCIE_PHY_TRSV_REG10_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x8, FSD_PCIE_PHY_TRSV_REG11_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0xFF, FSD_PCIE_PHY_TRSV_REG12_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x3D, FSD_PCIE_PHY_TRSV_REG13_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x33, FSD_PCIE_PHY_TRSV_REG14_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x33, FSD_PCIE_PHY_TRSV_REG15_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x3F, FSD_PCIE_PHY_TRSV_REG16_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x1C, FSD_PCIE_PHY_TRSV_REG17_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x2B, FSD_PCIE_PHY_TRSV_REG18_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, pdata->phy_trsv_reg19_val,
    + FSD_PCIE_PHY_TRSV_REG19_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x9, FSD_PCIE_PHY_TRSV_REG20_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x10, FSD_PCIE_PHY_TRSV_REG21_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG22_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x93, FSD_PCIE_PHY_TRSV_REG23_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x1, FSD_PCIE_PHY_TRSV_REG24_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG25_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG26_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG27_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG28_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, pdata->phy_trsv_reg29_val,
    + FSD_PCIE_PHY_TRSV_REG29_LN_N);
    + fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG30_LN_N);
    +
    + regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con,
    + pdata->phy_cmn_rstn_mask, pdata->phy_cmn_rstn);
    +
    + return 0;
    +}
    +
    +static int fsd_pcie_phy_reset(struct phy *phy)
    +{
    + struct fsd_pcie_phy *phy_ctrl = phy_get_drvdata(phy);
    + struct fsd_pcie_phy_n_pdata *pdata = phy_ctrl->pdata;
    +
    + writel(0x1, phy_ctrl->pcs_base + PCIE_PCS_CLK);
    +
    + regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con, pdata->phy_con_mask,
    + 0x0);
    + regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con, pdata->phy_aux_en_mask,
    + pdata->phy_aux_en);
    + regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con, pdata->phy_ref_sel_mask,
    + pdata->phy_ref_sel);
    +
    + /* Perform Init Reset Release */
    + regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con,
    + pdata->phy_init_rstn_mask, pdata->phy_init_rstn);
    + return 0;
    +}
    +
    +static const struct phy_ops fsd_phy_ops = {
    + .init = fsd_pcie_phy_init,
    + .reset = fsd_pcie_phy_reset,
    + .owner = THIS_MODULE,
    +};
    +
    +static const struct fsd_pcie_phy_data fsd_pcie_phy = {
    + .ops = &fsd_phy_ops,
    + .phy0_pdata = &fsd_phy0_con,
    + .phy1_pdata = &fsd_phy1_con,
    +};
    +
    +static const struct of_device_id fsd_pcie_phy_match[] = {
    + {
    + .compatible = "tesla,fsd-pcie-phy",
    + .data = &fsd_pcie_phy,
    + },
    + {},
    +};
    +
    +static int fsd_pcie_phy_probe(struct platform_device *pdev)
    +{
    + int ret;
    + struct device *dev = &pdev->dev;
    + struct fsd_pcie_phy *fsd_phy;
    + struct phy *generic_phy;
    + struct phy_provider *phy_provider;
    + struct resource *res;
    + const struct fsd_pcie_phy_data *drv_data;
    + struct regmap *sysreg;
    + struct fsd_pcie_phy_n_pdata *pdata;
    +
    + drv_data = of_device_get_match_data(dev);
    + if (!drv_data)
    + return -ENODEV;
    +
    + fsd_phy = devm_kzalloc(dev, sizeof(*fsd_phy), GFP_KERNEL);
    + if (!fsd_phy)
    + return -ENOMEM;
    +
    + fsd_phy->phy_id = of_alias_get_id(dev->of_node, "pciephy");
    + if (fsd_phy->phy_id == 0)
    + fsd_phy->pdata = drv_data->phy0_pdata;
    + else
    + fsd_phy->pdata = drv_data->phy1_pdata;
    + pdata = fsd_phy->pdata;
    +
    + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    + fsd_phy->phy_base = devm_ioremap_resource(dev, res);
    + if (IS_ERR(fsd_phy->phy_base)) {
    + dev_err(dev, "Failed to get phy_base resource\n");
    + ret = PTR_ERR(fsd_phy->phy_base);
    + goto fail_get_resource;
    + }
    +
    + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
    + fsd_phy->pcs_base = devm_ioremap_resource(dev, res);
    + if (IS_ERR(fsd_phy->pcs_base)) {
    + dev_err(dev, "Failed to get pcs_base resource\n");
    + ret = PTR_ERR(fsd_phy->pcs_base);
    + goto fail_get_resource;
    + }
    +
    + /* sysreg regmap handle */
    + fsd_phy->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
    + "tesla,pcie-sysreg");
    + if (IS_ERR(fsd_phy->sysreg)) {
    + dev_err(dev, "pcie sysreg regmap lookup failed.\n");
    + ret = PTR_ERR(fsd_phy->sysreg);
    + goto fail_get_resource;
    + }
    +
    + /* Bifurcation/Aggregation configuration */
    + if (of_property_read_u32(dev->of_node, "phy-mode",
    + &fsd_phy->bifurcation_mode)) {
    + dev_err(dev, "Failed selecting the phy-mode\n");
    + ret = -EINVAL;
    + goto fail_get_resource;
    + }
    + dev_info(dev, "property phy-mode from u32 : %x\n", fsd_phy->bifurcation_mode);
    +
    + sysreg = fsd_phy->sysreg;
    + fsd_phy->drv_data = drv_data;
    +
    + generic_phy = devm_phy_create(dev, dev->of_node, drv_data->ops);
    + if (IS_ERR(generic_phy)) {
    + dev_err(dev, "Failed to create PHY\n");
    + ret = PTR_ERR(generic_phy);
    + goto fail_get_resource;
    + }
    +
    + phy_set_drvdata(generic_phy, fsd_phy);
    + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
    + if (IS_ERR(phy_provider)) {
    + dev_err(dev, "Failed to register phy provider\n");
    + ret = PTR_ERR_OR_ZERO(phy_provider);
    + goto fail_phy_provider;
    + }
    +
    + writel(0x1, fsd_phy->pcs_base + PCIE_PCS_CLK);
    +
    + regmap_update_bits(sysreg, pdata->phy_con, pdata->phy_con_mask,
    + 0x0);
    + regmap_update_bits(sysreg, pdata->phy_con, pdata->phy_aux_en_mask,
    + pdata->phy_aux_en);
    + regmap_update_bits(sysreg, pdata->phy_con, pdata->phy_ref_sel_mask,
    + pdata->phy_ref_sel);
    +
    + /* Perform Init Reset Release */
    + regmap_update_bits(sysreg, pdata->phy_con, pdata->phy_init_rstn_mask,
    + pdata->phy_init_rstn);
    +
    + dev_info(dev, "PCIe PHY%d Probe Successful\n", fsd_phy->phy_id);
    +
    + return 0;
    +fail_phy_provider:
    + devm_phy_destroy(dev, generic_phy);
    +fail_get_resource:
    + return ret;
    +}
    +
    +static struct platform_driver fsd_pcie_phy_driver = {
    + .probe = fsd_pcie_phy_probe,
    + .driver = {
    + .of_match_table = fsd_pcie_phy_match,
    + .name = "fsd_pcie_phy",
    + }
    +};
    +
    +builtin_platform_driver(fsd_pcie_phy_driver);
    --
    2.17.1
    \
     
     \ /
      Last update: 2022-11-21 12:46    [W:6.151 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site