PROTO_SEL_25G_50G_100G = 0x1a,
};
+enum lynx_lane_mode {
+ LANE_MODE_UNKNOWN,
+ LANE_MODE_1000BASEX_SGMII,
+ LANE_MODE_10GBASER_USXGMII,
+ LANE_MODE_MAX,
+};
+
struct lynx_28g_proto_conf {
/* LNaGCR0 */
int proto_sel;
int smp_autoz_eg1r;
};
-static const struct lynx_28g_proto_conf lynx_28g_proto_conf[PHY_INTERFACE_MODE_MAX] = {
- [PHY_INTERFACE_MODE_SGMII] = {
+static const struct lynx_28g_proto_conf lynx_28g_proto_conf[LANE_MODE_MAX] = {
+ [LANE_MODE_1000BASEX_SGMII] = {
.proto_sel = LNaGCR0_PROTO_SEL_SGMII,
.if_width = LNaGCR0_IF_WIDTH_10_BIT,
.teq_type = EQ_TYPE_NO_EQ,
.smp_autoz_d1r = 0,
.smp_autoz_eg1r = 0,
},
- [PHY_INTERFACE_MODE_1000BASEX] = {
- .proto_sel = LNaGCR0_PROTO_SEL_SGMII,
- .if_width = LNaGCR0_IF_WIDTH_10_BIT,
- .teq_type = EQ_TYPE_NO_EQ,
- .sgn_preq = 1,
- .ratio_preq = 0,
- .sgn_post1q = 1,
- .ratio_post1q = 0,
- .amp_red = 6,
- .adpt_eq = 48,
- .enter_idle_flt_sel = 4,
- .exit_idle_flt_sel = 3,
- .data_lost_th_sel = 1,
- .gk2ovd = 0x1f,
- .gk3ovd = 0,
- .gk4ovd = 0,
- .gk2ovd_en = 1,
- .gk3ovd_en = 1,
- .gk4ovd_en = 0,
- .eq_offset_ovd = 0x1f,
- .eq_offset_ovd_en = 0,
- .eq_offset_rng_dbl = 0,
- .eq_blw_sel = 0,
- .eq_boost = 0,
- .spare_in = 0,
- .smp_autoz_d1r = 0,
- .smp_autoz_eg1r = 0,
- },
- [PHY_INTERFACE_MODE_10GBASER] = {
+ [LANE_MODE_10GBASER_USXGMII] = {
.proto_sel = LNaGCR0_PROTO_SEL_XFI,
.if_width = LNaGCR0_IF_WIDTH_20_BIT,
.teq_type = EQ_TYPE_2TAP,
struct lynx_28g_priv *priv;
u32 rstctl, cr0, cr1;
int id;
- DECLARE_PHY_INTERFACE_MASK(supported);
+ DECLARE_BITMAP(supported, LANE_MODE_MAX);
};
struct lynx_28g_lane {
bool powered_up;
bool init;
unsigned int id;
- phy_interface_t interface;
+ enum lynx_lane_mode mode;
};
struct lynx_28g_priv {
#define lynx_28g_pll_read(pll, reg) \
ioread32((pll)->priv->base + reg((pll)->id))
-static bool lynx_28g_supports_interface(struct lynx_28g_priv *priv, int intf)
+static const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode)
+{
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ return "1000Base-X/SGMII";
+ case LANE_MODE_10GBASER_USXGMII:
+ return "10GBase-R/USXGMII";
+ default:
+ return "unknown";
+ }
+}
+
+static enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf)
+{
+ switch (intf) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ return LANE_MODE_1000BASEX_SGMII;
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_USXGMII:
+ return LANE_MODE_10GBASER_USXGMII;
+ default:
+ return LANE_MODE_UNKNOWN;
+ }
+}
+
+static bool lynx_28g_supports_lane_mode(struct lynx_28g_priv *priv,
+ enum lynx_lane_mode mode)
{
int i;
if (PLLnRSTCTL_DIS(priv->pll[i].rstctl))
continue;
- if (test_bit(intf, priv->pll[i].supported))
+ if (test_bit(mode, priv->pll[i].supported))
return true;
}
}
static struct lynx_28g_pll *lynx_28g_pll_get(struct lynx_28g_priv *priv,
- phy_interface_t intf)
+ enum lynx_lane_mode mode)
{
struct lynx_28g_pll *pll;
int i;
if (PLLnRSTCTL_DIS(pll->rstctl))
continue;
- if (test_bit(intf, pll->supported))
+ if (test_bit(mode, pll->supported))
return pll;
}
/* no pll supports requested mode, either caller forgot to check
* lynx_28g_supports_lane_mode, or this is a bug.
*/
- dev_WARN_ONCE(priv->dev, 1, "no pll for interface %s\n", phy_modes(intf));
+ dev_WARN_ONCE(priv->dev, 1, "no pll for lane mode %s\n",
+ lynx_lane_mode_str(mode));
return NULL;
}
static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane,
struct lynx_28g_pll *pll,
- phy_interface_t intf)
+ enum lynx_lane_mode lane_mode)
{
switch (FIELD_GET(PLLnCR1_FRATE_SEL, pll->cr1)) {
case PLLnCR1_FRATE_5G_10GVCO:
case PLLnCR1_FRATE_5G_25GVCO:
- switch (intf) {
- case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_1000BASEX:
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
lynx_28g_lane_rmw(lane, LNaTGCR0,
FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_QUARTER),
LNaTGCR0_N_RATE);
}
break;
case PLLnCR1_FRATE_10G_20GVCO:
- switch (intf) {
- case PHY_INTERFACE_MODE_10GBASER:
- case PHY_INTERFACE_MODE_USXGMII:
+ switch (lane_mode) {
+ case LANE_MODE_10GBASER_USXGMII:
lynx_28g_lane_rmw(lane, LNaTGCR0,
FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_FULL),
LNaTGCR0_N_RATE);
return 0;
}
-static int lynx_28g_get_pccr(phy_interface_t interface, int lane,
+static int lynx_28g_get_pccr(enum lynx_lane_mode lane_mode, int lane,
struct lynx_pccr *pccr)
{
- switch (interface) {
- case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_1000BASEX:
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
pccr->offset = PCC8;
pccr->width = 4;
pccr->shift = SGMII_CFG(lane);
break;
- case PHY_INTERFACE_MODE_10GBASER:
+ case LANE_MODE_10GBASER_USXGMII:
pccr->offset = PCCC;
pccr->width = 4;
pccr->shift = SXGMII_CFG(lane);
return 0;
}
-static int lynx_28g_get_pcvt_offset(int lane, phy_interface_t interface)
+static int lynx_28g_get_pcvt_offset(int lane, enum lynx_lane_mode lane_mode)
{
- switch (interface) {
- case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_1000BASEX:
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
return SGMIIaCR0(lane);
- case PHY_INTERFACE_MODE_10GBASER:
+ case LANE_MODE_10GBASER_USXGMII:
return SXGMIIaCR0(lane);
default:
return -EOPNOTSUPP;
}
static int lynx_pccr_write(struct lynx_28g_lane *lane,
- phy_interface_t interface, u32 val)
+ enum lynx_lane_mode lane_mode, u32 val)
{
struct lynx_28g_priv *priv = lane->priv;
struct lynx_pccr pccr;
u32 old, tmp, mask;
int err;
- err = lynx_28g_get_pccr(interface, lane->id, &pccr);
+ err = lynx_28g_get_pccr(lane_mode, lane->id, &pccr);
if (err)
return err;
return 0;
}
-static int lynx_pcvt_read(struct lynx_28g_lane *lane, phy_interface_t interface,
- int cr, u32 *val)
+static int lynx_pcvt_read(struct lynx_28g_lane *lane,
+ enum lynx_lane_mode lane_mode, int cr, u32 *val)
{
struct lynx_28g_priv *priv = lane->priv;
int offset;
- offset = lynx_28g_get_pcvt_offset(lane->id, interface);
+ offset = lynx_28g_get_pcvt_offset(lane->id, lane_mode);
if (offset < 0)
return offset;
return 0;
}
-static int lynx_pcvt_write(struct lynx_28g_lane *lane, phy_interface_t interface,
- int cr, u32 val)
+static int lynx_pcvt_write(struct lynx_28g_lane *lane,
+ enum lynx_lane_mode lane_mode, int cr, u32 val)
{
struct lynx_28g_priv *priv = lane->priv;
int offset;
- offset = lynx_28g_get_pcvt_offset(lane->id, interface);
+ offset = lynx_28g_get_pcvt_offset(lane->id, lane_mode);
if (offset < 0)
return offset;
return 0;
}
-static int lynx_pcvt_rmw(struct lynx_28g_lane *lane, phy_interface_t interface,
+static int lynx_pcvt_rmw(struct lynx_28g_lane *lane,
+ enum lynx_lane_mode lane_mode,
int cr, u32 val, u32 mask)
{
int err;
u32 tmp;
- err = lynx_pcvt_read(lane, interface, cr, &tmp);
+ err = lynx_pcvt_read(lane, lane_mode, cr, &tmp);
if (err)
return err;
tmp &= ~mask;
tmp |= val;
- return lynx_pcvt_write(lane, interface, cr, tmp);
+ return lynx_pcvt_write(lane, lane_mode, cr, tmp);
}
static void lynx_28g_lane_remap_pll(struct lynx_28g_lane *lane,
- phy_interface_t interface)
+ enum lynx_lane_mode lane_mode)
{
struct lynx_28g_priv *priv = lane->priv;
struct lynx_28g_pll *pll;
/* Switch to the PLL that works with this interface type */
- pll = lynx_28g_pll_get(priv, interface);
+ pll = lynx_28g_pll_get(priv, lane_mode);
if (unlikely(pll == NULL))
return;
lynx_28g_lane_set_pll(lane, pll);
/* Choose the portion of clock net to be used on this lane */
- lynx_28g_lane_set_nrate(lane, pll, interface);
+ lynx_28g_lane_set_nrate(lane, pll, lane_mode);
}
static void lynx_28g_lane_change_proto_conf(struct lynx_28g_lane *lane,
- phy_interface_t interface)
+ enum lynx_lane_mode lane_mode)
{
- const struct lynx_28g_proto_conf *conf = &lynx_28g_proto_conf[interface];
+ const struct lynx_28g_proto_conf *conf = &lynx_28g_proto_conf[lane_mode];
lynx_28g_lane_rmw(lane, LNaGCR0,
FIELD_PREP(LNaGCR0_PROTO_SEL, conf->proto_sel) |
}
static int lynx_28g_lane_disable_pcvt(struct lynx_28g_lane *lane,
- phy_interface_t interface)
+ enum lynx_lane_mode lane_mode)
{
struct lynx_28g_priv *priv = lane->priv;
int err;
spin_lock(&priv->pcc_lock);
- err = lynx_pccr_write(lane, interface, 0);
+ err = lynx_pccr_write(lane, lane_mode, 0);
if (err)
goto out;
- switch (interface) {
- case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_1000BASEX:
- err = lynx_pcvt_rmw(lane, interface, CR(1), 0,
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ err = lynx_pcvt_rmw(lane, lane_mode, CR(1), 0,
SGMIIaCR1_SGPCS_EN);
break;
default:
}
static int lynx_28g_lane_enable_pcvt(struct lynx_28g_lane *lane,
- phy_interface_t interface)
+ enum lynx_lane_mode lane_mode)
{
struct lynx_28g_priv *priv = lane->priv;
u32 val;
spin_lock(&priv->pcc_lock);
- switch (interface) {
- case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_1000BASEX:
- err = lynx_pcvt_rmw(lane, interface, CR(1), SGMIIaCR1_SGPCS_EN,
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
+ err = lynx_pcvt_rmw(lane, lane_mode, CR(1), SGMIIaCR1_SGPCS_EN,
SGMIIaCR1_SGPCS_EN);
break;
default:
val = 0;
- switch (interface) {
- case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_1000BASEX:
+ switch (lane_mode) {
+ case LANE_MODE_1000BASEX_SGMII:
val |= PCC8_SGMIIa_CFG;
break;
- case PHY_INTERFACE_MODE_10GBASER:
+ case LANE_MODE_10GBASER_USXGMII:
val |= PCCC_SXGMIIn_CFG | PCCC_SXGMIIn_XFI;
break;
default:
break;
}
- err = lynx_pccr_write(lane, interface, val);
+ err = lynx_pccr_write(lane, lane_mode, val);
spin_unlock(&priv->pcc_lock);
struct lynx_28g_lane *lane = phy_get_drvdata(phy);
struct lynx_28g_priv *priv = lane->priv;
int powered_up = lane->powered_up;
+ enum lynx_lane_mode lane_mode;
int err = 0;
if (mode != PHY_MODE_ETHERNET)
return -EOPNOTSUPP;
- if (lane->interface == PHY_INTERFACE_MODE_NA)
+ if (lane->mode == LANE_MODE_UNKNOWN)
return -EOPNOTSUPP;
- if (!lynx_28g_supports_interface(priv, submode))
+ lane_mode = phy_interface_to_lane_mode(submode);
+ if (!lynx_28g_supports_lane_mode(priv, lane_mode))
return -EOPNOTSUPP;
- if (submode == lane->interface)
+ if (lane_mode == lane->mode)
return 0;
/* If the lane is powered up, put the lane into the halt state while
if (powered_up)
lynx_28g_power_off(phy);
- err = lynx_28g_lane_disable_pcvt(lane, lane->interface);
+ err = lynx_28g_lane_disable_pcvt(lane, lane->mode);
if (err)
goto out;
- lynx_28g_lane_change_proto_conf(lane, submode);
- lynx_28g_lane_remap_pll(lane, submode);
- WARN_ON(lynx_28g_lane_enable_pcvt(lane, submode));
+ lynx_28g_lane_change_proto_conf(lane, lane_mode);
+ lynx_28g_lane_remap_pll(lane, lane_mode);
+ WARN_ON(lynx_28g_lane_enable_pcvt(lane, lane_mode));
- lane->interface = submode;
+ lane->mode = lane_mode;
out:
if (powered_up)
{
struct lynx_28g_lane *lane = phy_get_drvdata(phy);
struct lynx_28g_priv *priv = lane->priv;
+ enum lynx_lane_mode lane_mode;
if (mode != PHY_MODE_ETHERNET)
return -EOPNOTSUPP;
- if (!lynx_28g_supports_interface(priv, submode))
+ lane_mode = phy_interface_to_lane_mode(submode);
+ if (!lynx_28g_supports_lane_mode(priv, lane_mode))
return -EOPNOTSUPP;
return 0;
case PLLnCR1_FRATE_5G_10GVCO:
case PLLnCR1_FRATE_5G_25GVCO:
/* 5GHz clock net */
- __set_bit(PHY_INTERFACE_MODE_1000BASEX, pll->supported);
- __set_bit(PHY_INTERFACE_MODE_SGMII, pll->supported);
+ __set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported);
break;
case PLLnCR1_FRATE_10G_20GVCO:
/* 10.3125GHz clock net */
- __set_bit(PHY_INTERFACE_MODE_10GBASER, pll->supported);
+ __set_bit(LANE_MODE_10GBASER_USXGMII, pll->supported);
break;
default:
/* 6GHz, 12.890625GHz, 8GHz */
protocol = FIELD_GET(LNaPSS_TYPE, pss);
switch (protocol) {
case LNaPSS_TYPE_SGMII:
- lane->interface = PHY_INTERFACE_MODE_SGMII;
+ lane->mode = LANE_MODE_1000BASEX_SGMII;
break;
case LNaPSS_TYPE_XFI:
- lane->interface = PHY_INTERFACE_MODE_10GBASER;
+ lane->mode = LANE_MODE_10GBASER_USXGMII;
break;
default:
- lane->interface = PHY_INTERFACE_MODE_NA;
+ lane->mode = LANE_MODE_UNKNOWN;
}
}