[PATCH net-next 7/7] net: dsa: mediatek: support EN751221 switch
Caleb James DeLisle
cjd at cjdns.fr
Wed Sep 9 07:03:46 PDT 2026
The EcoNet EN751221 has either one, or two, onboard MT7530 switches.
Every implementation of this SoC has one switch on die with the CPU,
but some chips - notably those with a "G" in the name, have a second
MT7530 as an MCM module.
The on-die MT7530 has 4 FE ports and 1 GE port. The MCM switch has all
gigabit ports.
The MCM switch connects to the SoC switch via a TRGMII link from port
5 on the SoC switch to port 6 on the MCM switch. This link undergoes
calibration on startup.
All known devices with the MCM present do not make any use of the ports
on the on-die switch, it is put into "passthrough" mode in which all
traffic is shuttled between port 6 and port 5 without alteration of the
DSA tags.
Add support for both the on-die and the MCM switch, and calibration of
the TRGMII link between them.
Signed-off-by: Caleb James DeLisle <cjd at cjdns.fr>
---
drivers/net/dsa/mt7530-mdio.c | 1 +
drivers/net/dsa/mt7530-mmio.c | 1 +
drivers/net/dsa/mt7530.c | 335 +++++++++++++++++++++++++++++++++-
drivers/net/dsa/mt7530.h | 24 +++
4 files changed, 357 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/mt7530-mdio.c b/drivers/net/dsa/mt7530-mdio.c
index 24ef54f3db2a..2fd987ff8510 100644
--- a/drivers/net/dsa/mt7530-mdio.c
+++ b/drivers/net/dsa/mt7530-mdio.c
@@ -139,6 +139,7 @@ mt7531_create_sgmii(struct mt7530_priv *priv)
}
static const struct of_device_id mt7530_of_match[] = {
+ { .compatible = "econet,en751221", .data = &mt753x_table[ID_EN751221_EXT], },
{ .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
{ .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
{ .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
diff --git a/drivers/net/dsa/mt7530-mmio.c b/drivers/net/dsa/mt7530-mmio.c
index 29fbd0fc50d1..1a29b1eefb2c 100644
--- a/drivers/net/dsa/mt7530-mmio.c
+++ b/drivers/net/dsa/mt7530-mmio.c
@@ -12,6 +12,7 @@
static const struct of_device_id mt7988_of_match[] = {
{ .compatible = "airoha,an7583-switch", .data = &mt753x_table[ID_AN7583], },
{ .compatible = "airoha,en7581-switch", .data = &mt753x_table[ID_EN7581], },
+ { .compatible = "econet,en751221-switch", .data = &mt753x_table[ID_EN751221], },
{ .compatible = "econet,en7528-switch", .data = &mt753x_table[ID_EN7528], },
{ .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], },
{ /* sentinel */ }
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 0c0c5358b8b8..6fd4719aab89 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -49,6 +49,9 @@ static const struct mt7530_mib_desc mt7530_mib[] = {
static int
mt753x_ctrl_phy_addr(struct mt7530_priv *priv)
{
+ if (priv->id == ID_EN751221)
+ return 12;
+
if (WARN_ON_ONCE(!priv->mdiodev))
return 0;
@@ -344,12 +347,19 @@ mt7530_setup_port6(struct dsa_switch *ds, phy_interface_t interface)
regmap_read(priv->regmap, MT753X_MTRAP, &xtal);
xtal &= MT7530_XTAL_MASK;
+ /* EN751221 on-die does not report clock speed in MTRAP */
+ if (priv->id == ID_EN751221)
+ xtal = MT7530_XTAL_25MHZ;
+
if (xtal == MT7530_XTAL_25MHZ)
ssc_delta = 0x57;
else
ssc_delta = 0x87;
- if (priv->id == ID_MT7621) {
+ if (priv->id == ID_EN751221_EXT || priv->id == ID_EN751221) {
+ /* PLL frequency: 362.5Mhz */
+ ncpo1 = 0x1d00;
+ } else if (priv->id == ID_MT7621) {
/* PLL frequency: 125MHz: 1.0GBit */
if (xtal == MT7530_XTAL_40MHZ)
ncpo1 = 0x0640;
@@ -466,6 +476,251 @@ mt7531_pll_setup(struct mt7530_priv *priv)
usleep_range(25, 35);
}
+static bool
+en751221_trgmii_cal_ok(struct mt7530_priv *rx, u32 reg, int chan, int i)
+{
+ u32 val = 0;
+
+ regmap_read(rx->regmap, reg, &val);
+ regmap_write(rx->regmap, reg, val | EDGE_CHK);
+ regmap_write(rx->regmap, reg, val & ~EDGE_CHK);
+ regmap_read(rx->regmap, reg, &val);
+
+ return FIELD_GET(RD_VALUE_MASK, val) == TGMII_TD_PAT &&
+ !FIELD_GET(RD_ERR_MASK, val);
+}
+
+static void
+en751221_trgmii_calibrate_direction(struct mt7530_priv *tx,
+ struct mt7530_priv *rx,
+ u8 *default_taps)
+{
+ int channel;
+
+ regmap_set_bits(tx->regmap, MT7530_TRGMII_TXCTRL, TRAIN_TXEN);
+
+ /* Put fail pattern on every channel */
+ for (channel = 0; channel < NUM_TRGMII_CTRL; channel++)
+ regmap_update_bits(tx->regmap, EN7530_TRGMII_TD_CTRL(channel),
+ TGMII_TD_PAT_MASK,
+ FIELD_PREP(TGMII_TD_PAT_MASK,
+ TGMII_TD_FAIL_PAT));
+
+ for (channel = 0; channel < NUM_TRGMII_CTRL; channel++) {
+ u32 rx_reg = MT7530_TRGMII_RD(channel);
+ int best_tap = -1, best_range = -1;
+ int first = -1;
+ u8 dac;
+ char log[TD_TAP_MAX + 1];
+
+ /* Put test pattern on correct channel */
+ regmap_update_bits(tx->regmap, EN7530_TRGMII_TD_CTRL(channel),
+ TGMII_TD_PAT_MASK,
+ FIELD_PREP(TGMII_TD_PAT_MASK, TGMII_TD_PAT));
+
+ for (dac = 0; dac < TD_TAP_MAX; dac++) {
+ /* Set TAP */
+ regmap_update_bits(rx->regmap, rx_reg, RD_TAP_MASK,
+ RD_TAP(dac));
+
+ /* Check if we can get a good read */
+ if (en751221_trgmii_cal_ok(rx, rx_reg, channel, dac)) {
+ log[dac] = '+';
+
+ if (first < 0)
+ first = dac;
+
+ if ((dac - first) > best_range) {
+ best_tap = (first + dac) / 2;
+ best_range = dac - first;
+ }
+ } else {
+ log[dac] = '.';
+ first = -1;
+ }
+ }
+
+ log[TD_TAP_MAX] = '\0';
+
+ if (best_tap > -1) {
+ regmap_update_bits(rx->regmap, rx_reg, RD_TAP_MASK,
+ RD_TAP(best_tap));
+
+ log[best_tap] = 'X';
+
+ dev_info(rx->dev,
+ "TRGMII lane %d: %s tap %d old %d\n",
+ channel, log, best_tap, default_taps[channel]);
+ } else {
+ regmap_update_bits(rx->regmap, rx_reg, RD_TAP_MASK,
+ RD_TAP(default_taps[channel]));
+
+ dev_warn(rx->dev,
+ "TRGMII lane %d: %s calibration failed, preserving tap %u\n",
+ channel, log, default_taps[channel]);
+ }
+
+ /* Return channel to failure pattern */
+ regmap_update_bits(tx->regmap, EN7530_TRGMII_TD_CTRL(channel),
+ TGMII_TD_PAT_MASK,
+ FIELD_PREP(TGMII_TD_PAT_MASK,
+ TGMII_TD_FAIL_PAT));
+ }
+
+ regmap_clear_bits(tx->regmap, MT7530_TRGMII_TXCTRL, TRAIN_TXEN);
+}
+
+static void
+en751221_set_tx_drive(struct mt7530_priv *priv, u8 drvp, u8 drvn, u8 clk_drvp,
+ u8 clk_drvn)
+{
+ int channel;
+
+ /* Tx driving for TRGMII path on SoC */
+ for (channel = 0; channel < NUM_TRGMII_CTRL; channel++)
+ regmap_write(priv->regmap, MT7530_TRGMII_TD_ODT(channel),
+ TD_DM_DRVP(drvp) | TD_DM_DRVN(drvn));
+
+ /* Undocumented 6th channel, probably drive strength for clock line. */
+ regmap_write(priv->regmap, MT7530_TRGMII_TD_ODT(5), TD_DM_DRVP(drvp) |
+ TD_DM_DRVN(drvn));
+}
+
+static void
+en751221_trgmii_pair_setup(struct mt7530_priv *ext, int ext_port,
+ struct mt7530_priv *ondie, int ondie_port)
+{
+ u8 default_taps_ondie[NUM_TRGMII_CTRL];
+ u8 default_taps_ext[NUM_TRGMII_CTRL];
+ u32 mcr_down, mcr_up;
+ int channel;
+ int reg_val;
+
+ /* BOTH: Put interfaces in a downed state */
+ mcr_down = PMCR_IFG_XMIT(PMCR_IFG_XMIT_64) | PMCR_MAC_MODE |
+ MT7530_FORCE_MODE | PMCR_MAC_RX_EN | PMCR_BACKOFF_EN |
+ PMCR_BACKPR_EN | PMCR_FORCE_SPEED_1000 | PMCR_FORCE_FDX;
+ regmap_write(ondie->regmap, MT753X_PMCR_P(ondie_port), mcr_down);
+ regmap_write(ext->regmap, MT753X_PMCR_P(ext_port), mcr_down);
+ usleep_range(5000, 6000);
+
+ /* BOTH: Reset TX */
+ regmap_set_bits(ext->regmap, MT7530_TRGMII_TXCTRL, TX_RST);
+ regmap_set_bits(ondie->regmap, MT7530_TRGMII_TXCTRL, TX_RST);
+ usleep_range(5000, 6000);
+ regmap_clear_bits(ext->regmap, MT7530_TRGMII_TXCTRL, TX_RST);
+ regmap_clear_bits(ondie->regmap, MT7530_TRGMII_TXCTRL, TX_RST);
+
+ /* BOTH: Reset RX controllers down */
+ regmap_set_bits(ext->regmap, MT7530_TRGMII_RCK_CTRL, RX_RST);
+ regmap_set_bits(ondie->regmap, MT7530_TRGMII_RCK_CTRL, RX_RST);
+
+ /* BOTH: Set TX drive strength, MCM uses more */
+ en751221_set_tx_drive(ondie, 8, 8, 7, 7);
+ en751221_set_tx_drive(ext, 11, 11, 16, 16);
+
+ /* BOTH: Reset RX controllers up */
+ regmap_clear_bits(ext->regmap, MT7530_TRGMII_RCK_CTRL, RX_RST);
+ regmap_clear_bits(ondie->regmap, MT7530_TRGMII_RCK_CTRL, RX_RST);
+
+ /* BOTH: Ports up */
+ mcr_up = mcr_down | PMCR_MAC_TX_EN | PMCR_FORCE_LNK;
+ regmap_write(ondie->regmap, MT753X_PMCR_P(ondie_port), mcr_up);
+ regmap_write(ext->regmap, MT753X_PMCR_P(ext_port), mcr_up);
+
+ /* MCM: Set Ext->SoC TX delay to 0 */
+ for (channel = 0; channel < NUM_TRGMII_CTRL; channel++)
+ regmap_clear_bits(ext->regmap, EN7530_TRGMII_TD_CTRL(channel),
+ TGMII_TD_TAP_MASK);
+
+ /* SOC: ODT */
+ regmap_set_bits(ondie->regmap, MT7530_TRGMII_RCK_RTT,
+ DQS1_GATE | DQS0_GATE | EN751221_B17);
+
+ /* SOC: Undocumented */
+ for (channel = 0; channel < NUM_TRGMII_CTRL; channel++)
+ regmap_write(ondie->regmap, (0x7a14 + channel * 8),
+ 0x3227700);
+
+ /* MCM: Spread spectrum clock*/
+ core_clear(ext, CORE_PLL_GROUP8, RG_LCDDS_SSC_EN);
+
+ /* BOTH: Zero clock delay */
+ regmap_clear_bits(ext->regmap, MT7530_TRGMII_RCK_CTRL,
+ DQSI0_TAP_MASK);
+ regmap_clear_bits(ondie->regmap, MT7530_TRGMII_RCK_CTRL,
+ DQSI0_TAP_MASK);
+
+ /* BOTH: Collect and then zero every RX TAP */
+ for (channel = 0; channel < NUM_TRGMII_CTRL; channel++) {
+ reg_val = 0;
+ regmap_read(ext->regmap, MT7530_TRGMII_RD(channel), ®_val);
+ default_taps_ext[channel] = FIELD_GET(RD_TAP_MASK, reg_val);
+ regmap_clear_bits(ext->regmap, MT7530_TRGMII_RD(channel),
+ RD_TAP_MASK);
+
+ reg_val = 0;
+ regmap_read(ondie->regmap, MT7530_TRGMII_RD(channel), ®_val);
+ default_taps_ondie[channel] = FIELD_GET(RD_TAP_MASK, reg_val);
+ regmap_clear_bits(ondie->regmap, MT7530_TRGMII_RD(channel),
+ RD_TAP_MASK);
+ }
+
+ en751221_trgmii_calibrate_direction(ondie, ext, default_taps_ext);
+ en751221_trgmii_calibrate_direction(ext, ondie, default_taps_ext);
+
+ dev_info(ondie->dev, "TRGMII inter-switch link initialized\n");
+}
+
+static void
+mt7530_cal_interswitch_trgmii(struct dsa_port *dp)
+{
+ struct dsa_switch *ds = dp->ds;
+ struct dsa_switch *peer_ds;
+ struct dsa_port *peer_dp;
+ struct mt7530_priv *peer;
+ struct mt7530_priv *priv;
+ struct dsa_link *dl;
+ u32 pmsr = 0;
+
+ priv = ds->priv;
+
+ if (priv->id != ID_EN751221_EXT)
+ return;
+
+ if (dp->type != DSA_PORT_TYPE_DSA)
+ return;
+
+ regmap_read(priv->regmap, MT7530_PMSR_P(dp->index), &pmsr);
+
+ if (!(pmsr & PMSR_LINK))
+ return;
+
+ list_for_each_entry(dl, &ds->dst->rtable, list) {
+ if (dl->dp != dp)
+ continue;
+
+ peer_dp = dl->link_dp;
+
+ if (peer_dp->type != DSA_PORT_TYPE_DSA)
+ continue;
+
+ peer_ds = dl->link_dp->ds;
+
+ if (!of_device_is_compatible(peer_ds->dev->of_node,
+ "econet,en751221-switch"))
+ continue;
+
+ peer = peer_ds->priv;
+
+ if (peer->id != ID_EN751221)
+ continue;
+
+ en751221_trgmii_pair_setup(priv, dp->index, peer,
+ peer_dp->index);
+ }
+}
+
static void
mt7530_mib_reset(struct dsa_switch *ds)
{
@@ -1408,7 +1663,8 @@ mt7530_port_enable(struct dsa_switch *ds, int port,
mutex_unlock(&priv->reg_mutex);
- if (priv->id != ID_MT7530 && priv->id != ID_MT7621)
+ if (priv->id != ID_MT7530 && priv->id != ID_MT7621 &&
+ priv->id != ID_EN751221 && priv->id != ID_EN751221_EXT)
return 0;
if (port == 5)
@@ -1435,7 +1691,8 @@ mt7530_port_disable(struct dsa_switch *ds, int port)
mutex_unlock(&priv->reg_mutex);
- if (priv->id != ID_MT7530 && priv->id != ID_MT7621)
+ if (priv->id != ID_MT7530 && priv->id != ID_MT7621 &&
+ priv->id != ID_EN751221 && priv->id != ID_EN751221_EXT)
return;
/* Do not set MT7530_P5_DIS when port 5 is being used for PHY muxing. */
@@ -2563,6 +2820,12 @@ mt7530_setup(struct dsa_switch *ds)
MT7530_CHG_TRAP | MT7530_PHY_INDIRECT_ACCESS,
MT7530_CHG_TRAP);
+ /* EN751221 MCM starts on the wrong frequency */
+ if (priv->id == ID_EN751221_EXT)
+ regmap_update_bits(priv->regmap, MT753X_MTRAP,
+ MT7530_CHG_TRAP | MT7530_CK_SEL,
+ MT7530_CHG_TRAP);
+
if ((val & MT7530_XTAL_MASK) == MT7530_XTAL_40MHZ)
mt7530_pll_setup(priv);
@@ -2983,6 +3246,44 @@ static void en7528_mac_port_get_caps(struct dsa_switch *ds, int port,
}
}
+static void en751221_mac_port_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config)
+{
+ switch (port) {
+ /* EN751221 ports 0..3 are connected to the integrated FE PHYs. */
+ case 0 ... 3:
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+
+ config->mac_capabilities |= MAC_10 | MAC_100;
+ break;
+
+ /* Port 4 is connected to the standalone EN7512/EN7521 GPHY. */
+ case 4:
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+
+ config->mac_capabilities |= MAC_10 | MAC_100 | MAC_1000FD;
+ break;
+
+ /* Port 5 is the 1 Gbit/s TRGMII cascade to the external MT7530. */
+ case 5:
+ __set_bit(PHY_INTERFACE_MODE_TRGMII,
+ config->supported_interfaces);
+
+ config->mac_capabilities |= MAC_1000FD;
+ break;
+
+ /* Port 6 is the 1 Gbit/s CPU link to GDM1. */
+ case 6:
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+
+ config->mac_capabilities |= MAC_1000FD;
+ break;
+ }
+}
+
static void
mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
phy_interface_t interface)
@@ -3132,6 +3433,9 @@ static void mt753x_phylink_mac_link_up(struct phylink_config *config,
}
regmap_set_bits(priv->regmap, MT753X_PMCR_P(dp->index), mcr);
+
+ if (interface == PHY_INTERFACE_MODE_TRGMII)
+ mt7530_cal_interswitch_trgmii(dp);
}
static void mt753x_phylink_mac_disable_tx_lpi(struct phylink_config *config)
@@ -3374,7 +3678,8 @@ mt753x_conduit_state_change(struct dsa_switch *ds,
* interface is up. NOTE: "CPU port" can also mean an upstream DSA link.
*/
if (priv->id != ID_MT7530 && priv->id != ID_MT7621 &&
- priv->id != ID_EN7528)
+ priv->id != ID_EN7528 && priv->id != ID_EN751221 &&
+ priv->id != ID_EN751221_EXT)
return;
mask = BIT(cpu_dp->index);
@@ -3662,6 +3967,28 @@ const struct mt753x_info mt753x_table[] = {
.phy_write_c45 = mt7531_ind_c45_phy_write,
.mac_port_get_caps = en7528_mac_port_get_caps,
},
+ [ID_EN751221] = {
+ .id = ID_EN751221,
+ .pcs_ops = &mt7530_pcs_ops,
+ .sw_setup = mt7988_setup,
+ .phy_read_c22 = mt7531_ind_c22_phy_read,
+ .phy_write_c22 = mt7531_ind_c22_phy_write,
+ .phy_read_c45 = mt7531_ind_c45_phy_read,
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
+ .mac_port_get_caps = en751221_mac_port_get_caps,
+ .mac_port_config = mt7530_mac_config,
+ },
+ [ID_EN751221_EXT] = {
+ .id = ID_EN751221_EXT,
+ .pcs_ops = &mt7530_pcs_ops,
+ .sw_setup = mt7530_setup,
+ .phy_read_c22 = mt7530_phy_read_c22,
+ .phy_write_c22 = mt7530_phy_write_c22,
+ .phy_read_c45 = mt7530_phy_read_c45,
+ .phy_write_c45 = mt7530_phy_write_c45,
+ .mac_port_get_caps = mt7530_mac_port_get_caps,
+ .mac_port_config = mt7530_mac_config,
+ },
};
EXPORT_SYMBOL_GPL(mt753x_table);
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index c86bc4bca29b..1a4329749c0f 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -24,6 +24,8 @@ enum mt753x_id {
ID_EN7581 = 4,
ID_AN7583 = 5,
ID_EN7528 = 6,
+ ID_EN751221 = 7,
+ ID_EN751221_EXT = 8,
};
#define NUM_TRGMII_CTRL 5
@@ -356,6 +358,9 @@ enum mt7530_vlan_port_acc_frm {
#define MT753X_PMCR_P(x) (0x3000 + ((x) * 0x100))
#define PMCR_IFG_XMIT_MASK GENMASK(19, 18)
#define PMCR_IFG_XMIT(x) FIELD_PREP(PMCR_IFG_XMIT_MASK, x)
+#define PMCR_IFG_XMIT_96 0
+#define PMCR_IFG_XMIT_RAND 1
+#define PMCR_IFG_XMIT_64 2
#define PMCR_EXT_PHY BIT(17)
#define PMCR_MAC_MODE BIT(16)
#define MT7530_FORCE_MODE BIT(15)
@@ -584,6 +589,7 @@ enum mt7531_clk_skew {
#define MT753X_MTRAP 0x7804
#define MT7530_P5_PHY0_SEL BIT(20)
#define MT7530_CHG_TRAP BIT(16)
+#define MT7530_CK_SEL BIT(15)
#define MT7530_LOOP_DET_DISABLE BIT(14)
#define MT7530_P5_MAC_SEL BIT(13)
#define MT7530_P6_DIS BIT(8)
@@ -601,6 +607,8 @@ enum mt7531_xtal_fsel {
/* Register for TOP signal control */
#define MT7530_TOP_SIG_CTRL 0x7808
#define TOP_SIG_CTRL_NORMAL (BIT(17) | BIT(16))
+/* Undocumented */
+#define TOP_SIG_CTRL_B0 BIT(0)
#define MT7531_TOP_SIG_SR 0x780c
#define PAD_DUAL_SGMII_EN BIT(1)
@@ -647,18 +655,31 @@ enum mt7531_xtal_fsel {
#define MT7530_TRGMII_RCK_RTT 0x7a04
#define DQS1_GATE BIT(31)
#define DQS0_GATE BIT(30)
+/* Undocumented */
+#define EN751221_B17 BIT(17)
#define MT7530_TRGMII_RD(x) (0x7a10 + (x) * 8)
#define BSLIP_EN BIT(31)
#define EDGE_CHK BIT(30)
+#define RD_VALUE_MASK GENMASK(23, 16)
+#define RD_ERR_MASK GENMASK(11, 8)
#define RD_TAP_MASK GENMASK(6, 0)
#define RD_TAP(x) FIELD_PREP(RD_TAP_MASK, x)
+/* Training does not try anything beyond this */
+#define TD_TAP_MAX 64
#define MT7530_TRGMII_TXCTRL 0x7a40
#define TRAIN_TXEN BIT(31)
#define TXC_INV BIT(30)
#define TX_RST BIT(28)
+#define EN7530_TRGMII_TD_CTRL(x) (0x7a50 + (x) * 8)
+#define TGMII_TD_TAP_MASK GENMASK(11, 8)
+#define TGMII_TD_PAT_MASK GENMASK(7, 0)
+/* Use a 01010101 bit pattern */
+#define TGMII_TD_PAT 0x55
+#define TGMII_TD_FAIL_PAT 0xaa
+
#define MT7530_TRGMII_TD_ODT(i) (0x7a54 + 8 * (i))
#define TD_DM_DRVP_MASK GENMASK(3, 0)
#define TD_DM_DRVP(x) FIELD_PREP(TD_DM_DRVP_MASK, x)
@@ -764,6 +785,9 @@ enum mt7531_xtal_fsel {
#define RG_LCCDS_C(x) FIELD_PREP(RG_LCCDS_C_MASK, x)
#define RG_LCDDS_PCW_NCPO_CHG BIT(3)
+#define CORE_PLL_GROUP8 0x407
+#define RG_LCDDS_SSC_EN BIT(10)
+
#define CORE_PLL_GROUP10 0x409
#define RG_LCDDS_SSC_DELTA_MASK GENMASK(11, 0)
#define RG_LCDDS_SSC_DELTA(x) FIELD_PREP(RG_LCDDS_SSC_DELTA_MASK, x)
--
2.39.5
More information about the Linux-mediatek
mailing list