0001
0002
0003
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
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
0040
0041
0042
0043 struct sja1105_cgu_idiv {
0044 u64 clksrc;
0045 u64 autoblock;
0046 u64 idiv;
0047 u64 pd;
0048 };
0049
0050
0051
0052
0053
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
0093
0094
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
0130 idiv.clksrc = 0x0A;
0131 idiv.autoblock = 1;
0132 idiv.idiv = factor - 1;
0133 idiv.pd = enabled ? 0 : 1;
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
0182 mii_tx_clk.clksrc = clksrc;
0183 mii_tx_clk.autoblock = 1;
0184 mii_tx_clk.pd = 0;
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
0209 mii_rx_clk.clksrc = clk_sources[port];
0210 mii_rx_clk.autoblock = 1;
0211 mii_rx_clk.pd = 0;
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
0236 mii_ext_tx_clk.clksrc = clk_sources[port];
0237 mii_ext_tx_clk.autoblock = 1;
0238 mii_ext_tx_clk.pd = 0;
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
0263 mii_ext_rx_clk.clksrc = clk_sources[port];
0264 mii_ext_rx_clk.autoblock = 1;
0265 mii_ext_rx_clk.pd = 0;
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
0281
0282
0283 rc = sja1105_cgu_idiv_config(priv, port, (role == XMII_PHY), 1);
0284 if (rc < 0)
0285 return rc;
0286
0287
0288
0289
0290
0291 rc = sja1105_cgu_mii_tx_clk_config(priv, port, role);
0292 if (rc < 0)
0293 return rc;
0294
0295
0296
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
0304
0305
0306
0307
0308 rc = sja1105_cgu_mii_ext_tx_clk_config(priv, port);
0309 if (rc < 0)
0310 return rc;
0311
0312
0313
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
0358 txc.clksrc = clksrc;
0359
0360 txc.autoblock = 1;
0361
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
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
0401 pad_mii_tx.d32_os = 3;
0402
0403 pad_mii_tx.d10_os = 3;
0404
0405 pad_mii_tx.d32_ipud = 2;
0406
0407 pad_mii_tx.d10_ipud = 2;
0408
0409 pad_mii_tx.ctrl_os = 3;
0410 pad_mii_tx.ctrl_ipud = 2;
0411 pad_mii_tx.clk_os = 3;
0412 pad_mii_tx.clk_ih = 0;
0413 pad_mii_tx.clk_ipud = 2;
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
0430 pad_mii_rx.d32_ih = 0;
0431
0432 pad_mii_rx.d32_ipud = 2;
0433
0434 pad_mii_rx.d10_ih = 0;
0435
0436 pad_mii_rx.d10_ipud = 2;
0437
0438 pad_mii_rx.ctrl_ih = 0;
0439
0440
0441 pad_mii_rx.ctrl_ipud = 3;
0442
0443
0444 pad_mii_rx.clk_os = 2;
0445
0446 pad_mii_rx.clk_ih = 0;
0447
0448 pad_mii_rx.clk_ipud = 2;
0449
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
0480
0481
0482
0483
0484
0485
0486
0487
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
0502
0503
0504
0505
0506
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
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
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
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
0597 rc = sja1105_cgu_idiv_config(priv, port, false, 1);
0598 } else if (speed == priv->info->port_speed[SJA1105_SPEED_100MBPS]) {
0599
0600 rc = sja1105_cgu_idiv_config(priv, port, true, 1);
0601 } else if (speed == priv->info->port_speed[SJA1105_SPEED_10MBPS]) {
0602
0603 rc = sja1105_cgu_idiv_config(priv, port, true, 10);
0604 } else if (speed == priv->info->port_speed[SJA1105_SPEED_AUTO]) {
0605
0606
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
0653 ref_clk.clksrc = clk_sources[port];
0654 ref_clk.autoblock = 1;
0655 ref_clk.pd = 0;
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
0673 ext_tx_clk.clksrc = CLKSRC_PLL1;
0674 ext_tx_clk.autoblock = 1;
0675 ext_tx_clk.pd = 0;
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
0694
0695
0696
0697
0698
0699
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
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
0739 if (role == XMII_MAC) {
0740
0741 rc = sja1105_cgu_rmii_pll_config(priv);
0742 if (rc < 0)
0743 return rc;
0744 }
0745
0746 rc = sja1105_cgu_idiv_config(priv, port, false, 1);
0747 if (rc < 0)
0748 return rc;
0749
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
0772 phy_mode = mii->xmii_mode[port];
0773
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
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
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
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
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 }