Skip to content

Commit

Permalink
amd-xgbe: Prepare for a new PCS register access method
Browse files Browse the repository at this point in the history
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: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Lendacky, Thomas authored and David S. Miller committed Nov 4, 2016
1 parent 1bf40ad commit b03a4a6
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 19 deletions.
21 changes: 11 additions & 10 deletions drivers/net/ethernet/amd/xgbe/xgbe-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
*/
Expand Down
107 changes: 98 additions & 9 deletions drivers/net/ethernet/amd/xgbe/xgbe-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,8 +1026,71 @@ 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,
int mmd_reg)
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;
unsigned int mmd_address;
Expand All @@ -1048,15 +1111,15 @@ 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,
int mmd_reg, int mmd_data)
static void xgbe_write_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
int mmd_reg, int mmd_data)
{
unsigned int mmd_address;
unsigned long flags;
Expand All @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/amd/xgbe/xgbe-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/amd/xgbe/xgbe.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit b03a4a6

Please sign in to comment.