net: ethernet: mtk_eth_wed: add axi bus support
authorLorenzo Bianconi <lorenzo@kernel.org>
Tue, 20 Sep 2022 10:11:22 +0000 (12:11 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 22 Sep 2022 13:13:24 +0000 (15:13 +0200)
Other than pcie bus, introduce support for axi bus to mtk wed driver.
Axi bus is used to connect mt7986-wmac soc chip available on mt7986
device.

Tested-by: Daniel Golle <daniel@makrotopia.org>
Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
Co-developed-by: Sujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/mediatek/mtk_wed.c
drivers/net/ethernet/mediatek/mtk_wed_regs.h
include/linux/soc/mediatek/mtk_wed.h

index e261858..099b6e0 100644 (file)
@@ -85,11 +85,31 @@ static struct mtk_wed_hw *
 mtk_wed_assign(struct mtk_wed_device *dev)
 {
        struct mtk_wed_hw *hw;
+       int i;
+
+       if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
+               hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)];
+               if (!hw)
+                       return NULL;
 
-       hw = hw_list[pci_domain_nr(dev->wlan.pci_dev->bus)];
-       if (!hw || hw->wed_dev)
-               return NULL;
+               if (!hw->wed_dev)
+                       goto out;
 
+               if (hw->version == 1)
+                       return NULL;
+
+               /* MT7986 WED devices do not have any pcie slot restrictions */
+       }
+       /* MT7986 PCIE or AXI */
+       for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
+               hw = hw_list[i];
+               if (hw && !hw->wed_dev)
+                       goto out;
+       }
+
+       return NULL;
+
+out:
        hw->wed_dev = dev;
        return hw;
 }
@@ -322,7 +342,6 @@ mtk_wed_stop(struct mtk_wed_device *dev)
 static void
 mtk_wed_detach(struct mtk_wed_device *dev)
 {
-       struct device_node *wlan_node = dev->wlan.pci_dev->dev.of_node;
        struct mtk_wed_hw *hw = dev->hw;
 
        mutex_lock(&hw_lock);
@@ -337,9 +356,14 @@ mtk_wed_detach(struct mtk_wed_device *dev)
        mtk_wed_free_buffer(dev);
        mtk_wed_free_tx_rings(dev);
 
-       if (of_dma_is_coherent(wlan_node) && hw->hifsys)
-               regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
-                                  BIT(hw->index), BIT(hw->index));
+       if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
+               struct device_node *wlan_node;
+
+               wlan_node = dev->wlan.pci_dev->dev.of_node;
+               if (of_dma_is_coherent(wlan_node) && hw->hifsys)
+                       regmap_update_bits(hw->hifsys, HIFSYS_DMA_AG_MAP,
+                                          BIT(hw->index), BIT(hw->index));
+       }
 
        if (!hw_list[!hw->index]->wed_dev &&
            hw->eth->dma_dev != hw->eth->dev)
@@ -356,33 +380,47 @@ mtk_wed_detach(struct mtk_wed_device *dev)
 static void
 mtk_wed_bus_init(struct mtk_wed_device *dev)
 {
-       struct device_node *np = dev->hw->eth->dev->of_node;
-       struct regmap *regs;
-
-       regs = syscon_regmap_lookup_by_phandle(np, "mediatek,wed-pcie");
-       if (IS_ERR(regs))
-               return;
+       switch (dev->wlan.bus_type) {
+       case MTK_WED_BUS_PCIE: {
+               struct device_node *np = dev->hw->eth->dev->of_node;
+               struct regmap *regs;
+
+               regs = syscon_regmap_lookup_by_phandle(np,
+                                                      "mediatek,wed-pcie");
+               if (IS_ERR(regs))
+                       break;
 
-       regmap_update_bits(regs, 0, BIT(0), BIT(0));
+               regmap_update_bits(regs, 0, BIT(0), BIT(0));
 
-       wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
-               FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
+               wed_w32(dev, MTK_WED_PCIE_INT_CTRL,
+                       FIELD_PREP(MTK_WED_PCIE_INT_CTRL_POLL_EN, 2));
 
-       /* pcie interrupt control: pola/source selection */
-       wed_set(dev, MTK_WED_PCIE_INT_CTRL,
-               MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
-               FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1));
-       wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
+               /* pcie interrupt control: pola/source selection */
+               wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+                       MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA |
+                       FIELD_PREP(MTK_WED_PCIE_INT_CTRL_SRC_SEL, 1));
+               wed_r32(dev, MTK_WED_PCIE_INT_CTRL);
 
-       wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180);
-       wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184);
+               wed_w32(dev, MTK_WED_PCIE_CFG_INTM, PCIE_BASE_ADDR0 | 0x180);
+               wed_w32(dev, MTK_WED_PCIE_CFG_BASE, PCIE_BASE_ADDR0 | 0x184);
 
