linux/drivers/phy/xilinx/phy-zynqmp.c

// SPDX-License-Identifier: GPL-2.0
/*
 * phy-zynqmp.c - PHY driver for Xilinx ZynqMP GT.
 *
 * Copyright (C) 2018-2020 Xilinx Inc.
 *
 * Author: Anurag Kumar Vulisha <[email protected]>
 * Author: Subbaraya Sundeep <[email protected]>
 * Author: Laurent Pinchart <[email protected]>
 *
 * This driver is tested for USB, SGMII, SATA and Display Port currently.
 * PCIe should also work but that is experimental as of now.
 */

#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>

#include <dt-bindings/phy/phy.h>

/*
 * Lane Registers
 */

/* TX De-emphasis parameters */
#define L0_TX_ANA_TM_18
#define L0_TX_ANA_TM_118
#define L0_TX_ANA_TM_118_FORCE_17_0

/* DN Resistor calibration code parameters */
#define L0_TXPMA_ST_3
#define L0_DN_CALIB_CODE

/* PMA control parameters */
#define L0_TXPMD_TM_45
#define L0_TXPMD_TM_48
#define L0_TXPMD_TM_45_OVER_DP_MAIN
#define L0_TXPMD_TM_45_ENABLE_DP_MAIN
#define L0_TXPMD_TM_45_OVER_DP_POST1
#define L0_TXPMD_TM_45_ENABLE_DP_POST1
#define L0_TXPMD_TM_45_OVER_DP_POST2
#define L0_TXPMD_TM_45_ENABLE_DP_POST2

/* PCS control parameters */
#define L0_TM_DIG_6
#define L0_TM_DIS_DESCRAMBLE_DECODER
#define L0_TX_DIG_61
#define L0_TM_DISABLE_SCRAMBLE_ENCODER

/* PLL Test Mode register parameters */
#define L0_TM_PLL_DIG_37
#define L0_TM_COARSE_CODE_LIMIT

/* PLL SSC step size offsets */
#define L0_PLL_SS_STEPS_0_LSB
#define L0_PLL_SS_STEPS_1_MSB
#define L0_PLL_SS_STEP_SIZE_0_LSB
#define L0_PLL_SS_STEP_SIZE_1
#define L0_PLL_SS_STEP_SIZE_2
#define L0_PLL_SS_STEP_SIZE_3_MSB
#define L0_PLL_STATUS_READ_1

/* SSC step size parameters */
#define STEP_SIZE_0_MASK
#define STEP_SIZE_1_MASK
#define STEP_SIZE_2_MASK
#define STEP_SIZE_3_MASK
#define STEP_SIZE_SHIFT
#define FORCE_STEP_SIZE
#define FORCE_STEPS
#define STEPS_0_MASK
#define STEPS_1_MASK

/* Reference clock selection parameters */
#define L0_Ln_REF_CLK_SEL(n)
#define L0_REF_CLK_LCL_SEL
#define L0_REF_CLK_SEL_MASK

/* Calibration digital logic parameters */
#define L3_TM_CALIB_DIG19
#define L3_CALIB_DONE_STATUS
#define L3_TM_CALIB_DIG18
#define L3_TM_CALIB_DIG19_NSW
#define L3_TM_CALIB_DIG18_NSW
#define L3_TM_OVERRIDE_NSW_CODE
#define L3_CALIB_DONE
#define L3_NSW_SHIFT
#define L3_NSW_PIPE_SHIFT
#define L3_NSW_CALIB_SHIFT

#define PHY_REG_OFFSET

/*
 * Global Registers
 */

/* Refclk selection parameters */
#define PLL_REF_SEL(n)
#define PLL_FREQ_MASK
#define PLL_STATUS_LOCKED

/* Inter Connect Matrix parameters */
#define ICM_CFG0
#define ICM_CFG1
#define ICM_CFG0_L0_MASK
#define ICM_CFG0_L1_MASK
#define ICM_CFG1_L2_MASK
#define ICM_CFG2_L3_MASK
#define ICM_CFG_SHIFT

/* Inter Connect Matrix allowed protocols */
#define ICM_PROTOCOL_PD
#define ICM_PROTOCOL_PCIE
#define ICM_PROTOCOL_SATA
#define ICM_PROTOCOL_USB
#define ICM_PROTOCOL_DP
#define ICM_PROTOCOL_SGMII

static const char *const xpsgtr_icm_str[] =;

/* Test Mode common reset control  parameters */
#define TM_CMN_RST
#define TM_CMN_RST_EN
#define TM_CMN_RST_SET
#define TM_CMN_RST_MASK

/* Bus width parameters */
#define TX_PROT_BUS_WIDTH
#define RX_PROT_BUS_WIDTH
#define PROT_BUS_WIDTH_10
#define PROT_BUS_WIDTH_20
#define PROT_BUS_WIDTH_40
#define PROT_BUS_WIDTH_SHIFT(n)
#define PROT_BUS_WIDTH_MASK(n)

/* Number of GT lanes */
#define NUM_LANES

/* SIOU SATA control register */
#define SATA_CONTROL_OFFSET

/* Total number of controllers */
#define CONTROLLERS_PER_LANE

/* Timeout values */
#define TIMEOUT_US

struct xpsgtr_dev;

/**
 * struct xpsgtr_ssc - structure to hold SSC settings for a lane
 * @refclk_rate: PLL reference clock frequency
 * @pll_ref_clk: value to be written to register for corresponding ref clk rate
 * @steps: number of steps of SSC (Spread Spectrum Clock)
 * @step_size: step size of each step
 */
struct xpsgtr_ssc {};

