summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/mediatek/Kconfig6
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.c75
-rw-r--r--drivers/net/ethernet/mediatek/mtk_eth_soc.h23
3 files changed, 88 insertions, 16 deletions
diff --git a/drivers/net/ethernet/mediatek/Kconfig b/drivers/net/ethernet/mediatek/Kconfig
index 698bb89aa901..f9149d2a4694 100644
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -7,11 +7,11 @@ config NET_VENDOR_MEDIATEK
if NET_VENDOR_MEDIATEK
config NET_MEDIATEK_SOC
- tristate "MediaTek MT7623 Gigabit ethernet support"
- depends on NET_VENDOR_MEDIATEK && (MACH_MT7623 || MACH_MT2701)
+ tristate "MediaTek SoC Gigabit Ethernet support"
+ depends on NET_VENDOR_MEDIATEK
select PHYLIB
---help---
This driver supports the gigabit ethernet MACs in the
- MediaTek MT2701/MT7623 chipset family.
+ MediaTek SoC family.
endif #NET_VENDOR_MEDIATEK
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index f1886e1bdd82..0337fe99500a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -185,7 +185,8 @@ static void mtk_phy_link_adjust(struct net_device *dev)
break;
};
- if (mac->id == 0 && !mac->trgmii)
+ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) &&
+ !mac->id && !mac->trgmii)
mtk_gmac0_rgmii_adjust(mac->hw, dev->phydev->speed);
if (dev->phydev->link)
@@ -1834,9 +1835,36 @@ static void ethsys_reset(struct mtk_eth *eth, u32 reset_bits)
mdelay(10);
}
+static void mtk_clk_disable(struct mtk_eth *eth)
+{
+ int clk;
+
+ for (clk = MTK_CLK_MAX - 1; clk >= 0; clk--)
+ clk_disable_unprepare(eth->clks[clk]);
+}
+
+static int mtk_clk_enable(struct mtk_eth *eth)
+{
+ int clk, ret;
+
+ for (clk = 0; clk < MTK_CLK_MAX ; clk++) {
+ ret = clk_prepare_enable(eth->clks[clk]);
+ if (ret)
+ goto err_disable_clks;
+ }
+
+ return 0;
+
+err_disable_clks:
+ while (--clk >= 0)
+ clk_disable_unprepare(eth->clks[clk]);
+
+ return ret;
+}
+
static int mtk_hw_init(struct mtk_eth *eth)
{
- int i, val;
+ int i, val, ret;
if (test_and_set_bit(MTK_HW_INIT, &eth->state))
return 0;
@@ -1844,10 +1872,10 @@ static int mtk_hw_init(struct mtk_eth *eth)
pm_runtime_enable(eth->dev);
pm_runtime_get_sync(eth->dev);
- clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
- clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
- clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
- clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
+ ret = mtk_clk_enable(eth);
+ if (ret)
+ goto err_disable_pm;
+
ethsys_reset(eth, RSTCTRL_FE);
ethsys_reset(eth, RSTCTRL_PPE);
@@ -1915,6 +1943,12 @@ static int mtk_hw_init(struct mtk_eth *eth)
}
return 0;
+
+err_disable_pm:
+ pm_runtime_put_sync(eth->dev);
+ pm_runtime_disable(eth->dev);
+
+ return ret;
}
static int mtk_hw_deinit(struct mtk_eth *eth)
@@ -1922,10 +1956,7 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
if (!test_and_clear_bit(MTK_HW_INIT, &eth->state))
return 0;
- clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
- clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
- clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
- clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+ mtk_clk_disable(eth);
pm_runtime_put_sync(eth->dev);
pm_runtime_disable(eth->dev);
@@ -2403,6 +2434,7 @@ static int mtk_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct device_node *mac_np;
+ const struct of_device_id *match;
struct mtk_eth *eth;
int err;
int i;
@@ -2411,6 +2443,9 @@ static int mtk_probe(struct platform_device *pdev)
if (!eth)
return -ENOMEM;
+ match = of_match_device(of_mtk_match, &pdev->dev);
+ eth->soc = (struct mtk_soc_data *)match->data;
+
eth->dev = &pdev->dev;
eth->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(eth->base))
@@ -2447,7 +2482,12 @@ static int mtk_probe(struct platform_device *pdev)
if (IS_ERR(eth->clks[i])) {
if (PTR_ERR(eth->clks[i]) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- return -ENODEV;
+ if (eth->soc->required_clks & BIT(i)) {
+ dev_err(&pdev->dev, "clock %s not found\n",
+ mtk_clks_source_name[i]);
+ return -EINVAL;
+ }
+ eth->clks[i] = NULL;
}
}
@@ -2550,8 +2590,19 @@ static int mtk_remove(struct platform_device *pdev)
return 0;
}
+static const struct mtk_soc_data mt2701_data = {
+ .caps = MTK_GMAC1_TRGMII,
+ .required_clks = MT7623_CLKS_BITMAP
+};
+
+static const struct mtk_soc_data mt7623_data = {
+ .caps = MTK_GMAC1_TRGMII,
+ .required_clks = MT7623_CLKS_BITMAP
+};
+
const struct of_device_id of_mtk_match[] = {
- { .compatible = "mediatek,mt2701-eth" },
+ { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
+ { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
{},
};
MODULE_DEVICE_TABLE(of, of_mtk_match);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 5868a09f623a..8ade23dfcc77 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -443,6 +443,9 @@ enum mtk_clks_map {
MTK_CLK_MAX
};
+#define MT7623_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \
+ BIT(MTK_CLK_GP1) | BIT(MTK_CLK_GP2) | \
+ BIT(MTK_CLK_TRGPLL))
enum mtk_dev_state {
MTK_HW_INIT,
MTK_RESETTING
@@ -511,6 +514,21 @@ struct mtk_rx_ring {
u32 crx_idx_reg;
};
+#define MTK_TRGMII BIT(0)
+#define MTK_GMAC1_TRGMII (BIT(1) | MTK_TRGMII)
+#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x))
+
+/* struct mtk_soc_data - This is the structure holding all differences
+ * among various plaforms
+ * @caps Flags shown the extra capability for the SoC
+ * @required_clks Flags shown the bitmap for required clocks on
+ * the target SoC
+ */
+struct mtk_soc_data {
+ u32 caps;
+ u32 required_clks;
+};
+
/* currently no SoC has more than 2 macs */
#define MTK_MAX_DEVS 2
@@ -542,7 +560,8 @@ struct mtk_rx_ring {
* @clks: clock array for all clocks required
* @mii_bus: If there is a bus we need to create an instance for it
* @pending_work: The workqueue used to reset the dma ring
- * @state Initialization and runtime state of the device.
+ * @state Initialization and runtime state of the device
+ * @soc: Holding specific data among vaious SoCs
*/
struct mtk_eth {
@@ -574,6 +593,8 @@ struct mtk_eth {
struct mii_bus *mii_bus;
struct work_struct pending_work;
unsigned long state;
+
+ const struct mtk_soc_data *soc;
};
/* struct mtk_mac - the structure that holds the info about the MACs of the