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: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1bf40ada62
commit
b03a4a6fb3
|
@ -852,14 +852,9 @@
|
||||||
#define MTL_TSA_SP 0x00
|
#define MTL_TSA_SP 0x00
|
||||||
#define MTL_TSA_ETS 0x02
|
#define MTL_TSA_ETS 0x02
|
||||||
|
|
||||||
/* PCS MMD select register offset
|
/* PCS register offsets */
|
||||||
* The MMD select register is used for accessing PCS registers
|
#define PCS_V1_WINDOW_SELECT 0x03fc
|
||||||
* when the underlying APB3 interface is using indirect addressing.
|
#define PCS_V2_WINDOW_SELECT 0x9064
|
||||||
* 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
|
|
||||||
|
|
||||||
/* SerDes integration register offsets */
|
/* SerDes integration register offsets */
|
||||||
#define SIR0_KR_RT_1 0x002c
|
#define SIR0_KR_RT_1 0x002c
|
||||||
|
@ -1241,12 +1236,18 @@ do { \
|
||||||
/* Macros for building, reading or writing register values or bits
|
/* Macros for building, reading or writing register values or bits
|
||||||
* within the register values of XPCS registers.
|
* 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))
|
iowrite32(_val, (_pdata)->xpcs_regs + (_off))
|
||||||
|
|
||||||
#define XPCS_IOREAD(_pdata, _off) \
|
#define XPCS32_IOREAD(_pdata, _off) \
|
||||||
ioread32((_pdata)->xpcs_regs + (_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
|
/* Macros for building, reading or writing register values or bits
|
||||||
* within the register values of SerDes integration registers.
|
* within the register values of SerDes integration registers.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1026,8 +1026,71 @@ static int xgbe_config_rx_mode(struct xgbe_prv_data *pdata)
|
||||||
return 0;
|
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)
|
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 long flags;
|
||||||
unsigned int mmd_address;
|
unsigned int mmd_address;
|
||||||
|
@ -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.
|
* offset 2 bits and reading 32 bits of data.
|
||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&pdata->xpcs_lock, flags);
|
spin_lock_irqsave(&pdata->xpcs_lock, flags);
|
||||||
XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
|
XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8);
|
||||||
mmd_data = XPCS_IOREAD(pdata, (mmd_address & 0xff) << 2);
|
mmd_data = XPCS32_IOREAD(pdata, (mmd_address & 0xff) << 2);
|
||||||
spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
|
spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
|
||||||
|
|
||||||
return mmd_data;
|
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)
|
int mmd_reg, int mmd_data)
|
||||||
{
|
{
|
||||||
unsigned int mmd_address;
|
unsigned int mmd_address;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -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
|
* The mmio interface is based on 32-bit offsets and values. All
|
||||||
* register offsets must therefore be adjusted by left shifting the
|
* 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);
|
spin_lock_irqsave(&pdata->xpcs_lock, flags);
|
||||||
XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
|
XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8);
|
||||||
XPCS_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
|
XPCS32_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
|
||||||
spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
|
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)
|
static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc)
|
||||||
{
|
{
|
||||||
return !XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN);
|
return !XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN);
|
||||||
|
|
|
@ -785,6 +785,7 @@ static int xgbe_resume(struct device *dev)
|
||||||
|
|
||||||
static const struct xgbe_version_data xgbe_v1 = {
|
static const struct xgbe_version_data xgbe_v1 = {
|
||||||
.init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1,
|
.init_function_ptrs_phy_impl = xgbe_init_function_ptrs_phy_v1,
|
||||||
|
.xpcs_access = XGBE_XPCS_ACCESS_V1,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
|
|
|
@ -471,6 +471,11 @@ enum xgbe_speed {
|
||||||
XGBE_SPEEDS,
|
XGBE_SPEEDS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum xgbe_xpcs_access {
|
||||||
|
XGBE_XPCS_ACCESS_V1 = 0,
|
||||||
|
XGBE_XPCS_ACCESS_V2,
|
||||||
|
};
|
||||||
|
|
||||||
enum xgbe_an_mode {
|
enum xgbe_an_mode {
|
||||||
XGBE_AN_MODE_CL73 = 0,
|
XGBE_AN_MODE_CL73 = 0,
|
||||||
XGBE_AN_MODE_CL37,
|
XGBE_AN_MODE_CL37,
|
||||||
|
@ -798,6 +803,7 @@ struct xgbe_hw_features {
|
||||||
|
|
||||||
struct xgbe_version_data {
|
struct xgbe_version_data {
|
||||||
void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *);
|
void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *);
|
||||||
|
enum xgbe_xpcs_access xpcs_access;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xgbe_prv_data {
|
struct xgbe_prv_data {
|
||||||
|
@ -826,6 +832,9 @@ struct xgbe_prv_data {
|
||||||
|
|
||||||
/* XPCS indirect addressing lock */
|
/* XPCS indirect addressing lock */
|
||||||
spinlock_t xpcs_lock;
|
spinlock_t xpcs_lock;
|
||||||
|
unsigned int xpcs_window;
|
||||||
|
unsigned int xpcs_window_size;
|
||||||
|
unsigned int xpcs_window_mask;
|
||||||
|
|
||||||
/* RSS addressing mutex */
|
/* RSS addressing mutex */
|
||||||
struct mutex rss_mutex;
|
struct mutex rss_mutex;
|
||||||
|
|
Loading…
Reference in New Issue