Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1// SPDX-License-Identifier: GPL-2.0+
  2/* Copyright (c) Tehuti Networks Ltd. */
  3
  4#include <linux/netdevice.h>
  5#include <linux/pci.h>
  6#include <linux/phylink.h>
  7
  8#include "tn40.h"
  9
 10#define TN40_MDIO_DEVAD_MASK GENMASK(4, 0)
 11#define TN40_MDIO_PRTAD_MASK GENMASK(9, 5)
 12#define TN40_MDIO_CMD_VAL(device, port)			\
 13	(FIELD_PREP(TN40_MDIO_DEVAD_MASK, (device)) |	\
 14	 (FIELD_PREP(TN40_MDIO_PRTAD_MASK, (port))))
 15#define TN40_MDIO_CMD_READ BIT(15)
 16
 17static void tn40_mdio_set_speed(struct tn40_priv *priv, u32 speed)
 18{
 19	void __iomem *regs = priv->regs;
 20	int mdio_cfg;
 21
 22	if (speed == TN40_MDIO_SPEED_1MHZ)
 23		mdio_cfg = (0x7d << 7) | 0x08;	/* 1MHz */
 24	else
 25		mdio_cfg = 0xA08;	/* 6MHz */
 26	mdio_cfg |= (1 << 6);
 27	writel(mdio_cfg, regs + TN40_REG_MDIO_CMD_STAT);
 28	msleep(100);
 29}
 30
 31static u32 tn40_mdio_stat(struct tn40_priv *priv)
 32{
 33	void __iomem *regs = priv->regs;
 34
 35	return readl(regs + TN40_REG_MDIO_CMD_STAT);
 36}
 37
 38static int tn40_mdio_wait_nobusy(struct tn40_priv *priv, u32 *val)
 39{
 40	u32 stat;
 41	int ret;
 42
 43	ret = readx_poll_timeout_atomic(tn40_mdio_stat, priv, stat,
 44					TN40_GET_MDIO_BUSY(stat) == 0, 10,
 45					10000);
 46	if (val)
 47		*val = stat;
 48	return ret;
 49}
 50
 51static int tn40_mdio_read(struct tn40_priv *priv, int port, int device,
 52			  u16 regnum)
 53{
 54	void __iomem *regs = priv->regs;
 55	u32 i;
 56
 57	/* wait until MDIO is not busy */
 58	if (tn40_mdio_wait_nobusy(priv, NULL))
 59		return -EIO;
 60
 61	i = TN40_MDIO_CMD_VAL(device, port);
 62	writel(i, regs + TN40_REG_MDIO_CMD);
 63	writel((u32)regnum, regs + TN40_REG_MDIO_ADDR);
 64	if (tn40_mdio_wait_nobusy(priv, NULL))
 65		return -EIO;
 66
 67	writel(TN40_MDIO_CMD_READ | i, regs + TN40_REG_MDIO_CMD);
 68	/* read CMD_STAT until not busy */
 69	if (tn40_mdio_wait_nobusy(priv, NULL))
 70		return -EIO;
 71
 72	return lower_16_bits(readl(regs + TN40_REG_MDIO_DATA));
 73}
 74
 75static int tn40_mdio_write(struct tn40_priv *priv, int port, int device,
 76			   u16 regnum, u16 data)
 77{
 78	void __iomem *regs = priv->regs;
 79	u32 tmp_reg = 0;
 80	int ret;
 81
 82	/* wait until MDIO is not busy */
 83	if (tn40_mdio_wait_nobusy(priv, NULL))
 84		return -EIO;
 85	writel(TN40_MDIO_CMD_VAL(device, port), regs + TN40_REG_MDIO_CMD);
 86	writel((u32)regnum, regs + TN40_REG_MDIO_ADDR);
 87	if (tn40_mdio_wait_nobusy(priv, NULL))
 88		return -EIO;
 89	writel((u32)data, regs + TN40_REG_MDIO_DATA);
 90	/* read CMD_STAT until not busy */
 91	ret = tn40_mdio_wait_nobusy(priv, &tmp_reg);
 92	if (ret)
 93		return -EIO;
 94
 95	if (TN40_GET_MDIO_RD_ERR(tmp_reg)) {
 96		dev_err(&priv->pdev->dev, "MDIO error after write command\n");
 97		return -EIO;
 98	}
 99	return 0;
100}
101
102static int tn40_mdio_read_c45(struct mii_bus *mii_bus, int addr, int devnum,
103			      int regnum)
104{
105	return tn40_mdio_read(mii_bus->priv, addr, devnum, regnum);
106}
107
108static int tn40_mdio_write_c45(struct mii_bus *mii_bus, int addr, int devnum,
109			       int regnum, u16 val)
110{
111	return  tn40_mdio_write(mii_bus->priv, addr, devnum, regnum, val);
112}
113
114int tn40_mdiobus_init(struct tn40_priv *priv)
115{
116	struct pci_dev *pdev = priv->pdev;
117	struct mii_bus *bus;
118	int ret;
119
120	bus = devm_mdiobus_alloc(&pdev->dev);
121	if (!bus)
122		return -ENOMEM;
123
124	bus->name = TN40_DRV_NAME;
125	bus->parent = &pdev->dev;
126	snprintf(bus->id, MII_BUS_ID_SIZE, "tn40xx-%x-%x",
127		 pci_domain_nr(pdev->bus), pci_dev_id(pdev));
128	bus->priv = priv;
129
130	bus->read_c45 = tn40_mdio_read_c45;
131	bus->write_c45 = tn40_mdio_write_c45;
132
133	ret = devm_mdiobus_register(&pdev->dev, bus);
134	if (ret) {
135		dev_err(&pdev->dev, "failed to register mdiobus %d %u %u\n",
136			ret, bus->state, MDIOBUS_UNREGISTERED);
137		return ret;
138	}
139	tn40_mdio_set_speed(priv, TN40_MDIO_SPEED_6MHZ);
140	priv->mdio = bus;
141	return 0;
142}