shat from Georg Lukas
[openwrt/openwrt.git] / openwrt / package / linux / kernel-patches / 309-b44-bcm47xx-support.patch
1 This patch adds BCM47xx support for the B44 driver. It has been backported
2 from Florian Schirmer's 2.6 port.
3
4 Imre Kaloz <kaloz@dune.hu>
5
6 diff -Nur linux-2.4.29/drivers/net/b44.c linux-2.4.29-b44/drivers/net/b44.c
7 --- linux-2.4.29/drivers/net/b44.c 2004-08-08 01:26:05.000000000 +0200
8 +++ linux-2.4.29-b44/drivers/net/b44.c 2005-04-09 10:17:33.000000000 +0200
9 @@ -1,7 +1,8 @@
10 /* b44.c: Broadcom 4400 device driver.
11 *
12 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
13 - * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
14 + * Copyright (C) 2004 Pekka Pietikainen (pp@ee.oulu.fi)
15 + * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
16 *
17 * Distribute under GPL.
18 */
19 @@ -25,6 +26,16 @@
20
21 #include "b44.h"
22
23 +#include <typedefs.h>
24 +#include <bcmdevs.h>
25 +#include <bcmutils.h>
26 +#include <osl.h>
27 +#include <bcmutils.h>
28 +#include <bcmnvram.h>
29 +#include <sbconfig.h>
30 +#include <sbchipc.h>
31 +#include <sflash.h>
32 +
33 #define DRV_MODULE_NAME "b44"
34 #define PFX DRV_MODULE_NAME ": "
35 #define DRV_MODULE_VERSION "0.93"
36 @@ -75,7 +86,7 @@
37 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
38
39 MODULE_AUTHOR("David S. Miller (davem@redhat.com)");
40 -MODULE_DESCRIPTION("Broadcom 4400 10/100 PCI ethernet driver");
41 +MODULE_DESCRIPTION("Broadcom 4400/47xx 10/100 PCI ethernet driver");
42 MODULE_LICENSE("GPL");
43 MODULE_PARM(b44_debug, "i");
44 MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
45 @@ -89,6 +100,8 @@
46 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
47 { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1,
48 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
49 + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4713,
50 + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
51 { } /* terminate list with empty entry */
52 };
53
54 @@ -236,6 +249,8 @@
55 udelay(1);
56 }
57
58 +static int b44_4713_instance;
59 +
60 static int ssb_core_unit(struct b44 *bp)
61 {
62 #if 0
63 @@ -258,6 +273,9 @@
64 break;
65 };
66 #endif
67 + if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
68 + return b44_4713_instance++;
69 + else
70 return 0;
71 }
72
73 @@ -267,6 +285,28 @@
74 == SBTMSLOW_CLOCK);
75 }
76
77 +static void __b44_cam_read(struct b44 *bp, unsigned char *data, int index)
78 +{
79 + u32 val;
80 +
81 + bw32(B44_CAM_CTRL, (CAM_CTRL_READ |
82 + (index << CAM_CTRL_INDEX_SHIFT)));
83 +
84 + b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
85 +
86 + val = br32(B44_CAM_DATA_LO);
87 +
88 + data[2] = (val >> 24) & 0xFF;
89 + data[3] = (val >> 16) & 0xFF;
90 + data[4] = (val >> 8) & 0xFF;
91 + data[5] = (val >> 0) & 0xFF;
92 +
93 + val = br32(B44_CAM_DATA_HI);
94 +
95 + data[0] = (val >> 8) & 0xFF;
96 + data[1] = (val >> 0) & 0xFF;
97 +}
98 +
99 static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
100 {
101 u32 val;
102 @@ -307,6 +347,9 @@
103 {
104 int err;
105
106 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
107 + return 0;
108 +
109 bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
110 bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
111 (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
112 @@ -321,6 +364,9 @@
113
114 static int b44_writephy(struct b44 *bp, int reg, u32 val)
115 {
116 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
117 + return 0;
118 +
119 bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
120 bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
121 (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
122 @@ -336,6 +382,9 @@
123 u32 val;
124 int err;
125
126 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
127 + return 0;
128 +
129 err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
130 if (err)
131 return err;
132 @@ -406,6 +455,9 @@
133 u32 val;
134 int err;
135
136 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
137 + return 0;
138 +
139 if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
140 goto out;
141 if ((err = b44_writephy(bp, B44_MII_ALEDCTRL,
142 @@ -498,6 +550,19 @@
143 {
144 u32 bmsr, aux;
145
146 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
147 + bp->flags |= B44_FLAG_100_BASE_T;
148 + bp->flags |= B44_FLAG_FULL_DUPLEX;
149 + if (!netif_carrier_ok(bp->dev)) {
150 + u32 val = br32(B44_TX_CTRL);
151 + val |= TX_CTRL_DUPLEX;
152 + bw32(B44_TX_CTRL, val);
153 + netif_carrier_on(bp->dev);
154 + b44_link_report(bp);
155 + }
156 + return;
157 + }
158 +
159 if (!b44_readphy(bp, MII_BMSR, &bmsr) &&
160 !b44_readphy(bp, B44_MII_AUXCTRL, &aux) &&
161 (bmsr != 0xffff)) {
162 @@ -1092,6 +1157,8 @@
163 /* bp->lock is held. */
164 static void b44_chip_reset(struct b44 *bp)
165 {
166 + unsigned int sb_clock;
167 +
168 if (ssb_is_core_up(bp)) {
169 bw32(B44_RCV_LAZY, 0);
170 bw32(B44_ENET_CTRL, ENET_CTRL_DISABLE);
171 @@ -1105,9 +1172,10 @@
172 bw32(B44_DMARX_CTRL, 0);
173 bp->rx_prod = bp->rx_cons = 0;
174 } else {
175 - ssb_pci_setup(bp, (bp->core_unit == 0 ?
176 - SBINTVEC_ENET0 :
177 - SBINTVEC_ENET1));
178 + if (bp->pdev->device != PCI_DEVICE_ID_BCM4713)
179 + ssb_pci_setup(bp, (bp->core_unit == 0 ?
180 + SBINTVEC_ENET0 :
181 + SBINTVEC_ENET1));
182 }
183
184 ssb_core_reset(bp);
185 @@ -1115,6 +1183,11 @@
186 b44_clear_stats(bp);
187
188 /* Make PHY accessible. */
189 + if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
190 + sb_clock = 100000000; /* 100 MHz */
191 + else
192 + sb_clock = 62500000; /* 62.5 MHz */
193 +
194 bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
195 (0x0d & MDIO_CTRL_MAXF_MASK)));
196 br32(B44_MDIO_CTRL);
197 @@ -1669,20 +1742,42 @@
198 {
199 u8 eeprom[128];
200 int err;
201 + unsigned long flags;
202
203 - err = b44_read_eeprom(bp, &eeprom[0]);
204 - if (err)
205 - goto out;
206 -
207 - bp->dev->dev_addr[0] = eeprom[79];
208 - bp->dev->dev_addr[1] = eeprom[78];
209 - bp->dev->dev_addr[2] = eeprom[81];
210 - bp->dev->dev_addr[3] = eeprom[80];
211 - bp->dev->dev_addr[4] = eeprom[83];
212 - bp->dev->dev_addr[5] = eeprom[82];
213 -
214 - bp->phy_addr = eeprom[90] & 0x1f;
215 - bp->mdc_port = (eeprom[90] >> 14) & 0x1;
216 + if (bp->pdev->device == PCI_DEVICE_ID_BCM4713) {
217 + /*
218 + * BCM47xx boards don't have a EEPROM. The MAC is stored in
219 + * a NVRAM area somewhere in the flash memory. As we don't
220 + * know the location and/or the format of the NVRAM area
221 + * here, we simply rely on the bootloader to write the
222 + * MAC into the CAM.
223 + */
224 + spin_lock_irqsave(&bp->lock, flags);
225 + __b44_cam_read(bp, bp->dev->dev_addr, 0);
226 + spin_unlock_irqrestore(&bp->lock, flags);
227 +
228 + /*
229 + * BCM47xx boards don't have a PHY. Usually there is a switch
230 + * chip with multiple PHYs connected to the PHY port.
231 + */
232 + bp->phy_addr = B44_PHY_ADDR_NO_PHY;
233 + bp->dma_offset = 0;
234 + } else {
235 + err = b44_read_eeprom(bp, &eeprom[0]);
236 + if (err)
237 + return err;
238 +
239 + bp->dev->dev_addr[0] = eeprom[79];
240 + bp->dev->dev_addr[1] = eeprom[78];
241 + bp->dev->dev_addr[2] = eeprom[81];
242 + bp->dev->dev_addr[3] = eeprom[80];
243 + bp->dev->dev_addr[4] = eeprom[83];
244 + bp->dev->dev_addr[5] = eeprom[82];
245 +
246 + bp->phy_addr = eeprom[90] & 0x1f;
247 + bp->dma_offset = SB_PCI_DMA;
248 + bp->mdc_port = (eeprom[90] >> 14) & 0x1;
249 + }
250
251 /* With this, plus the rx_header prepended to the data by the
252 * hardware, we'll land the ethernet header on a 2-byte boundary.
253 @@ -1692,13 +1787,12 @@
254 bp->imask = IMASK_DEF;
255
256 bp->core_unit = ssb_core_unit(bp);
257 - bp->dma_offset = ssb_get_addr(bp, SBID_PCI_DMA, 0);
258
259 /* XXX - really required?
260 bp->flags |= B44_FLAG_BUGGY_TXPTR;
261 */
262 -out:
263 - return err;
264 +
265 + return 0;
266 }
267
268 static int __devinit b44_init_one(struct pci_dev *pdev,
269 @@ -1819,7 +1913,8 @@
270
271 pci_save_state(bp->pdev, bp->pci_cfg_state);
272
273 - printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
274 + printk(KERN_INFO "%s: Broadcom %s 10/100BaseT Ethernet ", dev->name,
275 + (pdev->device == PCI_DEVICE_ID_BCM4713) ? "47xx" : "4400");
276 for (i = 0; i < 6; i++)
277 printk("%2.2x%c", dev->dev_addr[i],
278 i == 5 ? '\n' : ':');
279 diff -Nur linux-2.4.29/drivers/net/b44.h linux-2.4.29-b44/drivers/net/b44.h
280 --- linux-2.4.29/drivers/net/b44.h 2003-08-25 13:44:42.000000000 +0200
281 +++ linux-2.4.29-b44/drivers/net/b44.h 2005-04-09 10:13:55.000000000 +0200
282 @@ -461,6 +461,8 @@
283 };
284
285 #define B44_MCAST_TABLE_SIZE 32
286 +#define B44_PHY_ADDR_NO_PHY 30
287 +#define B44_MDC_RATIO 5000000
288
289 /* SW copy of device statistics, kept up to date by periodic timer
290 * which probes HW values. Must have same relative layout as HW
291 diff -Nur linux-2.4.29/include/linux/pci_ids.h linux-2.4.29-b44/include/linux/pci_ids.h
292 --- linux-2.4.29/include/linux/pci_ids.h 2005-01-19 15:10:12.000000000 +0100
293 +++ linux-2.4.29-b44/include/linux/pci_ids.h 2005-04-09 10:13:55.000000000 +0200
294 @@ -1735,6 +1735,7 @@
295 #define PCI_DEVICE_ID_TIGON3_5901_2 0x170e
296 #define PCI_DEVICE_ID_BCM4401 0x4401
297 #define PCI_DEVICE_ID_BCM4401B0 0x4402
298 +#define PCI_DEVICE_ID_BCM4713 0x4713
299
300 #define PCI_VENDOR_ID_ENE 0x1524
301 #define PCI_DEVICE_ID_ENE_1211 0x1211