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-ingenic.c (11070B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * dwmac-ingenic.c - Ingenic SoCs DWMAC specific glue layer
      4 *
      5 * Copyright (c) 2021 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
      6 */
      7
      8#include <linux/bitfield.h>
      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/regmap.h>
     19#include <linux/slab.h>
     20#include <linux/stmmac.h>
     21
     22#include "stmmac_platform.h"
     23
     24#define MACPHYC_TXCLK_SEL_MASK		GENMASK(31, 31)
     25#define MACPHYC_TXCLK_SEL_OUTPUT	0x1
     26#define MACPHYC_TXCLK_SEL_INPUT		0x0
     27#define MACPHYC_MODE_SEL_MASK		GENMASK(31, 31)
     28#define MACPHYC_MODE_SEL_RMII		0x0
     29#define MACPHYC_TX_SEL_MASK			GENMASK(19, 19)
     30#define MACPHYC_TX_SEL_ORIGIN		0x0
     31#define MACPHYC_TX_SEL_DELAY		0x1
     32#define MACPHYC_TX_DELAY_MASK		GENMASK(18, 12)
     33#define MACPHYC_RX_SEL_MASK			GENMASK(11, 11)
     34#define MACPHYC_RX_SEL_ORIGIN		0x0
     35#define MACPHYC_RX_SEL_DELAY		0x1
     36#define MACPHYC_RX_DELAY_MASK		GENMASK(10, 4)
     37#define MACPHYC_SOFT_RST_MASK		GENMASK(3, 3)
     38#define MACPHYC_PHY_INFT_MASK		GENMASK(2, 0)
     39#define MACPHYC_PHY_INFT_RMII		0x4
     40#define MACPHYC_PHY_INFT_RGMII		0x1
     41#define MACPHYC_PHY_INFT_GMII		0x0
     42#define MACPHYC_PHY_INFT_MII		0x0
     43
     44#define MACPHYC_TX_DELAY_PS_MAX		2496
     45#define MACPHYC_TX_DELAY_PS_MIN		20
     46
     47#define MACPHYC_RX_DELAY_PS_MAX		2496
     48#define MACPHYC_RX_DELAY_PS_MIN		20
     49
     50enum ingenic_mac_version {
     51	ID_JZ4775,
     52	ID_X1000,
     53	ID_X1600,
     54	ID_X1830,
     55	ID_X2000,
     56};
     57
     58struct ingenic_mac {
     59	const struct ingenic_soc_info *soc_info;
     60	struct device *dev;
     61	struct regmap *regmap;
     62
     63	int rx_delay;
     64	int tx_delay;
     65};
     66
     67struct ingenic_soc_info {
     68	enum ingenic_mac_version version;
     69	u32 mask;
     70
     71	int (*set_mode)(struct plat_stmmacenet_data *plat_dat);
     72};
     73
     74static int ingenic_mac_init(struct plat_stmmacenet_data *plat_dat)
     75{
     76	struct ingenic_mac *mac = plat_dat->bsp_priv;
     77	int ret;
     78
     79	if (mac->soc_info->set_mode) {
     80		ret = mac->soc_info->set_mode(plat_dat);
     81		if (ret)
     82			return ret;
     83	}
     84
     85	return 0;
     86}
     87
     88static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
     89{
     90	struct ingenic_mac *mac = plat_dat->bsp_priv;
     91	unsigned int val;
     92
     93	switch (plat_dat->interface) {
     94	case PHY_INTERFACE_MODE_MII:
     95		val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
     96			  FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_MII);
     97		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_MII\n");
     98		break;
     99
    100	case PHY_INTERFACE_MODE_GMII:
    101		val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
    102			  FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_GMII);
    103		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_GMII\n");
    104		break;
    105
    106	case PHY_INTERFACE_MODE_RMII:
    107		val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
    108			  FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
    109		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
    110		break;
    111
    112	case PHY_INTERFACE_MODE_RGMII:
    113	case PHY_INTERFACE_MODE_RGMII_ID:
    114	case PHY_INTERFACE_MODE_RGMII_TXID:
    115	case PHY_INTERFACE_MODE_RGMII_RXID:
    116		val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) |
    117			  FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII);
    118		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n");
    119		break;
    120
    121	default:
    122		dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
    123		return -EINVAL;
    124	}
    125
    126	/* Update MAC PHY control register */
    127	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
    128}
    129
    130static int x1000_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
    131{
    132	struct ingenic_mac *mac = plat_dat->bsp_priv;
    133
    134	switch (plat_dat->interface) {
    135	case PHY_INTERFACE_MODE_RMII:
    136		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
    137		break;
    138
    139	default:
    140		dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
    141		return -EINVAL;
    142	}
    143
    144	/* Update MAC PHY control register */
    145	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, 0);
    146}
    147
    148static int x1600_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
    149{
    150	struct ingenic_mac *mac = plat_dat->bsp_priv;
    151	unsigned int val;
    152
    153	switch (plat_dat->interface) {
    154	case PHY_INTERFACE_MODE_RMII:
    155		val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
    156		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
    157		break;
    158
    159	default:
    160		dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
    161		return -EINVAL;
    162	}
    163
    164	/* Update MAC PHY control register */
    165	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
    166}
    167
    168static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
    169{
    170	struct ingenic_mac *mac = plat_dat->bsp_priv;
    171	unsigned int val;
    172
    173	switch (plat_dat->interface) {
    174	case PHY_INTERFACE_MODE_RMII:
    175		val = FIELD_PREP(MACPHYC_MODE_SEL_MASK, MACPHYC_MODE_SEL_RMII) |
    176			  FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
    177		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
    178		break;
    179
    180	default:
    181		dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
    182		return -EINVAL;
    183	}
    184
    185	/* Update MAC PHY control register */
    186	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
    187}
    188
    189static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat)
    190{
    191	struct ingenic_mac *mac = plat_dat->bsp_priv;
    192	unsigned int val;
    193
    194	switch (plat_dat->interface) {
    195	case PHY_INTERFACE_MODE_RMII:
    196		val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) |
    197			  FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) |
    198			  FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII);
    199		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n");
    200		break;
    201
    202	case PHY_INTERFACE_MODE_RGMII:
    203	case PHY_INTERFACE_MODE_RGMII_ID:
    204	case PHY_INTERFACE_MODE_RGMII_TXID:
    205	case PHY_INTERFACE_MODE_RGMII_RXID:
    206		val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RGMII);
    207
    208		if (mac->tx_delay == 0)
    209			val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN);
    210		else
    211			val |= FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_DELAY) |
    212				   FIELD_PREP(MACPHYC_TX_DELAY_MASK, (mac->tx_delay + 9750) / 19500 - 1);
    213
    214		if (mac->rx_delay == 0)
    215			val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN);
    216		else
    217			val |= FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_DELAY) |
    218				   FIELD_PREP(MACPHYC_RX_DELAY_MASK, (mac->rx_delay + 9750) / 19500 - 1);
    219
    220		dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RGMII\n");
    221		break;
    222
    223	default:
    224		dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface);
    225		return -EINVAL;
    226	}
    227
    228	/* Update MAC PHY control register */
    229	return regmap_update_bits(mac->regmap, 0, mac->soc_info->mask, val);
    230}
    231
    232static int ingenic_mac_probe(struct platform_device *pdev)
    233{
    234	struct plat_stmmacenet_data *plat_dat;
    235	struct stmmac_resources stmmac_res;
    236	struct ingenic_mac *mac;
    237	const struct ingenic_soc_info *data;
    238	u32 tx_delay_ps, rx_delay_ps;
    239	int ret;
    240
    241	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
    242	if (ret)
    243		return ret;
    244
    245	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
    246	if (IS_ERR(plat_dat))
    247		return PTR_ERR(plat_dat);
    248
    249	mac = devm_kzalloc(&pdev->dev, sizeof(*mac), GFP_KERNEL);
    250	if (!mac) {
    251		ret = -ENOMEM;
    252		goto err_remove_config_dt;
    253	}
    254
    255	data = of_device_get_match_data(&pdev->dev);
    256	if (!data) {
    257		dev_err(&pdev->dev, "No of match data provided\n");
    258		ret = -EINVAL;
    259		goto err_remove_config_dt;
    260	}
    261
    262	/* Get MAC PHY control register */
    263	mac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "mode-reg");
    264	if (IS_ERR(mac->regmap)) {
    265		dev_err(&pdev->dev, "%s: Failed to get syscon regmap\n", __func__);
    266		ret = PTR_ERR(mac->regmap);
    267		goto err_remove_config_dt;
    268	}
    269
    270	if (!of_property_read_u32(pdev->dev.of_node, "tx-clk-delay-ps", &tx_delay_ps)) {
    271		if (tx_delay_ps >= MACPHYC_TX_DELAY_PS_MIN &&
    272			tx_delay_ps <= MACPHYC_TX_DELAY_PS_MAX) {
    273			mac->tx_delay = tx_delay_ps * 1000;
    274		} else {
    275			dev_err(&pdev->dev, "Invalid TX clock delay: %dps\n", tx_delay_ps);
    276			return -EINVAL;
    277		}
    278	}
    279
    280	if (!of_property_read_u32(pdev->dev.of_node, "rx-clk-delay-ps", &rx_delay_ps)) {
    281		if (rx_delay_ps >= MACPHYC_RX_DELAY_PS_MIN &&
    282			rx_delay_ps <= MACPHYC_RX_DELAY_PS_MAX) {
    283			mac->rx_delay = rx_delay_ps * 1000;
    284		} else {
    285			dev_err(&pdev->dev, "Invalid RX clock delay: %dps\n", rx_delay_ps);
    286			return -EINVAL;
    287		}
    288	}
    289
    290	mac->soc_info = data;
    291	mac->dev = &pdev->dev;
    292
    293	plat_dat->bsp_priv = mac;
    294
    295	ret = ingenic_mac_init(plat_dat);
    296	if (ret)
    297		goto err_remove_config_dt;
    298
    299	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
    300	if (ret)
    301		goto err_remove_config_dt;
    302
    303	return 0;
    304
    305err_remove_config_dt:
    306	stmmac_remove_config_dt(pdev, plat_dat);
    307
    308	return ret;
    309}
    310
    311#ifdef CONFIG_PM_SLEEP
    312static int ingenic_mac_suspend(struct device *dev)
    313{
    314	int ret;
    315
    316	ret = stmmac_suspend(dev);
    317
    318	return ret;
    319}
    320
    321static int ingenic_mac_resume(struct device *dev)
    322{
    323	struct net_device *ndev = dev_get_drvdata(dev);
    324	struct stmmac_priv *priv = netdev_priv(ndev);
    325	int ret;
    326
    327	ret = ingenic_mac_init(priv->plat);
    328	if (ret)
    329		return ret;
    330
    331	ret = stmmac_resume(dev);
    332
    333	return ret;
    334}
    335#endif /* CONFIG_PM_SLEEP */
    336
    337static SIMPLE_DEV_PM_OPS(ingenic_mac_pm_ops, ingenic_mac_suspend, ingenic_mac_resume);
    338
    339static struct ingenic_soc_info jz4775_soc_info = {
    340	.version = ID_JZ4775,
    341	.mask = MACPHYC_TXCLK_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
    342
    343	.set_mode = jz4775_mac_set_mode,
    344};
    345
    346static struct ingenic_soc_info x1000_soc_info = {
    347	.version = ID_X1000,
    348	.mask = MACPHYC_SOFT_RST_MASK,
    349
    350	.set_mode = x1000_mac_set_mode,
    351};
    352
    353static struct ingenic_soc_info x1600_soc_info = {
    354	.version = ID_X1600,
    355	.mask = MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
    356
    357	.set_mode = x1600_mac_set_mode,
    358};
    359
    360static struct ingenic_soc_info x1830_soc_info = {
    361	.version = ID_X1830,
    362	.mask = MACPHYC_MODE_SEL_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
    363
    364	.set_mode = x1830_mac_set_mode,
    365};
    366
    367static struct ingenic_soc_info x2000_soc_info = {
    368	.version = ID_X2000,
    369	.mask = MACPHYC_TX_SEL_MASK | MACPHYC_TX_DELAY_MASK | MACPHYC_RX_SEL_MASK |
    370			MACPHYC_RX_DELAY_MASK | MACPHYC_SOFT_RST_MASK | MACPHYC_PHY_INFT_MASK,
    371
    372	.set_mode = x2000_mac_set_mode,
    373};
    374
    375static const struct of_device_id ingenic_mac_of_matches[] = {
    376	{ .compatible = "ingenic,jz4775-mac", .data = &jz4775_soc_info },
    377	{ .compatible = "ingenic,x1000-mac", .data = &x1000_soc_info },
    378	{ .compatible = "ingenic,x1600-mac", .data = &x1600_soc_info },
    379	{ .compatible = "ingenic,x1830-mac", .data = &x1830_soc_info },
    380	{ .compatible = "ingenic,x2000-mac", .data = &x2000_soc_info },
    381	{ }
    382};
    383MODULE_DEVICE_TABLE(of, ingenic_mac_of_matches);
    384
    385static struct platform_driver ingenic_mac_driver = {
    386	.probe		= ingenic_mac_probe,
    387	.remove		= stmmac_pltfr_remove,
    388	.driver		= {
    389		.name	= "ingenic-mac",
    390		.pm		= pm_ptr(&ingenic_mac_pm_ops),
    391		.of_match_table = ingenic_mac_of_matches,
    392	},
    393};
    394module_platform_driver(ingenic_mac_driver);
    395
    396MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
    397MODULE_DESCRIPTION("Ingenic SoCs DWMAC specific glue layer");
    398MODULE_LICENSE("GPL v2");