summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:01:24 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:01:24 +0200
commit2c6d68cc7d67ec3746e5fd2747c24d81b8a6b09d (patch)
treec42d53dc643d3109d3bb515f85367f63dde96402 /drivers
parentcab98427c270e2c4a4fd611fe534ed5fc20d9cb5 (diff)
downloadbarebox-2c6d68cc7d67ec3746e5fd2747c24d81b8a6b09d.tar.gz
barebox-2c6d68cc7d67ec3746e5fd2747c24d81b8a6b09d.tar.xz
svn_rev_113
new api, cleanup
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/dm9000.c380
-rw-r--r--drivers/net/dm9000.h3
2 files changed, 112 insertions, 271 deletions
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 687707627e..d675327da1 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -44,12 +44,12 @@ TODO: Homerun NIC and longrun NIC are not functional, only internal at the
#include <common.h>
#include <command.h>
+#include <clock.h>
+#include <miiphy.h>
#include <net.h>
#include <asm/io.h>
-#ifdef CONFIG_DRIVER_DM9000
-
-#include "dm9000x.h"
+#include "dm9000.h"
/* Board/System/Debug information/definition ---------------- */
@@ -63,45 +63,6 @@ TODO: Homerun NIC and longrun NIC are not functional, only internal at the
#else /* */
#define DM9000_DBG(fmt,args...)
#endif /* */
-enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD =
- 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO =
- 8, DM9000_1M_HPNA = 0x10
-};
-enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2
-};
-
-/* Structure/enum declaration ------------------------------- */
-typedef struct board_info {
- u32 runt_length_counter; /* counter: RX length < 64byte */
- u32 long_length_counter; /* counter: RX length > 1514byte */
- u32 reset_counter; /* counter: RESET */
- u32 reset_tx_timeout; /* RESET caused by TX Timeout */
- u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
- u16 tx_pkt_cnt;
- u16 queue_start_addr;
- u16 dbug_cnt;
- u8 phy_addr;
- u8 device_wait_reset; /* device state */
- u8 nic_type; /* NIC type */
- unsigned char srom[128];
-} board_info_t;
-board_info_t dmfe_info;
-
-/* For module input parameter */
-static int media_mode = DM9000_AUTO;
-static u8 nfloor = 0;
-
-/* function declaration ------------------------------------- */
-int eth_init(bd_t * bd);
-int eth_send(volatile void *, int);
-int eth_rx(void);
-void eth_halt(void);
-static int dm9000_probe(void);
-static u16 phy_read(int);
-static void phy_write(int, u16);
-static u16 read_srom_word(int);
-static u8 DM9000_ior(int);
-static void DM9000_iow(int reg, u8 value);
/* DM9000 network board routine ---------------------------- */
@@ -129,11 +90,50 @@ dump_regs(void)
}
#endif /* */
-/*
- Search DM9000 board, allocate space and register it
-*/
-int
-dm9000_probe(void)
+static u8 DM9000_ior(int reg)
+{
+ DM9000_outb(reg, DM9000_IO);
+ return DM9000_inb(DM9000_DATA);
+}
+
+static void DM9000_iow(int reg, u8 value)
+{
+ DM9000_outb(reg, DM9000_IO);
+ DM9000_outb(value, DM9000_DATA);
+}
+
+static u16 phy_read(int reg)
+{
+ u16 val;
+
+ /* Fill the phyxcer register into REG_0C */
+ DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
+ DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
+ udelay(100); /* Wait read complete */
+ DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
+ val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
+
+ /* The read data keeps on REG_0D & REG_0E */
+ DM9000_DBG("phy_read(%d): %d\n", reg, val);
+ return val;
+}
+
+static void phy_write(int reg, u16 value)
+{
+
+ /* Fill the phyxcer register into REG_0C */
+ DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
+
+ /* Fill the written data into REG_0D & REG_0E */
+ DM9000_iow(DM9000_EPDRL, (value & 0xff));
+ DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
+ DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
+ udelay(500); /* Wait write complete */
+ DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
+ DM9000_DBG("phy_write(reg:%d, value:%d)\n", reg, value);
+}
+
+int dm9000_probe(void)
{
u32 id_val;
id_val = DM9000_ior(DM9000_VIDL);
@@ -151,144 +151,21 @@ dm9000_probe(void)
}
}
-/* Set PHY operationg mode
-*/
-static void
-set_PHY_mode(void)
-{
- u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000;
- if (!(media_mode & DM9000_AUTO)) {
- switch (media_mode) {
- case DM9000_10MHD:
- phy_reg4 = 0x21;
- phy_reg0 = 0x0000;
- break;
- case DM9000_10MFD:
- phy_reg4 = 0x41;
- phy_reg0 = 0x1100;
- break;
- case DM9000_100MHD:
- phy_reg4 = 0x81;
- phy_reg0 = 0x2000;
- break;
- case DM9000_100MFD:
- phy_reg4 = 0x101;
- phy_reg0 = 0x3100;
- break;
- }
- phy_write(4, phy_reg4); /* Set PHY media mode */
- phy_write(0, phy_reg0); /* Tmp */
- }
- DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */
- DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */
-}
-
-/*
- Init HomeRun DM9801
-*/
-static void
-program_dm9801(u16 HPNA_rev)
-{
- __u16 reg16, reg17, reg24, reg25;
- if (!nfloor)
- nfloor = DM9801_NOISE_FLOOR;
- reg16 = phy_read(16);
- reg17 = phy_read(17);
- reg24 = phy_read(24);
- reg25 = phy_read(25);
- switch (HPNA_rev) {
- case 0xb900: /* DM9801 E3 */
- reg16 |= 0x1000;
- reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000;
- break;
- case 0xb901: /* DM9801 E4 */
- reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200;
- reg17 = (reg17 & 0xfff0) + nfloor + 3;
- break;
- case 0xb902: /* DM9801 E5 */
- case 0xb903: /* DM9801 E6 */
- default:
- reg16 |= 0x1000;
- reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200;
- reg17 = (reg17 & 0xfff0) + nfloor;
- }
- phy_write(16, reg16);
- phy_write(17, reg17);
- phy_write(25, reg25);
-}
-
-/*
- Init LongRun DM9802
-*/
-static void
-program_dm9802(void)
-{
- __u16 reg25;
- if (!nfloor)
- nfloor = DM9802_NOISE_FLOOR;
- reg25 = phy_read(25);
- reg25 = (reg25 & 0xff00) + nfloor;
- phy_write(25, reg25);
-}
-
-/* Identify NIC type
-*/
-static void
-identify_nic(void)
-{
- struct board_info *db = &dmfe_info; /* Point a board information structure */
- u16 phy_reg3;
- DM9000_iow(DM9000_NCR, NCR_EXT_PHY);
- phy_reg3 = phy_read(3);
- switch (phy_reg3 & 0xfff0) {
- case 0xb900:
- if (phy_read(31) == 0x4404) {
- db->nic_type = HOMERUN_NIC;
- program_dm9801(phy_reg3);
- DM9000_DBG("found homerun NIC\n");
- } else {
- db->nic_type = LONGRUN_NIC;
- DM9000_DBG("found longrun NIC\n");
- program_dm9802();
- }
- break;
- default:
- db->nic_type = FASTETHER_NIC;
- break;
- }
- DM9000_iow(DM9000_NCR, 0);
-}
-
-/* General Purpose dm9000 reset routine */
-static void
-dm9000_reset(void)
+static void dm9000_reset(void)
{
DM9000_DBG("resetting\n");
DM9000_iow(DM9000_NCR, NCR_RST);
udelay(1000); /* delay 1ms */
}
-/* Initilize dm9000 board
-*/
-int
-eth_init(bd_t * bd)
+int dm9000_eth_init(struct eth_device *ndev, bd_t * bd)
{
- int i, oft, lnk;
- DM9000_DBG("eth_init()\n");
+ printf("dm9000_eth_init()\n");
/* RESET device */
dm9000_reset();
dm9000_probe();
- /* NIC Type: FASTETHER, HOMERUN, LONGRUN */
- identify_nic();
-
- /* GPIO0 on pre-activate PHY */
- DM9000_iow(DM9000_GPR, 0x00); /*REG_1F bit0 activate phyxcer */
-
- /* Set PHY */
- set_PHY_mode();
-
/* Program operating register */
DM9000_iow(DM9000_NCR, 0x0); /* only intern phy supported by now */
DM9000_iow(DM9000_TCR, 0); /* TX Polling clear */
@@ -299,32 +176,40 @@ eth_init(bd_t * bd)
DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); /* clear TX status */
DM9000_iow(DM9000_ISR, 0x0f); /* Clear interrupt status */
- /* Set Node address */
- for (i = 0; i < 6; i++)
- ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
- printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
- bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
- bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
- for (i = 0, oft = 0x10; i < 6; i++, oft++)
- DM9000_iow(oft, bd->bi_enetaddr[i]);
- for (i = 0, oft = 0x16; i < 8; i++, oft++)
- DM9000_iow(oft, 0xff);
+ return 0;
+}
- /* read back mac, just to be sure */
- for (i = 0, oft = 0x10; i < 6; i++, oft++)
- DM9000_DBG("%02x:", DM9000_ior(oft));
- DM9000_DBG("\n");
+
+int dm9000_eth_open(struct eth_device *ndev, bd_t * bd)
+{
+ int lnk, i = 0, ctl;
/* Activate DM9000 */
+ DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */
+ DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */
DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */
DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */
- i = 0;
- while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
+
+ phy_write(0, 0x8000); /* PHY RESET */
+
+ ctl = phy_read(PHY_BMCR);
+
+ if (ctl < 0)
+ return ctl;
+
+ ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
+
+ /* Don't isolate the PHY if we're negotiating */
+ ctl &= ~(PHY_BMCR_ISO);
+
+ phy_write(PHY_BMCR, ctl);
+
+ while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
i++;
- if (i == 10000) {
+ if (i == 5000) {
printf("could not establish link\n");
- return 0;
+ break;
}
}
@@ -352,16 +237,11 @@ eth_init(bd_t * bd)
return 0;
}
-/*
- Hardware start transmission.
- Send a packet to media from the upper layer.
-*/
-int
-eth_send(volatile void *packet, int length)
+int dm9000_eth_send (struct eth_device *ndev, volatile void *packet, int length)
{
char *data_ptr;
u32 tmplen, i;
- int tmo;
+ uint64_t tmo;
DM9000_DBG("eth_send: length: %d\n", length);
for (i = 0; i < length; i++) {
if (i % 8 == 0)
@@ -400,9 +280,9 @@ eth_send(volatile void *packet, int length)
DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
/* wait for end of transmission */
- tmo = get_timer(0) + 5 * CFG_HZ;
+ tmo = get_time_ns();
while (DM9000_ior(DM9000_TCR) & TCR_TXREQ) {
- if (get_timer(0) >= tmo) {
+ if (is_timeout(tmo, 5 * SECOND)) {
printf("transmission timeout\n");
break;
}
@@ -411,27 +291,17 @@ eth_send(volatile void *packet, int length)
return 0;
}
-/*
- Stop the interface.
- The interface is stopped when it is brought.
-*/
-void
-eth_halt(void)
+void dm9000_eth_halt (struct eth_device *ndev)
{
- DM9000_DBG("eth_halt\n");
+ printf("eth_halt\n");
- /* RESET devie */
phy_write(0, 0x8000); /* PHY RESET */
DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
}
-/*
- Received a packet and pass to upper layer
-*/
-int
-eth_rx(void)
+int dm9000_eth_rx (struct eth_device *ndev)
{
u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
u16 RxStatus, RxLen = 0;
@@ -519,11 +389,7 @@ eth_rx(void)
return 0;
}
-/*
- Read a word data from SROM
-*/
-static u16
-read_srom_word(int offset)
+static u16 read_srom_word(int offset)
{
DM9000_iow(DM9000_EPAR, offset);
DM9000_iow(DM9000_EPCR, 0x4);
@@ -532,62 +398,40 @@ read_srom_word(int offset)
return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
}
-/*
- Read a byte from I/O port
-*/
-static u8
-DM9000_ior(int reg)
+static int dm9000_get_mac_address(struct eth_device *eth, unsigned char *adr)
{
- DM9000_outb(reg, DM9000_IO);
- return DM9000_inb(DM9000_DATA);
-}
+ int i;
-/*
- Write a byte to I/O port
-*/
-static void
-DM9000_iow(int reg, u8 value)
-{
- DM9000_outb(reg, DM9000_IO);
- DM9000_outb(value, DM9000_DATA);
+ for (i = 0; i < 3; i++)
+ ((u16 *) adr)[i] = read_srom_word(i);
+
+ return 0;
}
-/*
- Read a word from phyxcer
-*/
-static u16
-phy_read(int reg)
+static int dm9000_set_mac_address(struct eth_device *eth, unsigned char *adr)
{
- u16 val;
-
- /* Fill the phyxcer register into REG_0C */
- DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
- DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
- udelay(100); /* Wait read complete */
- DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
- val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
+ int i, oft;
+printf("dm9000_set_mac_address\n");
+ for (i = 0, oft = 0x10; i < 6; i++, oft++)
+ DM9000_iow(oft, adr[i]);
+ for (i = 0, oft = 0x16; i < 8; i++, oft++)
+ DM9000_iow(oft, 0xff);
- /* The read data keeps on REG_0D & REG_0E */
- DM9000_DBG("phy_read(%d): %d\n", reg, val);
- return val;
+#if 0
+ for (i = 0; i < 5; i++)
+ printf ("%02x:", adr[i]);
+ printf ("%02x\n", adr[5]);
+#endif
+ return -0;
}
-/*
- Write a word to phyxcer
-*/
-static void
-phy_write(int reg, u16 value)
-{
-
- /* Fill the phyxcer register into REG_0C */
- DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
+struct eth_device dm9000_eth = {
+ .init = dm9000_eth_init,
+ .open = dm9000_eth_open,
+ .send = dm9000_eth_send,
+ .recv = dm9000_eth_rx,
+ .halt = dm9000_eth_halt,
+ .get_mac_address = dm9000_get_mac_address,
+ .set_mac_address = dm9000_set_mac_address,
+};
- /* Fill the written data into REG_0D & REG_0E */
- DM9000_iow(DM9000_EPDRL, (value & 0xff));
- DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
- DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
- udelay(500); /* Wait write complete */
- DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
- DM9000_DBG("phy_write(reg:%d, value:%d)\n", reg, value);
-}
-#endif /* CONFIG_DRIVER_DM9000 */
diff --git a/drivers/net/dm9000.h b/drivers/net/dm9000.h
index f47ff8cb34..442c86ddbd 100644
--- a/drivers/net/dm9000.h
+++ b/drivers/net/dm9000.h
@@ -2,8 +2,6 @@
* dm9000 Ethernet
*/
-#ifdef CONFIG_DRIVER_DM9000
-
#define DM9000_ID 0x90000A46
#define DM9000_PKT_MAX 1536 /* Received packet max size */
#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */
@@ -116,4 +114,3 @@
#define IMR_PTM (1<<1)
#define IMR_PRM (1<<0)
-#endif