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

realtek-smi.c (13594B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/* Realtek Simple Management Interface (SMI) driver
      3 * It can be discussed how "simple" this interface is.
      4 *
      5 * The SMI protocol piggy-backs the MDIO MDC and MDIO signals levels
      6 * but the protocol is not MDIO at all. Instead it is a Realtek
      7 * pecularity that need to bit-bang the lines in a special way to
      8 * communicate with the switch.
      9 *
     10 * ASICs we intend to support with this driver:
     11 *
     12 * RTL8366   - The original version, apparently
     13 * RTL8369   - Similar enough to have the same datsheet as RTL8366
     14 * RTL8366RB - Probably reads out "RTL8366 revision B", has a quite
     15 *             different register layout from the other two
     16 * RTL8366S  - Is this "RTL8366 super"?
     17 * RTL8367   - Has an OpenWRT driver as well
     18 * RTL8368S  - Seems to be an alternative name for RTL8366RB
     19 * RTL8370   - Also uses SMI
     20 *
     21 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
     22 * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
     23 * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
     24 * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
     25 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
     26 */
     27
     28#include <linux/kernel.h>
     29#include <linux/module.h>
     30#include <linux/device.h>
     31#include <linux/spinlock.h>
     32#include <linux/skbuff.h>
     33#include <linux/of.h>
     34#include <linux/of_device.h>
     35#include <linux/of_mdio.h>
     36#include <linux/delay.h>
     37#include <linux/gpio/consumer.h>
     38#include <linux/platform_device.h>
     39#include <linux/regmap.h>
     40#include <linux/bitops.h>
     41#include <linux/if_bridge.h>
     42
     43#include "realtek.h"
     44
     45#define REALTEK_SMI_ACK_RETRY_COUNT		5
     46
     47static inline void realtek_smi_clk_delay(struct realtek_priv *priv)
     48{
     49	ndelay(priv->clk_delay);
     50}
     51
     52static void realtek_smi_start(struct realtek_priv *priv)
     53{
     54	/* Set GPIO pins to output mode, with initial state:
     55	 * SCK = 0, SDA = 1
     56	 */
     57	gpiod_direction_output(priv->mdc, 0);
     58	gpiod_direction_output(priv->mdio, 1);
     59	realtek_smi_clk_delay(priv);
     60
     61	/* CLK 1: 0 -> 1, 1 -> 0 */
     62	gpiod_set_value(priv->mdc, 1);
     63	realtek_smi_clk_delay(priv);
     64	gpiod_set_value(priv->mdc, 0);
     65	realtek_smi_clk_delay(priv);
     66
     67	/* CLK 2: */
     68	gpiod_set_value(priv->mdc, 1);
     69	realtek_smi_clk_delay(priv);
     70	gpiod_set_value(priv->mdio, 0);
     71	realtek_smi_clk_delay(priv);
     72	gpiod_set_value(priv->mdc, 0);
     73	realtek_smi_clk_delay(priv);
     74	gpiod_set_value(priv->mdio, 1);
     75}
     76
     77static void realtek_smi_stop(struct realtek_priv *priv)
     78{
     79	realtek_smi_clk_delay(priv);
     80	gpiod_set_value(priv->mdio, 0);
     81	gpiod_set_value(priv->mdc, 1);
     82	realtek_smi_clk_delay(priv);
     83	gpiod_set_value(priv->mdio, 1);
     84	realtek_smi_clk_delay(priv);
     85	gpiod_set_value(priv->mdc, 1);
     86	realtek_smi_clk_delay(priv);
     87	gpiod_set_value(priv->mdc, 0);
     88	realtek_smi_clk_delay(priv);
     89	gpiod_set_value(priv->mdc, 1);
     90
     91	/* Add a click */
     92	realtek_smi_clk_delay(priv);
     93	gpiod_set_value(priv->mdc, 0);
     94	realtek_smi_clk_delay(priv);
     95	gpiod_set_value(priv->mdc, 1);
     96
     97	/* Set GPIO pins to input mode */
     98	gpiod_direction_input(priv->mdio);
     99	gpiod_direction_input(priv->mdc);
    100}
    101
    102static void realtek_smi_write_bits(struct realtek_priv *priv, u32 data, u32 len)
    103{
    104	for (; len > 0; len--) {
    105		realtek_smi_clk_delay(priv);
    106
    107		/* Prepare data */
    108		gpiod_set_value(priv->mdio, !!(data & (1 << (len - 1))));
    109		realtek_smi_clk_delay(priv);
    110
    111		/* Clocking */
    112		gpiod_set_value(priv->mdc, 1);
    113		realtek_smi_clk_delay(priv);
    114		gpiod_set_value(priv->mdc, 0);
    115	}
    116}
    117
    118static void realtek_smi_read_bits(struct realtek_priv *priv, u32 len, u32 *data)
    119{
    120	gpiod_direction_input(priv->mdio);
    121
    122	for (*data = 0; len > 0; len--) {
    123		u32 u;
    124
    125		realtek_smi_clk_delay(priv);
    126
    127		/* Clocking */
    128		gpiod_set_value(priv->mdc, 1);
    129		realtek_smi_clk_delay(priv);
    130		u = !!gpiod_get_value(priv->mdio);
    131		gpiod_set_value(priv->mdc, 0);
    132
    133		*data |= (u << (len - 1));
    134	}
    135
    136	gpiod_direction_output(priv->mdio, 0);
    137}
    138
    139static int realtek_smi_wait_for_ack(struct realtek_priv *priv)
    140{
    141	int retry_cnt;
    142
    143	retry_cnt = 0;
    144	do {
    145		u32 ack;
    146
    147		realtek_smi_read_bits(priv, 1, &ack);
    148		if (ack == 0)
    149			break;
    150
    151		if (++retry_cnt > REALTEK_SMI_ACK_RETRY_COUNT) {
    152			dev_err(priv->dev, "ACK timeout\n");
    153			return -ETIMEDOUT;
    154		}
    155	} while (1);
    156
    157	return 0;
    158}
    159
    160static int realtek_smi_write_byte(struct realtek_priv *priv, u8 data)
    161{
    162	realtek_smi_write_bits(priv, data, 8);
    163	return realtek_smi_wait_for_ack(priv);
    164}
    165
    166static int realtek_smi_write_byte_noack(struct realtek_priv *priv, u8 data)
    167{
    168	realtek_smi_write_bits(priv, data, 8);
    169	return 0;
    170}
    171
    172static int realtek_smi_read_byte0(struct realtek_priv *priv, u8 *data)
    173{
    174	u32 t;
    175
    176	/* Read data */
    177	realtek_smi_read_bits(priv, 8, &t);
    178	*data = (t & 0xff);
    179
    180	/* Send an ACK */
    181	realtek_smi_write_bits(priv, 0x00, 1);
    182
    183	return 0;
    184}
    185
    186static int realtek_smi_read_byte1(struct realtek_priv *priv, u8 *data)
    187{
    188	u32 t;
    189
    190	/* Read data */
    191	realtek_smi_read_bits(priv, 8, &t);
    192	*data = (t & 0xff);
    193
    194	/* Send an ACK */
    195	realtek_smi_write_bits(priv, 0x01, 1);
    196
    197	return 0;
    198}
    199
    200static int realtek_smi_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
    201{
    202	unsigned long flags;
    203	u8 lo = 0;
    204	u8 hi = 0;
    205	int ret;
    206
    207	spin_lock_irqsave(&priv->lock, flags);
    208
    209	realtek_smi_start(priv);
    210
    211	/* Send READ command */
    212	ret = realtek_smi_write_byte(priv, priv->cmd_read);
    213	if (ret)
    214		goto out;
    215
    216	/* Set ADDR[7:0] */
    217	ret = realtek_smi_write_byte(priv, addr & 0xff);
    218	if (ret)
    219		goto out;
    220
    221	/* Set ADDR[15:8] */
    222	ret = realtek_smi_write_byte(priv, addr >> 8);
    223	if (ret)
    224		goto out;
    225
    226	/* Read DATA[7:0] */
    227	realtek_smi_read_byte0(priv, &lo);
    228	/* Read DATA[15:8] */
    229	realtek_smi_read_byte1(priv, &hi);
    230
    231	*data = ((u32)lo) | (((u32)hi) << 8);
    232
    233	ret = 0;
    234
    235 out:
    236	realtek_smi_stop(priv);
    237	spin_unlock_irqrestore(&priv->lock, flags);
    238
    239	return ret;
    240}
    241
    242static int realtek_smi_write_reg(struct realtek_priv *priv,
    243				 u32 addr, u32 data, bool ack)
    244{
    245	unsigned long flags;
    246	int ret;
    247
    248	spin_lock_irqsave(&priv->lock, flags);
    249
    250	realtek_smi_start(priv);
    251
    252	/* Send WRITE command */
    253	ret = realtek_smi_write_byte(priv, priv->cmd_write);
    254	if (ret)
    255		goto out;
    256
    257	/* Set ADDR[7:0] */
    258	ret = realtek_smi_write_byte(priv, addr & 0xff);
    259	if (ret)
    260		goto out;
    261
    262	/* Set ADDR[15:8] */
    263	ret = realtek_smi_write_byte(priv, addr >> 8);
    264	if (ret)
    265		goto out;
    266
    267	/* Write DATA[7:0] */
    268	ret = realtek_smi_write_byte(priv, data & 0xff);
    269	if (ret)
    270		goto out;
    271
    272	/* Write DATA[15:8] */
    273	if (ack)
    274		ret = realtek_smi_write_byte(priv, data >> 8);
    275	else
    276		ret = realtek_smi_write_byte_noack(priv, data >> 8);
    277	if (ret)
    278		goto out;
    279
    280	ret = 0;
    281
    282 out:
    283	realtek_smi_stop(priv);
    284	spin_unlock_irqrestore(&priv->lock, flags);
    285
    286	return ret;
    287}
    288
    289/* There is one single case when we need to use this accessor and that
    290 * is when issueing soft reset. Since the device reset as soon as we write
    291 * that bit, no ACK will come back for natural reasons.
    292 */
    293static int realtek_smi_write_reg_noack(void *ctx, u32 reg, u32 val)
    294{
    295	return realtek_smi_write_reg(ctx, reg, val, false);
    296}
    297
    298/* Regmap accessors */
    299
    300static int realtek_smi_write(void *ctx, u32 reg, u32 val)
    301{
    302	struct realtek_priv *priv = ctx;
    303
    304	return realtek_smi_write_reg(priv, reg, val, true);
    305}
    306
    307static int realtek_smi_read(void *ctx, u32 reg, u32 *val)
    308{
    309	struct realtek_priv *priv = ctx;
    310
    311	return realtek_smi_read_reg(priv, reg, val);
    312}
    313
    314static void realtek_smi_lock(void *ctx)
    315{
    316	struct realtek_priv *priv = ctx;
    317
    318	mutex_lock(&priv->map_lock);
    319}
    320
    321static void realtek_smi_unlock(void *ctx)
    322{
    323	struct realtek_priv *priv = ctx;
    324
    325	mutex_unlock(&priv->map_lock);
    326}
    327
    328static const struct regmap_config realtek_smi_regmap_config = {
    329	.reg_bits = 10, /* A4..A0 R4..R0 */
    330	.val_bits = 16,
    331	.reg_stride = 1,
    332	/* PHY regs are at 0x8000 */
    333	.max_register = 0xffff,
    334	.reg_format_endian = REGMAP_ENDIAN_BIG,
    335	.reg_read = realtek_smi_read,
    336	.reg_write = realtek_smi_write,
    337	.cache_type = REGCACHE_NONE,
    338	.lock = realtek_smi_lock,
    339	.unlock = realtek_smi_unlock,
    340};
    341
    342static const struct regmap_config realtek_smi_nolock_regmap_config = {
    343	.reg_bits = 10, /* A4..A0 R4..R0 */
    344	.val_bits = 16,
    345	.reg_stride = 1,
    346	/* PHY regs are at 0x8000 */
    347	.max_register = 0xffff,
    348	.reg_format_endian = REGMAP_ENDIAN_BIG,
    349	.reg_read = realtek_smi_read,
    350	.reg_write = realtek_smi_write,
    351	.cache_type = REGCACHE_NONE,
    352	.disable_locking = true,
    353};
    354
    355static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
    356{
    357	struct realtek_priv *priv = bus->priv;
    358
    359	return priv->ops->phy_read(priv, addr, regnum);
    360}
    361
    362static int realtek_smi_mdio_write(struct mii_bus *bus, int addr, int regnum,
    363				  u16 val)
    364{
    365	struct realtek_priv *priv = bus->priv;
    366
    367	return priv->ops->phy_write(priv, addr, regnum, val);
    368}
    369
    370static int realtek_smi_setup_mdio(struct dsa_switch *ds)
    371{
    372	struct realtek_priv *priv =  ds->priv;
    373	struct device_node *mdio_np;
    374	int ret;
    375
    376	mdio_np = of_get_compatible_child(priv->dev->of_node, "realtek,smi-mdio");
    377	if (!mdio_np) {
    378		dev_err(priv->dev, "no MDIO bus node\n");
    379		return -ENODEV;
    380	}
    381
    382	priv->slave_mii_bus = devm_mdiobus_alloc(priv->dev);
    383	if (!priv->slave_mii_bus) {
    384		ret = -ENOMEM;
    385		goto err_put_node;
    386	}
    387	priv->slave_mii_bus->priv = priv;
    388	priv->slave_mii_bus->name = "SMI slave MII";
    389	priv->slave_mii_bus->read = realtek_smi_mdio_read;
    390	priv->slave_mii_bus->write = realtek_smi_mdio_write;
    391	snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
    392		 ds->index);
    393	priv->slave_mii_bus->dev.of_node = mdio_np;
    394	priv->slave_mii_bus->parent = priv->dev;
    395	ds->slave_mii_bus = priv->slave_mii_bus;
    396
    397	ret = devm_of_mdiobus_register(priv->dev, priv->slave_mii_bus, mdio_np);
    398	if (ret) {
    399		dev_err(priv->dev, "unable to register MDIO bus %s\n",
    400			priv->slave_mii_bus->id);
    401		goto err_put_node;
    402	}
    403
    404	return 0;
    405
    406err_put_node:
    407	of_node_put(mdio_np);
    408
    409	return ret;
    410}
    411
    412static int realtek_smi_probe(struct platform_device *pdev)
    413{
    414	const struct realtek_variant *var;
    415	struct device *dev = &pdev->dev;
    416	struct realtek_priv *priv;
    417	struct regmap_config rc;
    418	struct device_node *np;
    419	int ret;
    420
    421	var = of_device_get_match_data(dev);
    422	np = dev->of_node;
    423
    424	priv = devm_kzalloc(dev, sizeof(*priv) + var->chip_data_sz, GFP_KERNEL);
    425	if (!priv)
    426		return -ENOMEM;
    427	priv->chip_data = (void *)priv + sizeof(*priv);
    428
    429	mutex_init(&priv->map_lock);
    430
    431	rc = realtek_smi_regmap_config;
    432	rc.lock_arg = priv;
    433	priv->map = devm_regmap_init(dev, NULL, priv, &rc);
    434	if (IS_ERR(priv->map)) {
    435		ret = PTR_ERR(priv->map);
    436		dev_err(dev, "regmap init failed: %d\n", ret);
    437		return ret;
    438	}
    439
    440	rc = realtek_smi_nolock_regmap_config;
    441	priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
    442	if (IS_ERR(priv->map_nolock)) {
    443		ret = PTR_ERR(priv->map_nolock);
    444		dev_err(dev, "regmap init failed: %d\n", ret);
    445		return ret;
    446	}
    447
    448	/* Link forward and backward */
    449	priv->dev = dev;
    450	priv->clk_delay = var->clk_delay;
    451	priv->cmd_read = var->cmd_read;
    452	priv->cmd_write = var->cmd_write;
    453	priv->ops = var->ops;
    454
    455	priv->setup_interface = realtek_smi_setup_mdio;
    456	priv->write_reg_noack = realtek_smi_write_reg_noack;
    457
    458	dev_set_drvdata(dev, priv);
    459	spin_lock_init(&priv->lock);
    460
    461	/* TODO: if power is software controlled, set up any regulators here */
    462
    463	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
    464	if (IS_ERR(priv->reset)) {
    465		dev_err(dev, "failed to get RESET GPIO\n");
    466		return PTR_ERR(priv->reset);
    467	}
    468	if (priv->reset) {
    469		gpiod_set_value(priv->reset, 1);
    470		dev_dbg(dev, "asserted RESET\n");
    471		msleep(REALTEK_HW_STOP_DELAY);
    472		gpiod_set_value(priv->reset, 0);
    473		msleep(REALTEK_HW_START_DELAY);
    474		dev_dbg(dev, "deasserted RESET\n");
    475	}
    476
    477	/* Fetch MDIO pins */
    478	priv->mdc = devm_gpiod_get_optional(dev, "mdc", GPIOD_OUT_LOW);
    479	if (IS_ERR(priv->mdc))
    480		return PTR_ERR(priv->mdc);
    481	priv->mdio = devm_gpiod_get_optional(dev, "mdio", GPIOD_OUT_LOW);
    482	if (IS_ERR(priv->mdio))
    483		return PTR_ERR(priv->mdio);
    484
    485	priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
    486
    487	ret = priv->ops->detect(priv);
    488	if (ret) {
    489		dev_err(dev, "unable to detect switch\n");
    490		return ret;
    491	}
    492
    493	priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
    494	if (!priv->ds)
    495		return -ENOMEM;
    496
    497	priv->ds->dev = dev;
    498	priv->ds->num_ports = priv->num_ports;
    499	priv->ds->priv = priv;
    500
    501	priv->ds->ops = var->ds_ops_smi;
    502	ret = dsa_register_switch(priv->ds);
    503	if (ret) {
    504		dev_err_probe(dev, ret, "unable to register switch\n");
    505		return ret;
    506	}
    507	return 0;
    508}
    509
    510static int realtek_smi_remove(struct platform_device *pdev)
    511{
    512	struct realtek_priv *priv = platform_get_drvdata(pdev);
    513
    514	if (!priv)
    515		return 0;
    516
    517	dsa_unregister_switch(priv->ds);
    518	if (priv->slave_mii_bus)
    519		of_node_put(priv->slave_mii_bus->dev.of_node);
    520
    521	/* leave the device reset asserted */
    522	if (priv->reset)
    523		gpiod_set_value(priv->reset, 1);
    524
    525	platform_set_drvdata(pdev, NULL);
    526
    527	return 0;
    528}
    529
    530static void realtek_smi_shutdown(struct platform_device *pdev)
    531{
    532	struct realtek_priv *priv = platform_get_drvdata(pdev);
    533
    534	if (!priv)
    535		return;
    536
    537	dsa_switch_shutdown(priv->ds);
    538
    539	platform_set_drvdata(pdev, NULL);
    540}
    541
    542static const struct of_device_id realtek_smi_of_match[] = {
    543#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
    544	{
    545		.compatible = "realtek,rtl8366rb",
    546		.data = &rtl8366rb_variant,
    547	},
    548#endif
    549#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
    550	{
    551		.compatible = "realtek,rtl8365mb",
    552		.data = &rtl8365mb_variant,
    553	},
    554#endif
    555	{ /* sentinel */ },
    556};
    557MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
    558
    559static struct platform_driver realtek_smi_driver = {
    560	.driver = {
    561		.name = "realtek-smi",
    562		.of_match_table = of_match_ptr(realtek_smi_of_match),
    563	},
    564	.probe  = realtek_smi_probe,
    565	.remove = realtek_smi_remove,
    566	.shutdown = realtek_smi_shutdown,
    567};
    568module_platform_driver(realtek_smi_driver);
    569
    570MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
    571MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
    572MODULE_LICENSE("GPL");