1 This patch adds BCM47xx support for the B44 driver. It has been backported
2 from Florian Schirmer's 2.6 port.
4 Imre Kaloz <kaloz@dune.hu>
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
10 /* b44.c: Broadcom 4400 device driver.
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)
17 * Distribute under GPL.
23 +#include <typedefs.h>
25 +#include <bcmutils.h>
27 +#include <bcmutils.h>
28 +#include <bcmnvram.h>
29 +#include <sbconfig.h>
33 #define DRV_MODULE_NAME "b44"
34 #define PFX DRV_MODULE_NAME ": "
35 #define DRV_MODULE_VERSION "0.93"
37 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
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");
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 */
58 +static int b44_4713_instance;
60 static int ssb_core_unit(struct b44 *bp)
67 + if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
68 + return b44_4713_instance++;
77 +static void __b44_cam_read(struct b44 *bp, unsigned char *data, int index)
81 + bw32(B44_CAM_CTRL, (CAM_CTRL_READ |
82 + (index << CAM_CTRL_INDEX_SHIFT)));
84 + b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
86 + val = br32(B44_CAM_DATA_LO);
88 + data[2] = (val >> 24) & 0xFF;
89 + data[3] = (val >> 16) & 0xFF;
90 + data[4] = (val >> 8) & 0xFF;
91 + data[5] = (val >> 0) & 0xFF;
93 + val = br32(B44_CAM_DATA_HI);
95 + data[0] = (val >> 8) & 0xFF;
96 + data[1] = (val >> 0) & 0xFF;
99 static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
106 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
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) |
114 static int b44_writephy(struct b44 *bp, int reg, u32 val)
116 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
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) |
126 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
129 err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
136 + if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
139 if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
141 if ((err = b44_writephy(bp, B44_MII_ALEDCTRL,
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);
159 if (!b44_readphy(bp, MII_BMSR, &bmsr) &&
160 !b44_readphy(bp, B44_MII_AUXCTRL, &aux) &&
162 @@ -1092,6 +1157,8 @@
163 /* bp->lock is held. */
164 static void b44_chip_reset(struct b44 *bp)
166 + unsigned int sb_clock;
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;
175 - ssb_pci_setup(bp, (bp->core_unit == 0 ?
178 + if (bp->pdev->device != PCI_DEVICE_ID_BCM4713)
179 + ssb_pci_setup(bp, (bp->core_unit == 0 ?
185 @@ -1115,6 +1183,11 @@
188 /* Make PHY accessible. */
189 + if (bp->pdev->device == PCI_DEVICE_ID_BCM4713)
190 + sb_clock = 100000000; /* 100 MHz */
192 + sb_clock = 62500000; /* 62.5 MHz */
194 bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
195 (0x0d & MDIO_CTRL_MAXF_MASK)));
197 @@ -1669,20 +1742,42 @@
201 + unsigned long flags;
203 - err = b44_read_eeprom(bp, &eeprom[0]);
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];
214 - bp->phy_addr = eeprom[90] & 0x1f;
215 - bp->mdc_port = (eeprom[90] >> 14) & 0x1;
216 + if (bp->pdev->device == PCI_DEVICE_ID_BCM4713) {
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.
224 + spin_lock_irqsave(&bp->lock, flags);
225 + __b44_cam_read(bp, bp->dev->dev_addr, 0);
226 + spin_unlock_irqrestore(&bp->lock, flags);
229 + * BCM47xx boards don't have a PHY. Usually there is a switch
230 + * chip with multiple PHYs connected to the PHY port.
232 + bp->phy_addr = B44_PHY_ADDR_NO_PHY;
233 + bp->dma_offset = 0;
235 + err = b44_read_eeprom(bp, &eeprom[0]);
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];
246 + bp->phy_addr = eeprom[90] & 0x1f;
247 + bp->dma_offset = SB_PCI_DMA;
248 + bp->mdc_port = (eeprom[90] >> 14) & 0x1;
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;
256 bp->core_unit = ssb_core_unit(bp);
257 - bp->dma_offset = ssb_get_addr(bp, SBID_PCI_DMA, 0);
259 /* XXX - really required?
260 bp->flags |= B44_FLAG_BUGGY_TXPTR;
268 static int __devinit b44_init_one(struct pci_dev *pdev,
269 @@ -1819,7 +1913,8 @@
271 pci_save_state(bp->pdev, bp->pci_cfg_state);
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
285 #define B44_MCAST_TABLE_SIZE 32
286 +#define B44_PHY_ADDR_NO_PHY 30
287 +#define B44_MDC_RATIO 5000000
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
300 #define PCI_VENDOR_ID_ENE 0x1524
301 #define PCI_DEVICE_ID_ENE_1211 0x1211