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

sja1105_mdio.c (12245B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright 2021 NXP
      3 */
      4#include <linux/pcs/pcs-xpcs.h>
      5#include <linux/of_mdio.h>
      6#include "sja1105.h"
      7
      8#define SJA1110_PCS_BANK_REG		SJA1110_SPI_ADDR(0x3fc)
      9
     10int sja1105_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
     11{
     12	struct sja1105_mdio_private *mdio_priv = bus->priv;
     13	struct sja1105_private *priv = mdio_priv->priv;
     14	u64 addr;
     15	u32 tmp;
     16	u16 mmd;
     17	int rc;
     18
     19	if (!(reg & MII_ADDR_C45))
     20		return -EINVAL;
     21
     22	mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
     23	addr = (mmd << 16) | (reg & GENMASK(15, 0));
     24
     25	if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
     26		return 0xffff;
     27
     28	if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
     29		return NXP_SJA1105_XPCS_ID >> 16;
     30	if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
     31		return NXP_SJA1105_XPCS_ID & GENMASK(15, 0);
     32
     33	rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
     34	if (rc < 0)
     35		return rc;
     36
     37	return tmp & 0xffff;
     38}
     39
     40int sja1105_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
     41{
     42	struct sja1105_mdio_private *mdio_priv = bus->priv;
     43	struct sja1105_private *priv = mdio_priv->priv;
     44	u64 addr;
     45	u32 tmp;
     46	u16 mmd;
     47
     48	if (!(reg & MII_ADDR_C45))
     49		return -EINVAL;
     50
     51	mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
     52	addr = (mmd << 16) | (reg & GENMASK(15, 0));
     53	tmp = val;
     54
     55	if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
     56		return -EINVAL;
     57
     58	return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
     59}
     60
     61int sja1110_pcs_mdio_read(struct mii_bus *bus, int phy, int reg)
     62{
     63	struct sja1105_mdio_private *mdio_priv = bus->priv;
     64	struct sja1105_private *priv = mdio_priv->priv;
     65	const struct sja1105_regs *regs = priv->info->regs;
     66	int offset, bank;
     67	u64 addr;
     68	u32 tmp;
     69	u16 mmd;
     70	int rc;
     71
     72	if (!(reg & MII_ADDR_C45))
     73		return -EINVAL;
     74
     75	if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
     76		return -ENODEV;
     77
     78	mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
     79	addr = (mmd << 16) | (reg & GENMASK(15, 0));
     80
     81	if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
     82		return NXP_SJA1110_XPCS_ID >> 16;
     83	if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
     84		return NXP_SJA1110_XPCS_ID & GENMASK(15, 0);
     85
     86	bank = addr >> 8;
     87	offset = addr & GENMASK(7, 0);
     88
     89	/* This addressing scheme reserves register 0xff for the bank address
     90	 * register, so that can never be addressed.
     91	 */
     92	if (WARN_ON(offset == 0xff))
     93		return -ENODEV;
     94
     95	tmp = bank;
     96
     97	rc = sja1105_xfer_u32(priv, SPI_WRITE,
     98			      regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
     99			      &tmp, NULL);
    100	if (rc < 0)
    101		return rc;
    102
    103	rc = sja1105_xfer_u32(priv, SPI_READ, regs->pcs_base[phy] + offset,
    104			      &tmp, NULL);
    105	if (rc < 0)
    106		return rc;
    107
    108	return tmp & 0xffff;
    109}
    110
    111int sja1110_pcs_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
    112{
    113	struct sja1105_mdio_private *mdio_priv = bus->priv;
    114	struct sja1105_private *priv = mdio_priv->priv;
    115	const struct sja1105_regs *regs = priv->info->regs;
    116	int offset, bank;
    117	u64 addr;
    118	u32 tmp;
    119	u16 mmd;
    120	int rc;
    121
    122	if (!(reg & MII_ADDR_C45))
    123		return -EINVAL;
    124
    125	if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
    126		return -ENODEV;
    127
    128	mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
    129	addr = (mmd << 16) | (reg & GENMASK(15, 0));
    130
    131	bank = addr >> 8;
    132	offset = addr & GENMASK(7, 0);
    133
    134	/* This addressing scheme reserves register 0xff for the bank address
    135	 * register, so that can never be addressed.
    136	 */
    137	if (WARN_ON(offset == 0xff))
    138		return -ENODEV;
    139
    140	tmp = bank;
    141
    142	rc = sja1105_xfer_u32(priv, SPI_WRITE,
    143			      regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
    144			      &tmp, NULL);
    145	if (rc < 0)
    146		return rc;
    147
    148	tmp = val;
    149
    150	return sja1105_xfer_u32(priv, SPI_WRITE, regs->pcs_base[phy] + offset,
    151				&tmp, NULL);
    152}
    153
    154enum sja1105_mdio_opcode {
    155	SJA1105_C45_ADDR = 0,
    156	SJA1105_C22 = 1,
    157	SJA1105_C45_DATA = 2,
    158	SJA1105_C45_DATA_AUTOINC = 3,
    159};
    160
    161static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
    162				       int phy, enum sja1105_mdio_opcode op,
    163				       int xad)
    164{
    165	const struct sja1105_regs *regs = priv->info->regs;
    166
    167	return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
    168}
    169
    170static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg)
    171{
    172	struct sja1105_mdio_private *mdio_priv = bus->priv;
    173	struct sja1105_private *priv = mdio_priv->priv;
    174	u64 addr;
    175	u32 tmp;
    176	int rc;
    177
    178	if (reg & MII_ADDR_C45) {
    179		u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
    180
    181		addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
    182						   mmd);
    183
    184		tmp = reg & MII_REGADDR_C45_MASK;
    185
    186		rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
    187		if (rc < 0)
    188			return rc;
    189
    190		addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
    191						   mmd);
    192
    193		rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
    194		if (rc < 0)
    195			return rc;
    196
    197		return tmp & 0xffff;
    198	}
    199
    200	/* Clause 22 read */
    201	addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
    202
    203	rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
    204	if (rc < 0)
    205		return rc;
    206
    207	return tmp & 0xffff;
    208}
    209
    210static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg,
    211				      u16 val)
    212{
    213	struct sja1105_mdio_private *mdio_priv = bus->priv;
    214	struct sja1105_private *priv = mdio_priv->priv;
    215	u64 addr;
    216	u32 tmp;
    217	int rc;
    218
    219	if (reg & MII_ADDR_C45) {
    220		u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f;
    221
    222		addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR,
    223						   mmd);
    224
    225		tmp = reg & MII_REGADDR_C45_MASK;
    226
    227		rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
    228		if (rc < 0)
    229			return rc;
    230
    231		addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA,
    232						   mmd);
    233
    234		tmp = val & 0xffff;
    235
    236		rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
    237		if (rc < 0)
    238			return rc;
    239
    240		return 0;
    241	}
    242
    243	/* Clause 22 write */
    244	addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
    245
    246	tmp = val & 0xffff;
    247
    248	return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
    249}
    250
    251static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg)
    252{
    253	struct sja1105_mdio_private *mdio_priv = bus->priv;
    254	struct sja1105_private *priv = mdio_priv->priv;
    255	const struct sja1105_regs *regs = priv->info->regs;
    256	u32 tmp;
    257	int rc;
    258
    259	rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
    260			      &tmp, NULL);
    261	if (rc < 0)
    262		return rc;
    263
    264	return tmp & 0xffff;
    265}
    266
    267static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
    268				      u16 val)
    269{
    270	struct sja1105_mdio_private *mdio_priv = bus->priv;
    271	struct sja1105_private *priv = mdio_priv->priv;
    272	const struct sja1105_regs *regs = priv->info->regs;
    273	u32 tmp = val;
    274
    275	return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
    276				&tmp, NULL);
    277}
    278
    279static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
    280					    struct device_node *mdio_node)
    281{
    282	struct sja1105_mdio_private *mdio_priv;
    283	struct device_node *np;
    284	struct mii_bus *bus;
    285	int rc = 0;
    286
    287	np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
    288	if (!np)
    289		return 0;
    290
    291	if (!of_device_is_available(np))
    292		goto out_put_np;
    293
    294	bus = mdiobus_alloc_size(sizeof(*mdio_priv));
    295	if (!bus) {
    296		rc = -ENOMEM;
    297		goto out_put_np;
    298	}
    299
    300	bus->name = "SJA1110 100base-TX MDIO bus";
    301	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx",
    302		 dev_name(priv->ds->dev));
    303	bus->read = sja1105_base_tx_mdio_read;
    304	bus->write = sja1105_base_tx_mdio_write;
    305	bus->parent = priv->ds->dev;
    306	mdio_priv = bus->priv;
    307	mdio_priv->priv = priv;
    308
    309	rc = of_mdiobus_register(bus, np);
    310	if (rc) {
    311		mdiobus_free(bus);
    312		goto out_put_np;
    313	}
    314
    315	priv->mdio_base_tx = bus;
    316
    317out_put_np:
    318	of_node_put(np);
    319
    320	return rc;
    321}
    322
    323static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
    324{
    325	if (!priv->mdio_base_tx)
    326		return;
    327
    328	mdiobus_unregister(priv->mdio_base_tx);
    329	mdiobus_free(priv->mdio_base_tx);
    330	priv->mdio_base_tx = NULL;
    331}
    332
    333static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
    334					    struct device_node *mdio_node)
    335{
    336	struct sja1105_mdio_private *mdio_priv;
    337	struct device_node *np;
    338	struct mii_bus *bus;
    339	int rc = 0;
    340
    341	np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
    342	if (!np)
    343		return 0;
    344
    345	if (!of_device_is_available(np))
    346		goto out_put_np;
    347
    348	bus = mdiobus_alloc_size(sizeof(*mdio_priv));
    349	if (!bus) {
    350		rc = -ENOMEM;
    351		goto out_put_np;
    352	}
    353
    354	bus->name = "SJA1110 100base-T1 MDIO bus";
    355	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
    356		 dev_name(priv->ds->dev));
    357	bus->read = sja1105_base_t1_mdio_read;
    358	bus->write = sja1105_base_t1_mdio_write;
    359	bus->parent = priv->ds->dev;
    360	mdio_priv = bus->priv;
    361	mdio_priv->priv = priv;
    362
    363	rc = of_mdiobus_register(bus, np);
    364	if (rc) {
    365		mdiobus_free(bus);
    366		goto out_put_np;
    367	}
    368
    369	priv->mdio_base_t1 = bus;
    370
    371out_put_np:
    372	of_node_put(np);
    373
    374	return rc;
    375}
    376
    377static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
    378{
    379	if (!priv->mdio_base_t1)
    380		return;
    381
    382	mdiobus_unregister(priv->mdio_base_t1);
    383	mdiobus_free(priv->mdio_base_t1);
    384	priv->mdio_base_t1 = NULL;
    385}
    386
    387static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
    388{
    389	struct sja1105_mdio_private *mdio_priv;
    390	struct dsa_switch *ds = priv->ds;
    391	struct mii_bus *bus;
    392	int rc = 0;
    393	int port;
    394
    395	if (!priv->info->pcs_mdio_read || !priv->info->pcs_mdio_write)
    396		return 0;
    397
    398	bus = mdiobus_alloc_size(sizeof(*mdio_priv));
    399	if (!bus)
    400		return -ENOMEM;
    401
    402	bus->name = "SJA1105 PCS MDIO bus";
    403	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
    404		 dev_name(ds->dev));
    405	bus->read = priv->info->pcs_mdio_read;
    406	bus->write = priv->info->pcs_mdio_write;
    407	bus->parent = ds->dev;
    408	/* There is no PHY on this MDIO bus => mask out all PHY addresses
    409	 * from auto probing.
    410	 */
    411	bus->phy_mask = ~0;
    412	mdio_priv = bus->priv;
    413	mdio_priv->priv = priv;
    414
    415	rc = mdiobus_register(bus);
    416	if (rc) {
    417		mdiobus_free(bus);
    418		return rc;
    419	}
    420
    421	for (port = 0; port < ds->num_ports; port++) {
    422		struct mdio_device *mdiodev;
    423		struct dw_xpcs *xpcs;
    424
    425		if (dsa_is_unused_port(ds, port))
    426			continue;
    427
    428		if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII &&
    429		    priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
    430			continue;
    431
    432		mdiodev = mdio_device_create(bus, port);
    433		if (IS_ERR(mdiodev)) {
    434			rc = PTR_ERR(mdiodev);
    435			goto out_pcs_free;
    436		}
    437
    438		xpcs = xpcs_create(mdiodev, priv->phy_mode[port]);
    439		if (IS_ERR(xpcs)) {
    440			rc = PTR_ERR(xpcs);
    441			goto out_pcs_free;
    442		}
    443
    444		priv->xpcs[port] = xpcs;
    445	}
    446
    447	priv->mdio_pcs = bus;
    448
    449	return 0;
    450
    451out_pcs_free:
    452	for (port = 0; port < ds->num_ports; port++) {
    453		if (!priv->xpcs[port])
    454			continue;
    455
    456		mdio_device_free(priv->xpcs[port]->mdiodev);
    457		xpcs_destroy(priv->xpcs[port]);
    458		priv->xpcs[port] = NULL;
    459	}
    460
    461	mdiobus_unregister(bus);
    462	mdiobus_free(bus);
    463
    464	return rc;
    465}
    466
    467static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
    468{
    469	struct dsa_switch *ds = priv->ds;
    470	int port;
    471
    472	if (!priv->mdio_pcs)
    473		return;
    474
    475	for (port = 0; port < ds->num_ports; port++) {
    476		if (!priv->xpcs[port])
    477			continue;
    478
    479		mdio_device_free(priv->xpcs[port]->mdiodev);
    480		xpcs_destroy(priv->xpcs[port]);
    481		priv->xpcs[port] = NULL;
    482	}
    483
    484	mdiobus_unregister(priv->mdio_pcs);
    485	mdiobus_free(priv->mdio_pcs);
    486	priv->mdio_pcs = NULL;
    487}
    488
    489int sja1105_mdiobus_register(struct dsa_switch *ds)
    490{
    491	struct sja1105_private *priv = ds->priv;
    492	const struct sja1105_regs *regs = priv->info->regs;
    493	struct device_node *switch_node = ds->dev->of_node;
    494	struct device_node *mdio_node;
    495	int rc;
    496
    497	rc = sja1105_mdiobus_pcs_register(priv);
    498	if (rc)
    499		return rc;
    500
    501	mdio_node = of_get_child_by_name(switch_node, "mdios");
    502	if (!mdio_node)
    503		return 0;
    504
    505	if (!of_device_is_available(mdio_node))
    506		goto out_put_mdio_node;
    507
    508	if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
    509		rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
    510		if (rc)
    511			goto err_put_mdio_node;
    512	}
    513
    514	if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
    515		rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
    516		if (rc)
    517			goto err_free_base_tx_mdiobus;
    518	}
    519
    520out_put_mdio_node:
    521	of_node_put(mdio_node);
    522
    523	return 0;
    524
    525err_free_base_tx_mdiobus:
    526	sja1105_mdiobus_base_tx_unregister(priv);
    527err_put_mdio_node:
    528	of_node_put(mdio_node);
    529	sja1105_mdiobus_pcs_unregister(priv);
    530
    531	return rc;
    532}
    533
    534void sja1105_mdiobus_unregister(struct dsa_switch *ds)
    535{
    536	struct sja1105_private *priv = ds->priv;
    537
    538	sja1105_mdiobus_base_t1_unregister(priv);
    539	sja1105_mdiobus_base_tx_unregister(priv);
    540	sja1105_mdiobus_pcs_unregister(priv);
    541}