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

xrs700x_mdio.c (4238B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2020 NovaTech LLC
      4 * George McCollister <george.mccollister@gmail.com>
      5 */
      6
      7#include <linux/bitfield.h>
      8#include <linux/bits.h>
      9#include <linux/mdio.h>
     10#include <linux/module.h>
     11#include <linux/phy.h>
     12#include <linux/if_vlan.h>
     13#include <linux/of.h>
     14#include "xrs700x.h"
     15#include "xrs700x_reg.h"
     16
     17#define XRS_MDIO_IBA0	0x10
     18#define XRS_MDIO_IBA1	0x11
     19#define XRS_MDIO_IBD	0x14
     20
     21#define XRS_IB_READ	0x0
     22#define XRS_IB_WRITE	0x1
     23
     24static int xrs700x_mdio_reg_read(void *context, unsigned int reg,
     25				 unsigned int *val)
     26{
     27	struct mdio_device *mdiodev = context;
     28	struct device *dev = &mdiodev->dev;
     29	u16 uval;
     30	int ret;
     31
     32	uval = (u16)FIELD_GET(GENMASK(31, 16), reg);
     33
     34	ret = mdiodev_write(mdiodev, XRS_MDIO_IBA1, uval);
     35	if (ret < 0) {
     36		dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
     37		return ret;
     38	}
     39
     40	uval = (u16)((reg & GENMASK(15, 1)) | XRS_IB_READ);
     41
     42	ret = mdiodev_write(mdiodev, XRS_MDIO_IBA0, uval);
     43	if (ret < 0) {
     44		dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
     45		return ret;
     46	}
     47
     48	ret = mdiodev_read(mdiodev, XRS_MDIO_IBD);
     49	if (ret < 0) {
     50		dev_err(dev, "xrs mdiobus_read returned %d\n", ret);
     51		return ret;
     52	}
     53
     54	*val = (unsigned int)ret;
     55
     56	return 0;
     57}
     58
     59static int xrs700x_mdio_reg_write(void *context, unsigned int reg,
     60				  unsigned int val)
     61{
     62	struct mdio_device *mdiodev = context;
     63	struct device *dev = &mdiodev->dev;
     64	u16 uval;
     65	int ret;
     66
     67	ret = mdiodev_write(mdiodev, XRS_MDIO_IBD, (u16)val);
     68	if (ret < 0) {
     69		dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
     70		return ret;
     71	}
     72
     73	uval = (u16)FIELD_GET(GENMASK(31, 16), reg);
     74
     75	ret = mdiodev_write(mdiodev, XRS_MDIO_IBA1, uval);
     76	if (ret < 0) {
     77		dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
     78		return ret;
     79	}
     80
     81	uval = (u16)((reg & GENMASK(15, 1)) | XRS_IB_WRITE);
     82
     83	ret = mdiodev_write(mdiodev, XRS_MDIO_IBA0, uval);
     84	if (ret < 0) {
     85		dev_err(dev, "xrs mdiobus_write returned %d\n", ret);
     86		return ret;
     87	}
     88
     89	return 0;
     90}
     91
     92static const struct regmap_config xrs700x_mdio_regmap_config = {
     93	.val_bits = 16,
     94	.reg_stride = 2,
     95	.reg_bits = 32,
     96	.pad_bits = 0,
     97	.write_flag_mask = 0,
     98	.read_flag_mask = 0,
     99	.reg_read = xrs700x_mdio_reg_read,
    100	.reg_write = xrs700x_mdio_reg_write,
    101	.max_register = XRS_VLAN(VLAN_N_VID - 1),
    102	.cache_type = REGCACHE_NONE,
    103	.reg_format_endian = REGMAP_ENDIAN_BIG,
    104	.val_format_endian = REGMAP_ENDIAN_BIG
    105};
    106
    107static int xrs700x_mdio_probe(struct mdio_device *mdiodev)
    108{
    109	struct xrs700x *priv;
    110	int ret;
    111
    112	priv = xrs700x_switch_alloc(&mdiodev->dev, mdiodev);
    113	if (!priv)
    114		return -ENOMEM;
    115
    116	priv->regmap = devm_regmap_init(&mdiodev->dev, NULL, mdiodev,
    117					&xrs700x_mdio_regmap_config);
    118	if (IS_ERR(priv->regmap)) {
    119		ret = PTR_ERR(priv->regmap);
    120		dev_err(&mdiodev->dev, "Failed to initialize regmap: %d\n", ret);
    121		return ret;
    122	}
    123
    124	dev_set_drvdata(&mdiodev->dev, priv);
    125
    126	ret = xrs700x_switch_register(priv);
    127
    128	/* Main DSA driver may not be started yet. */
    129	if (ret)
    130		return ret;
    131
    132	return 0;
    133}
    134
    135static void xrs700x_mdio_remove(struct mdio_device *mdiodev)
    136{
    137	struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev);
    138
    139	if (!priv)
    140		return;
    141
    142	xrs700x_switch_remove(priv);
    143
    144	dev_set_drvdata(&mdiodev->dev, NULL);
    145}
    146
    147static void xrs700x_mdio_shutdown(struct mdio_device *mdiodev)
    148{
    149	struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev);
    150
    151	if (!priv)
    152		return;
    153
    154	xrs700x_switch_shutdown(priv);
    155
    156	dev_set_drvdata(&mdiodev->dev, NULL);
    157}
    158
    159static const struct of_device_id __maybe_unused xrs700x_mdio_dt_ids[] = {
    160	{ .compatible = "arrow,xrs7003e", .data = &xrs7003e_info },
    161	{ .compatible = "arrow,xrs7003f", .data = &xrs7003f_info },
    162	{ .compatible = "arrow,xrs7004e", .data = &xrs7004e_info },
    163	{ .compatible = "arrow,xrs7004f", .data = &xrs7004f_info },
    164	{},
    165};
    166MODULE_DEVICE_TABLE(of, xrs700x_mdio_dt_ids);
    167
    168static struct mdio_driver xrs700x_mdio_driver = {
    169	.mdiodrv.driver = {
    170		.name	= "xrs700x-mdio",
    171		.of_match_table = of_match_ptr(xrs700x_mdio_dt_ids),
    172	},
    173	.probe	= xrs700x_mdio_probe,
    174	.remove	= xrs700x_mdio_remove,
    175	.shutdown = xrs700x_mdio_shutdown,
    176};
    177
    178mdio_module_driver(xrs700x_mdio_driver);
    179
    180MODULE_AUTHOR("George McCollister <george.mccollister@gmail.com>");
    181MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA MDIO driver");
    182MODULE_LICENSE("GPL v2");