12439e4bfSJean-Christophe PLAGNIOL-VILLARD /***********************************************************************
22439e4bfSJean-Christophe PLAGNIOL-VILLARD *
32439e4bfSJean-Christophe PLAGNIOL-VILLARD * Copyright (c) 2005 Freescale Semiconductor, Inc.
42439e4bfSJean-Christophe PLAGNIOL-VILLARD *
51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
62439e4bfSJean-Christophe PLAGNIOL-VILLARD *
72439e4bfSJean-Christophe PLAGNIOL-VILLARD * Description:
82439e4bfSJean-Christophe PLAGNIOL-VILLARD * Ethernet interface for Tundra TSI108 bridge chip
92439e4bfSJean-Christophe PLAGNIOL-VILLARD *
102439e4bfSJean-Christophe PLAGNIOL-VILLARD ***********************************************************************/
112439e4bfSJean-Christophe PLAGNIOL-VILLARD
122439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <config.h>
132439e4bfSJean-Christophe PLAGNIOL-VILLARD
142439e4bfSJean-Christophe PLAGNIOL-VILLARD #if !defined(CONFIG_TSI108_ETH_NUM_PORTS) || (CONFIG_TSI108_ETH_NUM_PORTS > 2)
152439e4bfSJean-Christophe PLAGNIOL-VILLARD #error "CONFIG_TSI108_ETH_NUM_PORTS must be defined as 1 or 2"
162439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
172439e4bfSJean-Christophe PLAGNIOL-VILLARD
182439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
192439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <malloc.h>
202439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h>
21ccdd12f8SBen Warren #include <netdev.h>
222439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/cache.h>
232439e4bfSJean-Christophe PLAGNIOL-VILLARD
242439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG
252439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TSI108_ETH_DEBUG 7
262439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
272439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TSI108_ETH_DEBUG 0
282439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
292439e4bfSJean-Christophe PLAGNIOL-VILLARD
302439e4bfSJean-Christophe PLAGNIOL-VILLARD #if TSI108_ETH_DEBUG > 0
312439e4bfSJean-Christophe PLAGNIOL-VILLARD #define debug_lev(lev, fmt, args...) \
322439e4bfSJean-Christophe PLAGNIOL-VILLARD if (lev <= TSI108_ETH_DEBUG) \
332439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s %d: " fmt, __FUNCTION__, __LINE__, ##args)
342439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
352439e4bfSJean-Christophe PLAGNIOL-VILLARD #define debug_lev(lev, fmt, args...) do{}while(0)
362439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
372439e4bfSJean-Christophe PLAGNIOL-VILLARD
382439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_PRINT_ERRORS
392439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_PRINT_ERRORS
402439e4bfSJean-Christophe PLAGNIOL-VILLARD
416d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #define ETH_BASE (CONFIG_SYS_TSI108_CSR_BASE + 0x6000)
422439e4bfSJean-Christophe PLAGNIOL-VILLARD
432439e4bfSJean-Christophe PLAGNIOL-VILLARD #define ETH_PORT_OFFSET 0x400
442439e4bfSJean-Christophe PLAGNIOL-VILLARD
452439e4bfSJean-Christophe PLAGNIOL-VILLARD #define __REG32(base, offset) (*((volatile u32 *)((char *)(base) + (offset))))
462439e4bfSJean-Christophe PLAGNIOL-VILLARD
472439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MAC_CONFIG_1(base) __REG32(base, 0x00000000)
482439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_TX_ENABLE (0x00000001)
492439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_SYNC_TX_ENABLE (0x00000002)
502439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_RX_ENABLE (0x00000004)
512439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_SYNC_RX_ENABLE (0x00000008)
522439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_TX_FLOW_CONTROL (0x00000010)
532439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_RX_FLOW_CONTROL (0x00000020)
542439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_LOOP_BACK (0x00000100)
552439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_RESET_TX_FUNCTION (0x00010000)
562439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_RESET_RX_FUNCTION (0x00020000)
572439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_RESET_TX_MAC (0x00040000)
582439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_RESET_RX_MAC (0x00080000)
592439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_SIM_RESET (0x40000000)
602439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_1_SOFT_RESET (0x80000000)
612439e4bfSJean-Christophe PLAGNIOL-VILLARD
622439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MAC_CONFIG_2(base) __REG32(base, 0x00000004)
632439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_2_FULL_DUPLEX (0x00000001)
642439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_2_CRC_ENABLE (0x00000002)
652439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_2_PAD_CRC (0x00000004)
662439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_2_LENGTH_CHECK (0x00000010)
672439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_2_HUGE_FRAME (0x00000020)
682439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_2_INTERFACE_MODE(val) (((val) & 0x3) << 8)
692439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAC_CONFIG_2_PREAMBLE_LENGTH(val) (((val) & 0xf) << 12)
702439e4bfSJean-Christophe PLAGNIOL-VILLARD #define INTERFACE_MODE_NIBBLE 1 /* 10/100 Mb/s MII) */
712439e4bfSJean-Christophe PLAGNIOL-VILLARD #define INTERFACE_MODE_BYTE 2 /* 1000 Mb/s GMII/TBI */
722439e4bfSJean-Christophe PLAGNIOL-VILLARD
732439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MAXIMUM_FRAME_LENGTH(base) __REG32(base, 0x00000010)
742439e4bfSJean-Christophe PLAGNIOL-VILLARD
752439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MII_MGMT_CONFIG(base) __REG32(base, 0x00000020)
762439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_CONFIG_MGMT_CLOCK_SELECT(val) ((val) & 0x7)
772439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_CONFIG_NO_PREAMBLE (0x00000010)
782439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_CONFIG_SCAN_INCREMENT (0x00000020)
792439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_CONFIG_RESET_MGMT (0x80000000)
802439e4bfSJean-Christophe PLAGNIOL-VILLARD
812439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MII_MGMT_COMMAND(base) __REG32(base, 0x00000024)
822439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_COMMAND_READ_CYCLE (0x00000001)
832439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_COMMAND_SCAN_CYCLE (0x00000002)
842439e4bfSJean-Christophe PLAGNIOL-VILLARD
852439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MII_MGMT_ADDRESS(base) __REG32(base, 0x00000028)
862439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MII_MGMT_CONTROL(base) __REG32(base, 0x0000002c)
872439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MII_MGMT_STATUS(base) __REG32(base, 0x00000030)
882439e4bfSJean-Christophe PLAGNIOL-VILLARD
892439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_MII_MGMT_INDICATORS(base) __REG32(base, 0x00000034)
902439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_INDICATORS_BUSY (0x00000001)
912439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_INDICATORS_SCAN (0x00000002)
922439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MII_MGMT_INDICATORS_NOT_VALID (0x00000004)
932439e4bfSJean-Christophe PLAGNIOL-VILLARD
942439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_INTERFACE_STATUS(base) __REG32(base, 0x0000003c)
952439e4bfSJean-Christophe PLAGNIOL-VILLARD #define INTERFACE_STATUS_LINK_FAIL (0x00000008)
962439e4bfSJean-Christophe PLAGNIOL-VILLARD #define INTERFACE_STATUS_EXCESS_DEFER (0x00000200)
972439e4bfSJean-Christophe PLAGNIOL-VILLARD
982439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_STATION_ADDRESS_1(base) __REG32(base, 0x00000040)
992439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_STATION_ADDRESS_2(base) __REG32(base, 0x00000044)
1002439e4bfSJean-Christophe PLAGNIOL-VILLARD
1012439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_PORT_CONTROL(base) __REG32(base, 0x00000200)
1022439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_PRI (0x00000001)
1032439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_BPT (0x00010000)
1042439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_SPD (0x00040000)
1052439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_RBC (0x00080000)
1062439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_PRB (0x00200000)
1072439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_DIS (0x00400000)
1082439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_TBI (0x00800000)
1092439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_STE (0x10000000)
1102439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_ZOR (0x20000000)
1112439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_CLR (0x40000000)
1122439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PORT_CONTROL_SRT (0x80000000)
1132439e4bfSJean-Christophe PLAGNIOL-VILLARD
1142439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_CONFIG(base) __REG32(base, 0x00000220)
1152439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONFIG_START_Q (0x00000003)
1162439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONFIG_EHP (0x00400000)
1172439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONFIG_CHP (0x00800000)
1182439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONFIG_RST (0x80000000)
1192439e4bfSJean-Christophe PLAGNIOL-VILLARD
1202439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_CONTROL(base) __REG32(base, 0x00000224)
1212439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONTROL_GO (0x00008000)
1222439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONTROL_MP (0x01000000)
1232439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONTROL_EAI (0x20000000)
1242439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONTROL_ABT (0x40000000)
1252439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_CONTROL_EII (0x80000000)
1262439e4bfSJean-Christophe PLAGNIOL-VILLARD
1272439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_STATUS(base) __REG32(base, 0x00000228)
1282439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_STATUS_QUEUE_USABLE (0x0000000f)
1292439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_STATUS_CURR_Q (0x00000300)
1302439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_STATUS_ACT (0x00008000)
1312439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_STATUS_QUEUE_IDLE (0x000f0000)
1322439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_STATUS_EOQ_PENDING (0x0f000000)
1332439e4bfSJean-Christophe PLAGNIOL-VILLARD
1342439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_EXTENDED_STATUS(base) __REG32(base, 0x0000022c)
1352439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_EXTENDED_STATUS_END_OF_QUEUE_CONDITION (0x0000000f)
1362439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_EXTENDED_STATUS_END_OF_FRAME_CONDITION (0x00000f00)
1372439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000)
1382439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000)
1392439e4bfSJean-Christophe PLAGNIOL-VILLARD
1402439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_THRESHOLDS(base) __REG32(base, 0x00000230)
1412439e4bfSJean-Christophe PLAGNIOL-VILLARD
1422439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000270)
1432439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_DIAGNOSTIC_ADDR_INDEX (0x0000007f)
1442439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_DIAGNOSTIC_ADDR_DFR (0x40000000)
1452439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_DIAGNOSTIC_ADDR_AI (0x80000000)
1462439e4bfSJean-Christophe PLAGNIOL-VILLARD
1472439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000274)
1482439e4bfSJean-Christophe PLAGNIOL-VILLARD
1492439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_ERROR_STATUS(base) __REG32(base, 0x00000278)
1502439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS (0x00000278)
1512439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_QUEUE_0_ERROR_RESPONSE (0x0000000f)
1522439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_TEA_ON_QUEUE_0 (0x00000010)
1532439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_RER_ON_QUEUE_0 (0x00000020)
1542439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_TER_ON_QUEUE_0 (0x00000040)
1552439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_DER_ON_QUEUE_0 (0x00000080)
1562439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_QUEUE_1_ERROR_RESPONSE (0x00000f00)
1572439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_TEA_ON_QUEUE_1 (0x00001000)
1582439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_RER_ON_QUEUE_1 (0x00002000)
1592439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_TER_ON_QUEUE_1 (0x00004000)
1602439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_DER_ON_QUEUE_1 (0x00008000)
1612439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_QUEUE_2_ERROR_RESPONSE (0x000f0000)
1622439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_TEA_ON_QUEUE_2 (0x00100000)
1632439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_RER_ON_QUEUE_2 (0x00200000)
1642439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_TER_ON_QUEUE_2 (0x00400000)
1652439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_DER_ON_QUEUE_2 (0x00800000)
1662439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_QUEUE_3_ERROR_RESPONSE (0x0f000000)
1672439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_TEA_ON_QUEUE_3 (0x10000000)
1682439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_RER_ON_QUEUE_3 (0x20000000)
1692439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_TER_ON_QUEUE_3 (0x40000000)
1702439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_ERROR_STATUS_DER_ON_QUEUE_3 (0x80000000)
1712439e4bfSJean-Christophe PLAGNIOL-VILLARD
1722439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000280)
1732439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f)
1742439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_BSWP (0x00000400)
1752439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_WSWP (0x00000800)
1762439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_AM (0x00004000)
1772439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_GVI (0x00008000)
1782439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_EEI (0x00010000)
1792439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_ELI (0x00020000)
1802439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_ENI (0x00040000)
1812439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_ESI (0x00080000)
1822439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_CONFIG_EDI (0x00100000)
1832439e4bfSJean-Christophe PLAGNIOL-VILLARD
1842439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000284)
1852439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f)
1862439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_BUF_CONFIG_BURST (0x00000300)
1872439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400)
1882439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800)
1892439e4bfSJean-Christophe PLAGNIOL-VILLARD
1902439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OCN_PORT_HLP 0 /* HLP Interface */
1912439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OCN_PORT_PCI_X 1 /* PCI-X Interface */
1922439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OCN_PORT_PROCESSOR_MASTER 2 /* Processor Interface (master) */
1932439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OCN_PORT_PROCESSOR_SLAVE 3 /* Processor Interface (slave) */
1942439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OCN_PORT_MEMORY 4 /* Memory Controller */
1952439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OCN_PORT_DMA 5 /* DMA Controller */
1962439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OCN_PORT_ETHERNET 6 /* Ethernet Controller */
1972439e4bfSJean-Christophe PLAGNIOL-VILLARD #define OCN_PORT_PRINT 7 /* Print Engine Interface */
1982439e4bfSJean-Christophe PLAGNIOL-VILLARD
1992439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000288)
2002439e4bfSJean-Christophe PLAGNIOL-VILLARD
2012439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_TX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000028c)
2022439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TX_QUEUE_0_PTR_HIGH_VALID (0x80000000)
2032439e4bfSJean-Christophe PLAGNIOL-VILLARD
2042439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_CONFIG(base) __REG32(base, 0x00000320)
2052439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_DEF_Q (0x00000003)
2062439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_EMF (0x00000100)
2072439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_EUF (0x00000200)
2082439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_BFE (0x00000400)
2092439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_MFE (0x00000800)
2102439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_UFE (0x00001000)
2112439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_SE (0x00002000)
2122439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_ABF (0x00200000)
2132439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_APE (0x00400000)
2142439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_CHP (0x00800000)
2152439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_CONFIG_RST (0x80000000)
2162439e4bfSJean-Christophe PLAGNIOL-VILLARD
2172439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_CONTROL(base) __REG32(base, 0x00000324)
2182439e4bfSJean-Christophe PLAGNIOL-VILLARD #define GE_E0_RX_CONTROL_QUEUE_ENABLES (0x0000000f)
2192439e4bfSJean-Christophe PLAGNIOL-VILLARD #define GE_E0_RX_CONTROL_GO (0x00008000)
2202439e4bfSJean-Christophe PLAGNIOL-VILLARD #define GE_E0_RX_CONTROL_EAI (0x20000000)
2212439e4bfSJean-Christophe PLAGNIOL-VILLARD #define GE_E0_RX_CONTROL_ABT (0x40000000)
2222439e4bfSJean-Christophe PLAGNIOL-VILLARD #define GE_E0_RX_CONTROL_EII (0x80000000)
2232439e4bfSJean-Christophe PLAGNIOL-VILLARD
2242439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_EXTENDED_STATUS(base) __REG32(base, 0x0000032c)
2252439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_EXTENDED_STATUS (0x0000032c)
2262439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_EXTENDED_STATUS_EOQ (0x0000000f)
2272439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_EXTENDED_STATUS_EOQ_0 (0x00000001)
2282439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_EXTENDED_STATUS_EOF (0x00000f00)
2292439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000)
2302439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000)
2312439e4bfSJean-Christophe PLAGNIOL-VILLARD
2322439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_THRESHOLDS(base) __REG32(base, 0x00000330)
2332439e4bfSJean-Christophe PLAGNIOL-VILLARD
2342439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000370)
2352439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_DIAGNOSTIC_ADDR_INDEX (0x0000007f)
2362439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_DIAGNOSTIC_ADDR_DFR (0x40000000)
2372439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_DIAGNOSTIC_ADDR_AI (0x80000000)
2382439e4bfSJean-Christophe PLAGNIOL-VILLARD
2392439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000374)
2402439e4bfSJean-Christophe PLAGNIOL-VILLARD
2412439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000380)
2422439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f)
2432439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_BSWP (0x00000400)
2442439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_WSWP (0x00000800)
2452439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_AM (0x00004000)
2462439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_EEI (0x00010000)
2472439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_ELI (0x00020000)
2482439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_ENI (0x00040000)
2492439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_ESI (0x00080000)
2502439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_CONFIG_EDI (0x00100000)
2512439e4bfSJean-Christophe PLAGNIOL-VILLARD
2522439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000384)
2532439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f)
2542439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_BUF_CONFIG_BURST (0x00000300)
2552439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400)
2562439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800)
2572439e4bfSJean-Christophe PLAGNIOL-VILLARD
2582439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000388)
2592439e4bfSJean-Christophe PLAGNIOL-VILLARD
2602439e4bfSJean-Christophe PLAGNIOL-VILLARD #define reg_RX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000038c)
2612439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_QUEUE_0_PTR_HIGH_VALID (0x80000000)
2622439e4bfSJean-Christophe PLAGNIOL-VILLARD
2632439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
2642439e4bfSJean-Christophe PLAGNIOL-VILLARD * PHY register definitions
2652439e4bfSJean-Christophe PLAGNIOL-VILLARD */
2662439e4bfSJean-Christophe PLAGNIOL-VILLARD /* the first 15 PHY registers are standard. */
2672439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_REG 0 /* Control Register */
2682439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STATUS_REG 1 /* Status Regiser */
2692439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_ID1_REG 2 /* Phy Id Reg (word 1) */
2702439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_ID2_REG 3 /* Phy Id Reg (word 2) */
2712439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_AN_ADV_REG 4 /* Autoneg Advertisement */
2722439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_LP_ABILITY_REG 5 /* Link Partner Ability (Base Page) */
2732439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_AUTONEG_EXP_REG 6 /* Autoneg Expansion Reg */
2742439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_NEXT_PAGE_TX_REG 7 /* Next Page TX */
2752439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_LP_NEXT_PAGE_REG 8 /* Link Partner Next Page */
2762439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_1000T_CTRL_REG 9 /* 1000Base-T Control Reg */
2772439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_1000T_STATUS_REG 10 /* 1000Base-T Status Reg */
2782439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_EXT_STATUS_REG 11 /* Extended Status Reg */
2792439e4bfSJean-Christophe PLAGNIOL-VILLARD
2802439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
2812439e4bfSJean-Christophe PLAGNIOL-VILLARD * PHY Register bit masks.
2822439e4bfSJean-Christophe PLAGNIOL-VILLARD */
2832439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_RESET (1 << 15)
2842439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_LOOPBACK (1 << 14)
2852439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_SPEED0 (1 << 13)
2862439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_AN_EN (1 << 12)
2872439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_PWR_DN (1 << 11)
2882439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_ISOLATE (1 << 10)
2892439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_RESTART_AN (1 << 9)
2902439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_FULL_DUPLEX (1 << 8)
2912439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_CT_EN (1 << 7)
2922439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_CTRL_SPEED1 (1 << 6)
2932439e4bfSJean-Christophe PLAGNIOL-VILLARD
2942439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_100BASE_T4 (1 << 15)
2952439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_100BASE_X_FD (1 << 14)
2962439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_100BASE_X_HD (1 << 13)
2972439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_10BASE_T_FD (1 << 12)
2982439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_10BASE_T_HD (1 << 11)
2992439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_100BASE_T2_FD (1 << 10)
3002439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_100BASE_T2_HD (1 << 9)
3012439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_EXT_STAT (1 << 8)
3022439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_RESERVED (1 << 7)
3032439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_MFPS (1 << 6) /* Management Frames Preamble Suppression */
3042439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_AN_COMPLETE (1 << 5)
3052439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_REM_FAULT (1 << 4)
3062439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_AN_CAP (1 << 3)
3072439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_LINK_UP (1 << 2)
3082439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_JABBER (1 << 1)
3092439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PHY_STAT_EXT_CAP (1 << 0)
3102439e4bfSJean-Christophe PLAGNIOL-VILLARD
3112439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2 0x11
3122439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_ENABLE_COMMA_DETECT 0x0001
3132439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_ENABLE_WRAP 0x0002
3142439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_G_MII_MODE 0x0010
3152439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_RECEIVE_CLOCK_SELECT 0x0020
3162439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_AUTO_NEGOTIATION_SENSE 0x0100
3172439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_DISABLE_TRANSMIT_RUNNING_DISPARITY 0x1000
3182439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_DISABLE_RECEIVE_RUNNING_DISPARITY 0x2000
3192439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_SHORTCUT_LINK_TIMER 0x4000
3202439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_CONTROL_2_SOFT_RESET 0x8000
3212439e4bfSJean-Christophe PLAGNIOL-VILLARD
3222439e4bfSJean-Christophe PLAGNIOL-VILLARD /* marvel specific */
3232439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MV1111_EXT_CTRL1_REG 16 /* PHY Specific Control Reg */
3242439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MV1111_SPEC_STAT_REG 17 /* PHY Specific Status Reg */
3252439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MV1111_EXT_CTRL2_REG 20 /* Extended PHY Specific Control Reg */
3262439e4bfSJean-Christophe PLAGNIOL-VILLARD
3272439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
3282439e4bfSJean-Christophe PLAGNIOL-VILLARD * MARVELL 88E1111 PHY register bit masks
3292439e4bfSJean-Christophe PLAGNIOL-VILLARD */
3302439e4bfSJean-Christophe PLAGNIOL-VILLARD /* PHY Specific Status Register (MV1111_EXT_CTRL1_REG) */
3312439e4bfSJean-Christophe PLAGNIOL-VILLARD
3322439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_SPEED_MASK (3 << 14)
3332439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_FULL_DUP (1 << 13)
3342439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_PAGE_RCVD (1 << 12)
3352439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_RESOLVED (1 << 11) /* Speed and Duplex Resolved */
3362439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_LINK_UP (1 << 10)
3372439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_CABLE_LEN_MASK (7 << 7)/* Cable Length (100/1000 modes only) */
3382439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_MDIX (1 << 6)
3392439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_POLARITY (1 << 1)
3402439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEC_STAT_JABBER (1 << 0)
3412439e4bfSJean-Christophe PLAGNIOL-VILLARD
3422439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEED_1000 (2 << 14)
3432439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEED_100 (1 << 14)
3442439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SPEED_10 (0 << 14)
3452439e4bfSJean-Christophe PLAGNIOL-VILLARD
3462439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TBI_ADDR 0x1E /* Ten Bit Interface address */
3472439e4bfSJean-Christophe PLAGNIOL-VILLARD
3482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* negotiated link parameters */
3492439e4bfSJean-Christophe PLAGNIOL-VILLARD #define LINK_SPEED_UNKNOWN 0
3502439e4bfSJean-Christophe PLAGNIOL-VILLARD #define LINK_SPEED_10 1
3512439e4bfSJean-Christophe PLAGNIOL-VILLARD #define LINK_SPEED_100 2
3522439e4bfSJean-Christophe PLAGNIOL-VILLARD #define LINK_SPEED_1000 3
3532439e4bfSJean-Christophe PLAGNIOL-VILLARD
3542439e4bfSJean-Christophe PLAGNIOL-VILLARD #define LINK_DUPLEX_UNKNOWN 0
3552439e4bfSJean-Christophe PLAGNIOL-VILLARD #define LINK_DUPLEX_HALF 1
3562439e4bfSJean-Christophe PLAGNIOL-VILLARD #define LINK_DUPLEX_FULL 2
3572439e4bfSJean-Christophe PLAGNIOL-VILLARD
3582439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned int phy_address[] = { 8, 9 };
3592439e4bfSJean-Christophe PLAGNIOL-VILLARD
3602439e4bfSJean-Christophe PLAGNIOL-VILLARD #define vuint32 volatile u32
3612439e4bfSJean-Christophe PLAGNIOL-VILLARD
3622439e4bfSJean-Christophe PLAGNIOL-VILLARD /* TX/RX buffer descriptors. MUST be cache line aligned in memory. (32 byte)
3632439e4bfSJean-Christophe PLAGNIOL-VILLARD * This structure is accessed by the ethernet DMA engine which means it
3642439e4bfSJean-Christophe PLAGNIOL-VILLARD * MUST be in LITTLE ENDIAN format */
3652439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dma_descriptor {
3662439e4bfSJean-Christophe PLAGNIOL-VILLARD vuint32 start_addr0; /* buffer address, least significant bytes. */
3672439e4bfSJean-Christophe PLAGNIOL-VILLARD vuint32 start_addr1; /* buffer address, most significant bytes. */
3682439e4bfSJean-Christophe PLAGNIOL-VILLARD vuint32 next_descr_addr0;/* next descriptor address, least significant bytes. Must be 64-bit aligned. */
3692439e4bfSJean-Christophe PLAGNIOL-VILLARD vuint32 next_descr_addr1;/* next descriptor address, most significant bytes. */
3702439e4bfSJean-Christophe PLAGNIOL-VILLARD vuint32 vlan_byte_count;/* VLAN tag(top 2 bytes) and byte countt (bottom 2 bytes). */
3712439e4bfSJean-Christophe PLAGNIOL-VILLARD vuint32 config_status; /* Configuration/Status. */
3722439e4bfSJean-Christophe PLAGNIOL-VILLARD vuint32 reserved1; /* reserved to make the descriptor cache line aligned. */
3732439e4bfSJean-Christophe PLAGNIOL-VILLARD vuint32 reserved2; /* reserved to make the descriptor cache line aligned. */
3742439e4bfSJean-Christophe PLAGNIOL-VILLARD };
3752439e4bfSJean-Christophe PLAGNIOL-VILLARD
3762439e4bfSJean-Christophe PLAGNIOL-VILLARD /* last next descriptor address flag */
3772439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_LAST (1 << 31)
3782439e4bfSJean-Christophe PLAGNIOL-VILLARD
3792439e4bfSJean-Christophe PLAGNIOL-VILLARD /* TX DMA descriptor config status bits */
3802439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_EOF (1 << 0) /* end of frame */
3812439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_SOF (1 << 1) /* start of frame */
3822439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_PFVLAN (1 << 2)
3832439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_HUGE (1 << 3)
3842439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_PAD (1 << 4)
3852439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_CRC (1 << 5)
3862439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_DESCR_INT (1 << 14)
3872439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_RETRY_COUNT 0x000F0000
3882439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_ONE_COLLISION (1 << 20)
3892439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_LATE_COLLISION (1 << 24)
3902439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_UNDERRUN (1 << 25)
3912439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_RETRY_LIMIT (1 << 26)
3922439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_OK (1 << 30)
3932439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_TX_OWNER (1 << 31)
3942439e4bfSJean-Christophe PLAGNIOL-VILLARD
3952439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RX DMA descriptor status bits */
3962439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_EOF (1 << 0)
3972439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_SOF (1 << 1)
3982439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_VTF (1 << 2)
3992439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_FRAME_IS_TYPE (1 << 3)
4002439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_SHORT_FRAME (1 << 4)
4012439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_HASH_MATCH (1 << 7)
4022439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_BAD_FRAME (1 << 8)
4032439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_OVERRUN (1 << 9)
4042439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_MAX_FRAME_LEN (1 << 11)
4052439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_CRC_ERROR (1 << 12)
4062439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_DESCR_INT (1 << 13)
4072439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DMA_DESCR_RX_OWNER (1 << 15)
4082439e4bfSJean-Christophe PLAGNIOL-VILLARD
4092439e4bfSJean-Christophe PLAGNIOL-VILLARD #define RX_BUFFER_SIZE PKTSIZE
4102439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NUM_RX_DESC PKTBUFSRX
4112439e4bfSJean-Christophe PLAGNIOL-VILLARD
4122439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct dma_descriptor tx_descriptor __attribute__ ((aligned(32)));
4132439e4bfSJean-Christophe PLAGNIOL-VILLARD
4142439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct dma_descriptor rx_descr_array[NUM_RX_DESC]
4152439e4bfSJean-Christophe PLAGNIOL-VILLARD __attribute__ ((aligned(32)));
4162439e4bfSJean-Christophe PLAGNIOL-VILLARD
4172439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct dma_descriptor *rx_descr_current;
4182439e4bfSJean-Christophe PLAGNIOL-VILLARD
4192439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis);
420e5c83f33SJoe Hershberger static int tsi108_eth_send(struct eth_device *dev, void *packet, int length);
4212439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tsi108_eth_recv (struct eth_device *dev);
4222439e4bfSJean-Christophe PLAGNIOL-VILLARD static void tsi108_eth_halt (struct eth_device *dev);
4232439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned int read_phy (unsigned int base,
4242439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int phy_addr, unsigned int phy_reg);
4252439e4bfSJean-Christophe PLAGNIOL-VILLARD static void write_phy (unsigned int base,
4262439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int phy_addr,
4272439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int phy_reg, unsigned int phy_data);
4282439e4bfSJean-Christophe PLAGNIOL-VILLARD
4292439e4bfSJean-Christophe PLAGNIOL-VILLARD #if TSI108_ETH_DEBUG > 100
4302439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4312439e4bfSJean-Christophe PLAGNIOL-VILLARD * print phy debug infomation
4322439e4bfSJean-Christophe PLAGNIOL-VILLARD */
dump_phy_regs(unsigned int phy_addr)4332439e4bfSJean-Christophe PLAGNIOL-VILLARD static void dump_phy_regs (unsigned int phy_addr)
4342439e4bfSJean-Christophe PLAGNIOL-VILLARD {
4352439e4bfSJean-Christophe PLAGNIOL-VILLARD int i;
4362439e4bfSJean-Christophe PLAGNIOL-VILLARD
4372439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("PHY %d registers\n", phy_addr);
4382439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i <= 30; i++) {
4392439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%2d 0x%04x\n", i, read_phy (ETH_BASE, phy_addr, i));
4402439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4412439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("\n");
4422439e4bfSJean-Christophe PLAGNIOL-VILLARD
4432439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4442439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
4452439e4bfSJean-Christophe PLAGNIOL-VILLARD #define dump_phy_regs(base) do{}while(0)
4462439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
4472439e4bfSJean-Christophe PLAGNIOL-VILLARD
4482439e4bfSJean-Christophe PLAGNIOL-VILLARD #if TSI108_ETH_DEBUG > 100
4492439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4502439e4bfSJean-Christophe PLAGNIOL-VILLARD * print debug infomation
4512439e4bfSJean-Christophe PLAGNIOL-VILLARD */
tx_diag_regs(unsigned int base)4522439e4bfSJean-Christophe PLAGNIOL-VILLARD static void tx_diag_regs (unsigned int base)
4532439e4bfSJean-Christophe PLAGNIOL-VILLARD {
4542439e4bfSJean-Christophe PLAGNIOL-VILLARD int i;
4552439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long dummy;
4562439e4bfSJean-Christophe PLAGNIOL-VILLARD
4572439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("TX diagnostics registers\n");
4582439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_DIAGNOSTIC_ADDR(base) = 0x00 | TX_DIAGNOSTIC_ADDR_AI;
4592439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1000);
4602439e4bfSJean-Christophe PLAGNIOL-VILLARD dummy = reg_TX_DIAGNOSTIC_DATA(base);
4612439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0x00; i <= 0x05; i++) {
4622439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1000);
4632439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base));
4642439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4652439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_DIAGNOSTIC_ADDR(base) = 0x40 | TX_DIAGNOSTIC_ADDR_AI;
4662439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1000);
4672439e4bfSJean-Christophe PLAGNIOL-VILLARD dummy = reg_TX_DIAGNOSTIC_DATA(base);
4682439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0x40; i <= 0x47; i++) {
4692439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1000);
4702439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base));
4712439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4722439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("\n");
4732439e4bfSJean-Christophe PLAGNIOL-VILLARD
4742439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4752439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
4762439e4bfSJean-Christophe PLAGNIOL-VILLARD #define tx_diag_regs(base) do{}while(0)
4772439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
4782439e4bfSJean-Christophe PLAGNIOL-VILLARD
4792439e4bfSJean-Christophe PLAGNIOL-VILLARD #if TSI108_ETH_DEBUG > 100
4802439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4812439e4bfSJean-Christophe PLAGNIOL-VILLARD * print debug infomation
4822439e4bfSJean-Christophe PLAGNIOL-VILLARD */
rx_diag_regs(unsigned int base)4832439e4bfSJean-Christophe PLAGNIOL-VILLARD static void rx_diag_regs (unsigned int base)
4842439e4bfSJean-Christophe PLAGNIOL-VILLARD {
4852439e4bfSJean-Christophe PLAGNIOL-VILLARD int i;
4862439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long dummy;
4872439e4bfSJean-Christophe PLAGNIOL-VILLARD
4882439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("RX diagnostics registers\n");
4892439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_DIAGNOSTIC_ADDR(base) = 0x00 | RX_DIAGNOSTIC_ADDR_AI;
4902439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1000);
4912439e4bfSJean-Christophe PLAGNIOL-VILLARD dummy = reg_RX_DIAGNOSTIC_DATA(base);
4922439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0x00; i <= 0x05; i++) {
4932439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1000);
4942439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base));
4952439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4962439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_DIAGNOSTIC_ADDR(base) = 0x40 | RX_DIAGNOSTIC_ADDR_AI;
4972439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1000);
4982439e4bfSJean-Christophe PLAGNIOL-VILLARD dummy = reg_RX_DIAGNOSTIC_DATA(base);
4992439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0x08; i <= 0x0a; i++) {
5002439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (1000);
5012439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base));
5022439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5032439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("\n");
5042439e4bfSJean-Christophe PLAGNIOL-VILLARD
5052439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5062439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
5072439e4bfSJean-Christophe PLAGNIOL-VILLARD #define rx_diag_regs(base) do{}while(0)
5082439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
5092439e4bfSJean-Christophe PLAGNIOL-VILLARD
5102439e4bfSJean-Christophe PLAGNIOL-VILLARD #if TSI108_ETH_DEBUG > 100
5112439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5122439e4bfSJean-Christophe PLAGNIOL-VILLARD * print debug infomation
5132439e4bfSJean-Christophe PLAGNIOL-VILLARD */
debug_mii_regs(unsigned int base)5142439e4bfSJean-Christophe PLAGNIOL-VILLARD static void debug_mii_regs (unsigned int base)
5152439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5162439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("MII_MGMT_CONFIG 0x%08x\n", reg_MII_MGMT_CONFIG(base));
5172439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("MII_MGMT_COMMAND 0x%08x\n", reg_MII_MGMT_COMMAND(base));
5182439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("MII_MGMT_ADDRESS 0x%08x\n", reg_MII_MGMT_ADDRESS(base));
5192439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("MII_MGMT_CONTROL 0x%08x\n", reg_MII_MGMT_CONTROL(base));
5202439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("MII_MGMT_STATUS 0x%08x\n", reg_MII_MGMT_STATUS(base));
5212439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("MII_MGMT_INDICATORS 0x%08x\n", reg_MII_MGMT_INDICATORS(base));
5222439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("\n");
5232439e4bfSJean-Christophe PLAGNIOL-VILLARD
5242439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5252439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
5262439e4bfSJean-Christophe PLAGNIOL-VILLARD #define debug_mii_regs(base) do{}while(0)
5272439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
5282439e4bfSJean-Christophe PLAGNIOL-VILLARD
5292439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5302439e4bfSJean-Christophe PLAGNIOL-VILLARD * Wait until the phy bus is non-busy
5312439e4bfSJean-Christophe PLAGNIOL-VILLARD */
phy_wait(unsigned int base,unsigned int condition)5322439e4bfSJean-Christophe PLAGNIOL-VILLARD static void phy_wait (unsigned int base, unsigned int condition)
5332439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5342439e4bfSJean-Christophe PLAGNIOL-VILLARD int timeout;
5352439e4bfSJean-Christophe PLAGNIOL-VILLARD
5362439e4bfSJean-Christophe PLAGNIOL-VILLARD timeout = 0;
5372439e4bfSJean-Christophe PLAGNIOL-VILLARD while (reg_MII_MGMT_INDICATORS(base) & condition) {
5382439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (10);
5392439e4bfSJean-Christophe PLAGNIOL-VILLARD if (++timeout > 10000) {
5402439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("ERROR: timeout waiting for phy bus (%d)\n",
5412439e4bfSJean-Christophe PLAGNIOL-VILLARD condition);
5422439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
5432439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5442439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5452439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5462439e4bfSJean-Christophe PLAGNIOL-VILLARD
5472439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5482439e4bfSJean-Christophe PLAGNIOL-VILLARD * read phy register
5492439e4bfSJean-Christophe PLAGNIOL-VILLARD */
read_phy(unsigned int base,unsigned int phy_addr,unsigned int phy_reg)5502439e4bfSJean-Christophe PLAGNIOL-VILLARD static unsigned int read_phy (unsigned int base,
5512439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int phy_addr, unsigned int phy_reg)
5522439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5532439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int value;
5542439e4bfSJean-Christophe PLAGNIOL-VILLARD
5552439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_wait (base, MII_MGMT_INDICATORS_BUSY);
5562439e4bfSJean-Christophe PLAGNIOL-VILLARD
5572439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg;
5582439e4bfSJean-Christophe PLAGNIOL-VILLARD
5592439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Ensure that the Read Cycle bit is cleared prior to next read cycle */
5602439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MII_MGMT_COMMAND(base) = 0;
5612439e4bfSJean-Christophe PLAGNIOL-VILLARD
5622439e4bfSJean-Christophe PLAGNIOL-VILLARD /* start the read */
5632439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MII_MGMT_COMMAND(base) = MII_MGMT_COMMAND_READ_CYCLE;
5642439e4bfSJean-Christophe PLAGNIOL-VILLARD
5652439e4bfSJean-Christophe PLAGNIOL-VILLARD /* wait for the read to complete */
5662439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_wait (base,
5672439e4bfSJean-Christophe PLAGNIOL-VILLARD MII_MGMT_INDICATORS_NOT_VALID | MII_MGMT_INDICATORS_BUSY);
5682439e4bfSJean-Christophe PLAGNIOL-VILLARD
5692439e4bfSJean-Christophe PLAGNIOL-VILLARD value = reg_MII_MGMT_STATUS(base);
5702439e4bfSJean-Christophe PLAGNIOL-VILLARD
5712439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MII_MGMT_COMMAND(base) = 0;
5722439e4bfSJean-Christophe PLAGNIOL-VILLARD
5732439e4bfSJean-Christophe PLAGNIOL-VILLARD return value;
5742439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5752439e4bfSJean-Christophe PLAGNIOL-VILLARD
5762439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5772439e4bfSJean-Christophe PLAGNIOL-VILLARD * write phy register
5782439e4bfSJean-Christophe PLAGNIOL-VILLARD */
write_phy(unsigned int base,unsigned int phy_addr,unsigned int phy_reg,unsigned int phy_data)5792439e4bfSJean-Christophe PLAGNIOL-VILLARD static void write_phy (unsigned int base,
5802439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int phy_addr,
5812439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int phy_reg, unsigned int phy_data)
5822439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5832439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_wait (base, MII_MGMT_INDICATORS_BUSY);
5842439e4bfSJean-Christophe PLAGNIOL-VILLARD
5852439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg;
5862439e4bfSJean-Christophe PLAGNIOL-VILLARD
5872439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Ensure that the Read Cycle bit is cleared prior to next cycle */
5882439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MII_MGMT_COMMAND(base) = 0;
5892439e4bfSJean-Christophe PLAGNIOL-VILLARD
5902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* start the write */
5912439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MII_MGMT_CONTROL(base) = phy_data;
5922439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5932439e4bfSJean-Christophe PLAGNIOL-VILLARD
5942439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5952439e4bfSJean-Christophe PLAGNIOL-VILLARD * configure the marvell 88e1111 phy
5962439e4bfSJean-Christophe PLAGNIOL-VILLARD */
marvell_88e_phy_config(struct eth_device * dev,int * speed,int * duplex)5972439e4bfSJean-Christophe PLAGNIOL-VILLARD static int marvell_88e_phy_config (struct eth_device *dev, int *speed,
5982439e4bfSJean-Christophe PLAGNIOL-VILLARD int *duplex)
5992439e4bfSJean-Christophe PLAGNIOL-VILLARD {
6002439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long base;
6012439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long phy_addr;
6022439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int phy_status;
6032439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int phy_spec_status;
6042439e4bfSJean-Christophe PLAGNIOL-VILLARD int timeout;
6052439e4bfSJean-Christophe PLAGNIOL-VILLARD int phy_speed;
6062439e4bfSJean-Christophe PLAGNIOL-VILLARD int phy_duplex;
6072439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned int value;
6082439e4bfSJean-Christophe PLAGNIOL-VILLARD
6092439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_speed = LINK_SPEED_UNKNOWN;
6102439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_duplex = LINK_DUPLEX_UNKNOWN;
6112439e4bfSJean-Christophe PLAGNIOL-VILLARD
6122439e4bfSJean-Christophe PLAGNIOL-VILLARD base = dev->iobase;
6132439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_addr = (unsigned long)dev->priv;
6142439e4bfSJean-Christophe PLAGNIOL-VILLARD
6152439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Take the PHY out of reset. */
6162439e4bfSJean-Christophe PLAGNIOL-VILLARD write_phy (ETH_BASE, phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET);
6172439e4bfSJean-Christophe PLAGNIOL-VILLARD
6182439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for the reset process to complete. */
6192439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (10);
6202439e4bfSJean-Christophe PLAGNIOL-VILLARD timeout = 0;
6212439e4bfSJean-Christophe PLAGNIOL-VILLARD while ((phy_status =
6222439e4bfSJean-Christophe PLAGNIOL-VILLARD read_phy (ETH_BASE, phy_addr, PHY_CTRL_REG)) & PHY_CTRL_RESET) {
6232439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (10);
6242439e4bfSJean-Christophe PLAGNIOL-VILLARD if (++timeout > 10000) {
6252439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("ERROR: timeout waiting for phy reset\n");
6262439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
6272439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6282439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6292439e4bfSJean-Christophe PLAGNIOL-VILLARD
6302439e4bfSJean-Christophe PLAGNIOL-VILLARD /* TBI Configuration. */
6312439e4bfSJean-Christophe PLAGNIOL-VILLARD write_phy (base, TBI_ADDR, TBI_CONTROL_2, TBI_CONTROL_2_G_MII_MODE |
6322439e4bfSJean-Christophe PLAGNIOL-VILLARD TBI_CONTROL_2_RECEIVE_CLOCK_SELECT);
6332439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for the link to be established. */
6342439e4bfSJean-Christophe PLAGNIOL-VILLARD timeout = 0;
6352439e4bfSJean-Christophe PLAGNIOL-VILLARD do {
6362439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (20000);
6372439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_status = read_phy (ETH_BASE, phy_addr, PHY_STATUS_REG);
6382439e4bfSJean-Christophe PLAGNIOL-VILLARD if (++timeout > 100) {
6392439e4bfSJean-Christophe PLAGNIOL-VILLARD debug_lev(1, "ERROR: unable to establish link!!!\n");
6402439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
6412439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6422439e4bfSJean-Christophe PLAGNIOL-VILLARD } while ((phy_status & PHY_STAT_LINK_UP) == 0);
6432439e4bfSJean-Christophe PLAGNIOL-VILLARD
6442439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((phy_status & PHY_STAT_LINK_UP) == 0)
6452439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0;
6462439e4bfSJean-Christophe PLAGNIOL-VILLARD
6472439e4bfSJean-Christophe PLAGNIOL-VILLARD value = 0;
6482439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG);
6492439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_spec_status & SPEC_STAT_RESOLVED) {
6502439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (phy_spec_status & SPEC_STAT_SPEED_MASK) {
6512439e4bfSJean-Christophe PLAGNIOL-VILLARD case SPEED_1000:
6522439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_speed = LINK_SPEED_1000;
6532439e4bfSJean-Christophe PLAGNIOL-VILLARD value |= PHY_CTRL_SPEED1;
6542439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
6552439e4bfSJean-Christophe PLAGNIOL-VILLARD case SPEED_100:
6562439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_speed = LINK_SPEED_100;
6572439e4bfSJean-Christophe PLAGNIOL-VILLARD value |= PHY_CTRL_SPEED0;
6582439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
6592439e4bfSJean-Christophe PLAGNIOL-VILLARD case SPEED_10:
6602439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_speed = LINK_SPEED_10;
6612439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
6622439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6632439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_spec_status & SPEC_STAT_FULL_DUP) {
6642439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_duplex = LINK_DUPLEX_FULL;
6652439e4bfSJean-Christophe PLAGNIOL-VILLARD value |= PHY_CTRL_FULL_DUPLEX;
6662439e4bfSJean-Christophe PLAGNIOL-VILLARD } else
6672439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_duplex = LINK_DUPLEX_HALF;
6682439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6692439e4bfSJean-Christophe PLAGNIOL-VILLARD /* set TBI speed */
6702439e4bfSJean-Christophe PLAGNIOL-VILLARD write_phy (base, TBI_ADDR, PHY_CTRL_REG, value);
6712439e4bfSJean-Christophe PLAGNIOL-VILLARD write_phy (base, TBI_ADDR, PHY_AN_ADV_REG, 0x0060);
6722439e4bfSJean-Christophe PLAGNIOL-VILLARD
6732439e4bfSJean-Christophe PLAGNIOL-VILLARD #if TSI108_ETH_DEBUG > 0
6742439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("%s link is up", dev->name);
6752439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG);
6762439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_spec_status & SPEC_STAT_RESOLVED) {
6772439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (phy_speed) {
6782439e4bfSJean-Christophe PLAGNIOL-VILLARD case LINK_SPEED_1000:
6792439e4bfSJean-Christophe PLAGNIOL-VILLARD printf (", 1000 Mbps");
6802439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
6812439e4bfSJean-Christophe PLAGNIOL-VILLARD case LINK_SPEED_100:
6822439e4bfSJean-Christophe PLAGNIOL-VILLARD printf (", 100 Mbps");
6832439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
6842439e4bfSJean-Christophe PLAGNIOL-VILLARD case LINK_SPEED_10:
6852439e4bfSJean-Christophe PLAGNIOL-VILLARD printf (", 10 Mbps");
6862439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
6872439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6882439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_duplex == LINK_DUPLEX_FULL)
6892439e4bfSJean-Christophe PLAGNIOL-VILLARD printf (", Full duplex");
6902439e4bfSJean-Christophe PLAGNIOL-VILLARD else
6912439e4bfSJean-Christophe PLAGNIOL-VILLARD printf (", Half duplex");
6922439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6932439e4bfSJean-Christophe PLAGNIOL-VILLARD printf ("\n");
6942439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
6952439e4bfSJean-Christophe PLAGNIOL-VILLARD
6962439e4bfSJean-Christophe PLAGNIOL-VILLARD dump_phy_regs (TBI_ADDR);
6972439e4bfSJean-Christophe PLAGNIOL-VILLARD if (speed)
6982439e4bfSJean-Christophe PLAGNIOL-VILLARD *speed = phy_speed;
6992439e4bfSJean-Christophe PLAGNIOL-VILLARD if (duplex)
7002439e4bfSJean-Christophe PLAGNIOL-VILLARD *duplex = phy_duplex;
7012439e4bfSJean-Christophe PLAGNIOL-VILLARD
7022439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1;
7032439e4bfSJean-Christophe PLAGNIOL-VILLARD }
7042439e4bfSJean-Christophe PLAGNIOL-VILLARD
7052439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
7062439e4bfSJean-Christophe PLAGNIOL-VILLARD * External interface
7072439e4bfSJean-Christophe PLAGNIOL-VILLARD *
7082439e4bfSJean-Christophe PLAGNIOL-VILLARD * register the tsi108 ethernet controllers with the multi-ethernet system
7092439e4bfSJean-Christophe PLAGNIOL-VILLARD */
tsi108_eth_initialize(bd_t * bis)7102439e4bfSJean-Christophe PLAGNIOL-VILLARD int tsi108_eth_initialize (bd_t * bis)
7112439e4bfSJean-Christophe PLAGNIOL-VILLARD {
7122439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *dev;
7132439e4bfSJean-Christophe PLAGNIOL-VILLARD int index;
7142439e4bfSJean-Christophe PLAGNIOL-VILLARD
7152439e4bfSJean-Christophe PLAGNIOL-VILLARD for (index = 0; index < CONFIG_TSI108_ETH_NUM_PORTS; index++) {
7162439e4bfSJean-Christophe PLAGNIOL-VILLARD dev = (struct eth_device *)malloc(sizeof(struct eth_device));
7177faeb997SNobuhiro Iwamatsu if (!dev) {
7187faeb997SNobuhiro Iwamatsu printf("tsi108: Can not allocate memory\n");
7197faeb997SNobuhiro Iwamatsu break;
7207faeb997SNobuhiro Iwamatsu }
7217faeb997SNobuhiro Iwamatsu memset(dev, 0, sizeof(*dev));
7222439e4bfSJean-Christophe PLAGNIOL-VILLARD sprintf (dev->name, "TSI108_eth%d", index);
7232439e4bfSJean-Christophe PLAGNIOL-VILLARD
7242439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->iobase = ETH_BASE + (index * ETH_PORT_OFFSET);
7252439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->priv = (void *)(phy_address[index]);
7262439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->init = tsi108_eth_probe;
7272439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->halt = tsi108_eth_halt;
7282439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->send = tsi108_eth_send;
7292439e4bfSJean-Christophe PLAGNIOL-VILLARD dev->recv = tsi108_eth_recv;
7302439e4bfSJean-Christophe PLAGNIOL-VILLARD
7312439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_register(dev);
7322439e4bfSJean-Christophe PLAGNIOL-VILLARD }
7332439e4bfSJean-Christophe PLAGNIOL-VILLARD return index;
7342439e4bfSJean-Christophe PLAGNIOL-VILLARD }
7352439e4bfSJean-Christophe PLAGNIOL-VILLARD
7362439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
7372439e4bfSJean-Christophe PLAGNIOL-VILLARD * probe for and initialize a single ethernet interface
7382439e4bfSJean-Christophe PLAGNIOL-VILLARD */
tsi108_eth_probe(struct eth_device * dev,bd_t * bis)7392439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis)
7402439e4bfSJean-Christophe PLAGNIOL-VILLARD {
7412439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long base;
7422439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long value;
7432439e4bfSJean-Christophe PLAGNIOL-VILLARD int index;
7442439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dma_descriptor *tx_descr;
7452439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dma_descriptor *rx_descr;
7462439e4bfSJean-Christophe PLAGNIOL-VILLARD int speed;
7472439e4bfSJean-Christophe PLAGNIOL-VILLARD int duplex;
7482439e4bfSJean-Christophe PLAGNIOL-VILLARD
7492439e4bfSJean-Christophe PLAGNIOL-VILLARD base = dev->iobase;
7502439e4bfSJean-Christophe PLAGNIOL-VILLARD
7512439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_PORT_CONTROL(base) = PORT_CONTROL_STE | PORT_CONTROL_BPT;
7522439e4bfSJean-Christophe PLAGNIOL-VILLARD
7532439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Bring DMA/FIFO out of reset. */
7542439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_CONFIG(base) = 0x00000000;
7552439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_CONFIG(base) = 0x00000000;
7562439e4bfSJean-Christophe PLAGNIOL-VILLARD
7572439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_THRESHOLDS(base) = (192 << 16) | 192;
7582439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_THRESHOLDS(base) = (192 << 16) | 112;
7592439e4bfSJean-Christophe PLAGNIOL-VILLARD
7602439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Bring MAC out of reset. */
7612439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MAC_CONFIG_1(base) = 0x00000000;
7622439e4bfSJean-Christophe PLAGNIOL-VILLARD
7632439e4bfSJean-Christophe PLAGNIOL-VILLARD /* DMA MAC configuration. */
7642439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MAC_CONFIG_1(base) =
7652439e4bfSJean-Christophe PLAGNIOL-VILLARD MAC_CONFIG_1_RX_ENABLE | MAC_CONFIG_1_TX_ENABLE;
7662439e4bfSJean-Christophe PLAGNIOL-VILLARD
7672439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MII_MGMT_CONFIG(base) = MII_MGMT_CONFIG_NO_PREAMBLE;
7682439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MAXIMUM_FRAME_LENGTH(base) = RX_BUFFER_SIZE;
7692439e4bfSJean-Christophe PLAGNIOL-VILLARD
7702439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Note: Early tsi108 manual did not have correct byte order
7712439e4bfSJean-Christophe PLAGNIOL-VILLARD * for the station address.*/
7722439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_STATION_ADDRESS_1(base) = (dev->enetaddr[5] << 24) |
7732439e4bfSJean-Christophe PLAGNIOL-VILLARD (dev->enetaddr[4] << 16) |
7742439e4bfSJean-Christophe PLAGNIOL-VILLARD (dev->enetaddr[3] << 8) | (dev->enetaddr[2] << 0);
7752439e4bfSJean-Christophe PLAGNIOL-VILLARD
7762439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_STATION_ADDRESS_2(base) = (dev->enetaddr[1] << 24) |
7772439e4bfSJean-Christophe PLAGNIOL-VILLARD (dev->enetaddr[0] << 16);
7782439e4bfSJean-Christophe PLAGNIOL-VILLARD
7792439e4bfSJean-Christophe PLAGNIOL-VILLARD if (marvell_88e_phy_config(dev, &speed, &duplex) == 0)
780422b1a01SBen Warren return -1;
7812439e4bfSJean-Christophe PLAGNIOL-VILLARD
7822439e4bfSJean-Christophe PLAGNIOL-VILLARD value =
7832439e4bfSJean-Christophe PLAGNIOL-VILLARD MAC_CONFIG_2_PREAMBLE_LENGTH(7) | MAC_CONFIG_2_PAD_CRC |
7842439e4bfSJean-Christophe PLAGNIOL-VILLARD MAC_CONFIG_2_CRC_ENABLE;
7852439e4bfSJean-Christophe PLAGNIOL-VILLARD if (speed == LINK_SPEED_1000)
7862439e4bfSJean-Christophe PLAGNIOL-VILLARD value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_BYTE);
7872439e4bfSJean-Christophe PLAGNIOL-VILLARD else {
7882439e4bfSJean-Christophe PLAGNIOL-VILLARD value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_NIBBLE);
7892439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_PORT_CONTROL(base) |= PORT_CONTROL_SPD;
7902439e4bfSJean-Christophe PLAGNIOL-VILLARD }
7912439e4bfSJean-Christophe PLAGNIOL-VILLARD if (duplex == LINK_DUPLEX_FULL) {
7922439e4bfSJean-Christophe PLAGNIOL-VILLARD value |= MAC_CONFIG_2_FULL_DUPLEX;
7932439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_PORT_CONTROL(base) &= ~PORT_CONTROL_BPT;
7942439e4bfSJean-Christophe PLAGNIOL-VILLARD } else
7952439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_PORT_CONTROL(base) |= PORT_CONTROL_BPT;
7962439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MAC_CONFIG_2(base) = value;
7972439e4bfSJean-Christophe PLAGNIOL-VILLARD
7982439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_CONFIG(base) = RX_CONFIG_SE;
7992439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY;
8002439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY;
8012439e4bfSJean-Christophe PLAGNIOL-VILLARD
8022439e4bfSJean-Christophe PLAGNIOL-VILLARD /* initialize the RX DMA descriptors */
8032439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr = &rx_descr_array[0];
8042439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr_current = rx_descr;
8052439e4bfSJean-Christophe PLAGNIOL-VILLARD for (index = 0; index < NUM_RX_DESC; index++) {
8062439e4bfSJean-Christophe PLAGNIOL-VILLARD /* make sure the receive buffers are not in cache */
807*1fd92db8SJoe Hershberger invalidate_dcache_range((unsigned long)net_rx_packets[index],
808*1fd92db8SJoe Hershberger (unsigned long)net_rx_packets[index] +
8092439e4bfSJean-Christophe PLAGNIOL-VILLARD RX_BUFFER_SIZE);
8102439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->start_addr0 =
811*1fd92db8SJoe Hershberger cpu_to_le32((vuint32) net_rx_packets[index]);
8122439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->start_addr1 = 0;
8132439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->next_descr_addr0 =
8142439e4bfSJean-Christophe PLAGNIOL-VILLARD cpu_to_le32((vuint32) (rx_descr + 1));
8152439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->next_descr_addr1 = 0;
8162439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->vlan_byte_count = 0;
8172439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->config_status = cpu_to_le32((RX_BUFFER_SIZE << 16) |
8182439e4bfSJean-Christophe PLAGNIOL-VILLARD DMA_DESCR_RX_OWNER);
8192439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr++;
8202439e4bfSJean-Christophe PLAGNIOL-VILLARD }
8212439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr--;
8222439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->next_descr_addr0 = 0;
8232439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST);
8242439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Push the descriptors to RAM so the ethernet DMA can see them */
8252439e4bfSJean-Christophe PLAGNIOL-VILLARD invalidate_dcache_range((unsigned long)rx_descr_array,
8262439e4bfSJean-Christophe PLAGNIOL-VILLARD (unsigned long)rx_descr_array +
8272439e4bfSJean-Christophe PLAGNIOL-VILLARD sizeof(rx_descr_array));
8282439e4bfSJean-Christophe PLAGNIOL-VILLARD
8292439e4bfSJean-Christophe PLAGNIOL-VILLARD /* enable RX queue */
8302439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_CONTROL(base) = TX_CONTROL_GO | 0x01;
8312439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_QUEUE_0_PTR_LOW(base) = (u32) rx_descr_current;
8322439e4bfSJean-Christophe PLAGNIOL-VILLARD /* enable receive DMA */
8332439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID;
8342439e4bfSJean-Christophe PLAGNIOL-VILLARD
8352439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY;
8362439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY;
8372439e4bfSJean-Christophe PLAGNIOL-VILLARD
8382439e4bfSJean-Christophe PLAGNIOL-VILLARD /* initialize the TX DMA descriptor */
8392439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr = &tx_descriptor;
8402439e4bfSJean-Christophe PLAGNIOL-VILLARD
8412439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->start_addr0 = 0;
8422439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->start_addr1 = 0;
8432439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->next_descr_addr0 = 0;
8442439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST);
8452439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->vlan_byte_count = 0;
8462439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OK |
8472439e4bfSJean-Christophe PLAGNIOL-VILLARD DMA_DESCR_TX_SOF |
8482439e4bfSJean-Christophe PLAGNIOL-VILLARD DMA_DESCR_TX_EOF);
8492439e4bfSJean-Christophe PLAGNIOL-VILLARD /* enable TX queue */
8502439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_CONTROL(base) = TX_CONTROL_GO | 0x01;
8512439e4bfSJean-Christophe PLAGNIOL-VILLARD
852422b1a01SBen Warren return 0;
8532439e4bfSJean-Christophe PLAGNIOL-VILLARD }
8542439e4bfSJean-Christophe PLAGNIOL-VILLARD
8552439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
8562439e4bfSJean-Christophe PLAGNIOL-VILLARD * send a packet
8572439e4bfSJean-Christophe PLAGNIOL-VILLARD */
tsi108_eth_send(struct eth_device * dev,void * packet,int length)858e5c83f33SJoe Hershberger static int tsi108_eth_send(struct eth_device *dev, void *packet, int length)
8592439e4bfSJean-Christophe PLAGNIOL-VILLARD {
8602439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long base;
8612439e4bfSJean-Christophe PLAGNIOL-VILLARD int timeout;
8622439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dma_descriptor *tx_descr;
8632439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long status;
8642439e4bfSJean-Christophe PLAGNIOL-VILLARD
8652439e4bfSJean-Christophe PLAGNIOL-VILLARD base = dev->iobase;
8662439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr = &tx_descriptor;
8672439e4bfSJean-Christophe PLAGNIOL-VILLARD
8682439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait until the last packet has been transmitted. */
8692439e4bfSJean-Christophe PLAGNIOL-VILLARD timeout = 0;
8702439e4bfSJean-Christophe PLAGNIOL-VILLARD do {
8712439e4bfSJean-Christophe PLAGNIOL-VILLARD /* make sure we see the changes made by the DMA engine */
8722439e4bfSJean-Christophe PLAGNIOL-VILLARD invalidate_dcache_range((unsigned long)tx_descr,
8732439e4bfSJean-Christophe PLAGNIOL-VILLARD (unsigned long)tx_descr +
8742439e4bfSJean-Christophe PLAGNIOL-VILLARD sizeof(struct dma_descriptor));
8752439e4bfSJean-Christophe PLAGNIOL-VILLARD
8762439e4bfSJean-Christophe PLAGNIOL-VILLARD if (timeout != 0)
8772439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay (15);
8782439e4bfSJean-Christophe PLAGNIOL-VILLARD if (++timeout > 10000) {
8792439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_diag_regs(base);
8802439e4bfSJean-Christophe PLAGNIOL-VILLARD debug_lev(1,
8812439e4bfSJean-Christophe PLAGNIOL-VILLARD "ERROR: timeout waiting for last transmit packet to be sent\n");
8822439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0;
8832439e4bfSJean-Christophe PLAGNIOL-VILLARD }
8842439e4bfSJean-Christophe PLAGNIOL-VILLARD } while (tx_descr->config_status & cpu_to_le32(DMA_DESCR_TX_OWNER));
8852439e4bfSJean-Christophe PLAGNIOL-VILLARD
8862439e4bfSJean-Christophe PLAGNIOL-VILLARD status = le32_to_cpu(tx_descr->config_status);
8872439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((status & DMA_DESCR_TX_OK) == 0) {
8882439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef TX_PRINT_ERRORS
889bde63587SWolfgang Denk printf ("TX packet error: 0x%08lx\n %s%s%s%s\n", status,
8902439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_TX_OK ? "tx error, " : "",
8912439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_TX_RETRY_LIMIT ?
8922439e4bfSJean-Christophe PLAGNIOL-VILLARD "retry limit reached, " : "",
8932439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_TX_UNDERRUN ? "underrun, " : "",
8942439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_TX_LATE_COLLISION ? "late collision, "
8952439e4bfSJean-Christophe PLAGNIOL-VILLARD : "");
8962439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
8972439e4bfSJean-Christophe PLAGNIOL-VILLARD }
8982439e4bfSJean-Christophe PLAGNIOL-VILLARD
8992439e4bfSJean-Christophe PLAGNIOL-VILLARD debug_lev (9, "sending packet %d\n", length);
9002439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->start_addr0 = cpu_to_le32((vuint32) packet);
9012439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->start_addr1 = 0;
9022439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->next_descr_addr0 = 0;
9032439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST);
9042439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->vlan_byte_count = cpu_to_le32(length);
9052439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OWNER |
9062439e4bfSJean-Christophe PLAGNIOL-VILLARD DMA_DESCR_TX_CRC |
9072439e4bfSJean-Christophe PLAGNIOL-VILLARD DMA_DESCR_TX_PAD |
9082439e4bfSJean-Christophe PLAGNIOL-VILLARD DMA_DESCR_TX_SOF |
9092439e4bfSJean-Christophe PLAGNIOL-VILLARD DMA_DESCR_TX_EOF);
9102439e4bfSJean-Christophe PLAGNIOL-VILLARD
9112439e4bfSJean-Christophe PLAGNIOL-VILLARD invalidate_dcache_range((unsigned long)tx_descr,
9122439e4bfSJean-Christophe PLAGNIOL-VILLARD (unsigned long)tx_descr +
9132439e4bfSJean-Christophe PLAGNIOL-VILLARD sizeof(struct dma_descriptor));
9142439e4bfSJean-Christophe PLAGNIOL-VILLARD
9152439e4bfSJean-Christophe PLAGNIOL-VILLARD invalidate_dcache_range((unsigned long)packet,
9162439e4bfSJean-Christophe PLAGNIOL-VILLARD (unsigned long)packet + length);
9172439e4bfSJean-Christophe PLAGNIOL-VILLARD
9182439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_QUEUE_0_PTR_LOW(base) = (u32) tx_descr;
9192439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_QUEUE_0_PTR_HIGH(base) = TX_QUEUE_0_PTR_HIGH_VALID;
9202439e4bfSJean-Christophe PLAGNIOL-VILLARD
9212439e4bfSJean-Christophe PLAGNIOL-VILLARD return length;
9222439e4bfSJean-Christophe PLAGNIOL-VILLARD }
9232439e4bfSJean-Christophe PLAGNIOL-VILLARD
9242439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
9252439e4bfSJean-Christophe PLAGNIOL-VILLARD * Check for received packets and send them up the protocal stack
9262439e4bfSJean-Christophe PLAGNIOL-VILLARD */
tsi108_eth_recv(struct eth_device * dev)9272439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tsi108_eth_recv (struct eth_device *dev)
9282439e4bfSJean-Christophe PLAGNIOL-VILLARD {
9292439e4bfSJean-Christophe PLAGNIOL-VILLARD struct dma_descriptor *rx_descr;
9302439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long base;
9312439e4bfSJean-Christophe PLAGNIOL-VILLARD int length = 0;
9322439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long status;
933e5c83f33SJoe Hershberger uchar *buffer;
9342439e4bfSJean-Christophe PLAGNIOL-VILLARD
9352439e4bfSJean-Christophe PLAGNIOL-VILLARD base = dev->iobase;
9362439e4bfSJean-Christophe PLAGNIOL-VILLARD
9372439e4bfSJean-Christophe PLAGNIOL-VILLARD /* make sure we see the changes made by the DMA engine */
9382439e4bfSJean-Christophe PLAGNIOL-VILLARD invalidate_dcache_range ((unsigned long)rx_descr_array,
9392439e4bfSJean-Christophe PLAGNIOL-VILLARD (unsigned long)rx_descr_array +
9402439e4bfSJean-Christophe PLAGNIOL-VILLARD sizeof(rx_descr_array));
9412439e4bfSJean-Christophe PLAGNIOL-VILLARD
9422439e4bfSJean-Christophe PLAGNIOL-VILLARD /* process all of the received packets */
9432439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr = rx_descr_current;
9442439e4bfSJean-Christophe PLAGNIOL-VILLARD while ((rx_descr->config_status & cpu_to_le32(DMA_DESCR_RX_OWNER)) == 0) {
9452439e4bfSJean-Christophe PLAGNIOL-VILLARD /* check for error */
9462439e4bfSJean-Christophe PLAGNIOL-VILLARD status = le32_to_cpu(rx_descr->config_status);
9472439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & DMA_DESCR_RX_BAD_FRAME) {
9482439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef RX_PRINT_ERRORS
949bde63587SWolfgang Denk printf ("RX packet error: 0x%08lx\n %s%s%s%s%s%s\n",
9502439e4bfSJean-Christophe PLAGNIOL-VILLARD status,
9512439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_RX_FRAME_IS_TYPE ? "too big, "
9522439e4bfSJean-Christophe PLAGNIOL-VILLARD : "",
9532439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_RX_SHORT_FRAME ? "too short, "
9542439e4bfSJean-Christophe PLAGNIOL-VILLARD : "",
9552439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_RX_BAD_FRAME ? "bad frame, " :
9562439e4bfSJean-Christophe PLAGNIOL-VILLARD "",
9572439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_RX_OVERRUN ? "overrun, " : "",
9582439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_RX_MAX_FRAME_LEN ?
9592439e4bfSJean-Christophe PLAGNIOL-VILLARD "max length, " : "",
9602439e4bfSJean-Christophe PLAGNIOL-VILLARD status & DMA_DESCR_RX_CRC_ERROR ? "CRC error, " :
9612439e4bfSJean-Christophe PLAGNIOL-VILLARD "");
9622439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
9632439e4bfSJean-Christophe PLAGNIOL-VILLARD } else {
9642439e4bfSJean-Christophe PLAGNIOL-VILLARD length =
9652439e4bfSJean-Christophe PLAGNIOL-VILLARD le32_to_cpu(rx_descr->vlan_byte_count) & 0xFFFF;
9662439e4bfSJean-Christophe PLAGNIOL-VILLARD
9672439e4bfSJean-Christophe PLAGNIOL-VILLARD /*** process packet ***/
968e5c83f33SJoe Hershberger buffer = (uchar *)(le32_to_cpu(rx_descr->start_addr0));
969*1fd92db8SJoe Hershberger net_process_received_packet(buffer, length);
9702439e4bfSJean-Christophe PLAGNIOL-VILLARD
9712439e4bfSJean-Christophe PLAGNIOL-VILLARD invalidate_dcache_range ((unsigned long)buffer,
9722439e4bfSJean-Christophe PLAGNIOL-VILLARD (unsigned long)buffer +
9732439e4bfSJean-Christophe PLAGNIOL-VILLARD RX_BUFFER_SIZE);
9742439e4bfSJean-Christophe PLAGNIOL-VILLARD }
9752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Give this buffer back to the DMA engine */
9762439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->vlan_byte_count = 0;
9772439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr->config_status = cpu_to_le32 ((RX_BUFFER_SIZE << 16) |
9782439e4bfSJean-Christophe PLAGNIOL-VILLARD DMA_DESCR_RX_OWNER);
9792439e4bfSJean-Christophe PLAGNIOL-VILLARD /* move descriptor pointer forward */
9802439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr =
9812439e4bfSJean-Christophe PLAGNIOL-VILLARD (struct dma_descriptor
9822439e4bfSJean-Christophe PLAGNIOL-VILLARD *)(le32_to_cpu (rx_descr->next_descr_addr0));
9832439e4bfSJean-Christophe PLAGNIOL-VILLARD if (rx_descr == 0)
9842439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr = &rx_descr_array[0];
9852439e4bfSJean-Christophe PLAGNIOL-VILLARD }
9862439e4bfSJean-Christophe PLAGNIOL-VILLARD /* remember where we are for next time */
9872439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_descr_current = rx_descr;
9882439e4bfSJean-Christophe PLAGNIOL-VILLARD
9892439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If the DMA engine has reached the end of the queue
9902439e4bfSJean-Christophe PLAGNIOL-VILLARD * start over at the begining */
9912439e4bfSJean-Christophe PLAGNIOL-VILLARD if (reg_RX_EXTENDED_STATUS(base) & RX_EXTENDED_STATUS_EOQ_0) {
9922439e4bfSJean-Christophe PLAGNIOL-VILLARD
9932439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_EXTENDED_STATUS(base) = RX_EXTENDED_STATUS_EOQ_0;
9942439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_QUEUE_0_PTR_LOW(base) = (u32) & rx_descr_array[0];
9952439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID;
9962439e4bfSJean-Christophe PLAGNIOL-VILLARD }
9972439e4bfSJean-Christophe PLAGNIOL-VILLARD
9982439e4bfSJean-Christophe PLAGNIOL-VILLARD return length;
9992439e4bfSJean-Christophe PLAGNIOL-VILLARD }
10002439e4bfSJean-Christophe PLAGNIOL-VILLARD
10012439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
10022439e4bfSJean-Christophe PLAGNIOL-VILLARD * disable an ethernet interface
10032439e4bfSJean-Christophe PLAGNIOL-VILLARD */
tsi108_eth_halt(struct eth_device * dev)10042439e4bfSJean-Christophe PLAGNIOL-VILLARD static void tsi108_eth_halt (struct eth_device *dev)
10052439e4bfSJean-Christophe PLAGNIOL-VILLARD {
10062439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long base;
10072439e4bfSJean-Christophe PLAGNIOL-VILLARD
10082439e4bfSJean-Christophe PLAGNIOL-VILLARD base = dev->iobase;
10092439e4bfSJean-Christophe PLAGNIOL-VILLARD
10102439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Put DMA/FIFO into reset state. */
10112439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_TX_CONFIG(base) = TX_CONFIG_RST;
10122439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_RX_CONFIG(base) = RX_CONFIG_RST;
10132439e4bfSJean-Christophe PLAGNIOL-VILLARD
10142439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Put MAC into reset state. */
10152439e4bfSJean-Christophe PLAGNIOL-VILLARD reg_MAC_CONFIG_1(base) = MAC_CONFIG_1_SOFT_RESET;
10162439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1017