Skip to content

Commit

Permalink
Merge branch 'net-stmmac-cleanup-transmit-clock-setting'
Browse files Browse the repository at this point in the history
Russell King says:

====================
net: stmmac: cleanup transmit clock setting

A lot of stmmac platform code which sets the transmit clock is very
similar - they decode the speed to the clock rate (125, 25 or 2.5 MHz)
and then set a clock to that rate.

The DWMAC core appears to have a clock input for the transmit section
called clk_tx_i which requires this rate.

This series moves the code which sets this clock into the core stmmac
code.

Patch 1 adds a hook that platforms can use to configure the clock rate.
Patch 2 adds a generic implementation.
The remainder of the patches convert the glue code for various platforms
to use this new infrastructure.
====================

Link: https://patch.msgid.link/Z8AtX-wyPal1auVO@shell.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Feb 28, 2025
2 parents 56794b5 + 945db20 commit 8e7e3d9
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 90 deletions.
10 changes: 2 additions & 8 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ struct tegra_eqos {

struct reset_control *rst;
struct clk *clk_slave;
struct clk *clk_tx;

struct gpio_desc *reset;
};
Expand Down Expand Up @@ -150,7 +149,6 @@ static void tegra_eqos_fix_speed(void *priv, int speed, unsigned int mode)
{
struct tegra_eqos *eqos = priv;
bool needs_calibration = false;
long rate = 125000000;
u32 value;
int err;

Expand All @@ -161,7 +159,6 @@ static void tegra_eqos_fix_speed(void *priv, int speed, unsigned int mode)
fallthrough;

case SPEED_10:
rate = rgmii_clock(speed);
break;

default:
Expand Down Expand Up @@ -208,10 +205,6 @@ static void tegra_eqos_fix_speed(void *priv, int speed, unsigned int mode)
value &= ~AUTO_CAL_CONFIG_ENABLE;
writel(value, eqos->regs + AUTO_CAL_CONFIG);
}

err = clk_set_rate(eqos->clk_tx, rate);
if (err < 0)
dev_err(eqos->dev, "failed to set TX rate: %d\n", err);
}

