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

« back to all changes in this revision

Viewing changes to drivers/net/stmmac/stmmac_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
 
  STMMAC Ethernet Driver -- MDIO bus implementation
3
 
  Provides Bus interface for MII registers
4
 
 
5
 
  Copyright (C) 2007-2009  STMicroelectronics Ltd
6
 
 
7
 
  This program is free software; you can redistribute it and/or modify it
8
 
  under the terms and conditions of the GNU General Public License,
9
 
  version 2, as published by the Free Software Foundation.
10
 
 
11
 
  This program is distributed in the hope it will be useful, but WITHOUT
12
 
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
 
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
 
  more details.
15
 
 
16
 
  You should have received a copy of the GNU General Public License along with
17
 
  this program; if not, write to the Free Software Foundation, Inc.,
18
 
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19
 
 
20
 
  The full GNU General Public License is included in this distribution in
21
 
  the file called "COPYING".
22
 
 
23
 
  Author: Carl Shaw <carl.shaw@st.com>
24
 
  Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
25
 
*******************************************************************************/
26
 
 
27
 
#include <linux/mii.h>
28
 
#include <linux/phy.h>
29
 
#include <linux/slab.h>
30
 
 
31
 
#include "stmmac.h"
32
 
 
33
 
#define MII_BUSY 0x00000001
34
 
#define MII_WRITE 0x00000002
35
 
 
36
 
/**
37
 
 * stmmac_mdio_read
38
 
 * @bus: points to the mii_bus structure
39
 
 * @phyaddr: MII addr reg bits 15-11
40
 
 * @phyreg: MII addr reg bits 10-6
41
 
 * Description: it reads data from the MII register from within the phy device.
42
 
 * For the 7111 GMAC, we must set the bit 0 in the MII address register while
43
 
 * accessing the PHY registers.
44
 
 * Fortunately, it seems this has no drawback for the 7109 MAC.
45
 
 */
46
 
static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
47
 
{
48
 
        struct net_device *ndev = bus->priv;
49
 
        struct stmmac_priv *priv = netdev_priv(ndev);
50
 
        unsigned int mii_address = priv->hw->mii.addr;
51
 
        unsigned int mii_data = priv->hw->mii.data;
52
 
 
53
 
        int data;
54
 
        u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
55
 
                        ((phyreg << 6) & (0x000007C0)));
56
 
        regValue |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2);
57
 
 
58
 
        do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
59
 
        writel(regValue, priv->ioaddr + mii_address);
60
 
        do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
61
 
 
62
 
        /* Read the data from the MII data register */
63
 
        data = (int)readl(priv->ioaddr + mii_data);
64
 
 
65
 
        return data;
66
 
}
67
 
 
68
 
/**
69
 
 * stmmac_mdio_write
70
 
 * @bus: points to the mii_bus structure
71
 
 * @phyaddr: MII addr reg bits 15-11
72
 
 * @phyreg: MII addr reg bits 10-6
73
 
 * @phydata: phy data
74
 
 * Description: it writes the data into the MII register from within the device.
75
 
 */
76
 
static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
77
 
                             u16 phydata)
78
 
{
79
 
        struct net_device *ndev = bus->priv;
80
 
        struct stmmac_priv *priv = netdev_priv(ndev);
81
 
        unsigned int mii_address = priv->hw->mii.addr;
82
 
        unsigned int mii_data = priv->hw->mii.data;
83
 
 
84
 
        u16 value =
85
 
            (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
86
 
            | MII_WRITE;
87
 
 
88
 
        value |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2);
89
 
 
90
 
 
91
 
        /* Wait until any existing MII operation is complete */
92
 
        do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
93
 
 
94
 
        /* Set the MII address register to write */
95
 
        writel(phydata, priv->ioaddr + mii_data);
96
 
        writel(value, priv->ioaddr + mii_address);
97
 
 
98
 
        /* Wait until any existing MII operation is complete */
99
 
        do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1);
100
 
 
101
 
        return 0;
102
 
}
103
 
 
104
 
/**
105
 
 * stmmac_mdio_reset
106
 
 * @bus: points to the mii_bus structure
107
 
 * Description: reset the MII bus
108
 
 */
109
 
static int stmmac_mdio_reset(struct mii_bus *bus)
110
 
