[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1205445473.8864.171.camel@localhost.localdomain>
Date: Thu, 13 Mar 2008 16:57:53 -0500
From: Nate Case <ncase@...-inc.com>
To: Olof Johansson <olof@...om.net>
Cc: netdev@...r.kernel.org, pasemi-linux@...abs.org,
afleming@...escale.com
Subject: Re: [Pasemi-linux] I2C MDIO support for pasemi_mac driver
On Fri, 2008-03-07 at 12:48 -0600, Olof Johansson wrote:
> On second thought, it might be a better idea to change from BUS:ID to
> BUSTYPE:BUS:ID in phylib, to separate the namespaces.
>
> That, plus a way to get to an i2c bus number from a device tree node,
> and we should be all set. That might be tricker though.
This turned out to not be as invasive of a change as I thought. Here's
my first attempt at it. The changes to pasemi_mac are based on your
first patch but modified accordingly for the new bus type field.
Comments are welcome. Patch is against 2.6.23 for now (though I
wouldn't expect any of these areas to have changed much since then).
After I get some feedback I can rebase against the latest netdev and do
a formal submission.
- Nate Case <ncase@...-inc.com>
---
arch/powerpc/platforms/pasemi/gpio_mdio.c | 1 +
drivers/net/gianfar.c | 3 +-
drivers/net/pasemi_mac.c | 58 ++++++++++++++++++++++++++---
drivers/net/phy/mdio_bus.c | 3 +-
drivers/net/ucc_geth.c | 4 +-
include/linux/phy.h | 7 ++-
6 files changed, 64 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index 098450e..37fa0f5 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -239,6 +239,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
new_bus->read = &gpio_mdio_read;
new_bus->write = &gpio_mdio_write;
new_bus->reset = &gpio_mdio_reset;
+ new_bus->type = "pas_gpio";
prop = of_get_property(np, "reg", NULL);
new_bus->id = *prop;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index f926905..dad8703 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -458,7 +458,8 @@ static int init_phy(struct net_device *dev)
priv->oldspeed = 0;
priv->oldduplex = -1;
- snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id);
+ snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "gfar", priv->einfo->bus_id,
+ priv->einfo->phy_id);
interface = gfar_get_interface(dev);
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 79d277f..6322215 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -181,6 +181,37 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
return 0;
}
+/*
+ * Return the "index number" of an OF device node name. This is for the
+ * node names of the format <device name>@<address>,<index #>
+ * (e.g., "serial@1d,1" or "i2c@1c,2"). If no index exists, 0 is
+ * returned.
+ */
+static int of_get_node_devindex(struct device_node *node)
+{
+ int i, at_index = -1, comma_index = -1;
+
+ i = strlen(node->full_name);
+ while (i > 0) {
+ if (node->full_name[i-1] == '/')
+ return 0;
+
+ if (node->full_name[i-1] == '@') {
+ at_index = i - 1;
+ break;
+ }
+
+ if (node->full_name[i-1] == ',')
+ comma_index = i -1;
+
+ i--;
+ }
+
+ if (at_index == -1 || comma_index == -1)
+ return 0;
+
+ return simple_strtoul(&(node->full_name[comma_index+1]), NULL, 16);
+}
static int mac_to_intf(const struct pasemi_mac *mac)
{
@@ -969,9 +1000,10 @@ static int pasemi_mac_phy_init(struct net_device *dev)
struct pasemi_mac *mac = netdev_priv(dev);
struct device_node *dn, *phy_dn;
struct phy_device *phydev;
- unsigned int phy_id;
+ unsigned int phy_id, bus_id;
const phandle *ph;
const unsigned int *prop;
+ const char *type;
struct resource r;
int ret;
@@ -982,12 +1014,26 @@ static int pasemi_mac_phy_init(struct net_device *dev)
phy_dn = of_find_node_by_phandle(*ph);
prop = of_get_property(phy_dn, "reg", NULL);
- ret = of_address_to_resource(phy_dn->parent, 0, &r);
- if (ret)
- goto err;
+ phy_id = *prop & (PHY_MAX_ADDR - 1);
+ if (of_device_is_compatible(phy_dn->parent, "gpio-mdio")) {
+ ret = of_address_to_resource(phy_dn->parent, 0, &r);
+ if (ret)
+ goto err;
+
+ bus_id = (int)r.start;
+ type = "pas_gpio";
+ } else if (phy_dn->parent->type && !strcmp(phy_dn->parent->type,
+ "i2c")) {
+ /* PHY is on smbus. Bus ID matches I2C bus number.*/
+ bus_id = of_get_node_devindex(phy_dn->parent);
+ type = "i2c";
+ } else {
+ printk("Unknown PHY device in device tree\n");
+ bus_id = -1;
+ type = "unknown";
+ }
- phy_id = *prop;
- snprintf(mac->phy_id, BUS_ID_SIZE, PHY_ID_FMT, (int)r.start, phy_id);
+ snprintf(mac->phy_id, BUS_ID_SIZE, PHY_ID_FMT, type, bus_id, phy_id);
of_node_put(phy_dn);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index a0a706e..d873c5e 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -84,7 +84,8 @@ int mdiobus_register(struct mii_bus *bus)
phydev->dev.parent = bus->dev;
phydev->dev.bus = &mdio_bus_type;
- snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i);
+ snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT,
+ bus->type, bus->id, i);
phydev->bus = bus;
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 9a38dfe..1ea20d8 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1608,8 +1608,8 @@ static int init_phy(struct net_device *dev)
priv->oldspeed = 0;
priv->oldduplex = -1;
- snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->ug_info->mdio_bus,
- priv->ug_info->phy_address);
+ snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "ucc_geth",
+ priv->ug_info->mdio_bus, priv->ug_info->phy_address);
phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 294f4c5..10c59da 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -68,13 +68,16 @@ typedef enum {
#define PHY_MAX_ADDR 32
-/* Used when trying to connect to a specific phy (mii bus id:phy device id) */
-#define PHY_ID_FMT "%x:%02x"
+/*
+ * Used when trying to connect to a specific phy:
+ * (mdio bus type:bus id:phy device id) */
+#define PHY_ID_FMT "%s:%x:%02x"
/* The Bus class for PHYs. Devices which provide access to
* PHYs should register using this structure */
struct mii_bus {
const char *name;
+ const char *type;
int id;
void *priv;
int (*read)(struct mii_bus *bus, int phy_id, int regnum);
--
1.5.3.3
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists