ipq806x: dwmac: fix GMACs connected via SGMII fixed-link
[openwrt/openwrt.git] / target / linux / ipq806x / patches-5.4 / 100-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch
index 6cdbf4d3dc6bf354cf896a711ed5e94587a96fb2..3c497ead6afc71d816786bd0f05b1559a3271de8 100644 (file)
  #define QSGMII_PCS_CAL_LCKDT_CTL              0x120
  #define QSGMII_PCS_CAL_LCKDT_CTL_RST          BIT(19)
  
-@@ -345,6 +356,12 @@ static int ipq806x_gmac_probe(struct pla
+@@ -241,6 +252,36 @@ static void ipq806x_gmac_fix_mac_speed(v
+       ipq806x_gmac_set_speed(gmac, speed);
+ }
++static int
++ipq806x_gmac_get_qsgmii_pcs_speed_val(struct platform_device *pdev) {
++      struct device_node *fixed_link_node;
++      int rv;
++      int fixed_link_speed;
++
++      if (!of_phy_is_fixed_link(pdev->dev.of_node))
++              return 0;
++
++      fixed_link_node = of_get_child_by_name(pdev->dev.of_node, "fixed-link");
++      if (!fixed_link_node)
++              return -1;
++
++      rv = of_property_read_u32(fixed_link_node, "speed", &fixed_link_speed);
++      of_node_put(fixed_link_node);
++      if (rv)
++              return -1;
++
++      switch (fixed_link_speed) {
++      case SPEED_1000:
++              return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_1000;
++      case SPEED_100:
++              return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_100;
++      case SPEED_10:
++              return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_10;
++      }
++
++      return -1;
++}
++
+ static int ipq806x_gmac_probe(struct platform_device *pdev)
+ {
+       struct plat_stmmacenet_data *plat_dat;
+@@ -249,6 +290,7 @@ static int ipq806x_gmac_probe(struct pla
+       struct ipq806x_gmac *gmac;
+       int val;
+       int err;
++      int qsgmii_pcs_speed;
+       val = stmmac_get_platform_resources(pdev, &stmmac_res);
+       if (val)
+@@ -345,6 +387,17 @@ static int ipq806x_gmac_probe(struct pla
                             0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
                             0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
                             0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
 +
-+              regmap_update_bits(gmac->qsgmii_csr,
-+                                 QSGMII_PCS_ALL_CH_CTL,
-+                                 QSGMII_PCS_CH_SPEED_MASK <<
-+                                  QSGMII_PCS_CH_SPEED_SHIFT(gmac->id),
-+                                 0);
++              qsgmii_pcs_speed = ipq806x_gmac_get_qsgmii_pcs_speed_val(pdev);
++              if (qsgmii_pcs_speed != -1) {
++                      regmap_update_bits(
++                          gmac->qsgmii_csr,
++                          QSGMII_PCS_ALL_CH_CTL,
++                          QSGMII_PCS_CH_SPEED_MASK <<
++                              QSGMII_PCS_CH_SPEED_SHIFT(gmac->id),
++                          qsgmii_pcs_speed <<
++                              QSGMII_PCS_CH_SPEED_SHIFT(gmac->id));
++              }
        }
  
        plat_dat->has_gmac = true;