Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b03a4a6f authored by Lendacky, Thomas's avatar Lendacky, Thomas Committed by David S. Miller
Browse files

amd-xgbe: Prepare for a new PCS register access method



Prepare the code to be able to support accessing of the PCS registers
in a new way, while maintaining the current access method. Provide a
version specific field that indicates the method to use.

Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1bf40ada
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -852,14 +852,9 @@
#define MTL_TSA_SP			0x00
#define MTL_TSA_ETS			0x02

/* PCS MMD select register offset
 *  The MMD select register is used for accessing PCS registers
 *  when the underlying APB3 interface is using indirect addressing.
 *  Indirect addressing requires accessing registers in two phases,
 *  an address phase and a data phase.  The address phases requires
 *  writing an address selection value to the MMD select regiesters.
 */
#define PCS_MMD_SELECT			0xff
/* PCS register offsets */
#define PCS_V1_WINDOW_SELECT		0x03fc
#define PCS_V2_WINDOW_SELECT		0x9064

/* SerDes integration register offsets */
#define SIR0_KR_RT_1			0x002c
@@ -1241,12 +1236,18 @@ do { \
/* Macros for building, reading or writing register values or bits
 * within the register values of XPCS registers.
 */
#define XPCS_IOWRITE(_pdata, _off, _val)				\
#define XPCS32_IOWRITE(_pdata, _off, _val)				\
	iowrite32(_val, (_pdata)->xpcs_regs + (_off))

#define XPCS_IOREAD(_pdata, _off)					\
#define XPCS32_IOREAD(_pdata, _off)					\
	ioread32((_pdata)->xpcs_regs + (_off))

#define XPCS16_IOWRITE(_pdata, _off, _val)				\
	iowrite16(_val, (_pdata)->xpcs_regs + (_off))

#define XPCS16_IOREAD(_pdata, _off)					\
	ioread16((_pdata)->xpcs_regs + (_off))

/* Macros for building, reading or writing register values or bits
 * within the register values of SerDes integration registers.
 */
+98 −9
Original line number Diff line number Diff line
@@ -1026,7 +1026,70 @@ static int xgbe_config_rx_mode(struct xgbe_prv_data *pdata)
	return 0;
}

static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
static int xgbe_read_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
				 int mmd_reg)
{
	unsigned long flags;
	unsigned int mmd_address, index, offset;
	int mmd_data;

	if (mmd_reg & MII_ADDR_C45)
		mmd_address = mmd_reg & ~MII_ADDR_C45;
	else
		mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);

	/* The PCS registers are accessed using mmio. The underlying
	 * management interface uses indirect addressing to access the MMD
	 * register sets. This requires accessing of the PCS register in two
	 * phases, an address phase and a data phase.
	 *
	 * The mmio interface is based on 16-bit offsets and values. All
	 * register offsets must therefore be adjusted by left shifting the
	 * offset 1 bit and reading 16 bits of data.
	 */
	mmd_address <<= 1;
	index = mmd_address & ~pdata->xpcs_window_mask;
	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);

	spin_lock_irqsave(&pdata->xpcs_lock, flags);
	XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index);
	mmd_data = XPCS16_IOREAD(pdata, offset);
	spin_unlock_irqrestore(&pdata->xpcs_lock, flags);

	return mmd_data;
}

static void xgbe_write_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
				   int mmd_reg, int mmd_data)
{
	unsigned long flags;
	unsigned int mmd_address, index, offset;

	if (mmd_reg & MII_ADDR_C45)
		mmd_address = mmd_reg & ~MII_ADDR_C45;
	else
		mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);

	/* The PCS registers are accessed using mmio. The underlying
	 * management interface uses indirect addressing to access the MMD
	 * register sets. This requires accessing of the PCS register in two
	 * phases, an address phase and a data phase.
	 *
	 * The mmio interface is based on 16-bit offsets and values. All
	 * register offsets must therefore be adjusted by left shifting the
	 * offset 1 bit and writing 16 bits of data.
	 */
	mmd_address <<= 1;
	index = mmd_address & ~pdata->xpcs_window_mask;
	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);

	spin_lock_irqsave(&pdata->xpcs_lock, flags);
	XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index);
	XPCS16_IOWRITE(pdata, offset, mmd_data);
	spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
}

