aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMaxime Bizon <mbizon@freebox.fr>2009-06-30 21:29:36 -0400
committerDavid S. Miller <davem@davemloft.net>2009-07-07 22:23:51 -0400
commit09bb9aa0ed22bea814b0f137390f911af33ddd1b (patch)
tree121981bf01b28cf0b5354b07fde82153883a530b /drivers
parent460deefae62db4472e8bd16b21c7d70f3c7fd785 (diff)
MIPS: BCM63XX: Add integrated ethernet PHY support for phylib.
Signed-off-by: Maxime Bizon <mbizon@freebox.fr> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> drivers/net/phy/Kconfig | 6 ++ drivers/net/phy/Makefile | 1 drivers/net/phy/bcm63xx.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 drivers/net/phy/bcm63xx.c Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/Kconfig6
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/bcm63xx.c132
3 files changed, 139 insertions, 0 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index de9cf5136fdc..d5d8e1c5bc91 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -56,6 +56,12 @@ config BROADCOM_PHY
56 Currently supports the BCM5411, BCM5421, BCM5461, BCM5464, BCM5481 56 Currently supports the BCM5411, BCM5421, BCM5461, BCM5464, BCM5481
57 and BCM5482 PHYs. 57 and BCM5482 PHYs.
58 58
59config BCM63XX_PHY
60 tristate "Drivers for Broadcom 63xx SOCs internal PHY"
61 depends on BCM63XX
62 ---help---
63 Currently supports the 6348 and 6358 PHYs.
64
59config ICPLUS_PHY 65config ICPLUS_PHY
60 tristate "Drivers for ICPlus PHYs" 66 tristate "Drivers for ICPlus PHYs"
61 ---help--- 67 ---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 3a1bfefefbc3..edfaac48cbd5 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
11obj-$(CONFIG_SMSC_PHY) += smsc.o 11obj-$(CONFIG_SMSC_PHY) += smsc.o
12obj-$(CONFIG_VITESSE_PHY) += vitesse.o 12obj-$(CONFIG_VITESSE_PHY) += vitesse.o
13obj-$(CONFIG_BROADCOM_PHY) += broadcom.o 13obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
14obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o
14obj-$(CONFIG_ICPLUS_PHY) += icplus.o 15obj-$(CONFIG_ICPLUS_PHY) += icplus.o
15obj-$(CONFIG_REALTEK_PHY) += realtek.o 16obj-$(CONFIG_REALTEK_PHY) += realtek.o
16obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o 17obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
new file mode 100644
index 000000000000..4fed95e8350e
--- /dev/null
+++ b/drivers/net/phy/bcm63xx.c
@@ -0,0 +1,132 @@
1/*
2 * Driver for Broadcom 63xx SOCs integrated PHYs
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <linux/module.h>
10#include <linux/phy.h>
11
12#define MII_BCM63XX_IR 0x1a /* interrupt register */
13#define MII_BCM63XX_IR_EN 0x4000 /* global interrupt enable */
14#define MII_BCM63XX_IR_DUPLEX 0x0800 /* duplex changed */
15#define MII_BCM63XX_IR_SPEED 0x0400 /* speed changed */
16#define MII_BCM63XX_IR_LINK 0x0200 /* link changed */
17#define MII_BCM63XX_IR_GMASK 0x0100 /* global interrupt mask */
18
19MODULE_DESCRIPTION("Broadcom 63xx internal PHY driver");
20MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
21MODULE_LICENSE("GPL");
22
23static int bcm63xx_config_init(struct phy_device *phydev)
24{
25 int reg, err;
26
27 reg = phy_read(phydev, MII_BCM63XX_IR);
28 if (reg < 0)
29 return reg;
30
31 /* Mask interrupts globally. */
32 reg |= MII_BCM63XX_IR_GMASK;
33 err = phy_write(phydev, MII_BCM63XX_IR, reg);
34 if (err < 0)
35 return err;
36
37 /* Unmask events we are interested in */
38 reg = ~(MII_BCM63XX_IR_DUPLEX |
39 MII_BCM63XX_IR_SPEED |
40 MII_BCM63XX_IR_LINK) |
41 MII_BCM63XX_IR_EN;
42 err = phy_write(phydev, MII_BCM63XX_IR, reg);
43 if (err < 0)
44 return err;
45 return 0;
46}
47
48static int bcm63xx_ack_interrupt(struct phy_device *phydev)
49{
50 int reg;
51
52 /* Clear pending interrupts. */
53 reg = phy_read(phydev, MII_BCM63XX_IR);
54 if (reg < 0)
55 return reg;
56
57 return 0;
58}
59
60static int bcm63xx_config_intr(struct phy_device *phydev)
61{
62 int reg, err;
63
64 reg = phy_read(phydev, MII_BCM63XX_IR);
65 if (reg < 0)
66 return reg;
67
68 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
69 reg &= ~MII_BCM63XX_IR_GMASK;
70 else
71 reg |= MII_BCM63XX_IR_GMASK;
72
73 err = phy_write(phydev, MII_BCM63XX_IR, reg);
74 return err;
75}
76
77static struct phy_driver bcm63xx_1_driver = {
78 .phy_id = 0x00406000,
79 .phy_id_mask = 0xfffffc00,
80 .name = "Broadcom BCM63XX (1)",
81 /* ASYM_PAUSE bit is marked RO in datasheet, so don't cheat */
82 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
83 .flags = PHY_HAS_INTERRUPT,
84 .config_init = bcm63xx_config_init,
85 .config_aneg = genphy_config_aneg,
86 .read_status = genphy_read_status,
87 .ack_interrupt = bcm63xx_ack_interrupt,
88 .config_intr = bcm63xx_config_intr,
89 .driver = { .owner = THIS_MODULE },
90};
91
92/* same phy as above, with just a different OUI */
93static struct phy_driver bcm63xx_2_driver = {
94 .phy_id = 0x002bdc00,
95 .phy_id_mask = 0xfffffc00,
96 .name = "Broadcom BCM63XX (2)",
97 .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
98 .flags = PHY_HAS_INTERRUPT,
99 .config_init = bcm63xx_config_init,
100 .config_aneg = genphy_config_aneg,
101 .read_status = genphy_read_status,
102 .ack_interrupt = bcm63xx_ack_interrupt,
103 .config_intr = bcm63xx_config_intr,
104 .driver = { .owner = THIS_MODULE },
105};
106
107static int __init bcm63xx_phy_init(void)
108{
109 int ret;
110
111 ret = phy_driver_register(&bcm63xx_1_driver);
112 if (ret)
113 goto out_63xx_1;
114 ret = phy_driver_register(&bcm63xx_2_driver);
115 if (ret)
116 goto out_63xx_2;
117 return ret;
118
119out_63xx_2:
120 phy_driver_unregister(&bcm63xx_1_driver);
121out_63xx_1:
122 return ret;
123}
124
125static void __exit bcm63xx_phy_exit(void)
126{
127 phy_driver_unregister(&bcm63xx_1_driver);
128 phy_driver_unregister(&bcm63xx_2_driver);
129}
130
131module_init(bcm63xx_phy_init);
132module_exit(bcm63xx_phy_exit);