1*de1b686bSSascha Hauer /* 2*de1b686bSSascha Hauer * SMSC LAN9[12]1[567] Network driver 3*de1b686bSSascha Hauer * 4*de1b686bSSascha Hauer * (c) 2007 Pengutronix, Sascha Hauer <s.hauer <at> pengutronix.de> 5*de1b686bSSascha Hauer * 6*de1b686bSSascha Hauer * See file CREDITS for list of people who contributed to this 7*de1b686bSSascha Hauer * project. 8*de1b686bSSascha Hauer * 9*de1b686bSSascha Hauer * This program is free software; you can redistribute it and/or 10*de1b686bSSascha Hauer * modify it under the terms of the GNU General Public License as 11*de1b686bSSascha Hauer * published by the Free Software Foundation; either version 2 of 12*de1b686bSSascha Hauer * the License, or (at your option) any later version. 13*de1b686bSSascha Hauer * 14*de1b686bSSascha Hauer * This program is distributed in the hope that it will be useful, 15*de1b686bSSascha Hauer * but WITHOUT ANY WARRANTY; without even the implied warranty of 16*de1b686bSSascha Hauer * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*de1b686bSSascha Hauer * GNU General Public License for more details. 18*de1b686bSSascha Hauer * 19*de1b686bSSascha Hauer * You should have received a copy of the GNU General Public License 20*de1b686bSSascha Hauer * along with this program; if not, write to the Free Software 21*de1b686bSSascha Hauer * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22*de1b686bSSascha Hauer * MA 02111-1307 USA 23*de1b686bSSascha Hauer */ 24*de1b686bSSascha Hauer 25*de1b686bSSascha Hauer #include <common.h> 26*de1b686bSSascha Hauer 27*de1b686bSSascha Hauer #ifdef CONFIG_DRIVER_SMC911X 28*de1b686bSSascha Hauer 29*de1b686bSSascha Hauer #include <command.h> 30*de1b686bSSascha Hauer #include <net.h> 31*de1b686bSSascha Hauer #include <miiphy.h> 32*de1b686bSSascha Hauer 33*de1b686bSSascha Hauer #define mdelay(n) udelay((n)*1000) 34*de1b686bSSascha Hauer 35*de1b686bSSascha Hauer #define __REG(x) (*((volatile u32 *)(x))) 36*de1b686bSSascha Hauer 37*de1b686bSSascha Hauer /* Below are the register offsets and bit definitions 38*de1b686bSSascha Hauer * of the Lan911x memory space 39*de1b686bSSascha Hauer */ 40*de1b686bSSascha Hauer #define RX_DATA_FIFO __REG(CONFIG_DRIVER_SMC911X_BASE + 0x00) 41*de1b686bSSascha Hauer 42*de1b686bSSascha Hauer #define TX_DATA_FIFO __REG(CONFIG_DRIVER_SMC911X_BASE + 0x20) 43*de1b686bSSascha Hauer #define TX_CMD_A_INT_ON_COMP (0x80000000) 44*de1b686bSSascha Hauer #define TX_CMD_A_INT_BUF_END_ALGN (0x03000000) 45*de1b686bSSascha Hauer #define TX_CMD_A_INT_4_BYTE_ALGN (0x00000000) 46*de1b686bSSascha Hauer #define TX_CMD_A_INT_16_BYTE_ALGN (0x01000000) 47*de1b686bSSascha Hauer #define TX_CMD_A_INT_32_BYTE_ALGN (0x02000000) 48*de1b686bSSascha Hauer #define TX_CMD_A_INT_DATA_OFFSET (0x001F0000) 49*de1b686bSSascha Hauer #define TX_CMD_A_INT_FIRST_SEG (0x00002000) 50*de1b686bSSascha Hauer #define TX_CMD_A_INT_LAST_SEG (0x00001000) 51*de1b686bSSascha Hauer #define TX_CMD_A_BUF_SIZE (0x000007FF) 52*de1b686bSSascha Hauer #define TX_CMD_B_PKT_TAG (0xFFFF0000) 53*de1b686bSSascha Hauer #define TX_CMD_B_ADD_CRC_DISABLE (0x00002000) 54*de1b686bSSascha Hauer #define TX_CMD_B_DISABLE_PADDING (0x00001000) 55*de1b686bSSascha Hauer #define TX_CMD_B_PKT_BYTE_LENGTH (0x000007FF) 56*de1b686bSSascha Hauer 57*de1b686bSSascha Hauer #define RX_STATUS_FIFO __REG(CONFIG_DRIVER_SMC911X_BASE + 0x40) 58*de1b686bSSascha Hauer #define RX_STS_PKT_LEN (0x3FFF0000) 59*de1b686bSSascha Hauer #define RX_STS_ES (0x00008000) 60*de1b686bSSascha Hauer #define RX_STS_BCST (0x00002000) 61*de1b686bSSascha Hauer #define RX_STS_LEN_ERR (0x00001000) 62*de1b686bSSascha Hauer #define RX_STS_RUNT_ERR (0x00000800) 63*de1b686bSSascha Hauer #define RX_STS_MCAST (0x00000400) 64*de1b686bSSascha Hauer #define RX_STS_TOO_LONG (0x00000080) 65*de1b686bSSascha Hauer #define RX_STS_COLL (0x00000040) 66*de1b686bSSascha Hauer #define RX_STS_ETH_TYPE (0x00000020) 67*de1b686bSSascha Hauer #define RX_STS_WDOG_TMT (0x00000010) 68*de1b686bSSascha Hauer #define RX_STS_MII_ERR (0x00000008) 69*de1b686bSSascha Hauer #define RX_STS_DRIBBLING (0x00000004) 70*de1b686bSSascha Hauer #define RX_STS_CRC_ERR (0x00000002) 71*de1b686bSSascha Hauer #define RX_STATUS_FIFO_PEEK __REG(CONFIG_DRIVER_SMC911X_BASE + 0x44) 72*de1b686bSSascha Hauer #define TX_STATUS_FIFO __REG(CONFIG_DRIVER_SMC911X_BASE + 0x48) 73*de1b686bSSascha Hauer #define TX_STS_TAG (0xFFFF0000) 74*de1b686bSSascha Hauer #define TX_STS_ES (0x00008000) 75*de1b686bSSascha Hauer #define TX_STS_LOC (0x00000800) 76*de1b686bSSascha Hauer #define TX_STS_NO_CARR (0x00000400) 77*de1b686bSSascha Hauer #define TX_STS_LATE_COLL (0x00000200) 78*de1b686bSSascha Hauer #define TX_STS_MANY_COLL (0x00000100) 79*de1b686bSSascha Hauer #define TX_STS_COLL_CNT (0x00000078) 80*de1b686bSSascha Hauer #define TX_STS_MANY_DEFER (0x00000004) 81*de1b686bSSascha Hauer #define TX_STS_UNDERRUN (0x00000002) 82*de1b686bSSascha Hauer #define TX_STS_DEFERRED (0x00000001) 83*de1b686bSSascha Hauer #define TX_STATUS_FIFO_PEEK __REG(CONFIG_DRIVER_SMC911X_BASE + 0x4C) 84*de1b686bSSascha Hauer #define ID_REV __REG(CONFIG_DRIVER_SMC911X_BASE + 0x50) 85*de1b686bSSascha Hauer #define ID_REV_CHIP_ID (0xFFFF0000) /* RO */ 86*de1b686bSSascha Hauer #define ID_REV_REV_ID (0x0000FFFF) /* RO */ 87*de1b686bSSascha Hauer 88*de1b686bSSascha Hauer #define INT_CFG __REG(CONFIG_DRIVER_SMC911X_BASE + 0x54) 89*de1b686bSSascha Hauer #define INT_CFG_INT_DEAS (0xFF000000) /* R/W */ 90*de1b686bSSascha Hauer #define INT_CFG_INT_DEAS_CLR (0x00004000) 91*de1b686bSSascha Hauer #define INT_CFG_INT_DEAS_STS (0x00002000) 92*de1b686bSSascha Hauer #define INT_CFG_IRQ_INT (0x00001000) /* RO */ 93*de1b686bSSascha Hauer #define INT_CFG_IRQ_EN (0x00000100) /* R/W */ 94*de1b686bSSascha Hauer #define INT_CFG_IRQ_POL (0x00000010) /* R/W Not Affected by SW Reset */ 95*de1b686bSSascha Hauer #define INT_CFG_IRQ_TYPE (0x00000001) /* R/W Not Affected by SW Reset */ 96*de1b686bSSascha Hauer 97*de1b686bSSascha Hauer #define INT_STS __REG(CONFIG_DRIVER_SMC911X_BASE + 0x58) 98*de1b686bSSascha Hauer #define INT_STS_SW_INT (0x80000000) /* R/WC */ 99*de1b686bSSascha Hauer #define INT_STS_TXSTOP_INT (0x02000000) /* R/WC */ 100*de1b686bSSascha Hauer #define INT_STS_RXSTOP_INT (0x01000000) /* R/WC */ 101*de1b686bSSascha Hauer #define INT_STS_RXDFH_INT (0x00800000) /* R/WC */ 102*de1b686bSSascha Hauer #define INT_STS_RXDF_INT (0x00400000) /* R/WC */ 103*de1b686bSSascha Hauer #define INT_STS_TX_IOC (0x00200000) /* R/WC */ 104*de1b686bSSascha Hauer #define INT_STS_RXD_INT (0x00100000) /* R/WC */ 105*de1b686bSSascha Hauer #define INT_STS_GPT_INT (0x00080000) /* R/WC */ 106*de1b686bSSascha Hauer #define INT_STS_PHY_INT (0x00040000) /* RO */ 107*de1b686bSSascha Hauer #define INT_STS_PME_INT (0x00020000) /* R/WC */ 108*de1b686bSSascha Hauer #define INT_STS_TXSO (0x00010000) /* R/WC */ 109*de1b686bSSascha Hauer #define INT_STS_RWT (0x00008000) /* R/WC */ 110*de1b686bSSascha Hauer #define INT_STS_RXE (0x00004000) /* R/WC */ 111*de1b686bSSascha Hauer #define INT_STS_TXE (0x00002000) /* R/WC */ 112*de1b686bSSascha Hauer /*#define INT_STS_ERX (0x00001000)*/ /* R/WC */ 113*de1b686bSSascha Hauer #define INT_STS_TDFU (0x00000800) /* R/WC */ 114*de1b686bSSascha Hauer #define INT_STS_TDFO (0x00000400) /* R/WC */ 115*de1b686bSSascha Hauer #define INT_STS_TDFA (0x00000200) /* R/WC */ 116*de1b686bSSascha Hauer #define INT_STS_TSFF (0x00000100) /* R/WC */ 117*de1b686bSSascha Hauer #define INT_STS_TSFL (0x00000080) /* R/WC */ 118*de1b686bSSascha Hauer /*#define INT_STS_RXDF (0x00000040)*/ /* R/WC */ 119*de1b686bSSascha Hauer #define INT_STS_RDFO (0x00000040) /* R/WC */ 120*de1b686bSSascha Hauer #define INT_STS_RDFL (0x00000020) /* R/WC */ 121*de1b686bSSascha Hauer #define INT_STS_RSFF (0x00000010) /* R/WC */ 122*de1b686bSSascha Hauer #define INT_STS_RSFL (0x00000008) /* R/WC */ 123*de1b686bSSascha Hauer #define INT_STS_GPIO2_INT (0x00000004) /* R/WC */ 124*de1b686bSSascha Hauer #define INT_STS_GPIO1_INT (0x00000002) /* R/WC */ 125*de1b686bSSascha Hauer #define INT_STS_GPIO0_INT (0x00000001) /* R/WC */ 126*de1b686bSSascha Hauer #define INT_EN __REG(CONFIG_DRIVER_SMC911X_BASE + 0x5C) 127*de1b686bSSascha Hauer #define INT_EN_SW_INT_EN (0x80000000) /* R/W */ 128*de1b686bSSascha Hauer #define INT_EN_TXSTOP_INT_EN (0x02000000) /* R/W */ 129*de1b686bSSascha Hauer #define INT_EN_RXSTOP_INT_EN (0x01000000) /* R/W */ 130*de1b686bSSascha Hauer #define INT_EN_RXDFH_INT_EN (0x00800000) /* R/W */ 131*de1b686bSSascha Hauer /*#define INT_EN_RXDF_INT_EN (0x00400000)*/ /* R/W */ 132*de1b686bSSascha Hauer #define INT_EN_TIOC_INT_EN (0x00200000) /* R/W */ 133*de1b686bSSascha Hauer #define INT_EN_RXD_INT_EN (0x00100000) /* R/W */ 134*de1b686bSSascha Hauer #define INT_EN_GPT_INT_EN (0x00080000) /* R/W */ 135*de1b686bSSascha Hauer #define INT_EN_PHY_INT_EN (0x00040000) /* R/W */ 136*de1b686bSSascha Hauer #define INT_EN_PME_INT_EN (0x00020000) /* R/W */ 137*de1b686bSSascha Hauer #define INT_EN_TXSO_EN (0x00010000) /* R/W */ 138*de1b686bSSascha Hauer #define INT_EN_RWT_EN (0x00008000) /* R/W */ 139*de1b686bSSascha Hauer #define INT_EN_RXE_EN (0x00004000) /* R/W */ 140*de1b686bSSascha Hauer #define INT_EN_TXE_EN (0x00002000) /* R/W */ 141*de1b686bSSascha Hauer /*#define INT_EN_ERX_EN (0x00001000)*/ /* R/W */ 142*de1b686bSSascha Hauer #define INT_EN_TDFU_EN (0x00000800) /* R/W */ 143*de1b686bSSascha Hauer #define INT_EN_TDFO_EN (0x00000400) /* R/W */ 144*de1b686bSSascha Hauer #define INT_EN_TDFA_EN (0x00000200) /* R/W */ 145*de1b686bSSascha Hauer #define INT_EN_TSFF_EN (0x00000100) /* R/W */ 146*de1b686bSSascha Hauer #define INT_EN_TSFL_EN (0x00000080) /* R/W */ 147*de1b686bSSascha Hauer /*#define INT_EN_RXDF_EN (0x00000040)*/ /* R/W */ 148*de1b686bSSascha Hauer #define INT_EN_RDFO_EN (0x00000040) /* R/W */ 149*de1b686bSSascha Hauer #define INT_EN_RDFL_EN (0x00000020) /* R/W */ 150*de1b686bSSascha Hauer #define INT_EN_RSFF_EN (0x00000010) /* R/W */ 151*de1b686bSSascha Hauer #define INT_EN_RSFL_EN (0x00000008) /* R/W */ 152*de1b686bSSascha Hauer #define INT_EN_GPIO2_INT (0x00000004) /* R/W */ 153*de1b686bSSascha Hauer #define INT_EN_GPIO1_INT (0x00000002) /* R/W */ 154*de1b686bSSascha Hauer #define INT_EN_GPIO0_INT (0x00000001) /* R/W */ 155*de1b686bSSascha Hauer 156*de1b686bSSascha Hauer #define BYTE_TEST __REG(CONFIG_DRIVER_SMC911X_BASE + 0x64) 157*de1b686bSSascha Hauer #define FIFO_INT __REG(CONFIG_DRIVER_SMC911X_BASE + 0x68) 158*de1b686bSSascha Hauer #define FIFO_INT_TX_AVAIL_LEVEL (0xFF000000) /* R/W */ 159*de1b686bSSascha Hauer #define FIFO_INT_TX_STS_LEVEL (0x00FF0000) /* R/W */ 160*de1b686bSSascha Hauer #define FIFO_INT_RX_AVAIL_LEVEL (0x0000FF00) /* R/W */ 161*de1b686bSSascha Hauer #define FIFO_INT_RX_STS_LEVEL (0x000000FF) /* R/W */ 162*de1b686bSSascha Hauer 163*de1b686bSSascha Hauer #define RX_CFG __REG(CONFIG_DRIVER_SMC911X_BASE + 0x6C) 164*de1b686bSSascha Hauer #define RX_CFG_RX_END_ALGN (0xC0000000) /* R/W */ 165*de1b686bSSascha Hauer #define RX_CFG_RX_END_ALGN4 (0x00000000) /* R/W */ 166*de1b686bSSascha Hauer #define RX_CFG_RX_END_ALGN16 (0x40000000) /* R/W */ 167*de1b686bSSascha Hauer #define RX_CFG_RX_END_ALGN32 (0x80000000) /* R/W */ 168*de1b686bSSascha Hauer #define RX_CFG_RX_DMA_CNT (0x0FFF0000) /* R/W */ 169*de1b686bSSascha Hauer #define RX_CFG_RX_DUMP (0x00008000) /* R/W */ 170*de1b686bSSascha Hauer #define RX_CFG_RXDOFF (0x00001F00) /* R/W */ 171*de1b686bSSascha Hauer /*#define RX_CFG_RXBAD (0x00000001)*/ /* R/W */ 172*de1b686bSSascha Hauer 173*de1b686bSSascha Hauer #define TX_CFG __REG(CONFIG_DRIVER_SMC911X_BASE + 0x70) 174*de1b686bSSascha Hauer /*#define TX_CFG_TX_DMA_LVL (0xE0000000)*/ /* R/W */ 175*de1b686bSSascha Hauer /*#define TX_CFG_TX_DMA_CNT (0x0FFF0000)*/ /* R/W Self Clearing */ 176*de1b686bSSascha Hauer #define TX_CFG_TXS_DUMP (0x00008000) /* Self Clearing */ 177*de1b686bSSascha Hauer #define TX_CFG_TXD_DUMP (0x00004000) /* Self Clearing */ 178*de1b686bSSascha Hauer #define TX_CFG_TXSAO (0x00000004) /* R/W */ 179*de1b686bSSascha Hauer #define TX_CFG_TX_ON (0x00000002) /* R/W */ 180*de1b686bSSascha Hauer #define TX_CFG_STOP_TX (0x00000001) /* Self Clearing */ 181*de1b686bSSascha Hauer 182*de1b686bSSascha Hauer #define HW_CFG __REG(CONFIG_DRIVER_SMC911X_BASE + 0x74) 183*de1b686bSSascha Hauer #define HW_CFG_TTM (0x00200000) /* R/W */ 184*de1b686bSSascha Hauer #define HW_CFG_SF (0x00100000) /* R/W */ 185*de1b686bSSascha Hauer #define HW_CFG_TX_FIF_SZ (0x000F0000) /* R/W */ 186*de1b686bSSascha Hauer #define HW_CFG_TR (0x00003000) /* R/W */ 187*de1b686bSSascha Hauer #define HW_CFG_PHY_CLK_SEL (0x00000060) /* R/W */ 188*de1b686bSSascha Hauer #define HW_CFG_PHY_CLK_SEL_INT_PHY (0x00000000) /* R/W */ 189*de1b686bSSascha Hauer #define HW_CFG_PHY_CLK_SEL_EXT_PHY (0x00000020) /* R/W */ 190*de1b686bSSascha Hauer #define HW_CFG_PHY_CLK_SEL_CLK_DIS (0x00000040) /* R/W */ 191*de1b686bSSascha Hauer #define HW_CFG_SMI_SEL (0x00000010) /* R/W */ 192*de1b686bSSascha Hauer #define HW_CFG_EXT_PHY_DET (0x00000008) /* RO */ 193*de1b686bSSascha Hauer #define HW_CFG_EXT_PHY_EN (0x00000004) /* R/W */ 194*de1b686bSSascha Hauer #define HW_CFG_32_16_BIT_MODE (0x00000004) /* RO */ 195*de1b686bSSascha Hauer #define HW_CFG_SRST_TO (0x00000002) /* RO */ 196*de1b686bSSascha Hauer #define HW_CFG_SRST (0x00000001) /* Self Clearing */ 197*de1b686bSSascha Hauer 198*de1b686bSSascha Hauer #define RX_DP_CTRL __REG(CONFIG_DRIVER_SMC911X_BASE + 0x78) 199*de1b686bSSascha Hauer #define RX_DP_CTRL_RX_FFWD (0x80000000) /* R/W */ 200*de1b686bSSascha Hauer #define RX_DP_CTRL_FFWD_BUSY (0x80000000) /* RO */ 201*de1b686bSSascha Hauer 202*de1b686bSSascha Hauer #define RX_FIFO_INF __REG(CONFIG_DRIVER_SMC911X_BASE + 0x7C) 203*de1b686bSSascha Hauer #define RX_FIFO_INF_RXSUSED (0x00FF0000) /* RO */ 204*de1b686bSSascha Hauer #define RX_FIFO_INF_RXDUSED (0x0000FFFF) /* RO */ 205*de1b686bSSascha Hauer 206*de1b686bSSascha Hauer #define TX_FIFO_INF __REG(CONFIG_DRIVER_SMC911X_BASE + 0x80) 207*de1b686bSSascha Hauer #define TX_FIFO_INF_TSUSED (0x00FF0000) /* RO */ 208*de1b686bSSascha Hauer #define TX_FIFO_INF_TDFREE (0x0000FFFF) /* RO */ 209*de1b686bSSascha Hauer 210*de1b686bSSascha Hauer #define PMT_CTRL __REG(CONFIG_DRIVER_SMC911X_BASE + 0x84) 211*de1b686bSSascha Hauer #define PMT_CTRL_PM_MODE (0x00003000) /* Self Clearing */ 212*de1b686bSSascha Hauer #define PMT_CTRL_PHY_RST (0x00000400) /* Self Clearing */ 213*de1b686bSSascha Hauer #define PMT_CTRL_WOL_EN (0x00000200) /* R/W */ 214*de1b686bSSascha Hauer #define PMT_CTRL_ED_EN (0x00000100) /* R/W */ 215*de1b686bSSascha Hauer #define PMT_CTRL_PME_TYPE (0x00000040) /* R/W Not Affected by SW Reset */ 216*de1b686bSSascha Hauer #define PMT_CTRL_WUPS (0x00000030) /* R/WC */ 217*de1b686bSSascha Hauer #define PMT_CTRL_WUPS_NOWAKE (0x00000000) /* R/WC */ 218*de1b686bSSascha Hauer #define PMT_CTRL_WUPS_ED (0x00000010) /* R/WC */ 219*de1b686bSSascha Hauer #define PMT_CTRL_WUPS_WOL (0x00000020) /* R/WC */ 220*de1b686bSSascha Hauer #define PMT_CTRL_WUPS_MULTI (0x00000030) /* R/WC */ 221*de1b686bSSascha Hauer #define PMT_CTRL_PME_IND (0x00000008) /* R/W */ 222*de1b686bSSascha Hauer #define PMT_CTRL_PME_POL (0x00000004) /* R/W */ 223*de1b686bSSascha Hauer #define PMT_CTRL_PME_EN (0x00000002) /* R/W Not Affected by SW Reset */ 224*de1b686bSSascha Hauer #define PMT_CTRL_READY (0x00000001) /* RO */ 225*de1b686bSSascha Hauer 226*de1b686bSSascha Hauer #define GPIO_CFG __REG(CONFIG_DRIVER_SMC911X_BASE + 0x88) 227*de1b686bSSascha Hauer #define GPIO_CFG_LED3_EN (0x40000000) /* R/W */ 228*de1b686bSSascha Hauer #define GPIO_CFG_LED2_EN (0x20000000) /* R/W */ 229*de1b686bSSascha Hauer #define GPIO_CFG_LED1_EN (0x10000000) /* R/W */ 230*de1b686bSSascha Hauer #define GPIO_CFG_GPIO2_INT_POL (0x04000000) /* R/W */ 231*de1b686bSSascha Hauer #define GPIO_CFG_GPIO1_INT_POL (0x02000000) /* R/W */ 232*de1b686bSSascha Hauer #define GPIO_CFG_GPIO0_INT_POL (0x01000000) /* R/W */ 233*de1b686bSSascha Hauer #define GPIO_CFG_EEPR_EN (0x00700000) /* R/W */ 234*de1b686bSSascha Hauer #define GPIO_CFG_GPIOBUF2 (0x00040000) /* R/W */ 235*de1b686bSSascha Hauer #define GPIO_CFG_GPIOBUF1 (0x00020000) /* R/W */ 236*de1b686bSSascha Hauer #define GPIO_CFG_GPIOBUF0 (0x00010000) /* R/W */ 237*de1b686bSSascha Hauer #define GPIO_CFG_GPIODIR2 (0x00000400) /* R/W */ 238*de1b686bSSascha Hauer #define GPIO_CFG_GPIODIR1 (0x00000200) /* R/W */ 239*de1b686bSSascha Hauer #define GPIO_CFG_GPIODIR0 (0x00000100) /* R/W */ 240*de1b686bSSascha Hauer #define GPIO_CFG_GPIOD4 (0x00000010) /* R/W */ 241*de1b686bSSascha Hauer #define GPIO_CFG_GPIOD3 (0x00000008) /* R/W */ 242*de1b686bSSascha Hauer #define GPIO_CFG_GPIOD2 (0x00000004) /* R/W */ 243*de1b686bSSascha Hauer #define GPIO_CFG_GPIOD1 (0x00000002) /* R/W */ 244*de1b686bSSascha Hauer #define GPIO_CFG_GPIOD0 (0x00000001) /* R/W */ 245*de1b686bSSascha Hauer 246*de1b686bSSascha Hauer #define GPT_CFG __REG(CONFIG_DRIVER_SMC911X_BASE + 0x8C) 247*de1b686bSSascha Hauer #define GPT_CFG_TIMER_EN (0x20000000) /* R/W */ 248*de1b686bSSascha Hauer #define GPT_CFG_GPT_LOAD (0x0000FFFF) /* R/W */ 249*de1b686bSSascha Hauer 250*de1b686bSSascha Hauer #define GPT_CNT __REG(CONFIG_DRIVER_SMC911X_BASE + 0x90) 251*de1b686bSSascha Hauer #define GPT_CNT_GPT_CNT (0x0000FFFF) /* RO */ 252*de1b686bSSascha Hauer 253*de1b686bSSascha Hauer #define ENDIAN __REG(CONFIG_DRIVER_SMC911X_BASE + 0x98) 254*de1b686bSSascha Hauer #define FREE_RUN __REG(CONFIG_DRIVER_SMC911X_BASE + 0x9C) 255*de1b686bSSascha Hauer #define RX_DROP __REG(CONFIG_DRIVER_SMC911X_BASE + 0xA0) 256*de1b686bSSascha Hauer #define MAC_CSR_CMD __REG(CONFIG_DRIVER_SMC911X_BASE + 0xA4) 257*de1b686bSSascha Hauer #define MAC_CSR_CMD_CSR_BUSY (0x80000000) /* Self Clearing */ 258*de1b686bSSascha Hauer #define MAC_CSR_CMD_R_NOT_W (0x40000000) /* R/W */ 259*de1b686bSSascha Hauer #define MAC_CSR_CMD_CSR_ADDR (0x000000FF) /* R/W */ 260*de1b686bSSascha Hauer 261*de1b686bSSascha Hauer #define MAC_CSR_DATA __REG(CONFIG_DRIVER_SMC911X_BASE + 0xA8) 262*de1b686bSSascha Hauer #define AFC_CFG __REG(CONFIG_DRIVER_SMC911X_BASE + 0xAC) 263*de1b686bSSascha Hauer #define AFC_CFG_AFC_HI (0x00FF0000) /* R/W */ 264*de1b686bSSascha Hauer #define AFC_CFG_AFC_LO (0x0000FF00) /* R/W */ 265*de1b686bSSascha Hauer #define AFC_CFG_BACK_DUR (0x000000F0) /* R/W */ 266*de1b686bSSascha Hauer #define AFC_CFG_FCMULT (0x00000008) /* R/W */ 267*de1b686bSSascha Hauer #define AFC_CFG_FCBRD (0x00000004) /* R/W */ 268*de1b686bSSascha Hauer #define AFC_CFG_FCADD (0x00000002) /* R/W */ 269*de1b686bSSascha Hauer #define AFC_CFG_FCANY (0x00000001) /* R/W */ 270*de1b686bSSascha Hauer 271*de1b686bSSascha Hauer #define E2P_CMD __REG(CONFIG_DRIVER_SMC911X_BASE + 0xB0) 272*de1b686bSSascha Hauer #define E2P_CMD_EPC_BUSY (0x80000000) /* Self Clearing */ 273*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD (0x70000000) /* R/W */ 274*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD_READ (0x00000000) /* R/W */ 275*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD_EWDS (0x10000000) /* R/W */ 276*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD_EWEN (0x20000000) /* R/W */ 277*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD_WRITE (0x30000000) /* R/W */ 278*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD_WRAL (0x40000000) /* R/W */ 279*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD_ERASE (0x50000000) /* R/W */ 280*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD_ERAL (0x60000000) /* R/W */ 281*de1b686bSSascha Hauer #define E2P_CMD_EPC_CMD_RELOAD (0x70000000) /* R/W */ 282*de1b686bSSascha Hauer #define E2P_CMD_EPC_TIMEOUT (0x00000200) /* RO */ 283*de1b686bSSascha Hauer #define E2P_CMD_MAC_ADDR_LOADED (0x00000100) /* RO */ 284*de1b686bSSascha Hauer #define E2P_CMD_EPC_ADDR (0x000000FF) /* R/W */ 285*de1b686bSSascha Hauer 286*de1b686bSSascha Hauer #define E2P_DATA __REG(CONFIG_DRIVER_SMC911X_BASE + 0xB4) 287*de1b686bSSascha Hauer #define E2P_DATA_EEPROM_DATA (0x000000FF) /* R/W */ 288*de1b686bSSascha Hauer /* end of LAN register offsets and bit definitions */ 289*de1b686bSSascha Hauer 290*de1b686bSSascha Hauer /* MAC Control and Status registers */ 291*de1b686bSSascha Hauer #define MAC_CR (0x01) /* R/W */ 292*de1b686bSSascha Hauer 293*de1b686bSSascha Hauer /* MAC_CR - MAC Control Register */ 294*de1b686bSSascha Hauer #define MAC_CR_RXALL (0x80000000) 295*de1b686bSSascha Hauer /* TODO: delete this bit? It is not described in the data sheet. */ 296*de1b686bSSascha Hauer #define MAC_CR_HBDIS (0x10000000) 297*de1b686bSSascha Hauer #define MAC_CR_RCVOWN (0x00800000) 298*de1b686bSSascha Hauer #define MAC_CR_LOOPBK (0x00200000) 299*de1b686bSSascha Hauer #define MAC_CR_FDPX (0x00100000) 300*de1b686bSSascha Hauer #define MAC_CR_MCPAS (0x00080000) 301*de1b686bSSascha Hauer #define MAC_CR_PRMS (0x00040000) 302*de1b686bSSascha Hauer #define MAC_CR_INVFILT (0x00020000) 303*de1b686bSSascha Hauer #define MAC_CR_PASSBAD (0x00010000) 304*de1b686bSSascha Hauer #define MAC_CR_HFILT (0x00008000) 305*de1b686bSSascha Hauer #define MAC_CR_HPFILT (0x00002000) 306*de1b686bSSascha Hauer #define MAC_CR_LCOLL (0x00001000) 307*de1b686bSSascha Hauer #define MAC_CR_BCAST (0x00000800) 308*de1b686bSSascha Hauer #define MAC_CR_DISRTY (0x00000400) 309*de1b686bSSascha Hauer #define MAC_CR_PADSTR (0x00000100) 310*de1b686bSSascha Hauer #define MAC_CR_BOLMT_MASK (0x000000C0) 311*de1b686bSSascha Hauer #define MAC_CR_DFCHK (0x00000020) 312*de1b686bSSascha Hauer #define MAC_CR_TXEN (0x00000008) 313*de1b686bSSascha Hauer #define MAC_CR_RXEN (0x00000004) 314*de1b686bSSascha Hauer 315*de1b686bSSascha Hauer #define ADDRH (0x02) /* R/W mask 0x0000FFFFUL */ 316*de1b686bSSascha Hauer #define ADDRL (0x03) /* R/W mask 0xFFFFFFFFUL */ 317*de1b686bSSascha Hauer #define HASHH (0x04) /* R/W */ 318*de1b686bSSascha Hauer #define HASHL (0x05) /* R/W */ 319*de1b686bSSascha Hauer 320*de1b686bSSascha Hauer #define MII_ACC (0x06) /* R/W */ 321*de1b686bSSascha Hauer #define MII_ACC_PHY_ADDR (0x0000F800) 322*de1b686bSSascha Hauer #define MII_ACC_MIIRINDA (0x000007C0) 323*de1b686bSSascha Hauer #define MII_ACC_MII_WRITE (0x00000002) 324*de1b686bSSascha Hauer #define MII_ACC_MII_BUSY (0x00000001) 325*de1b686bSSascha Hauer 326*de1b686bSSascha Hauer #define MII_DATA (0x07) /* R/W mask 0x0000FFFFUL */ 327*de1b686bSSascha Hauer 328*de1b686bSSascha Hauer #define FLOW (0x08) /* R/W */ 329*de1b686bSSascha Hauer #define FLOW_FCPT (0xFFFF0000) 330*de1b686bSSascha Hauer #define FLOW_FCPASS (0x00000004) 331*de1b686bSSascha Hauer #define FLOW_FCEN (0x00000002) 332*de1b686bSSascha Hauer #define FLOW_FCBSY (0x00000001) 333*de1b686bSSascha Hauer 334*de1b686bSSascha Hauer #define VLAN1 (0x09) /* R/W mask 0x0000FFFFUL */ 335*de1b686bSSascha Hauer #define VLAN1_VTI1 (0x0000ffff) 336*de1b686bSSascha Hauer 337*de1b686bSSascha Hauer #define VLAN2 (0x0A) /* R/W mask 0x0000FFFFUL */ 338*de1b686bSSascha Hauer #define VLAN2_VTI2 (0x0000ffff) 339*de1b686bSSascha Hauer 340*de1b686bSSascha Hauer #define WUFF (0x0B) /* WO */ 341*de1b686bSSascha Hauer 342*de1b686bSSascha Hauer #define WUCSR (0x0C) /* R/W */ 343*de1b686bSSascha Hauer #define WUCSR_GUE (0x00000200) 344*de1b686bSSascha Hauer #define WUCSR_WUFR (0x00000040) 345*de1b686bSSascha Hauer #define WUCSR_MPR (0x00000020) 346*de1b686bSSascha Hauer #define WUCSR_WAKE_EN (0x00000004) 347*de1b686bSSascha Hauer #define WUCSR_MPEN (0x00000002) 348*de1b686bSSascha Hauer 349*de1b686bSSascha Hauer /* Chip ID values */ 350*de1b686bSSascha Hauer #define CHIP_9115 0x115 351*de1b686bSSascha Hauer #define CHIP_9116 0x116 352*de1b686bSSascha Hauer #define CHIP_9117 0x117 353*de1b686bSSascha Hauer #define CHIP_9118 0x118 354*de1b686bSSascha Hauer #define CHIP_9215 0x115a 355*de1b686bSSascha Hauer #define CHIP_9216 0x116a 356*de1b686bSSascha Hauer #define CHIP_9217 0x117a 357*de1b686bSSascha Hauer #define CHIP_9218 0x118a 358*de1b686bSSascha Hauer 359*de1b686bSSascha Hauer struct chip_id { 360*de1b686bSSascha Hauer u16 id; 361*de1b686bSSascha Hauer char *name; 362*de1b686bSSascha Hauer }; 363*de1b686bSSascha Hauer 364*de1b686bSSascha Hauer static const struct chip_id chip_ids[] = { 365*de1b686bSSascha Hauer { CHIP_9115, "LAN9115" }, 366*de1b686bSSascha Hauer { CHIP_9116, "LAN9116" }, 367*de1b686bSSascha Hauer { CHIP_9117, "LAN9117" }, 368*de1b686bSSascha Hauer { CHIP_9118, "LAN9118" }, 369*de1b686bSSascha Hauer { CHIP_9215, "LAN9215" }, 370*de1b686bSSascha Hauer { CHIP_9216, "LAN9216" }, 371*de1b686bSSascha Hauer { CHIP_9217, "LAN9217" }, 372*de1b686bSSascha Hauer { CHIP_9218, "LAN9218" }, 373*de1b686bSSascha Hauer { 0, NULL }, 374*de1b686bSSascha Hauer }; 375*de1b686bSSascha Hauer 376*de1b686bSSascha Hauer #define DRIVERNAME "smc911x" 377*de1b686bSSascha Hauer 378*de1b686bSSascha Hauer u32 smc911x_get_mac_csr(u8 reg) 379*de1b686bSSascha Hauer { 380*de1b686bSSascha Hauer while (MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY); 381*de1b686bSSascha Hauer MAC_CSR_CMD = MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg; 382*de1b686bSSascha Hauer while (MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY); 383*de1b686bSSascha Hauer 384*de1b686bSSascha Hauer return MAC_CSR_DATA; 385*de1b686bSSascha Hauer } 386*de1b686bSSascha Hauer 387*de1b686bSSascha Hauer void smc911x_set_mac_csr(u8 reg, u32 data) 388*de1b686bSSascha Hauer { 389*de1b686bSSascha Hauer while (MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY); 390*de1b686bSSascha Hauer MAC_CSR_DATA = data; 391*de1b686bSSascha Hauer MAC_CSR_CMD = MAC_CSR_CMD_CSR_BUSY | reg; 392*de1b686bSSascha Hauer while (MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY); 393*de1b686bSSascha Hauer } 394*de1b686bSSascha Hauer 395*de1b686bSSascha Hauer static int smx911x_handle_mac_address(bd_t *bd) 396*de1b686bSSascha Hauer { 397*de1b686bSSascha Hauer unsigned long addrh, addrl; 398*de1b686bSSascha Hauer unsigned char *m = bd->bi_enetaddr; 399*de1b686bSSascha Hauer 400*de1b686bSSascha Hauer /* if the environment has a valid mac address then use it */ 401*de1b686bSSascha Hauer if ((m[0] | m[1] | m[2] | m[3] | m[4] | m[5])) { 402*de1b686bSSascha Hauer addrl = m[0] | m[1] << 8 | m[2] << 16 | m[3] << 24; 403*de1b686bSSascha Hauer addrh = m[4] | m[5] << 8; 404*de1b686bSSascha Hauer smc911x_set_mac_csr(ADDRH, addrh); 405*de1b686bSSascha Hauer smc911x_set_mac_csr(ADDRL, addrl); 406*de1b686bSSascha Hauer } else { 407*de1b686bSSascha Hauer /* if not, try to get one from the eeprom */ 408*de1b686bSSascha Hauer addrh = smc911x_get_mac_csr(ADDRH); 409*de1b686bSSascha Hauer addrl = smc911x_get_mac_csr(ADDRL); 410*de1b686bSSascha Hauer 411*de1b686bSSascha Hauer m[0] = (addrl ) & 0xff; 412*de1b686bSSascha Hauer m[1] = (addrl >> 8 ) & 0xff; 413*de1b686bSSascha Hauer m[2] = (addrl >> 16 ) & 0xff; 414*de1b686bSSascha Hauer m[3] = (addrl >> 24 ) & 0xff; 415*de1b686bSSascha Hauer m[4] = (addrh ) & 0xff; 416*de1b686bSSascha Hauer m[5] = (addrh >> 8 ) & 0xff; 417*de1b686bSSascha Hauer 418*de1b686bSSascha Hauer /* we get 0xff when there is no eeprom connected */ 419*de1b686bSSascha Hauer if ((m[0] & m[1] & m[2] & m[3] & m[4] & m[5]) == 0xff) { 420*de1b686bSSascha Hauer printf(DRIVERNAME ": no valid mac address in environment " 421*de1b686bSSascha Hauer "and no eeprom found\n"); 422*de1b686bSSascha Hauer return -1; 423*de1b686bSSascha Hauer } 424*de1b686bSSascha Hauer } 425*de1b686bSSascha Hauer 426*de1b686bSSascha Hauer printf(DRIVERNAME ": MAC %02x:%02x:%02x:%02x:%02x:%02x\n", 427*de1b686bSSascha Hauer m[0], m[1], m[2], m[3], m[4], m[5]); 428*de1b686bSSascha Hauer 429*de1b686bSSascha Hauer return 0; 430*de1b686bSSascha Hauer } 431*de1b686bSSascha Hauer 432*de1b686bSSascha Hauer static int smc911x_miiphy_read(u8 phy, u8 reg, u16 *val) 433*de1b686bSSascha Hauer { 434*de1b686bSSascha Hauer while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY); 435*de1b686bSSascha Hauer 436*de1b686bSSascha Hauer smc911x_set_mac_csr( MII_ACC, phy << 11 | reg << 6 | MII_ACC_MII_BUSY); 437*de1b686bSSascha Hauer 438*de1b686bSSascha Hauer while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY); 439*de1b686bSSascha Hauer 440*de1b686bSSascha Hauer *val = smc911x_get_mac_csr(MII_DATA); 441*de1b686bSSascha Hauer 442*de1b686bSSascha Hauer return 0; 443*de1b686bSSascha Hauer } 444*de1b686bSSascha Hauer 445*de1b686bSSascha Hauer static int smc911x_miiphy_write(u8 phy, u8 reg, u16 val) 446*de1b686bSSascha Hauer { 447*de1b686bSSascha Hauer while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY); 448*de1b686bSSascha Hauer 449*de1b686bSSascha Hauer smc911x_set_mac_csr(MII_DATA, val); 450*de1b686bSSascha Hauer smc911x_set_mac_csr(MII_ACC, 451*de1b686bSSascha Hauer phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE); 452*de1b686bSSascha Hauer 453*de1b686bSSascha Hauer while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY); 454*de1b686bSSascha Hauer return 0; 455*de1b686bSSascha Hauer } 456*de1b686bSSascha Hauer 457*de1b686bSSascha Hauer static int smc911x_phy_reset(void) 458*de1b686bSSascha Hauer { 459*de1b686bSSascha Hauer u32 reg; 460*de1b686bSSascha Hauer 461*de1b686bSSascha Hauer reg = PMT_CTRL; 462*de1b686bSSascha Hauer reg &= ~0xfffff030; 463*de1b686bSSascha Hauer reg |= PMT_CTRL_PHY_RST; 464*de1b686bSSascha Hauer PMT_CTRL = reg; 465*de1b686bSSascha Hauer 466*de1b686bSSascha Hauer mdelay(100); 467*de1b686bSSascha Hauer 468*de1b686bSSascha Hauer return 0; 469*de1b686bSSascha Hauer } 470*de1b686bSSascha Hauer 471*de1b686bSSascha Hauer static void smc911x_phy_configure(void) 472*de1b686bSSascha Hauer { 473*de1b686bSSascha Hauer int timeout; 474*de1b686bSSascha Hauer u16 status; 475*de1b686bSSascha Hauer 476*de1b686bSSascha Hauer smc911x_phy_reset(); 477*de1b686bSSascha Hauer 478*de1b686bSSascha Hauer smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_RESET); 479*de1b686bSSascha Hauer mdelay(1); 480*de1b686bSSascha Hauer smc911x_miiphy_write(1, PHY_ANAR, 0x01e1); 481*de1b686bSSascha Hauer smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); 482*de1b686bSSascha Hauer 483*de1b686bSSascha Hauer timeout = 5000; 484*de1b686bSSascha Hauer do { 485*de1b686bSSascha Hauer mdelay(1); 486*de1b686bSSascha Hauer if ((timeout--) == 0) 487*de1b686bSSascha Hauer goto err_out; 488*de1b686bSSascha Hauer 489*de1b686bSSascha Hauer if (smc911x_miiphy_read(1, PHY_BMSR, &status) != 0) 490*de1b686bSSascha Hauer goto err_out; 491*de1b686bSSascha Hauer } while (!(status & PHY_BMSR_LS)); 492*de1b686bSSascha Hauer 493*de1b686bSSascha Hauer printf(DRIVERNAME ": phy initialized\n"); 494*de1b686bSSascha Hauer 495*de1b686bSSascha Hauer return; 496*de1b686bSSascha Hauer 497*de1b686bSSascha Hauer err_out: 498*de1b686bSSascha Hauer printf(DRIVERNAME ": autonegotiation timed out\n"); 499*de1b686bSSascha Hauer } 500*de1b686bSSascha Hauer 501*de1b686bSSascha Hauer static void smc911x_reset(void) 502*de1b686bSSascha Hauer { 503*de1b686bSSascha Hauer int timeout; 504*de1b686bSSascha Hauer 505*de1b686bSSascha Hauer /* Take out of PM setting first */ 506*de1b686bSSascha Hauer if (PMT_CTRL & PMT_CTRL_READY) { 507*de1b686bSSascha Hauer /* Write to the bytetest will take out of powerdown */ 508*de1b686bSSascha Hauer BYTE_TEST = 0x0; 509*de1b686bSSascha Hauer 510*de1b686bSSascha Hauer timeout = 10; 511*de1b686bSSascha Hauer 512*de1b686bSSascha Hauer while ( timeout-- && !(PMT_CTRL & PMT_CTRL_READY)) 513*de1b686bSSascha Hauer udelay(10); 514*de1b686bSSascha Hauer if (!timeout) { 515*de1b686bSSascha Hauer printf(DRIVERNAME 516*de1b686bSSascha Hauer ": timeout waiting for PM restore\n"); 517*de1b686bSSascha Hauer return; 518*de1b686bSSascha Hauer } 519*de1b686bSSascha Hauer } 520*de1b686bSSascha Hauer 521*de1b686bSSascha Hauer /* Disable interrupts */ 522*de1b686bSSascha Hauer INT_EN = 0; 523*de1b686bSSascha Hauer 524*de1b686bSSascha Hauer HW_CFG = HW_CFG_SRST; 525*de1b686bSSascha Hauer 526*de1b686bSSascha Hauer timeout = 1000; 527*de1b686bSSascha Hauer while (timeout-- && E2P_CMD & E2P_CMD_EPC_BUSY) 528*de1b686bSSascha Hauer udelay(10); 529*de1b686bSSascha Hauer 530*de1b686bSSascha Hauer if(!timeout) { 531*de1b686bSSascha Hauer printf(DRIVERNAME ": reset timeout\n"); 532*de1b686bSSascha Hauer return; 533*de1b686bSSascha Hauer } 534*de1b686bSSascha Hauer 535*de1b686bSSascha Hauer /* Reset the FIFO level and flow control settings */ 536*de1b686bSSascha Hauer smc911x_set_mac_csr(FLOW, FLOW_FCPT | FLOW_FCEN); 537*de1b686bSSascha Hauer AFC_CFG = 0x0050287F; 538*de1b686bSSascha Hauer 539*de1b686bSSascha Hauer /* Set to LED outputs */ 540*de1b686bSSascha Hauer GPIO_CFG = 0x70070000; 541*de1b686bSSascha Hauer } 542*de1b686bSSascha Hauer 543*de1b686bSSascha Hauer static void smc911x_enable(void) 544*de1b686bSSascha Hauer { 545*de1b686bSSascha Hauer /* Enable TX */ 546*de1b686bSSascha Hauer HW_CFG = 8 << 16 | HW_CFG_SF; 547*de1b686bSSascha Hauer 548*de1b686bSSascha Hauer GPT_CFG = GPT_CFG_TIMER_EN | 10000; 549*de1b686bSSascha Hauer 550*de1b686bSSascha Hauer TX_CFG = TX_CFG_TX_ON; 551*de1b686bSSascha Hauer 552*de1b686bSSascha Hauer /* no padding to start of packets */ 553*de1b686bSSascha Hauer RX_CFG = 0; 554*de1b686bSSascha Hauer 555*de1b686bSSascha Hauer smc911x_set_mac_csr(MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS); 556*de1b686bSSascha Hauer 557*de1b686bSSascha Hauer } 558*de1b686bSSascha Hauer 559*de1b686bSSascha Hauer int eth_init(bd_t *bd) 560*de1b686bSSascha Hauer { 561*de1b686bSSascha Hauer unsigned long val, i; 562*de1b686bSSascha Hauer 563*de1b686bSSascha Hauer printf(DRIVERNAME ": initializing\n"); 564*de1b686bSSascha Hauer 565*de1b686bSSascha Hauer val = BYTE_TEST; 566*de1b686bSSascha Hauer if(val != 0x87654321) { 567*de1b686bSSascha Hauer printf(DRIVERNAME ": Invalid chip endian 0x08%x\n", val); 568*de1b686bSSascha Hauer goto err_out; 569*de1b686bSSascha Hauer } 570*de1b686bSSascha Hauer 571*de1b686bSSascha Hauer val = ID_REV >> 16; 572*de1b686bSSascha Hauer for(i = 0; chip_ids[i].id != 0; i++) { 573*de1b686bSSascha Hauer if (chip_ids[i].id == val) break; 574*de1b686bSSascha Hauer } 575*de1b686bSSascha Hauer if (!chip_ids[i].id) { 576*de1b686bSSascha Hauer printf(DRIVERNAME ": Unknown chip ID %04x\n", val); 577*de1b686bSSascha Hauer goto err_out; 578*de1b686bSSascha Hauer } 579*de1b686bSSascha Hauer 580*de1b686bSSascha Hauer printf(DRIVERNAME ": detected %s controller\n", chip_ids[i].name); 581*de1b686bSSascha Hauer 582*de1b686bSSascha Hauer smc911x_reset(); 583*de1b686bSSascha Hauer 584*de1b686bSSascha Hauer /* Configure the PHY, initialize the link state */ 585*de1b686bSSascha Hauer smc911x_phy_configure(); 586*de1b686bSSascha Hauer 587*de1b686bSSascha Hauer if (smx911x_handle_mac_address(bd)) 588*de1b686bSSascha Hauer goto err_out; 589*de1b686bSSascha Hauer 590*de1b686bSSascha Hauer /* Turn on Tx + Rx */ 591*de1b686bSSascha Hauer smc911x_enable(); 592*de1b686bSSascha Hauer 593*de1b686bSSascha Hauer return 0; 594*de1b686bSSascha Hauer 595*de1b686bSSascha Hauer err_out: 596*de1b686bSSascha Hauer return -1; 597*de1b686bSSascha Hauer } 598*de1b686bSSascha Hauer 599*de1b686bSSascha Hauer int eth_send(volatile void *packet, int length) 600*de1b686bSSascha Hauer { 601*de1b686bSSascha Hauer u32 *data = (u32*)packet; 602*de1b686bSSascha Hauer u32 tmplen; 603*de1b686bSSascha Hauer u32 status; 604*de1b686bSSascha Hauer 605*de1b686bSSascha Hauer TX_DATA_FIFO = TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | length; 606*de1b686bSSascha Hauer TX_DATA_FIFO = length; 607*de1b686bSSascha Hauer 608*de1b686bSSascha Hauer tmplen = (length + 3) / 4; 609*de1b686bSSascha Hauer 610*de1b686bSSascha Hauer while(tmplen--) 611*de1b686bSSascha Hauer TX_DATA_FIFO = *data++; 612*de1b686bSSascha Hauer 613*de1b686bSSascha Hauer /* wait for transmission */ 614*de1b686bSSascha Hauer while (!((TX_FIFO_INF & TX_FIFO_INF_TSUSED) >> 16)); 615*de1b686bSSascha Hauer 616*de1b686bSSascha Hauer /* get status. Ignore 'no carrier' error, it has no meaning for 617*de1b686bSSascha Hauer * full duplex operation 618*de1b686bSSascha Hauer */ 619*de1b686bSSascha Hauer status = TX_STATUS_FIFO & (TX_STS_LOC | TX_STS_LATE_COLL | 620*de1b686bSSascha Hauer TX_STS_MANY_COLL | TX_STS_MANY_DEFER | TX_STS_UNDERRUN); 621*de1b686bSSascha Hauer 622*de1b686bSSascha Hauer if(!status) 623*de1b686bSSascha Hauer return 0; 624*de1b686bSSascha Hauer 625*de1b686bSSascha Hauer printf(DRIVERNAME ": failed to send packet: %s%s%s%s%s\n", 626*de1b686bSSascha Hauer status & TX_STS_LOC ? "TX_STS_LOC " : "", 627*de1b686bSSascha Hauer status & TX_STS_LATE_COLL ? "TX_STS_LATE_COLL " : "", 628*de1b686bSSascha Hauer status & TX_STS_MANY_COLL ? "TX_STS_MANY_COLL " : "", 629*de1b686bSSascha Hauer status & TX_STS_MANY_DEFER ? "TX_STS_MANY_DEFER " : "", 630*de1b686bSSascha Hauer status & TX_STS_UNDERRUN ? "TX_STS_UNDERRUN" : ""); 631*de1b686bSSascha Hauer 632*de1b686bSSascha Hauer return -1; 633*de1b686bSSascha Hauer } 634*de1b686bSSascha Hauer 635*de1b686bSSascha Hauer void eth_halt(void) 636*de1b686bSSascha Hauer { 637*de1b686bSSascha Hauer smc911x_reset(); 638*de1b686bSSascha Hauer } 639*de1b686bSSascha Hauer 640*de1b686bSSascha Hauer int eth_rx(void) 641*de1b686bSSascha Hauer { 642*de1b686bSSascha Hauer u32 *data = (u32 *)NetRxPackets[0]; 643*de1b686bSSascha Hauer u32 pktlen, tmplen; 644*de1b686bSSascha Hauer u32 status; 645*de1b686bSSascha Hauer 646*de1b686bSSascha Hauer if((RX_FIFO_INF & RX_FIFO_INF_RXSUSED) >> 16) { 647*de1b686bSSascha Hauer status = RX_STATUS_FIFO; 648*de1b686bSSascha Hauer pktlen = (status & RX_STS_PKT_LEN) >> 16; 649*de1b686bSSascha Hauer 650*de1b686bSSascha Hauer RX_CFG = 0; 651*de1b686bSSascha Hauer 652*de1b686bSSascha Hauer tmplen = (pktlen + 2+ 3) / 4; 653*de1b686bSSascha Hauer while(tmplen--) 654*de1b686bSSascha Hauer *data++ = RX_DATA_FIFO; 655*de1b686bSSascha Hauer 656*de1b686bSSascha Hauer if(status & RX_STS_ES) 657*de1b686bSSascha Hauer printf(DRIVERNAME 658*de1b686bSSascha Hauer ": dropped bad packet. Status: 0x%08x\n", 659*de1b686bSSascha Hauer status); 660*de1b686bSSascha Hauer else 661*de1b686bSSascha Hauer NetReceive(NetRxPackets[0], pktlen); 662*de1b686bSSascha Hauer } 663*de1b686bSSascha Hauer 664*de1b686bSSascha Hauer return 0; 665*de1b686bSSascha Hauer } 666*de1b686bSSascha Hauer 667*de1b686bSSascha Hauer #endif /* CONFIG_DRIVER_SMC911X */ 668