~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise-security

« back to all changes in this revision

Viewing changes to drivers/net/ethernet/xilinx/ll_temac_mdio.c

  • Committer: Package Import Robot
  • Author(s): Paolo Pisati, Paolo Pisati
  • Date: 2011-12-06 15:56:07 UTC
  • Revision ID: package-import@ubuntu.com-20111206155607-pcf44kv5fmhk564f
Tags: 3.2.0-1401.1
[ Paolo Pisati ]

* Rebased on top of Ubuntu-3.2.0-3.8
* Tilt-tracking @ ef2487af4bb15bdd0689631774b5a5e3a59f74e2
* Delete debian.ti-omap4/control, it shoudln't be tracked
* Fix architecture spelling (s/armel/armhf/)
* [Config] Update configs following 3.2 import
* [Config] Fix compilation: disable CODA and ARCH_OMAP3
* [Config] Fix compilation: disable Ethernet Faraday
* Update series to precise

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * MDIO bus driver for the Xilinx TEMAC device
 
3
 *
 
4
 * Copyright (c) 2009 Secret Lab Technologies, Ltd.
 
5
 */
 
6
 
 
7
#include <linux/io.h>
 
8
#include <linux/netdevice.h>
 
9
#include <linux/mutex.h>
 
10
#include <linux/phy.h>
 
11
#include <linux/of.h>
 
12
#include <linux/of_device.h>
 
13
#include <linux/of_address.h>
 
14
#include <linux/slab.h>
 
15
#include <linux/of_mdio.h>
 
16
 
 
17
#include "ll_temac.h"
 
18
 
 
19
/* ---------------------------------------------------------------------
 
20
 * MDIO Bus functions
 
21
 */
 
22
static int temac_mdio_read(struct mii_bus *bus, int phy_id, int reg)
 
23
{
 
24
        struct temac_local *lp = bus->priv;
 
25
        u32 rc;
 
26
 
 
27
        /* Write the PHY address to the MIIM Access Initiator register.
 
28
         * When the transfer completes, the PHY register value will appear
 
29
         * in the LSW0 register */
 
30
        mutex_lock(&lp->indirect_mutex);
 
31
        temac_iow(lp, XTE_LSW0_OFFSET, (phy_id << 5) | reg);
 
32
        rc = temac_indirect_in32(lp, XTE_MIIMAI_OFFSET);
 
33
        mutex_unlock(&lp->indirect_mutex);
 
34
 
 
35
        dev_dbg(lp->dev, "temac_mdio_read(phy_id=%i, reg=%x) == %x\n",
 
36
                phy_id, reg, rc);
 
37
 
 
38
        return rc;
 
39
}
 
40
 
 
41
static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
 
42
{
 
43
        struct temac_local *lp = bus->priv;
 
44
 
 
45
        dev_dbg(lp->dev, "temac_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
 
46
                phy_id, reg, val);
 
47
 
 
48
        /* First write the desired value into the write data register
 
49
         * and then write the address into the access initiator register
 
50
         */
 
51
        mutex_lock(&lp->indirect_mutex);
 
52
        temac_indirect_out32(lp, XTE_MGTDR_OFFSET, val);
 
53
        temac_indirect_out32(lp, XTE_MIIMAI_OFFSET, (phy_id << 5) | reg);
 
54
        mutex_unlock(&lp->indirect_mutex);
 
55
 
 
56
        return 0;
 
57
}
 
58
 
 
59
int temac_mdio_setup(struct temac_local *lp, struct device_node *np)
 
60
{
 
61
        struct mii_bus *bus;
 
62
        const u32 *bus_hz;
 
63
        int clk_div;
 
64
        int rc, size;
 
65
        struct resource res;
 
66
 
 
67
        /* Calculate a reasonable divisor for the clock rate */
 
68
        clk_div = 0x3f; /* worst-case default setting */
 
69
        bus_hz = of_get_property(np, "clock-frequency", &size);
 
70
        if (bus_hz && size >= sizeof(*bus_hz)) {
 
71
                clk_div = (*bus_hz) / (2500 * 1000 * 2) - 1;
 
72
                if (clk_div < 1)
 
73
                        clk_div = 1;
 
74
                if (clk_div > 0x3f)
 
75
                        clk_div = 0x3f;
 
76
        }
 
77
 
 
78
        /* Enable the MDIO bus by asserting the enable bit and writing
 
79
         * in the clock config */
 
80
        mutex_lock(&lp->indirect_mutex);
 
81
        temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div);
 
82
        mutex_unlock(&lp->indirect_mutex);
 
83
 
 
84
        bus = mdiobus_alloc();
 
85
        if (!bus)
 
86
                return -ENOMEM;
 
87
 
 
88
        of_address_to_resource(np, 0, &res);
 
89
        snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
 
90
                 (unsigned long long)res.start);
 
91
        bus->priv = lp;
 
92
        bus->name = "Xilinx TEMAC MDIO";
 
93
        bus->read = temac_mdio_read;
 
94
        bus->write = temac_mdio_write;
 
95
        bus->parent = lp->dev;
 
96
        bus->irq = lp->mdio_irqs; /* preallocated IRQ table */
 
97
 
 
98
        lp->mii_bus = bus;
 
99
 
 
100
        rc = of_mdiobus_register(bus, np);
 
101
        if (rc)
 
102
                goto err_register;
 
103
 
 
104
        mutex_lock(&lp->indirect_mutex);
 
105
        dev_dbg(lp->dev, "MDIO bus registered;  MC:%x\n",
 
106
                temac_indirect_in32(lp, XTE_MC_OFFSET));
 
107
        mutex_unlock(&lp->indirect_mutex);
 
108
        return 0;
 
109
 
 
110
 err_register:
 
111
        mdiobus_free(bus);
 
112
        return rc;
 
113
}
 
114
 
 
115
void temac_mdio_teardown(struct temac_local *lp)
 
116
{
 
117
        mdiobus_unregister(lp->mii_bus);
 
118
        kfree(lp->mii_bus->irq);
 
119
        mdiobus_free(lp->mii_bus);
 
120
        lp->mii_bus = NULL;
 
121
}
 
122