/*
- * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ * Copyright (C) 2001,2002,2003,2004 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
-#include <linux/config.h>
#include <linux/bitops.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/io.h>
#define SBMAC_ETH0_HWADDR "40:00:00:00:01:00"
#define SBMAC_ETH1_HWADDR "40:00:00:00:01:01"
#define SBMAC_ETH2_HWADDR "40:00:00:00:01:02"
+#define SBMAC_ETH3_HWADDR "40:00:00:00:01:03"
#endif
#define CONFIG_SBMAC_COALESCE
-#define MAX_UNITS 3 /* More are supported, limit only on options */
+#define MAX_UNITS 4 /* More are supported, limit only on options */
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (2*HZ)
The media type is usually passed in 'options[]'.
*/
#ifdef MODULE
-static int options[MAX_UNITS] = {-1, -1, -1};
+static int options[MAX_UNITS] = {-1, -1, -1, -1};
module_param_array(options, int, NULL, S_IRUGO);
MODULE_PARM_DESC(options, "1-" __MODULE_STRING(MAX_UNITS));
-static int full_duplex[MAX_UNITS] = {-1, -1, -1};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1};
module_param_array(full_duplex, int, NULL, S_IRUGO);
MODULE_PARM_DESC(full_duplex, "1-" __MODULE_STRING(MAX_UNITS));
#endif
#endif
#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_defs.h>
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_mac.h>
-#include <asm/sibyte/sb1250_dma.h>
#include <asm/sibyte/sb1250_int.h>
+#else
+#error invalid SiByte MAC configuation
+#endif
#include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/sb1250_mac.h>
+#include <asm/sibyte/sb1250_dma.h>
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#define UNIT_INT(n) (K_BCM1480_INT_MAC_0 + ((n) * 2))
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
+#define UNIT_INT(n) (K_INT_MAC_0 + (n))
+#else
+#error invalid SiByte MAC configuation
+#endif
/**********************************************************************
* Simple types
static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int sbmac_close(struct net_device *dev);
static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);
+static int sbmac_mii_probe(struct net_device *dev);
static void sbmac_mii_sync(struct sbmac_softc *s);
static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt);
#define MII_BMCR 0x00 /* Basic mode control register (rw) */
#define MII_BMSR 0x01 /* Basic mode status register (ro) */
+#define MII_PHYIDR1 0x02
+#define MII_PHYIDR2 0x03
+
#define MII_K1STSR 0x0A /* 1K Status Register (ro) */
#define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */
* and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
* Use a larger RD_THRSH for gigabit
*/
- if (periph_rev >= 2)
- th_value = 64;
- else
+ if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2)
th_value = 28;
+ else
+ th_value = 64;
fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */
((s->sbm_speed == sbmac_speed_1000)
* Turn on the rest of the bits in the enable register
*/
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ __raw_writeq(M_MAC_RXDMA_EN0 |
+ M_MAC_TXDMA_EN0, s->sbm_macenable);
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
__raw_writeq(M_MAC_RXDMA_EN0 |
M_MAC_TXDMA_EN0 |
M_MAC_RX_ENABLE |
M_MAC_TX_ENABLE, s->sbm_macenable);
-
-
-
+#else
+#error invalid SiByte MAC configuation
+#endif
#ifdef CONFIG_SBMAC_COALESCE
/*
reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
__raw_writeq(reg, sc->sbm_rxfilter);
- /* read system identification to determine revision */
- if (periph_rev >= 2) {
- sc->rx_hw_checksum = ENABLE;
- } else {
+ /* BCM1250 pass1 didn't have hardware checksum. Everything
+ later does. */
+ if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) {
sc->rx_hw_checksum = DISABLE;
+ } else {
+ sc->rx_hw_checksum = ENABLE;
}
}
-#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
+#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR)
/**********************************************************************
* SBMAC_PARSE_XDIGIT(str)
*
*/
__raw_readq(sc->sbm_isr);
- if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev))
+ if (request_irq(dev->irq, &sbmac_intr, IRQF_SHARED, dev->name, dev))
return -EBUSY;
+ /*
+ * Probe phy address
+ */
+
+ if(sbmac_mii_probe(dev) == -1) {
+ printk("%s: failed to probe PHY.\n", dev->name);
+ return -EINVAL;
+ }
+
/*
* Configure default speed
*/
return 0;
}
+static int sbmac_mii_probe(struct net_device *dev)
+{
+ int i;
+ struct sbmac_softc *s = netdev_priv(dev);
+ u16 bmsr, id1, id2;
+ u32 vendor, device;
+
+ for (i=1; i<31; i++) {
+ bmsr = sbmac_mii_read(s, i, MII_BMSR);
+ if (bmsr != 0) {
+ s->sbm_phys[0] = i;
+ id1 = sbmac_mii_read(s, i, MII_PHYIDR1);
+ id2 = sbmac_mii_read(s, i, MII_PHYIDR2);
+ vendor = ((u32)id1 << 6) | ((id2 >> 10) & 0x3f);
+ device = (id2 >> 4) & 0x3f;
+
+ printk(KERN_INFO "%s: found phy %d, vendor %06x part %02x\n",
+ dev->name, i, vendor, device);
+ return i;
+ }
+ }
+ return -1;
+}
static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
-#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
+#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) || defined(SBMAC_ETH3_HWADDR)
static void
sbmac_setup_hwaddr(int chan,char *addr)
{
unsigned long port;
int chip_max_units;
- /*
- * For bringup when not using the firmware, we can pre-fill
- * the MAC addresses using the environment variables
- * specified in this file (or maybe from the config file?)
- */
-#ifdef SBMAC_ETH0_HWADDR
- sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR);
-#endif
-#ifdef SBMAC_ETH1_HWADDR
- sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR);
-#endif
-#ifdef SBMAC_ETH2_HWADDR
- sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR);
-#endif
-
- /*
- * Walk through the Ethernet controllers and find
- * those who have their MAC addresses set.
- */
+ /* Set the number of available units based on the SOC type. */
switch (soc_type) {
case K_SYS_SOC_TYPE_BCM1250:
case K_SYS_SOC_TYPE_BCM1250_ALT:
case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */
chip_max_units = 2;
break;
+ case K_SYS_SOC_TYPE_BCM1x55:
+ case K_SYS_SOC_TYPE_BCM1x80:
+ chip_max_units = 4;
+ break;
default:
chip_max_units = 0;
break;
if (chip_max_units > MAX_UNITS)
chip_max_units = MAX_UNITS;
+ /*
+ * For bringup when not using the firmware, we can pre-fill
+ * the MAC addresses using the environment variables
+ * specified in this file (or maybe from the config file?)
+ */
+#ifdef SBMAC_ETH0_HWADDR
+ if (chip_max_units > 0)
+ sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR);
+#endif
+#ifdef SBMAC_ETH1_HWADDR
+ if (chip_max_units > 1)
+ sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR);
+#endif
+#ifdef SBMAC_ETH2_HWADDR
+ if (chip_max_units > 2)
+ sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR);
+#endif
+#ifdef SBMAC_ETH3_HWADDR
+ if (chip_max_units > 3)
+ sbmac_setup_hwaddr(3,SBMAC_ETH3_HWADDR);
+#endif
+
+ /*
+ * Walk through the Ethernet controllers and find
+ * those who have their MAC addresses set.
+ */
for (idx = 0; idx < chip_max_units; idx++) {
/*
printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
- dev->irq = K_INT_MAC_0 + idx;
+ dev->irq = UNIT_INT(idx);
dev->base_addr = port;
dev->mem_end = 0;
if (sbmac_init(dev, idx)) {