lkml.org 
[lkml]   [2011]   [Feb]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 10/10] staging: octeon_ethernet: Convert to use device tree.
    Date
    Get MAC address and PHY connection from the device tree.

    Signed-off-by: David Daney <ddaney@caviumnetworks.com>
    Cc: "David S. Miller" <davem@davemloft.net>
    Cc: netdev@vger.kernel.org
    ---
    drivers/staging/octeon/ethernet-mdio.c | 27 +++++----
    drivers/staging/octeon/ethernet.c | 101 +++++++++++++++++++-----------
    drivers/staging/octeon/octeon-ethernet.h | 3 +
    3 files changed, 82 insertions(+), 49 deletions(-)

    diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
    index 0e5dab7..38a0153 100644
    --- a/drivers/staging/octeon/ethernet-mdio.c
    +++ b/drivers/staging/octeon/ethernet-mdio.c
    @@ -27,6 +27,7 @@
    #include <linux/kernel.h>
    #include <linux/ethtool.h>
    #include <linux/phy.h>
    +#include <linux/of_mdio.h>

    #include <net/dst.h>

    @@ -162,22 +163,24 @@ static void cvm_oct_adjust_link(struct net_device *dev)
    int cvm_oct_phy_setup_device(struct net_device *dev)
    {
    struct octeon_ethernet *priv = netdev_priv(dev);
    + struct device_node *phy_node;

    - int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
    - if (phy_addr != -1) {
    - char phy_id[20];
    + if (!priv->of_node)
    + return 0;

    - snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
    + phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0);
    + if (!phy_node)
    + return 0;

    - priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
    - PHY_INTERFACE_MODE_GMII);
    + priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
    + PHY_INTERFACE_MODE_GMII);

    - if (IS_ERR(priv->phydev)) {
    - priv->phydev = NULL;
    - return -1;
    - }
    - priv->last_link = 0;
    - phy_start_aneg(priv->phydev);
    + if (IS_ERR(priv->phydev)) {
    + priv->phydev = NULL;
    + return -1;
    }
    + priv->last_link = 0;
    + phy_start_aneg(priv->phydev);
    +
    return 0;
    }
    diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
    index 042adf7..87f8956 100644
    --- a/drivers/staging/octeon/ethernet.c
    +++ b/drivers/staging/octeon/ethernet.c
    @@ -31,6 +31,7 @@
    #include <linux/etherdevice.h>
    #include <linux/phy.h>
    #include <linux/slab.h>
    +#include <linux/of_net.h>

    #include <net/dst.h>

    @@ -112,15 +113,6 @@ int rx_napi_weight = 32;
    module_param(rx_napi_weight, int, 0444);
    MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter.");

    -/*
    - * The offset from mac_addr_base that should be used for the next port
    - * that is configured. By convention, if any mgmt ports exist on the
    - * chip, they get the first mac addresses, The ports controlled by
    - * this driver are numbered sequencially following any mgmt addresses
    - * that may exist.
    - */
    -static unsigned int cvm_oct_mac_addr_offset;
    -
    /**
    * cvm_oct_poll_queue - Workqueue for polling operations.
    */
    @@ -447,26 +439,13 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
    int cvm_oct_common_init(struct net_device *dev)
    {
    struct octeon_ethernet *priv = netdev_priv(dev);
    - struct sockaddr sa;
    - u64 mac = ((u64)(octeon_bootinfo->mac_addr_base[0] & 0xff) << 40) |
    - ((u64)(octeon_bootinfo->mac_addr_base[1] & 0xff) << 32) |
    - ((u64)(octeon_bootinfo->mac_addr_base[2] & 0xff) << 24) |
    - ((u64)(octeon_bootinfo->mac_addr_base[3] & 0xff) << 16) |
    - ((u64)(octeon_bootinfo->mac_addr_base[4] & 0xff) << 8) |
    - (u64)(octeon_bootinfo->mac_addr_base[5] & 0xff);
    -
    - mac += cvm_oct_mac_addr_offset;
    - sa.sa_data[0] = (mac >> 40) & 0xff;
    - sa.sa_data[1] = (mac >> 32) & 0xff;
    - sa.sa_data[2] = (mac >> 24) & 0xff;
    - sa.sa_data[3] = (mac >> 16) & 0xff;
    - sa.sa_data[4] = (mac >> 8) & 0xff;
    - sa.sa_data[5] = mac & 0xff;
    -
    - if (cvm_oct_mac_addr_offset >= octeon_bootinfo->mac_addr_count)
    - printk(KERN_DEBUG "%s: Using MAC outside of the assigned range:"
    - " %pM\n", dev->name, sa.sa_data);
    - cvm_oct_mac_addr_offset++;
    + struct sockaddr sa = {0};
    +
    + if (priv->of_node) {
    + const u8 *mac = of_get_mac_address(priv->of_node);
    + if (mac)
    + memcpy(sa.sa_data, mac, 6);
    + }

    /*
    * Force the interface to use the POW send if always_use_pow
    @@ -594,22 +573,68 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {

    extern void octeon_mdiobus_force_mod_depencency(void);

    +static struct device_node * __init cvm_oct_of_get_child(const struct device_node *parent,
    + int reg_val)
    +{
    + struct device_node *node = NULL;
    + int size;
    + const __be32 *addr;
    +
    + for (;;) {
    + node = of_get_next_child(parent, node);
    + if (!node)
    + break;
    + addr = of_get_property(node, "reg", &size);
    + if (addr && (be32_to_cpu(*addr) == reg_val))
    + break;
    + }
    + return node;
    +}
    +
    +static struct device_node * __init cvm_oct_node_for_port(struct device_node *pip,
    + int interface, int port)
    +{
    + struct device_node *ni, *np;
    +
    + ni = cvm_oct_of_get_child(pip, interface);
    + if (!ni)
    + return NULL;
    +
    + np = cvm_oct_of_get_child(ni, port);
    + of_node_put(ni);
    +
    + return np;
    +}
    +
    static int __init cvm_oct_init_module(void)
    {
    int num_interfaces;
    int interface;
    int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
    int qos;
    + struct device_node *aliases;
    + const char *node_path;
    + struct device_node *pip;

    octeon_mdiobus_force_mod_depencency();
    pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);

    - if (OCTEON_IS_MODEL(OCTEON_CN52XX))
    - cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */
    - else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
    - cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */
    - else
    - cvm_oct_mac_addr_offset = 0;
    +
    + aliases = of_find_node_by_path("/aliases");
    + if (!aliases) {
    + pr_err("Error: No /aliases node in device tree.");
    + return -EINVAL;
    + }
    + node_path = of_get_property(aliases, "pip", NULL);
    + if (!node_path) {
    + pr_err("Error: No /aliases/pip node in device tree.");
    + return -EINVAL;
    + }
    + pip = of_find_node_by_path(node_path);
    + if (!pip) {
    + pr_err("Error: No %s in device tree.", node_path);
    + return -EINVAL;
    + }

    cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet");
    if (cvm_oct_poll_queue == NULL) {
    @@ -688,10 +713,11 @@ static int __init cvm_oct_init_module(void)
    cvmx_helper_interface_get_mode(interface);
    int num_ports = cvmx_helper_ports_on_interface(interface);
    int port;
    + int port_index;

    - for (port = cvmx_helper_get_ipd_port(interface, 0);
    + for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0);
    port < cvmx_helper_get_ipd_port(interface, num_ports);
    - port++) {
    + port_index++, port++) {
    struct octeon_ethernet *priv;
    struct net_device *dev =
    alloc_etherdev(sizeof(struct octeon_ethernet));
    @@ -702,6 +728,7 @@ static int __init cvm_oct_init_module(void)

    /* Initialize the device private structure. */
    priv = netdev_priv(dev);
    + priv->of_node = cvm_oct_node_for_port(pip, interface, port_index);

    INIT_DELAYED_WORK(&priv->port_periodic_work,
    cvm_oct_periodic_worker);
    diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h
    index d581925..9360e22 100644
    --- a/drivers/staging/octeon/octeon-ethernet.h
    +++ b/drivers/staging/octeon/octeon-ethernet.h
    @@ -31,6 +31,8 @@
    #ifndef OCTEON_ETHERNET_H
    #define OCTEON_ETHERNET_H

    +#include <linux/of.h>
    +
    /**
    * This is the definition of the Ethernet driver's private
    * driver state stored in netdev_priv(dev).
    @@ -59,6 +61,7 @@ struct octeon_ethernet {
    void (*poll) (struct net_device *dev);
    struct delayed_work port_periodic_work;
    struct work_struct port_work; /* may be unused. */
    + struct device_node *of_node;
    };

    int cvm_oct_free_work(void *work_queue_entry);
    --
    1.7.2.3


    \
     
     \ /
      Last update: 2011-02-22 22:01    [W:2.285 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site