static int tegra_eqos_init(struct platform_device *pdev, void *priv)
Expand Down Expand Up @@ -247,7 +240,7 @@ static int tegra_eqos_probe(struct platform_device *pdev,
if (!is_of_node(dev->fwnode))
goto bypass_clk_reset_gpio;

eqos->clk_tx = dwc_eth_find_clk(plat_dat, "tx");
plat_dat->clk_tx_i = dwc_eth_find_clk(plat_dat, "tx");

eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
if (IS_ERR(eqos->reset)) {
Expand Down Expand Up @@ -281,6 +274,7 @@ static int tegra_eqos_probe(struct platform_device *pdev,

bypass_clk_reset_gpio:
plat_dat->fix_mac_speed = tegra_eqos_fix_speed;
plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
plat_dat->init = tegra_eqos_init;
plat_dat->bsp_priv = eqos;
plat_dat->flags |= STMMAC_FLAG_SPH_DISABLE;
Expand Down
21 changes: 19 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,19 @@ static void imx_dwmac_exit(struct platform_device *pdev, void *priv)
/* nothing to do now */
}

static int imx_dwmac_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
phy_interface_t interface, int speed)
{
struct imx_priv_data *dwmac = bsp_priv;

interface = dwmac->plat_dat->mac_interface;
if (interface == PHY_INTERFACE_MODE_RMII ||
interface == PHY_INTERFACE_MODE_MII)
return 0;

return stmmac_set_clk_tx_rate(bsp_priv, clk_tx_i, interface, speed);
}

static void imx_dwmac_fix_speed(void *priv, int speed, unsigned int mode)
{
struct plat_stmmacenet_data *plat_dat;
Expand Down Expand Up @@ -358,7 +371,6 @@ static int imx_dwmac_probe(struct platform_device *pdev)
plat_dat->init = imx_dwmac_init;
plat_dat->exit = imx_dwmac_exit;
plat_dat->clks_config = imx_dwmac_clks_config;
plat_dat->fix_mac_speed = imx_dwmac_fix_speed;
plat_dat->bsp_priv = dwmac;
dwmac->plat_dat = plat_dat;
dwmac->base_addr = stmmac_res.addr;
Expand All @@ -371,8 +383,13 @@ static int imx_dwmac_probe(struct platform_device *pdev)
if (ret)
goto err_dwmac_init;

if (dwmac->ops->fix_mac_speed)
if (dwmac->ops->fix_mac_speed) {
plat_dat->fix_mac_speed = dwmac->ops->fix_mac_speed;
} else if (!dwmac->ops->mac_rgmii_txclk_auto_adj) {
plat_dat->clk_tx_i = dwmac->clk_tx;
plat_dat->set_clk_tx_rate = imx_dwmac_set_clk_tx_rate;
}

dwmac->plat_dat->fix_soc_reset = dwmac->ops->fix_soc_reset;

ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
Expand Down
24 changes: 3 additions & 21 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,12 @@ struct intel_dwmac {
};

struct intel_dwmac_data {
void (*fix_mac_speed)(void *priv, int speed, unsigned int mode);
unsigned long ptp_ref_clk_rate;
unsigned long tx_clk_rate;
bool tx_clk_en;
};

static void kmb_eth_fix_mac_speed(void *priv, int speed, unsigned int mode)
{
struct intel_dwmac *dwmac = priv;
long rate;
int ret;

rate = rgmii_clock(speed);
if (rate < 0) {
dev_err(dwmac->dev, "Invalid speed\n");
return;
}

ret = clk_set_rate(dwmac->tx_clk, rate);
if (ret)
dev_err(dwmac->dev, "Failed to configure tx clock rate\n");
}

static const struct intel_dwmac_data kmb_data = {
.fix_mac_speed = kmb_eth_fix_mac_speed,
.ptp_ref_clk_rate = 200000000,
.tx_clk_rate = 125000000,
.tx_clk_en = true,
Expand Down Expand Up @@ -89,8 +70,6 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
* platform_match().
*/
dwmac->data = device_get_match_data(&pdev->dev);
if (dwmac->data->fix_mac_speed)
plat_dat->fix_mac_speed = dwmac->data->fix_mac_speed;

/* Enable TX clock */
if (dwmac->data->tx_clk_en) {
Expand Down Expand Up @@ -132,6 +111,9 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
}
}

plat_dat->clk_tx_i = dwmac->tx_clk;
plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;

plat_dat->bsp_priv = dwmac;
plat_dat->eee_usecs_rate = plat_dat->clk_ptp_rate;

Expand Down
9 changes: 5 additions & 4 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,12 @@ static int ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
return PTR_ERR_OR_ZERO(gmac->qsgmii_csr);
}

static void ipq806x_gmac_fix_mac_speed(void *priv, int speed, unsigned int mode)
static int ipq806x_gmac_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
phy_interface_t interface, int speed)
{
struct ipq806x_gmac *gmac = priv;
struct ipq806x_gmac *gmac = bsp_priv;

ipq806x_gmac_set_speed(gmac, speed);
return ipq806x_gmac_set_speed(gmac, speed);
}

static int
Expand Down Expand Up @@ -478,7 +479,7 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)

plat_dat->has_gmac = true;
plat_dat->bsp_priv = gmac;
plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;
plat_dat->set_clk_tx_rate = ipq806x_gmac_set_clk_tx_rate;
plat_dat->multicast_filter_bins = 0;
plat_dat->tx_fifo_size = 8192;
plat_dat->rx_fifo_size = 8192;
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ struct meson_dwmac {
void __iomem *reg;
};

