staging: brcm80211: remove brcms_b_dotxstatus wrapper function
[zen-stable.git] / drivers / staging / et131x / et1310_phy.c
blob145ec765beaf5a9263091452e7742bedc8404c86
1 /*
2 * Agere Systems Inc.
3 * 10/100/1000 Base-T Ethernet Driver for the ET1310 and ET131x series MACs
5 * Copyright * 2005 Agere Systems Inc.
6 * All rights reserved.
7 * http://www.agere.com
9 * Copyright (c) 2011 Mark Einon <mark.einon@gmail.com>
11 *------------------------------------------------------------------------------
13 * et1310_phy.c - Routines for configuring and accessing the PHY
15 *------------------------------------------------------------------------------
17 * SOFTWARE LICENSE
19 * This software is provided subject to the following terms and conditions,
20 * which you should read carefully before using the software. Using this
21 * software indicates your acceptance of these terms and conditions. If you do
22 * not agree with these terms and conditions, do not use the software.
24 * Copyright * 2005 Agere Systems Inc.
25 * All rights reserved.
27 * Redistribution and use in source or binary forms, with or without
28 * modifications, are permitted provided that the following conditions are met:
30 * . Redistributions of source code must retain the above copyright notice, this
31 * list of conditions and the following Disclaimer as comments in the code as
32 * well as in the documentation and/or other materials provided with the
33 * distribution.
35 * . Redistributions in binary form must reproduce the above copyright notice,
36 * this list of conditions and the following Disclaimer in the documentation
37 * and/or other materials provided with the distribution.
39 * . Neither the name of Agere Systems Inc. nor the names of the contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * Disclaimer
45 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
46 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
47 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
48 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
49 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
50 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
51 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
52 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
56 * DAMAGE.
60 #include "et131x_version.h"
61 #include "et131x_defs.h"
63 #include <linux/pci.h>
64 #include <linux/init.h>
65 #include <linux/module.h>
66 #include <linux/types.h>
67 #include <linux/kernel.h>
69 #include <linux/sched.h>
70 #include <linux/ptrace.h>
71 #include <linux/ctype.h>
72 #include <linux/string.h>
73 #include <linux/timer.h>
74 #include <linux/interrupt.h>
75 #include <linux/in.h>
76 #include <linux/delay.h>
77 #include <linux/io.h>
78 #include <linux/bitops.h>
79 #include <asm/system.h>
81 #include <linux/netdevice.h>
82 #include <linux/etherdevice.h>
83 #include <linux/skbuff.h>
84 #include <linux/if_arp.h>
85 #include <linux/ioport.h>
86 #include <linux/random.h>
87 #include <linux/phy.h>
89 #include "et1310_phy.h"
91 #include "et131x_adapter.h"
93 #include "et1310_address_map.h"
94 #include "et1310_tx.h"
95 #include "et1310_rx.h"
97 #include "et131x.h"
99 int et131x_mdio_read(struct mii_bus *bus, int phy_addr, int reg)
101 struct net_device *netdev = bus->priv;
102 struct et131x_adapter *adapter = netdev_priv(netdev);
103 u16 value;
104 int ret;
106 ret = et131x_phy_mii_read(adapter, phy_addr, reg, &value);
108 if (ret < 0)
109 return ret;
110 else
111 return value;
114 int et131x_mdio_write(struct mii_bus *bus, int phy_addr, int reg, u16 value)
116 struct net_device *netdev = bus->priv;
117 struct et131x_adapter *adapter = netdev_priv(netdev);
119 return et131x_mii_write(adapter, reg, value);
122 int et131x_mdio_reset(struct mii_bus *bus)
124 struct net_device *netdev = bus->priv;
125 struct et131x_adapter *adapter = netdev_priv(netdev);
127 et131x_mii_write(adapter, MII_BMCR, BMCR_RESET);
129 return 0;
132 int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value)
134 struct phy_device *phydev = adapter->phydev;
136 if (!phydev)
137 return -EIO;
139 return et131x_phy_mii_read(adapter, phydev->addr, reg, value);
143 * et131x_phy_mii_read - Read from the PHY through the MII Interface on the MAC
144 * @adapter: pointer to our private adapter structure
145 * @addr: the address of the transceiver
146 * @reg: the register to read
147 * @value: pointer to a 16-bit value in which the value will be stored
149 * Returns 0 on success, errno on failure (as defined in errno.h)
151 int et131x_phy_mii_read(struct et131x_adapter *adapter, u8 addr,
152 u8 reg, u16 *value)
154 struct mac_regs __iomem *mac = &adapter->regs->mac;
155 int status = 0;
156 u32 delay = 0;
157 u32 mii_addr;
158 u32 mii_cmd;
159 u32 mii_indicator;
161 /* Save a local copy of the registers we are dealing with so we can
162 * set them back
164 mii_addr = readl(&mac->mii_mgmt_addr);
165 mii_cmd = readl(&mac->mii_mgmt_cmd);
167 /* Stop the current operation */
168 writel(0, &mac->mii_mgmt_cmd);
170 /* Set up the register we need to read from on the correct PHY */
171 writel(MII_ADDR(addr, reg), &mac->mii_mgmt_addr);
173 writel(0x1, &mac->mii_mgmt_cmd);
175 do {
176 udelay(50);
177 delay++;
178 mii_indicator = readl(&mac->mii_mgmt_indicator);
179 } while ((mii_indicator & MGMT_WAIT) && delay < 50);
181 /* If we hit the max delay, we could not read the register */
182 if (delay == 50) {
183 dev_warn(&adapter->pdev->dev,
184 "reg 0x%08x could not be read\n", reg);
185 dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
186 mii_indicator);
188 status = -EIO;
191 /* If we hit here we were able to read the register and we need to
192 * return the value to the caller */
193 *value = readl(&mac->mii_mgmt_stat) & 0xFFFF;
195 /* Stop the read operation */
196 writel(0, &mac->mii_mgmt_cmd);
198 /* set the registers we touched back to the state at which we entered
199 * this function
201 writel(mii_addr, &mac->mii_mgmt_addr);
202 writel(mii_cmd, &mac->mii_mgmt_cmd);
204 return status;
208 * et131x_mii_write - Write to a PHY register through the MII interface of the MAC
209 * @adapter: pointer to our private adapter structure
210 * @reg: the register to read
211 * @value: 16-bit value to write
213 * FIXME: one caller in netdev still
215 * Return 0 on success, errno on failure (as defined in errno.h)
217 int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value)
219 struct mac_regs __iomem *mac = &adapter->regs->mac;
220 struct phy_device *phydev = adapter->phydev;
221 int status = 0;
222 u8 addr;
223 u32 delay = 0;
224 u32 mii_addr;
225 u32 mii_cmd;
226 u32 mii_indicator;
228 if (!phydev)
229 return -EIO;
231 addr = phydev->addr;
233 /* Save a local copy of the registers we are dealing with so we can
234 * set them back
236 mii_addr = readl(&mac->mii_mgmt_addr);
237 mii_cmd = readl(&mac->mii_mgmt_cmd);
239 /* Stop the current operation */
240 writel(0, &mac->mii_mgmt_cmd);
242 /* Set up the register we need to write to on the correct PHY */
243 writel(MII_ADDR(addr, reg), &mac->mii_mgmt_addr);
245 /* Add the value to write to the registers to the mac */
246 writel(value, &mac->mii_mgmt_ctrl);
248 do {
249 udelay(50);
250 delay++;
251 mii_indicator = readl(&mac->mii_mgmt_indicator);
252 } while ((mii_indicator & MGMT_BUSY) && delay < 100);
254 /* If we hit the max delay, we could not write the register */
255 if (delay == 100) {
256 u16 tmp;
258 dev_warn(&adapter->pdev->dev,
259 "reg 0x%08x could not be written", reg);
260 dev_warn(&adapter->pdev->dev, "status is 0x%08x\n",
261 mii_indicator);
262 dev_warn(&adapter->pdev->dev, "command is 0x%08x\n",
263 readl(&mac->mii_mgmt_cmd));
265 et131x_mii_read(adapter, reg, &tmp);
267 status = -EIO;
269 /* Stop the write operation */
270 writel(0, &mac->mii_mgmt_cmd);
273 * set the registers we touched back to the state at which we entered
274 * this function
276 writel(mii_addr, &mac->mii_mgmt_addr);
277 writel(mii_cmd, &mac->mii_mgmt_cmd);
279 return status;
283 * et1310_phy_power_down - PHY power control
284 * @adapter: device to control
285 * @down: true for off/false for back on
287 * one hundred, ten, one thousand megs
288 * How would you like to have your LAN accessed
289 * Can't you see that this code processed
290 * Phy power, phy power..
292 void et1310_phy_power_down(struct et131x_adapter *adapter, bool down)
294 u16 data;
296 et131x_mii_read(adapter, MII_BMCR, &data);
297 data &= ~BMCR_PDOWN;
298 if (down)
299 data |= BMCR_PDOWN;
300 et131x_mii_write(adapter, MII_BMCR, data);
303 /* Still used from _mac for BIT_READ */
304 void et1310_phy_access_mii_bit(struct et131x_adapter *adapter, u16 action,
305 u16 regnum, u16 bitnum, u8 *value)
307 u16 reg;
308 u16 mask = 0x0001 << bitnum;
310 /* Read the requested register */
311 et131x_mii_read(adapter, regnum, &reg);
313 switch (action) {
314 case TRUEPHY_BIT_READ:
315 *value = (reg & mask) >> bitnum;
316 break;
318 case TRUEPHY_BIT_SET:
319 et131x_mii_write(adapter, regnum, reg | mask);
320 break;
322 case TRUEPHY_BIT_CLEAR:
323 et131x_mii_write(adapter, regnum, reg & ~mask);
324 break;
326 default:
327 break;
332 * et131x_xcvr_init - Init the phy if we are setting it into force mode
333 * @adapter: pointer to our private adapter structure
336 void et131x_xcvr_init(struct et131x_adapter *adapter)
338 u16 imr;
339 u16 isr;
340 u16 lcr2;
342 et131x_mii_read(adapter, PHY_INTERRUPT_STATUS, &isr);
343 et131x_mii_read(adapter, PHY_INTERRUPT_MASK, &imr);
345 /* Set the link status interrupt only. Bad behavior when link status
346 * and auto neg are set, we run into a nested interrupt problem
348 imr |= (ET_PHY_INT_MASK_AUTONEGSTAT &
349 ET_PHY_INT_MASK_LINKSTAT &
350 ET_PHY_INT_MASK_ENABLE);
352 et131x_mii_write(adapter, PHY_INTERRUPT_MASK, imr);
354 /* Set the LED behavior such that LED 1 indicates speed (off =
355 * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
356 * link and activity (on for link, blink off for activity).
358 * NOTE: Some customizations have been added here for specific
359 * vendors; The LED behavior is now determined by vendor data in the
360 * EEPROM. However, the above description is the default.
362 if ((adapter->eeprom_data[1] & 0x4) == 0) {
363 et131x_mii_read(adapter, PHY_LED_2, &lcr2);
365 lcr2 &= (ET_LED2_LED_100TX & ET_LED2_LED_1000T);
366 lcr2 |= (LED_VAL_LINKON_ACTIVE << LED_LINK_SHIFT);
368 if ((adapter->eeprom_data[1] & 0x8) == 0)
369 lcr2 |= (LED_VAL_1000BT_100BTX << LED_TXRX_SHIFT);
370 else
371 lcr2 |= (LED_VAL_LINKON << LED_TXRX_SHIFT);
373 et131x_mii_write(adapter, PHY_LED_2, lcr2);