Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 314685
b: refs/heads/master
c: ac28b9f
h: refs/heads/master
i:
  314683: 899805a
v: v3
  • Loading branch information
David Daney authored and David S. Miller committed Jun 28, 2012
1 parent ec3d94d commit 1bf5d5d
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a3caad0a160c03b7238a2518fa89abda78adef1e
refs/heads/master: ac28b9f8cd66d6bc54f8063df59e99abd62173a4
2 changes: 1 addition & 1 deletion trunk/drivers/net/phy/mdio_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
struct phy_device *phydev;
int err;

phydev = get_phy_device(bus, addr);
phydev = get_phy_device(bus, addr, false);
if (IS_ERR(phydev) || phydev == NULL)
return phydev;

Expand Down
105 changes: 97 additions & 8 deletions trunk/drivers/net/phy/phy_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ int phy_scan_fixups(struct phy_device *phydev)
}
EXPORT_SYMBOL(phy_scan_fixups);

static struct phy_device* phy_device_create(struct mii_bus *bus,
int addr, int phy_id)
struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
bool is_c45, struct phy_c45_device_ids *c45_ids)
{
struct phy_device *dev;

Expand All @@ -174,8 +174,11 @@ static struct phy_device* phy_device_create(struct mii_bus *bus,

dev->autoneg = AUTONEG_ENABLE;

dev->is_c45 = is_c45;
dev->addr = addr;
dev->phy_id = phy_id;
if (c45_ids)
dev->c45_ids = *c45_ids;
dev->bus = bus;
dev->dev.parent = bus->parent;
dev->dev.bus = &mdio_bus_type;
Expand All @@ -200,20 +203,99 @@ static struct phy_device* phy_device_create(struct mii_bus *bus,

return dev;
}
EXPORT_SYMBOL(phy_device_create);

/**
* get_phy_c45_ids - reads the specified addr for its 802.3-c45 IDs.
* @bus: the target MII bus
* @addr: PHY address on the MII bus
* @phy_id: where to store the ID retrieved.
* @c45_ids: where to store the c45 ID information.
*
* If the PHY devices-in-package appears to be valid, it and the
* corresponding identifiers are stored in @c45_ids, zero is stored
* in @phy_id. Otherwise 0xffffffff is stored in @phy_id. Returns
* zero on success.
*
*/
static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id,
struct phy_c45_device_ids *c45_ids) {
int phy_reg;
int i, reg_addr;
const int num_ids = ARRAY_SIZE(c45_ids->device_ids);

/* Find first non-zero Devices In package. Device
* zero is reserved, so don't probe it.
*/
for (i = 1;
i < num_ids && c45_ids->devices_in_package == 0;
i++) {
reg_addr = MII_ADDR_C45 | i << 16 | 6;
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
c45_ids->devices_in_package = (phy_reg & 0xffff) << 16;

reg_addr = MII_ADDR_C45 | i << 16 | 5;
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
c45_ids->devices_in_package |= (phy_reg & 0xffff);

/* If mostly Fs, there is no device there,
* let's get out of here.
*/
if ((c45_ids->devices_in_package & 0x1fffffff) == 0x1fffffff) {
*phy_id = 0xffffffff;
return 0;
}
}

/* Now probe Device Identifiers for each device present. */
for (i = 1; i < num_ids; i++) {
if (!(c45_ids->devices_in_package & (1 << i)))
continue;

reg_addr = MII_ADDR_C45 | i << 16 | MII_PHYSID1;
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
c45_ids->device_ids[i] = (phy_reg & 0xffff) << 16;

reg_addr = MII_ADDR_C45 | i << 16 | MII_PHYSID2;
phy_reg = mdiobus_read(bus, addr, reg_addr);
if (phy_reg < 0)
return -EIO;
c45_ids->device_ids[i] |= (phy_reg & 0xffff);
}
*phy_id = 0;
return 0;
}

/**
* get_phy_id - reads the specified addr for its ID.
* @bus: the target MII bus
* @addr: PHY address on the MII bus
* @phy_id: where to store the ID retrieved.
* @is_c45: If true the PHY uses the 802.3 clause 45 protocol
* @c45_ids: where to store the c45 ID information.
*
* Description: In the case of a 802.3-c22 PHY, reads the ID registers
* of the PHY at @addr on the @bus, stores it in @phy_id and returns
* zero on success.
*
* In the case of a 802.3-c45 PHY, get_phy_c45_ids() is invoked, and
* its return value is in turn returned.
*
* Description: Reads the ID registers of the PHY at @addr on the
* @bus, stores it in @phy_id and returns zero on success.
*/
static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id,
bool is_c45, struct phy_c45_device_ids *c45_ids)
{
int phy_reg;

if (is_c45)
return get_phy_c45_ids(bus, addr, phy_id, c45_ids);

/* Grab the bits from PHYIR1, and put them
* in the upper half */
phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);
Expand All @@ -238,25 +320,27 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id)
* get_phy_device - reads the specified PHY device and returns its @phy_device struct
* @bus: the target MII bus
* @addr: PHY address on the MII bus
* @is_c45: If true the PHY uses the 802.3 clause 45 protocol
*
* Description: Reads the ID registers of the PHY at @addr on the
* @bus, then allocates and returns the phy_device to represent it.
*/
struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
{
struct phy_device *dev = NULL;
u32 phy_id;
struct phy_c45_device_ids c45_ids = {0};
int r;

r = get_phy_id(bus, addr, &phy_id);
r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids);
if (r)
return ERR_PTR(r);

