Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause
0002 /* Copyright 2016-2018 NXP
0003  * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
0004  */
0005 #include <linux/packing.h>
0006 #include "sja1105.h"
0007 
0008 #define SJA1105_SIZE_CGU_CMD    4
0009 #define SJA1110_BASE_MCSS_CLK   SJA1110_CGU_ADDR(0x70)
0010 #define SJA1110_BASE_TIMER_CLK  SJA1110_CGU_ADDR(0x74)
0011 
0012 /* Common structure for CFG_PAD_MIIx_RX and CFG_PAD_MIIx_TX */
0013 struct sja1105_cfg_pad_mii {
0014     u64 d32_os;
0015     u64 d32_ih;
0016     u64 d32_ipud;
0017     u64 d10_ih;
0018     u64 d10_os;
0019     u64 d10_ipud;
0020     u64 ctrl_os;
0021     u64 ctrl_ih;
0022     u64 ctrl_ipud;
0023     u64 clk_os;
0024     u64 clk_ih;
0025     u64 clk_ipud;
0026 };
0027 
0028 struct sja1105_cfg_pad_mii_id {
0029     u64 rxc_stable_ovr;
0030     u64 rxc_delay;
0031     u64 rxc_bypass;
0032     u64 rxc_pd;
0033     u64 txc_stable_ovr;
0034     u64 txc_delay;
0035     u64 txc_bypass;
0036     u64 txc_pd;
0037 };
0038 
0039 /* UM10944 Table 82.
0040  * IDIV_0_C to IDIV_4_C control registers
0041  * (addr. 10000Bh to 10000Fh)
0042  */
0043 struct sja1105_cgu_idiv {
0044     u64 clksrc;
0045     u64 autoblock;
0046     u64 idiv;
0047     u64 pd;
0048 };
0049 
0050 /* PLL_1_C control register
0051  *
0052  * SJA1105 E/T: UM10944 Table 81 (address 10000Ah)
0053  * SJA1105 P/Q/R/S: UM11040 Table 116 (address 10000Ah)
0054  */
0055 struct sja1105_cgu_pll_ctrl {
0056     u64 pllclksrc;
0057     u64 msel;
0058     u64 autoblock;
0059     u64 psel;
0060     u64 direct;
0061     u64 fbsel;
0062     u64 bypass;
0063     u64 pd;
0064 };
0065 
0066 struct sja1110_cgu_outclk {
0067     u64 clksrc;
0068     u64 autoblock;
0069     u64 pd;
0070 };
0071 
0072 enum {
0073     CLKSRC_MII0_TX_CLK  = 0x00,
0074     CLKSRC_MII0_RX_CLK  = 0x01,
0075     CLKSRC_MII1_TX_CLK  = 0x02,
0076     CLKSRC_MII1_RX_CLK  = 0x03,
0077     CLKSRC_MII2_TX_CLK  = 0x04,
0078     CLKSRC_MII2_RX_CLK  = 0x05,
0079     CLKSRC_MII3_TX_CLK  = 0x06,
0080     CLKSRC_MII3_RX_CLK  = 0x07,
0081     CLKSRC_MII4_TX_CLK  = 0x08,
0082     CLKSRC_MII4_RX_CLK  = 0x09,
0083     CLKSRC_PLL0     = 0x0B,
0084     CLKSRC_PLL1     = 0x0E,
0085     CLKSRC_IDIV0        = 0x11,
0086     CLKSRC_IDIV1        = 0x12,
0087     CLKSRC_IDIV2        = 0x13,
0088     CLKSRC_IDIV3        = 0x14,
0089     CLKSRC_IDIV4        = 0x15,
0090 };
0091 
0092 /* UM10944 Table 83.
0093  * MIIx clock control registers 1 to 30
0094  * (addresses 100013h to 100035h)
0095  */
0096 struct sja1105_cgu_mii_ctrl {
0097     u64 clksrc;
0098     u64 autoblock;
0099     u64 pd;
0100 };
0101 
0102 static void sja1105_cgu_idiv_packing(void *buf, struct sja1105_cgu_idiv *idiv,
0103                      enum packing_op op)
0104 {
0105     const int size = 4;
0106 
0107     sja1105_packing(buf, &idiv->clksrc,    28, 24, size, op);
0108     sja1105_packing(buf, &idiv->autoblock, 11, 11, size, op);
0109     sja1105_packing(buf, &idiv->idiv,       5,  2, size, op);
0110     sja1105_packing(buf, &idiv->pd,         0,  0, size, op);
0111 }
0112 
0113 static int sja1105_cgu_idiv_config(struct sja1105_private *priv, int port,
0114                    bool enabled, int factor)
0115 {
0116     const struct sja1105_regs *regs = priv->info->regs;
0117     struct device *dev = priv->ds->dev;
0118     struct sja1105_cgu_idiv idiv;
0119     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0120 
0121     if (regs->cgu_idiv[port] == SJA1105_RSV_ADDR)
0122         return 0;
0123 
0124     if (enabled && factor != 1 && factor != 10) {
0125         dev_err(dev, "idiv factor must be 1 or 10\n");
0126         return -ERANGE;
0127     }
0128 
0129     /* Payload for packed_buf */
0130     idiv.clksrc    = 0x0A;            /* 25MHz */
0131     idiv.autoblock = 1;               /* Block clk automatically */
0132     idiv.idiv      = factor - 1;      /* Divide by 1 or 10 */
0133     idiv.pd        = enabled ? 0 : 1; /* Power down? */
0134     sja1105_cgu_idiv_packing(packed_buf, &idiv, PACK);
0135 
0136     return sja1105_xfer_buf(priv, SPI_WRITE, regs->cgu_idiv[port],
0137                 packed_buf, SJA1105_SIZE_CGU_CMD);
0138 }
0139 
0140 static void
0141 sja1105_cgu_mii_control_packing(void *buf, struct sja1105_cgu_mii_ctrl *cmd,
0142                 enum packing_op op)
0143 {
0144     const int size = 4;
0145 
0146     sja1105_packing(buf, &cmd->clksrc,    28, 24, size, op);
0147     sja1105_packing(buf, &cmd->autoblock, 11, 11, size, op);
0148     sja1105_packing(buf, &cmd->pd,         0,  0, size, op);
0149 }
0150 
0151 static int sja1105_cgu_mii_tx_clk_config(struct sja1105_private *priv,
0152                      int port, sja1105_mii_role_t role)
0153 {
0154     const struct sja1105_regs *regs = priv->info->regs;
0155     struct sja1105_cgu_mii_ctrl mii_tx_clk;
0156     const int mac_clk_sources[] = {
0157         CLKSRC_MII0_TX_CLK,
0158         CLKSRC_MII1_TX_CLK,
0159         CLKSRC_MII2_TX_CLK,
0160         CLKSRC_MII3_TX_CLK,
0161         CLKSRC_MII4_TX_CLK,
0162     };
0163     const int phy_clk_sources[] = {
0164         CLKSRC_IDIV0,
0165         CLKSRC_IDIV1,
0166         CLKSRC_IDIV2,
0167         CLKSRC_IDIV3,
0168         CLKSRC_IDIV4,
0169     };
0170     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0171     int clksrc;
0172 
0173     if (regs->mii_tx_clk[port] == SJA1105_RSV_ADDR)
0174         return 0;
0175 
0176     if (role == XMII_MAC)
0177         clksrc = mac_clk_sources[port];
0178     else
0179         clksrc = phy_clk_sources[port];
0180 
0181     /* Payload for packed_buf */
0182     mii_tx_clk.clksrc    = clksrc;
0183     mii_tx_clk.autoblock = 1;  /* Autoblock clk while changing clksrc */
0184     mii_tx_clk.pd        = 0;  /* Power Down off => enabled */
0185     sja1105_cgu_mii_control_packing(packed_buf, &mii_tx_clk, PACK);
0186 
0187     return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_tx_clk[port],
0188                 packed_buf, SJA1105_SIZE_CGU_CMD);
0189 }
0190 
0191 static int
0192 sja1105_cgu_mii_rx_clk_config(struct sja1105_private *priv, int port)
0193 {
0194     const struct sja1105_regs *regs = priv->info->regs;
0195     struct sja1105_cgu_mii_ctrl mii_rx_clk;
0196     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0197     const int clk_sources[] = {
0198         CLKSRC_MII0_RX_CLK,
0199         CLKSRC_MII1_RX_CLK,
0200         CLKSRC_MII2_RX_CLK,
0201         CLKSRC_MII3_RX_CLK,
0202         CLKSRC_MII4_RX_CLK,
0203     };
0204 
0205     if (regs->mii_rx_clk[port] == SJA1105_RSV_ADDR)
0206         return 0;
0207 
0208     /* Payload for packed_buf */
0209     mii_rx_clk.clksrc    = clk_sources[port];
0210     mii_rx_clk.autoblock = 1;  /* Autoblock clk while changing clksrc */
0211     mii_rx_clk.pd        = 0;  /* Power Down off => enabled */
0212     sja1105_cgu_mii_control_packing(packed_buf, &mii_rx_clk, PACK);
0213 
0214     return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_rx_clk[port],
0215                 packed_buf, SJA1105_SIZE_CGU_CMD);
0216 }
0217 
0218 static int
0219 sja1105_cgu_mii_ext_tx_clk_config(struct sja1105_private *priv, int port)
0220 {
0221     const struct sja1105_regs *regs = priv->info->regs;
0222     struct sja1105_cgu_mii_ctrl mii_ext_tx_clk;
0223     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0224     const int clk_sources[] = {
0225         CLKSRC_IDIV0,
0226         CLKSRC_IDIV1,
0227         CLKSRC_IDIV2,
0228         CLKSRC_IDIV3,
0229         CLKSRC_IDIV4,
0230     };
0231 
0232     if (regs->mii_ext_tx_clk[port] == SJA1105_RSV_ADDR)
0233         return 0;
0234 
0235     /* Payload for packed_buf */
0236     mii_ext_tx_clk.clksrc    = clk_sources[port];
0237     mii_ext_tx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */
0238     mii_ext_tx_clk.pd        = 0; /* Power Down off => enabled */
0239     sja1105_cgu_mii_control_packing(packed_buf, &mii_ext_tx_clk, PACK);
0240 
0241     return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_ext_tx_clk[port],
0242                 packed_buf, SJA1105_SIZE_CGU_CMD);
0243 }
0244 
0245 static int
0246 sja1105_cgu_mii_ext_rx_clk_config(struct sja1105_private *priv, int port)
0247 {
0248     const struct sja1105_regs *regs = priv->info->regs;
0249     struct sja1105_cgu_mii_ctrl mii_ext_rx_clk;
0250     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0251     const int clk_sources[] = {
0252         CLKSRC_IDIV0,
0253         CLKSRC_IDIV1,
0254         CLKSRC_IDIV2,
0255         CLKSRC_IDIV3,
0256         CLKSRC_IDIV4,
0257     };
0258 
0259     if (regs->mii_ext_rx_clk[port] == SJA1105_RSV_ADDR)
0260         return 0;
0261 
0262     /* Payload for packed_buf */
0263     mii_ext_rx_clk.clksrc    = clk_sources[port];
0264     mii_ext_rx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */
0265     mii_ext_rx_clk.pd        = 0; /* Power Down off => enabled */
0266     sja1105_cgu_mii_control_packing(packed_buf, &mii_ext_rx_clk, PACK);
0267 
0268     return sja1105_xfer_buf(priv, SPI_WRITE, regs->mii_ext_rx_clk[port],
0269                 packed_buf, SJA1105_SIZE_CGU_CMD);
0270 }
0271 
0272 static int sja1105_mii_clocking_setup(struct sja1105_private *priv, int port,
0273                       sja1105_mii_role_t role)
0274 {
0275     struct device *dev = priv->ds->dev;
0276     int rc;
0277 
0278     dev_dbg(dev, "Configuring MII-%s clocking\n",
0279         (role == XMII_MAC) ? "MAC" : "PHY");
0280     /* If role is MAC, disable IDIV
0281      * If role is PHY, enable IDIV and configure for 1/1 divider
0282      */
0283     rc = sja1105_cgu_idiv_config(priv, port, (role == XMII_PHY), 1);
0284     if (rc < 0)
0285         return rc;
0286 
0287     /* Configure CLKSRC of MII_TX_CLK_n
0288      *   * If role is MAC, select TX_CLK_n
0289      *   * If role is PHY, select IDIV_n
0290      */
0291     rc = sja1105_cgu_mii_tx_clk_config(priv, port, role);
0292     if (rc < 0)
0293         return rc;
0294 
0295     /* Configure CLKSRC of MII_RX_CLK_n
0296      * Select RX_CLK_n
0297      */
0298     rc = sja1105_cgu_mii_rx_clk_config(priv, port);
0299     if (rc < 0)
0300         return rc;
0301 
0302     if (role == XMII_PHY) {
0303         /* Per MII spec, the PHY (which is us) drives the TX_CLK pin */
0304 
0305         /* Configure CLKSRC of EXT_TX_CLK_n
0306          * Select IDIV_n
0307          */
0308         rc = sja1105_cgu_mii_ext_tx_clk_config(priv, port);
0309         if (rc < 0)
0310             return rc;
0311 
0312         /* Configure CLKSRC of EXT_RX_CLK_n
0313          * Select IDIV_n
0314          */
0315         rc = sja1105_cgu_mii_ext_rx_clk_config(priv, port);
0316         if (rc < 0)
0317             return rc;
0318     }
0319     return 0;
0320 }
0321 
0322 static void
0323 sja1105_cgu_pll_control_packing(void *buf, struct sja1105_cgu_pll_ctrl *cmd,
0324                 enum packing_op op)
0325 {
0326     const int size = 4;
0327 
0328     sja1105_packing(buf, &cmd->pllclksrc, 28, 24, size, op);
0329     sja1105_packing(buf, &cmd->msel,      23, 16, size, op);
0330     sja1105_packing(buf, &cmd->autoblock, 11, 11, size, op);
0331     sja1105_packing(buf, &cmd->psel,       9,  8, size, op);
0332     sja1105_packing(buf, &cmd->direct,     7,  7, size, op);
0333     sja1105_packing(buf, &cmd->fbsel,      6,  6, size, op);
0334     sja1105_packing(buf, &cmd->bypass,     1,  1, size, op);
0335     sja1105_packing(buf, &cmd->pd,         0,  0, size, op);
0336 }
0337 
0338 static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv,
0339                        int port, u64 speed)
0340 {
0341     const struct sja1105_regs *regs = priv->info->regs;
0342     struct sja1105_cgu_mii_ctrl txc;
0343     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0344     int clksrc;
0345 
0346     if (regs->rgmii_tx_clk[port] == SJA1105_RSV_ADDR)
0347         return 0;
0348 
0349     if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) {
0350         clksrc = CLKSRC_PLL0;
0351     } else {
0352         int clk_sources[] = {CLKSRC_IDIV0, CLKSRC_IDIV1, CLKSRC_IDIV2,
0353                      CLKSRC_IDIV3, CLKSRC_IDIV4};
0354         clksrc = clk_sources[port];
0355     }
0356 
0357     /* RGMII: 125MHz for 1000, 25MHz for 100, 2.5MHz for 10 */
0358     txc.clksrc = clksrc;
0359     /* Autoblock clk while changing clksrc */
0360     txc.autoblock = 1;
0361     /* Power Down off => enabled */
0362     txc.pd = 0;
0363     sja1105_cgu_mii_control_packing(packed_buf, &txc, PACK);
0364 
0365     return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgmii_tx_clk[port],
0366                 packed_buf, SJA1105_SIZE_CGU_CMD);
0367 }
0368 
0369 /* AGU */
0370 static void
0371 sja1105_cfg_pad_mii_packing(void *buf, struct sja1105_cfg_pad_mii *cmd,
0372                 enum packing_op op)
0373 {
0374     const int size = 4;
0375 
0376     sja1105_packing(buf, &cmd->d32_os,   28, 27, size, op);
0377     sja1105_packing(buf, &cmd->d32_ih,   26, 26, size, op);
0378     sja1105_packing(buf, &cmd->d32_ipud, 25, 24, size, op);
0379     sja1105_packing(buf, &cmd->d10_os,   20, 19, size, op);
0380     sja1105_packing(buf, &cmd->d10_ih,   18, 18, size, op);
0381     sja1105_packing(buf, &cmd->d10_ipud, 17, 16, size, op);
0382     sja1105_packing(buf, &cmd->ctrl_os,  12, 11, size, op);
0383     sja1105_packing(buf, &cmd->ctrl_ih,  10, 10, size, op);
0384     sja1105_packing(buf, &cmd->ctrl_ipud, 9,  8, size, op);
0385     sja1105_packing(buf, &cmd->clk_os,    4,  3, size, op);
0386     sja1105_packing(buf, &cmd->clk_ih,    2,  2, size, op);
0387     sja1105_packing(buf, &cmd->clk_ipud,  1,  0, size, op);
0388 }
0389 
0390 static int sja1105_rgmii_cfg_pad_tx_config(struct sja1105_private *priv,
0391                        int port)
0392 {
0393     const struct sja1105_regs *regs = priv->info->regs;
0394     struct sja1105_cfg_pad_mii pad_mii_tx = {0};
0395     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0396 
0397     if (regs->pad_mii_tx[port] == SJA1105_RSV_ADDR)
0398         return 0;
0399 
0400     /* Payload */
0401     pad_mii_tx.d32_os    = 3; /* TXD[3:2] output stage: */
0402                   /*          high noise/high speed */
0403     pad_mii_tx.d10_os    = 3; /* TXD[1:0] output stage: */
0404                   /*          high noise/high speed */
0405     pad_mii_tx.d32_ipud  = 2; /* TXD[3:2] input stage: */
0406                   /*          plain input (default) */
0407     pad_mii_tx.d10_ipud  = 2; /* TXD[1:0] input stage: */
0408                   /*          plain input (default) */
0409     pad_mii_tx.ctrl_os   = 3; /* TX_CTL / TX_ER output stage */
0410     pad_mii_tx.ctrl_ipud = 2; /* TX_CTL / TX_ER input stage (default) */
0411     pad_mii_tx.clk_os    = 3; /* TX_CLK output stage */
0412     pad_mii_tx.clk_ih    = 0; /* TX_CLK input hysteresis (default) */
0413     pad_mii_tx.clk_ipud  = 2; /* TX_CLK input stage (default) */
0414     sja1105_cfg_pad_mii_packing(packed_buf, &pad_mii_tx, PACK);
0415 
0416     return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_tx[port],
0417                 packed_buf, SJA1105_SIZE_CGU_CMD);
0418 }
0419 
0420 static int sja1105_cfg_pad_rx_config(struct sja1105_private *priv, int port)
0421 {
0422     const struct sja1105_regs *regs = priv->info->regs;
0423     struct sja1105_cfg_pad_mii pad_mii_rx = {0};
0424     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0425 
0426     if (regs->pad_mii_rx[port] == SJA1105_RSV_ADDR)
0427         return 0;
0428 
0429     /* Payload */
0430     pad_mii_rx.d32_ih    = 0; /* RXD[3:2] input stage hysteresis: */
0431                   /*          non-Schmitt (default) */
0432     pad_mii_rx.d32_ipud  = 2; /* RXD[3:2] input weak pull-up/down */
0433                   /*          plain input (default) */
0434     pad_mii_rx.d10_ih    = 0; /* RXD[1:0] input stage hysteresis: */
0435                   /*          non-Schmitt (default) */
0436     pad_mii_rx.d10_ipud  = 2; /* RXD[1:0] input weak pull-up/down */
0437                   /*          plain input (default) */
0438     pad_mii_rx.ctrl_ih   = 0; /* RX_DV/CRS_DV/RX_CTL and RX_ER */
0439                   /* input stage hysteresis: */
0440                   /* non-Schmitt (default) */
0441     pad_mii_rx.ctrl_ipud = 3; /* RX_DV/CRS_DV/RX_CTL and RX_ER */
0442                   /* input stage weak pull-up/down: */
0443                   /* pull-down */
0444     pad_mii_rx.clk_os    = 2; /* RX_CLK/RXC output stage: */
0445                   /* medium noise/fast speed (default) */
0446     pad_mii_rx.clk_ih    = 0; /* RX_CLK/RXC input hysteresis: */
0447                   /* non-Schmitt (default) */
0448     pad_mii_rx.clk_ipud  = 2; /* RX_CLK/RXC input pull-up/down: */
0449                   /* plain input (default) */
0450     sja1105_cfg_pad_mii_packing(packed_buf, &pad_mii_rx, PACK);
0451 
0452     return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_rx[port],
0453                 packed_buf, SJA1105_SIZE_CGU_CMD);
0454 }
0455 
0456 static void
0457 sja1105_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd,
0458                    enum packing_op op)
0459 {
0460     const int size = SJA1105_SIZE_CGU_CMD;
0461 
0462     sja1105_packing(buf, &cmd->rxc_stable_ovr, 15, 15, size, op);
0463     sja1105_packing(buf, &cmd->rxc_delay,      14, 10, size, op);
0464     sja1105_packing(buf, &cmd->rxc_bypass,      9,  9, size, op);
0465     sja1105_packing(buf, &cmd->rxc_pd,          8,  8, size, op);
0466     sja1105_packing(buf, &cmd->txc_stable_ovr,  7,  7, size, op);
0467     sja1105_packing(buf, &cmd->txc_delay,       6,  2, size, op);
0468     sja1105_packing(buf, &cmd->txc_bypass,      1,  1, size, op);
0469     sja1105_packing(buf, &cmd->txc_pd,          0,  0, size, op);
0470 }
0471 
0472 static void
0473 sja1110_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd,
0474                    enum packing_op op)
0475 {
0476     const int size = SJA1105_SIZE_CGU_CMD;
0477     u64 range = 4;
0478 
0479     /* Fields RXC_RANGE and TXC_RANGE select the input frequency range:
0480      * 0 = 2.5MHz
0481      * 1 = 25MHz
0482      * 2 = 50MHz
0483      * 3 = 125MHz
0484      * 4 = Automatically determined by port speed.
0485      * There's no point in defining a structure different than the one for
0486      * SJA1105, so just hardcode the frequency range to automatic, just as
0487      * before.
0488      */
0489     sja1105_packing(buf, &cmd->rxc_stable_ovr, 26, 26, size, op);
0490     sja1105_packing(buf, &cmd->rxc_delay,      25, 21, size, op);
0491     sja1105_packing(buf, &range,               20, 18, size, op);
0492     sja1105_packing(buf, &cmd->rxc_bypass,     17, 17, size, op);
0493     sja1105_packing(buf, &cmd->rxc_pd,         16, 16, size, op);
0494     sja1105_packing(buf, &cmd->txc_stable_ovr, 10, 10, size, op);
0495     sja1105_packing(buf, &cmd->txc_delay,       9,  5, size, op);
0496     sja1105_packing(buf, &range,                4,  2, size, op);
0497     sja1105_packing(buf, &cmd->txc_bypass,      1,  1, size, op);
0498     sja1105_packing(buf, &cmd->txc_pd,          0,  0, size, op);
0499 }
0500 
0501 /* The RGMII delay setup procedure is 2-step and gets called upon each
0502  * .phylink_mac_config. Both are strategic.
0503  * The reason is that the RX Tunable Delay Line of the SJA1105 MAC has issues
0504  * with recovering from a frequency change of the link partner's RGMII clock.
0505  * The easiest way to recover from this is to temporarily power down the TDL,
0506  * as it will re-lock at the new frequency afterwards.
0507  */
0508 int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port)
0509 {
0510     const struct sja1105_private *priv = ctx;
0511     const struct sja1105_regs *regs = priv->info->regs;
0512     struct sja1105_cfg_pad_mii_id pad_mii_id = {0};
0513     int rx_delay = priv->rgmii_rx_delay_ps[port];
0514     int tx_delay = priv->rgmii_tx_delay_ps[port];
0515     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0516     int rc;
0517 
0518     if (rx_delay)
0519         pad_mii_id.rxc_delay = SJA1105_RGMII_DELAY_PS_TO_HW(rx_delay);
0520     if (tx_delay)
0521         pad_mii_id.txc_delay = SJA1105_RGMII_DELAY_PS_TO_HW(tx_delay);
0522 
0523     /* Stage 1: Turn the RGMII delay lines off. */
0524     pad_mii_id.rxc_bypass = 1;
0525     pad_mii_id.rxc_pd = 1;
0526     pad_mii_id.txc_bypass = 1;
0527     pad_mii_id.txc_pd = 1;
0528     sja1105_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK);
0529 
0530     rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port],
0531                   packed_buf, SJA1105_SIZE_CGU_CMD);
0532     if (rc < 0)
0533         return rc;
0534 
0535     /* Stage 2: Turn the RGMII delay lines on. */
0536     if (rx_delay) {
0537         pad_mii_id.rxc_bypass = 0;
0538         pad_mii_id.rxc_pd = 0;
0539     }
0540     if (tx_delay) {
0541         pad_mii_id.txc_bypass = 0;
0542         pad_mii_id.txc_pd = 0;
0543     }
0544     sja1105_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK);
0545 
0546     return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port],
0547                 packed_buf, SJA1105_SIZE_CGU_CMD);
0548 }
0549 
0550 int sja1110_setup_rgmii_delay(const void *ctx, int port)
0551 {
0552     const struct sja1105_private *priv = ctx;
0553     const struct sja1105_regs *regs = priv->info->regs;
0554     struct sja1105_cfg_pad_mii_id pad_mii_id = {0};
0555     int rx_delay = priv->rgmii_rx_delay_ps[port];
0556     int tx_delay = priv->rgmii_tx_delay_ps[port];
0557     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0558 
0559     pad_mii_id.rxc_pd = 1;
0560     pad_mii_id.txc_pd = 1;
0561 
0562     if (rx_delay) {
0563         pad_mii_id.rxc_delay = SJA1105_RGMII_DELAY_PS_TO_HW(rx_delay);
0564         /* The "BYPASS" bit in SJA1110 is actually a "don't bypass" */
0565         pad_mii_id.rxc_bypass = 1;
0566         pad_mii_id.rxc_pd = 0;
0567     }
0568 
0569     if (tx_delay) {
0570         pad_mii_id.txc_delay = SJA1105_RGMII_DELAY_PS_TO_HW(tx_delay);
0571         pad_mii_id.txc_bypass = 1;
0572         pad_mii_id.txc_pd = 0;
0573     }
0574 
0575     sja1110_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK);
0576 
0577     return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port],
0578                 packed_buf, SJA1105_SIZE_CGU_CMD);
0579 }
0580 
0581 static int sja1105_rgmii_clocking_setup(struct sja1105_private *priv, int port,
0582                     sja1105_mii_role_t role)
0583 {
0584     struct device *dev = priv->ds->dev;
0585     struct sja1105_mac_config_entry *mac;
0586     u64 speed;
0587     int rc;
0588 
0589     mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
0590     speed = mac[port].speed;
0591 
0592     dev_dbg(dev, "Configuring port %d RGMII at speed %lldMbps\n",
0593         port, speed);
0594 
0595     if (speed == priv->info->port_speed[SJA1105_SPEED_1000MBPS]) {
0596         /* 1000Mbps, IDIV disabled (125 MHz) */
0597         rc = sja1105_cgu_idiv_config(priv, port, false, 1);
0598     } else if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) {
0599         /* 100Mbps, IDIV enabled, divide by 1 (25 MHz) */
0600         rc = sja1105_cgu_idiv_config(priv, port, true, 1);
0601     } else if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) {
0602         /* 10Mbps, IDIV enabled, divide by 10 (2.5 MHz) */
0603         rc = sja1105_cgu_idiv_config(priv, port, true, 10);
0604     } else if (speed == priv->info->port_speed[SJA1105_SPEED_AUTO]) {
0605         /* Skip CGU configuration if there is no speed available
0606          * (e.g. link is not established yet)
0607          */
0608         dev_dbg(dev, "Speed not available, skipping CGU config\n");
0609         return 0;
0610     } else {
0611         rc = -EINVAL;
0612     }
0613 
0614     if (rc < 0) {
0615         dev_err(dev, "Failed to configure idiv\n");
0616         return rc;
0617     }
0618     rc = sja1105_cgu_rgmii_tx_clk_config(priv, port, speed);
0619     if (rc < 0) {
0620         dev_err(dev, "Failed to configure RGMII Tx clock\n");
0621         return rc;
0622     }
0623     rc = sja1105_rgmii_cfg_pad_tx_config(priv, port);
0624     if (rc < 0) {
0625         dev_err(dev, "Failed to configure Tx pad registers\n");
0626         return rc;
0627     }
0628 
0629     if (!priv->info->setup_rgmii_delay)
0630         return 0;
0631 
0632     return priv->info->setup_rgmii_delay(priv, port);
0633 }
0634 
0635 static int sja1105_cgu_rmii_ref_clk_config(struct sja1105_private *priv,
0636                        int port)
0637 {
0638     const struct sja1105_regs *regs = priv->info->regs;
0639     struct sja1105_cgu_mii_ctrl ref_clk;
0640     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0641     const int clk_sources[] = {
0642         CLKSRC_MII0_TX_CLK,
0643         CLKSRC_MII1_TX_CLK,
0644         CLKSRC_MII2_TX_CLK,
0645         CLKSRC_MII3_TX_CLK,
0646         CLKSRC_MII4_TX_CLK,
0647     };
0648 
0649     if (regs->rmii_ref_clk[port] == SJA1105_RSV_ADDR)
0650         return 0;
0651 
0652     /* Payload for packed_buf */
0653     ref_clk.clksrc    = clk_sources[port];
0654     ref_clk.autoblock = 1;      /* Autoblock clk while changing clksrc */
0655     ref_clk.pd        = 0;      /* Power Down off => enabled */
0656     sja1105_cgu_mii_control_packing(packed_buf, &ref_clk, PACK);
0657 
0658     return sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_ref_clk[port],
0659                 packed_buf, SJA1105_SIZE_CGU_CMD);
0660 }
0661 
0662 static int
0663 sja1105_cgu_rmii_ext_tx_clk_config(struct sja1105_private *priv, int port)
0664 {
0665     const struct sja1105_regs *regs = priv->info->regs;
0666     struct sja1105_cgu_mii_ctrl ext_tx_clk;
0667     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0668 
0669     if (regs->rmii_ext_tx_clk[port] == SJA1105_RSV_ADDR)
0670         return 0;
0671 
0672     /* Payload for packed_buf */
0673     ext_tx_clk.clksrc    = CLKSRC_PLL1;
0674     ext_tx_clk.autoblock = 1;   /* Autoblock clk while changing clksrc */
0675     ext_tx_clk.pd        = 0;   /* Power Down off => enabled */
0676     sja1105_cgu_mii_control_packing(packed_buf, &ext_tx_clk, PACK);
0677 
0678     return sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_ext_tx_clk[port],
0679                 packed_buf, SJA1105_SIZE_CGU_CMD);
0680 }
0681 
0682 static int sja1105_cgu_rmii_pll_config(struct sja1105_private *priv)
0683 {
0684     const struct sja1105_regs *regs = priv->info->regs;
0685     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0686     struct sja1105_cgu_pll_ctrl pll = {0};
0687     struct device *dev = priv->ds->dev;
0688     int rc;
0689 
0690     if (regs->rmii_pll1 == SJA1105_RSV_ADDR)
0691         return 0;
0692 
0693     /* PLL1 must be enabled and output 50 Mhz.
0694      * This is done by writing first 0x0A010941 to
0695      * the PLL_1_C register and then deasserting
0696      * power down (PD) 0x0A010940.
0697      */
0698 
0699     /* Step 1: PLL1 setup for 50Mhz */
0700     pll.pllclksrc = 0xA;
0701     pll.msel      = 0x1;
0702     pll.autoblock = 0x1;
0703     pll.psel      = 0x1;
0704     pll.direct    = 0x0;
0705     pll.fbsel     = 0x1;
0706     pll.bypass    = 0x0;
0707     pll.pd        = 0x1;
0708 
0709     sja1105_cgu_pll_control_packing(packed_buf, &pll, PACK);
0710     rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_pll1, packed_buf,
0711                   SJA1105_SIZE_CGU_CMD);
0712     if (rc < 0) {
0713         dev_err(dev, "failed to configure PLL1 for 50MHz\n");
0714         return rc;
0715     }
0716 
0717     /* Step 2: Enable PLL1 */
0718     pll.pd = 0x0;
0719 
0720     sja1105_cgu_pll_control_packing(packed_buf, &pll, PACK);
0721     rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->rmii_pll1, packed_buf,
0722                   SJA1105_SIZE_CGU_CMD);
0723     if (rc < 0) {
0724         dev_err(dev, "failed to enable PLL1\n");
0725         return rc;
0726     }
0727     return rc;
0728 }
0729 
0730 static int sja1105_rmii_clocking_setup(struct sja1105_private *priv, int port,
0731                        sja1105_mii_role_t role)
0732 {
0733     struct device *dev = priv->ds->dev;
0734     int rc;
0735 
0736     dev_dbg(dev, "Configuring RMII-%s clocking\n",
0737         (role == XMII_MAC) ? "MAC" : "PHY");
0738     /* AH1601.pdf chapter 2.5.1. Sources */
0739     if (role == XMII_MAC) {
0740         /* Configure and enable PLL1 for 50Mhz output */
0741         rc = sja1105_cgu_rmii_pll_config(priv);
0742         if (rc < 0)
0743             return rc;
0744     }
0745     /* Disable IDIV for this port */
0746     rc = sja1105_cgu_idiv_config(priv, port, false, 1);
0747     if (rc < 0)
0748         return rc;
0749     /* Source to sink mappings */
0750     rc = sja1105_cgu_rmii_ref_clk_config(priv, port);
0751     if (rc < 0)
0752         return rc;
0753     if (role == XMII_MAC) {
0754         rc = sja1105_cgu_rmii_ext_tx_clk_config(priv, port);
0755         if (rc < 0)
0756             return rc;
0757     }
0758     return 0;
0759 }
0760 
0761 int sja1105_clocking_setup_port(struct sja1105_private *priv, int port)
0762 {
0763     struct sja1105_xmii_params_entry *mii;
0764     struct device *dev = priv->ds->dev;
0765     sja1105_phy_interface_t phy_mode;
0766     sja1105_mii_role_t role;
0767     int rc;
0768 
0769     mii = priv->static_config.tables[BLK_IDX_XMII_PARAMS].entries;
0770 
0771     /* RGMII etc */
0772     phy_mode = mii->xmii_mode[port];
0773     /* MAC or PHY, for applicable types (not RGMII) */
0774     role = mii->phy_mac[port];
0775 
0776     switch (phy_mode) {
0777     case XMII_MODE_MII:
0778         rc = sja1105_mii_clocking_setup(priv, port, role);
0779         break;
0780     case XMII_MODE_RMII:
0781         rc = sja1105_rmii_clocking_setup(priv, port, role);
0782         break;
0783     case XMII_MODE_RGMII:
0784         rc = sja1105_rgmii_clocking_setup(priv, port, role);
0785         break;
0786     case XMII_MODE_SGMII:
0787         /* Nothing to do in the CGU for SGMII */
0788         rc = 0;
0789         break;
0790     default:
0791         dev_err(dev, "Invalid interface mode specified: %d\n",
0792             phy_mode);
0793         return -EINVAL;
0794     }
0795     if (rc) {
0796         dev_err(dev, "Clocking setup for port %d failed: %d\n",
0797             port, rc);
0798         return rc;
0799     }
0800 
0801     /* Internally pull down the RX_DV/CRS_DV/RX_CTL and RX_ER inputs */
0802     return sja1105_cfg_pad_rx_config(priv, port);
0803 }
0804 
0805 int sja1105_clocking_setup(struct sja1105_private *priv)
0806 {
0807     struct dsa_switch *ds = priv->ds;
0808     int port, rc;
0809 
0810     for (port = 0; port < ds->num_ports; port++) {
0811         rc = sja1105_clocking_setup_port(priv, port);
0812         if (rc < 0)
0813             return rc;
0814     }
0815     return 0;
0816 }
0817 
0818 static void
0819 sja1110_cgu_outclk_packing(void *buf, struct sja1110_cgu_outclk *outclk,
0820                enum packing_op op)
0821 {
0822     const int size = 4;
0823 
0824     sja1105_packing(buf, &outclk->clksrc,    27, 24, size, op);
0825     sja1105_packing(buf, &outclk->autoblock, 11, 11, size, op);
0826     sja1105_packing(buf, &outclk->pd,         0,  0, size, op);
0827 }
0828 
0829 int sja1110_disable_microcontroller(struct sja1105_private *priv)
0830 {
0831     u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
0832     struct sja1110_cgu_outclk outclk_6_c = {
0833         .clksrc = 0x3,
0834         .pd = true,
0835     };
0836     struct sja1110_cgu_outclk outclk_7_c = {
0837         .clksrc = 0x5,
0838         .pd = true,
0839     };
0840     int rc;
0841 
0842     /* Power down the BASE_TIMER_CLK to disable the watchdog timer */
0843     sja1110_cgu_outclk_packing(packed_buf, &outclk_7_c, PACK);
0844 
0845     rc = sja1105_xfer_buf(priv, SPI_WRITE, SJA1110_BASE_TIMER_CLK,
0846                   packed_buf, SJA1105_SIZE_CGU_CMD);
0847     if (rc)
0848         return rc;
0849 
0850     /* Power down the BASE_MCSS_CLOCK to gate the microcontroller off */
0851     sja1110_cgu_outclk_packing(packed_buf, &outclk_6_c, PACK);
0852 
0853     return sja1105_xfer_buf(priv, SPI_WRITE, SJA1110_BASE_MCSS_CLK,
0854                 packed_buf, SJA1105_SIZE_CGU_CMD);
0855 }