aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhao Qiang <qiang.zhao@nxp.com>2019-06-11 11:44:49 +0800
committerDaniel Thompson <daniel@redfelineninja.org.uk>2019-09-17 22:29:28 +0100
commit65e3d91b93c191cfa8b896a39b744aef6e747530 (patch)
tree9c1c45a302b0f295c3145f1a5f9714f56f7d43fa
parent1f306eea9c78d968a20ec71c2a1a8045e8e069ea (diff)
driver: phy: remove Freescale backplane phy driver
Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com>
-rw-r--r--Documentation/devicetree/bindings/net/dpaa-backplane.txt105
-rw-r--r--drivers/net/phy/Kconfig6
-rw-r--r--drivers/net/phy/Makefile3
-rw-r--r--drivers/net/phy/fsl_backplane.c1780
-rw-r--r--drivers/net/phy/fsl_backplane.h41
-rw-r--r--drivers/net/phy/fsl_backplane_serdes_10g.c281
-rw-r--r--drivers/net/phy/fsl_backplane_serdes_28g.c336
7 files changed, 0 insertions, 2552 deletions
diff --git a/Documentation/devicetree/bindings/net/dpaa-backplane.txt b/Documentation/devicetree/bindings/net/dpaa-backplane.txt
deleted file mode 100644
index c243196a6742..000000000000
--- a/Documentation/devicetree/bindings/net/dpaa-backplane.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-=============================================================================
-DPAA Backplane Device Bindings
-
-CONTENTS
- - SerDes Node
- - PCS Phy Node
-
-=============================================================================
-SerDes Node
-
-DESCRIPTION
-
-SerDes (Serializer/Deserializer) HW peripheral
-
-PROPERTIES
-
-- compatible
- Usage: required
- Value type: <stringlist>
- Definition: Specifies the type of SerDes.
- Must include the prefix "fsl,serdes"
- SerDes can be of different types:
- - 10G SerDes must be specified as: "fsl,serdes-10g"
- - 28G SerDes must be specified as: "fsl,serdes-28g"
-
-- reg
- Usage: required
- Value type: <prop-encoded-array>
- Definition: Specifies the offset of the SerDes configuration registers
-
-- little-endian
- Usage: optional
- Value type: <Boolean>
- Definition: Specifies endianness access to SerDes registers.
- If omitted, big-endian will be used
- See common-properties.txt for complete definition
-
-EXAMPLE
-
-Example of 10G SerDes node:
-
-serdes1: serdes@1ea0000 {
- compatible = "fsl,serdes-10g";
- reg = <0x0 0x1ea0000 0 0x00002000>;
- little-endian;
-};
-
-=============================================================================
-PCS Phy Node
-
-DESCRIPTION
-
-PCS Phy (Physical Coding Sublayer / Physical layer) node
-
-PROPERTIES
-
-- compatible
- Usage: required
- Value type: <stringlist>
- Definition: A standard property. Specifies the IEEE 802.3 Clause
- Different IEEE 802.3 Clauses can be specified:
- - Clause 22 must be specified as: "ethernet-phy-ieee802.3-c22"
- - Clause 45 must be specified as: "ethernet-phy-ieee802.3-c45"
- For complete definition see:
- Documentation/devicetree/bindings/net/phy.txt
-
-- reg
- Usage: required
- Value type: <prop-encoded-array>
- Definition: A standard property.
- Specifies the offset of the PCS Phy configuration registers
- For complete definition see:
- Documentation/devicetree/bindings/net/phy.txt
-
-- backplane-mode
- Usage: required
- Value type: <stringlist>
- Definition: Specifies the speed and type of the protocol used
- Different speeds and backplane protocol types can be used:
- - 10GBase-KR must be specified as: "10gbase-kr"
- - 40GBase-KR must be specified as: "40gbase-kr"
-
-- fsl,lane-handle
- Usage: required
- Value type: <phandle>
- Definition: Specifies the reference to a node representing the SerDes
- device
-
-- fsl,lane-reg
- Usage: required
- Value type: <prop-encoded-array>
- Definition: Specifies the offsets of the SerDes lanes configuration
- registers
-
-EXAMPLE
-
-Example of pcs phy node for 10GBase-KR:
-
-pcs_phy1: ethernet-phy@0 {
- compatible = "ethernet-phy-ieee802.3-c45";
- backplane-mode = "10gbase-kr";
- reg = <0x0>;
- fsl,lane-handle = <&serdes1>;
- fsl,lane-reg = <0xE00>; /* lane G */
-};
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 8989fbca7dcb..32af93206076 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -102,12 +102,6 @@ config MDIO_BUS_MUX_MULTIPLEXER
config MDIO_CAVIUM
tristate
-config MDIO_FSL_BACKPLANE
- tristate "Support for backplane on Freescale XFI interface"
- depends on OF_MDIO
- help
- This module provides a driver for Freescale XFI's backplane.
-
config MDIO_GPIO
tristate "GPIO lib-based bitbanged MDIO buses"
depends on MDIO_BITBANG
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 34ef0d2d49cb..f67d76060a90 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -31,9 +31,6 @@ obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
obj-$(CONFIG_MDIO_BUS_MUX_MULTIPLEXER) += mdio-mux-multiplexer.o
obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o
-obj-$(CONFIG_MDIO_FSL_BACKPLANE) += fsl_backplane.o
-obj-$(CONFIG_MDIO_FSL_BACKPLANE) += fsl_backplane_serdes_10g.o
-obj-$(CONFIG_MDIO_FSL_BACKPLANE) += fsl_backplane_serdes_28g.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
obj-$(CONFIG_MDIO_I2C) += mdio-i2c.o
diff --git a/drivers/net/phy/fsl_backplane.c b/drivers/net/phy/fsl_backplane.c
deleted file mode 100644
index 30fc3c5df211..000000000000
--- a/drivers/net/phy/fsl_backplane.c
+++ /dev/null
@@ -1,1780 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * DPAA backplane driver.
- * Author: Shaohui Xie <Shaohui.Xie@freescale.com>
- * Florinel Iordache <florinel.iordache@nxp.com>
- *
- * Copyright 2015 Freescale Semiconductor, Inc.
- * Copyright 2018 NXP
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mii.h>
-#include <linux/mdio.h>
-#include <linux/ethtool.h>
-#include <linux/phy.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_net.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/workqueue.h>
-#include <linux/netdevice.h>
-
-#include "fsl_backplane.h"
-
-
-/* PCS Device Identifier */
-#define PCS_PHY_DEVICE_ID 0x0083e400
-#define PCS_PHY_DEVICE_ID_MASK 0xffffffff
-
-/* 10G Long cables setup: 1 m to 2 m cables */
-#define RATIO_PREQ_10G 0x3
-#define RATIO_PST1Q_10G 0xd
-#define RATIO_EQ_10G 0x20
-
-/* 10G Short cables setup: up to 30 cm cable */
-//#define RATIO_PREQ_10G 0x3
-//#define RATIO_PST1Q_10G 0xa
-//#define RATIO_EQ_10G 0x29
-
-/* 40G Long cables setup: 1 m to 2 m cables */
-#define RATIO_PREQ_40G 0x2
-#define RATIO_PST1Q_40G 0xd
-#define RATIO_EQ_40G 0x20
-
-/* 40G Short cables setup: up to 30 cm cable */
-//#define RATIO_PREQ_40G 0x1
-//#define RATIO_PST1Q_40G 0x3
-//#define RATIO_EQ_40G 0x29
-
-/* LX2 2x40G default RCW setup */
-//#define RATIO_PREQ_40G 0x0
-//#define RATIO_PST1Q_40G 0x3
-//#define RATIO_EQ_40G 0x30
-
-/* Max/Min coefficient values */
-#define PRE_COE_MAX 0x0
-#define PRE_COE_MIN 0x8
-#define POST_COE_MAX 0x0
-#define POST_COE_MIN 0x10
-#define ZERO_COE_MAX 0x30
-#define ZERO_COE_MIN 0x0
-
-/* KR PMD defines */
-#define PMD_RESET 0x1
-#define PMD_STATUS_SUP_STAT 0x4
-#define PMD_STATUS_FRAME_LOCK 0x2
-#define TRAIN_EN 0x3
-#define TRAIN_DISABLE 0x1
-#define RX_STAT 0x1
-
-/* PCS Link up */
-#define XFI_PCS_SR1 0x20
-#define KR_RX_LINK_STAT_MASK 0x1000
-
-/* KX PCS mode register */
-#define KX_PCS_IF_MODE 0x8014
-
-/* KX PCS mode register init value */
-#define KX_IF_MODE_INIT 0x8
-
-/* KX/KR AN registers */
-#define AN_CTRL_INIT 0x1200
-#define KX_AN_AD1_INIT 0x25
-#define KR_AN_AD1_INIT_10G 0x85
-#define KR_AN_AD1_INIT_40G 0x105
-#define AN_LNK_UP_MASK 0x4
-#define KR_AN_MASK_10G 0x8
-#define KR_AN_MASK_40G 0x20
-#define TRAIN_FAIL 0x8
-#define KR_AN_40G_MDIO_OFFSET 4
-
-/* XGKR Timeouts */
-#define XGKR_TIMEOUT 1050
-#define XGKR_DENY_RT_INTERVAL 3000
-#define XGKR_AN_WAIT_ITERATIONS 5
-
-/* XGKR Increment/Decrement Requests */
-#define INCREMENT 1
-#define DECREMENT 2
-#define TIMEOUT_LONG 3
-#define TIMEOUT_M1 3
-
-/* XGKR Masks */
-#define RX_READY_MASK 0x8000
-#define PRESET_MASK 0x2000
-#define INIT_MASK 0x1000
-#define COP1_MASK 0x30
-#define COP1_SHIFT 4
-#define COZ_MASK 0xc
-#define COZ_SHIFT 2
-#define COM1_MASK 0x3
-#define COM1_SHIFT 0
-#define REQUEST_MASK 0x3f
-#define LD_ALL_MASK (PRESET_MASK | INIT_MASK | \
- COP1_MASK | COZ_MASK | COM1_MASK)
-
-/* Lanes definitions */
-#define MASTER_LANE 0
-#define SINGLE_LANE 0
-#define MAX_PHY_LANES_NO 4
-
-/* Invalid value */
-#define VAL_INVALID 0xff
-
-/* New XGKR Training Algorithm */
-#define NEW_ALGORITHM_TRAIN_TX
-
-#ifdef NEW_ALGORITHM_TRAIN_TX
-#define FORCE_INC_COP1_NUMBER 0
-#define FORCE_INC_COM1_NUMBER 1
-#endif
-
-/* Link_Training_Registers offsets */
-static int lt_MDIO_MMD = 0;
-static u32 lt_KR_PMD_CTRL = 0;
-static u32 lt_KR_PMD_STATUS = 0;
-static u32 lt_KR_LP_CU = 0;
-static u32 lt_KR_LP_STATUS = 0;
-static u32 lt_KR_LD_CU = 0;
-static u32 lt_KR_LD_STATUS = 0;
-
-/* KX/KR AN registers offsets */
-static u32 g_an_AD1 = 0;
-static u32 g_an_BP_STAT = 0;
-
-static const u32 preq_table[] = {0x0, 0x1, 0x3, 0x5,
- 0x7, 0x9, 0xb, 0xc, VAL_INVALID};
-static const u32 pst1q_table[] = {0x0, 0x1, 0x3, 0x5, 0x7,
- 0x9, 0xb, 0xd, 0xf, 0x10, VAL_INVALID};
-
-enum backplane_mode {
- PHY_BACKPLANE_1000BASE_KX,
- PHY_BACKPLANE_10GBASE_KR,
- PHY_BACKPLANE_40GBASE_KR,
- PHY_BACKPLANE_INVAL
-};
-
-enum serdes_type {
- SERDES_10G,
- SERDES_28G,
- SERDES_INVAL
-};
-
-enum coe_filed {
- COE_COP1,
- COE_COZ,
- COE_COM
-};
-
-enum coe_update {
- COE_NOTUPDATED,
- COE_UPDATED,
- COE_MIN,
- COE_MAX,
- COE_INV
-};
-
-enum train_state {
- DETECTING_LP,
- TRAINED,
-};
-
-struct tx_condition {
- bool bin_m1_late_early;
- bool bin_long_late_early;
- bool bin_m1_stop;
- bool bin_long_stop;
- bool tx_complete;
- bool sent_init;
- int m1_min_max_cnt;
- int long_min_max_cnt;
-#ifdef NEW_ALGORITHM_TRAIN_TX
- int pre_inc;
- int post_inc;
-#endif
-};
-
-struct xgkr_params {
- void *reg_base; /* lane memory map: registers base address */
- int idx; /* lane relative index inside a multi-lane PHY */
- struct phy_device *phydev;
- struct serdes_access *srds;
- struct tx_condition tx_c;
- struct delayed_work xgkr_wk;
- enum train_state state;
- int an_wait_count;
- unsigned long rt_time;
- u32 ld_update;
- u32 ld_status;
- u32 ratio_preq;
- u32 ratio_pst1q;
- u32 adpt_eq;
- u32 tuned_ratio_preq;
- u32 tuned_ratio_pst1q;
- u32 tuned_adpt_eq;
-};
-
-struct xgkr_phy_data {
- int bp_mode;
- u32 phy_lanes;
- struct mutex phy_lock;
- bool aneg_done;
- struct xgkr_params xgkr[MAX_PHY_LANES_NO];
-};
-
-static void setup_an_lt_ls(void)
-{
- /* KR PMD registers */
- lt_MDIO_MMD = MDIO_MMD_PMAPMD;
- lt_KR_PMD_CTRL = 0x96;
- lt_KR_PMD_STATUS = 0x97;
- lt_KR_LP_CU = 0x98;
- lt_KR_LP_STATUS = 0x99;
- lt_KR_LD_CU = 0x9a;
- lt_KR_LD_STATUS = 0x9b;
-
- /* KX/KR AN registers */
- g_an_AD1 = 0x11;
- g_an_BP_STAT = 0x30;
-}
-
-static void setup_an_lt_lx(void)
-{
- /* Auto-Negotiation and Link Training Core Registers page 1: 256 = 0x100 */
- lt_MDIO_MMD = MDIO_MMD_AN;
- lt_KR_PMD_CTRL = 0x100;
- lt_KR_PMD_STATUS = 0x101;
- lt_KR_LP_CU = 0x102;
- lt_KR_LP_STATUS = 0x103;
- lt_KR_LD_CU = 0x104;
- lt_KR_LD_STATUS = 0x105;
-
- /* KX/KR AN registers */
- g_an_AD1 = 0x03;
- g_an_BP_STAT = 0x0F;
-}
-
-static u32 le_ioread32(u32 *reg)
-{
- return ioread32(reg);
-}
-
-static void le_iowrite32(u32 value, u32 *reg)
-{
- iowrite32(value, reg);
-}
-
-static u32 be_ioread32(u32 *reg)
-{
- return ioread32be(reg);
-}
-
-static void be_iowrite32(u32 value, u32 *reg)
-{
- iowrite32be(value, reg);
-}
-
-/**
- * xgkr_phy_write_mmd - Wrapper function for phy_write_mmd
- * for writing a register on an MMD on a given PHY.
- *
- * Same rules as for phy_write_mmd();
- */
-static int xgkr_phy_write_mmd(struct xgkr_params *xgkr, int devad, u32 regnum, u16 val)
-{
- struct phy_device *phydev = xgkr->phydev;
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- int mdio_addr = phydev->mdio.addr;
- int err;
-
- mutex_lock(&xgkr_inst->phy_lock);
-
- if (xgkr_inst->bp_mode == PHY_BACKPLANE_40GBASE_KR && devad == MDIO_MMD_AN) {
- //40G AN: prepare mdio address for writing phydev AN registers for 40G on respective lane
- phydev->mdio.addr = KR_AN_40G_MDIO_OFFSET + xgkr->idx;
- }
-
- err = phy_write_mmd(phydev, devad, regnum, val);
- if (err)
- dev_err(&phydev->mdio.dev, "Writing PHY (%p) MMD = 0x%02x register = 0x%02x failed with error code: 0x%08x \n", phydev, devad, regnum, err);
-
- if (xgkr_inst->bp_mode == PHY_BACKPLANE_40GBASE_KR && devad == MDIO_MMD_AN) {
- //40G AN: restore mdio address
- phydev->mdio.addr = mdio_addr;
- }
-
- mutex_unlock(&xgkr_inst->phy_lock);
-
- return err;
-}
-
-/**
- * xgkr_phy_read_mmd - Wrapper function for phy_read_mmd
- * for reading a register from an MMD on a given PHY.
- *
- * Same rules as for phy_read_mmd();
- */
-static int xgkr_phy_read_mmd(struct xgkr_params *xgkr, int devad, u32 regnum)
-{
- struct phy_device *phydev = xgkr->phydev;
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- int mdio_addr = phydev->mdio.addr;
- int ret;
-
- mutex_lock(&xgkr_inst->phy_lock);
-
- if (xgkr_inst->bp_mode == PHY_BACKPLANE_40GBASE_KR && devad == MDIO_MMD_AN) {
- //40G AN: prepare mdio address for reading phydev AN registers for 40G on respective lane
- phydev->mdio.addr = KR_AN_40G_MDIO_OFFSET + xgkr->idx;
- }
-
- ret = phy_read_mmd(phydev, devad, regnum);
-
- if (xgkr_inst->bp_mode == PHY_BACKPLANE_40GBASE_KR && devad == MDIO_MMD_AN) {
- //40G AN: restore mdio address
- phydev->mdio.addr = mdio_addr;
- }
-
- mutex_unlock(&xgkr_inst->phy_lock);
-
- return ret;
-}
-
-static void tx_condition_init(struct tx_condition *tx_c)
-{
- tx_c->bin_m1_late_early = true;
- tx_c->bin_long_late_early = false;
- tx_c->bin_m1_stop = false;
- tx_c->bin_long_stop = false;
- tx_c->tx_complete = false;
- tx_c->sent_init = false;
- tx_c->m1_min_max_cnt = 0;
- tx_c->long_min_max_cnt = 0;
-#ifdef NEW_ALGORITHM_TRAIN_TX
- tx_c->pre_inc = FORCE_INC_COM1_NUMBER;
- tx_c->post_inc = FORCE_INC_COP1_NUMBER;
-#endif
-}
-
-void tune_tecr(struct xgkr_params *xgkr)
-{
- struct phy_device *phydev = xgkr->phydev;
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- bool reset = false;
-
- if (xgkr_inst->bp_mode == PHY_BACKPLANE_40GBASE_KR) {
- /* Reset only the Master Lane */
- reset = (xgkr->idx == MASTER_LANE);
- } else {
- reset = true;
- }
-
- xgkr->srds->tune_tecr(xgkr->reg_base, xgkr->ratio_preq, xgkr->ratio_pst1q, xgkr->adpt_eq, reset);
-
- xgkr->tuned_ratio_preq = xgkr->ratio_preq;
- xgkr->tuned_ratio_pst1q = xgkr->ratio_pst1q;
- xgkr->tuned_adpt_eq = xgkr->adpt_eq;
-}
-
-static void start_lt(struct xgkr_params *xgkr)
-{
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, lt_KR_PMD_CTRL, TRAIN_EN);
-}
-
-static void stop_lt(struct xgkr_params *xgkr)
-{
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, lt_KR_PMD_CTRL, TRAIN_DISABLE);
-}
-
-static void reset_lt(struct xgkr_params *xgkr)
-{
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, MDIO_CTRL1, PMD_RESET);
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, lt_KR_PMD_CTRL, TRAIN_DISABLE);
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, lt_KR_LD_CU, 0);
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, lt_KR_LD_STATUS, 0);
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, lt_KR_PMD_STATUS, 0);
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, lt_KR_LP_CU, 0);
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD, lt_KR_LP_STATUS, 0);
-
-}
-
-static void ld_coe_status(struct xgkr_params *xgkr)
-{
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD,
- lt_KR_LD_STATUS, xgkr->ld_status);
-}
-
-static void ld_coe_update(struct xgkr_params *xgkr)
-{
- dev_dbg(&xgkr->phydev->mdio.dev, "sending request: %x\n", xgkr->ld_update);
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD,
- lt_KR_LD_CU, xgkr->ld_update);
-}
-
-static void start_xgkr_state_machine(struct delayed_work *work)
-{
- queue_delayed_work(system_power_efficient_wq, work,
- msecs_to_jiffies(XGKR_TIMEOUT));
-}
-
-static void start_xgkr_an(struct xgkr_params *xgkr)
-{
- struct phy_device *phydev = xgkr->phydev;
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- int i;
- int err;
-
- switch (xgkr_inst->bp_mode)
- {
- case PHY_BACKPLANE_1000BASE_KX:
- dev_err(&phydev->mdio.dev, "Wrong call path for 1000Base-KX \n");
- break;
-
- case PHY_BACKPLANE_10GBASE_KR:
- err = xgkr_phy_write_mmd(xgkr, MDIO_MMD_AN, g_an_AD1, KR_AN_AD1_INIT_10G);
- if (err)
- dev_err(&phydev->mdio.dev, "Setting AN register 0x%02x failed with error code: 0x%08x \n", g_an_AD1, err);
- udelay(1);
- err = xgkr_phy_write_mmd(xgkr, MDIO_MMD_AN, MDIO_CTRL1, AN_CTRL_INIT);
- if (err)
- dev_err(&phydev->mdio.dev, "Setting AN register 0x%02x failed with error code: 0x%08x \n", MDIO_CTRL1, err);
- break;
-
- case PHY_BACKPLANE_40GBASE_KR:
- if (xgkr->idx == MASTER_LANE) {
- for (i = 0; i < xgkr_inst->phy_lanes; i++) {
- err = xgkr_phy_write_mmd(&xgkr_inst->xgkr[i], MDIO_MMD_AN, g_an_AD1, KR_AN_AD1_INIT_40G);
- if (err)
- dev_err(&phydev->mdio.dev, "Setting AN register 0x%02x on lane %d failed with error code: 0x%08x \n", g_an_AD1, xgkr_inst->xgkr[i].idx, err);
- }
- udelay(1);
- err = xgkr_phy_write_mmd(xgkr, MDIO_MMD_AN, MDIO_CTRL1, AN_CTRL_INIT);
- if (err)
- dev_err(&phydev->mdio.dev, "Setting AN register 0x%02x on Master Lane failed with error code: 0x%08x \n", MDIO_CTRL1, err);
- }
- break;
- }
-}
-
-static void start_1gkx_an(struct phy_device *phydev)
-{
- phy_write_mmd(phydev, MDIO_MMD_PCS, KX_PCS_IF_MODE, KX_IF_MODE_INIT);
- phy_write_mmd(phydev, MDIO_MMD_AN, g_an_AD1, KX_AN_AD1_INIT);
- phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, AN_CTRL_INIT);
-}
-
-static void reset_tecr(struct xgkr_params *xgkr)
-{
- struct phy_device *phydev = xgkr->phydev;
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
-
- switch (xgkr_inst->bp_mode)
- {
- case PHY_BACKPLANE_1000BASE_KX:
- dev_err(&phydev->mdio.dev, "Wrong call path for 1000Base-KX \n");
- break;
-
- case PHY_BACKPLANE_10GBASE_KR:
- xgkr->ratio_preq = RATIO_PREQ_10G;
- xgkr->ratio_pst1q = RATIO_PST1Q_10G;
- xgkr->adpt_eq = RATIO_EQ_10G;
- break;
-
- case PHY_BACKPLANE_40GBASE_KR:
- xgkr->ratio_preq = RATIO_PREQ_40G;
- xgkr->ratio_pst1q = RATIO_PST1Q_40G;
- xgkr->adpt_eq = RATIO_EQ_40G;
- break;
- }
-
- tune_tecr(xgkr);
-}
-
-static void init_xgkr(struct xgkr_params *xgkr, int reset)
-{
- if (reset)
- reset_tecr(xgkr);
-
- tx_condition_init(&xgkr->tx_c);
- xgkr->state = DETECTING_LP;
-
- xgkr->ld_status &= RX_READY_MASK;
- ld_coe_status(xgkr);
- xgkr->ld_update = 0;
- xgkr->ld_status &= ~RX_READY_MASK;
- ld_coe_status(xgkr);
-
-}
-
-static void initialize(struct xgkr_params *xgkr)
-{
- reset_tecr(xgkr);
-
- xgkr->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
- xgkr->ld_status |= COE_UPDATED << COP1_SHIFT |
- COE_UPDATED << COZ_SHIFT |
- COE_UPDATED << COM1_SHIFT;
- ld_coe_status(xgkr);
-}
-
-static void train_remote_tx(struct xgkr_params *xgkr)
-{
- struct tx_condition *tx_c = &xgkr->tx_c;
- bool bin_m1_early, bin_long_early;
- u32 lp_status, old_ld_update;
- u32 status_cop1, status_coz, status_com1;
- u32 req_cop1, req_coz, req_com1, req_preset, req_init;
- u32 temp;
-#ifdef NEW_ALGORITHM_TRAIN_TX
- u32 median_gaink2;
-#endif
-
-recheck:
- if (tx_c->bin_long_stop && tx_c->bin_m1_stop) {
- tx_c->tx_complete = true;
- xgkr->ld_status |= RX_READY_MASK;
- ld_coe_status(xgkr);
-
- /* tell LP we are ready */
- xgkr_phy_write_mmd(xgkr, lt_MDIO_MMD,
- lt_KR_PMD_STATUS, RX_STAT);
-
- return;
- }
-
- /* We start by checking the current LP status. If we got any responses,
- * we can clear up the appropriate update request so that the
- * subsequent code may easily issue new update requests if needed.
- */
- lp_status = xgkr_phy_read_mmd(xgkr, lt_MDIO_MMD, lt_KR_LP_STATUS) &
- REQUEST_MASK;
-
- status_cop1 = (lp_status & COP1_MASK) >> COP1_SHIFT;
- status_coz = (lp_status & COZ_MASK) >> COZ_SHIFT;
- status_com1 = (lp_status & COM1_MASK) >> COM1_SHIFT;
-
- old_ld_update = xgkr->ld_update;
- req_cop1 = (old_ld_update & COP1_MASK) >> COP1_SHIFT;
- req_coz = (old_ld_update & COZ_MASK) >> COZ_SHIFT;
- req_com1 = (old_ld_update & COM1_MASK) >> COM1_SHIFT;
- req_preset = old_ld_update & PRESET_MASK;
- req_init = old_ld_update & INIT_MASK;
-
- /* IEEE802.3-2008, 72.6.10.2.3.1
- * We may clear PRESET when all coefficients show UPDATED or MAX.
- */
- if (req_preset) {
- if ((status_cop1 == COE_UPDATED || status_cop1 == COE_MAX) &&
- (status_coz == COE_UPDATED || status_coz == COE_MAX) &&
- (status_com1 == COE_UPDATED || status_com1 == COE_MAX)) {
- xgkr->ld_update &= ~PRESET_MASK;
- }
- }
-
- /* IEEE802.3-2008, 72.6.10.2.3.2
- * We may clear INITIALIZE when no coefficients show NOT UPDATED.
- */
- if (req_init) {
- if (status_cop1 != COE_NOTUPDATED &&
- status_coz != COE_NOTUPDATED &&
- status_com1 != COE_NOTUPDATED) {
- xgkr->ld_update &= ~INIT_MASK;
- }
- }
-
- /* IEEE802.3-2008, 72.6.10.2.3.2
- * we send initialize to the other side to ensure default settings
- * for the LP. Naturally, we should do this only once.
- */
- if (!tx_c->sent_init) {
- if (!lp_status && !(old_ld_update & (LD_ALL_MASK))) {
- xgkr->ld_update = INIT_MASK;
- tx_c->sent_init = true;
- }
- }
-
- /* IEEE802.3-2008, 72.6.10.2.3.3
- * We set coefficient requests to HOLD when we get the information
- * about any updates On clearing our prior response, we also update
- * our internal status.
- */
- if (status_cop1 != COE_NOTUPDATED) {
- if (req_cop1) {
- xgkr->ld_update &= ~COP1_MASK;
-#ifdef NEW_ALGORITHM_TRAIN_TX
- if (tx_c->post_inc) {
- if (req_cop1 == INCREMENT &&
- status_cop1 == COE_MAX) {
- tx_c->post_inc = 0;
- tx_c->bin_long_stop = true;
- tx_c->bin_m1_stop = true;
- } else {
- tx_c->post_inc -= 1;
- }
-
- ld_coe_update(xgkr);
- goto recheck;
- }
-#endif
- if ((req_cop1 == DECREMENT && status_cop1 == COE_MIN) ||
- (req_cop1 == INCREMENT && status_cop1 == COE_MAX)) {
- dev_dbg(&xgkr->phydev->mdio.dev, "COP1 hit limit %s",
- (status_cop1 == COE_MIN) ?
- "DEC MIN" : "INC MAX");
- tx_c->long_min_max_cnt++;
- if (tx_c->long_min_max_cnt >= TIMEOUT_LONG) {
- tx_c->bin_long_stop = true;
- ld_coe_update(xgkr);
- goto recheck;
- }
- }
- }
- }
-
- if (status_coz != COE_NOTUPDATED) {
- if (req_coz)
- xgkr->ld_update &= ~COZ_MASK;
- }
-
- if (status_com1 != COE_NOTUPDATED) {
- if (req_com1) {
- xgkr->ld_update &= ~COM1_MASK;
-#ifdef NEW_ALGORITHM_TRAIN_TX
- if (tx_c->pre_inc) {
- if (req_com1 == INCREMENT &&
- status_com1 == COE_MAX)
- tx_c->pre_inc = 0;
- else
- tx_c->pre_inc -= 1;
-
- ld_coe_update(xgkr);
- goto recheck;
- }
-#endif
- /* Stop If we have reached the limit for a parameter. */
- if ((req_com1 == DECREMENT && status_com1 == COE_MIN) ||
- (req_com1 == INCREMENT && status_com1 == COE_MAX)) {
- dev_dbg(&xgkr->phydev->mdio.dev, "COM1 hit limit %s",
- (status_com1 == COE_MIN) ?
- "DEC MIN" : "INC MAX");
- tx_c->m1_min_max_cnt++;
- if (tx_c->m1_min_max_cnt >= TIMEOUT_M1) {
- tx_c->bin_m1_stop = true;
- ld_coe_update(xgkr);
- goto recheck;
- }
- }
- }
- }
-
- if (old_ld_update != xgkr->ld_update) {
- ld_coe_update(xgkr);
- /* Redo these status checks and updates until we have no more
- * changes, to speed up the overall process.
- */
- goto recheck;
- }
-
- /* Do nothing if we have pending request. */
- if ((req_coz || req_com1 || req_cop1))
- return;
- else if (lp_status)
- /* No pending request but LP status was not reverted to
- * not updated.
- */
- return;
-
-#ifdef NEW_ALGORITHM_TRAIN_TX
- if (!(xgkr->ld_update & (PRESET_MASK | INIT_MASK))) {
- if (tx_c->pre_inc) {
- xgkr->ld_update = INCREMENT << COM1_SHIFT;
- ld_coe_update(xgkr);
- return;
- }
-
- if (status_cop1 != COE_MAX) {
- median_gaink2 = xgkr->srds->get_median_gaink2(xgkr->reg_base);
- if (median_gaink2 == 0xf) {
- tx_c->post_inc = 1;
- } else {
- /* Gaink2 median lower than "F" */
- tx_c->bin_m1_stop = true;
- tx_c->bin_long_stop = true;
- goto recheck;
- }
- } else {
- /* C1 MAX */
- tx_c->bin_m1_stop = true;
- tx_c->bin_long_stop = true;
- goto recheck;
- }
-
- if (tx_c->post_inc) {
- xgkr->ld_update = INCREMENT << COP1_SHIFT;
- ld_coe_update(xgkr);
- return;
- }
- }
-#endif
-
- /* snapshot and select bin */
- bin_m1_early = xgkr->srds->is_bin_early(BIN_M1, xgkr->reg_base);
- bin_long_early = xgkr->srds->is_bin_early(BIN_LONG, xgkr->reg_base);
-
- if (!tx_c->bin_m1_stop && !tx_c->bin_m1_late_early && bin_m1_early) {
- tx_c->bin_m1_stop = true;
- goto recheck;
- }
-
- if (!tx_c->bin_long_stop &&
- tx_c->bin_long_late_early && !bin_long_early) {
- tx_c->bin_long_stop = true;
- goto recheck;
- }
-
- /* IEEE802.3-2008, 72.6.10.2.3.3
- * We only request coefficient updates when no PRESET/INITIALIZE is
- * pending. We also only request coefficient updates when the
- * corresponding status is NOT UPDATED and nothing is pending.
- */
- if (!(xgkr->ld_update & (PRESET_MASK | INIT_MASK))) {
- if (!tx_c->bin_long_stop) {
- /* BinM1 correction means changing COM1 */
- if (!status_com1 && !(xgkr->ld_update & COM1_MASK)) {
- /* Avoid BinM1Late by requesting an
- * immediate decrement.
- */
- if (!bin_m1_early) {
- /* request decrement c(-1) */
- temp = DECREMENT << COM1_SHIFT;
- xgkr->ld_update = temp;
- ld_coe_update(xgkr);
- tx_c->bin_m1_late_early = bin_m1_early;
- return;
- }
- }
-
- /* BinLong correction means changing COP1 */
- if (!status_cop1 && !(xgkr->ld_update & COP1_MASK)) {
- /* Locate BinLong transition point (if any)
- * while avoiding BinM1Late.
- */
- if (bin_long_early) {
- /* request increment c(1) */
- temp = INCREMENT << COP1_SHIFT;
- xgkr->ld_update = temp;
- } else {
- /* request decrement c(1) */
- temp = DECREMENT << COP1_SHIFT;
- xgkr->ld_update = temp;
- }
-
- ld_coe_update(xgkr);
- tx_c->bin_long_late_early = bin_long_early;
- }
- /* We try to finish BinLong before we do BinM1 */
- return;
- }
-
- if (!tx_c->bin_m1_stop) {
- /* BinM1 correction means changing COM1 */
- if (!status_com1 && !(xgkr->ld_update & COM1_MASK)) {
- /* Locate BinM1 transition point (if any) */
- if (bin_m1_early) {
- /* request increment c(-1) */
- temp = INCREMENT << COM1_SHIFT;
- xgkr->ld_update = temp;
- } else {
- /* request decrement c(-1) */
- temp = DECREMENT << COM1_SHIFT;
- xgkr->ld_update = temp;
- }
-
- ld_coe_update(xgkr);
- tx_c->bin_m1_late_early = bin_m1_early;
- }
- }
- }
-}
-
-static int is_link_up(struct phy_device *phydev)
-{
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- int val = 0;
-
- mutex_lock(&xgkr_inst->phy_lock);
-
- val = phy_read_mmd(phydev, MDIO_MMD_PCS, XFI_PCS_SR1);
-
- mutex_unlock(&xgkr_inst->phy_lock);
-
- return (val & KR_RX_LINK_STAT_MASK) ? 1 : 0;
-}
-
-static int is_link_training_fail(struct xgkr_params *xgkr)
-{
- struct phy_device *phydev = xgkr->phydev;
- int val;
- int timeout = 100;
-
- val = xgkr_phy_read_mmd(xgkr, lt_MDIO_MMD, lt_KR_PMD_STATUS);
-
- if (!(val & TRAIN_FAIL) && (val & RX_STAT)) {
- /* check LNK_STAT for sure */
- while (timeout--) {
- if (is_link_up(phydev))
- return 0;
-
- usleep_range(100, 500);
- }
- }
-
- return 1;
-}
-
-static int check_rx(struct xgkr_params *xgkr)
-{
- return xgkr_phy_read_mmd(xgkr, lt_MDIO_MMD, lt_KR_LP_STATUS) &
- RX_READY_MASK;
-}
-
-/* Coefficient values have hardware restrictions */
-static int is_ld_valid(struct xgkr_params *xgkr)
-{
- u32 ratio_pst1q = xgkr->ratio_pst1q;
- u32 adpt_eq = xgkr->adpt_eq;
- u32 ratio_preq = xgkr->ratio_preq;
-
- if ((ratio_pst1q + adpt_eq + ratio_preq) > 48)
- return 0;
-
- if (((ratio_pst1q + adpt_eq + ratio_preq) * 4) >=
- ((adpt_eq - ratio_pst1q - ratio_preq) * 17))
- return 0;
-
- if (ratio_preq > ratio_pst1q)
- return 0;
-
- if (ratio_preq > 8)
- return 0;
-
- if (adpt_eq < 26)
- return 0;
-
- if (ratio_pst1q > 16)
- return 0;
-
- return 1;
-}
-
-static int is_value_allowed(const u32 *val_table, u32 val)
-{
- int i;
-
- for (i = 0;; i++) {
- if (*(val_table + i) == VAL_INVALID)
- return 0;
- if (*(val_table + i) == val)
- return 1;
- }
-}
-
-static enum coe_update inc_dec(struct xgkr_params *xgkr, int field, int request)
-{
- u32 ld_limit[3], ld_coe[3], step[3];
-
- ld_coe[0] = xgkr->ratio_pst1q;
- ld_coe[1] = xgkr->adpt_eq;
- ld_coe[2] = xgkr->ratio_preq;
-
- /* Information specific to the SerDes for 10GBase-KR:
- * Incrementing C(+1) means *decrementing* RATIO_PST1Q
- * Incrementing C(0) means incrementing ADPT_EQ
- * Incrementing C(-1) means *decrementing* RATIO_PREQ
- */
- step[0] = -1;
- step[1] = 1;
- step[2] = -1;
-
- switch (request) {
- case INCREMENT:
- ld_limit[0] = POST_COE_MAX;
- ld_limit[1] = ZERO_COE_MAX;
- ld_limit[2] = PRE_COE_MAX;
- if (ld_coe[field] != ld_limit[field])
- ld_coe[field] += step[field];
- else
- /* MAX */
- return COE_MAX;
- break;
- case DECREMENT:
- ld_limit[0] = POST_COE_MIN;
- ld_limit[1] = ZERO_COE_MIN;
- ld_limit[2] = PRE_COE_MIN;
- if (ld_coe[field] != ld_limit[field])
- ld_coe[field] -= step[field];
- else
- /* MIN */
- return COE_MIN;
- break;
- default:
- break;
- }
-
- if (is_ld_valid(xgkr)) {
- /* accept new ld */
- xgkr->ratio_pst1q = ld_coe[0];
- xgkr->adpt_eq = ld_coe[1];
- xgkr->ratio_preq = ld_coe[2];
- /* only some values for preq and pst1q can be used.
- * for preq: 0x0, 0x1, 0x3, 0x5, 0x7, 0x9, 0xb, 0xc.
- * for pst1q: 0x0, 0x1, 0x3, 0x5, 0x7, 0x9, 0xb, 0xd, 0xf, 0x10.
- */
- if (!is_value_allowed((const u32 *)&preq_table, ld_coe[2])) {
- dev_dbg(&xgkr->phydev->mdio.dev,
- "preq skipped value: %d\n", ld_coe[2]);
- /* NOT UPDATED */
- return COE_NOTUPDATED;
- }
-
- if (!is_value_allowed((const u32 *)&pst1q_table, ld_coe[0])) {
- dev_dbg(&xgkr->phydev->mdio.dev,
- "pst1q skipped value: %d\n", ld_coe[0]);
- /* NOT UPDATED */
- return COE_NOTUPDATED;
- }
-
- tune_tecr(xgkr);
- } else {
- if (request == DECREMENT)
- /* MIN */
- return COE_MIN;
- if (request == INCREMENT)
- /* MAX */
- return COE_MAX;
- }
-
- /* UPDATED */
- return COE_UPDATED;
-}
-
-static void min_max_updated(struct xgkr_params *xgkr, int field, enum coe_update cs)
-{
- u32 mask, val;
- u32 ld_cs = cs;
-
- if (cs == COE_INV)
- return;
-
- switch (field) {
- case COE_COP1:
- mask = COP1_MASK;
- val = ld_cs << COP1_SHIFT;
- break;
- case COE_COZ:
- mask = COZ_MASK;
- val = ld_cs << COZ_SHIFT;
- break;
- case COE_COM:
- mask = COM1_MASK;
- val = ld_cs << COM1_SHIFT;
- break;
- default:
- return;
- }
-
- xgkr->ld_status &= ~mask;
- xgkr->ld_status |= val;
-}
-
-static void check_request(struct xgkr_params *xgkr, int request)
-{
- int cop1_req, coz_req, com_req;
- int old_status;
- enum coe_update cu;
-
- cop1_req = (request & COP1_MASK) >> COP1_SHIFT;
- coz_req = (request & COZ_MASK) >> COZ_SHIFT;
- com_req = (request & COM1_MASK) >> COM1_SHIFT;
-
- /* IEEE802.3-2008, 72.6.10.2.5
- * Ensure we only act on INCREMENT/DECREMENT when we are in NOT UPDATED
- */
- old_status = xgkr->ld_status;
-
- if (cop1_req && !(xgkr->ld_status & COP1_MASK)) {
- cu = inc_dec(xgkr, COE_COP1, cop1_req);
- min_max_updated(xgkr, COE_COP1, cu);
- }
-
- if (coz_req && !(xgkr->ld_status & COZ_MASK)) {
- cu = inc_dec(xgkr, COE_COZ, coz_req);
- min_max_updated(xgkr, COE_COZ, cu);
- }
-
- if (com_req && !(xgkr->ld_status & COM1_MASK)) {
- cu = inc_dec(xgkr, COE_COM, com_req);
- min_max_updated(xgkr, COE_COM, cu);
- }
-
- if (old_status != xgkr->ld_status)
- ld_coe_status(xgkr);
-}
-
-static void preset(struct xgkr_params *xgkr)
-{
- /* These are all MAX values from the IEEE802.3 perspective. */
- xgkr->ratio_pst1q = POST_COE_MAX;
- xgkr->adpt_eq = ZERO_COE_MAX;
- xgkr->ratio_preq = PRE_COE_MAX;
-
- tune_tecr(xgkr);
- xgkr->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
- xgkr->ld_status |= COE_MAX << COP1_SHIFT |
- COE_MAX << COZ_SHIFT |
- COE_MAX << COM1_SHIFT;
- ld_coe_status(xgkr);
-}
-
-static void train_local_tx(struct xgkr_params *xgkr)
-{
- int request, old_ld_status;
-
- /* get request from LP */
- request = xgkr_phy_read_mmd(xgkr, lt_MDIO_MMD, lt_KR_LP_CU) &
- (LD_ALL_MASK);
-
- old_ld_status = xgkr->ld_status;
-
- /* IEEE802.3-2008, 72.6.10.2.5
- * Ensure we always go to NOT UDPATED for status reporting in
- * response to HOLD requests.
- * IEEE802.3-2008, 72.6.10.2.3.1/2
- * ... but only if PRESET/INITIALIZE are not active to ensure
- * we keep status until they are released.
- */
- if (!(request & (PRESET_MASK | INIT_MASK))) {
- if (!(request & COP1_MASK))
- xgkr->ld_status &= ~COP1_MASK;
-
- if (!(request & COZ_MASK))
- xgkr->ld_status &= ~COZ_MASK;
-
- if (!(request & COM1_MASK))
- xgkr->ld_status &= ~COM1_MASK;
-
- if (old_ld_status != xgkr->ld_status)
- ld_coe_status(xgkr);
- }
-
- /* As soon as the LP shows ready, no need to do any more updates. */
- if (check_rx(xgkr)) {
- /* LP receiver is ready */
- if (xgkr->ld_status & (COP1_MASK | COZ_MASK | COM1_MASK)) {
- xgkr->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
- ld_coe_status(xgkr);
- }
- } else {
- /* IEEE802.3-2008, 72.6.10.2.3.1/2
- * only act on PRESET/INITIALIZE if all status is NOT UPDATED.
- */
- if (request & (PRESET_MASK | INIT_MASK)) {
- if (!(xgkr->ld_status &
- (COP1_MASK | COZ_MASK | COM1_MASK))) {
- if (request & PRESET_MASK)
- preset(xgkr);
-
- if (request & INIT_MASK)
- initialize(xgkr);
- }
- }
-
- /* LP Coefficient are not in HOLD */
- if (request & REQUEST_MASK)
- check_request(xgkr, request & REQUEST_MASK);
- }
-}
-
-static void xgkr_start_train(struct xgkr_params *xgkr)
-{
- struct phy_device *phydev = xgkr->phydev;
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- struct tx_condition *tx_c = &xgkr->tx_c;
- int val = 0, i, j;
- int lt_state;
- unsigned long dead_line;
- int lp_rx_ready, tx_training_complete;
- u32 lt_timeout = 500;
-
- init_xgkr(xgkr, 0);
-
- start_lt(xgkr);
-
- if (xgkr_inst->bp_mode == PHY_BACKPLANE_40GBASE_KR) {
- lt_timeout = 2000;
- }
-
- for (i = 0; i < 2;) {
-
- dead_line = jiffies + msecs_to_jiffies(lt_timeout);
-
- while (time_before(jiffies, dead_line)) {
-
- val = xgkr_phy_read_mmd(xgkr, lt_MDIO_MMD,
- lt_KR_PMD_STATUS);
-
- if (val & TRAIN_FAIL) {
- /* LT failed already, reset lane to avoid
- * it run into hanging, then start LT again.
- */
- if (xgkr_inst->bp_mode == PHY_BACKPLANE_40GBASE_KR) {
- /* Reset only the Master Lane */
- if (xgkr->idx == MASTER_LANE)
- xgkr->srds->reset_lane(xgkr->reg_base);
- } else {
- xgkr->srds->reset_lane(xgkr->reg_base);
- }
-
- start_lt(xgkr);
- } else if ((val & PMD_STATUS_SUP_STAT) &&
- (val & PMD_STATUS_FRAME_LOCK))
- break;
- usleep_range(100, 500);
- }
-
- if (!((val & PMD_STATUS_FRAME_LOCK) &&
- (val & PMD_STATUS_SUP_STAT))) {
- i++;
- continue;
- }
-
- /* init process */
- lp_rx_ready = false;
- tx_training_complete = false;
- /* the LT should be finished in 500ms, failed or OK. */
- dead_line = jiffies + msecs_to_jiffies(lt_timeout);
-
- while (time_before(jiffies, dead_line)) {
- /* check if the LT is already failed */
-
- lt_state = xgkr_phy_read_mmd(xgkr, lt_MDIO_MMD,
- lt_KR_PMD_STATUS);
-
- if (lt_state & TRAIN_FAIL) {
-
- if (xgkr_inst->bp_mode == PHY_BACKPLANE_40GBASE_KR) {
- /* Reset only the Master Lane */
- if (xgkr->idx == MASTER_LANE)
- xgkr->srds->reset_lane(xgkr->reg_base);
- } else {
- xgkr->srds->reset_lane(xgkr->reg_base);
- }
-
- break;
- }
-
- lp_rx_ready = check_rx(xgkr);
- tx_training_complete = tx_c->tx_complete;
-
- if (lp_rx_ready && tx_training_complete)
- break;
-
- if (!lp_rx_ready)
- train_local_tx(xgkr);
-
- if (!tx_training_complete)
- train_remote_tx(xgkr);
-
- usleep_range(100, 500);
- }
-
- i++;
- /* check LT result */
- if (is_link_training_fail(xgkr)) {
- init_xgkr(xgkr, 0);
- continue;
- } else {
- stop_lt(xgkr);
- xgkr->state = TRAINED;
-
- switch (xgkr_inst->bp_mode)
- {
- case PHY_BACKPLANE_10GBASE_KR:
- if (phydev->attached_dev == NULL)
- dev_info(&phydev->mdio.dev, "10GBase-KR link trained (Tx equalization: RATIO_PREQ = 0x%x, RATIO_PST1Q = 0x%x, ADPT_EQ = 0x%x)\n",
- xgkr->tuned_ratio_preq, xgkr->tuned_ratio_pst1q, xgkr->tuned_adpt_eq);
- else
- dev_info(&phydev->mdio.dev, "%s %s: 10GBase-KR link trained (Tx equalization: RATIO_PREQ = 0x%x, RATIO_PST1Q = 0x%x, ADPT_EQ = 0x%x)\n",
- dev_driver_string(phydev->attached_dev->dev.parent),
- dev_name(phydev->attached_dev->dev.parent),
- xgkr->tuned_ratio_preq, xgkr->tuned_ratio_pst1q, xgkr->tuned_adpt_eq);
- break;
-
- case PHY_BACKPLANE_40GBASE_KR:
- if (xgkr->idx == xgkr_inst->phy_lanes - 1) {
- if (phydev->attached_dev == NULL)
- dev_info(&phydev->mdio.dev, "40GBase-KR link trained at lanes Tx equalization:\n");
- else
- dev_info(&phydev->mdio.dev, "%s %s: 40GBase-KR link trained at lanes Tx equalization:\n",
- dev_driver_string(phydev->attached_dev->dev.parent),
- dev_name(phydev->attached_dev->dev.parent));
-
- for (j = 0; j < xgkr_inst->phy_lanes; j++) {
- if (phydev->attached_dev == NULL)
- dev_info(&phydev->mdio.dev, "40GBase-KR Lane %d: RATIO_PREQ = 0x%x, RATIO_PST1Q = 0x%x, ADPT_EQ = 0x%x\n",
- j, xgkr_inst->xgkr[j].tuned_ratio_preq, xgkr_inst->xgkr[j].tuned_ratio_pst1q, xgkr_inst->xgkr[j].tuned_adpt_eq);
- else
- dev_info(&phydev->mdio.dev, "%s %s: 40GBase-KR Lane %d: RATIO_PREQ = 0x%x, RATIO_PST1Q = 0x%x, ADPT_EQ = 0x%x\n",
- dev_driver_string(phydev->attached_dev->dev.parent),
- dev_name(phydev->attached_dev->dev.parent),
- j, xgkr_inst->xgkr[j].tuned_ratio_preq, xgkr_inst->xgkr[j].tuned_ratio_pst1q, xgkr_inst->xgkr[j].tuned_adpt_eq);
- }
- }
- break;
- }
-
- break;
- }
- }
-}
-
-static void xgkr_request_restart_an(struct xgkr_params *xgkr)
-{
- struct phy_device *phydev = xgkr->phydev;
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- int i;
-
- if (time_before(jiffies, xgkr->rt_time))
- return;
-
- switch (xgkr_inst->bp_mode)
- {
- case PHY_BACKPLANE_1000BASE_KX:
- dev_err(&phydev->mdio.dev, "Wrong call path for 1000Base-KX \n");
- break;
-
- case PHY_BACKPLANE_10GBASE_KR:
- init_xgkr(xgkr, 0);
- reset_lt(xgkr);
- xgkr->state = DETECTING_LP;
- start_xgkr_an(xgkr);
- start_xgkr_state_machine(&xgkr->xgkr_wk);
- break;
-
- case PHY_BACKPLANE_40GBASE_KR:
- for (i = 0; i < xgkr_inst->phy_lanes; i++) {
- init_xgkr(&xgkr_inst->xgkr[i], 0);
- reset_lt(&xgkr_inst->xgkr[i]);
- xgkr_inst->xgkr[i].state = DETECTING_LP;
- }
- //Start AN only for Master Lane
- start_xgkr_an(&xgkr_inst->xgkr[MASTER_LANE]);
- //start state machine
- for (i = 0; i < xgkr_inst->phy_lanes; i++) {
- start_xgkr_state_machine(&xgkr_inst->xgkr[i].xgkr_wk);
- }
- break;
- }
-
- xgkr->rt_time = jiffies + msecs_to_jiffies(XGKR_DENY_RT_INTERVAL);
-}
-
-static void xgkr_state_machine(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct xgkr_params *xgkr = container_of(dwork,
- struct xgkr_params, xgkr_wk);
- struct phy_device *phydev = xgkr->phydev;
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- int an_state;
- bool start_train = false;
- bool all_lanes_trained = false;
- int i;
-
- if (!xgkr_inst->aneg_done) {
- start_xgkr_state_machine(&xgkr->xgkr_wk);
- return;
- }
-
- mutex_lock(&phydev->lock);
-
- switch (xgkr->state) {
- case DETECTING_LP:
-
- switch (xgkr_inst->bp_mode)
- {
- case PHY_BACKPLANE_1000BASE_KX:
- dev_err(&phydev->mdio.dev, "Wrong call path for 1000Base-KX \n");
- break;
-
- case PHY_BACKPLANE_10GBASE_KR:
- an_state = xgkr_phy_read_mmd(xgkr, MDIO_MMD_AN, g_an_BP_STAT);
- if (an_state & KR_AN_MASK_10G) {
- //AN acquired: Train the lane
- xgkr->an_wait_count = 0;
- start_train = true;
- } else {
- //AN lost or not yet acquired
- if (!is_link_up(phydev)) {
- //Link is down: restart training
- xgkr->an_wait_count = 0;
- xgkr_request_restart_an(xgkr);
- } else {
- //Link is up: wait few iterations for AN to be acquired
- if (xgkr->an_wait_count >= XGKR_AN_WAIT_ITERATIONS) {
- xgkr->an_wait_count = 0;
- xgkr_request_restart_an(xgkr);
- } else {
- xgkr->an_wait_count++;
- }
- }
- }
- break;
-
- case PHY_BACKPLANE_40GBASE_KR:
- //Check AN state only on Master Lane
- an_state = xgkr_phy_read_mmd(&xgkr_inst->xgkr[MASTER_LANE], MDIO_MMD_AN, g_an_BP_STAT);
- if (an_state & KR_AN_MASK_40G) {
- //AN acquired: Train all lanes in order starting with Master Lane
- xgkr->an_wait_count = 0;
- if (xgkr->idx == MASTER_LANE) {
- start_train = true;
- }
- else if (xgkr_inst->xgkr[xgkr->idx - 1].state == TRAINED) {
- start_train = true;
- }
- } else {
- //AN lost or not yet acquired
- if (!is_link_up(phydev)) {
- //Link is down: restart training
- xgkr->an_wait_count = 0;
- xgkr_request_restart_an(xgkr);
- } else {
- //Link is up: wait few iterations for AN to be acquired
- if (xgkr->an_wait_count >= XGKR_AN_WAIT_ITERATIONS) {
- xgkr->an_wait_count = 0;
- xgkr_request_restart_an(xgkr);
- } else {
- xgkr->an_wait_count++;
- }
- }
- }
- break;
- }
- break;
-
- case TRAINED:
- if (!is_link_up(phydev)) {
- switch (xgkr_inst->bp_mode)
- {
- case PHY_BACKPLANE_1000BASE_KX:
- dev_err(&phydev->mdio.dev, "Wrong call path for 1000Base-KX \n");
- break;
-
- case PHY_BACKPLANE_10GBASE_KR:
- dev_info(&phydev->mdio.dev, "Detect hotplug, restart training\n");
- xgkr_request_restart_an(xgkr);
- break;
-
- case PHY_BACKPLANE_40GBASE_KR:
- if (xgkr->idx == MASTER_LANE) {
- //check if all lanes are trained only on Master Lane
- all_lanes_trained = true;
- for (i = 0; i < xgkr_inst->phy_lanes; i++) {
- if (xgkr_inst->xgkr[i].state != TRAINED) {
- all_lanes_trained = false;
- break;
- }
- }
- if (all_lanes_trained) {
- dev_info(&phydev->mdio.dev, "Detect hotplug, restart training\n");
- xgkr_request_restart_an(xgkr);
- }
- }
- break;
- }
- }
- break;
- }
-
- if (start_train) {
- xgkr_start_train(xgkr);
- }
-
- mutex_unlock(&phydev->lock);
- start_xgkr_state_machine(&xgkr->xgkr_wk);
-}
-
-static int fsl_backplane_probe(struct phy_device *phydev)
-{
- struct xgkr_phy_data *xgkr_inst;
- struct device_node *phy_node, *lane_node;
- struct resource res_lane;
- struct serdes_access *srds = NULL;
- int serdes_type;
- const char *st;
- const char *bm;
- int ret, i, phy_lanes;
- int bp_mode;
- u32 lane_base_addr[MAX_PHY_LANES_NO], lane_memmap_size;
-
- phy_node = phydev->mdio.dev.of_node;
- if (!phy_node) {
- dev_err(&phydev->mdio.dev, "No associated device tree node\n");
- return -EINVAL;
- }
-
- bp_mode = of_property_read_string(phy_node, "backplane-mode", &bm);
- if (bp_mode < 0)
- return -EINVAL;
-
- phy_lanes = 1;
- if (!strcasecmp(bm, "1000base-kx")) {
- bp_mode = PHY_BACKPLANE_1000BASE_KX;
- } else if (!strcasecmp(bm, "10gbase-kr")) {
- bp_mode = PHY_BACKPLANE_10GBASE_KR;
- } else if (!strcasecmp(bm, "40gbase-kr")) {
- bp_mode = PHY_BACKPLANE_40GBASE_KR;
- phy_lanes = 4;
- } else {
- dev_err(&phydev->mdio.dev, "Unknown backplane-mode\n");
- return -EINVAL;
- }
-
- lane_node = of_parse_phandle(phy_node, "fsl,lane-handle", 0);
- if (!lane_node) {
- dev_err(&phydev->mdio.dev, "parse fsl,lane-handle failed\n");
- return -EINVAL;
- }
-
- ret = of_property_read_string(lane_node, "compatible", &st);
- if (ret < 0) {
- //assume SERDES-10G if compatible property is not specified
- serdes_type = SERDES_10G;
- }
- else if (!strcasecmp(st, "fsl,serdes-10g")) {
- serdes_type = SERDES_10G;
- } else if (!strcasecmp(st, "fsl,serdes-28g")) {
- serdes_type = SERDES_28G;
- } else {
- dev_err(&phydev->mdio.dev, "Unknown serdes-type\n");
- return -EINVAL;
- }
-
- ret = of_address_to_resource(lane_node, 0, &res_lane);
- if (ret) {
- dev_err(&phydev->mdio.dev, "could not obtain memory map\n");
- return ret;
- }
-
- of_node_put(lane_node);
- ret = of_property_read_u32_array(phy_node, "fsl,lane-reg",
- (u32 *)lane_base_addr, phy_lanes);
- if (ret) {
- dev_err(&phydev->mdio.dev, "could not get fsl,lane-reg\n");
- return -EINVAL;
- }
-
- switch (serdes_type)
- {
- case SERDES_10G:
- setup_an_lt_ls();
- srds = setup_serdes_access_10g();
- break;
-
- case SERDES_28G:
- setup_an_lt_lx();
- srds = setup_serdes_access_28g();
- break;
-
- default:
- dev_err(&phydev->mdio.dev, "Unsupported serdes-type\n");
- return -EINVAL;
- }
-
- if (!srds) {
- dev_err(&phydev->mdio.dev, "Unsupported serdes-type\n");
- return -EINVAL;
- }
-
- srds->serdes_type = serdes_type;
- srds->is_little_endian = of_property_read_bool(lane_node, "little-endian");
-
- if (srds->is_little_endian) {
- srds->ioread32 = le_ioread32;
- srds->iowrite32 = le_iowrite32;
- } else {
- srds->ioread32 = be_ioread32;
- srds->iowrite32 = be_iowrite32;
- }
-
- xgkr_inst = devm_kzalloc(&phydev->mdio.dev,
- sizeof(*xgkr_inst), GFP_KERNEL);
- if (!xgkr_inst)
- return -ENOMEM;
-
- xgkr_inst->phy_lanes = phy_lanes;
- xgkr_inst->bp_mode = bp_mode;
- mutex_init(&xgkr_inst->phy_lock);
-
- lane_memmap_size = srds->get_lane_memmap_size();
-
- for (i = 0; i < phy_lanes; i++) {
- xgkr_inst->xgkr[i].idx = i;
- xgkr_inst->xgkr[i].phydev = phydev;
- xgkr_inst->xgkr[i].srds = srds;
- xgkr_inst->xgkr[i].reg_base = devm_ioremap_nocache(&phydev->mdio.dev,
- res_lane.start + lane_base_addr[i],
- lane_memmap_size);
- if (!xgkr_inst->xgkr[i].reg_base) {
- dev_err(&phydev->mdio.dev, "ioremap_nocache failed\n");
- return -ENOMEM;
- }
- xgkr_inst->xgkr[i].rt_time = jiffies + msecs_to_jiffies(XGKR_DENY_RT_INTERVAL);
- }
-
- phydev->priv = xgkr_inst;
-
- switch (bp_mode)
- {
- case PHY_BACKPLANE_1000BASE_KX:
- phydev->speed = SPEED_1000;
- /* configure the lane for 1000BASE-KX */
- srds->lane_set_1gkx(xgkr_inst->xgkr[SINGLE_LANE].reg_base);
- break;
-
- case PHY_BACKPLANE_10GBASE_KR:
- phydev->speed = SPEED_10000;
- INIT_DELAYED_WORK(&xgkr_inst->xgkr[SINGLE_LANE].xgkr_wk, xgkr_state_machine);
- break;
-
- case PHY_BACKPLANE_40GBASE_KR:
- phydev->speed = SPEED_40000;
- for (i = 0; i < phy_lanes; i++)
- INIT_DELAYED_WORK(&xgkr_inst->xgkr[i].xgkr_wk, xgkr_state_machine);
- break;
- }
-
- return 0;
-}
-
-static int fsl_backplane_aneg_done(struct phy_device *phydev)
-{
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
-
- if (!phydev->mdio.dev.of_node) {
- dev_err(&phydev->mdio.dev, "No associated device tree node\n");
- return -EINVAL;
- }
-
- xgkr_inst->aneg_done = true;
-
- return 1;
-}
-
-static int fsl_backplane_config_aneg(struct phy_device *phydev)
-{
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- int i;
-
- if (!phydev->mdio.dev.of_node) {
- dev_err(&phydev->mdio.dev, "No associated device tree node\n");
- return -EINVAL;
- }
-
- switch (phydev->speed)
- {
- case SPEED_1000:
- phydev->supported |= SUPPORTED_1000baseKX_Full;
- start_1gkx_an(phydev);
- break;
-
- case SPEED_10000:
- phydev->supported |= SUPPORTED_10000baseKR_Full;
- reset_lt(&xgkr_inst->xgkr[SINGLE_LANE]);
- start_xgkr_an(&xgkr_inst->xgkr[SINGLE_LANE]);
- /* start state machine*/
- start_xgkr_state_machine(&xgkr_inst->xgkr[SINGLE_LANE].xgkr_wk);
- break;
-
- case SPEED_40000:
- phydev->supported |= SUPPORTED_40000baseKR4_Full;
- for (i = 0; i < xgkr_inst->phy_lanes; i++) {
- reset_lt(&xgkr_inst->xgkr[i]);
- }
- //Start AN only for Master Lane
- start_xgkr_an(&xgkr_inst->xgkr[MASTER_LANE]);
- /* start state machine*/
- for (i = 0; i < xgkr_inst->phy_lanes; i++) {
- start_xgkr_state_machine(&xgkr_inst->xgkr[i].xgkr_wk);
- }
-
- break;
- }
-
- phydev->advertising = phydev->supported;
- phydev->duplex = 1;
-
- return 0;
-}
-
-static int fsl_backplane_suspend(struct phy_device *phydev)
-{
- int i;
-
- if (!phydev->mdio.dev.of_node) {
- dev_err(&phydev->mdio.dev, "No associated device tree node\n");
- return -EINVAL;
- }
-
- if (phydev->speed == SPEED_10000 || phydev->speed == SPEED_40000) {
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
-
- for (i = 0; i < xgkr_inst->phy_lanes; i++)
- cancel_delayed_work_sync(&xgkr_inst->xgkr[i].xgkr_wk);
- }
- return 0;
-}
-
-static int fsl_backplane_resume(struct phy_device *phydev)
-{
- struct xgkr_phy_data *xgkr_inst = phydev->priv;
- int i;
-
- if (!phydev->mdio.dev.of_node) {
- dev_err(&phydev->mdio.dev, "No associated device tree node\n");
- return -EINVAL;
- }
-
- if (phydev->speed == SPEED_10000 || phydev->speed == SPEED_40000) {
- for (i = 0; i < xgkr_inst->phy_lanes; i++) {
- init_xgkr(&xgkr_inst->xgkr[i], 1);
- start_xgkr_state_machine(&xgkr_inst->xgkr[i].xgkr_wk);
- }
- }
- return 0;
-}
-
-static int fsl_backplane_read_status(struct phy_device *phydev)
-{
- if (!phydev->mdio.dev.of_node) {
- dev_err(&phydev->mdio.dev, "No associated device tree node\n");
- return -EINVAL;
- }
-
- if (is_link_up(phydev))
- phydev->link = 1;
- else
- phydev->link = 0;
-
- return 0;
-}
-
-static int fsl_backplane_match_phy_device(struct phy_device *phydev)
-{
- struct device_node *phy_node, *lane_node;
- const char *st;
- int serdes_type, i, ret;
- const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
-
- if (!phydev->mdio.dev.of_node) {
- return 0;
- }
-
- // WORKAROUND:
- // Required for LX2 devices
- // where PHY ID cannot be verified in PCS
- // because PCS Device Identifier Upper and Lower registers are hidden
- // and always return 0 when they are read:
- // 2 02 Device_ID0 RO Bits 15:0 0
- // val = phy_read_mmd(phydev, MDIO_MMD_PCS, 0x2);
- // 3 03 Device_ID1 RO Bits 31:16 0
- // val = phy_read_mmd(phydev, MDIO_MMD_PCS, 0x3);
- //
- // To be removed: After the issue will be fixed on LX2 devices
-
- if (!phydev->is_c45)
- return 0;
-
- phy_node = phydev->mdio.dev.of_node;
-
- lane_node = of_parse_phandle(phy_node, "fsl,lane-handle", 0);
- if (!lane_node) {
- dev_err(&phydev->mdio.dev, "parse fsl,lane-handle failed\n");
- return 0;
- }
-
- ret = of_property_read_string(lane_node, "compatible", &st);
- if (ret < 0) {
- //assume SERDES-10G if compatible property is not specified
- serdes_type = SERDES_10G;
- }
- else if (!strcasecmp(st, "fsl,serdes-10g")) {
- serdes_type = SERDES_10G;
- } else if (!strcasecmp(st, "fsl,serdes-28g")) {
- serdes_type = SERDES_28G;
- } else {
- dev_err(&phydev->mdio.dev, "Unknown serdes-type\n");
- return 0;
- }
-
- if (serdes_type == SERDES_10G) {
- //On LS devices we must find the c45 device with correct PHY ID
- //Implementation similar with the one existent in phy_device: @function: phy_bus_match
- for (i = 1; i < num_ids; i++) {
- if (!(phydev->c45_ids.devices_in_package & (1 << i)))
- continue;
-
- if ((PCS_PHY_DEVICE_ID & PCS_PHY_DEVICE_ID_MASK) ==
- (phydev->c45_ids.device_ids[i] & PCS_PHY_DEVICE_ID_MASK))
- {
- return 1;
- }
- }
- return 0;
- }
-
- //On LX devices we cannot verify PHY ID
- //so we are happy only with preliminary verifications already made: mdio.dev.of_node and is_c45
- //because we already filtered other undesired devices: non clause 45
-
- return 1;
-}
-
-static struct phy_driver fsl_backplane_driver[] = {
- {
- .phy_id = PCS_PHY_DEVICE_ID,
- .name = "Freescale Backplane",
- .phy_id_mask = PCS_PHY_DEVICE_ID_MASK,
- .features = SUPPORTED_Backplane | SUPPORTED_Autoneg |
- SUPPORTED_MII,
- .probe = fsl_backplane_probe,
- .aneg_done = fsl_backplane_aneg_done,
- .config_aneg = fsl_backplane_config_aneg,
- .read_status = fsl_backplane_read_status,
- .suspend = fsl_backplane_suspend,
- .resume = fsl_backplane_resume,
- .match_phy_device = fsl_backplane_match_phy_device,
- },
-};
-
-module_phy_driver(fsl_backplane_driver);
-
-static struct mdio_device_id __maybe_unused freescale_tbl[] = {
- { PCS_PHY_DEVICE_ID, PCS_PHY_DEVICE_ID_MASK },
- { }
-};
-
-MODULE_DEVICE_TABLE(mdio, freescale_tbl);
-
-MODULE_DESCRIPTION("Freescale Backplane driver");
-MODULE_AUTHOR("Shaohui Xie <Shaohui.Xie@freescale.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/phy/fsl_backplane.h b/drivers/net/phy/fsl_backplane.h
deleted file mode 100644
index 8c50586f3959..000000000000
--- a/drivers/net/phy/fsl_backplane.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * DPAA backplane driver.
- * Author: Florinel Iordache <florinel.iordache@nxp.com>
- *
- * Copyright 2018 NXP
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef FSL_BACKPLANE_H
-#define FSL_BACKPLANE_H
-
-/* C(-1) */
-#define BIN_M1 0
-/* C(1) */
-#define BIN_LONG 1
-
-#define BIN_SNAPSHOT_NUM 5
-#define BIN_M1_THRESHOLD 3
-#define BIN_LONG_THRESHOLD 2
-
-struct serdes_access {
-
- int serdes_type;
- bool is_little_endian;
- u32 (*ioread32)(u32 *reg);
- void (*iowrite32)(u32 value, u32 *reg);
- u32 (*get_lane_memmap_size)(void);
- void (*tune_tecr)(void *reg, u32 ratio_preq, u32 ratio_pst1q, u32 adpt_eq, bool reset);
- void (*reset_lane)(void *reg);
- void (*lane_set_1gkx)(void *reg);
- int (*get_median_gaink2)(u32 *reg);
- bool (*is_bin_early)(int bin_sel, void *reg);
-};
-
-struct serdes_access* setup_serdes_access_10g(void);
-struct serdes_access* setup_serdes_access_28g(void);
-
-
-#endif //FSL_BACKPLANE_H
diff --git a/drivers/net/phy/fsl_backplane_serdes_10g.c b/drivers/net/phy/fsl_backplane_serdes_10g.c
deleted file mode 100644
index 2d19d881faf0..000000000000
--- a/drivers/net/phy/fsl_backplane_serdes_10g.c
+++ /dev/null
@@ -1,281 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * DPAA backplane driver for SerDes 10G.
- * Author: Florinel Iordache <florinel.iordache@nxp.com>
- *
- * Copyright 2018 NXP
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include "fsl_backplane.h"
-
-#define BIN_M1_SEL 6
-#define BIN_Long_SEL 7
-#define CDR_SEL_MASK 0x00070000
-
-#define PRE_COE_SHIFT 22
-#define POST_COE_SHIFT 16
-#define ZERO_COE_SHIFT 8
-
-#define TECR0_INIT 0x24200000
-
-#define GCR0_RESET_MASK 0x00600000
-
-#define GCR1_SNP_START_MASK 0x00000040
-#define GCR1_CTL_SNP_START_MASK 0x00002000
-
-#define RECR1_CTL_SNP_DONE_MASK 0x00000002
-#define RECR1_SNP_DONE_MASK 0x00000004
-#define TCSR1_SNP_DATA_MASK 0x0000ffc0
-#define TCSR1_SNP_DATA_SHIFT 6
-#define TCSR1_EQ_SNPBIN_SIGN_MASK 0x100
-
-#define RECR1_GAINK2_MASK 0x0f000000
-#define RECR1_GAINK2_SHIFT 24
-
-/* Required only for 1000BASE KX */
-#define GCR1_REIDL_TH_MASK 0x00700000
-#define GCR1_REIDL_EX_SEL_MASK 0x000c0000
-#define GCR1_REIDL_ET_MAS_MASK 0x00004000
-#define TECR0_AMP_RED_MASK 0x0000003f
-
-struct per_lane_ctrl_status {
- u32 gcr0; /* 0x.000 - General Control Register 0 */
- u32 gcr1; /* 0x.004 - General Control Register 1 */
- u32 gcr2; /* 0x.008 - General Control Register 2 */
- u32 resv1; /* 0x.00C - Reserved */
- u32 recr0; /* 0x.010 - Receive Equalization Control Register 0 */
- u32 recr1; /* 0x.014 - Receive Equalization Control Register 1 */
- u32 tecr0; /* 0x.018 - Transmit Equalization Control Register 0 */
- u32 resv2; /* 0x.01C - Reserved */
- u32 tlcr0; /* 0x.020 - TTL Control Register 0 */
- u32 tlcr1; /* 0x.024 - TTL Control Register 1 */
- u32 tlcr2; /* 0x.028 - TTL Control Register 2 */
- u32 tlcr3; /* 0x.02C - TTL Control Register 3 */
- u32 tcsr0; /* 0x.030 - Test Control/Status Register 0 */
- u32 tcsr1; /* 0x.034 - Test Control/Status Register 1 */
- u32 tcsr2; /* 0x.038 - Test Control/Status Register 2 */
- u32 tcsr3; /* 0x.03C - Test Control/Status Register 3 */
-};
-
-static struct serdes_access srds;
-
-static u32 get_lane_memmap_size(void)
-{
- return 0x40;
-}
-
-static void reset_lane(void *reg)
-{
- struct per_lane_ctrl_status *reg_base = reg;
-
- /* reset the lane */
- srds.iowrite32(srds.ioread32(&reg_base->gcr0) & ~GCR0_RESET_MASK,
- &reg_base->gcr0);
- udelay(1);
-
- /* unreset the lane */
- srds.iowrite32(srds.ioread32(&reg_base->gcr0) | GCR0_RESET_MASK,
- &reg_base->gcr0);
- udelay(1);
-}
-
-static void tune_tecr(void *reg, u32 ratio_preq, u32 ratio_pst1q, u32 adpt_eq, bool reset)
-{
- struct per_lane_ctrl_status *reg_base = reg;
- u32 val;
-
- val = TECR0_INIT |
- adpt_eq << ZERO_COE_SHIFT |
- ratio_preq << PRE_COE_SHIFT |
- ratio_pst1q << POST_COE_SHIFT;
-
- if (reset) {
- /* reset the lane */
- srds.iowrite32(srds.ioread32(&reg_base->gcr0) & ~GCR0_RESET_MASK,
- &reg_base->gcr0);
- udelay(1);
- }
-
- srds.iowrite32(val, &reg_base->tecr0);
- udelay(1);
-
- if (reset) {
- /* unreset the lane */
- srds.iowrite32(srds.ioread32(&reg_base->gcr0) | GCR0_RESET_MASK,
- &reg_base->gcr0);
- udelay(1);
- }
-}
-
-static void lane_set_1gkx(void *reg)
-{
- struct per_lane_ctrl_status *reg_base = reg;
- u32 val;
-
- /* reset the lane */
- srds.iowrite32(srds.ioread32(&reg_base->gcr0) & ~GCR0_RESET_MASK,
- &reg_base->gcr0);
- udelay(1);
-
- /* set gcr1 for 1GKX */
- val = srds.ioread32(&reg_base->gcr1);
- val &= ~(GCR1_REIDL_TH_MASK | GCR1_REIDL_EX_SEL_MASK |
- GCR1_REIDL_ET_MAS_MASK);
- srds.iowrite32(val, &reg_base->gcr1);
- udelay(1);
-
- /* set tecr0 for 1GKX */
- val = srds.ioread32(&reg_base->tecr0);
- val &= ~TECR0_AMP_RED_MASK;
- srds.iowrite32(val, &reg_base->tecr0);
- udelay(1);
-
- /* unreset the lane */
- srds.iowrite32(srds.ioread32(&reg_base->gcr0) | GCR0_RESET_MASK,
- &reg_base->gcr0);
- udelay(1);
-}
-
-static int get_median_gaink2(u32 *reg)
-{
- int gaink2_snap_shot[BIN_SNAPSHOT_NUM];
- u32 rx_eq_snp;
- struct per_lane_ctrl_status *reg_base;
- int timeout;
- int i, j, tmp, pos;
-
- reg_base = (struct per_lane_ctrl_status *)reg;
-
- for (i = 0; i < BIN_SNAPSHOT_NUM; i++) {
- /* wait RECR1_CTL_SNP_DONE_MASK has cleared */
- timeout = 100;
- while (srds.ioread32(&reg_base->recr1) &
- RECR1_CTL_SNP_DONE_MASK) {
- udelay(1);
- timeout--;
- if (timeout == 0)
- break;
- }
-
- /* start snap shot */
- srds.iowrite32((srds.ioread32(&reg_base->gcr1) |
- GCR1_CTL_SNP_START_MASK),
- &reg_base->gcr1);
-
- /* wait for SNP done */
- timeout = 100;
- while (!(srds.ioread32(&reg_base->recr1) &
- RECR1_CTL_SNP_DONE_MASK)) {
- udelay(1);
- timeout--;
- if (timeout == 0)
- break;
- }
-
- /* read and save the snap shot */
- rx_eq_snp = srds.ioread32(&reg_base->recr1);
- gaink2_snap_shot[i] = (rx_eq_snp & RECR1_GAINK2_MASK) >>
- RECR1_GAINK2_SHIFT;
-
- /* terminate the snap shot by setting GCR1[REQ_CTL_SNP] */
- srds.iowrite32((srds.ioread32(&reg_base->gcr1) &
- ~GCR1_CTL_SNP_START_MASK),
- &reg_base->gcr1);
- }
-
- /* get median of the 5 snap shot */
- for (i = 0; i < BIN_SNAPSHOT_NUM - 1; i++) {
- tmp = gaink2_snap_shot[i];
- pos = i;
- for (j = i + 1; j < BIN_SNAPSHOT_NUM; j++) {
- if (gaink2_snap_shot[j] < tmp) {
- tmp = gaink2_snap_shot[j];
- pos = j;
- }
- }
-
- gaink2_snap_shot[pos] = gaink2_snap_shot[i];
- gaink2_snap_shot[i] = tmp;
- }
-
- return gaink2_snap_shot[2];
-}
-
-static bool is_bin_early(int bin_sel, void *reg)
-{
- bool early = false;
- int bin_snap_shot[BIN_SNAPSHOT_NUM];
- int i, negative_count = 0;
- struct per_lane_ctrl_status *reg_base = reg;
- int timeout;
-
- for (i = 0; i < BIN_SNAPSHOT_NUM; i++) {
- /* wait RECR1_SNP_DONE_MASK has cleared */
- timeout = 100;
- while ((srds.ioread32(&reg_base->recr1) & RECR1_SNP_DONE_MASK)) {
- udelay(1);
- timeout--;
- if (timeout == 0)
- break;
- }
-
- /* set TCSR1[CDR_SEL] to BinM1/BinLong */
- if (bin_sel == BIN_M1) {
- srds.iowrite32((srds.ioread32(&reg_base->tcsr1) &
- ~CDR_SEL_MASK) | BIN_M1_SEL,
- &reg_base->tcsr1);
- } else {
- srds.iowrite32((srds.ioread32(&reg_base->tcsr1) &
- ~CDR_SEL_MASK) | BIN_Long_SEL,
- &reg_base->tcsr1);
- }
-
- /* start snap shot */
- srds.iowrite32(srds.ioread32(&reg_base->gcr1) | GCR1_SNP_START_MASK,
- &reg_base->gcr1);
-
- /* wait for SNP done */
- timeout = 100;
- while (!(srds.ioread32(&reg_base->recr1) & RECR1_SNP_DONE_MASK)) {
- udelay(1);
- timeout--;
- if (timeout == 0)
- break;
- }
-
- /* read and save the snap shot */
- bin_snap_shot[i] = (srds.ioread32(&reg_base->tcsr1) &
- TCSR1_SNP_DATA_MASK) >> TCSR1_SNP_DATA_SHIFT;
- if (bin_snap_shot[i] & TCSR1_EQ_SNPBIN_SIGN_MASK)
- negative_count++;
-
- /* terminate the snap shot by setting GCR1[REQ_CTL_SNP] */
- srds.iowrite32(srds.ioread32(&reg_base->gcr1) & ~GCR1_SNP_START_MASK,
- &reg_base->gcr1);
- }
-
- if (((bin_sel == BIN_M1) && (negative_count > BIN_M1_THRESHOLD)) ||
- ((bin_sel == BIN_LONG && (negative_count > BIN_LONG_THRESHOLD)))) {
- early = true;
- }
-
- return early;
-}
-
-struct serdes_access* setup_serdes_access_10g(void)
-{
- srds.get_lane_memmap_size = get_lane_memmap_size;
- srds.tune_tecr = tune_tecr;
- srds.reset_lane = reset_lane;
- srds.lane_set_1gkx = lane_set_1gkx;
- srds.get_median_gaink2 = get_median_gaink2;
- srds.is_bin_early = is_bin_early;
-
- return &srds;
-}
-
diff --git a/drivers/net/phy/fsl_backplane_serdes_28g.c b/drivers/net/phy/fsl_backplane_serdes_28g.c
deleted file mode 100644
index 4e188ad92224..000000000000
--- a/drivers/net/phy/fsl_backplane_serdes_28g.c
+++ /dev/null
@@ -1,336 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * DPAA backplane driver for SerDes 28G.
- * Author: Florinel Iordache <florinel.iordache@nxp.com>
- *
- * Copyright 2018 NXP
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-
-#include "fsl_backplane.h"
-
-#define BIN_M1_SEL 0x0000c000
-#define BIN_Long_SEL 0x0000d000
-#define CDR_SEL_MASK 0x0000f000
-
-#define PRE_COE_SHIFT 16
-#define POST_COE_SHIFT 8
-#define ZERO_COE_SHIFT 24
-
-#define TECR0_INIT 0x20808000
-
-#define RESET_REQ_MASK 0x80000000
-
-#define RECR3_SNP_START_MASK 0x80000000
-#define RECR3_SNP_DONE_MASK 0x40000000
-
-#define RECR4_SNP_DATA_MASK 0x000003ff
-#define RECR4_SNP_DATA_SHIFT 0
-#define RECR4_EQ_SNPBIN_SIGN_MASK 0x200
-
-#define RECR3_GAINK2_MASK 0x1f000000
-#define RECR3_GAINK2_SHIFT 24
-
-/* Required only for 1000BASE KX */
-#define GCR1_REIDL_TH_MASK 0x00700000
-#define GCR1_REIDL_EX_SEL_MASK 0x000c0000
-#define GCR1_REIDL_ET_MAS_MASK 0x04000000
-#define TECR0_AMP_RED_MASK 0x0000003f
-
-struct per_lane_ctrl_status {
- u32 gcr0; /* 0x.000 - General Control Register 0 */
- u32 resv1; /* 0x.004 - Reserved */
- u32 resv2; /* 0x.008 - Reserved */
- u32 resv3; /* 0x.00C - Reserved */
- u32 resv4; /* 0x.010 - Reserved */
- u32 resv5; /* 0x.014 - Reserved */
- u32 resv6; /* 0x.018 - Reserved */
- u32 resv7; /* 0x.01C - Reserved */
- u32 trstctl; /* 0x.020 - TX Reset Control Register */
- u32 tgcr0; /* 0x.024 - TX General Control Register 0 */
- u32 tgcr1; /* 0x.028 - TX General Control Register 1 */
- u32 tgcr2; /* 0x.02C - TX General Control Register 2 */
- u32 tecr0; /* 0x.030 - Transmit Equalization Control Register 0 */
- u32 tecr1; /* 0x.034 - Transmit Equalization Control Register 1 */
- u32 resv8; /* 0x.038 - Reserved */
- u32 resv9; /* 0x.03C - Reserved */
- u32 rrstctl; /* 0x.040 - RX Reset Control Register */
- u32 rgcr0; /* 0x.044 - RX General Control Register 0 */
- u32 rxgcr1; /* 0x.048 - RX General Control Register 1 */
- u32 resv10; /* 0x.04C - Reserved */
- u32 recr0; /* 0x.050 - RX Equalization Register 0 */
- u32 recr1; /* 0x.054 - RX Equalization Register 1 */
- u32 recr2; /* 0x.058 - RX Equalization Register 2 */
- u32 recr3; /* 0x.05C - RX Equalization Register 3 */
- u32 recr4; /* 0x.060 - RX Equalization Register 4 */
- u32 resv11; /* 0x.064 - Reserved */
- u32 rccr0; /* 0x.068 - RX Calibration Register 0 */
- u32 rccr1; /* 0x.06C - RX Calibration Register 1 */
- u32 rcpcr0; /* 0x.070 - RX Clock Path Register 0 */
- u32 rsccr0; /* 0x.074 - RX Sampler Calibration Control Register 0 */
- u32 rsccr1; /* 0x.078 - RX Sampler Calibration Control Register 1 */
- u32 resv12; /* 0x.07C - Reserved */
- u32 ttlcr0; /* 0x.080 - Transition Tracking Loop Register 0 */
- u32 ttlcr1; /* 0x.084 - Transition Tracking Loop Register 1 */
- u32 ttlcr2; /* 0x.088 - Transition Tracking Loop Register 2 */
- u32 ttlcr3; /* 0x.08C - Transition Tracking Loop Register 3 */
- u32 resv13; /* 0x.090 - Reserved */
- u32 resv14; /* 0x.094 - Reserved */
- u32 resv15; /* 0x.098 - Reserved */
- u32 resv16; /* 0x.09C - Reserved */
- u32 tcsr0; /* 0x.0A0 - Test Control/Status Register 0 */
- u32 tcsr1; /* 0x.0A4 - Test Control/Status Register 1 */
- u32 tcsr2; /* 0x.0A8 - Test Control/Status Register 2 */
- u32 tcsr3; /* 0x.0AC - Test Control/Status Register 3 */
- u32 tcsr4; /* 0x.0B0 - Test Control/Status Register 4 */
- u32 resv17; /* 0x.0B4 - Reserved */
- u32 resv18; /* 0x.0B8 - Reserved */
- u32 resv19; /* 0x.0BC - Reserved */
- u32 rxcb0; /* 0x.0C0 - RX Control Block Register 0 */
- u32 rxcb1; /* 0x.0C4 - RX Control Block Register 1 */
- u32 resv20; /* 0x.0C8 - Reserved */
- u32 resv21; /* 0x.0CC - Reserved */
- u32 rxss0; /* 0x.0D0 - RX Speed Switch Register 0 */
- u32 rxss1; /* 0x.0D4 - RX Speed Switch Register 1 */
- u32 rxss2; /* 0x.0D8 - RX Speed Switch Register 2 */
- u32 resv22; /* 0x.0DC - Reserved */
- u32 txcb0; /* 0x.0E0 - TX Control Block Register 0 */
- u32 txcb1; /* 0x.0E4 - TX Control Block Register 1 */
- u32 resv23; /* 0x.0E8 - Reserved */
- u32 resv24; /* 0x.0EC - Reserved */
- u32 txss0; /* 0x.0F0 - TX Speed Switch Register 0 */
- u32 txss1; /* 0x.0F4 - TX Speed Switch Register 1 */
- u32 txss2; /* 0x.0F8 - TX Speed Switch Register 2 */
- u32 resv25; /* 0x.0FC - Reserved */
-};
-
-static struct serdes_access srds;
-
-static u32 get_lane_memmap_size(void)
-{
- return 0x100;
-}
-
-static void reset_lane(void *reg)
-{
- struct per_lane_ctrl_status *reg_base = reg;
- u32 val;
- unsigned long timeout;
-
- /* reset Tx lane: send reset request */
- srds.iowrite32(srds.ioread32(&reg_base->trstctl) | RESET_REQ_MASK,
- &reg_base->trstctl);
- udelay(1);
- timeout = 10;
- while (timeout--) {
- val = srds.ioread32(&reg_base->trstctl);
- if (!(val & RESET_REQ_MASK))
- break;
- usleep_range(5, 20);
- }
-
- /* reset Rx lane: send reset request */
- srds.iowrite32(srds.ioread32(&reg_base->rrstctl) | RESET_REQ_MASK,
- &reg_base->rrstctl);
- udelay(1);
- timeout = 10;
- while (timeout--) {
- val = srds.ioread32(&reg_base->rrstctl);
- if (!(val & RESET_REQ_MASK))
- break;
- usleep_range(5, 20);
- }
-
- /* wait for a while after reset */
- timeout = jiffies + 10;
- while (time_before(jiffies, timeout)) {
- schedule();
- usleep_range(5, 20);
- }
-}
-
-static void tune_tecr(void *reg, u32 ratio_preq, u32 ratio_pst1q, u32 adpt_eq, bool reset)
-{
- struct per_lane_ctrl_status *reg_base = reg;
- u32 val;
-
- if (reset) {
- /* reset lanes */
- reset_lane(reg);
- }
-
- val = TECR0_INIT |
- ratio_preq << PRE_COE_SHIFT |
- ratio_pst1q << POST_COE_SHIFT;
- srds.iowrite32(val, &reg_base->tecr0);
-
- val = adpt_eq << ZERO_COE_SHIFT;
- srds.iowrite32(val, &reg_base->tecr1);
-
- udelay(1);
-}
-
-static void lane_set_1gkx(void *reg)
-{
- struct per_lane_ctrl_status *reg_base = reg;
- u32 val;
-
- /* reset lanes */
- reset_lane(reg);
-
- /* set gcr1 for 1GKX */
- val = srds.ioread32(&reg_base->rxgcr1);
- val &= ~(GCR1_REIDL_TH_MASK | GCR1_REIDL_EX_SEL_MASK |
- GCR1_REIDL_ET_MAS_MASK);
- srds.iowrite32(val, &reg_base->rxgcr1);
- udelay(1);
-
- /* set tecr0 for 1GKX */
- val = srds.ioread32(&reg_base->tecr0);
- val &= ~TECR0_AMP_RED_MASK;
- srds.iowrite32(val, &reg_base->tecr0);
- udelay(1);
-}
-
-static int get_median_gaink2(u32 *reg)
-{
- int gaink2_snap_shot[BIN_SNAPSHOT_NUM];
- u32 rx_eq_snp;
- struct per_lane_ctrl_status *reg_base;
- int timeout;
- int i, j, tmp, pos;
-
- reg_base = (struct per_lane_ctrl_status *)reg;
-
- for (i = 0; i < BIN_SNAPSHOT_NUM; i++) {
- /* wait RECR3_SNP_DONE_MASK has cleared */
- timeout = 100;
- while (srds.ioread32(&reg_base->recr3) &
- RECR3_SNP_DONE_MASK) {
- udelay(1);
- timeout--;
- if (timeout == 0)
- break;
- }
-
- /* start snap shot */
- srds.iowrite32((srds.ioread32(&reg_base->recr3) |
- RECR3_SNP_START_MASK),
- &reg_base->recr3);
-
- /* wait for SNP done */
- timeout = 100;
- while (!(srds.ioread32(&reg_base->recr3) &
- RECR3_SNP_DONE_MASK)) {
- udelay(1);
- timeout--;
- if (timeout == 0)
- break;
- }
-
- /* read and save the snap shot */
- rx_eq_snp = srds.ioread32(&reg_base->recr3);
- gaink2_snap_shot[i] = (rx_eq_snp & RECR3_GAINK2_MASK) >>
- RECR3_GAINK2_SHIFT;
-
- /* terminate the snap shot by setting GCR1[REQ_CTL_SNP] */
- srds.iowrite32((srds.ioread32(&reg_base->recr3) &
- ~RECR3_SNP_START_MASK),
- &reg_base->recr3);
- }
-
- /* get median of the 5 snap shot */
- for (i = 0; i < BIN_SNAPSHOT_NUM - 1; i++) {
- tmp = gaink2_snap_shot[i];
- pos = i;
- for (j = i + 1; j < BIN_SNAPSHOT_NUM; j++) {
- if (gaink2_snap_shot[j] < tmp) {
- tmp = gaink2_snap_shot[j];
- pos = j;
- }
- }
-
- gaink2_snap_shot[pos] = gaink2_snap_shot[i];
- gaink2_snap_shot[i] = tmp;
- }
-
- return gaink2_snap_shot[2];
-}
-
-static bool is_bin_early(int bin_sel, void *reg)
-{
- bool early = false;
- int bin_snap_shot[BIN_SNAPSHOT_NUM];
- int i, negative_count = 0;
- struct per_lane_ctrl_status *reg_base = reg;
- int timeout;
-
- for (i = 0; i < BIN_SNAPSHOT_NUM; i++) {
- /* wait RECR3_SNP_DONE_MASK has cleared */
- timeout = 100;
- while ((srds.ioread32(&reg_base->recr3) & RECR3_SNP_DONE_MASK)) {
- udelay(1);
- timeout--;
- if (timeout == 0)
- break;
- }
-
- /* set TCSR1[CDR_SEL] to BinM1/BinLong */
- if (bin_sel == BIN_M1) {
- srds.iowrite32((srds.ioread32(&reg_base->recr4) &
- ~CDR_SEL_MASK) | BIN_M1_SEL,
- &reg_base->recr4);
- } else {
- srds.iowrite32((srds.ioread32(&reg_base->recr4) &
- ~CDR_SEL_MASK) | BIN_Long_SEL,
- &reg_base->recr4);
- }
-
- /* start snap shot */
- srds.iowrite32(srds.ioread32(&reg_base->recr3) | RECR3_SNP_START_MASK,
- &reg_base->recr3);
-
- /* wait for SNP done */
- timeout = 100;
- while (!(srds.ioread32(&reg_base->recr3) & RECR3_SNP_DONE_MASK)) {
- udelay(1);
- timeout--;
- if (timeout == 0)
- break;
- }
-
- /* read and save the snap shot */
- bin_snap_shot[i] = (srds.ioread32(&reg_base->recr4) &
- RECR4_SNP_DATA_MASK) >> RECR4_SNP_DATA_SHIFT;
- if (bin_snap_shot[i] & RECR4_EQ_SNPBIN_SIGN_MASK)
- negative_count++;
-
- /* terminate the snap shot by setting GCR1[REQ_CTL_SNP] */
- srds.iowrite32(srds.ioread32(&reg_base->recr3) & ~RECR3_SNP_START_MASK,
- &reg_base->recr3);
- }
-
- if (((bin_sel == BIN_M1) && (negative_count > BIN_M1_THRESHOLD)) ||
- ((bin_sel == BIN_LONG && (negative_count > BIN_LONG_THRESHOLD)))) {
- early = true;
- }
-
- return early;
-}
-
-struct serdes_access* setup_serdes_access_28g(void)
-{
- srds.get_lane_memmap_size = get_lane_memmap_size;
- srds.tune_tecr = tune_tecr;
- srds.reset_lane = reset_lane;
- srds.lane_set_1gkx = lane_set_1gkx;
- srds.get_median_gaink2 = get_median_gaink2;
- srds.is_bin_early = is_bin_early;
-
- return &srds;
-}