aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/marvell.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index def19d7c53ef..e8b9c53c304b 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -30,6 +30,7 @@
30#include <linux/ethtool.h> 30#include <linux/ethtool.h>
31#include <linux/phy.h> 31#include <linux/phy.h>
32#include <linux/marvell_phy.h> 32#include <linux/marvell_phy.h>
33#include <linux/of.h>
33 34
34#include <asm/io.h> 35#include <asm/io.h>
35#include <asm/irq.h> 36#include <asm/irq.h>
@@ -187,6 +188,87 @@ static int marvell_config_aneg(struct phy_device *phydev)
187 return 0; 188 return 0;
188} 189}
189 190
191#ifdef CONFIG_OF_MDIO
192/*
193 * Set and/or override some configuration registers based on the
194 * marvell,reg-init property stored in the of_node for the phydev.
195 *
196 * marvell,reg-init = <reg-page reg mask value>,...;
197 *
198 * There may be one or more sets of <reg-page reg mask value>:
199 *
200 * reg-page: which register bank to use.
201 * reg: the register.
202 * mask: if non-zero, ANDed with existing register value.
203 * value: ORed with the masked value and written to the regiser.
204 *
205 */
206static int marvell_of_reg_init(struct phy_device *phydev)
207{
208 const __be32 *paddr;
209 int len, i, saved_page, current_page, page_changed, ret;
210
211 if (!phydev->dev.of_node)
212 return 0;
213
214 paddr = of_get_property(phydev->dev.of_node, "marvell,reg-init", &len);
215 if (!paddr || len < (4 * sizeof(*paddr)))
216 return 0;
217
218 saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE);
219 if (saved_page < 0)
220 return saved_page;
221 page_changed = 0;
222 current_page = saved_page;
223
224 ret = 0;
225 len /= sizeof(*paddr);
226 for (i = 0; i < len - 3; i += 4) {
227 u16 reg_page = be32_to_cpup(paddr + i);
228 u16 reg = be32_to_cpup(paddr + i + 1);
229 u16 mask = be32_to_cpup(paddr + i + 2);
230 u16 val_bits = be32_to_cpup(paddr + i + 3);
231 int val;
232
233 if (reg_page != current_page) {
234 current_page = reg_page;
235 page_changed = 1;
236 ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page);
237 if (ret < 0)
238 goto err;
239 }
240
241 val = 0;
242 if (mask) {
243 val = phy_read(phydev, reg);
244 if (val < 0) {
245 ret = val;
246 goto err;
247 }
248 val &= mask;
249 }
250 val |= val_bits;
251
252 ret = phy_write(phydev, reg, val);
253 if (ret < 0)
254 goto err;
255
256 }
257err:
258 if (page_changed) {
259 i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page);
260 if (ret == 0)
261 ret = i;
262 }
263 return ret;
264}
265#else
266static int marvell_of_reg_init(struct phy_device *phydev)
267{
268 return 0;
269}
270#endif /* CONFIG_OF_MDIO */
271
190static int m88e1121_config_aneg(struct phy_device *phydev) 272static int m88e1121_config_aneg(struct phy_device *phydev)
191{ 273{
192 int err, oldpage, mscr; 274 int err, oldpage, mscr;
@@ -369,6 +451,9 @@ static int m88e1111_config_init(struct phy_device *phydev)
369 return err; 451 return err;
370 } 452 }
371 453
454 err = marvell_of_reg_init(phydev);
455 if (err < 0)
456 return err;
372 457
373 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 458 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
374 if (err < 0) 459 if (err < 0)
@@ -421,6 +506,10 @@ static int m88e1118_config_init(struct phy_device *phydev)
421 if (err < 0) 506 if (err < 0)
422 return err; 507 return err;
423 508
509 err = marvell_of_reg_init(phydev);
510 if (err < 0)
511 return err;
512
424 /* Reset address */ 513 /* Reset address */
425 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0); 514 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0);
426 if (err < 0) 515 if (err < 0)
@@ -447,6 +536,10 @@ static int m88e1149_config_init(struct phy_device *phydev)
447 if (err < 0) 536 if (err < 0)
448 return err; 537 return err;
449 538
539 err = marvell_of_reg_init(phydev);
540 if (err < 0)
541 return err;
542
450 /* Reset address */ 543 /* Reset address */
451 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0); 544 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0);
452 if (err < 0) 545 if (err < 0)
@@ -518,6 +611,10 @@ static int m88e1145_config_init(struct phy_device *phydev)
518 } 611 }
519 } 612 }
520 613
614 err = marvell_of_reg_init(phydev);
615 if (err < 0)
616 return err;
617
521 return 0; 618 return 0;
522} 619}
523 620