};
struct rtpcs_ctrl;
+struct rtpcs_serdes;
+
+struct rtpcs_serdes_ops {
+ int (*read)(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow);
+ int (*write)(struct rtpcs_serdes *sds, int page, int regnum, int bithigh, int bitlow,
+ u16 value);
+};
struct rtpcs_serdes {
struct rtpcs_ctrl *ctrl;
+ const struct rtpcs_serdes_ops *ops;
enum rtpcs_sds_mode hw_mode;
u8 id;
u8 num_of_links;
u8 serdes_count;
const struct phylink_pcs_ops *pcs_ops;
+ const struct rtpcs_serdes_ops *sds_ops;
int (*init_serdes_common)(struct rtpcs_ctrl *ctrl);
int (*set_autoneg)(struct rtpcs_serdes *sds, unsigned int neg_mode);
int (*setup_serdes)(struct rtpcs_serdes *sds, phy_interface_t mode);
return (sds_page << 8) + sds_regnum;
}
-static int rtpcs_sds_read(struct rtpcs_serdes *sds, int page, int regnum)
-{
- int mmd_regnum = rtpcs_sds_to_mmd(page, regnum);
-
- return mdiobus_c45_read(sds->ctrl->bus, sds->id, MDIO_MMD_VEND1,
- mmd_regnum);
-}
+/*
+ * Basic helpers
+ *
+ * These work on the plain SerDes ID. They shouldn't be used except for
+ * implementing the SerDes read/write ops.
+ */
-static int rtpcs_sds_read_bits(struct rtpcs_serdes *sds, int page,
- int regnum, int bithigh, int bitlow)
+static int __rtpcs_sds_read_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, int regnum,
+ int bithigh, int bitlow)
{
- int mask, val;
+ int mmd_regnum = rtpcs_sds_to_mmd(page, regnum);
+ u16 mask;
+ int val;
- WARN_ON(bithigh < bitlow);
+ if (WARN_ON(bithigh < bitlow))
+ return -EINVAL;
mask = GENMASK(bithigh, bitlow);
- val = rtpcs_sds_read(sds, page, regnum);
+ val = mdiobus_c45_read(ctrl->bus, sds_id, MDIO_MMD_VEND1, mmd_regnum);
if (val < 0)
return val;
return (val & mask) >> bitlow;
}
-static int rtpcs_sds_write(struct rtpcs_serdes *sds, int page, int regnum, u16 value)
+static int __rtpcs_sds_write_raw(struct rtpcs_ctrl *ctrl, int sds_id, int page, int regnum,
+ int bithigh, int bitlow, u16 value)
{
int mmd_regnum = rtpcs_sds_to_mmd(page, regnum);
+ u16 mask, set;
+
+ if (WARN_ON(bithigh < bitlow))
+ return -EINVAL;
+
+ if (bithigh == 15 && bitlow == 0)
+ return mdiobus_c45_write(ctrl->bus, sds_id, MDIO_MMD_VEND1, mmd_regnum, value);
- return mdiobus_c45_write(sds->ctrl->bus, sds->id, MDIO_MMD_VEND1,
- mmd_regnum, value);
+ mask = GENMASK(bithigh, bitlow);
+ set = (value << bitlow) & mask;
+ return mdiobus_c45_modify(ctrl->bus, sds_id, MDIO_MMD_VEND1, mmd_regnum, mask, set);
}
-static int rtpcs_sds_write_bits(struct rtpcs_serdes *sds, int page,
- int regnum, int bithigh, int bitlow, u16 value)
+/* Generic implementations, if no special behavior is needed */
+
+static int rtpcs_generic_sds_op_read(struct rtpcs_serdes *sds, int page, int regnum, int bithigh,
+ int bitlow)
{
- int mask, reg;
+ return __rtpcs_sds_read_raw(sds->ctrl, sds->id, page, regnum, bithigh, bitlow);
+}
- WARN_ON(bithigh < bitlow);
+static int rtpcs_generic_sds_op_write(struct rtpcs_serdes *sds, int page, int regnum, int bithigh,
+ int bitlow, u16 value)
+{
+ return __rtpcs_sds_write_raw(sds->ctrl, sds->id, page, regnum, bithigh, bitlow, value);
+}
- mask = GENMASK(bithigh, bitlow);
- reg = rtpcs_sds_read(sds, page, regnum);
- if (reg < 0)
- return reg;
+/* Convenience helpers */
- reg = (reg & ~mask);
- reg |= (value << bitlow) & mask;
+static int rtpcs_sds_read_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh,
+ int bitlow)
+{
+ return sds->ops->read(sds, page, regnum, bithigh, bitlow);
+}
+
+static int rtpcs_sds_write_bits(struct rtpcs_serdes *sds, int page, int regnum, int bithigh,
+ int bitlow, u16 value)
+{
+ return sds->ops->write(sds, page, regnum, bithigh, bitlow, value);
+}
- return rtpcs_sds_write(sds, page, regnum, reg);
+static int rtpcs_sds_read(struct rtpcs_serdes *sds, int page, int regnum)
+{
+ return sds->ops->read(sds, page, regnum, 15, 0);
+}
+
+static int rtpcs_sds_write(struct rtpcs_serdes *sds, int page, int regnum, u16 value)
+{
+ return sds->ops->write(sds, page, regnum, 15, 0, value);
}
+/* Other helpers */
+
static int rtpcs_sds_modify(struct rtpcs_serdes *sds, int page, int regnum,
u16 mask, u16 set)
{
sds = &ctrl->serdes[i];
sds->ctrl = ctrl;
sds->id = i;
+
+ sds->ops = ctrl->cfg->sds_ops;
}
for_each_child_of_node(dev->of_node, child) {
.pcs_get_state = rtpcs_pcs_get_state,
};
+static const struct rtpcs_serdes_ops rtpcs_838x_sds_ops = {
+ .read = rtpcs_generic_sds_op_read,
+ .write = rtpcs_generic_sds_op_write,
+};
+
static const struct rtpcs_config rtpcs_838x_cfg = {
.cpu_port = RTPCS_838X_CPU_PORT,
.mac_link_dup_sts = RTPCS_838X_MAC_LINK_DUP_STS,
.mac_tx_pause_sts = RTPCS_838X_MAC_TX_PAUSE_STS,
.serdes_count = RTPCS_838X_SERDES_CNT,
.pcs_ops = &rtpcs_838x_pcs_ops,
+ .sds_ops = &rtpcs_838x_sds_ops,
.init_serdes_common = rtpcs_838x_init_serdes_common,
.setup_serdes = rtpcs_838x_setup_serdes,
};
.pcs_get_state = rtpcs_pcs_get_state,
};
+static const struct rtpcs_serdes_ops rtpcs_839x_sds_ops = {
+ .read = rtpcs_generic_sds_op_read,
+ .write = rtpcs_generic_sds_op_write,
+};
+
static const struct rtpcs_config rtpcs_839x_cfg = {
.cpu_port = RTPCS_839X_CPU_PORT,
.mac_link_dup_sts = RTPCS_839X_MAC_LINK_DUP_STS,
.mac_tx_pause_sts = RTPCS_839X_MAC_TX_PAUSE_STS,
.serdes_count = RTPCS_839X_SERDES_CNT,
.pcs_ops = &rtpcs_839x_pcs_ops,
+ .sds_ops = &rtpcs_839x_sds_ops,
.init_serdes_common = rtpcs_839x_init_serdes_common,
.setup_serdes = rtpcs_839x_setup_serdes,
};
.pcs_get_state = rtpcs_pcs_get_state,
};
+static const struct rtpcs_serdes_ops rtpcs_930x_sds_ops = {
+ .read = rtpcs_generic_sds_op_read,
+ .write = rtpcs_generic_sds_op_write,
+};
+
static const struct rtpcs_config rtpcs_930x_cfg = {
.cpu_port = RTPCS_930X_CPU_PORT,
.mac_link_dup_sts = RTPCS_930X_MAC_LINK_DUP_STS,
.mac_tx_pause_sts = RTPCS_930X_MAC_TX_PAUSE_STS,
.serdes_count = RTPCS_930X_SERDES_CNT,
.pcs_ops = &rtpcs_930x_pcs_ops,
+ .sds_ops = &rtpcs_930x_sds_ops,
.set_autoneg = rtpcs_93xx_set_autoneg,
.setup_serdes = rtpcs_930x_setup_serdes,
};
.pcs_get_state = rtpcs_pcs_get_state,
};
+static const struct rtpcs_serdes_ops rtpcs_931x_sds_ops = {
+ .read = rtpcs_generic_sds_op_read,
+ .write = rtpcs_generic_sds_op_write,
+};
+
static const struct rtpcs_config rtpcs_931x_cfg = {
.cpu_port = RTPCS_931X_CPU_PORT,
.mac_link_dup_sts = RTPCS_931X_MAC_LINK_DUP_STS,
.mac_tx_pause_sts = RTPCS_931X_MAC_TX_PAUSE_STS,
.serdes_count = RTPCS_931X_SERDES_CNT,
.pcs_ops = &rtpcs_931x_pcs_ops,
+ .sds_ops = &rtpcs_931x_sds_ops,
.set_autoneg = rtpcs_93xx_set_autoneg,
.setup_serdes = rtpcs_931x_setup_serdes,
};