mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-07-27 12:47:13 +08:00
dpaa: Support c45 phys
This commit is contained in:
parent
66e83e0e64
commit
9da83e7886
@ -80,9 +80,11 @@ typedef enum {
|
|||||||
#define SUPPORTED_MII (1U << 8)
|
#define SUPPORTED_MII (1U << 8)
|
||||||
#define SUPPORTED_Pause (1U << 9)
|
#define SUPPORTED_Pause (1U << 9)
|
||||||
|
|
||||||
|
#define MII_ADDR_C45 (1 << 30)
|
||||||
|
|
||||||
struct mdio_bus {
|
struct mdio_bus {
|
||||||
int (*read)(struct mdio_bus *bus, int phy, int reg);
|
int (*read)(struct mdio_bus *bus, int addr, int reg);
|
||||||
int (*write)(struct mdio_bus *bus, int phy, int reg, int val);
|
int (*write)(struct mdio_bus *bus, int addr, int reg, int val);
|
||||||
SLIST_ENTRY(mdio_bus) next;
|
SLIST_ENTRY(mdio_bus) next;
|
||||||
int node;
|
int node;
|
||||||
};
|
};
|
||||||
@ -91,27 +93,14 @@ struct phy_device {
|
|||||||
struct {
|
struct {
|
||||||
struct device dev;
|
struct device dev;
|
||||||
int addr;
|
int addr;
|
||||||
|
int is_c45;
|
||||||
struct mdio_bus *bus;
|
struct mdio_bus *bus;
|
||||||
} mdio;
|
} mdio;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int
|
int phy_read(struct phy_device *phy_dev, int reg);
|
||||||
phy_read(struct phy_device *phy_dev, int reg)
|
|
||||||
{
|
|
||||||
struct mdio_bus *mdio_dev;
|
|
||||||
|
|
||||||
mdio_dev = phy_dev->mdio.bus;
|
int phy_write(struct phy_device *phy_dev, int reg, int val);
|
||||||
return ((*mdio_dev->read)(mdio_dev, phy_dev->mdio.addr, (int)reg));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
phy_write(struct phy_device *phy_dev, int reg, int val)
|
|
||||||
{
|
|
||||||
struct mdio_bus *mdio_dev;
|
|
||||||
|
|
||||||
mdio_dev = phy_dev->mdio.bus;
|
|
||||||
return ((*mdio_dev->write)(mdio_dev, phy_dev->mdio.addr, reg, val));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,35 @@ static struct {
|
|||||||
.instances = SLIST_HEAD_INITIALIZER(mdio.instances)
|
.instances = SLIST_HEAD_INITIALIZER(mdio.instances)
|
||||||
};
|
};
|
||||||
|
|
||||||
MTX_SYSINIT(mdio_mutex, &mdio.mutex, "FDT MDIO", MTX_DEF);
|
MTX_SYSINIT(mdio_mutex, &mdio.mutex, "MDIO", MTX_DEF);
|
||||||
|
|
||||||
|
int
|
||||||
|
phy_read(struct phy_device *phy_dev, int reg)
|
||||||
|
{
|
||||||
|
struct mdio_bus *mdio_dev;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
mdio_dev = phy_dev->mdio.bus;
|
||||||
|
MDIO_LOCK();
|
||||||
|
val = (*mdio_dev->read)(mdio_dev, phy_dev->mdio.addr,
|
||||||
|
reg | phy_dev->mdio.is_c45);
|
||||||
|
MDIO_UNLOCK();
|
||||||
|
return (val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
phy_write(struct phy_device *phy_dev, int reg, int val)
|
||||||
|
{
|
||||||
|
struct mdio_bus *mdio_dev;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
mdio_dev = phy_dev->mdio.bus;
|
||||||
|
MDIO_LOCK();
|
||||||
|
err = (*mdio_dev->write)(mdio_dev, phy_dev->mdio.addr,
|
||||||
|
reg | phy_dev->mdio.is_c45, val);
|
||||||
|
MDIO_UNLOCK();
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
fdt_get_address(const void *fdt, int node)
|
fdt_get_address(const void *fdt, int node)
|
||||||
@ -157,78 +185,92 @@ fman_mdio_wait(volatile struct fman_mdio_regs *regs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fman_mdio_read(struct mdio_bus *base, int phy, int reg)
|
fman_mdio_setup(volatile struct fman_mdio_regs *regs, int addr, int reg,
|
||||||
|
uint32_t *mdio_ctrl_p)
|
||||||
|
{
|
||||||
|
uint32_t mdio_cfg;
|
||||||
|
uint32_t mdio_ctrl;
|
||||||
|
uint32_t reg_addr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = fman_mdio_wait(regs);
|
||||||
|
if (err != 0) {
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
mdio_cfg = regs->mdio_cfg;
|
||||||
|
if ((reg & MII_ADDR_C45) != 0) {
|
||||||
|
reg_addr = (uint32_t)(reg >> 16);
|
||||||
|
mdio_cfg |= MDIO_CFG_ENC45;
|
||||||
|
} else {
|
||||||
|
reg_addr = (uint32_t)reg;
|
||||||
|
mdio_cfg &= ~MDIO_CFG_ENC45;
|
||||||
|
}
|
||||||
|
regs->mdio_cfg = mdio_cfg;
|
||||||
|
|
||||||
|
mdio_ctrl = MDIO_CTRL_PHY_ADDR(addr) | MDIO_CTRL_REG_ADDR(reg_addr);
|
||||||
|
regs->mdio_ctrl = mdio_ctrl;
|
||||||
|
|
||||||
|
if ((reg & MII_ADDR_C45) != 0) {
|
||||||
|
regs->mdio_addr = (uint32_t)(reg & 0xffff);
|
||||||
|
err = fman_mdio_wait(regs);
|
||||||
|
if (err != 0) {
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*mdio_ctrl_p = mdio_ctrl;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fman_mdio_read(struct mdio_bus *base, int addr, int reg)
|
||||||
{
|
{
|
||||||
struct fman_mdio_bus *fm;
|
struct fman_mdio_bus *fm;
|
||||||
volatile struct fman_mdio_regs *regs;
|
volatile struct fman_mdio_regs *regs;
|
||||||
|
uint32_t mdio_ctrl;
|
||||||
int val;
|
int val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
fm = (struct fman_mdio_bus *)base;
|
fm = (struct fman_mdio_bus *)base;
|
||||||
regs = fm->regs;
|
regs = fm->regs;
|
||||||
|
|
||||||
MDIO_LOCK();
|
err = fman_mdio_setup(regs, addr, reg, &mdio_ctrl);
|
||||||
|
if (err != 0) {
|
||||||
err = fman_mdio_wait(regs);
|
return (-1);
|
||||||
if (err == 0) {
|
|
||||||
uint32_t mdio_cfg;
|
|
||||||
uint32_t mdio_ctrl;
|
|
||||||
|
|
||||||
mdio_cfg = regs->mdio_cfg;
|
|
||||||
mdio_cfg &= ~MDIO_CFG_ENC45;
|
|
||||||
regs->mdio_cfg = mdio_cfg;
|
|
||||||
|
|
||||||
mdio_ctrl = MDIO_CTRL_PHY_ADDR(phy) | MDIO_CTRL_REG_ADDR(reg);
|
|
||||||
regs->mdio_ctrl = mdio_ctrl;
|
|
||||||
mdio_ctrl |= MDIO_CTRL_READ;
|
|
||||||
regs->mdio_ctrl = mdio_ctrl;
|
|
||||||
|
|
||||||
err = fman_mdio_wait(regs);
|
|
||||||
if (err == 0 && (regs->mdio_cfg & MDIO_CFG_RD_ERR) == 0) {
|
|
||||||
val = (int)(regs->mdio_data & 0xffff);
|
|
||||||
} else {
|
|
||||||
val = 0xffff;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val = 0xffff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MDIO_UNLOCK();
|
mdio_ctrl |= MDIO_CTRL_READ;
|
||||||
|
regs->mdio_ctrl = mdio_ctrl;
|
||||||
|
|
||||||
|
err = fman_mdio_wait(regs);
|
||||||
|
if (err == 0 && (regs->mdio_cfg & MDIO_CFG_RD_ERR) == 0) {
|
||||||
|
val = (int)(regs->mdio_data & 0xffff);
|
||||||
|
} else {
|
||||||
|
val = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return (val);
|
return (val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fman_mdio_write(struct mdio_bus *base, int phy, int reg, int val)
|
fman_mdio_write(struct mdio_bus *base, int addr, int reg, int val)
|
||||||
{
|
{
|
||||||
struct fman_mdio_bus *fm;
|
struct fman_mdio_bus *fm;
|
||||||
volatile struct fman_mdio_regs *regs;
|
volatile struct fman_mdio_regs *regs;
|
||||||
|
uint32_t mdio_ctrl;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
fm = (struct fman_mdio_bus *)base;
|
fm = (struct fman_mdio_bus *)base;
|
||||||
regs = fm->regs;
|
regs = fm->regs;
|
||||||
|
|
||||||
MDIO_LOCK();
|
err = fman_mdio_setup(regs, addr, reg, &mdio_ctrl);
|
||||||
|
if (err != 0) {
|
||||||
err = fman_mdio_wait(regs);
|
return (0);
|
||||||
if (err == 0) {
|
|
||||||
uint32_t mdio_cfg;
|
|
||||||
uint32_t mdio_ctrl;
|
|
||||||
|
|
||||||
mdio_cfg = regs->mdio_cfg;
|
|
||||||
mdio_cfg &= ~MDIO_CFG_ENC45;
|
|
||||||
regs->mdio_cfg = mdio_cfg;
|
|
||||||
|
|
||||||
mdio_ctrl = MDIO_CTRL_PHY_ADDR(phy) | MDIO_CTRL_REG_ADDR(reg);
|
|
||||||
regs->mdio_ctrl = mdio_ctrl;
|
|
||||||
|
|
||||||
regs->mdio_data = (uint32_t)(val & 0xffff);
|
|
||||||
|
|
||||||
fman_mdio_wait(regs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MDIO_UNLOCK();
|
regs->mdio_data = (uint32_t)(val & 0xffff);
|
||||||
|
fman_mdio_wait(regs);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +332,7 @@ find_mdio_bus(const void *fdt, int mdio_node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct phy_device *
|
static struct phy_device *
|
||||||
phy_obtain(const void *fdt, int mdio_node, int phy)
|
phy_obtain(const void *fdt, int is_c45, int mdio_node, int addr)
|
||||||
{
|
{
|
||||||
struct phy_device *phy_dev;
|
struct phy_device *phy_dev;
|
||||||
int err;
|
int err;
|
||||||
@ -300,7 +342,8 @@ phy_obtain(const void *fdt, int mdio_node, int phy)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
phy_dev->mdio.addr = phy;
|
phy_dev->mdio.addr = addr;
|
||||||
|
phy_dev->mdio.is_c45 = is_c45;
|
||||||
MDIO_LOCK();
|
MDIO_LOCK();
|
||||||
err = find_mdio_bus(fdt, mdio_node, phy_dev);
|
err = find_mdio_bus(fdt, mdio_node, phy_dev);
|
||||||
MDIO_UNLOCK();
|
MDIO_UNLOCK();
|
||||||
@ -317,21 +360,28 @@ struct phy_device *
|
|||||||
of_phy_find_device(struct device_node *dn)
|
of_phy_find_device(struct device_node *dn)
|
||||||
{
|
{
|
||||||
const void *fdt;
|
const void *fdt;
|
||||||
const fdt32_t *phy;
|
const fdt32_t *addr;
|
||||||
int len;
|
int len;
|
||||||
|
int is_c45;
|
||||||
int mdio_node;
|
int mdio_node;
|
||||||
|
|
||||||
fdt = bsp_fdt_get();
|
fdt = bsp_fdt_get();
|
||||||
|
|
||||||
phy = fdt_getprop(fdt, dn->offset, "reg", &len);
|
addr = fdt_getprop(fdt, dn->offset, "reg", &len);
|
||||||
if (phy == NULL || len != sizeof(*phy)) {
|
if (addr == NULL || len != sizeof(*addr)) {
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (of_device_is_compatible(dn, "ethernet-phy-ieee802.3-c45")) {
|
||||||
|
is_c45 = MII_ADDR_C45;
|
||||||
|
} else {
|
||||||
|
is_c45 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
mdio_node = fdt_parent_offset(fdt, dn->offset);
|
mdio_node = fdt_parent_offset(fdt, dn->offset);
|
||||||
if (mdio_node < 0) {
|
if (mdio_node < 0) {
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (phy_obtain(fdt, mdio_node, (int)fdt32_to_cpu(*phy)));
|
return (phy_obtain(fdt, is_c45, mdio_node, (int)fdt32_to_cpu(*addr)));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user