const struct rtpcs_sds_ops *ops;
const struct rtpcs_sds_regs *regs;
enum rtpcs_sds_type type;
+ DECLARE_BITMAP(supported_modes, RTPCS_SDS_MODE_MAX);
struct {
struct regmap_field *mac_mode;
struct regmap_field *mac_mode_force; /* nullable, 931x only */
*hw_mode = RTPCS_SDS_MODE_USXGMII_10GQXGMII;
break;
default:
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
}
- /* TODO: check if the particular SerDes supports the mode */
+ if (!test_bit(*hw_mode, sds->supported_modes))
+ return -EOPNOTSUPP;
return 0;
}
dev_info(sds->ctrl->dev, "SerDes %d reset\n", sds->id);
}
-static bool rtpcs_838x_sds_is_hw_mode_supported(struct rtpcs_serdes *sds,
- enum rtpcs_sds_mode hw_mode)
+static void rtpcs_838x_sds_fill_caps(struct rtpcs_serdes *sds)
{
- switch (sds->id) {
- case 0 ... 3:
- return hw_mode == RTPCS_SDS_MODE_QSGMII;
- case 4:
- return hw_mode == RTPCS_SDS_MODE_QSGMII ||
- hw_mode == RTPCS_SDS_MODE_SGMII ||
- hw_mode == RTPCS_SDS_MODE_1000BASEX;
- case 5:
- return hw_mode == RTPCS_SDS_MODE_SGMII ||
- hw_mode == RTPCS_SDS_MODE_1000BASEX;
- default:
- return false;
+ __set_bit(RTPCS_SDS_MODE_OFF, sds->supported_modes);
+
+ if (sds->id <= 4)
+ __set_bit(RTPCS_SDS_MODE_QSGMII, sds->supported_modes);
+
+ if (sds->id >= 4) {
+ __set_bit(RTPCS_SDS_MODE_SGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_1000BASEX, sds->supported_modes);
}
}
sds->type = RTPCS_SDS_TYPE_5G;
+ rtpcs_838x_sds_fill_caps(sds);
+
/*
* SDS_MODE_SEL packs 5-bit fields in reverse order: SDS 0 at [25:29],
* SDS 5 at [0:4].
{
int ret;
- if (!rtpcs_838x_sds_is_hw_mode_supported(sds, hw_mode))
- return -ENOTSUPP;
-
rtpcs_838x_sds_deactivate(sds);
/* take reset */
rtpcs_sds_write(odd_sds, 0x0, 0x3, 0x7106);
}
+static void rtpcs_839x_sds_fill_caps(struct rtpcs_serdes *sds)
+{
+ __set_bit(RTPCS_SDS_MODE_OFF, sds->supported_modes);
+
+ if (sds->id <= 12)
+ __set_bit(RTPCS_SDS_MODE_QSGMII, sds->supported_modes);
+
+ /* Uncomment this when modes are supported
+ if (sds->id >= 12) {
+ __set_bit(RTPCS_SDS_MODE_SGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_100BASEX, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_1000BASEX, sds->supported_modes);
+ }
+ */
+}
+
static int rtpcs_839x_sds_probe(struct rtpcs_serdes *sds)
{
u8 id = sds->id;
else
sds->type = RTPCS_SDS_TYPE_5G;
+ rtpcs_839x_sds_fill_caps(sds);
+
/*
* This function is quite "mystic". It has been taken over from the vendor SDK function
* rtl839x_serdes_patch_init(). There is not much documentation about it but one could
return rtpcs_sds_write_bits(sds, 0x1f, 0x09, 11, 6, raw << 1 | BIT(0));
}
+static void rtpcs_93xx_sds_fill_caps(struct rtpcs_serdes *sds)
+{
+ __set_bit(RTPCS_SDS_MODE_OFF, sds->supported_modes);
+
+ switch (sds->type) {
+ case RTPCS_SDS_TYPE_5G:
+ __set_bit(RTPCS_SDS_MODE_QSGMII, sds->supported_modes);
+ break;
+ case RTPCS_SDS_TYPE_10G:
+ __set_bit(RTPCS_SDS_MODE_SGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_XSGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_USXGMII_10GSXGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_USXGMII_10GDXGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_USXGMII_10GQXGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_USXGMII_5GSXGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_USXGMII_5GDXGMII, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_USXGMII_2_5GSXGMII, sds->supported_modes);
+
+ __set_bit(RTPCS_SDS_MODE_1000BASEX, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_2500BASEX, sds->supported_modes);
+ __set_bit(RTPCS_SDS_MODE_10GBASER, sds->supported_modes);
+ break;
+ case RTPCS_SDS_TYPE_UNKNOWN:
+ default:
+ break;
+ }
+}
+
/* RTL930X */
/* This mapping is not coherent so it cannot be expressed arithmetically */
else
sds->type = RTPCS_SDS_TYPE_UNKNOWN;
+ rtpcs_93xx_sds_fill_caps(sds);
+
sds->swcore_regs.mac_mode = devm_regmap_field_alloc(dev, map,
rtpcs_930x_mac_mode_fields[id]);
if (IS_ERR(sds->swcore_regs.mac_mode))
else
sds->type = RTPCS_SDS_TYPE_UNKNOWN;
+ rtpcs_93xx_sds_fill_caps(sds);
+
/*
* Width is 7 bits (lsb..lsb+6) so every MAC mode write also clears
* bit 5 (FEC enable) and bit 6 (10G speedup). These are mode-dependent