gk7205v200-uboot/drivers/net/femac/mdio.c
2025-08-07 17:13:54 +08:00

105 lines
2.1 KiB
C
Executable File

/*
* Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
*/
#define BSPETH_FEMAC
#include "bspeth.h"
#include "mdio.h"
/* write mdio registers reset value */
static void mdio_reg_reset(struct bspeth_netdev_local *ld)
{
bspeth_writel(ld, 0x00008000, MDIO_RWCTRL);
bspeth_writel(ld, 0x00000001, U_MDIO_PHYADDR);
bspeth_writel(ld, 0x00000001, D_MDIO_PHYADDR);
bspeth_writel(ld, 0x04631EA9, U_MDIO_ANEG_CTRL);
bspeth_writel(ld, 0x04631EA9, D_MDIO_ANEG_CTRL);
bspeth_writel(ld, 0x00000000, U_MDIO_IRQENA);
bspeth_writel(ld, 0x00000000, D_MDIO_IRQENA);
}
static int wait_mdio_ready(struct bspeth_netdev_local *ld)
{
int timeout_us = 5000;
while (--timeout_us && !test_mdio_ready(ld))
udelay(50); /* delay 50us */
return timeout_us;
}
int bspeth_mdio_read(struct bspeth_netdev_local *ld, int phy_addr, unsigned int regnum)
{
int val = 0;
bspeth_assert((!((unsigned int)phy_addr & (~0x1F))) && (!(regnum & (~0x1F))));
local_lock(ld);
if (!wait_mdio_ready(ld)) {
bspeth_error("mdio busy");
goto error_exit;
}
mdio_start_phyread(ld, (unsigned int)phy_addr, regnum);
if (wait_mdio_ready(ld) != 0) {
val = mdio_get_phyread_val(ld);
} else {
bspeth_error("read timeout");
}
error_exit:
local_unlock(ld);
bspeth_trace(BSPETH_TRACE_MDIO, "phy_addr = %d, regnum = %d, val = 0x%04x", phy_addr,
(int)regnum, val);
return val;
}
int bspeth_mdio_write(struct bspeth_netdev_local *ld, int phy_addr, int regnum, int val)
{
bspeth_assert((!((unsigned int)phy_addr & (~0x1F))) && (!((unsigned int)regnum & (~0x1F))));
bspeth_trace(BSPETH_TRACE_MDIO, "phy_addr = %d, regnum = %d", phy_addr, regnum);
local_lock(ld);
if (!wait_mdio_ready(ld)) {
bspeth_error("mdio busy");
val = -1;
goto error_exit;
}
mdio_phywrite(ld, (unsigned int)phy_addr, (unsigned int)regnum, (unsigned int)val);
error_exit:
local_unlock(ld);
return val;
}
int bspeth_mdio_reset(struct bspeth_netdev_local *ld)
{
mdio_reg_reset(ld);
return 0;
}
int bspeth_mdio_init(struct bspeth_netdev_local *ld)
{
local_lock_init(ld);
bspeth_mdio_reset(ld);
return 0;
}
void bspeth_mdio_exit(struct bspeth_netdev_local *ld)
{
local_lock_exit(ld);
}