-       /* pcie interrupt status trigger register */
-       wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
-       wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
+               /* pcie interrupt status trigger register */
+               wed_w32(dev, MTK_WED_PCIE_INT_TRIGGER, BIT(24));
+               wed_r32(dev, MTK_WED_PCIE_INT_TRIGGER);
 
-       /* pola setting */
-       wed_set(dev, MTK_WED_PCIE_INT_CTRL, MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
+               /* pola setting */
+               wed_set(dev, MTK_WED_PCIE_INT_CTRL,
+                       MTK_WED_PCIE_INT_CTRL_MSK_EN_POLA);
+               break;
+       }
+       case MTK_WED_BUS_AXI:
+               wed_set(dev, MTK_WED_WPDMA_INT_CTRL,
+                       MTK_WED_WPDMA_INT_CTRL_SIG_SRC |
+                       FIELD_PREP(MTK_WED_WPDMA_INT_CTRL_SRC_SEL, 0));
+               break;
+       default:
+               break;
+       }
 }
 
 static void
@@ -793,12 +831,14 @@ mtk_wed_attach(struct mtk_wed_device *dev)
        __releases(RCU)
 {
        struct mtk_wed_hw *hw;
+       struct device *device;
        int ret = 0;
 
        RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
                         "mtk_wed_attach without holding the RCU read lock");
 
-       if (pci_domain_nr(dev->wlan.pci_dev->bus) > 1 ||
+       if ((dev->wlan.bus_type == MTK_WED_BUS_PCIE &&
+            pci_domain_nr(dev->wlan.pci_dev->bus) > 1) ||
            !try_module_get(THIS_MODULE))
                ret = -ENODEV;
 
@@ -816,8 +856,10 @@ mtk_wed_attach(struct mtk_wed_device *dev)
                goto out;
        }
 
-       dev_info(&dev->wlan.pci_dev->dev,
-                "attaching wed device %d version %d\n",
+       device = dev->wlan.bus_type == MTK_WED_BUS_PCIE
+               ? &dev->wlan.pci_dev->dev
+               : &dev->wlan.platform_dev->dev;
+       dev_info(device, "attaching wed device %d version %d\n",
                 hw->index, hw->version);
 
        dev->hw = hw;
index 5dd78e3..e270fb3 100644 (file)
@@ -198,6 +198,8 @@ struct mtk_wdma_desc {
 
 #define MTK_WED_WPDMA_INT_CTRL                         0x520
 #define MTK_WED_WPDMA_INT_CTRL_SUBRT_ADV               BIT(21)
+#define MTK_WED_WPDMA_INT_CTRL_SIG_SRC                 BIT(22)
+#define MTK_WED_WPDMA_INT_CTRL_SRC_SEL                 GENMASK(17, 16)
 
 #define MTK_WED_WPDMA_INT_MASK                         0x524
 
index 592221a..4450c8b 100644 (file)
 struct mtk_wed_hw;
 struct mtk_wdma_desc;
 
+enum mtk_wed_bus_tye {
+       MTK_WED_BUS_PCIE,
+       MTK_WED_BUS_AXI,
+};
+
 struct mtk_wed_ring {
        struct mtk_wdma_desc *desc;
        dma_addr_t desc_phys;
@@ -43,7 +48,11 @@ struct mtk_wed_device {
 
        /* filled by driver: */
        struct {
-               struct pci_dev *pci_dev;
+               union {
+                       struct platform_device *platform_dev;
+                       struct pci_dev *pci_dev;
+               };
+               enum mtk_wed_bus_tye bus_type;
 
                u32 wpdma_phys;
                u32 wpdma_int;