#define RTMDIO_931X_MAC_L2_GLOBAL_CTRL2 (0x1358)
#define RTMDIO_931X_SMI_PORT_POLLING_SEL (0x0C9C)
#define RTMDIO_931X_SMI_PORT_ADDR (0x0C74)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL0 (0x0CF0)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL1 (0x0CF4)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL2 (0x0CF8)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL3 (0x0CFC)
+#define RTMDIO_931X_SMI_10GPHY_POLLING_SEL4 (0x0D00)
#define sw_r32(reg) readl(RTMDIO_SW_BASE + reg)
#define sw_w32(val, reg) writel(val, RTMDIO_SW_BASE + reg)
int mac_type;
bool has_giga_lite;
bool has_res_reg;
+ bool force_res;
unsigned int poll_duplex;
unsigned int poll_adv_1000;
unsigned int poll_lpa_1000;
static int rtmdio_931x_reset(struct mii_bus *bus)
{
struct rtmdio_bus_priv *priv = bus->priv;
+ struct rtmdio_phy_info phyinfo;
u32 poll_sel[4] = { 0 };
u32 poll_ctrl = 0;
u32 c45_mask = 0;
sw_w32(poll_sel[i], RTMDIO_931X_SMI_PORT_POLLING_SEL + (i * 4));
}
- /* Configure which SMI busses */
- pr_info("c45_mask: %08x, RTMDIO_931X_SMI_GLB_CTRL0 was %X", c45_mask, sw_r32(RTMDIO_931X_SMI_GLB_CTRL0));
+ /* Configure c22/c45 polling (bit 1 of SMI_SETX_FMT_SEL)
+ *
+ * NOTE: this seems to be needed before accessing the bus though
+ * it should only apply to the SMI polling. Not setting c22/c45 here
+ * apparently causes garbage being read below.
+ */
for (int i = 0; i < RTMDIO_MAX_SMI_BUS; i++) {
/* bus is polled in c45 */
if (priv->smi_bus_isc45[i])
c45_mask |= 0x2 << (i * 2); /* Std. C45, non-standard is 0x3 */
}
+ pr_info("%s: c45_mask: %08x", __func__, c45_mask);
+ sw_w32_mask(GENMASK(7, 0), c45_mask, RTMDIO_931X_SMI_GLB_CTRL1);
- pr_info("c45_mask: %08x, RTL931X_SMI_GLB_CTRL0 was %X", c45_mask, sw_r32(RTMDIO_931X_SMI_GLB_CTRL0));
-
- /* We have a 10G PHY enable polling
- * sw_w32(0x01010000, RTL931X_SMI_10GPHY_POLLING_SEL2);
- * sw_w32(0x01E7C400, RTL931X_SMI_10GPHY_POLLING_SEL3);
- * sw_w32(0x01E7E820, RTL931X_SMI_10GPHY_POLLING_SEL4);
+ /* Define PHY specific polling parameters
+ *
+ * Those are applied per port here but the SoC only supports them
+ * per SMI bus or for all GPHY/10GPHY. This should be guarded by
+ * the existing hardware designs (i.e. only equally polled PHYs on
+ * the same SMI bus or kind of PHYs).
*/
- sw_w32_mask(GENMASK(7, 0), c45_mask, RTMDIO_931X_SMI_GLB_CTRL1);
+ for (int addr = 0; addr < priv->cfg->cpu_port; addr++) {
+ unsigned int mask, val;
+ int smi = priv->smi_bus[addr];
+
+ if (smi < 0)
+ continue;
+
+ rtmdio_get_phy_info(bus, addr, &phyinfo);
+ if (phyinfo.phy_unknown) {
+ pr_warn("skip polling setup for unknown PHY %08x on port %d\n",
+ phyinfo.phy_id, addr);
+ continue;
+ }
+
+ mask = val = 0;
+
+ /* PRVTE0 polling */
+ mask |= BIT(20 + smi);
+ if (phyinfo.has_res_reg)
+ val |= BIT(20 + smi);
+
+ /* PRVTE1 polling */
+ mask |= BIT(24 + smi);
+ if (phyinfo.force_res)
+ val |= BIT(24 + smi);
+
+ sw_w32_mask(mask, val, RTMDIO_931X_SMI_GLB_CTRL0);
+
+ /* polling std. or proprietary format (bit 0 of SMI_SETX_FMT_SEL) */
+ mask = BIT(smi * 2);
+ val = phyinfo.force_res ? mask : 0;
+ sw_w32_mask(mask, val, RTMDIO_931X_SMI_GLB_CTRL1);
+
+ /* special polling registers */
+ if (phyinfo.poll_duplex || phyinfo.poll_adv_1000 || phyinfo.poll_lpa_1000) {
+ sw_w32(phyinfo.poll_duplex, RTMDIO_931X_SMI_10GPHY_POLLING_SEL2);
+ sw_w32(phyinfo.poll_adv_1000, RTMDIO_931X_SMI_10GPHY_POLLING_SEL3);
+ sw_w32(phyinfo.poll_lpa_1000, RTMDIO_931X_SMI_10GPHY_POLLING_SEL4);
+ }
+ }
+
+ pr_debug("%s: RTMDIO_931X_SMI_GLB_CTRL0 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_GLB_CTRL0));
+ pr_debug("%s: RTMDIO_931X_SMI_GLB_CTRL1 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_GLB_CTRL1));
+ pr_debug("%s: RTMDIO_931X_SMI_PORT_POLLING_SEL_0_15 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_PORT_POLLING_SEL));
+ pr_debug("%s: RTMDIO_931X_SMI_PORT_POLLING_SEL_16_27 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_PORT_POLLING_SEL + 4));
+ pr_debug("%s: RTMDIO_931X_SMI_PORT_POLLING_SEL_28_43 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_PORT_POLLING_SEL + 8));
+ pr_debug("%s: RTMDIO_931X_SMI_PORT_POLLING_SEL_44_55 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_PORT_POLLING_SEL + 12));
+ pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL0 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL0));
+ pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL1 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL1));
+ pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL2 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL2));
+ pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL3 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL3));
+ pr_debug("%s: RTMDIO_931X_SMI_10GPHY_POLLING_SEL4 %08x\n", __func__,
+ sw_r32(RTMDIO_931X_SMI_10GPHY_POLLING_SEL4));
return 0;
}