realtek: RTL839x: reorganize mdio functions and SerDes register layout
The RTL839x mdio functions are scattered around the code. Relocate
them to the bus (still inside the ethernet driver).
Additionally provide a consistent SerDes register access through the
mdio bus. Until now when a SerDes directly drives a SFP module there
is no clear rule of how to handle its register set that consists of
two parts:
- c22 phy registers 0-15 live in the fiber page (2) of the SerDes
- other SerDes specific registers exist in pages before and after
The mdio bus and other SerDes functions are a wild mix of directly
looking into page 2 or just using self defined methods to access
data.
Adapt the bus to the new consistent phy interface that mixes the
SerDes register set like classic Realtek phys do it.
- Use register 31 as page select (already in the bus)
- Always keep the common registers 0-15 in place and read fiber page
- Map the SerDes internal registers into the upper vendor specific
registers 16-23 according to the page select register (31).
That gives a register mapping as follows:
+-----------------------+-----------------------+---------------+-------------+
| reg 0x00-0x0f | reg 0x10-0x17 | reg 0x18-0x1e | reg 0x1f |
+-----------------------+-----------------------+---------------+-------------+
| SerDes fiber page (3) | real SerDes registers | zero | SerDes page |
| registers 0 - 15 | in packages of 8 | | select reg |
+-----------------------+-----------------------+---------------+-------------+
Example to make it as clear as possible.
SerDes registers on a RTL839x show
Page / Reg | 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B ...
-------------+----------------------------------------------------------------
0 - SDS | 0C03 0F00 7060 7106 074D 0EBF 0F0F 0359 5248 0000 0F80 0000 ...
1 - SDS_EXT | 0000 0000 85FA 8C6D 5CCC 0000 20D8 0003 79AA 8C64 00C3 1482 ...
2 - FIB | 1140 6189 001C CA40 01A0 0000 0000 0004 0000 0000 0000 0000 ...
3 - FIB_EXT | 1140 6109 001C CA40 01A0 0000 0000 0004 0000 0000 0000 0000 ...
This translates to this phy layout
| SerDes fiber registers normal SerDes registers zero p.sel
Page / Reg | 0x00 0x01 0x02 0x03 ... 0x10 0x11 0x12 0x13 ... 0x18 ... 0x1f
-------------+---------------------------------------------------------------
0 | 1140 6189 001C CA40 ... 0C03 0F00 7060 7106 ... 0000 ... 0000
1 | 1140 6189 001C CA40 ... 5248 0000 0F80 0000 ... 0000 ... 0001
...
4 | 1140 6189 001C CA40 ... 0000 0000 85FA 8C6D ... 0000 ... 0004
...
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/19634
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
committed by
Robert Marko
parent
7d570a489b
commit
afa4662ed0
@@ -644,166 +644,6 @@ int rtl8390_sds_power(int mac, int val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl839x_smi_wait_op(int timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val;
|
||||
|
||||
ret = readx_poll_timeout(sw_r32, RTL839X_PHYREG_ACCESS_CTRL,
|
||||
val, !(val & 0x1), 20, timeout);
|
||||
if (ret)
|
||||
pr_err("%s: timeout\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
|
||||
{
|
||||
u32 v;
|
||||
int err = 0;
|
||||
|
||||
if (port > 63 || page > 8191 || reg > 31)
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* Take bug on RTL839x Rev <= C into account */
|
||||
if (port >= RTL839X_CPU_PORT)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&smi_lock);
|
||||
|
||||
sw_w32_mask(0xffff0000, port << 16, RTL839X_PHYREG_DATA_CTRL);
|
||||
v = reg << 5 | page << 10 | ((page == 0x1fff) ? 0x1f : 0) << 23;
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
sw_w32(0x1ff, RTL839X_PHYREG_CTRL);
|
||||
|
||||
v |= 1;
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
err = rtl839x_smi_wait_op(100000);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
*val = sw_r32(RTL839X_PHYREG_DATA_CTRL) & 0xffff;
|
||||
|
||||
errout:
|
||||
mutex_unlock(&smi_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val)
|
||||
{
|
||||
u32 v;
|
||||
int err = 0;
|
||||
|
||||
val &= 0xffff;
|
||||
if (port > 63 || page > 8191 || reg > 31)
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* Take bug on RTL839x Rev <= C into account */
|
||||
if (port >= RTL839X_CPU_PORT)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&smi_lock);
|
||||
|
||||
/* Set PHY to access */
|
||||
rtl839x_set_port_reg_le(BIT_ULL(port), RTL839X_PHYREG_PORT_CTRL);
|
||||
|
||||
sw_w32_mask(0xffff0000, val << 16, RTL839X_PHYREG_DATA_CTRL);
|
||||
|
||||
v = reg << 5 | page << 10 | ((page == 0x1fff) ? 0x1f : 0) << 23;
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
sw_w32(0x1ff, RTL839X_PHYREG_CTRL);
|
||||
|
||||
v |= BIT(3) | 1; /* Write operation and execute */
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
err = rtl839x_smi_wait_op(100000);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
if (sw_r32(RTL839X_PHYREG_ACCESS_CTRL) & 0x2)
|
||||
err = -EIO;
|
||||
|
||||
errout:
|
||||
mutex_unlock(&smi_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Read an mmd register of the PHY */
|
||||
int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
|
||||
{
|
||||
int err = 0;
|
||||
u32 v;
|
||||
|
||||
/* Take bug on RTL839x Rev <= C into account */
|
||||
if (port >= RTL839X_CPU_PORT)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&smi_lock);
|
||||
|
||||
/* Set PHY to access */
|
||||
sw_w32_mask(0xffff << 16, port << 16, RTL839X_PHYREG_DATA_CTRL);
|
||||
|
||||
/* Set MMD device number and register to write to */
|
||||
sw_w32(devnum << 16 | (regnum & 0xffff), RTL839X_PHYREG_MMD_CTRL);
|
||||
|
||||
v = BIT(2) | BIT(0); /* MMD-access | EXEC */
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
err = rtl839x_smi_wait_op(100000);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
/* There is no error-checking via BIT 1 of v, as it does not seem to be set correctly */
|
||||
*val = (sw_r32(RTL839X_PHYREG_DATA_CTRL) & 0xffff);
|
||||
pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, *val, err);
|
||||
|
||||
errout:
|
||||
mutex_unlock(&smi_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Write to an mmd register of the PHY */
|
||||
int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
|
||||
{
|
||||
int err = 0;
|
||||
u32 v;
|
||||
|
||||
/* Take bug on RTL839x Rev <= C into account */
|
||||
if (port >= RTL839X_CPU_PORT)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&smi_lock);
|
||||
|
||||
/* Set PHY to access */
|
||||
rtl839x_set_port_reg_le(BIT_ULL(port), RTL839X_PHYREG_PORT_CTRL);
|
||||
|
||||
/* Set data to write */
|
||||
sw_w32_mask(0xffff << 16, val << 16, RTL839X_PHYREG_DATA_CTRL);
|
||||
|
||||
/* Set MMD device number and register to write to */
|
||||
sw_w32(devnum << 16 | (regnum & 0xffff), RTL839X_PHYREG_MMD_CTRL);
|
||||
|
||||
v = BIT(3) | BIT(2) | BIT(0); /* WRITE | MMD-access | EXEC */
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
err = rtl839x_smi_wait_op(100000);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err);
|
||||
|
||||
errout:
|
||||
mutex_unlock(&smi_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void rtl8390_get_version(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
u32 info, model;
|
||||
|
||||
@@ -194,9 +194,6 @@ int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port);
|
||||
|
||||
/* phy functions that will need to be moved to the future mdio driver */
|
||||
|
||||
int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
|
||||
int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
|
||||
|
||||
int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
|
||||
int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
|
||||
|
||||
|
||||
@@ -27,13 +27,6 @@ extern struct rtl83xx_soc_info soc_info;
|
||||
|
||||
extern int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data);
|
||||
|
||||
extern int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
|
||||
extern int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
extern int rtl839x_read_sds_phy(int phy_addr, int phy_reg);
|
||||
extern int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
|
||||
extern int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
extern int rtl839x_write_sds_phy(int phy_addr, int phy_reg, u16 v);
|
||||
|
||||
extern int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
|
||||
extern int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
extern int rtl930x_read_sds_phy(int phy_addr, int page, int phy_reg);
|
||||
@@ -84,6 +77,7 @@ extern int rtl931x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v);
|
||||
#define RTMDIO_PKG BIT(3)
|
||||
|
||||
#define RTMDIO_838X_BASE (0xe780)
|
||||
#define RTMDIO_839X_BASE (0xa000)
|
||||
|
||||
struct p_hdr {
|
||||
uint8_t *buf;
|
||||
@@ -1960,6 +1954,263 @@ errout:
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* The RTL839x has 14 SerDes starting at 0xbb00a000. 0-7, 10, 11 are 5GBit, 8, 9, 12, 13 are
|
||||
* 10 GBit. Two adjacent SerDes are tightly coupled and share a 1024 bytes register area. Per 32
|
||||
* bit address two registers are stored. The first register is stored in the lower 2 bytes ("on
|
||||
* the right" due to big endian) and the second register in the upper 2 bytes. The following
|
||||
* register areas are known:
|
||||
*
|
||||
* - XSG0 (4 pages @ offset 0x000): for even SerDes
|
||||
* - XSG1 (4 pages @ offset 0x100): for odd SerDes
|
||||
* - TGRX (4 pages @ offset 0x200): for even 10G SerDes
|
||||
* - ANA_RG (2 pages @ offset 0x300): for even 5G SerDes
|
||||
* - ANA_RG (2 pages @ offset 0x380): for odd 5G SerDes
|
||||
* - ANA_TG (2 pages @ offset 0x300): for even 10G SerDes
|
||||
* - ANA_TG (2 pages @ offset 0x380): for odd 10G SerDes
|
||||
*
|
||||
* The most consistent mapping that aligns to the RTL93xx devices is:
|
||||
*
|
||||
* even 5G SerDes odd 5G SerDes even 10G SerDes odd 10G SerDes
|
||||
* Page 0: XSG0/0 XSG1/0 XSG0/0 XSG1/0
|
||||
* Page 1: XSG0/1 XSG1/1 XSG0/1 XSG1/1
|
||||
* Page 2: XSG0/2 XSG1/2 XSG0/2 XSG1/2
|
||||
* Page 3: XSG0/3 XSG1/3 XSG0/3 XSG1/3
|
||||
* Page 4: <zero> <zero> TGRX/0 <zero>
|
||||
* Page 5: <zero> <zero> TGRX/1 <zero>
|
||||
* Page 6: <zero> <zero> TGRX/2 <zero>
|
||||
* Page 7: <zero> <zero> TGRX/3 <zero>
|
||||
* Page 8: ANA_RG ANA_RG <zero> <zero>
|
||||
* Page 9: ANA_RG_EXT ANA_RG_EXT <zero> <zero>
|
||||
* Page 10: <zero> <zero> ANA_TG ANA_TG
|
||||
* Page 11: <zero> <zero> ANA_TG_EXT ANA_TG_EXT
|
||||
*/
|
||||
|
||||
static int rtmdio_839x_reg_offset(int sds, int page, int regnum)
|
||||
{
|
||||
int offset = ((sds & 0xfe) << 9) + ((regnum & 0xfe) << 1) + (page << 6);
|
||||
int sds5g = (GENMASK(11, 10) | GENMASK(7, 0)) & BIT(sds);
|
||||
|
||||
if (sds < 0 || sds > 13 || page < 0 || page > 11 || regnum < 0 || regnum > 31)
|
||||
return -EIO;
|
||||
|
||||
if (page < 4)
|
||||
return offset + ((sds & 1) << 8);
|
||||
else if ((page & 4) && (sds == 8 || sds == 12))
|
||||
return offset + 0x100;
|
||||
else if (page >= 8 && page <= 9 && sds5g)
|
||||
return offset + 0x100 + ((sds & 1) << 7);
|
||||
else if (page >= 10 && !sds5g)
|
||||
return offset + 0x80 + ((sds & 1) << 7);
|
||||
|
||||
return -EINVAL; /* hole */
|
||||
}
|
||||
|
||||
static int rtmdio_839x_read_sds_phy(int sds, int page, int regnum)
|
||||
{
|
||||
int bitpos = ((regnum << 4) & 0x10);
|
||||
int offset;
|
||||
u32 val;
|
||||
|
||||
offset = rtmdio_839x_reg_offset(sds, page, regnum);
|
||||
if (offset == -EINVAL)
|
||||
return 0;
|
||||
|
||||
if (offset < 0)
|
||||
return offset;
|
||||
|
||||
/* phy id is empty so simulate one */
|
||||
if (page == 2 && regnum == 2)
|
||||
return 0x1c;
|
||||
if (page == 2 && regnum == 3)
|
||||
return 0x8393;
|
||||
|
||||
val = sw_r32(RTMDIO_839X_BASE + offset);
|
||||
val = (val >> bitpos) & 0xffff;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int rtmdio_839x_write_sds_phy(int sds, int page, int regnum, u16 val)
|
||||
{
|
||||
u32 neighbor;
|
||||
int offset;
|
||||
u32 set;
|
||||
|
||||
offset = rtmdio_839x_reg_offset(sds, page, regnum);
|
||||
if (offset == -EINVAL)
|
||||
return 0;
|
||||
|
||||
if (offset < 0)
|
||||
return 0;
|
||||
|
||||
neighbor = rtmdio_839x_read_sds_phy(sds, page, regnum ^ 1);
|
||||
if (regnum & 1)
|
||||
set = (val << 16) + neighbor;
|
||||
else
|
||||
set = (neighbor << 16) + val;
|
||||
|
||||
sw_w32(set, RTMDIO_839X_BASE + offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RTL839x specific MDIO functions */
|
||||
|
||||
static int rtmdio_839x_smi_wait_op(int timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 val;
|
||||
|
||||
ret = readx_poll_timeout(sw_r32, RTL839X_PHYREG_ACCESS_CTRL,
|
||||
val, !(val & 0x1), 20, timeout);
|
||||
if (ret)
|
||||
pr_err("%s: timeout\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtmdio_839x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
|
||||
{
|
||||
int err = 0;
|
||||
u32 v;
|
||||
|
||||
if (port >= RTL839X_CPU_PORT || page > 8191 || reg > 31)
|
||||
return -ENOTSUPP;
|
||||
|
||||
mutex_lock(&rtmdio_lock);
|
||||
|
||||
sw_w32_mask(0xffff0000, port << 16, RTL839X_PHYREG_DATA_CTRL);
|
||||
v = reg << 5 | page << 10 | ((page == 0x1fff) ? 0x1f : 0) << 23;
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
sw_w32(0x1ff, RTL839X_PHYREG_CTRL);
|
||||
|
||||
v |= 1;
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
err = rtmdio_839x_smi_wait_op(100000);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
*val = sw_r32(RTL839X_PHYREG_DATA_CTRL) & 0xffff;
|
||||
|
||||
errout:
|
||||
mutex_unlock(&rtmdio_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rtmdio_839x_write_phy(u32 port, u32 page, u32 reg, u32 val)
|
||||
{
|
||||
int err = 0;
|
||||
u32 v;
|
||||
|
||||
val &= 0xffff;
|
||||
if (port >= RTL839X_CPU_PORT || page > 8191 || reg > 31)
|
||||
return -ENOTSUPP;
|
||||
|
||||
mutex_lock(&rtmdio_lock);
|
||||
|
||||
/* Set PHY to access */
|
||||
sw_w32(BIT_ULL(port), RTL839X_PHYREG_PORT_CTRL);
|
||||
sw_w32(BIT_ULL(port) >> 32, RTL839X_PHYREG_PORT_CTRL + 4);
|
||||
|
||||
sw_w32_mask(0xffff0000, val << 16, RTL839X_PHYREG_DATA_CTRL);
|
||||
|
||||
v = reg << 5 | page << 10 | ((page == 0x1fff) ? 0x1f : 0) << 23;
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
sw_w32(0x1ff, RTL839X_PHYREG_CTRL);
|
||||
|
||||
v |= BIT(3) | 1; /* Write operation and execute */
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
err = rtmdio_839x_smi_wait_op(100000);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
if (sw_r32(RTL839X_PHYREG_ACCESS_CTRL) & 0x2)
|
||||
err = -EIO;
|
||||
|
||||
errout:
|
||||
mutex_unlock(&rtmdio_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Read an mmd register of the PHY */
|
||||
static int rtmdio_839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
|
||||
{
|
||||
int err = 0;
|
||||
u32 v;
|
||||
|
||||
/* Take bug on RTL839x Rev <= C into account */
|
||||
if (port >= RTL839X_CPU_PORT)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&rtmdio_lock);
|
||||
|
||||
/* Set PHY to access */
|
||||
sw_w32_mask(0xffff << 16, port << 16, RTL839X_PHYREG_DATA_CTRL);
|
||||
|
||||
/* Set MMD device number and register to write to */
|
||||
sw_w32(devnum << 16 | (regnum & 0xffff), RTL839X_PHYREG_MMD_CTRL);
|
||||
|
||||
v = BIT(2) | BIT(0); /* MMD-access | EXEC */
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
err = rtmdio_839x_smi_wait_op(100000);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
/* There is no error-checking via BIT 1 of v, as it does not seem to be set correctly */
|
||||
*val = (sw_r32(RTL839X_PHYREG_DATA_CTRL) & 0xffff);
|
||||
pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, *val, err);
|
||||
|
||||
errout:
|
||||
mutex_unlock(&rtmdio_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Write to an mmd register of the PHY */
|
||||
static int rtmdio_839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
|
||||
{
|
||||
int err = 0;
|
||||
u32 v;
|
||||
|
||||
/* Take bug on RTL839x Rev <= C into account */
|
||||
if (port >= RTL839X_CPU_PORT)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&rtmdio_lock);
|
||||
|
||||
/* Set PHY to access */
|
||||
sw_w32(BIT_ULL(port), RTL839X_PHYREG_PORT_CTRL);
|
||||
sw_w32(BIT_ULL(port) >> 32, RTL839X_PHYREG_PORT_CTRL + 4);
|
||||
|
||||
/* Set data to write */
|
||||
sw_w32_mask(0xffff << 16, val << 16, RTL839X_PHYREG_DATA_CTRL);
|
||||
|
||||
/* Set MMD device number and register to write to */
|
||||
sw_w32(devnum << 16 | (regnum & 0xffff), RTL839X_PHYREG_MMD_CTRL);
|
||||
|
||||
v = BIT(3) | BIT(2) | BIT(0); /* WRITE | MMD-access | EXEC */
|
||||
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
|
||||
|
||||
err = rtmdio_839x_smi_wait_op(100000);
|
||||
if (err)
|
||||
goto errout;
|
||||
|
||||
pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err);
|
||||
|
||||
errout:
|
||||
mutex_unlock(&rtmdio_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* These are the core functions of our new Realtek SoC MDIO bus. */
|
||||
|
||||
static int rtmdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum)
|
||||
@@ -2046,13 +2297,9 @@ static int rtmdio_83xx_read(struct mii_bus *bus, int addr, int regnum)
|
||||
return priv->page[addr];
|
||||
|
||||
priv->raw[addr] = (priv->page[addr] == priv->rawpage);
|
||||
if ((priv->phy_is_internal[addr]) && (priv->sds_id[addr] >=0)) {
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
if ((priv->phy_is_internal[addr]) && (priv->sds_id[addr] >= 0))
|
||||
return rtmdio_read_sds_phy(priv, priv->sds_id[addr],
|
||||
priv->page[addr], regnum);
|
||||
else
|
||||
return rtl839x_read_sds_phy(addr, regnum);
|
||||
}
|
||||
|
||||
err = (*priv->read_phy)(addr, priv->page[addr], regnum, &val);
|
||||
pr_debug("rd_PHY(adr=%d, pag=%d, reg=%d) = %d, err = %d\n",
|
||||
@@ -2130,13 +2377,9 @@ static int rtmdio_83xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
|
||||
|
||||
if (!priv->raw[addr] && (regnum != RTMDIO_PAGE_SELECT || page == priv->rawpage)) {
|
||||
priv->raw[addr] = (page == priv->rawpage);
|
||||
if (priv->phy_is_internal[addr] && priv->sds_id[addr] >=0 ) {
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
if (priv->phy_is_internal[addr] && priv->sds_id[addr] >= 0)
|
||||
return rtmdio_write_sds_phy(priv, priv->sds_id[addr],
|
||||
priv->page[addr], regnum, val);
|
||||
else
|
||||
return rtl839x_write_sds_phy(addr, regnum, val);
|
||||
}
|
||||
|
||||
err = (*priv->write_phy)(addr, page, regnum, val);
|
||||
pr_debug("wr_PHY(adr=%d, pag=%d, reg=%d, val=%d) err = %d\n",
|
||||
@@ -2476,10 +2719,12 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
|
||||
priv->mii_bus->read = rtmdio_83xx_read;
|
||||
priv->mii_bus->write = rtmdio_83xx_write;
|
||||
priv->mii_bus->reset = rtmdio_839x_reset;
|
||||
bus_priv->read_mmd_phy = rtl839x_read_mmd_phy;
|
||||
bus_priv->write_mmd_phy = rtl839x_write_mmd_phy;
|
||||
bus_priv->read_phy = rtl839x_read_phy;
|
||||
bus_priv->write_phy = rtl839x_write_phy;
|
||||
bus_priv->read_sds_phy = rtmdio_839x_read_sds_phy;
|
||||
bus_priv->write_sds_phy = rtmdio_839x_write_sds_phy;
|
||||
bus_priv->read_mmd_phy = rtmdio_839x_read_mmd_phy;
|
||||
bus_priv->write_mmd_phy = rtmdio_839x_write_mmd_phy;
|
||||
bus_priv->read_phy = rtmdio_839x_read_phy;
|
||||
bus_priv->write_phy = rtmdio_839x_write_phy;
|
||||
bus_priv->cpu_port = RTL839X_CPU_PORT;
|
||||
bus_priv->rawpage = 0x1fff;
|
||||
break;
|
||||
|
||||
@@ -292,44 +292,6 @@ static u32 rtl9300_sds_mode_get(int sds_num)
|
||||
return v & RTL930X_SDS_MASK;
|
||||
}
|
||||
|
||||
/* On the RTL839x family of SoCs with inbuilt SerDes, these SerDes are accessed through
|
||||
* a 2048 bit register that holds the contents of the PHY being simulated by the SoC.
|
||||
*/
|
||||
int rtl839x_read_sds_phy(int phy_addr, int phy_reg)
|
||||
{
|
||||
int offset = 0;
|
||||
int reg;
|
||||
u32 val;
|
||||
|
||||
if (phy_addr == 49)
|
||||
offset = 0x100;
|
||||
|
||||
/* For the RTL8393 internal SerDes, we simulate a PHY ID in registers 2/3
|
||||
* which would otherwise read as 0.
|
||||
*/
|
||||
if (soc_info.id == 0x8393) {
|
||||
if (phy_reg == MII_PHYSID1)
|
||||
return 0x1c;
|
||||
if (phy_reg == MII_PHYSID2)
|
||||
return 0x8393;
|
||||
}
|
||||
|
||||
/* Register RTL839X_SDS12_13_XSG0 is 2048 bit broad, the MSB (bit 15) of the
|
||||
* 0th PHY register is bit 1023 (in byte 0x80). Because PHY-registers are 16
|
||||
* bit broad, we offset by reg << 1. In the SoC 2 registers are stored in
|
||||
* one 32 bit register.
|
||||
*/
|
||||
reg = (phy_reg << 1) & 0xfc;
|
||||
val = sw_r32(RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg);
|
||||
|
||||
if (phy_reg & 1)
|
||||
val = (val >> 16) & 0xffff;
|
||||
else
|
||||
val &= 0xffff;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* On the RTL930x family of SoCs, the internal SerDes are accessed through an IO
|
||||
* register which simulates commands to an internal MDIO bus.
|
||||
*/
|
||||
@@ -424,29 +386,6 @@ int rtl931x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl839x_write_sds_phy(int phy_addr, int phy_reg, u16 v)
|
||||
{
|
||||
int offset = 0;
|
||||
int reg;
|
||||
u32 val;
|
||||
|
||||
if (phy_addr == 49)
|
||||
offset = 0x100;
|
||||
|
||||
reg = (phy_reg << 1) & 0xfc;
|
||||
val = v;
|
||||
if (phy_reg & 1) {
|
||||
val = val << 16;
|
||||
sw_w32_mask(0xffff0000, val,
|
||||
RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg);
|
||||
} else {
|
||||
sw_w32_mask(0xffff, val,
|
||||
RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the link and speed status of the 2 internal SGMII/1000Base-X
|
||||
* ports of the RTL838x SoCs
|
||||
*/
|
||||
|
||||
@@ -68,9 +68,6 @@ struct __attribute__ ((__packed__)) fw_header {
|
||||
#define RTL931X_PS_SERDES_OFF_MODE_CTRL_ADDR (0x13F4)
|
||||
#define RTL931X_MAC_SERDES_MODE_CTRL(sds) (0x136C + (((sds) << 2)))
|
||||
|
||||
int rtl839x_read_sds_phy(int phy_addr, int phy_reg);
|
||||
int rtl839x_write_sds_phy(int phy_addr, int phy_reg, u16 v);
|
||||
|
||||
int rtl9300_serdes_setup(int port, int sds_num, phy_interface_t phy_mode);
|
||||
int rtl930x_read_sds_phy(int phy_addr, int page, int phy_reg);
|
||||
int rtl930x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v);
|
||||
|
||||
Reference in New Issue
Block a user