/* If the phy_id is mostly Fs, there is no device there */
if ((phy_id & 0x1fffffff) == 0x1fffffff)
return NULL;

dev = phy_device_create(bus, addr, phy_id);
dev = phy_device_create(bus, addr, phy_id, is_c45, &c45_ids);

return dev;
}
Expand Down Expand Up @@ -449,6 +533,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
/* Assume that if there is no driver, that it doesn't
* exist, and we should use the genphy driver. */
if (NULL == d->driver) {
if (phydev->is_c45) {
pr_err("No driver for phy %x\n", phydev->phy_id);
return -ENODEV;
}

d->driver = &genphy_driver.driver;

err = d->driver->probe(d);
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/of/of_mdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
mdio->irq[addr] = PHY_POLL;
}

phy = get_phy_device(mdio, addr);
phy = get_phy_device(mdio, addr, false);
if (!phy || IS_ERR(phy)) {
dev_err(&mdio->dev, "error probing PHY at address %i\n",
addr);
Expand Down
18 changes: 17 additions & 1 deletion trunk/include/linux/phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,24 @@ enum phy_state {
PHY_RESUMING
};

/**
* struct phy_c45_device_ids - 802.3-c45 Device Identifiers
* @devices_in_package: Bit vector of devices present.
* @device_ids: The device identifer for each present device.
*/
struct phy_c45_device_ids {
u32 devices_in_package;
u32 device_ids[8];
};

/* phy_device: An instance of a PHY
*
* drv: Pointer to the driver for this PHY instance
* bus: Pointer to the bus this PHY is on
* dev: driver model device structure for this PHY
* phy_id: UID for this device found during discovery
* c45_ids: 802.3-c45 Device Identifers if is_c45.
* is_c45: Set to true if this phy uses clause 45 addressing.
* state: state of the PHY for management purposes
* dev_flags: Device-specific flags used by the PHY driver.
* addr: Bus address of PHY
Expand Down Expand Up @@ -285,6 +296,9 @@ struct phy_device {

u32 phy_id;

struct phy_c45_device_ids c45_ids;
bool is_c45;

enum phy_state state;

u32 dev_flags;
Expand Down Expand Up @@ -480,7 +494,9 @@ static inline int phy_write(struct phy_device *phydev, u32 regnum, u16 val)
return mdiobus_write(phydev->bus, phydev->addr, regnum, val);
}

struct phy_device* get_phy_device(struct mii_bus *bus, int addr);
struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
bool is_c45, struct phy_c45_device_ids *c45_ids);
struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
int phy_device_register(struct phy_device *phy);
int phy_init_hw(struct phy_device *phydev);
struct phy_device * phy_attach(struct net_device *dev,
Expand Down

0 comments on commit 1bf5d5d

Please sign in to comment.