cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dwmac-stm32.c (14974B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * dwmac-stm32.c - DWMAC Specific Glue layer for STM32 MCU
      4 *
      5 * Copyright (C) STMicroelectronics SA 2017
      6 * Author:  Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
      7 */
      8
      9#include <linux/clk.h>
     10#include <linux/kernel.h>
     11#include <linux/mfd/syscon.h>
     12#include <linux/module.h>
     13#include <linux/of.h>
     14#include <linux/of_device.h>
     15#include <linux/of_net.h>
     16#include <linux/phy.h>
     17#include <linux/platform_device.h>
     18#include <linux/pm_wakeirq.h>
     19#include <linux/regmap.h>
     20#include <linux/slab.h>
     21#include <linux/stmmac.h>
     22
     23#include "stmmac_platform.h"
     24
     25#define SYSCFG_MCU_ETH_MASK		BIT(23)
     26#define SYSCFG_MP1_ETH_MASK		GENMASK(23, 16)
     27#define SYSCFG_PMCCLRR_OFFSET		0x40
     28
     29#define SYSCFG_PMCR_ETH_CLK_SEL		BIT(16)
     30#define SYSCFG_PMCR_ETH_REF_CLK_SEL	BIT(17)
     31
     32/* CLOCK feed to PHY*/
     33#define ETH_CK_F_25M	25000000
     34#define ETH_CK_F_50M	50000000
     35#define ETH_CK_F_125M	125000000
     36
     37/*  Ethernet PHY interface selection in register SYSCFG Configuration
     38 *------------------------------------------
     39 * src	 |BIT(23)| BIT(22)| BIT(21)|BIT(20)|
     40 *------------------------------------------
     41 * MII   |   0	 |   0	  |   0    |   1   |
     42 *------------------------------------------
     43 * GMII  |   0	 |   0	  |   0    |   0   |
     44 *------------------------------------------
     45 * RGMII |   0	 |   0	  |   1	   |  n/a  |
     46 *------------------------------------------
     47 * RMII  |   1	 |   0	  |   0	   |  n/a  |
     48 *------------------------------------------
     49 */
     50#define SYSCFG_PMCR_ETH_SEL_MII		BIT(20)
     51#define SYSCFG_PMCR_ETH_SEL_RGMII	BIT(21)
     52#define SYSCFG_PMCR_ETH_SEL_RMII	BIT(23)
     53#define SYSCFG_PMCR_ETH_SEL_GMII	0
     54#define SYSCFG_MCU_ETH_SEL_MII		0
     55#define SYSCFG_MCU_ETH_SEL_RMII		1
     56
     57/* STM32MP1 register definitions
     58 *
     59 * Below table summarizes the clock requirement and clock sources for
     60 * supported phy interface modes.
     61 * __________________________________________________________________________
     62 *|PHY_MODE | Normal | PHY wo crystal|   PHY wo crystal   |No 125Mhz from PHY|
     63 *|         |        |      25MHz    |        50MHz       |                  |
     64 * ---------------------------------------------------------------------------
     65 *|  MII    |	 -   |     eth-ck    |	      n/a	  |	  n/a        |
     66 *|         |        | st,ext-phyclk |                    |		     |
     67 * ---------------------------------------------------------------------------
     68 *|  GMII   |	 -   |     eth-ck    |	      n/a	  |	  n/a        |
     69 *|         |        | st,ext-phyclk |                    |		     |
     70 * ---------------------------------------------------------------------------
     71 *| RGMII   |	 -   |     eth-ck    |	      n/a	  |      eth-ck      |
     72 *|         |        | st,ext-phyclk |                    | st,eth-clk-sel or|
     73 *|         |        |               |                    | st,ext-phyclk    |
     74 * ---------------------------------------------------------------------------
     75 *| RMII    |	 -   |     eth-ck    |	    eth-ck        |	  n/a        |
     76 *|         |        | st,ext-phyclk | st,eth-ref-clk-sel |		     |
     77 *|         |        |               | or st,ext-phyclk   |		     |
     78 * ---------------------------------------------------------------------------
     79 *
     80 */
     81
     82struct stm32_dwmac {
     83	struct clk *clk_tx;
     84	struct clk *clk_rx;
     85	struct clk *clk_eth_ck;
     86	struct clk *clk_ethstp;
     87	struct clk *syscfg_clk;
     88	int ext_phyclk;
     89	int enable_eth_ck;
     90	int eth_clk_sel_reg;
     91	int eth_ref_clk_sel_reg;
     92	int irq_pwr_wakeup;
     93	u32 mode_reg;		 /* MAC glue-logic mode register */
     94	struct regmap *regmap;
     95	u32 speed;
     96	const struct stm32_ops *ops;
     97	struct device *dev;
     98};
     99
    100struct stm32_ops {
    101	int (*set_mode)(struct plat_stmmacenet_data *plat_dat);
    102	int (*clk_prepare)(struct stm32_dwmac *dwmac, bool prepare);
    103	int (*suspend)(struct stm32_dwmac *dwmac);
    104	void (*resume)(struct stm32_dwmac *dwmac);
    105	int (*parse_data)(struct stm32_dwmac *dwmac,
    106			  struct device *dev);
    107	u32 syscfg_eth_mask;
    108};
    109
    110static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
    111{
    112	struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
    113	int ret;
    114
    115	if (dwmac->ops->set_mode) {
    116		ret = dwmac->ops->set_mode(plat_dat);
    117		if (ret)
    118			return ret;
    119	}
    120
    121	ret = clk_prepare_enable(dwmac->clk_tx);
    122	if (ret)
    123		return ret;
    124
    125	if (!dwmac->dev->power.is_suspended) {
    126		ret = clk_prepare_enable(dwmac->clk_rx);
    127		if (ret) {
    128			clk_disable_unprepare(dwmac->clk_tx);
    129			return ret;
    130		}
    131	}
    132
    133	if (dwmac->ops->clk_prepare) {
    134		ret = dwmac->ops->clk_prepare(dwmac, true);
    135		if (ret) {
    136			clk_disable_unprepare(dwmac->clk_rx);
    137			clk_disable_unprepare(dwmac->clk_tx);
    138		}
    139	}
    140
    141	return ret;
    142}
    143
    144static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare)
    145{
    146	int ret = 0;
    147
    148	if (prepare) {
    149		ret = clk_prepare_enable(dwmac->syscfg_clk);
    150		if (ret)
    151			return ret;
    152		if (dwmac->enable_eth_ck) {
    153			ret = clk_prepare_enable(dwmac->clk_eth_ck);
    154			if (ret) {
    155				clk_disable_unprepare(dwmac->syscfg_clk);
    156				return ret;
    157			}
    158		}
    159	} else {
    160		clk_disable_unprepare(dwmac->syscfg_clk);
    161		if (dwmac->enable_eth_ck)
    162			clk_disable_unprepare(dwmac->clk_eth_ck);
    163	}
    164	return ret;
    165}
    166
    167static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat)
    168{
    169	struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
    170	u32 reg = dwmac->mode_reg, clk_rate;
    171	int val;
    172
    173	clk_rate = clk_get_rate(dwmac->clk_eth_ck);
    174	dwmac->enable_eth_ck = false;
    175	switch (plat_dat->interface) {
    176	case PHY_INTERFACE_MODE_MII:
    177		if (clk_rate == ETH_CK_F_25M && dwmac->ext_phyclk)
    178			dwmac->enable_eth_ck = true;
    179		val = SYSCFG_PMCR_ETH_SEL_MII;
    180		pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n");
    181		break;
    182	case PHY_INTERFACE_MODE_GMII:
    183		val = SYSCFG_PMCR_ETH_SEL_GMII;
    184		if (clk_rate == ETH_CK_F_25M &&
    185		    (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) {
    186			dwmac->enable_eth_ck = true;
    187			val |= SYSCFG_PMCR_ETH_CLK_SEL;
    188		}
    189		pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n");
    190		break;
    191	case PHY_INTERFACE_MODE_RMII:
    192		val = SYSCFG_PMCR_ETH_SEL_RMII;
    193		if ((clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_50M) &&
    194		    (dwmac->eth_ref_clk_sel_reg || dwmac->ext_phyclk)) {
    195			dwmac->enable_eth_ck = true;
    196			val |= SYSCFG_PMCR_ETH_REF_CLK_SEL;
    197		}
    198		pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
    199		break;
    200	case PHY_INTERFACE_MODE_RGMII:
    201	case PHY_INTERFACE_MODE_RGMII_ID:
    202	case PHY_INTERFACE_MODE_RGMII_RXID:
    203	case PHY_INTERFACE_MODE_RGMII_TXID:
    204		val = SYSCFG_PMCR_ETH_SEL_RGMII;
    205		if ((clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_125M) &&
    206		    (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) {
    207			dwmac->enable_eth_ck = true;
    208			val |= SYSCFG_PMCR_ETH_CLK_SEL;
    209		}
    210		pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n");
    211		break;
    212	default:
    213		pr_debug("SYSCFG init :  Do not manage %d interface\n",
    214			 plat_dat->interface);
    215		/* Do not manage others interfaces */
    216		return -EINVAL;
    217	}
    218
    219	/* Need to update PMCCLRR (clear register) */
    220	regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET,
    221		     dwmac->ops->syscfg_eth_mask);
    222
    223	/* Update PMCSETR (set register) */
    224	return regmap_update_bits(dwmac->regmap, reg,
    225				 dwmac->ops->syscfg_eth_mask, val);
    226}
    227
    228static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat)
    229{
    230	struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
    231	u32 reg = dwmac->mode_reg;
    232	int val;
    233
    234	switch (plat_dat->interface) {
    235	case PHY_INTERFACE_MODE_MII:
    236		val = SYSCFG_MCU_ETH_SEL_MII;
    237		pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n");
    238		break;
    239	case PHY_INTERFACE_MODE_RMII:
    240		val = SYSCFG_MCU_ETH_SEL_RMII;
    241		pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n");
    242		break;
    243	default:
    244		pr_debug("SYSCFG init :  Do not manage %d interface\n",
    245			 plat_dat->interface);
    246		/* Do not manage others interfaces */
    247		return -EINVAL;
    248	}
    249
    250	return regmap_update_bits(dwmac->regmap, reg,
    251				 dwmac->ops->syscfg_eth_mask, val << 23);
    252}
    253
    254static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac)
    255{
    256	clk_disable_unprepare(dwmac->clk_tx);
    257	clk_disable_unprepare(dwmac->clk_rx);
    258
    259	if (dwmac->ops->clk_prepare)
    260		dwmac->ops->clk_prepare(dwmac, false);
    261}
    262
    263static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
    264				  struct device *dev)
    265{
    266	struct device_node *np = dev->of_node;
    267	int err;
    268
    269	/*  Get TX/RX clocks */
    270	dwmac->clk_tx = devm_clk_get(dev, "mac-clk-tx");
    271	if (IS_ERR(dwmac->clk_tx)) {
    272		dev_err(dev, "No ETH Tx clock provided...\n");
    273		return PTR_ERR(dwmac->clk_tx);
    274	}
    275
    276	dwmac->clk_rx = devm_clk_get(dev, "mac-clk-rx");
    277	if (IS_ERR(dwmac->clk_rx)) {
    278		dev_err(dev, "No ETH Rx clock provided...\n");
    279		return PTR_ERR(dwmac->clk_rx);
    280	}
    281
    282	if (dwmac->ops->parse_data) {
    283		err = dwmac->ops->parse_data(dwmac, dev);
    284		if (err)
    285			return err;
    286	}
    287
    288	/* Get mode register */
    289	dwmac->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
    290	if (IS_ERR(dwmac->regmap))
    291		return PTR_ERR(dwmac->regmap);
    292
    293	err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg);
    294	if (err)
    295		dev_err(dev, "Can't get sysconfig mode offset (%d)\n", err);
    296
    297	return err;
    298}
    299
    300static int stm32mp1_parse_data(struct stm32_dwmac *dwmac,
    301			       struct device *dev)
    302{
    303	struct platform_device *pdev = to_platform_device(dev);
    304	struct device_node *np = dev->of_node;
    305	int err = 0;
    306
    307	/* Ethernet PHY have no crystal */
    308	dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk");
    309
    310	/* Gigabit Ethernet 125MHz clock selection. */
    311	dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel");
    312
    313	/* Ethernet 50Mhz RMII clock selection */
    314	dwmac->eth_ref_clk_sel_reg =
    315		of_property_read_bool(np, "st,eth-ref-clk-sel");
    316
    317	/*  Get ETH_CLK clocks */
    318	dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck");
    319	if (IS_ERR(dwmac->clk_eth_ck)) {
    320		dev_info(dev, "No phy clock provided...\n");
    321		dwmac->clk_eth_ck = NULL;
    322	}
    323
    324	/*  Clock used for low power mode */
    325	dwmac->clk_ethstp = devm_clk_get(dev, "ethstp");
    326	if (IS_ERR(dwmac->clk_ethstp)) {
    327		dev_err(dev,
    328			"No ETH peripheral clock provided for CStop mode ...\n");
    329		return PTR_ERR(dwmac->clk_ethstp);
    330	}
    331
    332	/*  Optional Clock for sysconfig */
    333	dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk");
    334	if (IS_ERR(dwmac->syscfg_clk))
    335		dwmac->syscfg_clk = NULL;
    336
    337	/* Get IRQ information early to have an ability to ask for deferred
    338	 * probe if needed before we went too far with resource allocation.
    339	 */
    340	dwmac->irq_pwr_wakeup = platform_get_irq_byname_optional(pdev,
    341							"stm32_pwr_wakeup");
    342	if (dwmac->irq_pwr_wakeup == -EPROBE_DEFER)
    343		return -EPROBE_DEFER;
    344
    345	if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) {
    346		err = device_init_wakeup(&pdev->dev, true);
    347		if (err) {
    348			dev_err(&pdev->dev, "Failed to init wake up irq\n");
    349			return err;
    350		}
    351		err = dev_pm_set_dedicated_wake_irq(&pdev->dev,
    352						    dwmac->irq_pwr_wakeup);
    353		if (err) {
    354			dev_err(&pdev->dev, "Failed to set wake up irq\n");
    355			device_init_wakeup(&pdev->dev, false);
    356		}
    357		device_set_wakeup_enable(&pdev->dev, false);
    358	}
    359	return err;
    360}
    361
    362static int stm32_dwmac_probe(struct platform_device *pdev)
    363{
    364	struct plat_stmmacenet_data *plat_dat;
    365	struct stmmac_resources stmmac_res;
    366	struct stm32_dwmac *dwmac;
    367	const struct stm32_ops *data;
    368	int ret;
    369
    370	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
    371	if (ret)
    372		return ret;
    373
    374	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
    375	if (IS_ERR(plat_dat))
    376		return PTR_ERR(plat_dat);
    377
    378	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
    379	if (!dwmac) {
    380		ret = -ENOMEM;
    381		goto err_remove_config_dt;
    382	}
    383
    384	data = of_device_get_match_data(&pdev->dev);
    385	if (!data) {
    386		dev_err(&pdev->dev, "no of match data provided\n");
    387		ret = -EINVAL;
    388		goto err_remove_config_dt;
    389	}
    390
    391	dwmac->ops = data;
    392	dwmac->dev = &pdev->dev;
    393
    394	ret = stm32_dwmac_parse_data(dwmac, &pdev->dev);
    395	if (ret) {
    396		dev_err(&pdev->dev, "Unable to parse OF data\n");
    397		goto err_remove_config_dt;
    398	}
    399
    400	plat_dat->bsp_priv = dwmac;
    401
    402	ret = stm32_dwmac_init(plat_dat);
    403	if (ret)
    404		goto err_remove_config_dt;
    405
    406	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
    407	if (ret)
    408		goto err_clk_disable;
    409
    410	return 0;
    411
    412err_clk_disable:
    413	stm32_dwmac_clk_disable(dwmac);
    414err_remove_config_dt:
    415	stmmac_remove_config_dt(pdev, plat_dat);
    416
    417	return ret;
    418}
    419
    420static int stm32_dwmac_remove(struct platform_device *pdev)
    421{
    422	struct net_device *ndev = platform_get_drvdata(pdev);
    423	struct stmmac_priv *priv = netdev_priv(ndev);
    424	int ret = stmmac_dvr_remove(&pdev->dev);
    425	struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
    426
    427	stm32_dwmac_clk_disable(priv->plat->bsp_priv);
    428
    429	if (dwmac->irq_pwr_wakeup >= 0) {
    430		dev_pm_clear_wake_irq(&pdev->dev);
    431		device_init_wakeup(&pdev->dev, false);
    432	}
    433
    434	return ret;
    435}
    436
    437static int stm32mp1_suspend(struct stm32_dwmac *dwmac)
    438{
    439	int ret = 0;
    440
    441	ret = clk_prepare_enable(dwmac->clk_ethstp);
    442	if (ret)
    443		return ret;
    444
    445	clk_disable_unprepare(dwmac->clk_tx);
    446	clk_disable_unprepare(dwmac->syscfg_clk);
    447	if (dwmac->enable_eth_ck)
    448		clk_disable_unprepare(dwmac->clk_eth_ck);
    449
    450	return ret;
    451}
    452
    453static void stm32mp1_resume(struct stm32_dwmac *dwmac)
    454{
    455	clk_disable_unprepare(dwmac->clk_ethstp);
    456}
    457
    458static int stm32mcu_suspend(struct stm32_dwmac *dwmac)
    459{
    460	clk_disable_unprepare(dwmac->clk_tx);
    461	clk_disable_unprepare(dwmac->clk_rx);
    462
    463	return 0;
    464}
    465
    466#ifdef CONFIG_PM_SLEEP
    467static int stm32_dwmac_suspend(struct device *dev)
    468{
    469	struct net_device *ndev = dev_get_drvdata(dev);
    470	struct stmmac_priv *priv = netdev_priv(ndev);
    471	struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
    472
    473	int ret;
    474
    475	ret = stmmac_suspend(dev);
    476
    477	if (dwmac->ops->suspend)
    478		ret = dwmac->ops->suspend(dwmac);
    479
    480	return ret;
    481}
    482
    483static int stm32_dwmac_resume(struct device *dev)
    484{
    485	struct net_device *ndev = dev_get_drvdata(dev);
    486	struct stmmac_priv *priv = netdev_priv(ndev);
    487	struct stm32_dwmac *dwmac = priv->plat->bsp_priv;
    488	int ret;
    489
    490	if (dwmac->ops->resume)
    491		dwmac->ops->resume(dwmac);
    492
    493	ret = stm32_dwmac_init(priv->plat);
    494	if (ret)
    495		return ret;
    496
    497	ret = stmmac_resume(dev);
    498
    499	return ret;
    500}
    501#endif /* CONFIG_PM_SLEEP */
    502
    503static SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops,
    504	stm32_dwmac_suspend, stm32_dwmac_resume);
    505
    506static struct stm32_ops stm32mcu_dwmac_data = {
    507	.set_mode = stm32mcu_set_mode,
    508	.suspend = stm32mcu_suspend,
    509	.syscfg_eth_mask = SYSCFG_MCU_ETH_MASK
    510};
    511
    512static struct stm32_ops stm32mp1_dwmac_data = {
    513	.set_mode = stm32mp1_set_mode,
    514	.clk_prepare = stm32mp1_clk_prepare,
    515	.suspend = stm32mp1_suspend,
    516	.resume = stm32mp1_resume,
    517	.parse_data = stm32mp1_parse_data,
    518	.syscfg_eth_mask = SYSCFG_MP1_ETH_MASK
    519};
    520
    521static const struct of_device_id stm32_dwmac_match[] = {
    522	{ .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data},
    523	{ .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data},
    524	{ }
    525};
    526MODULE_DEVICE_TABLE(of, stm32_dwmac_match);
    527
    528static struct platform_driver stm32_dwmac_driver = {
    529	.probe  = stm32_dwmac_probe,
    530	.remove = stm32_dwmac_remove,
    531	.driver = {
    532		.name           = "stm32-dwmac",
    533		.pm		= &stm32_dwmac_pm_ops,
    534		.of_match_table = stm32_dwmac_match,
    535	},
    536};
    537module_platform_driver(stm32_dwmac_driver);
    538
    539MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@gmail.com>");
    540MODULE_AUTHOR("Christophe Roullier <christophe.roullier@st.com>");
    541MODULE_DESCRIPTION("STMicroelectronics STM32 DWMAC Specific Glue layer");
    542MODULE_LICENSE("GPL v2");