static void meson6_dwmac_fix_mac_speed(void *priv, int speed, unsigned int mode)
static int meson6_dwmac_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
phy_interface_t interface, int speed)
{
struct meson_dwmac *dwmac = priv;
struct meson_dwmac *dwmac = bsp_priv;
unsigned int val;

val = readl(dwmac->reg);
Expand All @@ -39,6 +40,8 @@ static void meson6_dwmac_fix_mac_speed(void *priv, int speed, unsigned int mode)
}

writel(val, dwmac->reg);

return 0;
}

static int meson6_dwmac_probe(struct platform_device *pdev)
Expand All @@ -65,7 +68,7 @@ static int meson6_dwmac_probe(struct platform_device *pdev)
return PTR_ERR(dwmac->reg);

plat_dat->bsp_priv = dwmac;
plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed;
plat_dat->set_clk_tx_rate = meson6_dwmac_set_clk_tx_rate;

return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
}
Expand Down
10 changes: 7 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1920,9 +1920,10 @@ static void rk_gmac_powerdown(struct rk_priv_data *gmac)
gmac_clk_enable(gmac, false);
}

static void rk_fix_speed(void *priv, int speed, unsigned int mode)
static int rk_set_clk_tx_rate(void *bsp_priv_, struct clk *clk_tx_i,
phy_interface_t interface, int speed)
{
struct rk_priv_data *bsp_priv = priv;
struct rk_priv_data *bsp_priv = bsp_priv_;
struct device *dev = &bsp_priv->pdev->dev;

switch (bsp_priv->phy_iface) {
Expand All @@ -1940,6 +1941,8 @@ static void rk_fix_speed(void *priv, int speed, unsigned int mode)
default:
dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
}

return 0;
}

static int rk_gmac_probe(struct platform_device *pdev)
Expand Down Expand Up @@ -1968,7 +1971,8 @@ static int rk_gmac_probe(struct platform_device *pdev)
*/
if (!plat_dat->has_gmac4)
plat_dat->has_gmac = true;
plat_dat->fix_mac_speed = rk_fix_speed;

plat_dat->set_clk_tx_rate = rk_set_clk_tx_rate;

plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data);
if (IS_ERR(plat_dat->bsp_priv))
Expand Down
22 changes: 3 additions & 19 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,6 @@ static void s32_gmac_exit(struct platform_device *pdev, void *priv)
clk_disable_unprepare(gmac->rx_clk);
}

static void s32_fix_mac_speed(void *priv, int speed, unsigned int mode)
{
struct s32_priv_data *gmac = priv;
long tx_clk_rate;
int ret;

tx_clk_rate = rgmii_clock(speed);
if (tx_clk_rate < 0) {
dev_err(gmac->dev, "Unsupported/Invalid speed: %d\n", speed);
return;
}

dev_dbg(gmac->dev, "Set tx clock to %ld Hz\n", tx_clk_rate);
ret = clk_set_rate(gmac->tx_clk, tx_clk_rate);
if (ret)
dev_err(gmac->dev, "Can't set tx clock\n");
}

static int s32_dwmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat;
Expand Down Expand Up @@ -172,7 +154,9 @@ static int s32_dwmac_probe(struct platform_device *pdev)

plat->init = s32_gmac_init;
plat->exit = s32_gmac_exit;
plat->fix_mac_speed = s32_fix_mac_speed;

plat->clk_tx_i = gmac->tx_clk;
plat->set_clk_tx_rate = stmmac_set_clk_tx_rate;

plat->bsp_priv = gmac;

Expand Down
26 changes: 4 additions & 22 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,9 @@ struct starfive_dwmac_data {

struct starfive_dwmac {
struct device *dev;
struct clk *clk_tx;
const struct starfive_dwmac_data *data;
};

static void starfive_dwmac_fix_mac_speed(void *priv, int speed, unsigned int mode)
{
struct starfive_dwmac *dwmac = priv;
long rate;
int err;

rate = rgmii_clock(speed);
if (rate < 0) {
dev_err(dwmac->dev, "invalid speed %d\n", speed);
return;
}

err = clk_set_rate(dwmac->clk_tx, rate);
if (err)
dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate);
}

