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);
extern int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
extern int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val);
-extern int rtl930x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v);
extern int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
extern int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
#define RTMDIO_ABS BIT(2)
#define RTMDIO_PKG BIT(3)
-#define RTMDIO_838X_BASE (0xe780)
-#define RTMDIO_839X_BASE (0xa000)
+#define RTMDIO_838X_BASE (0xe780)
+#define RTMDIO_839X_BASE (0xa000)
+#define RTMDIO_930X_SDS_INDACS_CMD (0x03B0)
+#define RTMDIO_930X_SDS_INDACS_DATA (0x03B4)
struct p_hdr {
uint8_t *buf;
*/
DEFINE_MUTEX(rtmdio_lock);
+DEFINE_MUTEX(rtmdio_lock_sds);
struct rtmdio_bus_priv {
u16 id;
return err;
}
+/*
+ * The RTL930x family has 12 SerDes of three types. They are accessed through two IO registers at
+ * 0xbb0003b0 which simulate commands to an internal MDIO bus:
+ *
+ * - SerDes 0-1 exist on the RTL9301 and 9302B and are QSGMII capable
+ * - SerDes 2-9 are USXGMII capabable with either quad or single configuration
+ * - SerDes 10-11 are 10GBase-R capable
+ */
+
+int rtmdio_930x_read_sds_phy(int sds, int page, int regnum)
+{
+ int i, ret = -EIO;
+ u32 cmd;
+
+ if (sds < 0 || sds > 11 || page < 0 || page > 63 || regnum < 0 || regnum > 31)
+ return -EIO;
+
+ mutex_lock(&rtmdio_lock_sds);
+
+ cmd = sds << 2 | page << 7 | regnum << 13 | 1;
+ sw_w32(cmd, RTMDIO_930X_SDS_INDACS_CMD);
+
+ for (i = 0; i < 100; i++) {
+ if (!(sw_r32(RTMDIO_930X_SDS_INDACS_CMD) & 0x1))
+ break;
+ mdelay(1);
+ }
+
+ if (i < 100)
+ ret = sw_r32(RTMDIO_930X_SDS_INDACS_DATA) & 0xffff;
+
+ mutex_unlock(&rtmdio_lock_sds);
+
+ return ret;
+}
+
+int rtmdio_930x_write_sds_phy(int sds, int page, int regnum, u16 val)
+{
+ int i, ret = -EIO;
+ u32 cmd;
+
+ if (sds < 0 || sds > 11 || page < 0 || page > 63 || regnum < 0 || regnum > 31)
+ return -EIO;
+
+ mutex_lock(&rtmdio_lock_sds);
+
+ cmd = sds << 2 | page << 7 | regnum << 13 | 0x3;
+ sw_w32(val, RTMDIO_930X_SDS_INDACS_DATA);
+ sw_w32(cmd, RTMDIO_930X_SDS_INDACS_CMD);
+
+ for (i = 0; i < 100; i++) {
+ if (!(sw_r32(RTMDIO_930X_SDS_INDACS_CMD) & 0x1))
+ break;
+ mdelay(1);
+ }
+
+ mutex_unlock(&rtmdio_lock_sds);
+
+ if (i < 100)
+ ret = 0;
+
+ return ret;
+}
+
/* 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)
priv->raw[addr] = (priv->page[addr] == priv->rawpage);
if (priv->phy_is_internal[addr]) {
if (priv->family_id == RTL9300_FAMILY_ID)
- return rtl930x_read_sds_phy(priv->sds_id[addr],
- priv->page[addr], regnum);
+ return rtmdio_930x_read_sds_phy(priv->sds_id[addr],
+ priv->page[addr], regnum);
else
return rtl931x_read_sds_phy(priv->sds_id[addr],
priv->page[addr], regnum);
priv->raw[addr] = (page == priv->rawpage);
if (priv->phy_is_internal[addr]) {
if (priv->family_id == RTL9300_FAMILY_ID)
- return rtl930x_write_sds_phy(priv->sds_id[addr],
- page, regnum, val);
+ return rtmdio_930x_write_sds_phy(priv->sds_id[addr],
+ page, regnum, val);
else
return rtl931x_write_sds_phy(priv->sds_id[addr],
page, regnum, val);
extern int phy_package_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum);
extern int phy_package_read_paged(struct phy_device *phydev, int page, u32 regnum);
+extern int rtmdio_930x_read_sds_phy(int sds, int page, int regnum);
+extern int rtmdio_930x_write_sds_phy(int sds, int page, int regnum, u16 val);
+
#define PHY_PAGE_2 2
#define PHY_PAGE_4 4
return v & RTL930X_SDS_MASK;
}
-/* On the RTL930x family of SoCs, the internal SerDes are accessed through an IO
- * register which simulates commands to an internal MDIO bus.
- */
-int rtl930x_read_sds_phy(int phy_addr, int page, int phy_reg)
-{
- int i;
- u32 cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 1;
-
- sw_w32(cmd, RTL930X_SDS_INDACS_CMD);
-
- for (i = 0; i < 100; i++) {
- if (!(sw_r32(RTL930X_SDS_INDACS_CMD) & 0x1))
- break;
- mdelay(1);
- }
-
- if (i >= 100)
- return -EIO;
-
- return sw_r32(RTL930X_SDS_INDACS_DATA) & 0xffff;
-}
-
-int rtl930x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v)
-{
- int i;
- u32 cmd;
-
- sw_w32(v, RTL930X_SDS_INDACS_DATA);
- cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 0x3;
-
- sw_w32(cmd, RTL930X_SDS_INDACS_CMD);
-
- for (i = 0; i < 100; i++) {
- if (!(sw_r32(RTL930X_SDS_INDACS_CMD) & 0x1))
- break;
- mdelay(1);
- }
-
-
- if (i >= 100) {
- pr_info("%s ERROR !!!!!!!!!!!!!!!!!!!!\n", __func__);
- return -EIO;
- }
-
- return 0;
-}
-
int rtl931x_read_sds_phy(int phy_addr, int page, int phy_reg)
{
int i;
if (l < 32) {
u32 mask = BIT(l) - 1;
- data = rtl930x_read_sds_phy(sds, page, reg);
+ data = rtmdio_930x_read_sds_phy(sds, page, reg);
data &= ~(mask << start_bit);
data |= (v & mask) << start_bit;
}
- rtl930x_write_sds_phy(sds, page, reg, data);
+ rtmdio_930x_write_sds_phy(sds, page, reg, data);
}
static u32 rtl9300_sds_field_r(int sds, u32 page, u32 reg, int end_bit, int start_bit)
{
int l = end_bit - start_bit + 1;
- u32 v = rtl930x_read_sds_phy(sds, page, reg);
+ u32 v = rtmdio_930x_read_sds_phy(sds, page, reg);
if (l >= 32)
return v;
for (i = 0; i < 20; i++) {
usleep_range(10000, 15000);
- rtl930x_write_sds_phy(base_sds, 0x1f, 0x02, 53);
+ rtmdio_930x_write_sds_phy(base_sds, 0x1f, 0x02, 53);
ready = rtl9300_sds_field_r(base_sds, 0x1f, 0x14, bit, bit);
ready_cnt = ready ? ready_cnt + 1 : 0;
{
u32 v10, v1;
- v10 = rtl930x_read_sds_phy(sds, 6, 2); /* 10GBit, page 6, reg 2 */
- v1 = rtl930x_read_sds_phy(sds, 0, 0); /* 1GBit, page 0, reg 0 */
+ v10 = rtmdio_930x_read_sds_phy(sds, 6, 2); /* 10GBit, page 6, reg 2 */
+ v1 = rtmdio_930x_read_sds_phy(sds, 0, 0); /* 1GBit, page 0, reg 0 */
pr_info("%s: registers before %08x %08x\n", __func__, v10, v1);
v10 &= ~(BIT(13) | BIT(14));
v10 |= tx_normal ? 0 : BIT(14);
v1 |= tx_normal ? 0 : BIT(8);
- rtl930x_write_sds_phy(sds, 6, 2, v10);
- rtl930x_write_sds_phy(sds, 0, 0, v1);
+ rtmdio_930x_write_sds_phy(sds, 6, 2, v10);
+ rtmdio_930x_write_sds_phy(sds, 0, 0, v1);
- v10 = rtl930x_read_sds_phy(sds, 6, 2);
- v1 = rtl930x_read_sds_phy(sds, 0, 0);
+ v10 = rtmdio_930x_read_sds_phy(sds, 6, 2);
+ v1 = rtmdio_930x_read_sds_phy(sds, 0, 0);
pr_info("%s: registers after %08x %08x\n", __func__, v10, v1);
}
bool dcvs_manual;
if (!(sds_num % 2))
- rtl930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
+ rtmdio_930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
else
- rtl930x_write_sds_phy(sds_num - 1, 0x1f, 0x2, 0x31);
+ rtmdio_930x_write_sds_phy(sds_num - 1, 0x1f, 0x2, 0x31);
/* ##Page0x2E, Reg0x15[9], REG0_RX_EN_TEST=[1] */
rtl9300_sds_field_w(sds_num, 0x2e, 0x15, 9, 9, 0x1);
bool leq_manual;
if (!(sds_num % 2))
- rtl930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
+ rtmdio_930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
else
- rtl930x_write_sds_phy(sds_num - 1, 0x1f, 0x2, 0x31);
+ rtmdio_930x_write_sds_phy(sds_num - 1, 0x1f, 0x2, 0x31);
/* ##Page0x2E, Reg0x15[9], REG0_RX_EN_TEST=[1] */
rtl9300_sds_field_w(sds_num, 0x2e, 0x15, 9, 9, 0x1);
/* ##Page0x1F, Reg0x02[15 0], REG_DBGO_SEL=[0x002F]; */ /* Lane0 */
/* ##Page0x1F, Reg0x02[15 0], REG_DBGO_SEL=[0x0031]; */ /* Lane1 */
if (!(sds_num % 2))
- rtl930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
+ rtmdio_930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
else
- rtl930x_write_sds_phy(sds_num - 1, 0x1f, 0x2, 0x31);
+ rtmdio_930x_write_sds_phy(sds_num - 1, 0x1f, 0x2, 0x31);
/* ##Page0x2E, Reg0x15[9], REG0_RX_EN_TEST=[1] */
rtl9300_sds_field_w(sds_num, 0x2e, 0x15, 9, 9, 0x1);
bool tap_manual;
if (!(sds_num % 2))
- rtl930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
+ rtmdio_930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
else
- rtl930x_write_sds_phy(sds_num - 1, 0x1f, 0x2, 0x31);
+ rtmdio_930x_write_sds_phy(sds_num - 1, 0x1f, 0x2, 0x31);
/* ##Page0x2E, Reg0x15[9], REG0_RX_EN_TEST=[1] */
rtl9300_sds_field_w(sds_num, 0x2e, 0x15, 9, 9, 0x1);
int vth_min = 0x0;
pr_info("start_1.1.1 initial value for sds %d\n", sds);
- rtl930x_write_sds_phy(sds, 6, 0, 0);
+ rtmdio_930x_write_sds_phy(sds, 6, 0, 0);
/* FGCAL */
rtl9300_sds_field_w(sds, 0x2e, 0x01, 14, 14, 0x00);
while(1) {
if (!(sds_num % 2))
- rtl930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
+ rtmdio_930x_write_sds_phy(sds_num, 0x1f, 0x2, 0x2f);
else
- rtl930x_write_sds_phy(sds_num -1 , 0x1f, 0x2, 0x31);
+ rtmdio_930x_write_sds_phy(sds_num -1 , 0x1f, 0x2, 0x31);
/* ##Page0x2E, Reg0x15[9], REG0_RX_EN_TEST=[1] */
rtl9300_sds_field_w(sds_num, 0x2e, 0x15, 9, 9, 0x1);
case PHY_INTERFACE_MODE_10GBASER:
/* Read twice to clear */
- rtl930x_read_sds_phy(sds_num, 5, 1);
- rtl930x_read_sds_phy(sds_num, 5, 1);
+ rtmdio_930x_read_sds_phy(sds_num, 5, 1);
+ rtmdio_930x_read_sds_phy(sds_num, 5, 1);
break;
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_10GBASER:
- v = rtl930x_read_sds_phy(sds_num, 5, 1);
+ v = rtmdio_930x_read_sds_phy(sds_num, 5, 1);
return v & 0xff;
default:
u32 v;
/* Enable 1GBit PHY */
- v = rtl930x_read_sds_phy(sds_num, PHY_PAGE_2, MII_BMCR);
+ v = rtmdio_930x_read_sds_phy(sds_num, PHY_PAGE_2, MII_BMCR);
pr_info("%s 1gbit phy: %08x\n", __func__, v);
v &= ~BMCR_PDOWN;
- rtl930x_write_sds_phy(sds_num, PHY_PAGE_2, MII_BMCR, v);
+ rtmdio_930x_write_sds_phy(sds_num, PHY_PAGE_2, MII_BMCR, v);
pr_info("%s 1gbit phy enabled: %08x\n", __func__, v);
/* Enable 10GBit PHY */
- v = rtl930x_read_sds_phy(sds_num, PHY_PAGE_4, MII_BMCR);
+ v = rtmdio_930x_read_sds_phy(sds_num, PHY_PAGE_4, MII_BMCR);
pr_info("%s 10gbit phy: %08x\n", __func__, v);
v &= ~BMCR_PDOWN;
- rtl930x_write_sds_phy(sds_num, PHY_PAGE_4, MII_BMCR, v);
+ rtmdio_930x_write_sds_phy(sds_num, PHY_PAGE_4, MII_BMCR, v);
pr_info("%s 10gbit phy after: %08x\n", __func__, v);
/* dal_longan_construct_mac_default_10gmedia_fiber */
- v = rtl930x_read_sds_phy(sds_num, 0x1f, 11);
+ v = rtmdio_930x_read_sds_phy(sds_num, 0x1f, 11);
pr_info("%s set medium: %08x\n", __func__, v);
v |= BIT(1);
- rtl930x_write_sds_phy(sds_num, 0x1f, 11, v);
+ rtmdio_930x_write_sds_phy(sds_num, 0x1f, 11, v);
pr_info("%s set medium after: %08x\n", __func__, v);
}
{
if (sds_num % 2) {
for (int i = 0; i < sizeof(rtl9300_a_sds_10gr_lane1) / sizeof(sds_config); ++i) {
- rtl930x_write_sds_phy(sds_num, rtl9300_a_sds_10gr_lane1[i].page,
- rtl9300_a_sds_10gr_lane1[i].reg,
- rtl9300_a_sds_10gr_lane1[i].data);
+ rtmdio_930x_write_sds_phy(sds_num, rtl9300_a_sds_10gr_lane1[i].page,
+ rtl9300_a_sds_10gr_lane1[i].reg,
+ rtl9300_a_sds_10gr_lane1[i].data);
}
} else {
for (int i = 0; i < sizeof(rtl9300_a_sds_10gr_lane0) / sizeof(sds_config); ++i) {
- rtl930x_write_sds_phy(sds_num, rtl9300_a_sds_10gr_lane0[i].page,
- rtl9300_a_sds_10gr_lane0[i].reg,
- rtl9300_a_sds_10gr_lane0[i].data);
+ rtmdio_930x_write_sds_phy(sds_num, rtl9300_a_sds_10gr_lane0[i].page,
+ rtl9300_a_sds_10gr_lane0[i].reg,
+ rtl9300_a_sds_10gr_lane0[i].data);
}
}
}
en = rtl9300_sds_field_r(sds, page, 27, 1, 1);
if(!en) { /* Auto mode */
- rtl930x_write_sds_phy(sds, 0x1f, 0x02, 31);
+ rtmdio_930x_write_sds_phy(sds, 0x1f, 0x02, 31);
cmu_band = rtl9300_sds_field_r(sds, 0x1f, 0x15, 5, 1);
} else {