|
6 | 6 | #include "sja1105.h" |
7 | 7 |
|
8 | 8 | #define SJA1105_SIZE_CGU_CMD 4 |
| 9 | +#define SJA1110_BASE_TIMER_CLK SJA1110_CGU_ADDR(0x74) |
9 | 10 |
|
10 | 11 | /* Common structure for CFG_PAD_MIIx_RX and CFG_PAD_MIIx_TX */ |
11 | 12 | struct sja1105_cfg_pad_mii { |
@@ -61,6 +62,12 @@ struct sja1105_cgu_pll_ctrl { |
61 | 62 | u64 pd; |
62 | 63 | }; |
63 | 64 |
|
| 65 | +struct sja1110_cgu_outclk { |
| 66 | + u64 clksrc; |
| 67 | + u64 autoblock; |
| 68 | + u64 pd; |
| 69 | +}; |
| 70 | + |
64 | 71 | enum { |
65 | 72 | CLKSRC_MII0_TX_CLK = 0x00, |
66 | 73 | CLKSRC_MII0_RX_CLK = 0x01, |
@@ -461,6 +468,35 @@ sja1105_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd, |
461 | 468 | sja1105_packing(buf, &cmd->txc_pd, 0, 0, size, op); |
462 | 469 | } |
463 | 470 |
|
| 471 | +static void |
| 472 | +sja1110_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd, |
| 473 | + enum packing_op op) |
| 474 | +{ |
| 475 | + const int size = SJA1105_SIZE_CGU_CMD; |
| 476 | + u64 range = 4; |
| 477 | + |
| 478 | + /* Fields RXC_RANGE and TXC_RANGE select the input frequency range: |
| 479 | + * 0 = 2.5MHz |
| 480 | + * 1 = 25MHz |
| 481 | + * 2 = 50MHz |
| 482 | + * 3 = 125MHz |
| 483 | + * 4 = Automatically determined by port speed. |
| 484 | + * There's no point in defining a structure different than the one for |
| 485 | + * SJA1105, so just hardcode the frequency range to automatic, just as |
| 486 | + * before. |
| 487 | + */ |
| 488 | + sja1105_packing(buf, &cmd->rxc_stable_ovr, 26, 26, size, op); |
| 489 | + sja1105_packing(buf, &cmd->rxc_delay, 25, 21, size, op); |
| 490 | + sja1105_packing(buf, &range, 20, 18, size, op); |
| 491 | + sja1105_packing(buf, &cmd->rxc_bypass, 17, 17, size, op); |
| 492 | + sja1105_packing(buf, &cmd->rxc_pd, 16, 16, size, op); |
| 493 | + sja1105_packing(buf, &cmd->txc_stable_ovr, 10, 10, size, op); |
| 494 | + sja1105_packing(buf, &cmd->txc_delay, 9, 5, size, op); |
| 495 | + sja1105_packing(buf, &range, 4, 2, size, op); |
| 496 | + sja1105_packing(buf, &cmd->txc_bypass, 1, 1, size, op); |
| 497 | + sja1105_packing(buf, &cmd->txc_pd, 0, 0, size, op); |
| 498 | +} |
| 499 | + |
464 | 500 | /* Valid range in degrees is an integer between 73.8 and 101.7 */ |
465 | 501 | static u64 sja1105_rgmii_delay(u64 phase) |
466 | 502 | { |
@@ -519,6 +555,35 @@ int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port) |
519 | 555 | packed_buf, SJA1105_SIZE_CGU_CMD); |
520 | 556 | } |
521 | 557 |
|
| 558 | +int sja1110_setup_rgmii_delay(const void *ctx, int port) |
| 559 | +{ |
| 560 | + const struct sja1105_private *priv = ctx; |
| 561 | + const struct sja1105_regs *regs = priv->info->regs; |
| 562 | + struct sja1105_cfg_pad_mii_id pad_mii_id = {0}; |
| 563 | + u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; |
| 564 | + |
| 565 | + pad_mii_id.rxc_pd = 1; |
| 566 | + pad_mii_id.txc_pd = 1; |
| 567 | + |
| 568 | + if (priv->rgmii_rx_delay[port]) { |
| 569 | + pad_mii_id.rxc_delay = sja1105_rgmii_delay(90); |
| 570 | + /* The "BYPASS" bit in SJA1110 is actually a "don't bypass" */ |
| 571 | + pad_mii_id.rxc_bypass = 1; |
| 572 | + pad_mii_id.rxc_pd = 0; |
| 573 | + } |
| 574 | + |
| 575 | + if (priv->rgmii_tx_delay[port]) { |
| 576 | + pad_mii_id.txc_delay = sja1105_rgmii_delay(90); |
| 577 | + pad_mii_id.txc_bypass = 1; |
| 578 | + pad_mii_id.txc_pd = 0; |
| 579 | + } |
| 580 | + |
| 581 | + sja1110_cfg_pad_mii_id_packing(packed_buf, &pad_mii_id, PACK); |
| 582 | + |
| 583 | + return sja1105_xfer_buf(priv, SPI_WRITE, regs->pad_mii_id[port], |
| 584 | + packed_buf, SJA1105_SIZE_CGU_CMD); |
| 585 | +} |
| 586 | + |
522 | 587 | static int sja1105_rgmii_clocking_setup(struct sja1105_private *priv, int port, |
523 | 588 | sja1105_mii_role_t role) |
524 | 589 | { |
@@ -755,3 +820,29 @@ int sja1105_clocking_setup(struct sja1105_private *priv) |
755 | 820 | } |
756 | 821 | return 0; |
757 | 822 | } |
| 823 | + |
| 824 | +static void |
| 825 | +sja1110_cgu_outclk_packing(void *buf, struct sja1110_cgu_outclk *outclk, |
| 826 | + enum packing_op op) |
| 827 | +{ |
| 828 | + const int size = 4; |
| 829 | + |
| 830 | + sja1105_packing(buf, &outclk->clksrc, 27, 24, size, op); |
| 831 | + sja1105_packing(buf, &outclk->autoblock, 11, 11, size, op); |
| 832 | + sja1105_packing(buf, &outclk->pd, 0, 0, size, op); |
| 833 | +} |
| 834 | + |
| 835 | +/* Power down the BASE_TIMER_CLK in order to disable the watchdog */ |
| 836 | +int sja1110_clocking_setup(struct sja1105_private *priv) |
| 837 | +{ |
| 838 | + u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; |
| 839 | + struct sja1110_cgu_outclk outclk_7_c = { |
| 840 | + .clksrc = 0x5, |
| 841 | + .pd = true, |
| 842 | + }; |
| 843 | + |
| 844 | + sja1110_cgu_outclk_packing(packed_buf, &outclk_7_c, PACK); |
| 845 | + |
| 846 | + return sja1105_xfer_buf(priv, SPI_WRITE, SJA1110_BASE_TIMER_CLK, |
| 847 | + packed_buf, SJA1105_SIZE_CGU_CMD); |
| 848 | +} |
0 commit comments