Add libpcap dependency
[openwrt.git] / 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