{
111
 
        struct net_device *ndev = bus->priv;
112
 
        struct stmmac_priv *priv = netdev_priv(ndev);
113
 
        unsigned int mii_address = priv->hw->mii.addr;
114
 
 
115
 
        if (priv->phy_reset) {
116
 
                pr_debug("stmmac_mdio_reset: calling phy_reset\n");
117
 
                priv->phy_reset(priv->plat->bsp_priv);
118
 
        }
119
 
 
120
 
        /* This is a workaround for problems with the STE101P PHY.
121
 
         * It doesn't complete its reset until at least one clock cycle
122
 
         * on MDC, so perform a dummy mdio read.
123
 
         */
124
 
        writel(0, priv->ioaddr + mii_address);
125
 
 
126
 
        return 0;
127
 
}
128
 
 
129
 
/**
130
 
 * stmmac_mdio_register
131
 
 * @ndev: net device structure
132
 
 * Description: it registers the MII bus
133
 
 */
134
 
int stmmac_mdio_register(struct net_device *ndev)
135
 
{
136
 
        int err = 0;
137
 
        struct mii_bus *new_bus;
138
 
        int *irqlist;
139
 
        struct stmmac_priv *priv = netdev_priv(ndev);
140
 
        int addr, found;
141
 
 
142
 
        new_bus = mdiobus_alloc();
143
 
        if (new_bus == NULL)
144
 
                return -ENOMEM;
145
 
 
146
 
        irqlist = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
147
 
        if (irqlist == NULL) {
148
 
                err = -ENOMEM;
149
 
                goto irqlist_alloc_fail;
150
 
        }
151
 
 
152
 
        /* Assign IRQ to phy at address phy_addr */
153
 
        if (priv->phy_addr != -1)
154
 
                irqlist[priv->phy_addr] = priv->phy_irq;
155
 
 
156
 
        new_bus->name = "STMMAC MII Bus";
157
 
        new_bus->read = &stmmac_mdio_read;
158
 
        new_bus->write = &stmmac_mdio_write;
159
 
        new_bus->reset = &stmmac_mdio_reset;
160
 
        snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
161
 
        new_bus->priv = ndev;
162
 
        new_bus->irq = irqlist;
163
 
        new_bus->phy_mask = priv->phy_mask;
164
 
        new_bus->parent = priv->device;
165
 
        err = mdiobus_register(new_bus);
166
 
        if (err != 0) {
167
 
                pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
168
 
                goto bus_register_fail;
169
 
        }
170
 
 
171
 
        priv->mii = new_bus;
172
 
 
173
 
        found = 0;
174
 
        for (addr = 0; addr < 32; addr++) {
175
 
                struct phy_device *phydev = new_bus->phy_map[addr];
176
 
                if (phydev) {
177
 
                        if (priv->phy_addr == -1) {
178
 
                                priv->phy_addr = addr;
179
 
                                phydev->irq = priv->phy_irq;
180
 
                                irqlist[addr] = priv->phy_irq;
181
 
                        }
182
 
                        pr_info("%s: PHY ID %08x at %d IRQ %d (%s)%s\n",
183
 
                               ndev->name, phydev->phy_id, addr,
184
 
                               phydev->irq, dev_name(&phydev->dev),
185
 
                               (addr == priv->phy_addr) ? " active" : "");
186
 
                        found = 1;
187
 
                }
188
 
        }
189
 
 
190
 
        if (!found)
191
 
                pr_warning("%s: No PHY found\n", ndev->name);
192
 
 
193
 
        return 0;
194
 
bus_register_fail:
195
 
        kfree(irqlist);
196
 
irqlist_alloc_fail:
197
 
        kfree(new_bus);
198
 
        return err;
199
 
}
200
 
 
201
 
/**
202
 
 * stmmac_mdio_unregister
203
 
 * @ndev: net device structure
204
 
 * Description: it unregisters the MII bus
205
 
 */
206
 
int stmmac_mdio_unregister(struct net_device *ndev)
207
 
{
208
 
        struct stmmac_priv *priv = netdev_priv(ndev);
209
 
 
210
 
        mdiobus_unregister(priv->mii);
211
 
        priv->mii->priv = NULL;
212
 
        kfree(priv->mii);
213
 
 
214
 
        return 0;
215
 
}