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

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
...@@ -852,14 +852,9 @@ ...@@ -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 { \ ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment