net: ftmac100: add mii read and write callbacks

Register mii_bus with read and write callbacks to allow the 'mii'
command to work. Use a timeout of 10 ms to wait for the R/W
operations to complete.

Signed-off-by: Sergei Antonov <saproj@gmail.com>
Reviewed-by: Rick Chen <rick@andestech.com>
Tested-by: Rick Chen <rick@andestech.com>
This commit is contained in:
Sergei Antonov 2023-02-03 22:09:04 +03:00 committed by Tom Rini
parent 9628c3e8b1
commit add396d667
3 changed files with 113 additions and 0 deletions

View file

@ -413,6 +413,7 @@ config FSL_FM_10GEC_REGULAR_NOTATION
config FTMAC100
bool "Ftmac100 Ethernet Support"
select MII
help
This MAC is present in Andestech SoCs.

View file

@ -12,9 +12,13 @@
#include <env.h>
#include <malloc.h>
#include <net.h>
#include <phy.h>
#include <miiphy.h>
#include <dm/device_compat.h>
#include <asm/global_data.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include "ftmac100.h"
#include <dm.h>
@ -23,12 +27,16 @@ DECLARE_GLOBAL_DATA_PTR;
#define ETH_ZLEN 60
/* Timeout for a mdio read/write operation */
#define FTMAC100_MDIO_TIMEOUT_USEC 10000
struct ftmac100_data {
struct ftmac100_txdes txdes[1];
struct ftmac100_rxdes rxdes[PKTBUFSRX];
int rx_index;
const char *name;
struct ftmac100 *ftmac100;
struct mii_dev *bus;
};
/*
@ -322,10 +330,104 @@ static int ftmac100_of_to_plat(struct udevice *dev)
return 0;
}
/*
* struct mii_bus functions
*/
static int ftmac100_mdio_read(struct mii_dev *bus, int addr, int devad,
int reg)
{
struct ftmac100_data *priv = bus->priv;
struct ftmac100 *ftmac100 = priv->ftmac100;
int phycr = FTMAC100_PHYCR_PHYAD(addr) |
FTMAC100_PHYCR_REGAD(reg) |
FTMAC100_PHYCR_MIIRD;
int ret;
writel(phycr, &ftmac100->phycr);
ret = readl_poll_timeout(&ftmac100->phycr, phycr,
!(phycr & FTMAC100_PHYCR_MIIRD),
FTMAC100_MDIO_TIMEOUT_USEC);
if (ret)
pr_err("%s: mdio read failed (addr=0x%x reg=0x%x)\n",
bus->name, addr, reg);
else
ret = phycr & FTMAC100_PHYCR_MIIRDATA;
return ret;
}
static int ftmac100_mdio_write(struct mii_dev *bus, int addr, int devad,
int reg, u16 value)
{
struct ftmac100_data *priv = bus->priv;
struct ftmac100 *ftmac100 = priv->ftmac100;
int phycr = FTMAC100_PHYCR_PHYAD(addr) |
FTMAC100_PHYCR_REGAD(reg) |
FTMAC100_PHYCR_MIIWR;
int ret;
writel(value, &ftmac100->phywdata);
writel(phycr, &ftmac100->phycr);
ret = readl_poll_timeout(&ftmac100->phycr, phycr,
!(phycr & FTMAC100_PHYCR_MIIWR),
FTMAC100_MDIO_TIMEOUT_USEC);
if (ret)
pr_err("%s: mdio write failed (addr=0x%x reg=0x%x)\n",
bus->name, addr, reg);
return ret;
}
static int ftmac100_mdio_init(struct udevice *dev)
{
struct ftmac100_data *priv = dev_get_priv(dev);
struct mii_dev *bus;
int ret;
bus = mdio_alloc();
if (!bus)
return -ENOMEM;
bus->read = ftmac100_mdio_read;
bus->write = ftmac100_mdio_write;
bus->priv = priv;
ret = mdio_register_seq(bus, dev_seq(dev));
if (ret) {
mdio_free(bus);
return ret;
}
priv->bus = bus;
return 0;
}
static int ftmac100_probe(struct udevice *dev)
{
struct ftmac100_data *priv = dev_get_priv(dev);
priv->name = dev->name;
int ret = 0;
ret = ftmac100_mdio_init(dev);
if (ret) {
dev_err(dev, "Failed to initialize mdiobus: %d\n", ret);
goto out;
}
out:
return ret;
}
static int ftmac100_remove(struct udevice *dev)
{
struct ftmac100_data *priv = dev_get_priv(dev);
mdio_unregister(priv->bus);
mdio_free(priv->bus);
return 0;
}
@ -354,6 +456,7 @@ U_BOOT_DRIVER(ftmac100) = {
.bind = ftmac100_bind,
.of_to_plat = ftmac100_of_to_plat,
.probe = ftmac100_probe,
.remove = ftmac100_remove,
.ops = &ftmac100_ops,
.priv_auto = sizeof(struct ftmac100_data),
.plat_auto = sizeof(struct eth_pdata),

View file

@ -92,6 +92,15 @@ struct ftmac100 {
#define FTMAC100_MACCR_RX_MULTIPKT (1 << 16)
#define FTMAC100_MACCR_RX_BROADPKT (1 << 17)
/*
* PHY control register
*/
#define FTMAC100_PHYCR_MIIRDATA 0xffff
#define FTMAC100_PHYCR_PHYAD(x) (((x) & 0x1f) << 16)
#define FTMAC100_PHYCR_REGAD(x) (((x) & 0x1f) << 21)
#define FTMAC100_PHYCR_MIIWR BIT(27)
#define FTMAC100_PHYCR_MIIRD BIT(26)
/*
* Transmit descriptor, aligned to 16 bytes
*/