FILE
dwmac-s32.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.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.