/**
 * struct xpsgtr_phy - representation of a lane
 * @phy: pointer to the kernel PHY device
 * @instance: instance of the protocol type (such as the lane within a
 *            protocol, or the USB/Ethernet controller)
 * @lane: lane number
 * @protocol: protocol in which the lane operates
 * @skip_phy_init: skip phy_init() if true
 * @dev: pointer to the xpsgtr_dev instance
 * @refclk: reference clock index
 */
struct xpsgtr_phy {};

/**
 * struct xpsgtr_dev - representation of a ZynMP GT device
 * @dev: pointer to device
 * @serdes: serdes base address
 * @siou: siou base address
 * @gtr_mutex: mutex for locking
 * @phys: PHY lanes
 * @refclk_sscs: spread spectrum settings for the reference clocks
 * @clk: reference clocks
 * @tx_term_fix: fix for GT issue
 * @saved_icm_cfg0: stored value of ICM CFG0 register
 * @saved_icm_cfg1: stored value of ICM CFG1 register
 */
struct xpsgtr_dev {};

/*
 * Configuration Data
 */

/* lookup table to hold all settings needed for a ref clock frequency */
static const struct xpsgtr_ssc ssc_lookup[] =;

/*
 * I/O Accessors
 */

static inline u32 xpsgtr_read(struct xpsgtr_dev *gtr_dev, u32 reg)
{}

static inline void xpsgtr_write(struct xpsgtr_dev *gtr_dev, u32 reg, u32 value)
{}

static inline void xpsgtr_clr_set(struct xpsgtr_dev *gtr_dev, u32 reg,
				  u32 clr, u32 set)
{}

static inline u32 xpsgtr_read_phy(struct xpsgtr_phy *gtr_phy, u32 reg)
{}

static inline void xpsgtr_write_phy(struct xpsgtr_phy *gtr_phy,
				    u32 reg, u32 value)
{}

static inline void xpsgtr_clr_set_phy(struct xpsgtr_phy *gtr_phy,
				      u32 reg, u32 clr, u32 set)
{}

/*
 * Hardware Configuration
 */

/* Wait for the PLL to lock (with a timeout). */
static int xpsgtr_wait_pll_lock(struct phy *phy)
{}

/* Configure PLL and spread-sprectrum clock. */
static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
{}

/* Configure the lane protocol. */
static void xpsgtr_lane_set_protocol(struct xpsgtr_phy *gtr_phy)
{}

/* Bypass (de)scrambler and 8b/10b decoder and encoder. */
static void xpsgtr_bypass_scrambler_8b10b(struct xpsgtr_phy *gtr_phy)
{}

/* DP-specific initialization. */
static void xpsgtr_phy_init_dp(struct xpsgtr_phy *gtr_phy)
{}

/* SATA-specific initialization. */
static void xpsgtr_phy_init_sata(struct xpsgtr_phy *gtr_phy)
{}

/* SGMII-specific initialization. */
static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy)
{}

/* Configure TX de-emphasis and margining for DP. */
static void xpsgtr_phy_configure_dp(struct xpsgtr_phy *gtr_phy, unsigned int pre,
				    unsigned int voltage)
{}

/*
 * PHY Operations
 */

static bool xpsgtr_phy_init_required(struct xpsgtr_phy *gtr_phy)
{}

/*
 * There is a functional issue in the GT. The TX termination resistance can be
 * out of spec due to a issue in the calibration logic. This is the workaround
 * to fix it, required for XCZU9EG silicon.
 */
static int xpsgtr_phy_tx_term_fix(struct xpsgtr_phy *gtr_phy)
{}

static int xpsgtr_phy_init(struct phy *phy)
{}

static int xpsgtr_phy_exit(struct phy *phy)
{}

static int xpsgtr_phy_power_on(struct phy *phy)
{}

static int xpsgtr_phy_configure(struct phy *phy, union phy_configure_opts *opts)
{}

static const struct phy_ops xpsgtr_phyops =;

/*
 * OF Xlate Support
 */

/* Set the lane protocol and instance based on the PHY type and instance number. */
static int xpsgtr_set_lane_type(struct xpsgtr_phy *gtr_phy, u8 phy_type,
				unsigned int phy_instance)
{}

/*
 * Valid combinations of controllers and lanes (Interconnect Matrix). Each
 * "instance" represents one controller for a lane. For PCIe and DP, the
 * "instance" is the logical lane in the link. For SATA, USB, and SGMII,
 * the instance is the index of the controller.
 *
 * This information is only used to validate the devicetree reference, and is
 * not used when programming the hardware.
 */
static const unsigned int icm_matrix[NUM_LANES][CONTROLLERS_PER_LANE] =;

/* Translate OF phandle and args to PHY instance. */
static struct phy *xpsgtr_xlate(struct device *dev,
				const struct of_phandle_args *args)
{}

/*
 * DebugFS
 */

static int xpsgtr_status_read(struct seq_file *seq, void *data)
{}

/*
 * Power Management
 */

static int xpsgtr_runtime_suspend(struct device *dev)
{}

static int xpsgtr_runtime_resume(struct device *dev)
{}

static DEFINE_RUNTIME_DEV_PM_OPS(xpsgtr_pm_ops, xpsgtr_runtime_suspend,
				 xpsgtr_runtime_resume, NULL);
/*
 * Probe & Platform Driver
 */

static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev)
{}

static int xpsgtr_probe(struct platform_device *pdev)
{}

static void xpsgtr_remove(struct platform_device *pdev)
{}

static const struct of_device_id xpsgtr_of_match[] =;
MODULE_DEVICE_TABLE(of, xpsgtr_of_match);

static struct platform_driver xpsgtr_driver =;

module_platform_driver();

MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_DESCRIPTION();