static int xgbe_read_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
				 int mmd_reg)
{
	unsigned long flags;
@@ -1048,14 +1111,14 @@ static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
	 * offset 2 bits and reading 32 bits of data.
	 */
	spin_lock_irqsave(&pdata->xpcs_lock, flags);
	XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
	mmd_data = XPCS_IOREAD(pdata, (mmd_address & 0xff) << 2);
	XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8);
	mmd_data = XPCS32_IOREAD(pdata, (mmd_address & 0xff) << 2);
	spin_unlock_irqrestore(&pdata->xpcs_lock, flags);

	return mmd_data;
}

static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
static void xgbe_write_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
				   int mmd_reg, int mmd_data)
{
	unsigned int mmd_address;
@@ -1073,14 +1136,40 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
	 *
	 * The mmio interface is based on 32-bit offsets and values. All
	 * register offsets must therefore be adjusted by left shifting the
	 * offset 2 bits and reading 32 bits of data.
	 * offset 2 bits and writing 32 bits of data.
	 */
	spin_lock_irqsave(&pdata->xpcs_lock, flags);
	XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
	XPCS_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
	XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8);
	XPCS32_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
	spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
}

static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
			      int mmd_reg)
{
	switch (pdata->vdata->xpcs_access) {
	case XGBE_XPCS_ACCESS_V1:
		return xgbe_read_mmd_regs_v1(pdata, prtad, mmd_reg);

	case XGBE_XPCS_ACCESS_V2:
	default:
		return xgbe_read_mmd_regs_v2(pdata, prtad, mmd_reg);
	}
}

static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
				int mmd_reg, int mmd_data)
{
	switch (pdata->vdata->xpcs_access) {
	case XGBE_XPCS_ACCESS_V1:
		return xgbe_write_mmd_regs_v1(pdata, prtad, mmd_reg, mmd_data);

	case XGBE_XPCS_ACCESS_V2:
	default:
		return xgbe_write_mmd_regs_v2(pdata, prtad, mmd_reg, mmd_data);
	}
}

static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc)
{
	return !XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN);
+1 −0
Original line number Diff line number Diff line
@@ -785,6 +785,7 @@ static int xgbe_resume(struct device *dev)

static const struct xgbe_version_data xgbe_v1 = {
	.init_function_ptrs_phy_impl	= xgbe_init_function_ptrs_phy_v1,
	.xpcs_access			= XGBE_XPCS_ACCESS_V1,
};

#ifdef CONFIG_ACPI
+9 −0
Original line number Diff line number Diff line
@@ -471,6 +471,11 @@ enum xgbe_speed {
	XGBE_SPEEDS,
};

enum xgbe_xpcs_access {
	XGBE_XPCS_ACCESS_V1 = 0,
	XGBE_XPCS_ACCESS_V2,
};

enum xgbe_an_mode {
	XGBE_AN_MODE_CL73 = 0,
	XGBE_AN_MODE_CL37,
@@ -798,6 +803,7 @@ struct xgbe_hw_features {

struct xgbe_version_data {
	void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *);
	enum xgbe_xpcs_access xpcs_access;
};

struct xgbe_prv_data {
@@ -826,6 +832,9 @@ struct xgbe_prv_data {

	/* XPCS indirect addressing lock */
	spinlock_t xpcs_lock;
	unsigned int xpcs_window;
	unsigned int xpcs_window_size;
	unsigned int xpcs_window_mask;

	/* RSS addressing mutex */
	struct mutex rss_mutex;