File Index
Files and directories
Sign in
FILE

dwmac-s32.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * NXP S32G/R GMAC glue layer
  4 *
  5 * Copyright 2019-2024 NXP
  6 *
  7 */
  8
  9#include <linux/clk.h>
 10#include <linux/clk-provider.h>
 11#include <linux/device.h>
 12#include <linux/ethtool.h>
 13#include <linux/io.h>
 14#include <linux/module.h>
 15#include <linux/of_mdio.h>
 16#include <linux/of_address.h>
 17#include <linux/phy.h>
 18#include <linux/phylink.h>
 19#include <linux/platform_device.h>
 20#include <linux/stmmac.h>
 21
 22#include "stmmac_platform.h"
 23
 24#define GMAC_INTF_RATE_125M	125000000	/* 125MHz */
 25
 26/* SoC PHY interface control register */
 27#define S32_PHY_INTF_SEL_MII	0x00
 28#define S32_PHY_INTF_SEL_SGMII	0x01
 29#define S32_PHY_INTF_SEL_RGMII	0x02
 30#define S32_PHY_INTF_SEL_RMII	0x08
 31
 32struct s32_priv_data {
 33	void __iomem *ioaddr;
 34	void __iomem *ctrl_sts;
 35	struct device *dev;
 36	phy_interface_t *intf_mode;
 37	struct clk *tx_clk;
 38	struct clk *rx_clk;
 39};
 40
 41static int s32_gmac_write_phy_intf_select(struct s32_priv_data *gmac)
 42{
 43	writel(S32_PHY_INTF_SEL_RGMII, gmac->ctrl_sts);
 44
 45	dev_dbg(gmac->dev, "PHY mode set to %s\n", phy_modes(*gmac->intf_mode));
 46
 47	return 0;
 48}
 49
 50static int s32_gmac_init(struct device *dev, void *priv)
 51{
 52	struct s32_priv_data *gmac = priv;
 53	int ret;
 54
 55	/* Set initial TX interface clock */
 56	ret = clk_prepare_enable(gmac->tx_clk);
 57	if (ret) {
 58		dev_err(dev, "Can't enable tx clock\n");
 59		return ret;
 60	}
 61	ret = clk_set_rate(gmac->tx_clk, GMAC_INTF_RATE_125M);
 62	if (ret) {
 63		dev_err(dev, "Can't set tx clock\n");
 64		goto err_tx_disable;
 65	}
 66
 67	/* Set initial RX interface clock */
 68	ret = clk_prepare_enable(gmac->rx_clk);
 69	if (ret) {
 70		dev_err(dev, "Can't enable rx clock\n");
 71		goto err_tx_disable;
 72	}
 73	ret = clk_set_rate(gmac->rx_clk, GMAC_INTF_RATE_125M);
 74	if (ret) {
 75		dev_err(dev, "Can't set rx clock\n");
 76		goto err_txrx_disable;
 77	}
 78
 79	/* Set interface mode */
 80	ret = s32_gmac_write_phy_intf_select(gmac);
 81	if (ret) {
 82		dev_err(dev, "Can't set PHY interface mode\n");
 83		goto err_txrx_disable;
 84	}
 85
 86	return 0;
 87
 88err_txrx_disable:
 89	clk_disable_unprepare(gmac->rx_clk);
 90err_tx_disable:
 91	clk_disable_unprepare(gmac->tx_clk);
 92	return ret;
 93}
 94
 95static void s32_gmac_exit(struct device *dev, void *priv)
 96{
 97	struct s32_priv_data *gmac = priv;
 98
 99	clk_disable_unprepare(gmac->tx_clk);
100	clk_disable_unprepare(gmac->rx_clk);
101}
102
103static int s32_dwmac_probe(struct platform_device *pdev)
104{
105	struct plat_stmmacenet_data *plat;
106	struct device *dev = &pdev->dev;
107	struct stmmac_resources res;
108	struct s32_priv_data *gmac;
109	int ret;
110
111	gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);
112	if (!gmac)
113		return -ENOMEM;
114
115	gmac->dev = &pdev->dev;
116
117	ret = stmmac_get_platform_resources(pdev, &res);
118	if (ret)
119		return dev_err_probe(dev, ret,
120				     "Failed to get platform resources\n");
121
122	plat = devm_stmmac_probe_config_dt(pdev, res.mac);
123	if (IS_ERR(plat))
124		return dev_err_probe(dev, PTR_ERR(plat),
125				     "dt configuration failed\n");
126
127	/* PHY interface mode control reg */
128	gmac->ctrl_sts = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
129	if (IS_ERR(gmac->ctrl_sts))
130		return dev_err_probe(dev, PTR_ERR(gmac->ctrl_sts),
131				     "S32CC config region is missing\n");
132
133	/* tx clock */
134	gmac->tx_clk = devm_clk_get(&pdev->dev, "tx");
135	if (IS_ERR(gmac->tx_clk))
136		return dev_err_probe(dev, PTR_ERR(gmac->tx_clk),
137				     "tx clock not found\n");
138
139	/* rx clock */
140	gmac->rx_clk = devm_clk_get(&pdev->dev, "rx");
141	if (IS_ERR(gmac->rx_clk))
142		return dev_err_probe(dev, PTR_ERR(gmac->rx_clk),
143				     "rx clock not found\n");
144
145	gmac->intf_mode = &plat->phy_interface;
146	gmac->ioaddr = res.addr;
147
148	/* S32CC core feature set */
149	plat->core_type = DWMAC_CORE_GMAC4;
150	plat->pmt = 1;
151	plat->flags |= STMMAC_FLAG_SPH_DISABLE;
152	plat->rx_fifo_size = 20480;
153	plat->tx_fifo_size = 20480;
154
155	plat->init = s32_gmac_init;
156	plat->exit = s32_gmac_exit;
157
158	plat->clk_tx_i = gmac->tx_clk;
159	plat->set_clk_tx_rate = stmmac_set_clk_tx_rate;
160
161	plat->bsp_priv = gmac;
162
163	return stmmac_pltfr_probe(pdev, plat, &res);
164}
165
166static const struct of_device_id s32_dwmac_match[] = {
167	{ .compatible = "nxp,s32g2-dwmac" },
168	{ }
169};
170MODULE_DEVICE_TABLE(of, s32_dwmac_match);
171
172static struct platform_driver s32_dwmac_driver = {
173	.probe = s32_dwmac_probe,
174	.remove = stmmac_pltfr_remove,
175	.driver = {
176		.name = "s32-dwmac",
177		.pm = &stmmac_pltfr_pm_ops,
178		.of_match_table = s32_dwmac_match,
179	},
180};
181module_platform_driver(s32_dwmac_driver);
182
183MODULE_AUTHOR("Jan Petrous (OSS) <jan.petrous@oss.nxp.com>");
184MODULE_DESCRIPTION("NXP S32G/R common chassis GMAC driver");
185MODULE_LICENSE("GPL");
186
~/ Read-only file preview.