13a7ea5d3a5d19afa7c676c62804daefcd7e631e
[openwrt/svn-archive/archive.git] / target / linux / brcm47xx / patches-3.10 / 770-bgmac-phylib.patch
1 --- a/drivers/net/ethernet/broadcom/Kconfig
2 +++ b/drivers/net/ethernet/broadcom/Kconfig
3 @@ -133,6 +133,7 @@ config BNX2X_SRIOV
4 config BGMAC
5 tristate "BCMA bus GBit core support"
6 depends on BCMA_HOST_SOC && HAS_DMA
7 + select PHYLIB
8 ---help---
9 This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus.
10 They can be found on BCM47xx SoCs and provide gigabit ethernet.
11 --- a/drivers/net/ethernet/broadcom/bgmac.c
12 +++ b/drivers/net/ethernet/broadcom/bgmac.c
13 @@ -1229,27 +1229,14 @@ static int bgmac_set_mac_address(struct
14 static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
15 {
16 struct bgmac *bgmac = netdev_priv(net_dev);
17 - struct mii_ioctl_data *data = if_mii(ifr);
18
19 - switch (cmd) {
20 - case SIOCGMIIPHY:
21 - data->phy_id = bgmac->phyaddr;
22 - /* fallthru */
23 - case SIOCGMIIREG:
24 - if (!netif_running(net_dev))
25 - return -EAGAIN;
26 - data->val_out = bgmac_phy_read(bgmac, data->phy_id,
27 - data->reg_num & 0x1f);
28 - return 0;
29 - case SIOCSMIIREG:
30 - if (!netif_running(net_dev))
31 - return -EAGAIN;
32 - bgmac_phy_write(bgmac, data->phy_id, data->reg_num & 0x1f,
33 - data->val_in);
34 - return 0;
35 - default:
36 - return -EOPNOTSUPP;
37 - }
38 + if (!netif_running(net_dev))
39 + return -EINVAL;
40 +
41 + if (!bgmac->phydev)
42 + return -EINVAL;
43 +
44 + return phy_mii_ioctl(bgmac->phydev, ifr, cmd);
45 }
46
47 static const struct net_device_ops bgmac_netdev_ops = {
48 @@ -1271,61 +1258,16 @@ static int bgmac_get_settings(struct net
49 {
50 struct bgmac *bgmac = netdev_priv(net_dev);
51
52 - cmd->supported = SUPPORTED_10baseT_Half |
53 - SUPPORTED_10baseT_Full |
54 - SUPPORTED_100baseT_Half |
55 - SUPPORTED_100baseT_Full |
56 - SUPPORTED_1000baseT_Half |
57 - SUPPORTED_1000baseT_Full |
58 - SUPPORTED_Autoneg;
59 -
60 - if (bgmac->autoneg) {
61 - WARN_ON(cmd->advertising);
62 - if (bgmac->full_duplex) {
63 - if (bgmac->speed & BGMAC_SPEED_10)
64 - cmd->advertising |= ADVERTISED_10baseT_Full;
65 - if (bgmac->speed & BGMAC_SPEED_100)
66 - cmd->advertising |= ADVERTISED_100baseT_Full;
67 - if (bgmac->speed & BGMAC_SPEED_1000)
68 - cmd->advertising |= ADVERTISED_1000baseT_Full;
69 - } else {
70 - if (bgmac->speed & BGMAC_SPEED_10)
71 - cmd->advertising |= ADVERTISED_10baseT_Half;
72 - if (bgmac->speed & BGMAC_SPEED_100)
73 - cmd->advertising |= ADVERTISED_100baseT_Half;
74 - if (bgmac->speed & BGMAC_SPEED_1000)
75 - cmd->advertising |= ADVERTISED_1000baseT_Half;
76 - }
77 - } else {
78 - switch (bgmac->speed) {
79 - case BGMAC_SPEED_10:
80 - ethtool_cmd_speed_set(cmd, SPEED_10);
81 - break;
82 - case BGMAC_SPEED_100:
83 - ethtool_cmd_speed_set(cmd, SPEED_100);
84 - break;
85 - case BGMAC_SPEED_1000:
86 - ethtool_cmd_speed_set(cmd, SPEED_1000);
87 - break;
88 - }
89 - }
90 -
91 - cmd->duplex = bgmac->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
92 -
93 - cmd->autoneg = bgmac->autoneg;
94 -
95 - return 0;
96 + return phy_ethtool_gset(bgmac->phydev, cmd);
97 }
98
99 -#if 0
100 static int bgmac_set_settings(struct net_device *net_dev,
101 struct ethtool_cmd *cmd)
102 {
103 struct bgmac *bgmac = netdev_priv(net_dev);
104
105 - return -1;
106 + return phy_ethtool_sset(bgmac->phydev, cmd);
107 }
108 -#endif
109
110 static void bgmac_get_drvinfo(struct net_device *net_dev,
111 struct ethtool_drvinfo *info)
112 @@ -1336,6 +1278,7 @@ static void bgmac_get_drvinfo(struct net
113
114 static const struct ethtool_ops bgmac_ethtool_ops = {
115 .get_settings = bgmac_get_settings,
116 + .set_settings = bgmac_set_settings,
117 .get_drvinfo = bgmac_get_drvinfo,
118 };
119
120 @@ -1354,10 +1297,36 @@ static int bgmac_mii_write(struct mii_bu
121 return bgmac_phy_write(bus->priv, mii_id, regnum, value);
122 }
123
124 +static void bgmac_adjust_link(struct net_device *dev)
125 +{
126 + struct bgmac *bgmac = netdev_priv(dev);
127 + struct phy_device *phydev = bgmac->phydev;
128 + bool status_changed = 0;
129 +
130 + BUG_ON(!phydev);
131 +
132 + if (bgmac->old_link != phydev->link) {
133 + status_changed = 1;
134 + bgmac->old_link = phydev->link;
135 + }
136 +
137 + /* reflect duplex change */
138 + if (phydev->link && (bgmac->old_duplex != phydev->duplex)) {
139 + status_changed = 1;
140 + bgmac->old_duplex = phydev->duplex;
141 + }
142 +
143 + if (status_changed)
144 + phy_print_status(phydev);
145 +}
146 +
147 static int bgmac_mii_register(struct bgmac *bgmac)
148 {
149 struct mii_bus *mii_bus;
150 int i, err = 0;
151 + struct phy_device *phydev = NULL;
152 + char phy_id[MII_BUS_ID_SIZE + 3];
153 + struct net_device *net_dev = bgmac->net_dev;
154
155 mii_bus = mdiobus_alloc();
156 if (!mii_bus)
157 @@ -1388,7 +1357,28 @@ static int bgmac_mii_register(struct bgm
158
159 bgmac->mii_bus = mii_bus;
160
161 - return err;
162 + /* connect to PHY */
163 + snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
164 + mii_bus->id, bgmac->phyaddr);
165 +
166 + phydev = phy_connect(net_dev, phy_id, &bgmac_adjust_link,
167 + PHY_INTERFACE_MODE_MII);
168 +
169 + if (IS_ERR(phydev)) {
170 + netdev_err(net_dev, "could not attach PHY: %s\n", phy_id);
171 + bgmac->phyaddr = BGMAC_PHY_NOREGS;
172 + return PTR_ERR(phydev);
173 + }
174 +
175 + bgmac->phydev = phydev;
176 + bgmac->old_link = 0;
177 + bgmac->old_duplex = -1;
178 + bgmac->phyaddr = phydev->addr;
179 +
180 + netdev_info(net_dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
181 + phydev->drv->name, dev_name(&phydev->dev));
182 +
183 + return 0;
184
185 err_free_irq:
186 kfree(mii_bus->irq);
187 --- a/drivers/net/ethernet/broadcom/bgmac.h
188 +++ b/drivers/net/ethernet/broadcom/bgmac.h
189 @@ -401,7 +401,10 @@ struct bgmac {
190 struct bcma_device *cmn; /* Reference to CMN core for BCM4706 */
191 struct net_device *net_dev;
192 struct napi_struct napi;
193 + struct phy_device *phydev;
194 struct mii_bus *mii_bus;
195 + int old_link;
196 + int old_duplex;
197
198 /* DMA */
199 struct bgmac_dma_ring tx_ring[BGMAC_MAX_TX_RINGS];