static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat)
{
struct starfive_dwmac *dwmac = plat_dat->bsp_priv;
Expand Down Expand Up @@ -122,9 +104,9 @@ static int starfive_dwmac_probe(struct platform_device *pdev)

dwmac->data = device_get_match_data(&pdev->dev);

dwmac->clk_tx = devm_clk_get_enabled(&pdev->dev, "tx");
if (IS_ERR(dwmac->clk_tx))
return dev_err_probe(&pdev->dev, PTR_ERR(dwmac->clk_tx),
plat_dat->clk_tx_i = devm_clk_get_enabled(&pdev->dev, "tx");
if (IS_ERR(plat_dat->clk_tx_i))
return dev_err_probe(&pdev->dev, PTR_ERR(plat_dat->clk_tx_i),
"error getting tx clock\n");

clk_gtx = devm_clk_get_enabled(&pdev->dev, "gtx");
Expand All @@ -139,7 +121,7 @@ static int starfive_dwmac_probe(struct platform_device *pdev)
* internally, because rgmii_rxin will be adaptively adjusted.
*/
if (!device_property_read_bool(&pdev->dev, "starfive,tx-use-rgmii-clk"))
plat_dat->fix_mac_speed = starfive_dwmac_fix_mac_speed;
plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate;

dwmac->dev = &pdev->dev;
plat_dat->bsp_priv = dwmac;
Expand Down
18 changes: 10 additions & 8 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,11 @@ static int thead_dwmac_set_txclk_dir(struct plat_stmmacenet_data *plat)
return 0;
}

static void thead_dwmac_fix_speed(void *priv, int speed, unsigned int mode)
static int thead_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
phy_interface_t interface, int speed)
{
struct thead_dwmac *dwmac = bsp_priv;
struct plat_stmmacenet_data *plat;
struct thead_dwmac *dwmac = priv;
unsigned long rate;
long tx_rate;
u32 div, reg;
Expand All @@ -114,7 +115,7 @@ static void thead_dwmac_fix_speed(void *priv, int speed, unsigned int mode)
switch (plat->mac_interface) {
/* For MII, rxc/txc is provided by phy */
case PHY_INTERFACE_MODE_MII:
return;
return 0;

case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
Expand All @@ -127,23 +128,24 @@ static void thead_dwmac_fix_speed(void *priv, int speed, unsigned int mode)
tx_rate = rgmii_clock(speed);
if (tx_rate < 0) {
dev_err(dwmac->dev, "invalid speed %d\n", speed);
return;
return tx_rate;
}

div = rate / tx_rate;
if (rate != tx_rate * div) {
dev_err(dwmac->dev, "invalid gmac rate %lu\n", rate);
return;
return -EINVAL;
}

reg = FIELD_PREP(GMAC_PLLCLK_DIV_EN, 1) |
FIELD_PREP(GMAC_PLLCLK_DIV_NUM, div);
writel(reg, dwmac->apb_base + GMAC_PLLCLK_DIV);
break;
return 0;

default:
dev_err(dwmac->dev, "unsupported phy interface %d\n",
plat->mac_interface);
return;
return -EINVAL;
}
}

Expand Down Expand Up @@ -235,7 +237,7 @@ static int thead_dwmac_probe(struct platform_device *pdev)
dwmac->plat = plat;
dwmac->apb_base = apb;
plat->bsp_priv = dwmac;
plat->fix_mac_speed = thead_dwmac_fix_speed;
plat->set_clk_tx_rate = thead_set_clk_tx_rate;
plat->init = thead_dwmac_init;

return devm_stmmac_pltfr_probe(pdev, plat, &stmmac_res);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,8 @@ int stmmac_dvr_probe(struct device *device,
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt);
int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size);
int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled);
int stmmac_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
phy_interface_t interface, int speed);

static inline bool stmmac_xdp_is_enabled(struct stmmac_priv *priv)
{
Expand Down
Loading

0 comments on commit 8e7e3d9

Please sign in to comment.