[U-Boot] [PATCH] smc911x_eeprom: new example app for managing newer SMC parts
Mike Frysinger
vapier at gentoo.org
Thu Dec 11 02:46:08 CET 2008
A forward port of the last version to work with the newer smc911x driver.
A bunch of simple functions/defines had to be split out of the smc911x
driver to avoid ugly code duplication in the eeprom programmer.
I only have a board with a LAN9218 part on it, so that is the only one
I've tested. But there isn't anything in this that would make it terribly
chip specific afaik.
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
drivers/net/smc911x.c | 452 +-----------------------------------------
drivers/net/smc911x.h | 486 +++++++++++++++++++++++++++++++++++++++++++++
examples/.gitignore | 1 +
examples/Makefile | 7 +-
examples/smc911x_eeprom.c | 381 +++++++++++++++++++++++++++++++++++
5 files changed, 874 insertions(+), 453 deletions(-)
create mode 100644 drivers/net/smc911x.h
create mode 100644 examples/smc911x_eeprom.c
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 648c94c..192bd96 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -27,35 +27,7 @@
#include <net.h>
#include <miiphy.h>
-#if defined (CONFIG_DRIVER_SMC911X_32_BIT) && \
- defined (CONFIG_DRIVER_SMC911X_16_BIT)
-#error "SMC911X: Only one of CONFIG_DRIVER_SMC911X_32_BIT and \
- CONFIG_DRIVER_SMC911X_16_BIT shall be set"
-#endif
-
-#if defined (CONFIG_DRIVER_SMC911X_32_BIT)
-static inline u32 reg_read(u32 addr)
-{
- return *(volatile u32*)addr;
-}
-static inline void reg_write(u32 addr, u32 val)
-{
- *(volatile u32*)addr = val;
-}
-#elif defined (CONFIG_DRIVER_SMC911X_16_BIT)
-static inline u32 reg_read(u32 addr)
-{
- volatile u16 *addr_16 = (u16 *)addr;
- return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16));
-}
-static inline void reg_write(u32 addr, u32 val)
-{
- *(volatile u16*)addr = (u16)val;
- *(volatile u16*)(addr + 2) = (u16)(val >> 16);
-}
-#else
-#error "SMC911X: undefined bus width"
-#endif /* CONFIG_DRIVER_SMC911X_16_BIT */
+#include "smc911x.h"
u32 pkt_data_pull(u32 addr) \
__attribute__ ((weak, alias ("reg_read")));
@@ -64,368 +36,6 @@ void pkt_data_push(u32 addr, u32 val) \
#define mdelay(n) udelay((n)*1000)
-/* Below are the register offsets and bit definitions
- * of the Lan911x memory space
- */
-#define RX_DATA_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x00)
-
-#define TX_DATA_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x20)
-#define TX_CMD_A_INT_ON_COMP 0x80000000
-#define TX_CMD_A_INT_BUF_END_ALGN 0x03000000
-#define TX_CMD_A_INT_4_BYTE_ALGN 0x00000000
-#define TX_CMD_A_INT_16_BYTE_ALGN 0x01000000
-#define TX_CMD_A_INT_32_BYTE_ALGN 0x02000000
-#define TX_CMD_A_INT_DATA_OFFSET 0x001F0000
-#define TX_CMD_A_INT_FIRST_SEG 0x00002000
-#define TX_CMD_A_INT_LAST_SEG 0x00001000
-#define TX_CMD_A_BUF_SIZE 0x000007FF
-#define TX_CMD_B_PKT_TAG 0xFFFF0000
-#define TX_CMD_B_ADD_CRC_DISABLE 0x00002000
-#define TX_CMD_B_DISABLE_PADDING 0x00001000
-#define TX_CMD_B_PKT_BYTE_LENGTH 0x000007FF
-
-#define RX_STATUS_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x40)
-#define RX_STS_PKT_LEN 0x3FFF0000
-#define RX_STS_ES 0x00008000
-#define RX_STS_BCST 0x00002000
-#define RX_STS_LEN_ERR 0x00001000
-#define RX_STS_RUNT_ERR 0x00000800
-#define RX_STS_MCAST 0x00000400
-#define RX_STS_TOO_LONG 0x00000080
-#define RX_STS_COLL 0x00000040
-#define RX_STS_ETH_TYPE 0x00000020
-#define RX_STS_WDOG_TMT 0x00000010
-#define RX_STS_MII_ERR 0x00000008
-#define RX_STS_DRIBBLING 0x00000004
-#define RX_STS_CRC_ERR 0x00000002
-#define RX_STATUS_FIFO_PEEK (CONFIG_DRIVER_SMC911X_BASE + 0x44)
-#define TX_STATUS_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x48)
-#define TX_STS_TAG 0xFFFF0000
-#define TX_STS_ES 0x00008000
-#define TX_STS_LOC 0x00000800
-#define TX_STS_NO_CARR 0x00000400
-#define TX_STS_LATE_COLL 0x00000200
-#define TX_STS_MANY_COLL 0x00000100
-#define TX_STS_COLL_CNT 0x00000078
-#define TX_STS_MANY_DEFER 0x00000004
-#define TX_STS_UNDERRUN 0x00000002
-#define TX_STS_DEFERRED 0x00000001
-#define TX_STATUS_FIFO_PEEK (CONFIG_DRIVER_SMC911X_BASE + 0x4C)
-#define ID_REV (CONFIG_DRIVER_SMC911X_BASE + 0x50)
-#define ID_REV_CHIP_ID 0xFFFF0000 /* RO */
-#define ID_REV_REV_ID 0x0000FFFF /* RO */
-
-#define INT_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x54)
-#define INT_CFG_INT_DEAS 0xFF000000 /* R/W */
-#define INT_CFG_INT_DEAS_CLR 0x00004000
-#define INT_CFG_INT_DEAS_STS 0x00002000
-#define INT_CFG_IRQ_INT 0x00001000 /* RO */
-#define INT_CFG_IRQ_EN 0x00000100 /* R/W */
-#define INT_CFG_IRQ_POL 0x00000010 /* R/W Not Affected by SW Reset */
-#define INT_CFG_IRQ_TYPE 0x00000001 /* R/W Not Affected by SW Reset */
-
-#define INT_STS (CONFIG_DRIVER_SMC911X_BASE + 0x58)
-#define INT_STS_SW_INT 0x80000000 /* R/WC */
-#define INT_STS_TXSTOP_INT 0x02000000 /* R/WC */
-#define INT_STS_RXSTOP_INT 0x01000000 /* R/WC */
-#define INT_STS_RXDFH_INT 0x00800000 /* R/WC */
-#define INT_STS_RXDF_INT 0x00400000 /* R/WC */
-#define INT_STS_TX_IOC 0x00200000 /* R/WC */
-#define INT_STS_RXD_INT 0x00100000 /* R/WC */
-#define INT_STS_GPT_INT 0x00080000 /* R/WC */
-#define INT_STS_PHY_INT 0x00040000 /* RO */
-#define INT_STS_PME_INT 0x00020000 /* R/WC */
-#define INT_STS_TXSO 0x00010000 /* R/WC */
-#define INT_STS_RWT 0x00008000 /* R/WC */
-#define INT_STS_RXE 0x00004000 /* R/WC */
-#define INT_STS_TXE 0x00002000 /* R/WC */
-/*#define INT_STS_ERX 0x00001000*/ /* R/WC */
-#define INT_STS_TDFU 0x00000800 /* R/WC */
-#define INT_STS_TDFO 0x00000400 /* R/WC */
-#define INT_STS_TDFA 0x00000200 /* R/WC */
-#define INT_STS_TSFF 0x00000100 /* R/WC */
-#define INT_STS_TSFL 0x00000080 /* R/WC */
-/*#define INT_STS_RXDF 0x00000040*/ /* R/WC */
-#define INT_STS_RDFO 0x00000040 /* R/WC */
-#define INT_STS_RDFL 0x00000020 /* R/WC */
-#define INT_STS_RSFF 0x00000010 /* R/WC */
-#define INT_STS_RSFL 0x00000008 /* R/WC */
-#define INT_STS_GPIO2_INT 0x00000004 /* R/WC */
-#define INT_STS_GPIO1_INT 0x00000002 /* R/WC */
-#define INT_STS_GPIO0_INT 0x00000001 /* R/WC */
-#define INT_EN (CONFIG_DRIVER_SMC911X_BASE + 0x5C)
-#define INT_EN_SW_INT_EN 0x80000000 /* R/W */
-#define INT_EN_TXSTOP_INT_EN 0x02000000 /* R/W */
-#define INT_EN_RXSTOP_INT_EN 0x01000000 /* R/W */
-#define INT_EN_RXDFH_INT_EN 0x00800000 /* R/W */
-/*#define INT_EN_RXDF_INT_EN 0x00400000*/ /* R/W */
-#define INT_EN_TIOC_INT_EN 0x00200000 /* R/W */
-#define INT_EN_RXD_INT_EN 0x00100000 /* R/W */
-#define INT_EN_GPT_INT_EN 0x00080000 /* R/W */
-#define INT_EN_PHY_INT_EN 0x00040000 /* R/W */
-#define INT_EN_PME_INT_EN 0x00020000 /* R/W */
-#define INT_EN_TXSO_EN 0x00010000 /* R/W */
-#define INT_EN_RWT_EN 0x00008000 /* R/W */
-#define INT_EN_RXE_EN 0x00004000 /* R/W */
-#define INT_EN_TXE_EN 0x00002000 /* R/W */
-/*#define INT_EN_ERX_EN 0x00001000*/ /* R/W */
-#define INT_EN_TDFU_EN 0x00000800 /* R/W */
-#define INT_EN_TDFO_EN 0x00000400 /* R/W */
-#define INT_EN_TDFA_EN 0x00000200 /* R/W */
-#define INT_EN_TSFF_EN 0x00000100 /* R/W */
-#define INT_EN_TSFL_EN 0x00000080 /* R/W */
-/*#define INT_EN_RXDF_EN 0x00000040*/ /* R/W */
-#define INT_EN_RDFO_EN 0x00000040 /* R/W */
-#define INT_EN_RDFL_EN 0x00000020 /* R/W */
-#define INT_EN_RSFF_EN 0x00000010 /* R/W */
-#define INT_EN_RSFL_EN 0x00000008 /* R/W */
-#define INT_EN_GPIO2_INT 0x00000004 /* R/W */
-#define INT_EN_GPIO1_INT 0x00000002 /* R/W */
-#define INT_EN_GPIO0_INT 0x00000001 /* R/W */
-
-#define BYTE_TEST (CONFIG_DRIVER_SMC911X_BASE + 0x64)
-#define FIFO_INT (CONFIG_DRIVER_SMC911X_BASE + 0x68)
-#define FIFO_INT_TX_AVAIL_LEVEL 0xFF000000 /* R/W */
-#define FIFO_INT_TX_STS_LEVEL 0x00FF0000 /* R/W */
-#define FIFO_INT_RX_AVAIL_LEVEL 0x0000FF00 /* R/W */
-#define FIFO_INT_RX_STS_LEVEL 0x000000FF /* R/W */
-
-#define RX_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x6C)
-#define RX_CFG_RX_END_ALGN 0xC0000000 /* R/W */
-#define RX_CFG_RX_END_ALGN4 0x00000000 /* R/W */
-#define RX_CFG_RX_END_ALGN16 0x40000000 /* R/W */
-#define RX_CFG_RX_END_ALGN32 0x80000000 /* R/W */
-#define RX_CFG_RX_DMA_CNT 0x0FFF0000 /* R/W */
-#define RX_CFG_RX_DUMP 0x00008000 /* R/W */
-#define RX_CFG_RXDOFF 0x00001F00 /* R/W */
-/*#define RX_CFG_RXBAD 0x00000001*/ /* R/W */
-
-#define TX_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x70)
-/*#define TX_CFG_TX_DMA_LVL 0xE0000000*/ /* R/W */
-/*#define TX_CFG_TX_DMA_CNT 0x0FFF0000*/ /* R/W Self Clearing */
-#define TX_CFG_TXS_DUMP 0x00008000 /* Self Clearing */
-#define TX_CFG_TXD_DUMP 0x00004000 /* Self Clearing */
-#define TX_CFG_TXSAO 0x00000004 /* R/W */
-#define TX_CFG_TX_ON 0x00000002 /* R/W */
-#define TX_CFG_STOP_TX 0x00000001 /* Self Clearing */
-
-#define HW_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x74)
-#define HW_CFG_TTM 0x00200000 /* R/W */
-#define HW_CFG_SF 0x00100000 /* R/W */
-#define HW_CFG_TX_FIF_SZ 0x000F0000 /* R/W */
-#define HW_CFG_TR 0x00003000 /* R/W */
-#define HW_CFG_PHY_CLK_SEL 0x00000060 /* R/W */
-#define HW_CFG_PHY_CLK_SEL_INT_PHY 0x00000000 /* R/W */
-#define HW_CFG_PHY_CLK_SEL_EXT_PHY 0x00000020 /* R/W */
-#define HW_CFG_PHY_CLK_SEL_CLK_DIS 0x00000040 /* R/W */
-#define HW_CFG_SMI_SEL 0x00000010 /* R/W */
-#define HW_CFG_EXT_PHY_DET 0x00000008 /* RO */
-#define HW_CFG_EXT_PHY_EN 0x00000004 /* R/W */
-#define HW_CFG_32_16_BIT_MODE 0x00000004 /* RO */
-#define HW_CFG_SRST_TO 0x00000002 /* RO */
-#define HW_CFG_SRST 0x00000001 /* Self Clearing */
-
-#define RX_DP_CTRL (CONFIG_DRIVER_SMC911X_BASE + 0x78)
-#define RX_DP_CTRL_RX_FFWD 0x80000000 /* R/W */
-#define RX_DP_CTRL_FFWD_BUSY 0x80000000 /* RO */
-
-#define RX_FIFO_INF (CONFIG_DRIVER_SMC911X_BASE + 0x7C)
-#define RX_FIFO_INF_RXSUSED 0x00FF0000 /* RO */
-#define RX_FIFO_INF_RXDUSED 0x0000FFFF /* RO */
-
-#define TX_FIFO_INF (CONFIG_DRIVER_SMC911X_BASE + 0x80)
-#define TX_FIFO_INF_TSUSED 0x00FF0000 /* RO */
-#define TX_FIFO_INF_TDFREE 0x0000FFFF /* RO */
-
-#define PMT_CTRL (CONFIG_DRIVER_SMC911X_BASE + 0x84)
-#define PMT_CTRL_PM_MODE 0x00003000 /* Self Clearing */
-#define PMT_CTRL_PHY_RST 0x00000400 /* Self Clearing */
-#define PMT_CTRL_WOL_EN 0x00000200 /* R/W */
-#define PMT_CTRL_ED_EN 0x00000100 /* R/W */
-#define PMT_CTRL_PME_TYPE 0x00000040 /* R/W Not Affected by SW Reset */
-#define PMT_CTRL_WUPS 0x00000030 /* R/WC */
-#define PMT_CTRL_WUPS_NOWAKE 0x00000000 /* R/WC */
-#define PMT_CTRL_WUPS_ED 0x00000010 /* R/WC */
-#define PMT_CTRL_WUPS_WOL 0x00000020 /* R/WC */
-#define PMT_CTRL_WUPS_MULTI 0x00000030 /* R/WC */
-#define PMT_CTRL_PME_IND 0x00000008 /* R/W */
-#define PMT_CTRL_PME_POL 0x00000004 /* R/W */
-#define PMT_CTRL_PME_EN 0x00000002 /* R/W Not Affected by SW Reset */
-#define PMT_CTRL_READY 0x00000001 /* RO */
-
-#define GPIO_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x88)
-#define GPIO_CFG_LED3_EN 0x40000000 /* R/W */
-#define GPIO_CFG_LED2_EN 0x20000000 /* R/W */
-#define GPIO_CFG_LED1_EN 0x10000000 /* R/W */
-#define GPIO_CFG_GPIO2_INT_POL 0x04000000 /* R/W */
-#define GPIO_CFG_GPIO1_INT_POL 0x02000000 /* R/W */
-#define GPIO_CFG_GPIO0_INT_POL 0x01000000 /* R/W */
-#define GPIO_CFG_EEPR_EN 0x00700000 /* R/W */
-#define GPIO_CFG_GPIOBUF2 0x00040000 /* R/W */
-#define GPIO_CFG_GPIOBUF1 0x00020000 /* R/W */
-#define GPIO_CFG_GPIOBUF0 0x00010000 /* R/W */
-#define GPIO_CFG_GPIODIR2 0x00000400 /* R/W */
-#define GPIO_CFG_GPIODIR1 0x00000200 /* R/W */
-#define GPIO_CFG_GPIODIR0 0x00000100 /* R/W */
-#define GPIO_CFG_GPIOD4 0x00000010 /* R/W */
-#define GPIO_CFG_GPIOD3 0x00000008 /* R/W */
-#define GPIO_CFG_GPIOD2 0x00000004 /* R/W */
-#define GPIO_CFG_GPIOD1 0x00000002 /* R/W */
-#define GPIO_CFG_GPIOD0 0x00000001 /* R/W */
-
-#define GPT_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x8C)
-#define GPT_CFG_TIMER_EN 0x20000000 /* R/W */
-#define GPT_CFG_GPT_LOAD 0x0000FFFF /* R/W */
-
-#define GPT_CNT (CONFIG_DRIVER_SMC911X_BASE + 0x90)
-#define GPT_CNT_GPT_CNT 0x0000FFFF /* RO */
-
-#define ENDIAN (CONFIG_DRIVER_SMC911X_BASE + 0x98)
-#define FREE_RUN (CONFIG_DRIVER_SMC911X_BASE + 0x9C)
-#define RX_DROP (CONFIG_DRIVER_SMC911X_BASE + 0xA0)
-#define MAC_CSR_CMD (CONFIG_DRIVER_SMC911X_BASE + 0xA4)
-#define MAC_CSR_CMD_CSR_BUSY 0x80000000 /* Self Clearing */
-#define MAC_CSR_CMD_R_NOT_W 0x40000000 /* R/W */
-#define MAC_CSR_CMD_CSR_ADDR 0x000000FF /* R/W */
-
-#define MAC_CSR_DATA (CONFIG_DRIVER_SMC911X_BASE + 0xA8)
-#define AFC_CFG (CONFIG_DRIVER_SMC911X_BASE + 0xAC)
-#define AFC_CFG_AFC_HI 0x00FF0000 /* R/W */
-#define AFC_CFG_AFC_LO 0x0000FF00 /* R/W */
-#define AFC_CFG_BACK_DUR 0x000000F0 /* R/W */
-#define AFC_CFG_FCMULT 0x00000008 /* R/W */
-#define AFC_CFG_FCBRD 0x00000004 /* R/W */
-#define AFC_CFG_FCADD 0x00000002 /* R/W */
-#define AFC_CFG_FCANY 0x00000001 /* R/W */
-
-#define E2P_CMD (CONFIG_DRIVER_SMC911X_BASE + 0xB0)
-#define E2P_CMD_EPC_BUSY 0x80000000 /* Self Clearing */
-#define E2P_CMD_EPC_CMD 0x70000000 /* R/W */
-#define E2P_CMD_EPC_CMD_READ 0x00000000 /* R/W */
-#define E2P_CMD_EPC_CMD_EWDS 0x10000000 /* R/W */
-#define E2P_CMD_EPC_CMD_EWEN 0x20000000 /* R/W */
-#define E2P_CMD_EPC_CMD_WRITE 0x30000000 /* R/W */
-#define E2P_CMD_EPC_CMD_WRAL 0x40000000 /* R/W */
-#define E2P_CMD_EPC_CMD_ERASE 0x50000000 /* R/W */
-#define E2P_CMD_EPC_CMD_ERAL 0x60000000 /* R/W */
-#define E2P_CMD_EPC_CMD_RELOAD 0x70000000 /* R/W */
-#define E2P_CMD_EPC_TIMEOUT 0x00000200 /* RO */
-#define E2P_CMD_MAC_ADDR_LOADED 0x00000100 /* RO */
-#define E2P_CMD_EPC_ADDR 0x000000FF /* R/W */
-
-#define E2P_DATA (CONFIG_DRIVER_SMC911X_BASE + 0xB4)
-#define E2P_DATA_EEPROM_DATA 0x000000FF /* R/W */
-/* end of LAN register offsets and bit definitions */
-
-/* MAC Control and Status registers */
-#define MAC_CR 0x01 /* R/W */
-
-/* MAC_CR - MAC Control Register */
-#define MAC_CR_RXALL 0x80000000
-/* TODO: delete this bit? It is not described in the data sheet. */
-#define MAC_CR_HBDIS 0x10000000
-#define MAC_CR_RCVOWN 0x00800000
-#define MAC_CR_LOOPBK 0x00200000
-#define MAC_CR_FDPX 0x00100000
-#define MAC_CR_MCPAS 0x00080000
-#define MAC_CR_PRMS 0x00040000
-#define MAC_CR_INVFILT 0x00020000
-#define MAC_CR_PASSBAD 0x00010000
-#define MAC_CR_HFILT 0x00008000
-#define MAC_CR_HPFILT 0x00002000
-#define MAC_CR_LCOLL 0x00001000
-#define MAC_CR_BCAST 0x00000800
-#define MAC_CR_DISRTY 0x00000400
-#define MAC_CR_PADSTR 0x00000100
-#define MAC_CR_BOLMT_MASK 0x000000C0
-#define MAC_CR_DFCHK 0x00000020
-#define MAC_CR_TXEN 0x00000008
-#define MAC_CR_RXEN 0x00000004
-
-#define ADDRH 0x02 /* R/W mask 0x0000FFFFUL */
-#define ADDRL 0x03 /* R/W mask 0xFFFFFFFFUL */
-#define HASHH 0x04 /* R/W */
-#define HASHL 0x05 /* R/W */
-
-#define MII_ACC 0x06 /* R/W */
-#define MII_ACC_PHY_ADDR 0x0000F800
-#define MII_ACC_MIIRINDA 0x000007C0
-#define MII_ACC_MII_WRITE 0x00000002
-#define MII_ACC_MII_BUSY 0x00000001
-
-#define MII_DATA 0x07 /* R/W mask 0x0000FFFFUL */
-
-#define FLOW 0x08 /* R/W */
-#define FLOW_FCPT 0xFFFF0000
-#define FLOW_FCPASS 0x00000004
-#define FLOW_FCEN 0x00000002
-#define FLOW_FCBSY 0x00000001
-
-#define VLAN1 0x09 /* R/W mask 0x0000FFFFUL */
-#define VLAN1_VTI1 0x0000ffff
-
-#define VLAN2 0x0A /* R/W mask 0x0000FFFFUL */
-#define VLAN2_VTI2 0x0000ffff
-
-#define WUFF 0x0B /* WO */
-
-#define WUCSR 0x0C /* R/W */
-#define WUCSR_GUE 0x00000200
-#define WUCSR_WUFR 0x00000040
-#define WUCSR_MPR 0x00000020
-#define WUCSR_WAKE_EN 0x00000004
-#define WUCSR_MPEN 0x00000002
-
-/* Chip ID values */
-#define CHIP_9115 0x115
-#define CHIP_9116 0x116
-#define CHIP_9117 0x117
-#define CHIP_9118 0x118
-#define CHIP_9215 0x115a
-#define CHIP_9216 0x116a
-#define CHIP_9217 0x117a
-#define CHIP_9218 0x118a
-
-struct chip_id {
- u16 id;
- char *name;
-};
-
-static const struct chip_id chip_ids[] = {
- { CHIP_9115, "LAN9115" },
- { CHIP_9116, "LAN9116" },
- { CHIP_9117, "LAN9117" },
- { CHIP_9118, "LAN9118" },
- { CHIP_9215, "LAN9215" },
- { CHIP_9216, "LAN9216" },
- { CHIP_9217, "LAN9217" },
- { CHIP_9218, "LAN9218" },
- { 0, NULL },
-};
-
-#define DRIVERNAME "smc911x"
-
-u32 smc911x_get_mac_csr(u8 reg)
-{
- while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
- ;
- reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
- while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
- ;
-
- return reg_read(MAC_CSR_DATA);
-}
-
-void smc911x_set_mac_csr(u8 reg, u32 data)
-{
- while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
- ;
- reg_write(MAC_CSR_DATA, data);
- reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
- while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
- ;
-}
-
static int smx911x_handle_mac_address(bd_t *bd)
{
unsigned long addrh, addrl;
@@ -536,48 +146,6 @@ err_out:
printf(DRIVERNAME ": autonegotiation timed out\n");
}
-static void smc911x_reset(void)
-{
- int timeout;
-
- /* Take out of PM setting first */
- if (reg_read(PMT_CTRL) & PMT_CTRL_READY) {
- /* Write to the bytetest will take out of powerdown */
- reg_write(BYTE_TEST, 0x0);
-
- timeout = 10;
-
- while (timeout-- && !(reg_read(PMT_CTRL) & PMT_CTRL_READY))
- udelay(10);
- if (!timeout) {
- printf(DRIVERNAME
- ": timeout waiting for PM restore\n");
- return;
- }
- }
-
- /* Disable interrupts */
- reg_write(INT_EN, 0);
-
- reg_write(HW_CFG, HW_CFG_SRST);
-
- timeout = 1000;
- while (timeout-- && reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY)
- udelay(10);
-
- if (!timeout) {
- printf(DRIVERNAME ": reset timeout\n");
- return;
- }
-
- /* Reset the FIFO level and flow control settings */
- smc911x_set_mac_csr(FLOW, FLOW_FCPT | FLOW_FCEN);
- reg_write(AFC_CFG, 0x0050287F);
-
- /* Set to LED outputs */
- reg_write(GPIO_CFG, 0x70070000);
-}
-
static void smc911x_enable(void)
{
/* Enable TX */
@@ -596,26 +164,10 @@ static void smc911x_enable(void)
int eth_init(bd_t *bd)
{
- unsigned long val, i;
-
printf(DRIVERNAME ": initializing\n");
- val = reg_read(BYTE_TEST);
- if (val != 0x87654321) {
- printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
+ if (!smc911x_detect_chip())
goto err_out;
- }
-
- val = reg_read(ID_REV) >> 16;
- for (i = 0; chip_ids[i].id != 0; i++) {
- if (chip_ids[i].id == val) break;
- }
- if (!chip_ids[i].id) {
- printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);
- goto err_out;
- }
-
- printf(DRIVERNAME ": detected %s controller\n", chip_ids[i].name);
smc911x_reset();
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
new file mode 100644
index 0000000..24cbaaa
--- /dev/null
+++ b/drivers/net/smc911x.h
@@ -0,0 +1,486 @@
+/*
+ * SMSC LAN9[12]1[567] Network driver
+ *
+ * (c) 2007 Pengutronix, Sascha Hauer <s.hauer at pengutronix.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _SMC911X_H_
+#define _SMC911X_H_
+
+#if defined (CONFIG_DRIVER_SMC911X_32_BIT) && \
+ defined (CONFIG_DRIVER_SMC911X_16_BIT)
+#error "SMC911X: Only one of CONFIG_DRIVER_SMC911X_32_BIT and \
+ CONFIG_DRIVER_SMC911X_16_BIT shall be set"
+#endif
+
+#if defined (CONFIG_DRIVER_SMC911X_32_BIT)
+static inline u32 reg_read(u32 addr)
+{
+ return *(volatile u32*)addr;
+}
+static inline void reg_write(u32 addr, u32 val)
+{
+ *(volatile u32*)addr = val;
+}
+#elif defined (CONFIG_DRIVER_SMC911X_16_BIT)
+static inline u32 reg_read(u32 addr)
+{
+ volatile u16 *addr_16 = (u16 *)addr;
+ return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16));
+}
+static inline void reg_write(u32 addr, u32 val)
+{
+ *(volatile u16*)addr = (u16)val;
+ *(volatile u16*)(addr + 2) = (u16)(val >> 16);
+}
+#else
+#error "SMC911X: undefined bus width"
+#endif /* CONFIG_DRIVER_SMC911X_16_BIT */
+
+/* Below are the register offsets and bit definitions
+ * of the Lan911x memory space
+ */
+#define RX_DATA_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x00)
+
+#define TX_DATA_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x20)
+#define TX_CMD_A_INT_ON_COMP 0x80000000
+#define TX_CMD_A_INT_BUF_END_ALGN 0x03000000
+#define TX_CMD_A_INT_4_BYTE_ALGN 0x00000000
+#define TX_CMD_A_INT_16_BYTE_ALGN 0x01000000
+#define TX_CMD_A_INT_32_BYTE_ALGN 0x02000000
+#define TX_CMD_A_INT_DATA_OFFSET 0x001F0000
+#define TX_CMD_A_INT_FIRST_SEG 0x00002000
+#define TX_CMD_A_INT_LAST_SEG 0x00001000
+#define TX_CMD_A_BUF_SIZE 0x000007FF
+#define TX_CMD_B_PKT_TAG 0xFFFF0000
+#define TX_CMD_B_ADD_CRC_DISABLE 0x00002000
+#define TX_CMD_B_DISABLE_PADDING 0x00001000
+#define TX_CMD_B_PKT_BYTE_LENGTH 0x000007FF
+
+#define RX_STATUS_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x40)
+#define RX_STS_PKT_LEN 0x3FFF0000
+#define RX_STS_ES 0x00008000
+#define RX_STS_BCST 0x00002000
+#define RX_STS_LEN_ERR 0x00001000
+#define RX_STS_RUNT_ERR 0x00000800
+#define RX_STS_MCAST 0x00000400
+#define RX_STS_TOO_LONG 0x00000080
+#define RX_STS_COLL 0x00000040
+#define RX_STS_ETH_TYPE 0x00000020
+#define RX_STS_WDOG_TMT 0x00000010
+#define RX_STS_MII_ERR 0x00000008
+#define RX_STS_DRIBBLING 0x00000004
+#define RX_STS_CRC_ERR 0x00000002
+#define RX_STATUS_FIFO_PEEK (CONFIG_DRIVER_SMC911X_BASE + 0x44)
+#define TX_STATUS_FIFO (CONFIG_DRIVER_SMC911X_BASE + 0x48)
+#define TX_STS_TAG 0xFFFF0000
+#define TX_STS_ES 0x00008000
+#define TX_STS_LOC 0x00000800
+#define TX_STS_NO_CARR 0x00000400
+#define TX_STS_LATE_COLL 0x00000200
+#define TX_STS_MANY_COLL 0x00000100
+#define TX_STS_COLL_CNT 0x00000078
+#define TX_STS_MANY_DEFER 0x00000004
+#define TX_STS_UNDERRUN 0x00000002
+#define TX_STS_DEFERRED 0x00000001
+#define TX_STATUS_FIFO_PEEK (CONFIG_DRIVER_SMC911X_BASE + 0x4C)
+#define ID_REV (CONFIG_DRIVER_SMC911X_BASE + 0x50)
+#define ID_REV_CHIP_ID 0xFFFF0000 /* RO */
+#define ID_REV_REV_ID 0x0000FFFF /* RO */
+
+#define INT_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x54)
+#define INT_CFG_INT_DEAS 0xFF000000 /* R/W */
+#define INT_CFG_INT_DEAS_CLR 0x00004000
+#define INT_CFG_INT_DEAS_STS 0x00002000
+#define INT_CFG_IRQ_INT 0x00001000 /* RO */
+#define INT_CFG_IRQ_EN 0x00000100 /* R/W */
+#define INT_CFG_IRQ_POL 0x00000010 /* R/W Not Affected by SW Reset */
+#define INT_CFG_IRQ_TYPE 0x00000001 /* R/W Not Affected by SW Reset */
+
+#define INT_STS (CONFIG_DRIVER_SMC911X_BASE + 0x58)
+#define INT_STS_SW_INT 0x80000000 /* R/WC */
+#define INT_STS_TXSTOP_INT 0x02000000 /* R/WC */
+#define INT_STS_RXSTOP_INT 0x01000000 /* R/WC */
+#define INT_STS_RXDFH_INT 0x00800000 /* R/WC */
+#define INT_STS_RXDF_INT 0x00400000 /* R/WC */
+#define INT_STS_TX_IOC 0x00200000 /* R/WC */
+#define INT_STS_RXD_INT 0x00100000 /* R/WC */
+#define INT_STS_GPT_INT 0x00080000 /* R/WC */
+#define INT_STS_PHY_INT 0x00040000 /* RO */
+#define INT_STS_PME_INT 0x00020000 /* R/WC */
+#define INT_STS_TXSO 0x00010000 /* R/WC */
+#define INT_STS_RWT 0x00008000 /* R/WC */
+#define INT_STS_RXE 0x00004000 /* R/WC */
+#define INT_STS_TXE 0x00002000 /* R/WC */
+/*#define INT_STS_ERX 0x00001000*/ /* R/WC */
+#define INT_STS_TDFU 0x00000800 /* R/WC */
+#define INT_STS_TDFO 0x00000400 /* R/WC */
+#define INT_STS_TDFA 0x00000200 /* R/WC */
+#define INT_STS_TSFF 0x00000100 /* R/WC */
+#define INT_STS_TSFL 0x00000080 /* R/WC */
+/*#define INT_STS_RXDF 0x00000040*/ /* R/WC */
+#define INT_STS_RDFO 0x00000040 /* R/WC */
+#define INT_STS_RDFL 0x00000020 /* R/WC */
+#define INT_STS_RSFF 0x00000010 /* R/WC */
+#define INT_STS_RSFL 0x00000008 /* R/WC */
+#define INT_STS_GPIO2_INT 0x00000004 /* R/WC */
+#define INT_STS_GPIO1_INT 0x00000002 /* R/WC */
+#define INT_STS_GPIO0_INT 0x00000001 /* R/WC */
+#define INT_EN (CONFIG_DRIVER_SMC911X_BASE + 0x5C)
+#define INT_EN_SW_INT_EN 0x80000000 /* R/W */
+#define INT_EN_TXSTOP_INT_EN 0x02000000 /* R/W */
+#define INT_EN_RXSTOP_INT_EN 0x01000000 /* R/W */
+#define INT_EN_RXDFH_INT_EN 0x00800000 /* R/W */
+/*#define INT_EN_RXDF_INT_EN 0x00400000*/ /* R/W */
+#define INT_EN_TIOC_INT_EN 0x00200000 /* R/W */
+#define INT_EN_RXD_INT_EN 0x00100000 /* R/W */
+#define INT_EN_GPT_INT_EN 0x00080000 /* R/W */
+#define INT_EN_PHY_INT_EN 0x00040000 /* R/W */
+#define INT_EN_PME_INT_EN 0x00020000 /* R/W */
+#define INT_EN_TXSO_EN 0x00010000 /* R/W */
+#define INT_EN_RWT_EN 0x00008000 /* R/W */
+#define INT_EN_RXE_EN 0x00004000 /* R/W */
+#define INT_EN_TXE_EN 0x00002000 /* R/W */
+/*#define INT_EN_ERX_EN 0x00001000*/ /* R/W */
+#define INT_EN_TDFU_EN 0x00000800 /* R/W */
+#define INT_EN_TDFO_EN 0x00000400 /* R/W */
+#define INT_EN_TDFA_EN 0x00000200 /* R/W */
+#define INT_EN_TSFF_EN 0x00000100 /* R/W */
+#define INT_EN_TSFL_EN 0x00000080 /* R/W */
+/*#define INT_EN_RXDF_EN 0x00000040*/ /* R/W */
+#define INT_EN_RDFO_EN 0x00000040 /* R/W */
+#define INT_EN_RDFL_EN 0x00000020 /* R/W */
+#define INT_EN_RSFF_EN 0x00000010 /* R/W */
+#define INT_EN_RSFL_EN 0x00000008 /* R/W */
+#define INT_EN_GPIO2_INT 0x00000004 /* R/W */
+#define INT_EN_GPIO1_INT 0x00000002 /* R/W */
+#define INT_EN_GPIO0_INT 0x00000001 /* R/W */
+
+#define BYTE_TEST (CONFIG_DRIVER_SMC911X_BASE + 0x64)
+#define FIFO_INT (CONFIG_DRIVER_SMC911X_BASE + 0x68)
+#define FIFO_INT_TX_AVAIL_LEVEL 0xFF000000 /* R/W */
+#define FIFO_INT_TX_STS_LEVEL 0x00FF0000 /* R/W */
+#define FIFO_INT_RX_AVAIL_LEVEL 0x0000FF00 /* R/W */
+#define FIFO_INT_RX_STS_LEVEL 0x000000FF /* R/W */
+
+#define RX_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x6C)
+#define RX_CFG_RX_END_ALGN 0xC0000000 /* R/W */
+#define RX_CFG_RX_END_ALGN4 0x00000000 /* R/W */
+#define RX_CFG_RX_END_ALGN16 0x40000000 /* R/W */
+#define RX_CFG_RX_END_ALGN32 0x80000000 /* R/W */
+#define RX_CFG_RX_DMA_CNT 0x0FFF0000 /* R/W */
+#define RX_CFG_RX_DUMP 0x00008000 /* R/W */
+#define RX_CFG_RXDOFF 0x00001F00 /* R/W */
+/*#define RX_CFG_RXBAD 0x00000001*/ /* R/W */
+
+#define TX_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x70)
+/*#define TX_CFG_TX_DMA_LVL 0xE0000000*/ /* R/W */
+/*#define TX_CFG_TX_DMA_CNT 0x0FFF0000*/ /* R/W Self Clearing */
+#define TX_CFG_TXS_DUMP 0x00008000 /* Self Clearing */
+#define TX_CFG_TXD_DUMP 0x00004000 /* Self Clearing */
+#define TX_CFG_TXSAO 0x00000004 /* R/W */
+#define TX_CFG_TX_ON 0x00000002 /* R/W */
+#define TX_CFG_STOP_TX 0x00000001 /* Self Clearing */
+
+#define HW_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x74)
+#define HW_CFG_TTM 0x00200000 /* R/W */
+#define HW_CFG_SF 0x00100000 /* R/W */
+#define HW_CFG_TX_FIF_SZ 0x000F0000 /* R/W */
+#define HW_CFG_TR 0x00003000 /* R/W */
+#define HW_CFG_PHY_CLK_SEL 0x00000060 /* R/W */
+#define HW_CFG_PHY_CLK_SEL_INT_PHY 0x00000000 /* R/W */
+#define HW_CFG_PHY_CLK_SEL_EXT_PHY 0x00000020 /* R/W */
+#define HW_CFG_PHY_CLK_SEL_CLK_DIS 0x00000040 /* R/W */
+#define HW_CFG_SMI_SEL 0x00000010 /* R/W */
+#define HW_CFG_EXT_PHY_DET 0x00000008 /* RO */
+#define HW_CFG_EXT_PHY_EN 0x00000004 /* R/W */
+#define HW_CFG_32_16_BIT_MODE 0x00000004 /* RO */
+#define HW_CFG_SRST_TO 0x00000002 /* RO */
+#define HW_CFG_SRST 0x00000001 /* Self Clearing */
+
+#define RX_DP_CTRL (CONFIG_DRIVER_SMC911X_BASE + 0x78)
+#define RX_DP_CTRL_RX_FFWD 0x80000000 /* R/W */
+#define RX_DP_CTRL_FFWD_BUSY 0x80000000 /* RO */
+
+#define RX_FIFO_INF (CONFIG_DRIVER_SMC911X_BASE + 0x7C)
+#define RX_FIFO_INF_RXSUSED 0x00FF0000 /* RO */
+#define RX_FIFO_INF_RXDUSED 0x0000FFFF /* RO */
+
+#define TX_FIFO_INF (CONFIG_DRIVER_SMC911X_BASE + 0x80)
+#define TX_FIFO_INF_TSUSED 0x00FF0000 /* RO */
+#define TX_FIFO_INF_TDFREE 0x0000FFFF /* RO */
+
+#define PMT_CTRL (CONFIG_DRIVER_SMC911X_BASE + 0x84)
+#define PMT_CTRL_PM_MODE 0x00003000 /* Self Clearing */
+#define PMT_CTRL_PHY_RST 0x00000400 /* Self Clearing */
+#define PMT_CTRL_WOL_EN 0x00000200 /* R/W */
+#define PMT_CTRL_ED_EN 0x00000100 /* R/W */
+#define PMT_CTRL_PME_TYPE 0x00000040 /* R/W Not Affected by SW Reset */
+#define PMT_CTRL_WUPS 0x00000030 /* R/WC */
+#define PMT_CTRL_WUPS_NOWAKE 0x00000000 /* R/WC */
+#define PMT_CTRL_WUPS_ED 0x00000010 /* R/WC */
+#define PMT_CTRL_WUPS_WOL 0x00000020 /* R/WC */
+#define PMT_CTRL_WUPS_MULTI 0x00000030 /* R/WC */
+#define PMT_CTRL_PME_IND 0x00000008 /* R/W */
+#define PMT_CTRL_PME_POL 0x00000004 /* R/W */
+#define PMT_CTRL_PME_EN 0x00000002 /* R/W Not Affected by SW Reset */
+#define PMT_CTRL_READY 0x00000001 /* RO */
+
+#define GPIO_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x88)
+#define GPIO_CFG_LED3_EN 0x40000000 /* R/W */
+#define GPIO_CFG_LED2_EN 0x20000000 /* R/W */
+#define GPIO_CFG_LED1_EN 0x10000000 /* R/W */
+#define GPIO_CFG_GPIO2_INT_POL 0x04000000 /* R/W */
+#define GPIO_CFG_GPIO1_INT_POL 0x02000000 /* R/W */
+#define GPIO_CFG_GPIO0_INT_POL 0x01000000 /* R/W */
+#define GPIO_CFG_EEPR_EN 0x00700000 /* R/W */
+#define GPIO_CFG_GPIOBUF2 0x00040000 /* R/W */
+#define GPIO_CFG_GPIOBUF1 0x00020000 /* R/W */
+#define GPIO_CFG_GPIOBUF0 0x00010000 /* R/W */
+#define GPIO_CFG_GPIODIR2 0x00000400 /* R/W */
+#define GPIO_CFG_GPIODIR1 0x00000200 /* R/W */
+#define GPIO_CFG_GPIODIR0 0x00000100 /* R/W */
+#define GPIO_CFG_GPIOD4 0x00000010 /* R/W */
+#define GPIO_CFG_GPIOD3 0x00000008 /* R/W */
+#define GPIO_CFG_GPIOD2 0x00000004 /* R/W */
+#define GPIO_CFG_GPIOD1 0x00000002 /* R/W */
+#define GPIO_CFG_GPIOD0 0x00000001 /* R/W */
+
+#define GPT_CFG (CONFIG_DRIVER_SMC911X_BASE + 0x8C)
+#define GPT_CFG_TIMER_EN 0x20000000 /* R/W */
+#define GPT_CFG_GPT_LOAD 0x0000FFFF /* R/W */
+
+#define GPT_CNT (CONFIG_DRIVER_SMC911X_BASE + 0x90)
+#define GPT_CNT_GPT_CNT 0x0000FFFF /* RO */
+
+#define ENDIAN (CONFIG_DRIVER_SMC911X_BASE + 0x98)
+#define FREE_RUN (CONFIG_DRIVER_SMC911X_BASE + 0x9C)
+#define RX_DROP (CONFIG_DRIVER_SMC911X_BASE + 0xA0)
+#define MAC_CSR_CMD (CONFIG_DRIVER_SMC911X_BASE + 0xA4)
+#define MAC_CSR_CMD_CSR_BUSY 0x80000000 /* Self Clearing */
+#define MAC_CSR_CMD_R_NOT_W 0x40000000 /* R/W */
+#define MAC_CSR_CMD_CSR_ADDR 0x000000FF /* R/W */
+
+#define MAC_CSR_DATA (CONFIG_DRIVER_SMC911X_BASE + 0xA8)
+#define AFC_CFG (CONFIG_DRIVER_SMC911X_BASE + 0xAC)
+#define AFC_CFG_AFC_HI 0x00FF0000 /* R/W */
+#define AFC_CFG_AFC_LO 0x0000FF00 /* R/W */
+#define AFC_CFG_BACK_DUR 0x000000F0 /* R/W */
+#define AFC_CFG_FCMULT 0x00000008 /* R/W */
+#define AFC_CFG_FCBRD 0x00000004 /* R/W */
+#define AFC_CFG_FCADD 0x00000002 /* R/W */
+#define AFC_CFG_FCANY 0x00000001 /* R/W */
+
+#define E2P_CMD (CONFIG_DRIVER_SMC911X_BASE + 0xB0)
+#define E2P_CMD_EPC_BUSY 0x80000000 /* Self Clearing */
+#define E2P_CMD_EPC_CMD 0x70000000 /* R/W */
+#define E2P_CMD_EPC_CMD_READ 0x00000000 /* R/W */
+#define E2P_CMD_EPC_CMD_EWDS 0x10000000 /* R/W */
+#define E2P_CMD_EPC_CMD_EWEN 0x20000000 /* R/W */
+#define E2P_CMD_EPC_CMD_WRITE 0x30000000 /* R/W */
+#define E2P_CMD_EPC_CMD_WRAL 0x40000000 /* R/W */
+#define E2P_CMD_EPC_CMD_ERASE 0x50000000 /* R/W */
+#define E2P_CMD_EPC_CMD_ERAL 0x60000000 /* R/W */
+#define E2P_CMD_EPC_CMD_RELOAD 0x70000000 /* R/W */
+#define E2P_CMD_EPC_TIMEOUT 0x00000200 /* RO */
+#define E2P_CMD_MAC_ADDR_LOADED 0x00000100 /* RO */
+#define E2P_CMD_EPC_ADDR 0x000000FF /* R/W */
+
+#define E2P_DATA (CONFIG_DRIVER_SMC911X_BASE + 0xB4)
+#define E2P_DATA_EEPROM_DATA 0x000000FF /* R/W */
+/* end of LAN register offsets and bit definitions */
+
+/* MAC Control and Status registers */
+#define MAC_CR 0x01 /* R/W */
+
+/* MAC_CR - MAC Control Register */
+#define MAC_CR_RXALL 0x80000000
+/* TODO: delete this bit? It is not described in the data sheet. */
+#define MAC_CR_HBDIS 0x10000000
+#define MAC_CR_RCVOWN 0x00800000
+#define MAC_CR_LOOPBK 0x00200000
+#define MAC_CR_FDPX 0x00100000
+#define MAC_CR_MCPAS 0x00080000
+#define MAC_CR_PRMS 0x00040000
+#define MAC_CR_INVFILT 0x00020000
+#define MAC_CR_PASSBAD 0x00010000
+#define MAC_CR_HFILT 0x00008000
+#define MAC_CR_HPFILT 0x00002000
+#define MAC_CR_LCOLL 0x00001000
+#define MAC_CR_BCAST 0x00000800
+#define MAC_CR_DISRTY 0x00000400
+#define MAC_CR_PADSTR 0x00000100
+#define MAC_CR_BOLMT_MASK 0x000000C0
+#define MAC_CR_DFCHK 0x00000020
+#define MAC_CR_TXEN 0x00000008
+#define MAC_CR_RXEN 0x00000004
+
+#define ADDRH 0x02 /* R/W mask 0x0000FFFFUL */
+#define ADDRL 0x03 /* R/W mask 0xFFFFFFFFUL */
+#define HASHH 0x04 /* R/W */
+#define HASHL 0x05 /* R/W */
+
+#define MII_ACC 0x06 /* R/W */
+#define MII_ACC_PHY_ADDR 0x0000F800
+#define MII_ACC_MIIRINDA 0x000007C0
+#define MII_ACC_MII_WRITE 0x00000002
+#define MII_ACC_MII_BUSY 0x00000001
+
+#define MII_DATA 0x07 /* R/W mask 0x0000FFFFUL */
+
+#define FLOW 0x08 /* R/W */
+#define FLOW_FCPT 0xFFFF0000
+#define FLOW_FCPASS 0x00000004
+#define FLOW_FCEN 0x00000002
+#define FLOW_FCBSY 0x00000001
+
+#define VLAN1 0x09 /* R/W mask 0x0000FFFFUL */
+#define VLAN1_VTI1 0x0000ffff
+
+#define VLAN2 0x0A /* R/W mask 0x0000FFFFUL */
+#define VLAN2_VTI2 0x0000ffff
+
+#define WUFF 0x0B /* WO */
+
+#define WUCSR 0x0C /* R/W */
+#define WUCSR_GUE 0x00000200
+#define WUCSR_WUFR 0x00000040
+#define WUCSR_MPR 0x00000020
+#define WUCSR_WAKE_EN 0x00000004
+#define WUCSR_MPEN 0x00000002
+
+/* Chip ID values */
+#define CHIP_9115 0x115
+#define CHIP_9116 0x116
+#define CHIP_9117 0x117
+#define CHIP_9118 0x118
+#define CHIP_9215 0x115a
+#define CHIP_9216 0x116a
+#define CHIP_9217 0x117a
+#define CHIP_9218 0x118a
+
+struct chip_id {
+ u16 id;
+ char *name;
+};
+
+static const struct chip_id chip_ids[] = {
+ { CHIP_9115, "LAN9115" },
+ { CHIP_9116, "LAN9116" },
+ { CHIP_9117, "LAN9117" },
+ { CHIP_9118, "LAN9118" },
+ { CHIP_9215, "LAN9215" },
+ { CHIP_9216, "LAN9216" },
+ { CHIP_9217, "LAN9217" },
+ { CHIP_9218, "LAN9218" },
+ { 0, NULL },
+};
+
+#define DRIVERNAME "smc911x"
+
+static u32 smc911x_get_mac_csr(u8 reg)
+{
+ while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ ;
+ reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
+ while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ ;
+
+ return reg_read(MAC_CSR_DATA);
+}
+
+static void smc911x_set_mac_csr(u8 reg, u32 data)
+{
+ while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ ;
+ reg_write(MAC_CSR_DATA, data);
+ reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
+ while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ ;
+}
+
+static bool smc911x_detect_chip(void)
+{
+ unsigned long val, i;
+
+ val = reg_read(BYTE_TEST);
+ if (val != 0x87654321) {
+ printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
+ return false;
+ }
+
+ val = reg_read(ID_REV) >> 16;
+ for (i = 0; chip_ids[i].id != 0; i++) {
+ if (chip_ids[i].id == val) break;
+ }
+ if (!chip_ids[i].id) {
+ printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);
+ return false;
+ }
+
+ printf(DRIVERNAME ": detected %s controller\n", chip_ids[i].name);
+
+ return true;
+}
+
+static void smc911x_reset(void)
+{
+ int timeout;
+
+ /* Take out of PM setting first */
+ if (reg_read(PMT_CTRL) & PMT_CTRL_READY) {
+ /* Write to the bytetest will take out of powerdown */
+ reg_write(BYTE_TEST, 0x0);
+
+ timeout = 10;
+
+ while (timeout-- && !(reg_read(PMT_CTRL) & PMT_CTRL_READY))
+ udelay(10);
+ if (!timeout) {
+ printf(DRIVERNAME
+ ": timeout waiting for PM restore\n");
+ return;
+ }
+ }
+
+ /* Disable interrupts */
+ reg_write(INT_EN, 0);
+
+ reg_write(HW_CFG, HW_CFG_SRST);
+
+ timeout = 1000;
+ while (timeout-- && reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY)
+ udelay(10);
+
+ if (!timeout) {
+ printf(DRIVERNAME ": reset timeout\n");
+ return;
+ }
+
+ /* Reset the FIFO level and flow control settings */
+ smc911x_set_mac_csr(FLOW, FLOW_FCPT | FLOW_FCEN);
+ reg_write(AFC_CFG, 0x0050287F);
+
+ /* Set to LED outputs */
+ reg_write(GPIO_CFG, 0x70070000);
+}
+
+#endif
diff --git a/examples/.gitignore b/examples/.gitignore
index 806425f..0d1864c 100644
--- a/examples/.gitignore
+++ b/examples/.gitignore
@@ -6,5 +6,6 @@
/timer
/sched
/smc91111_eeprom
+/smc911x_eeprom
*.bin
*.srec
diff --git a/examples/Makefile b/examples/Makefile
index b0a8853..962ca8a 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -101,9 +101,10 @@ BIN += sched.bin
endif
ifeq ($(ARCH),blackfin)
-ELF += smc91111_eeprom
-SREC += smc91111_eeprom.srec
-BIN += smc91111_eeprom.bin
+BFIN_BIN = smc91111_eeprom smc911x_eeprom
+ELF += $(BFIN_BIN)
+SREC += $(addsuffix .srec,$(BFIN_BIN))
+BIN += $(addsuffix .bin,$(BFIN_BIN))
endif
# The following example is pretty 8xx specific...
diff --git a/examples/smc911x_eeprom.c b/examples/smc911x_eeprom.c
new file mode 100644
index 0000000..3dac4d3
--- /dev/null
+++ b/examples/smc911x_eeprom.c
@@ -0,0 +1,381 @@
+/*
+ * smc911x_eeprom.c - EEPROM interface to SMC911x parts.
+ * Only tested on SMSC9118 though ...
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ * Based on smc91111_eeprom.c which:
+ * Heavily borrowed from the following peoples GPL'ed software:
+ * - Wolfgang Denk, DENX Software Engineering, wd at denx.de
+ * Das U-boot
+ * - Ladislav Michl ladis at linux-mips.org
+ * A rejected patch on the U-Boot mailing list
+ */
+
+#include <common.h>
+#include <exports.h>
+
+#ifdef CONFIG_DRIVER_SMC911X
+
+#include "../drivers/net/smc911x.h"
+
+/**
+ * smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?)
+ */
+static int smsc_ctrlc(void)
+{
+ return (tstc() && getc() == 0x03);
+}
+
+/**
+ * usage - dump usage information
+ */
+static void usage(void)
+{
+ puts(
+ "MAC/EEPROM Commands:\n"
+ " P : Print the MAC addresses\n"
+ " D : Dump the EEPROM contents\n"
+ " M : Dump the MAC contents\n"
+ " C : Copy the MAC address from the EEPROM to the MAC\n"
+ " W : Write a register in the EEPROM or in the MAC\n"
+ " Q : Quit\n"
+ "\n"
+ "Some commands take arguments:\n"
+ " W <E|M> <register> <value>\n"
+ " E: EEPROM M: MAC\n"
+ );
+}
+
+/**
+ * dump_regs - dump the MAC registers
+ *
+ * Registers 0x00 - 0x50 are FIFOs. The 0x50+ are the control registers
+ * and they're all 32bits long. 0xB8+ are reserved, so don't bother.
+ */
+static void dump_regs(void)
+{
+ u8 i, j = 0;
+ for (i = 0x50; i < 0xB8; i += sizeof(u32))
+ printf("%02x: 0x%08x %c", i, reg_read(CONFIG_DRIVER_SMC911X_BASE + i),
+ (j++ % 2 ? '\n' : ' '));
+}
+
+/**
+ * do_eeprom_cmd - handle eeprom communication
+ */
+static int do_eeprom_cmd(int cmd, u8 reg)
+{
+ if (reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY) {
+ printf("eeprom_cmd: busy at start (E2P_CMD = 0x%08x)\n",
+ reg_read(E2P_CMD));
+ return -1;
+ }
+
+ reg_write(E2P_CMD, E2P_CMD_EPC_BUSY | cmd | reg);
+
+ while (reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY)
+ if (smsc_ctrlc()) {
+ printf("eeprom_cmd: timeout (E2P_CMD = 0x%08x)\n",
+ reg_read(E2P_CMD));
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * read_eeprom_reg - read specified register in EEPROM
+ */
+static u8 read_eeprom_reg(u8 reg)
+{
+ int ret = do_eeprom_cmd(E2P_CMD_EPC_CMD_READ, reg);
+ return (ret ? : reg_read(E2P_DATA));
+}
+
+/**
+ * write_eeprom_reg - write specified value into specified register in EEPROM
+ */
+static int write_eeprom_reg(u8 value, u8 reg)
+{
+ int ret;
+
+ /* enable erasing/writing */
+ ret = do_eeprom_cmd(E2P_CMD_EPC_CMD_EWEN, reg);
+ if (ret)
+ goto done;
+
+ /* erase the eeprom reg */
+ ret = do_eeprom_cmd(E2P_CMD_EPC_CMD_ERASE, reg);
+ if (ret)
+ goto done;
+
+ /* write the eeprom reg */
+ reg_write(E2P_DATA, value);
+ ret = do_eeprom_cmd(E2P_CMD_EPC_CMD_WRITE, reg);
+ if (ret)
+ goto done;
+
+ /* disable erasing/writing */
+ ret = do_eeprom_cmd(E2P_CMD_EPC_CMD_EWDS, reg);
+
+ done:
+ return ret;
+}
+
+/**
+ * skip_space - find first non-whitespace in given pointer
+ */
+static char *skip_space(char *buf)
+{
+ while (buf[0] == ' ' || buf[0] == '\t')
+ ++buf;
+ return buf;
+}
+
+/**
+ * write_stuff - handle writing of MAC registers / eeprom
+ */
+static void write_stuff(char *line)
+{
+ char dest;
+ char *endp;
+ u8 reg;
+ u32 value;
+
+ /* Skip over the "W " part of the command */
+ line = skip_space(line + 1);
+
+ /* Figure out destination */
+ switch (line[0]) {
+ case 'E':
+ case 'M':
+ dest = line[0];
+ break;
+ default:
+ invalid_usage:
+ printf("ERROR: Invalid write usage\n");
+ usage();
+ return;
+ }
+
+ /* Get the register to write */
+ line = skip_space(line + 1);
+ reg = simple_strtoul(line, &endp, 16);
+ if (line == endp)
+ goto invalid_usage;
+
+ /* Get the value to write */
+ line = skip_space(endp);
+ value = simple_strtoul(line, &endp, 16);
+ if (line == endp)
+ goto invalid_usage;
+
+ /* Check for trailing cruft */
+ line = skip_space(endp);
+ if (line[0])
+ goto invalid_usage;
+
+ /* Finally, execute the command */
+ if (dest == 'E') {
+ printf("Writing EEPROM register %02x with %02x\n", reg, value);
+ write_eeprom_reg(value, reg);
+ } else {
+ printf("Writing MAC register %02x with %08x\n", reg, value);
+ reg_write(CONFIG_DRIVER_SMC911X_BASE + reg, value);
+ }
+}
+
+/**
+ * copy_from_eeprom - copy MAC address in eeprom to address registers
+ */
+static void copy_from_eeprom(void)
+{
+ ulong addrl =
+ read_eeprom_reg(0x01) |
+ read_eeprom_reg(0x02) << 8 |
+ read_eeprom_reg(0x03) << 16 |
+ read_eeprom_reg(0x04) << 24;
+ ulong addrh =
+ read_eeprom_reg(0x05) |
+ read_eeprom_reg(0x06) << 8;
+ smc911x_set_mac_csr(ADDRL, addrl);
+ smc911x_set_mac_csr(ADDRH, addrh);
+ puts("EEPROM contents copied to MAC\n");
+}
+
+/**
+ * print_macaddr - print MAC address registers and MAC address in eeprom
+ */
+static void print_macaddr(void)
+{
+ puts("Current MAC Address in MAC: ");
+ ulong addrl = smc911x_get_mac_csr(ADDRL);
+ ulong addrh = smc911x_get_mac_csr(ADDRH);
+ printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+ (u8)(addrl), (u8)(addrl >> 8), (u8)(addrl >> 16),
+ (u8)(addrl >> 24), (u8)(addrh), (u8)(addrh >> 8));
+
+ puts("Current MAC Address in EEPROM: ");
+ int i;
+ for (i = 1; i < 6; ++i)
+ printf("%02x:", read_eeprom_reg(i));
+ printf("%02x\n", read_eeprom_reg(i));
+}
+
+/**
+ * dump_eeprom - dump the whole content of the EEPROM
+ */
+static void dump_eeprom(void)
+{
+ int i;
+ puts("EEPROM:\n");
+ for (i = 0; i < 7; ++i)
+ printf("%02x: 0x%02x\n", i, read_eeprom_reg(i));
+}
+
+/**
+ * smc911x_init - get the MAC/EEPROM up and ready for use
+ */
+static int smc911x_init(void)
+{
+ /* See if there is anything there */
+ if (!smc911x_detect_chip())
+ return 1;
+
+ smc911x_reset();
+
+ /* Make sure we set EEDIO/EECLK to the EEPROM */
+ if (reg_read(GPIO_CFG) & GPIO_CFG_EEPR_EN) {
+ while (reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY)
+ if (smsc_ctrlc()) {
+ printf("init: timeout (E2P_CMD = 0x%08x)\n", reg_read(E2P_CMD));
+ return 1;
+ }
+ reg_write(GPIO_CFG, reg_read(GPIO_CFG) & ~GPIO_CFG_EEPR_EN);
+ }
+
+ return 0;
+}
+
+/**
+ * getline - consume a line of input and handle some escape sequences
+ */
+static char *getline(void)
+{
+ static char buffer[100];
+ char c;
+ size_t i;
+
+ i = 0;
+ while (1) {
+ buffer[i] = '\0';
+ while (!tstc())
+ continue;
+
+ c = getc();
+ /* Convert to uppercase */
+ if (c >= 'a' && c <= 'z')
+ c -= ('a' - 'A');
+
+ switch (c) {
+ case '\r': /* Enter/Return key */
+ case '\n':
+ puts("\n");
+ return buffer;
+
+ case 0x03: /* ^C - break */
+ return NULL;
+
+ case 0x5F:
+ case 0x08: /* ^H - backspace */
+ case 0x7F: /* DEL - backspace */
+ if (i) {
+ puts("\b \b");
+ i--;
+ }
+ break;
+
+ default:
+ /* Ignore control characters */
+ if (c < 0x20)
+ break;
+ /* Queue up all other characters */
+ buffer[i++] = c;
+ printf("%c", c);
+ break;
+ }
+ }
+}
+
+/**
+ * smc911x_eeprom - our application's main() function
+ */
+int smc911x_eeprom(int argc, char *argv[])
+{
+ /* Print the ABI version */
+ app_startup(argv);
+ if (XF_VERSION != get_version()) {
+ printf("Expects ABI version %d\n", XF_VERSION);
+ printf("Actual U-Boot ABI version %lu\n", get_version());
+ printf("Can't run\n\n");
+ return 1;
+ }
+
+ /* Initialize the MAC/EEPROM somewhat */
+ puts("\n");
+ if (smc911x_init())
+ return 1;
+
+ /* Dump helpful usage information */
+ puts("\n");
+ usage();
+ puts("\n");
+
+ while (1) {
+ char *line;
+
+ /* Send the prompt and wait for a line */
+ puts("eeprom> ");
+ line = getline();
+
+ /* Got a ctrl+c */
+ if (!line)
+ return 0;
+
+ /* Eat leading space */
+ line = skip_space(line);
+
+ /* Empty line, try again */
+ if (!line[0])
+ continue;
+
+ /* Only accept 1 letter commands */
+ if (line[0] && line[1] && line[1] != ' ' && line[1] != '\t')
+ goto unknown_cmd;
+
+ /* Now parse the command */
+ switch (line[0]) {
+ case 'W': write_stuff(line); break;
+ case 'D': dump_eeprom(); break;
+ case 'M': dump_regs(); break;
+ case 'C': copy_from_eeprom(); break;
+ case 'P': print_macaddr(); break;
+ unknown_cmd:
+ default: puts("ERROR: Unknown command!\n\n");
+ case '?':
+ case 'H': usage(); break;
+ case 'Q': return 0;
+ }
+ }
+}
+
+#else
+int smc911x_eeprom(int argc, char *argv[])
+{
+ puts("Not supported for this board\n");
+ return 1;
+}
+#endif
--
1.6.0.4
More information about the U-Boot
mailing list