105 lines
2.1 KiB
C
105 lines
2.1 KiB
C
|
|
/*
|
||
|
|
* 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);
|
||
|
|
}
|