Skip to content

Commit

Permalink
phy: generate swphy registers on the fly
Browse files Browse the repository at this point in the history
Generate software phy registers as and when requested, rather than
duplicating the state in fixed_phy.  This allows us to eliminate
the duplicate storage of of the same data, which is only different
in format.

As fixed_phy_update_regs() no longer updates register state, rename
it to fixed_phy_update().

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Russell King authored and David S. Miller committed Jun 27, 2016
1 parent 68888ce commit 37688e3
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 40 deletions.
31 changes: 5 additions & 26 deletions drivers/net/phy/fixed_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,13 @@

#include "swphy.h"

#define MII_REGS_NUM 29

struct fixed_mdio_bus {
struct mii_bus *mii_bus;
struct list_head phys;
};

struct fixed_phy {
int addr;
u16 regs[MII_REGS_NUM];
struct phy_device *phydev;
struct fixed_phy_status status;
int (*link_update)(struct net_device *, struct fixed_phy_status *);
Expand All @@ -48,42 +45,26 @@ static struct fixed_mdio_bus platform_fmb = {
.phys = LIST_HEAD_INIT(platform_fmb.phys),
};

static void fixed_phy_update_regs(struct fixed_phy *fp)
static void fixed_phy_update(struct fixed_phy *fp)
{
if (gpio_is_valid(fp->link_gpio))
fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio);

swphy_update_regs(fp->regs, &fp->status);
}

static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)
{
struct fixed_mdio_bus *fmb = bus->priv;
struct fixed_phy *fp;

if (reg_num >= MII_REGS_NUM)
return -1;

/* We do not support emulating Clause 45 over Clause 22 register reads
* return an error instead of bogus data.
*/
switch (reg_num) {
case MII_MMD_CTRL:
case MII_MMD_DATA:
return -1;
default:
break;
}

list_for_each_entry(fp, &fmb->phys, node) {
if (fp->addr == phy_addr) {
/* Issue callback if user registered it. */
if (fp->link_update) {
fp->link_update(fp->phydev->attached_dev,
&fp->status);
fixed_phy_update_regs(fp);
fixed_phy_update(fp);
}
return fp->regs[reg_num];
return swphy_read_reg(reg_num, &fp->status);
}
}

Expand Down Expand Up @@ -143,7 +124,7 @@ int fixed_phy_update_state(struct phy_device *phydev,
_UPD(pause);
_UPD(asym_pause);
#undef _UPD
fixed_phy_update_regs(fp);
fixed_phy_update(fp);
return 0;
}
}
Expand All @@ -168,8 +149,6 @@ int fixed_phy_add(unsigned int irq, int phy_addr,
if (!fp)
return -ENOMEM;

memset(fp->regs, 0xFF, sizeof(fp->regs[0]) * MII_REGS_NUM);

if (irq != PHY_POLL)
fmb->mii_bus->irq[phy_addr] = irq;

Expand All @@ -184,7 +163,7 @@ int fixed_phy_add(unsigned int irq, int phy_addr,
goto err_regs;
}

fixed_phy_update_regs(fp);
fixed_phy_update(fp);

list_add_tail(&fp->node, &fmb->phys);

Expand Down
47 changes: 34 additions & 13 deletions drivers/net/phy/swphy.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#include "swphy.h"

#define MII_REGS_NUM 29

struct swmii_regs {
u16 bmcr;
u16 bmsr;
Expand Down Expand Up @@ -110,24 +112,26 @@ int swphy_validate_state(const struct fixed_phy_status *state)
EXPORT_SYMBOL_GPL(swphy_validate_state);

/**
* swphy_update_regs - update MII register array with fixed phy state
* @regs: array of 32 registers to update
* swphy_read_reg - return a MII register from the fixed phy state
* @reg: MII register
* @state: fixed phy status
*
* Update the array of MII registers with the fixed phy link, speed,
* duplex and pause mode settings.
* Return the MII @reg register generated from the fixed phy state @state.
*/
void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
int swphy_read_reg(int reg, const struct fixed_phy_status *state)
{
int speed_index, duplex_index;
u16 bmsr = BMSR_ANEGCAPABLE;
u16 bmcr = 0;
u16 lpagb = 0;
u16 lpa = 0;

if (reg > MII_REGS_NUM)
return -1;

speed_index = swphy_decode_speed(state->speed);
if (WARN_ON(speed_index < 0))
return;
return 0;

duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF;

Expand All @@ -147,12 +151,29 @@ void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
lpa |= LPA_PAUSE_ASYM;
}

regs[MII_PHYSID1] = 0;
regs[MII_PHYSID2] = 0;
switch (reg) {
case MII_BMCR:
return bmcr;
case MII_BMSR:
return bmsr;
case MII_PHYSID1:
case MII_PHYSID2:
return 0;
case MII_LPA:
return lpa;
case MII_STAT1000:
return lpagb;

/*
* We do not support emulating Clause 45 over Clause 22 register
* reads. Return an error instead of bogus data.
*/
case MII_MMD_CTRL:
case MII_MMD_DATA:
return -1;

regs[MII_BMSR] = bmsr;
regs[MII_BMCR] = bmcr;
regs[MII_LPA] = lpa;
regs[MII_STAT1000] = lpagb;
default:
return 0xffff;
}
}
EXPORT_SYMBOL_GPL(swphy_update_regs);
EXPORT_SYMBOL_GPL(swphy_read_reg);
2 changes: 1 addition & 1 deletion drivers/net/phy/swphy.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
struct fixed_phy_status;

int swphy_validate_state(const struct fixed_phy_status *state);
void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state);
int swphy_read_reg(int reg, const struct fixed_phy_status *state);

#endif

0 comments on commit 37688e3

Please sign in to comment.