aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/marvell.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/phy/marvell.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/phy/marvell.c')
-rw-r--r--drivers/net/phy/marvell.c215
1 files changed, 180 insertions, 35 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 0101f2bdf400..e8b9c53c304b 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -30,11 +30,14 @@
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>
36#include <asm/uaccess.h> 37#include <asm/uaccess.h>
37 38
39#define MII_MARVELL_PHY_PAGE 22
40
38#define MII_M1011_IEVENT 0x13 41#define MII_M1011_IEVENT 0x13
39#define MII_M1011_IEVENT_CLEAR 0x0000 42#define MII_M1011_IEVENT_CLEAR 0x0000
40 43
@@ -74,13 +77,12 @@
74#define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4) 77#define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4)
75#define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4)) 78#define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4))
76 79
77#define MII_88EC048_PHY_MSCR1_REG 16 80#define MII_88E1318S_PHY_MSCR1_REG 16
78#define MII_88EC048_PHY_MSCR1_PAD_ODD BIT(6) 81#define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
79 82
80#define MII_88E1121_PHY_LED_CTRL 16 83#define MII_88E1121_PHY_LED_CTRL 16
81#define MII_88E1121_PHY_LED_PAGE 3 84#define MII_88E1121_PHY_LED_PAGE 3
82#define MII_88E1121_PHY_LED_DEF 0x0030 85#define MII_88E1121_PHY_LED_DEF 0x0030
83#define MII_88E1121_PHY_PAGE 22
84 86
85#define MII_M1011_PHY_STATUS 0x11 87#define MII_M1011_PHY_STATUS 0x11
86#define MII_M1011_PHY_STATUS_1000 0x8000 88#define MII_M1011_PHY_STATUS_1000 0x8000
@@ -186,32 +188,120 @@ static int marvell_config_aneg(struct phy_device *phydev)
186 return 0; 188 return 0;
187} 189}
188 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
189static int m88e1121_config_aneg(struct phy_device *phydev) 272static int m88e1121_config_aneg(struct phy_device *phydev)
190{ 273{
191 int err, oldpage, mscr; 274 int err, oldpage, mscr;
192 275
193 oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); 276 oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
194 277
195 err = phy_write(phydev, MII_88E1121_PHY_PAGE, 278 err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
196 MII_88E1121_PHY_MSCR_PAGE); 279 MII_88E1121_PHY_MSCR_PAGE);
197 if (err < 0) 280 if (err < 0)
198 return err; 281 return err;
199 mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
200 MII_88E1121_PHY_MSCR_DELAY_MASK;
201 282
202 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 283 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
203 mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY | 284 (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
204 MII_88E1121_PHY_MSCR_TX_DELAY); 285 (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
205 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 286 (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
206 mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
207 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
208 mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
209 287
210 err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); 288 mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
211 if (err < 0) 289 MII_88E1121_PHY_MSCR_DELAY_MASK;
212 return err; 290
291 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
292 mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
293 MII_88E1121_PHY_MSCR_TX_DELAY);
294 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
295 mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
296 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
297 mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
298
299 err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
300 if (err < 0)
301 return err;
302 }
213 303
214 phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); 304 phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
215 305
216 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 306 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
217 if (err < 0) 307 if (err < 0)
@@ -222,36 +312,36 @@ static int m88e1121_config_aneg(struct phy_device *phydev)
222 if (err < 0) 312 if (err < 0)
223 return err; 313 return err;
224 314
225 oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); 315 oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
226 316
227 phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); 317 phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1121_PHY_LED_PAGE);
228 phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF); 318 phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF);
229 phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); 319 phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
230 320
231 err = genphy_config_aneg(phydev); 321 err = genphy_config_aneg(phydev);
232 322
233 return err; 323 return err;
234} 324}
235 325
236static int m88ec048_config_aneg(struct phy_device *phydev) 326static int m88e1318_config_aneg(struct phy_device *phydev)
237{ 327{
238 int err, oldpage, mscr; 328 int err, oldpage, mscr;
239 329
240 oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); 330 oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
241 331
242 err = phy_write(phydev, MII_88E1121_PHY_PAGE, 332 err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
243 MII_88E1121_PHY_MSCR_PAGE); 333 MII_88E1121_PHY_MSCR_PAGE);
244 if (err < 0) 334 if (err < 0)
245 return err; 335 return err;
246 336
247 mscr = phy_read(phydev, MII_88EC048_PHY_MSCR1_REG); 337 mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG);
248 mscr |= MII_88EC048_PHY_MSCR1_PAD_ODD; 338 mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD;
249 339
250 err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); 340 err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr);
251 if (err < 0) 341 if (err < 0)
252 return err; 342 return err;
253 343
254 err = phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); 344 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
255 if (err < 0) 345 if (err < 0)
256 return err; 346 return err;
257 347
@@ -361,6 +451,9 @@ static int m88e1111_config_init(struct phy_device *phydev)
361 return err; 451 return err;
362 } 452 }
363 453
454 err = marvell_of_reg_init(phydev);
455 if (err < 0)
456 return err;
364 457
365 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 458 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
366 if (err < 0) 459 if (err < 0)
@@ -391,7 +484,7 @@ static int m88e1118_config_init(struct phy_device *phydev)
391 int err; 484 int err;
392 485
393 /* Change address */ 486 /* Change address */
394 err = phy_write(phydev, 0x16, 0x0002); 487 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002);
395 if (err < 0) 488 if (err < 0)
396 return err; 489 return err;
397 490
@@ -401,7 +494,7 @@ static int m88e1118_config_init(struct phy_device *phydev)
401 return err; 494 return err;
402 495
403 /* Change address */ 496 /* Change address */
404 err = phy_write(phydev, 0x16, 0x0003); 497 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0003);
405 if (err < 0) 498 if (err < 0)
406 return err; 499 return err;
407 500
@@ -413,8 +506,42 @@ static int m88e1118_config_init(struct phy_device *phydev)
413 if (err < 0) 506 if (err < 0)
414 return err; 507 return err;
415 508
509 err = marvell_of_reg_init(phydev);
510 if (err < 0)
511 return err;
512
513 /* Reset address */
514 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0);
515 if (err < 0)
516 return err;
517
518 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
519 if (err < 0)
520 return err;
521
522 return 0;
523}
524
525static int m88e1149_config_init(struct phy_device *phydev)
526{
527 int err;
528
529 /* Change address */
530 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002);
531 if (err < 0)
532 return err;
533
534 /* Enable 1000 Mbit */
535 err = phy_write(phydev, 0x15, 0x1048);
536 if (err < 0)
537 return err;
538
539 err = marvell_of_reg_init(phydev);
540 if (err < 0)
541 return err;
542
416 /* Reset address */ 543 /* Reset address */
417 err = phy_write(phydev, 0x16, 0x0); 544 err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0);
418 if (err < 0) 545 if (err < 0)
419 return err; 546 return err;
420 547
@@ -484,6 +611,10 @@ static int m88e1145_config_init(struct phy_device *phydev)
484 } 611 }
485 } 612 }
486 613
614 err = marvell_of_reg_init(phydev);
615 if (err < 0)
616 return err;
617
487 return 0; 618 return 0;
488} 619}
489 620
@@ -652,12 +783,12 @@ static struct phy_driver marvell_drivers[] = {
652 .driver = { .owner = THIS_MODULE }, 783 .driver = { .owner = THIS_MODULE },
653 }, 784 },
654 { 785 {
655 .phy_id = MARVELL_PHY_ID_88EC048, 786 .phy_id = MARVELL_PHY_ID_88E1318S,
656 .phy_id_mask = MARVELL_PHY_ID_MASK, 787 .phy_id_mask = MARVELL_PHY_ID_MASK,
657 .name = "Marvell 88EC048", 788 .name = "Marvell 88E1318S",
658 .features = PHY_GBIT_FEATURES, 789 .features = PHY_GBIT_FEATURES,
659 .flags = PHY_HAS_INTERRUPT, 790 .flags = PHY_HAS_INTERRUPT,
660 .config_aneg = &m88ec048_config_aneg, 791 .config_aneg = &m88e1318_config_aneg,
661 .read_status = &marvell_read_status, 792 .read_status = &marvell_read_status,
662 .ack_interrupt = &marvell_ack_interrupt, 793 .ack_interrupt = &marvell_ack_interrupt,
663 .config_intr = &marvell_config_intr, 794 .config_intr = &marvell_config_intr,
@@ -678,6 +809,19 @@ static struct phy_driver marvell_drivers[] = {
678 .driver = { .owner = THIS_MODULE }, 809 .driver = { .owner = THIS_MODULE },
679 }, 810 },
680 { 811 {
812 .phy_id = MARVELL_PHY_ID_88E1149R,
813 .phy_id_mask = MARVELL_PHY_ID_MASK,
814 .name = "Marvell 88E1149R",
815 .features = PHY_GBIT_FEATURES,
816 .flags = PHY_HAS_INTERRUPT,
817 .config_init = &m88e1149_config_init,
818 .config_aneg = &m88e1118_config_aneg,
819 .read_status = &genphy_read_status,
820 .ack_interrupt = &marvell_ack_interrupt,
821 .config_intr = &marvell_config_intr,
822 .driver = { .owner = THIS_MODULE },
823 },
824 {
681 .phy_id = MARVELL_PHY_ID_88E1240, 825 .phy_id = MARVELL_PHY_ID_88E1240,
682 .phy_id_mask = MARVELL_PHY_ID_MASK, 826 .phy_id_mask = MARVELL_PHY_ID_MASK,
683 .name = "Marvell 88E1240", 827 .name = "Marvell 88E1240",
@@ -721,13 +865,14 @@ static void __exit marvell_exit(void)
721module_init(marvell_init); 865module_init(marvell_init);
722module_exit(marvell_exit); 866module_exit(marvell_exit);
723 867
724static struct mdio_device_id marvell_tbl[] = { 868static struct mdio_device_id __maybe_unused marvell_tbl[] = {
725 { 0x01410c60, 0xfffffff0 }, 869 { 0x01410c60, 0xfffffff0 },
726 { 0x01410c90, 0xfffffff0 }, 870 { 0x01410c90, 0xfffffff0 },
727 { 0x01410cc0, 0xfffffff0 }, 871 { 0x01410cc0, 0xfffffff0 },
728 { 0x01410e10, 0xfffffff0 }, 872 { 0x01410e10, 0xfffffff0 },
729 { 0x01410cb0, 0xfffffff0 }, 873 { 0x01410cb0, 0xfffffff0 },
730 { 0x01410cd0, 0xfffffff0 }, 874 { 0x01410cd0, 0xfffffff0 },
875 { 0x01410e50, 0xfffffff0 },
731 { 0x01410e30, 0xfffffff0 }, 876 { 0x01410e30, 0xfffffff0 },
732 { 0x01410e90, 0xfffffff0 }, 877 { 0x01410e90, 0xfffffff0 },
733 { } 878 { }