hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
....@@ -1,17 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * dwmac-sun8i.c - Allwinner sun8i DWMAC specific glue layer
34 *
45 * Copyright (C) 2017 Corentin Labbe <clabbe.montjoie@gmail.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
156 */
167
178 #include <linux/clk.h>
....@@ -149,6 +140,20 @@
149140 .tx_delay_max = 7,
150141 };
151142
143
+static const struct emac_variant emac_variant_h6 = {
144
+ .default_syscon_value = 0x50000,
145
+ .syscon_field = &sun8i_syscon_reg_field,
146
+ /* The "Internal PHY" of H6 is not on the die. It's on the
147
+ * co-packaged AC200 chip instead.
148
+ */
149
+ .soc_has_internal_phy = false,
150
+ .support_mii = true,
151
+ .support_rmii = true,
152
+ .support_rgmii = true,
153
+ .rx_delay_max = 31,
154
+ .tx_delay_max = 7,
155
+};
156
+
152157 #define EMAC_BASIC_CTL0 0x00
153158 #define EMAC_BASIC_CTL1 0x04
154159 #define EMAC_INT_STA 0x08
....@@ -189,7 +194,7 @@
189194
190195 /* Used in RX_CTL1*/
191196 #define EMAC_RX_MD BIT(1)
192
-#define EMAC_RX_TH_MASK GENMASK(4, 5)
197
+#define EMAC_RX_TH_MASK GENMASK(5, 4)
193198 #define EMAC_RX_TH_32 0
194199 #define EMAC_RX_TH_64 (0x1 << 4)
195200 #define EMAC_RX_TH_96 (0x2 << 4)
....@@ -200,7 +205,7 @@
200205 /* Used in TX_CTL1*/
201206 #define EMAC_TX_MD BIT(1)
202207 #define EMAC_TX_NEXT_FRM BIT(2)
203
-#define EMAC_TX_TH_MASK GENMASK(8, 10)
208
+#define EMAC_TX_TH_MASK GENMASK(10, 8)
204209 #define EMAC_TX_TH_64 0
205210 #define EMAC_TX_TH_128 (0x1 << 8)
206211 #define EMAC_TX_TH_192 (0x2 << 8)
....@@ -286,18 +291,18 @@
286291
287292 static void sun8i_dwmac_dma_init_rx(void __iomem *ioaddr,
288293 struct stmmac_dma_cfg *dma_cfg,
289
- u32 dma_rx_phy, u32 chan)
294
+ dma_addr_t dma_rx_phy, u32 chan)
290295 {
291296 /* Write RX descriptors address */
292
- writel(dma_rx_phy, ioaddr + EMAC_RX_DESC_LIST);
297
+ writel(lower_32_bits(dma_rx_phy), ioaddr + EMAC_RX_DESC_LIST);
293298 }
294299
295300 static void sun8i_dwmac_dma_init_tx(void __iomem *ioaddr,
296301 struct stmmac_dma_cfg *dma_cfg,
297
- u32 dma_tx_phy, u32 chan)
302
+ dma_addr_t dma_tx_phy, u32 chan)
298303 {
299304 /* Write TX descriptors address */
300
- writel(dma_tx_phy, ioaddr + EMAC_TX_DESC_LIST);
305
+ writel(lower_32_bits(dma_tx_phy), ioaddr + EMAC_TX_DESC_LIST);
301306 }
302307
303308 /* sun8i_dwmac_dump_regs() - Dump EMAC address space
....@@ -332,14 +337,30 @@
332337 }
333338 }
334339
335
-static void sun8i_dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan)
340
+static void sun8i_dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan,
341
+ bool rx, bool tx)
336342 {
337
- writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN);
343
+ u32 value = readl(ioaddr + EMAC_INT_EN);
344
+
345
+ if (rx)
346
+ value |= EMAC_RX_INT;
347
+ if (tx)
348
+ value |= EMAC_TX_INT;
349
+
350
+ writel(value, ioaddr + EMAC_INT_EN);
338351 }
339352
340
-static void sun8i_dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan)
353
+static void sun8i_dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan,
354
+ bool rx, bool tx)
341355 {
342
- writel(0, ioaddr + EMAC_INT_EN);
356
+ u32 value = readl(ioaddr + EMAC_INT_EN);
357
+
358
+ if (rx)
359
+ value &= ~EMAC_RX_INT;
360
+ if (tx)
361
+ value &= ~EMAC_TX_INT;
362
+
363
+ writel(value, ioaddr + EMAC_INT_EN);
343364 }
344365
345366 static void sun8i_dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan)
....@@ -663,7 +684,8 @@
663684 }
664685 }
665686 } else {
666
- netdev_info(dev, "Too many address, switching to promiscuous\n");
687
+ if (!(readl(ioaddr + EMAC_RX_FRM_FLT) & EMAC_FRM_FLT_RXALL))
688
+ netdev_info(dev, "Too many address, switching to promiscuous\n");
667689 v = EMAC_FRM_FLT_RXALL;
668690 }
669691
....@@ -873,20 +895,27 @@
873895
874896 ret = mdio_mux_init(priv->device, mdio_mux, mdio_mux_syscon_switch_fn,
875897 &gmac->mux_handle, priv, priv->mii);
898
+ of_node_put(mdio_mux);
876899 return ret;
877900 }
878901
879
-static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
902
+static int sun8i_dwmac_set_syscon(struct device *dev,
903
+ struct plat_stmmacenet_data *plat)
880904 {
881
- struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
882
- struct device_node *node = priv->device->of_node;
905
+ struct sunxi_priv_data *gmac = plat->bsp_priv;
906
+ struct device_node *node = dev->of_node;
883907 int ret;
884908 u32 reg, val;
885909
886
- regmap_field_read(gmac->regmap_field, &val);
910
+ ret = regmap_field_read(gmac->regmap_field, &val);
911
+ if (ret) {
912
+ dev_err(dev, "Fail to read from regmap field.\n");
913
+ return ret;
914
+ }
915
+
887916 reg = gmac->variant->default_syscon_value;
888917 if (reg != val)
889
- dev_warn(priv->device,
918
+ dev_warn(dev,
890919 "Current syscon value is not the default %x (expect %x)\n",
891920 val, reg);
892921
....@@ -899,9 +928,9 @@
899928 /* Force EPHY xtal frequency to 24MHz. */
900929 reg |= H3_EPHY_CLK_SEL;
901930
902
- ret = of_mdio_parse_addr(priv->device, priv->plat->phy_node);
931
+ ret = of_mdio_parse_addr(dev, plat->phy_node);
903932 if (ret < 0) {
904
- dev_err(priv->device, "Could not parse MDIO addr\n");
933
+ dev_err(dev, "Could not parse MDIO addr\n");
905934 return ret;
906935 }
907936 /* of_mdio_parse_addr returns a valid (0 ~ 31) PHY
....@@ -917,17 +946,17 @@
917946
918947 if (!of_property_read_u32(node, "allwinner,tx-delay-ps", &val)) {
919948 if (val % 100) {
920
- dev_err(priv->device, "tx-delay must be a multiple of 100\n");
949
+ dev_err(dev, "tx-delay must be a multiple of 100\n");
921950 return -EINVAL;
922951 }
923952 val /= 100;
924
- dev_dbg(priv->device, "set tx-delay to %x\n", val);
953
+ dev_dbg(dev, "set tx-delay to %x\n", val);
925954 if (val <= gmac->variant->tx_delay_max) {
926955 reg &= ~(gmac->variant->tx_delay_max <<
927956 SYSCON_ETXDC_SHIFT);
928957 reg |= (val << SYSCON_ETXDC_SHIFT);
929958 } else {
930
- dev_err(priv->device, "Invalid TX clock delay: %d\n",
959
+ dev_err(dev, "Invalid TX clock delay: %d\n",
931960 val);
932961 return -EINVAL;
933962 }
....@@ -935,17 +964,17 @@
935964
936965 if (!of_property_read_u32(node, "allwinner,rx-delay-ps", &val)) {
937966 if (val % 100) {
938
- dev_err(priv->device, "rx-delay must be a multiple of 100\n");
967
+ dev_err(dev, "rx-delay must be a multiple of 100\n");
939968 return -EINVAL;
940969 }
941970 val /= 100;
942
- dev_dbg(priv->device, "set rx-delay to %x\n", val);
971
+ dev_dbg(dev, "set rx-delay to %x\n", val);
943972 if (val <= gmac->variant->rx_delay_max) {
944973 reg &= ~(gmac->variant->rx_delay_max <<
945974 SYSCON_ERXDC_SHIFT);
946975 reg |= (val << SYSCON_ERXDC_SHIFT);
947976 } else {
948
- dev_err(priv->device, "Invalid RX clock delay: %d\n",
977
+ dev_err(dev, "Invalid RX clock delay: %d\n",
949978 val);
950979 return -EINVAL;
951980 }
....@@ -956,7 +985,7 @@
956985 if (gmac->variant->support_rmii)
957986 reg &= ~SYSCON_RMII_EN;
958987
959
- switch (priv->plat->interface) {
988
+ switch (plat->interface) {
960989 case PHY_INTERFACE_MODE_MII:
961990 /* default */
962991 break;
....@@ -970,8 +999,8 @@
970999 reg |= SYSCON_RMII_EN | SYSCON_ETCS_EXT_GMII;
9711000 break;
9721001 default:
973
- dev_err(priv->device, "Unsupported interface mode: %s",
974
- phy_modes(priv->plat->interface));
1002
+ dev_err(dev, "Unsupported interface mode: %s",
1003
+ phy_modes(plat->interface));
9751004 return -EINVAL;
9761005 }
9771006
....@@ -996,12 +1025,22 @@
9961025 sun8i_dwmac_unpower_internal_phy(gmac);
9971026 }
9981027
999
- sun8i_dwmac_unset_syscon(gmac);
1000
-
10011028 clk_disable_unprepare(gmac->tx_clk);
10021029
10031030 if (gmac->regulator)
10041031 regulator_disable(gmac->regulator);
1032
+}
1033
+
1034
+static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable)
1035
+{
1036
+ u32 value = readl(ioaddr + EMAC_BASIC_CTL0);
1037
+
1038
+ if (enable)
1039
+ value |= EMAC_LOOPBACK;
1040
+ else
1041
+ value &= ~EMAC_LOOPBACK;
1042
+
1043
+ writel(value, ioaddr + EMAC_BASIC_CTL0);
10051044 }
10061045
10071046 static const struct stmmac_ops sun8i_dwmac_ops = {
....@@ -1013,20 +1052,16 @@
10131052 .flow_ctrl = sun8i_dwmac_flow_ctrl,
10141053 .set_umac_addr = sun8i_dwmac_set_umac_addr,
10151054 .get_umac_addr = sun8i_dwmac_get_umac_addr,
1055
+ .set_mac_loopback = sun8i_dwmac_set_mac_loopback,
10161056 };
10171057
10181058 static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
10191059 {
10201060 struct mac_device_info *mac;
10211061 struct stmmac_priv *priv = ppriv;
1022
- int ret;
10231062
10241063 mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
10251064 if (!mac)
1026
- return NULL;
1027
-
1028
- ret = sun8i_dwmac_set_syscon(priv);
1029
- if (ret)
10301065 return NULL;
10311066
10321067 mac->pcsr = priv->ioaddr;
....@@ -1094,6 +1129,7 @@
10941129 struct stmmac_resources stmmac_res;
10951130 struct sunxi_priv_data *gmac;
10961131 struct device *dev = &pdev->dev;
1132
+ phy_interface_t interface;
10971133 int ret;
10981134 struct stmmac_priv *priv;
10991135 struct net_device *ndev;
....@@ -1102,10 +1138,6 @@
11021138 ret = stmmac_get_platform_resources(pdev, &stmmac_res);
11031139 if (ret)
11041140 return ret;
1105
-
1106
- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
1107
- if (IS_ERR(plat_dat))
1108
- return PTR_ERR(plat_dat);
11091141
11101142 gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
11111143 if (!gmac)
....@@ -1167,11 +1199,18 @@
11671199 return ret;
11681200 }
11691201
1170
- plat_dat->interface = of_get_phy_mode(dev->of_node);
1202
+ ret = of_get_phy_mode(dev->of_node, &interface);
1203
+ if (ret)
1204
+ return -EINVAL;
1205
+
1206
+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
1207
+ if (IS_ERR(plat_dat))
1208
+ return PTR_ERR(plat_dat);
11711209
11721210 /* platform data specifying hardware features and callbacks.
11731211 * hardware features were copied from Allwinner drivers.
11741212 */
1213
+ plat_dat->interface = interface;
11751214 plat_dat->rx_coe = STMMAC_RX_COE_TYPE2;
11761215 plat_dat->tx_coe = 1;
11771216 plat_dat->has_sun8i = true;
....@@ -1182,9 +1221,13 @@
11821221 plat_dat->tx_fifo_size = 4096;
11831222 plat_dat->rx_fifo_size = 16384;
11841223
1224
+ ret = sun8i_dwmac_set_syscon(&pdev->dev, plat_dat);
1225
+ if (ret)
1226
+ goto dwmac_deconfig;
1227
+
11851228 ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv);
11861229 if (ret)
1187
- return ret;
1230
+ goto dwmac_syscon;
11881231
11891232 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
11901233 if (ret)
....@@ -1198,7 +1241,7 @@
11981241 if (gmac->variant->soc_has_internal_phy) {
11991242 ret = get_ephy_nodes(priv);
12001243 if (ret)
1201
- goto dwmac_exit;
1244
+ goto dwmac_remove;
12021245 ret = sun8i_dwmac_register_mdio_mux(priv);
12031246 if (ret) {
12041247 dev_err(&pdev->dev, "Failed to register mux\n");
....@@ -1207,17 +1250,23 @@
12071250 } else {
12081251 ret = sun8i_dwmac_reset(priv);
12091252 if (ret)
1210
- goto dwmac_exit;
1253
+ goto dwmac_remove;
12111254 }
12121255
12131256 return ret;
12141257 dwmac_mux:
12151258 reset_control_put(gmac->rst_ephy);
12161259 clk_put(gmac->ephy_clk);
1217
- sun8i_dwmac_unset_syscon(gmac);
1260
+dwmac_remove:
1261
+ stmmac_dvr_remove(&pdev->dev);
12181262 dwmac_exit:
1219
- stmmac_pltfr_remove(pdev);
1220
-return ret;
1263
+ sun8i_dwmac_exit(pdev, gmac);
1264
+dwmac_syscon:
1265
+ sun8i_dwmac_unset_syscon(gmac);
1266
+dwmac_deconfig:
1267
+ stmmac_remove_config_dt(pdev, plat_dat);
1268
+
1269
+ return ret;
12211270 }
12221271
12231272 static int sun8i_dwmac_remove(struct platform_device *pdev)
....@@ -1234,6 +1283,7 @@
12341283 }
12351284
12361285 stmmac_pltfr_remove(pdev);
1286
+ sun8i_dwmac_unset_syscon(gmac);
12371287
12381288 return 0;
12391289 }
....@@ -1249,6 +1299,8 @@
12491299 .data = &emac_variant_r40 },
12501300 { .compatible = "allwinner,sun50i-a64-emac",
12511301 .data = &emac_variant_a64 },
1302
+ { .compatible = "allwinner,sun50i-h6-emac",
1303
+ .data = &emac_variant_h6 },
12521304 { }
12531305 };
12541306 MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);