mirror of https://github.com/armbian/build.git
118 lines
3.5 KiB
Diff
118 lines
3.5 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
Date: Sat, 25 Dec 2021 04:22:53 +0100
|
|
Subject: net: stmmac: dwmac-meson: Manage the "ethernet" clock
|
|
|
|
Meson6 and Meson8 (both use the same glue registers on top of the DWMAC
|
|
IP) have a dedicated Ethernet clock. For RMII mode the SoC has an input
|
|
for an external RMII reference clock signal (which can be provided by
|
|
either the PHY or an external oscillator). This clock needs to run at
|
|
50MHz because the additional glue registers can divide by 2 - to achieve
|
|
25MHz for 100Mbit/s line speed, or 20 - to achieve 2.5MHz for 10Mbit/s
|
|
line speed.
|
|
|
|
Set the correct frequency for this clock and enable it during init. Also
|
|
enable the ETHMAC_DIV_EN bit which enables the divider in the glue
|
|
registers, based on the Ethernet clock input.
|
|
|
|
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
|
---
|
|
drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c | 51 +++++++++-
|
|
1 file changed, 50 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
|
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
|
|
@@ -5,6 +5,7 @@
|
|
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
|
|
*/
|
|
|
|
+#include <linux/clk.h>
|
|
#include <linux/device.h>
|
|
#include <linux/ethtool.h>
|
|
#include <linux/io.h>
|
|
@@ -15,12 +16,15 @@
|
|
|
|
#include "stmmac_platform.h"
|
|
|
|
+#define PREG_ETHERNET_ADDR0_DIV_EN BIT(0)
|
|
+
|
|
/* divides the input clock by 20 (= 0x0) or 2 (= 0x1) */
|
|
#define PREG_ETHERNET_ADDR0_SPEED_100 BIT(1)
|
|
|
|
struct meson_dwmac {
|
|
struct device *dev;
|
|
void __iomem *reg;
|
|
+ struct clk *ethernet_clk;
|
|
};
|
|
|
|
static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode)
|
|
@@ -42,6 +46,33 @@ static void meson6_dwmac_fix_mac_speed(void *priv, unsigned int speed, unsigned
|
|
writel(val, dwmac->reg);
|
|
}
|
|
|
|
+static int meson6_dwmac_init(struct platform_device *pdev, void *priv)
|
|
+{
|
|
+ struct meson_dwmac *dwmac = priv;
|
|
+ int ret;
|
|
+
|
|
+ ret = clk_set_rate(dwmac->ethernet_clk, 50 * 1000 * 1000);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = clk_prepare_enable(dwmac->ethernet_clk);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ writel(readl(dwmac->reg) | PREG_ETHERNET_ADDR0_DIV_EN, dwmac->reg);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void meson6_dwmac_exit(struct platform_device *pdev, void *priv)
|
|
+{
|
|
+ struct meson_dwmac *dwmac = priv;
|
|
+
|
|
+ writel(readl(dwmac->reg) & ~PREG_ETHERNET_ADDR0_DIV_EN, dwmac->reg);
|
|
+
|
|
+ clk_disable_unprepare(dwmac->ethernet_clk);
|
|
+}
|
|
+
|
|
static int meson6_dwmac_probe(struct platform_device *pdev)
|
|
{
|
|
struct plat_stmmacenet_data *plat_dat;
|
|
@@ -65,10 +96,28 @@ static int meson6_dwmac_probe(struct platform_device *pdev)
|
|
if (IS_ERR(dwmac->reg))
|
|
return PTR_ERR(dwmac->reg);
|
|
|
|
+ dwmac->ethernet_clk = devm_clk_get_optional(&pdev->dev, "ethernet");
|
|
+ if (IS_ERR(dwmac->ethernet_clk))
|
|
+ return PTR_ERR(dwmac->ethernet_clk);
|
|
+
|
|
plat_dat->bsp_priv = dwmac;
|
|
+ plat_dat->init = meson6_dwmac_init;
|
|
+ plat_dat->exit = meson6_dwmac_exit;
|
|
plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed;
|
|
|
|
- return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
|
|
+ ret = meson6_dwmac_init(pdev, dwmac);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
|
|
+ if (ret)
|
|
+ goto err_exit_dwmac;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_exit_dwmac:
|
|
+ meson6_dwmac_exit(pdev, dwmac);
|
|
+ return ret;
|
|
}
|
|
|
|
static const struct of_device_id meson6_dwmac_match[] = {
|
|
--
|
|
Armbian
|
|
|