From 4c52783b3d024e153c4972b97332e314bc3bdc46 Mon Sep 17 00:00:00 2001 From: roy zang Date: Thu, 2 Nov 2006 18:49:51 +0800 Subject: General code modification for mpc7448hpc2 board support. 1. Add 7447A and 7448 processor support. 2. Add the following flags. CFG_CONFIG_BUS_CLK : If the 74xx bus frequency can be configured dynamically (such as by switch on board), this flag should be set. CFG_EXCEPTION_AFTER_RELOCATE: If an exception occurs after the u-boot relocates to RAM, this flag should be set. CFG_SERIAL_HANG_IN_EXCEPTION: If the print out function will cause the system hang in exception, this flag should be set. There is a design issue for tsi108/109 pci configure read. When pci scan the slots, if there is no pci card, the tsi108/9 will cause a machine check exception for mpc7448 processor. Signed-off-by: Alexandre Bounine Signed-off-by: Roy Zang --- drivers/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/Makefile b/drivers/Makefile index 5a369df2c4..6a3ea5da25 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -35,8 +35,8 @@ COBJS = 3c589.o 5701rls.o ali512x.o atmel_usart.o \ lan91c96.o \ natsemi.o ne2000.o netarm_eth.o netconsole.o \ ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \ - omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o \ - pcnet.o plb2800_eth.o \ + omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o tsi108_pci.o\ + tsi108_i2c.o pcnet.o plb2800_eth.o \ ps2ser.o ps2mult.o pc_keyb.o \ rtl8019.o rtl8139.o rtl8169.o \ s3c4510b_eth.o s3c4510b_uart.o \ @@ -45,7 +45,7 @@ COBJS = 3c589.o 5701rls.o ali512x.o atmel_usart.o \ serial_pl010.o serial_pl011.o serial_xuartlite.o \ sl811_usb.o sm501.o smc91111.o smiLynxEM.o \ status_led.o sym53c8xx.o ahci.o \ - ti_pci1410a.o tigon3.o tsec.o \ + ti_pci1410a.o tigon3.o tsec.o tsi108_eth.o\ usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o \ videomodes.o w83c553f.o \ ks8695eth.o \ -- cgit v1.2.1 From d1927cee977126e547ceeba23e4f978f377cfb8f Mon Sep 17 00:00:00 2001 From: roy zang Date: Thu, 2 Nov 2006 19:08:55 +0800 Subject: Tundra tsi108 on chip Ethernet controller support. The following is a brief description of the Ethernet controller: The Tsi108/9 Ethernet Controller connects Switch Fabric to two independent Gigabit Ethernet ports,E0 and E1. It uses a single Management interface to manage the two physical connection devices (PHYs). Each Ethernet port has its own statistics monitor that tracks and reports key interface statistics. Each port supports a 256-entry hash table for address filtering. In addition, each port is bridged to the Switch Fabric through a 2-Kbyte transmit FIFO and a 4-Kbyte Receive FIFO. Each Ethernet port also has a pair of internal Ethernet DMA channels to support the transmit and receive data flows. The Ethernet DMA channels use descriptors set up in memory, the memory map of the device, and access via the Switch Fabric. The Ethernet Controller?s DMA arbiter handles arbitration for the Switch Fabric. The Controller also has a register businterface for register accesses and status monitor control. The PMD (Physical Media Device) interface operates in MII, GMII, or TBI modes. The MII mode is used for connecting with 10 or 100 Mbit/s PMDs. The GMII and TBI modes are used to connect with Gigabit PMDs. Internal data flows to and from the Ethernet Controller through the Switch Fabric. Each Ethernet port uses its transmit and receive DMA channels to manage data flows through buffer descriptors that are predefined by the system (the descriptors can exist anywhere in the system memory map). These descriptors are data structures that point to buffers filled with data ready to transmit over Ethernet, or they point to empty buffers ready to receive data from Ethernet. Signed-off-by: Alexandre Bounine Signed-off-by: Roy Zang --- drivers/tsi108_eth.c | 1043 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1043 insertions(+) create mode 100644 drivers/tsi108_eth.c (limited to 'drivers') diff --git a/drivers/tsi108_eth.c b/drivers/tsi108_eth.c new file mode 100644 index 0000000000..d95a047ce8 --- /dev/null +++ b/drivers/tsi108_eth.c @@ -0,0 +1,1043 @@ +/*********************************************************************** + * + * Copyright (c) 2005 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Description: + * Ethernet interface for Tundra TSI108 bridge chip + * + ***********************************************************************/ + +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \ + && defined(CONFIG_TSI108_ETH) + +#if !defined(CONFIG_TSI108_ETH_NUM_PORTS) || (CONFIG_TSI108_ETH_NUM_PORTS > 2) +#error "CONFIG_TSI108_ETH_NUM_PORTS must be defined as 1 or 2" +#endif + +#include +#include +#include +#include + +#ifdef DEBUG +#define TSI108_ETH_DEBUG 7 +#else +#define TSI108_ETH_DEBUG 0 +#endif + +#if TSI108_ETH_DEBUG > 0 +#define debug_lev(lev, fmt, args...) if (lev <= TSI108_ETH_DEBUG) printf("%s %d: " fmt, __FUNCTION__, __LINE__, ##args) +#else +#define debug_lev(lev, fmt, args...) do{}while(0) +#endif + +#define RX_PRINT_ERRORS +#define TX_PRINT_ERRORS + +#define ETH_BASE (CFG_TSI108_CSR_BASE + 0x6000) + +#define ETH_PORT_OFFSET 0x400 + +#define __REG32(base, offset) (*((volatile u32 *)((char *)(base) + (offset)))) + +#define reg_MAC_CONFIG_1(base) __REG32(base, 0x00000000) +#define MAC_CONFIG_1_TX_ENABLE (0x00000001) +#define MAC_CONFIG_1_SYNC_TX_ENABLE (0x00000002) +#define MAC_CONFIG_1_RX_ENABLE (0x00000004) +#define MAC_CONFIG_1_SYNC_RX_ENABLE (0x00000008) +#define MAC_CONFIG_1_TX_FLOW_CONTROL (0x00000010) +#define MAC_CONFIG_1_RX_FLOW_CONTROL (0x00000020) +#define MAC_CONFIG_1_LOOP_BACK (0x00000100) +#define MAC_CONFIG_1_RESET_TX_FUNCTION (0x00010000) +#define MAC_CONFIG_1_RESET_RX_FUNCTION (0x00020000) +#define MAC_CONFIG_1_RESET_TX_MAC (0x00040000) +#define MAC_CONFIG_1_RESET_RX_MAC (0x00080000) +#define MAC_CONFIG_1_SIM_RESET (0x40000000) +#define MAC_CONFIG_1_SOFT_RESET (0x80000000) + +#define reg_MAC_CONFIG_2(base) __REG32(base, 0x00000004) +#define MAC_CONFIG_2_FULL_DUPLEX (0x00000001) +#define MAC_CONFIG_2_CRC_ENABLE (0x00000002) +#define MAC_CONFIG_2_PAD_CRC (0x00000004) +#define MAC_CONFIG_2_LENGTH_CHECK (0x00000010) +#define MAC_CONFIG_2_HUGE_FRAME (0x00000020) +#define MAC_CONFIG_2_INTERFACE_MODE(val) (((val) & 0x3) << 8) +#define MAC_CONFIG_2_PREAMBLE_LENGTH(val) (((val) & 0xf) << 12) +#define INTERFACE_MODE_NIBBLE 1 /* 10/100 Mb/s MII) */ +#define INTERFACE_MODE_BYTE 2 /* 1000 Mb/s GMII/TBI */ + +#define reg_MAXIMUM_FRAME_LENGTH(base) __REG32(base, 0x00000010) + +#define reg_MII_MGMT_CONFIG(base) __REG32(base, 0x00000020) +#define MII_MGMT_CONFIG_MGMT_CLOCK_SELECT(val) ((val) & 0x7) +#define MII_MGMT_CONFIG_NO_PREAMBLE (0x00000010) +#define MII_MGMT_CONFIG_SCAN_INCREMENT (0x00000020) +#define MII_MGMT_CONFIG_RESET_MGMT (0x80000000) + +#define reg_MII_MGMT_COMMAND(base) __REG32(base, 0x00000024) +#define MII_MGMT_COMMAND_READ_CYCLE (0x00000001) +#define MII_MGMT_COMMAND_SCAN_CYCLE (0x00000002) + +#define reg_MII_MGMT_ADDRESS(base) __REG32(base, 0x00000028) +#define reg_MII_MGMT_CONTROL(base) __REG32(base, 0x0000002c) +#define reg_MII_MGMT_STATUS(base) __REG32(base, 0x00000030) + +#define reg_MII_MGMT_INDICATORS(base) __REG32(base, 0x00000034) +#define MII_MGMT_INDICATORS_BUSY (0x00000001) +#define MII_MGMT_INDICATORS_SCAN (0x00000002) +#define MII_MGMT_INDICATORS_NOT_VALID (0x00000004) + +#define reg_INTERFACE_STATUS(base) __REG32(base, 0x0000003c) +#define INTERFACE_STATUS_LINK_FAIL (0x00000008) +#define INTERFACE_STATUS_EXCESS_DEFER (0x00000200) + +#define reg_STATION_ADDRESS_1(base) __REG32(base, 0x00000040) +#define reg_STATION_ADDRESS_2(base) __REG32(base, 0x00000044) + +#define reg_PORT_CONTROL(base) __REG32(base, 0x00000200) +#define PORT_CONTROL_PRI (0x00000001) +#define PORT_CONTROL_BPT (0x00010000) +#define PORT_CONTROL_SPD (0x00040000) +#define PORT_CONTROL_RBC (0x00080000) +#define PORT_CONTROL_PRB (0x00200000) +#define PORT_CONTROL_DIS (0x00400000) +#define PORT_CONTROL_TBI (0x00800000) +#define PORT_CONTROL_STE (0x10000000) +#define PORT_CONTROL_ZOR (0x20000000) +#define PORT_CONTROL_CLR (0x40000000) +#define PORT_CONTROL_SRT (0x80000000) + +#define reg_TX_CONFIG(base) __REG32(base, 0x00000220) +#define TX_CONFIG_START_Q (0x00000003) +#define TX_CONFIG_EHP (0x00400000) +#define TX_CONFIG_CHP (0x00800000) +#define TX_CONFIG_RST (0x80000000) + +#define reg_TX_CONTROL(base) __REG32(base, 0x00000224) +#define TX_CONTROL_GO (0x00008000) +#define TX_CONTROL_MP (0x01000000) +#define TX_CONTROL_EAI (0x20000000) +#define TX_CONTROL_ABT (0x40000000) +#define TX_CONTROL_EII (0x80000000) + +#define reg_TX_STATUS(base) __REG32(base, 0x00000228) +#define TX_STATUS_QUEUE_USABLE (0x0000000f) +#define TX_STATUS_CURR_Q (0x00000300) +#define TX_STATUS_ACT (0x00008000) +#define TX_STATUS_QUEUE_IDLE (0x000f0000) +#define TX_STATUS_EOQ_PENDING (0x0f000000) + +#define reg_TX_EXTENDED_STATUS(base) __REG32(base, 0x0000022c) +#define TX_EXTENDED_STATUS_END_OF_QUEUE_CONDITION (0x0000000f) +#define TX_EXTENDED_STATUS_END_OF_FRAME_CONDITION (0x00000f00) +#define TX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) +#define TX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) + +#define reg_TX_THRESHOLDS(base) __REG32(base, 0x00000230) + +#define reg_TX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000270) +#define TX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) +#define TX_DIAGNOSTIC_ADDR_DFR (0x40000000) +#define TX_DIAGNOSTIC_ADDR_AI (0x80000000) + +#define reg_TX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000274) + +#define reg_TX_ERROR_STATUS(base) __REG32(base, 0x00000278) +#define TX_ERROR_STATUS (0x00000278) +#define TX_ERROR_STATUS_QUEUE_0_ERROR_RESPONSE (0x0000000f) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_0 (0x00000010) +#define TX_ERROR_STATUS_RER_ON_QUEUE_0 (0x00000020) +#define TX_ERROR_STATUS_TER_ON_QUEUE_0 (0x00000040) +#define TX_ERROR_STATUS_DER_ON_QUEUE_0 (0x00000080) +#define TX_ERROR_STATUS_QUEUE_1_ERROR_RESPONSE (0x00000f00) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_1 (0x00001000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_1 (0x00002000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_1 (0x00004000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_1 (0x00008000) +#define TX_ERROR_STATUS_QUEUE_2_ERROR_RESPONSE (0x000f0000) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_2 (0x00100000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_2 (0x00200000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_2 (0x00400000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_2 (0x00800000) +#define TX_ERROR_STATUS_QUEUE_3_ERROR_RESPONSE (0x0f000000) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_3 (0x10000000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_3 (0x20000000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_3 (0x40000000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_3 (0x80000000) + +#define reg_TX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000280) +#define TX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) +#define TX_QUEUE_0_CONFIG_BSWP (0x00000400) +#define TX_QUEUE_0_CONFIG_WSWP (0x00000800) +#define TX_QUEUE_0_CONFIG_AM (0x00004000) +#define TX_QUEUE_0_CONFIG_GVI (0x00008000) +#define TX_QUEUE_0_CONFIG_EEI (0x00010000) +#define TX_QUEUE_0_CONFIG_ELI (0x00020000) +#define TX_QUEUE_0_CONFIG_ENI (0x00040000) +#define TX_QUEUE_0_CONFIG_ESI (0x00080000) +#define TX_QUEUE_0_CONFIG_EDI (0x00100000) + +#define reg_TX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000284) +#define TX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) +#define TX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) +#define TX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) +#define TX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) + +#define OCN_PORT_HLP 0 /* HLP Interface */ +#define OCN_PORT_PCI_X 1 /* PCI-X Interface */ +#define OCN_PORT_PROCESSOR_MASTER 2 /* Processor Interface (master) */ +#define OCN_PORT_PROCESSOR_SLAVE 3 /* Processor Interface (slave) */ +#define OCN_PORT_MEMORY 4 /* Memory Controller */ +#define OCN_PORT_DMA 5 /* DMA Controller */ +#define OCN_PORT_ETHERNET 6 /* Ethernet Controller */ +#define OCN_PORT_PRINT 7 /* Print Engine Interface */ + +#define reg_TX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000288) + +#define reg_TX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000028c) +#define TX_QUEUE_0_PTR_HIGH_VALID (0x80000000) + +#define reg_RX_CONFIG(base) __REG32(base, 0x00000320) +#define RX_CONFIG_DEF_Q (0x00000003) +#define RX_CONFIG_EMF (0x00000100) +#define RX_CONFIG_EUF (0x00000200) +#define RX_CONFIG_BFE (0x00000400) +#define RX_CONFIG_MFE (0x00000800) +#define RX_CONFIG_UFE (0x00001000) +#define RX_CONFIG_SE (0x00002000) +#define RX_CONFIG_ABF (0x00200000) +#define RX_CONFIG_APE (0x00400000) +#define RX_CONFIG_CHP (0x00800000) +#define RX_CONFIG_RST (0x80000000) + +#define reg_RX_CONTROL(base) __REG32(base, 0x00000324) +#define GE_E0_RX_CONTROL_QUEUE_ENABLES (0x0000000f) +#define GE_E0_RX_CONTROL_GO (0x00008000) +#define GE_E0_RX_CONTROL_EAI (0x20000000) +#define GE_E0_RX_CONTROL_ABT (0x40000000) +#define GE_E0_RX_CONTROL_EII (0x80000000) + +#define reg_RX_EXTENDED_STATUS(base) __REG32(base, 0x0000032c) +#define RX_EXTENDED_STATUS (0x0000032c) +#define RX_EXTENDED_STATUS_EOQ (0x0000000f) +#define RX_EXTENDED_STATUS_EOQ_0 (0x00000001) +#define RX_EXTENDED_STATUS_EOF (0x00000f00) +#define RX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) +#define RX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) + +#define reg_RX_THRESHOLDS(base) __REG32(base, 0x00000330) + +#define reg_RX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000370) +#define RX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) +#define RX_DIAGNOSTIC_ADDR_DFR (0x40000000) +#define RX_DIAGNOSTIC_ADDR_AI (0x80000000) + +#define reg_RX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000374) + +#define reg_RX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000380) +#define RX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) +#define RX_QUEUE_0_CONFIG_BSWP (0x00000400) +#define RX_QUEUE_0_CONFIG_WSWP (0x00000800) +#define RX_QUEUE_0_CONFIG_AM (0x00004000) +#define RX_QUEUE_0_CONFIG_EEI (0x00010000) +#define RX_QUEUE_0_CONFIG_ELI (0x00020000) +#define RX_QUEUE_0_CONFIG_ENI (0x00040000) +#define RX_QUEUE_0_CONFIG_ESI (0x00080000) +#define RX_QUEUE_0_CONFIG_EDI (0x00100000) + +#define reg_RX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000384) +#define RX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) +#define RX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) +#define RX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) +#define RX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) + +#define reg_RX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000388) + +#define reg_RX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000038c) +#define RX_QUEUE_0_PTR_HIGH_VALID (0x80000000) + +/* + * PHY register definitions + */ +/* the first 15 PHY registers are standard. */ +#define PHY_CTRL_REG 0 /* Control Register */ +#define PHY_STATUS_REG 1 /* Status Regiser */ +#define PHY_ID1_REG 2 /* Phy Id Reg (word 1) */ +#define PHY_ID2_REG 3 /* Phy Id Reg (word 2) */ +#define PHY_AN_ADV_REG 4 /* Autoneg Advertisement */ +#define PHY_LP_ABILITY_REG 5 /* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP_REG 6 /* Autoneg Expansion Reg */ +#define PHY_NEXT_PAGE_TX_REG 7 /* Next Page TX */ +#define PHY_LP_NEXT_PAGE_REG 8 /* Link Partner Next Page */ +#define PHY_1000T_CTRL_REG 9 /* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS_REG 10 /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS_REG 11 /* Extended Status Reg */ + +/* + * PHY Register bit masks. + */ +#define PHY_CTRL_RESET (1 << 15) +#define PHY_CTRL_LOOPBACK (1 << 14) +#define PHY_CTRL_SPEED0 (1 << 13) +#define PHY_CTRL_AN_EN (1 << 12) +#define PHY_CTRL_PWR_DN (1 << 11) +#define PHY_CTRL_ISOLATE (1 << 10) +#define PHY_CTRL_RESTART_AN (1 << 9) +#define PHY_CTRL_FULL_DUPLEX (1 << 8) +#define PHY_CTRL_CT_EN (1 << 7) +#define PHY_CTRL_SPEED1 (1 << 6) + +#define PHY_STAT_100BASE_T4 (1 << 15) +#define PHY_STAT_100BASE_X_FD (1 << 14) +#define PHY_STAT_100BASE_X_HD (1 << 13) +#define PHY_STAT_10BASE_T_FD (1 << 12) +#define PHY_STAT_10BASE_T_HD (1 << 11) +#define PHY_STAT_100BASE_T2_FD (1 << 10) +#define PHY_STAT_100BASE_T2_HD (1 << 9) +#define PHY_STAT_EXT_STAT (1 << 8) +#define PHY_STAT_RESERVED (1 << 7) +#define PHY_STAT_MFPS (1 << 6) /* Management Frames Preamble Suppression */ +#define PHY_STAT_AN_COMPLETE (1 << 5) +#define PHY_STAT_REM_FAULT (1 << 4) +#define PHY_STAT_AN_CAP (1 << 3) +#define PHY_STAT_LINK_UP (1 << 2) +#define PHY_STAT_JABBER (1 << 1) +#define PHY_STAT_EXT_CAP (1 << 0) + +#define TBI_CONTROL_2 0x11 +#define TBI_CONTROL_2_ENABLE_COMMA_DETECT 0x0001 +#define TBI_CONTROL_2_ENABLE_WRAP 0x0002 +#define TBI_CONTROL_2_G_MII_MODE 0x0010 +#define TBI_CONTROL_2_RECEIVE_CLOCK_SELECT 0x0020 +#define TBI_CONTROL_2_AUTO_NEGOTIATION_SENSE 0x0100 +#define TBI_CONTROL_2_DISABLE_TRANSMIT_RUNNING_DISPARITY 0x1000 +#define TBI_CONTROL_2_DISABLE_RECEIVE_RUNNING_DISPARITY 0x2000 +#define TBI_CONTROL_2_SHORTCUT_LINK_TIMER 0x4000 +#define TBI_CONTROL_2_SOFT_RESET 0x8000 + +/* marvel specific */ +#define MV1111_EXT_CTRL1_REG 16 /* PHY Specific Control Reg */ +#define MV1111_SPEC_STAT_REG 17 /* PHY Specific Status Reg */ +#define MV1111_EXT_CTRL2_REG 20 /* Extended PHY Specific Control Reg */ + +/* + * MARVELL 88E1111 PHY register bit masks + */ +/* PHY Specific Status Register (MV1111_EXT_CTRL1_REG) */ + +#define SPEC_STAT_SPEED_MASK (3 << 14) +#define SPEC_STAT_FULL_DUP (1 << 13) +#define SPEC_STAT_PAGE_RCVD (1 << 12) +#define SPEC_STAT_RESOLVED (1 << 11) /* Speed and Duplex Resolved */ +#define SPEC_STAT_LINK_UP (1 << 10) +#define SPEC_STAT_CABLE_LEN_MASK (7 << 7) /* Cable Length (100/1000 modes only) */ +#define SPEC_STAT_MDIX (1 << 6) +#define SPEC_STAT_POLARITY (1 << 1) +#define SPEC_STAT_JABBER (1 << 0) + +#define SPEED_1000 (2 << 14) +#define SPEED_100 (1 << 14) +#define SPEED_10 (0 << 14) + +#define TBI_ADDR 0x1E /* Ten Bit Interface address */ + +/* negotiated link parameters */ +#define LINK_SPEED_UNKNOWN 0 +#define LINK_SPEED_10 1 +#define LINK_SPEED_100 2 +#define LINK_SPEED_1000 3 + +#define LINK_DUPLEX_UNKNOWN 0 +#define LINK_DUPLEX_HALF 1 +#define LINK_DUPLEX_FULL 2 + +static unsigned int phy_address[] = { 8, 9 }; + +#define vuint32 volatile u32 + +/* TX/RX buffer descriptors. MUST be cache line aligned in memory. (32 byte) + * This structure is accessed by the ethernet DMA engine which means it + * MUST be in LITTLE ENDIAN format */ +struct dma_descriptor { + vuint32 start_addr0; /* buffer address, least significant bytes. */ + vuint32 start_addr1; /* buffer address, most significant bytes. */ + vuint32 next_descr_addr0;/* next descriptor address, least significant bytes. Must be 64-bit aligned. */ + vuint32 next_descr_addr1;/* next descriptor address, most significant bytes. */ + vuint32 vlan_byte_count;/* VLAN tag(top 2 bytes) and byte countt (bottom 2 bytes). */ + vuint32 config_status; /* Configuration/Status. */ + vuint32 reserved1; /* reserved to make the descriptor cache line aligned. */ + vuint32 reserved2; /* reserved to make the descriptor cache line aligned. */ +}; + +/* last next descriptor address flag */ +#define DMA_DESCR_LAST (1 << 31) + +/* TX DMA descriptor config status bits */ +#define DMA_DESCR_TX_EOF (1 << 0) /* end of frame */ +#define DMA_DESCR_TX_SOF (1 << 1) /* start of frame */ +#define DMA_DESCR_TX_PFVLAN (1 << 2) +#define DMA_DESCR_TX_HUGE (1 << 3) +#define DMA_DESCR_TX_PAD (1 << 4) +#define DMA_DESCR_TX_CRC (1 << 5) +#define DMA_DESCR_TX_DESCR_INT (1 << 14) +#define DMA_DESCR_TX_RETRY_COUNT 0x000F0000 +#define DMA_DESCR_TX_ONE_COLLISION (1 << 20) +#define DMA_DESCR_TX_LATE_COLLISION (1 << 24) +#define DMA_DESCR_TX_UNDERRUN (1 << 25) +#define DMA_DESCR_TX_RETRY_LIMIT (1 << 26) +#define DMA_DESCR_TX_OK (1 << 30) +#define DMA_DESCR_TX_OWNER (1 << 31) + +/* RX DMA descriptor status bits */ +#define DMA_DESCR_RX_EOF (1 << 0) +#define DMA_DESCR_RX_SOF (1 << 1) +#define DMA_DESCR_RX_VTF (1 << 2) +#define DMA_DESCR_RX_FRAME_IS_TYPE (1 << 3) +#define DMA_DESCR_RX_SHORT_FRAME (1 << 4) +#define DMA_DESCR_RX_HASH_MATCH (1 << 7) +#define DMA_DESCR_RX_BAD_FRAME (1 << 8) +#define DMA_DESCR_RX_OVERRUN (1 << 9) +#define DMA_DESCR_RX_MAX_FRAME_LEN (1 << 11) +#define DMA_DESCR_RX_CRC_ERROR (1 << 12) +#define DMA_DESCR_RX_DESCR_INT (1 << 13) +#define DMA_DESCR_RX_OWNER (1 << 15) + +#define RX_BUFFER_SIZE PKTSIZE +#define NUM_RX_DESC PKTBUFSRX + +static struct dma_descriptor tx_descriptor __attribute__ ((aligned(32))); + +static struct dma_descriptor rx_descr_array[NUM_RX_DESC] + __attribute__ ((aligned(32))); + +static struct dma_descriptor *rx_descr_current; + +static int tsi108_eth_probe(struct eth_device *dev, bd_t * bis); +static int tsi108_eth_send(struct eth_device *dev, + volatile void *packet, int length); +static int tsi108_eth_recv(struct eth_device *dev); +static void tsi108_eth_halt(struct eth_device *dev); +static unsigned int read_phy(unsigned int base, + unsigned int phy_addr, unsigned int phy_reg); +static void write_phy(unsigned int base, + unsigned int phy_addr, + unsigned int phy_reg, unsigned int phy_data); + +#if TSI108_ETH_DEBUG > 100 +/* + * print phy debug infomation + */ +static void dump_phy_regs(unsigned int phy_addr) +{ + int i; + + printf("PHY %d registers\n", phy_addr); + for (i = 0; i <= 30; i++) { + printf("%2d 0x%04x\n", i, read_phy(ETH_BASE, phy_addr, i)); + } + printf("\n"); + +} +#else +#define dump_phy_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void tx_diag_regs(unsigned int base) +{ + int i; + unsigned long dummy; + + printf("TX diagnostics registers\n"); + reg_TX_DIAGNOSTIC_ADDR(base) = 0x00 | TX_DIAGNOSTIC_ADDR_AI; + udelay(1000); + dummy = reg_TX_DIAGNOSTIC_DATA(base); + for (i = 0x00; i <= 0x05; i++) { + udelay(1000); + printf("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); + } + reg_TX_DIAGNOSTIC_ADDR(base) = 0x40 | TX_DIAGNOSTIC_ADDR_AI; + udelay(1000); + dummy = reg_TX_DIAGNOSTIC_DATA(base); + for (i = 0x40; i <= 0x47; i++) { + udelay(1000); + printf("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); + } + printf("\n"); + +} +#else +#define tx_diag_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void rx_diag_regs(unsigned int base) +{ + int i; + unsigned long dummy; + + printf("RX diagnostics registers\n"); + reg_RX_DIAGNOSTIC_ADDR(base) = 0x00 | RX_DIAGNOSTIC_ADDR_AI; + udelay(1000); + dummy = reg_RX_DIAGNOSTIC_DATA(base); + for (i = 0x00; i <= 0x05; i++) { + udelay(1000); + printf("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); + } + reg_RX_DIAGNOSTIC_ADDR(base) = 0x40 | RX_DIAGNOSTIC_ADDR_AI; + udelay(1000); + dummy = reg_RX_DIAGNOSTIC_DATA(base); + for (i = 0x08; i <= 0x0a; i++) { + udelay(1000); + printf("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); + } + printf("\n"); + +} +#else +#define rx_diag_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void debug_mii_regs(unsigned int base) +{ + printf("MII_MGMT_CONFIG 0x%08x\n", reg_MII_MGMT_CONFIG(base)); + printf("MII_MGMT_COMMAND 0x%08x\n", reg_MII_MGMT_COMMAND(base)); + printf("MII_MGMT_ADDRESS 0x%08x\n", reg_MII_MGMT_ADDRESS(base)); + printf("MII_MGMT_CONTROL 0x%08x\n", reg_MII_MGMT_CONTROL(base)); + printf("MII_MGMT_STATUS 0x%08x\n", reg_MII_MGMT_STATUS(base)); + printf("MII_MGMT_INDICATORS 0x%08x\n", reg_MII_MGMT_INDICATORS(base)); + printf("\n"); + +} +#else +#define debug_mii_regs(base) do{}while(0) +#endif + +/* + * Wait until the phy bus is non-busy + */ +static void phy_wait(unsigned int base, unsigned int condition) +{ + int timeout; + + timeout = 0; + while (reg_MII_MGMT_INDICATORS(base) & condition) { + udelay(10); + if (++timeout > 10000) { + printf("ERROR: timeout waiting for phy bus (%d)\n", + condition); + break; + } + } +} + +/* + * read phy register + */ +static unsigned int read_phy(unsigned int base, + unsigned int phy_addr, unsigned int phy_reg) +{ + unsigned int value; + + phy_wait(base, MII_MGMT_INDICATORS_BUSY); + + reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; + + /* Ensure that the Read Cycle bit is cleared prior to next read cycle */ + reg_MII_MGMT_COMMAND(base) = 0; + + /* start the read */ + reg_MII_MGMT_COMMAND(base) = MII_MGMT_COMMAND_READ_CYCLE; + + /* wait for the read to complete */ + phy_wait(base, + MII_MGMT_INDICATORS_NOT_VALID | MII_MGMT_INDICATORS_BUSY); + + value = reg_MII_MGMT_STATUS(base); + + reg_MII_MGMT_COMMAND(base) = 0; + + return value; +} + +/* + * write phy register + */ +static void write_phy(unsigned int base, + unsigned int phy_addr, + unsigned int phy_reg, unsigned int phy_data) +{ + phy_wait(base, MII_MGMT_INDICATORS_BUSY); + + reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; + + /* Ensure that the Read Cycle bit is cleared prior to next cycle */ + reg_MII_MGMT_COMMAND(base) = 0; + + /* start the write */ + reg_MII_MGMT_CONTROL(base) = phy_data; +} + +/* + * configure the marvell 88e1111 phy + */ +static int marvell_88e_phy_config(struct eth_device *dev, int *speed, + int *duplex) +{ + unsigned long base; + unsigned long phy_addr; + unsigned int phy_status; + unsigned int phy_spec_status; + int timeout; + int phy_speed; + int phy_duplex; + unsigned int value; + + phy_speed = LINK_SPEED_UNKNOWN; + phy_duplex = LINK_DUPLEX_UNKNOWN; + + base = dev->iobase; + phy_addr = (unsigned long)dev->priv; + + /* Take the PHY out of reset. */ + write_phy(ETH_BASE, phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET); + + /* Wait for the reset process to complete. */ + udelay(10); + timeout = 0; + while ((phy_status = + read_phy(ETH_BASE, phy_addr, PHY_CTRL_REG)) & PHY_CTRL_RESET) { + udelay(10); + if (++timeout > 10000) { + printf("ERROR: timeout waiting for phy reset\n"); + break; + } + } + + /* TBI Configuration. */ + write_phy(base, TBI_ADDR, TBI_CONTROL_2, TBI_CONTROL_2_G_MII_MODE | + TBI_CONTROL_2_RECEIVE_CLOCK_SELECT); + /* Wait for the link to be established. */ + timeout = 0; + do { + udelay(20000); + phy_status = read_phy(ETH_BASE, phy_addr, PHY_STATUS_REG); + if (++timeout > 100) { + debug_lev(1, "ERROR: unable to establish link!!!\n"); + break; + } + } while ((phy_status & PHY_STAT_LINK_UP) == 0); + + if ((phy_status & PHY_STAT_LINK_UP) == 0) { + return 0; + } + + value = 0; + phy_spec_status = read_phy(ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); + if (phy_spec_status & SPEC_STAT_RESOLVED) { + switch (phy_spec_status & SPEC_STAT_SPEED_MASK) { + case SPEED_1000: + phy_speed = LINK_SPEED_1000; + value |= PHY_CTRL_SPEED1; + break; + case SPEED_100: + phy_speed = LINK_SPEED_100; + value |= PHY_CTRL_SPEED0; + break; + case SPEED_10: + phy_speed = LINK_SPEED_10; + break; + } + if (phy_spec_status & SPEC_STAT_FULL_DUP) { + phy_duplex = LINK_DUPLEX_FULL; + value |= PHY_CTRL_FULL_DUPLEX; + } else { + phy_duplex = LINK_DUPLEX_HALF; + } + } + /* set TBI speed */ + write_phy(base, TBI_ADDR, PHY_CTRL_REG, value); + write_phy(base, TBI_ADDR, PHY_AN_ADV_REG, 0x0060); + +#if TSI108_ETH_DEBUG > 0 + printf("%s link is up", dev->name); + phy_spec_status = read_phy(ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); + if (phy_spec_status & SPEC_STAT_RESOLVED) { + switch (phy_speed) { + case LINK_SPEED_1000: + printf(", 1000 Mbps"); + break; + case LINK_SPEED_100: + printf(", 100 Mbps"); + break; + case LINK_SPEED_10: + printf(", 10 Mbps"); + break; + } + if (phy_duplex == LINK_DUPLEX_FULL) { + printf(", Full duplex"); + } else { + printf(", Half duplex"); + } + } + printf("\n"); +#endif + + dump_phy_regs(TBI_ADDR); + if (speed) { + *speed = phy_speed; + } + if (duplex) { + *duplex = phy_duplex; + } + + return 1; +} + +/* + * External interface + * + * register the tsi108 ethernet controllers with the multi-ethernet system + */ +int tsi108_eth_initialize(bd_t * bis) +{ + struct eth_device *dev; + int index; + + for (index = 0; index < CONFIG_TSI108_ETH_NUM_PORTS; index++) { + dev = (struct eth_device *)malloc(sizeof(struct eth_device)); + + sprintf(dev->name, "TSI108_eth%d", index); + + dev->iobase = ETH_BASE + (index * ETH_PORT_OFFSET); + dev->priv = (void *)(phy_address[index]); + dev->init = tsi108_eth_probe; + dev->halt = tsi108_eth_halt; + dev->send = tsi108_eth_send; + dev->recv = tsi108_eth_recv; + + eth_register(dev); + } + return index; +} + +/* + * probe for and initialize a single ethernet interface + */ +static int tsi108_eth_probe(struct eth_device *dev, bd_t * bis) +{ + unsigned long base; + unsigned long value; + int index; + struct dma_descriptor *tx_descr; + struct dma_descriptor *rx_descr; + int speed; + int duplex; + + base = dev->iobase; + + reg_PORT_CONTROL(base) = PORT_CONTROL_STE | PORT_CONTROL_BPT; + + /* Bring DMA/FIFO out of reset. */ + reg_TX_CONFIG(base) = 0x00000000; + reg_RX_CONFIG(base) = 0x00000000; + + reg_TX_THRESHOLDS(base) = (192 << 16) | 192; + reg_RX_THRESHOLDS(base) = (192 << 16) | 112; + + /* Bring MAC out of reset. */ + reg_MAC_CONFIG_1(base) = 0x00000000; + + /* DMA MAC configuration. */ + reg_MAC_CONFIG_1(base) = + MAC_CONFIG_1_RX_ENABLE | MAC_CONFIG_1_TX_ENABLE; + + reg_MII_MGMT_CONFIG(base) = MII_MGMT_CONFIG_NO_PREAMBLE; + reg_MAXIMUM_FRAME_LENGTH(base) = RX_BUFFER_SIZE; + + /* Note: Early tsi108 manual did not have correct byte order + * for the station address.*/ + reg_STATION_ADDRESS_1(base) = (dev->enetaddr[5] << 24) | + (dev->enetaddr[4] << 16) | + (dev->enetaddr[3] << 8) | (dev->enetaddr[2] << 0); + + reg_STATION_ADDRESS_2(base) = (dev->enetaddr[1] << 24) | + (dev->enetaddr[0] << 16); + + if (marvell_88e_phy_config(dev, &speed, &duplex) == 0) { + return 0; + } + + value = + MAC_CONFIG_2_PREAMBLE_LENGTH(7) | MAC_CONFIG_2_PAD_CRC | + MAC_CONFIG_2_CRC_ENABLE; + if (speed == LINK_SPEED_1000) { + value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_BYTE); + } else { + value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_NIBBLE); + reg_PORT_CONTROL(base) |= PORT_CONTROL_SPD; + } + if (duplex == LINK_DUPLEX_FULL) { + value |= MAC_CONFIG_2_FULL_DUPLEX; + reg_PORT_CONTROL(base) &= ~PORT_CONTROL_BPT; + } else { + reg_PORT_CONTROL(base) |= PORT_CONTROL_BPT; + } + reg_MAC_CONFIG_2(base) = value; + + reg_RX_CONFIG(base) = RX_CONFIG_SE; + reg_RX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; + reg_RX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; + + /* initialize the RX DMA descriptors */ + rx_descr = &rx_descr_array[0]; + rx_descr_current = rx_descr; + for (index = 0; index < NUM_RX_DESC; index++) { + /* make sure the receive buffers are not in cache */ + invalidate_dcache_range((unsigned long)NetRxPackets[index], + (unsigned long)NetRxPackets[index] + + RX_BUFFER_SIZE); + rx_descr->start_addr0 = + cpu_to_le32((vuint32) NetRxPackets[index]); + rx_descr->start_addr1 = 0; + rx_descr->next_descr_addr0 = + cpu_to_le32((vuint32) (rx_descr + 1)); + rx_descr->next_descr_addr1 = 0; + rx_descr->vlan_byte_count = 0; + rx_descr->config_status = cpu_to_le32((RX_BUFFER_SIZE << 16) | + DMA_DESCR_RX_OWNER); + rx_descr++; + } + rx_descr--; + rx_descr->next_descr_addr0 = 0; + rx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); + /* Push the descriptors to RAM so the ethernet DMA can see them */ + invalidate_dcache_range((unsigned long)rx_descr_array, + (unsigned long)rx_descr_array + + sizeof(rx_descr_array)); + + /* enable RX queue */ + reg_RX_CONTROL(base) = TX_CONTROL_GO | 0x01; + reg_RX_QUEUE_0_PTR_LOW(base) = (u32) rx_descr_current; + /* enable receive DMA */ + reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; + + reg_TX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; + reg_TX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; + + /* initialize the TX DMA descriptor */ + tx_descr = &tx_descriptor; + + tx_descr->start_addr0 = 0; + tx_descr->start_addr1 = 0; + tx_descr->next_descr_addr0 = 0; + tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); + tx_descr->vlan_byte_count = 0; + tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OK | + DMA_DESCR_TX_SOF | + DMA_DESCR_TX_EOF); + /* enable TX queue */ + reg_TX_CONTROL(base) = TX_CONTROL_GO | 0x01; + + return 1; +} + +/* + * send a packet + */ +static int tsi108_eth_send(struct eth_device *dev, + volatile void *packet, int length) +{ + unsigned long base; + int timeout; + struct dma_descriptor *tx_descr; + unsigned long status; + + base = dev->iobase; + tx_descr = &tx_descriptor; + + /* Wait until the last packet has been transmitted. */ + timeout = 0; + do { + /* make sure we see the changes made by the DMA engine */ + invalidate_dcache_range((unsigned long)tx_descr, + (unsigned long)tx_descr + + sizeof(struct dma_descriptor)); + + if (timeout != 0) { + udelay(15); + } + if (++timeout > 10000) { + tx_diag_regs(base); + debug_lev(1, + "ERROR: timeout waiting for last transmit packet to be sent\n"); + return 0; + } + } while (tx_descr->config_status & cpu_to_le32(DMA_DESCR_TX_OWNER)); + + status = le32_to_cpu(tx_descr->config_status); + if ((status & DMA_DESCR_TX_OK) == 0) { +#ifdef TX_PRINT_ERRORS + printf("TX packet error: 0x%08x\n %s%s%s%s\n", status, + status & DMA_DESCR_TX_OK ? "tx error, " : "", + status & DMA_DESCR_TX_RETRY_LIMIT ? + "retry limit reached, " : "", + status & DMA_DESCR_TX_UNDERRUN ? "underrun, " : "", + status & DMA_DESCR_TX_LATE_COLLISION ? "late collision, " + : ""); +#endif + } + + debug_lev(9, "sending packet %d\n", length); + tx_descr->start_addr0 = cpu_to_le32((vuint32) packet); + tx_descr->start_addr1 = 0; + tx_descr->next_descr_addr0 = 0; + tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); + tx_descr->vlan_byte_count = cpu_to_le32(length); + tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OWNER | + DMA_DESCR_TX_CRC | + DMA_DESCR_TX_PAD | + DMA_DESCR_TX_SOF | + DMA_DESCR_TX_EOF); + + invalidate_dcache_range((unsigned long)tx_descr, + (unsigned long)tx_descr + + sizeof(struct dma_descriptor)); + + invalidate_dcache_range((unsigned long)packet, + (unsigned long)packet + length); + + reg_TX_QUEUE_0_PTR_LOW(base) = (u32) tx_descr; + reg_TX_QUEUE_0_PTR_HIGH(base) = TX_QUEUE_0_PTR_HIGH_VALID; + + return length; +} + +/* + * Check for received packets and send them up the protocal stack + */ +static int tsi108_eth_recv(struct eth_device *dev) +{ + struct dma_descriptor *rx_descr; + unsigned long base; + int length = 0; + unsigned long status; + volatile uchar *buffer; + + base = dev->iobase; + + /* make sure we see the changes made by the DMA engine */ + invalidate_dcache_range((unsigned long)rx_descr_array, + (unsigned long)rx_descr_array + + sizeof(rx_descr_array)); + + /* process all of the received packets */ + rx_descr = rx_descr_current; + while ((rx_descr->config_status & cpu_to_le32(DMA_DESCR_RX_OWNER)) == 0) { + /* check for error */ + status = le32_to_cpu(rx_descr->config_status); + if (status & DMA_DESCR_RX_BAD_FRAME) { +#ifdef RX_PRINT_ERRORS + printf("RX packet error: 0x%08x\n %s%s%s%s%s%s\n", + status, + status & DMA_DESCR_RX_FRAME_IS_TYPE ? "too big, " + : "", + status & DMA_DESCR_RX_SHORT_FRAME ? "too short, " + : "", + status & DMA_DESCR_RX_BAD_FRAME ? "bad frame, " : + "", + status & DMA_DESCR_RX_OVERRUN ? "overrun, " : "", + status & DMA_DESCR_RX_MAX_FRAME_LEN ? + "max length, " : "", + status & DMA_DESCR_RX_CRC_ERROR ? "CRC error, " : + ""); +#endif + } else { + length = + le32_to_cpu(rx_descr->vlan_byte_count) & 0xFFFF; + + /*** process packet ***/ + buffer = + (volatile uchar + *)(le32_to_cpu(rx_descr->start_addr0)); + NetReceive(buffer, length); + + invalidate_dcache_range((unsigned long)buffer, + (unsigned long)buffer + + RX_BUFFER_SIZE); + } + /* Give this buffer back to the DMA engine */ + rx_descr->vlan_byte_count = 0; + rx_descr->config_status = cpu_to_le32((RX_BUFFER_SIZE << 16) | + DMA_DESCR_RX_OWNER); + /* move descriptor pointer forward */ + rx_descr = + (struct dma_descriptor + *)(le32_to_cpu(rx_descr->next_descr_addr0)); + if (rx_descr == 0) { + rx_descr = &rx_descr_array[0]; + } + } + /* remember where we are for next time */ + rx_descr_current = rx_descr; + + /* If the DMA engine has reached the end of the queue + * start over at the begining */ + if (reg_RX_EXTENDED_STATUS(base) & RX_EXTENDED_STATUS_EOQ_0) { + + reg_RX_EXTENDED_STATUS(base) = RX_EXTENDED_STATUS_EOQ_0; + reg_RX_QUEUE_0_PTR_LOW(base) = (u32) & rx_descr_array[0]; + reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; + } + + return length; +} + +/* + * disable an ethernet interface + */ +static void tsi108_eth_halt(struct eth_device *dev) +{ + unsigned long base; + + base = dev->iobase; + + /* Put DMA/FIFO into reset state. */ + reg_TX_CONFIG(base) = TX_CONFIG_RST; + reg_RX_CONFIG(base) = RX_CONFIG_RST; + + /* Put MAC into reset state. */ + reg_MAC_CONFIG_1(base) = MAC_CONFIG_1_SOFT_RESET; +} + +#endif -- cgit v1.2.1 From 9226e7d6f09b9a1ac074cd918c81225a4689bba8 Mon Sep 17 00:00:00 2001 From: roy zang Date: Thu, 2 Nov 2006 19:11:06 +0800 Subject: Tsi108 on chip pci controller support. If there is no pci card, the tsi108/109 pci configure read will cause a machine check exception to the processor. PCI error should also be cleared after the read. Signed-off-by: Alexandre Bounine Signed-off-by: Roy Zang --- drivers/tsi108_pci.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 drivers/tsi108_pci.c (limited to 'drivers') diff --git a/drivers/tsi108_pci.c b/drivers/tsi108_pci.c new file mode 100644 index 0000000000..f374ede662 --- /dev/null +++ b/drivers/tsi108_pci.c @@ -0,0 +1,178 @@ +/* + * (C) Copyright 2004 Tundra Semiconductor Corp. + * Alex Bounine + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * PCI initialisation for the Tsi108 EMU board. + */ + +#include + +#ifdef CONFIG_TSI108_PCI + +#include +#include +#include +#include + +struct pci_controller local_hose; + +void tsi108_clear_pci_error(void) +{ + u32 err_stat, err_addr, pci_stat; + + /* + * Quietly clear errors signalled as result of PCI/X configuration read + * requests. + */ + /* Read PB Error Log Registers */ + err_stat = *(volatile u32 *)(CFG_TSI108_CSR_BASE + + TSI108_PB_REG_OFFSET + PB_ERRCS); + err_addr = *(volatile u32 *)(CFG_TSI108_CSR_BASE + + TSI108_PB_REG_OFFSET + PB_AERR); + if (err_stat & PB_ERRCS_ES) { + /* Clear PCI/X bus errors if applicable */ + if ((err_addr & 0xFF000000) == CFG_PCI_CFG_BASE) { + /* Clear error flag */ + *(u32 *) (CFG_TSI108_CSR_BASE + + TSI108_PB_REG_OFFSET + PB_ERRCS) = + PB_ERRCS_ES; + + /* Clear read error reported in PB_ISR */ + *(u32 *) (CFG_TSI108_CSR_BASE + + TSI108_PB_REG_OFFSET + PB_ISR) = + PB_ISR_PBS_RD_ERR; + + /* Clear errors reported by PCI CSR (Normally Master Abort) */ + pci_stat = *(volatile u32 *)(CFG_TSI108_CSR_BASE + + TSI108_PCI_REG_OFFSET + + PCI_CSR); + *(volatile u32 *)(CFG_TSI108_CSR_BASE + + TSI108_PCI_REG_OFFSET + PCI_CSR) = + pci_stat; + + *(volatile u32 *)(CFG_TSI108_CSR_BASE + + TSI108_PCI_REG_OFFSET + + PCI_IRP_STAT) = PCI_IRP_STAT_P_CSR; + } + } + + return; +} + +unsigned int __get_pci_config_dword(u32 addr) +{ + unsigned int retval; + + __asm__ __volatile__(" lwbrx %0,0,%1\n" + "1: eieio\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: li %0,-1\n" + " b 2b\n" + ".section __ex_table,\"a\"\n" + " .align 2\n" + " .long 1b,3b\n" + ".text":"=r"(retval):"r"(addr)); + + return (retval); +} + +static int tsi108_read_config_dword(struct pci_controller *hose, + pci_dev_t dev, int offset, u32 * value) +{ + dev &= (CFG_PCI_CFG_SIZE - 1); + dev |= (CFG_PCI_CFG_BASE | (offset & 0xfc)); + *value = __get_pci_config_dword(dev); + if (0xFFFFFFFF == *value) + tsi108_clear_pci_error(); + return 0; +} + +static int tsi108_write_config_dword(struct pci_controller *hose, + pci_dev_t dev, int offset, u32 value) +{ + dev &= (CFG_PCI_CFG_SIZE - 1); + dev |= (CFG_PCI_CFG_BASE | (offset & 0xfc)); + + out_le32((volatile unsigned *)dev, value); + + return 0; +} + +void pci_init_board(void) +{ + struct pci_controller *hose = (struct pci_controller *)&local_hose; + + hose->first_busno = 0; + hose->last_busno = 0xff; + + pci_set_region(hose->regions + 0, + CFG_PCI_MEMORY_BUS, + CFG_PCI_MEMORY_PHYS, + CFG_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_MEMORY); + + /* PCI memory space */ + pci_set_region(hose->regions + 1, + CFG_PCI_MEM_BUS, + CFG_PCI_MEM_PHYS, CFG_PCI_MEM_SIZE, PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(hose->regions + 2, + CFG_PCI_IO_BUS, + CFG_PCI_IO_PHYS, CFG_PCI_IO_SIZE, PCI_REGION_IO); + + hose->region_count = 3; + + pci_set_ops(hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + tsi108_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + tsi108_write_config_dword); + + pci_register_hose(hose); + + hose->last_busno = pci_hose_scan(hose); + + debug("Done PCI initialization\n"); + return; +} + +#ifdef CONFIG_OF_FLAT_TREE +void +ft_pci_setup(void *blob, bd_t *bd) +{ + u32 *p; + int len; + + p = (u32 *)ft_get_prop(blob, "/" OF_TSI "/pci@1000/bus-range", &len); + if (p != NULL) { + p[0] = local_hose.first_busno; + p[1] = local_hose.last_busno; + } + +} +#endif + +#endif /* CONFIG_TSI108_PCI */ -- cgit v1.2.1 From b825f158e449e1e9cf74c08e572955e122394c96 Mon Sep 17 00:00:00 2001 From: roy zang Date: Thu, 2 Nov 2006 19:12:31 +0800 Subject: Tsi108 on chip i2c support. The i2c Interface provides a master-only, serial interface that can be used for initializing Tsi108/Tsi109 registers from an EEPROM after a device reset. Signed-off-by: Alexandre Bounine Signed-off-by: Roy Zang --- drivers/tsi108_i2c.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 drivers/tsi108_i2c.c (limited to 'drivers') diff --git a/drivers/tsi108_i2c.c b/drivers/tsi108_i2c.c new file mode 100644 index 0000000000..08e5e3b4f5 --- /dev/null +++ b/drivers/tsi108_i2c.c @@ -0,0 +1,300 @@ +/* + * (C) Copyright 2004 Tundra Semiconductor Corp. + * Author: Alex Bounine + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include + +#ifdef CONFIG_TSI108_I2C + +#include +#include + +#if (CONFIG_COMMANDS & CFG_CMD_I2C) + +#define I2C_DELAY 100000 +#undef DEBUG_I2C + +#ifdef DEBUG_I2C +#define DPRINT(x) printf(x) +#else +#define DPRINT(x) +#endif + +/* All functions assume that Tsi108 I2C block is the only master on the bus */ +/* I2C read helper function */ + +static int i2c_read_byte( + uint i2c_chan, /* I2C channel number: 0 - main, 1 - SDC SPD */ + uchar chip_addr,/* I2C device address on the bus */ + uint byte_addr, /* Byte address within I2C device */ + uchar * buffer /* pointer to data buffer */ + ) +{ + u32 temp; + u32 to_count = I2C_DELAY; + u32 op_status = TSI108_I2C_TIMEOUT_ERR; + u32 chan_offset = TSI108_I2C_OFFSET; + + DPRINT(("I2C read_byte() %d 0x%02x 0x%02x\n", + i2c_chan, chip_addr, byte_addr)); + + if (0 != i2c_chan) { + chan_offset = TSI108_I2C_SDRAM_OFFSET; + } + + /* Check if I2C operation is in progress */ + temp = *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2); + + if (0 == (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | + I2C_CNTRL2_START)) + ) { + /* Set device address and operation (read = 0) */ + temp = (byte_addr << 16) | ((chip_addr & 0x07) << 8) | + ((chip_addr >> 3) & 0x0F); + *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + I2C_CNTRL1) = + temp; + + /* Issue the read command + * (at this moment all other parameters are 0 + * (size = 1 byte, lane = 0) + */ + + *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2) = + (I2C_CNTRL2_START); + + /* Wait until operation completed */ + do { + /* Read I2C operation status */ + temp = + *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + + I2C_CNTRL2); + + if (0 == + (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_START))) + { + if (0 == + (temp & + (I2C_CNTRL2_I2C_CFGERR | + I2C_CNTRL2_I2C_TO_ERR)) + ) { + op_status = TSI108_I2C_SUCCESS; + + temp = *(u32 *) (CFG_TSI108_CSR_BASE + + chan_offset + + I2C_RD_DATA); + + *buffer = (u8) (temp & 0xFF); + } else { + /* report HW error */ + op_status = TSI108_I2C_IF_ERROR; + + DPRINT(("I2C HW error reported: 0x%02x\n", temp)); + } + + break; + } + } while (to_count--); + } else { + op_status = TSI108_I2C_IF_BUSY; + + DPRINT(("I2C Transaction start failed: 0x%02x\n", temp)); + } + + DPRINT(("I2C read_byte() status: 0x%02x\n", op_status)); + return op_status; +} + +/* + * I2C Read interface as defined in "include/i2c.h" : + * chip_addr: I2C chip address, range 0..127 + * (to read from SPD channel EEPROM use (0xD0 ... 0xD7) + * NOTE: The bit 7 in the chip_addr serves as a channel select. + * This hack is for enabling "isdram" command on Tsi108 boards + * without changes to common code. Used for I2C reads only. + * byte_addr: Memory or register address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Pointer to destination buffer for data to be read + * len: How many bytes to read + * + * Returns: 0 on success, not 0 on failure + */ + +int i2c_read(uchar chip_addr, uint byte_addr, int alen, uchar * buffer, int len) +{ + u32 op_status = TSI108_I2C_PARAM_ERR; + u32 i2c_if = 0; + + /* Hack to support second (SPD) I2C controller (SPD EEPROM read only).*/ + if (0xD0 == (chip_addr & ~0x07)) { + i2c_if = 1; + chip_addr &= 0x7F; + } + /* Check for valid I2C address */ + if (chip_addr <= 0x7F && (byte_addr + len) <= (0x01 << (alen * 8))) { + while (len--) { + op_status = + i2c_read_byte(i2c_if, chip_addr, byte_addr++, + buffer++); + + if (TSI108_I2C_SUCCESS != op_status) { + DPRINT(("I2C read_byte() failed: 0x%02x (%d left)\n", op_status, len)); + + break; + } + } + } + + DPRINT(("I2C read() status: 0x%02x\n", op_status)); + return op_status; +} + +/* I2C write helper function */ + +static int i2c_write_byte(uchar chip_addr,/* I2C device address on the bus */ + uint byte_addr, /* Byte address within I2C device */ + uchar * buffer /* pointer to data buffer */ + ) +{ + u32 temp; + u32 to_count = I2C_DELAY; + u32 op_status = TSI108_I2C_TIMEOUT_ERR; + + /* Check if I2C operation is in progress */ + temp = *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_CNTRL2); + + if (0 == + (temp & + (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) + { + /* Place data into the I2C Tx Register */ + *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + + I2C_TX_DATA) = (u32) * buffer; + + /* Set device address and operation */ + temp = + I2C_CNTRL1_I2CWRITE | (byte_addr << 16) | + ((chip_addr & 0x07) << 8) | ((chip_addr >> 3) & 0x0F); + *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + + I2C_CNTRL1) = temp; + + /* Issue the write command (at this moment all other parameters + * are 0 (size = 1 byte, lane = 0) + */ + + *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + + I2C_CNTRL2) = (I2C_CNTRL2_START); + + op_status = TSI108_I2C_TIMEOUT_ERR; + + /* Wait until operation completed */ + do { + // Read I2C operation status + temp = + *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + + I2C_CNTRL2); + + if (0 == + (temp & (I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) + { + if (0 == + (temp & + (I2C_CNTRL2_I2C_CFGERR | + I2C_CNTRL2_I2C_TO_ERR))) { + op_status = TSI108_I2C_SUCCESS; + } else { + /* report detected HW error */ + op_status = TSI108_I2C_IF_ERROR; + + DPRINT(("I2C HW error reported: 0x%02x\n", temp)); + } + + break; + } + + } while (to_count--); + } else { + op_status = TSI108_I2C_IF_BUSY; + + DPRINT(("I2C Transaction start failed: 0x%02x\n", temp)); + } + + return op_status; +} + +/* + * I2C Write interface as defined in "include/i2c.h" : + * chip_addr: I2C chip address, range 0..127 + * byte_addr: Memory or register address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Pointer to data to be written + * len: How many bytes to write + * + * Returns: 0 on success, not 0 on failure + */ + +int i2c_write(uchar chip_addr, uint byte_addr, int alen, uchar * buffer, + int len) +{ + u32 op_status = TSI108_I2C_PARAM_ERR; + + /* Check for valid I2C address */ + if (chip_addr <= 0x7F && (byte_addr + len) <= (0x01 << (alen * 8))) { + while (len--) { + op_status = + i2c_write_byte(chip_addr, byte_addr++, buffer++); + + if (TSI108_I2C_SUCCESS != op_status) { + DPRINT(("I2C write_byte() failed: 0x%02x (%d left)\n", op_status, len)); + + break; + } + } + } + + return op_status; +} + +/* + * I2C interface function as defined in "include/i2c.h". + * Probe the given I2C chip address by reading single byte from offset 0. + * Returns 0 if a chip responded, not 0 on failure. + */ + +int i2c_probe(uchar chip) +{ + u32 tmp; + + /* + * Try to read the first location of the chip. + * The Tsi108 HW doesn't support sending just the chip address + * and checkong for an back. + */ + return i2c_read(chip, 0, 1, (char *)&tmp, 1); +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_I2C) */ +#endif /* CONFIG_TSI108_I2C */ -- cgit v1.2.1 From c1fbe4103a0d6c8957f912af902d705ba67836f2 Mon Sep 17 00:00:00 2001 From: roy zang Date: Thu, 2 Nov 2006 19:14:48 +0800 Subject: This patch comes from Yuli's posted patch on 8/8/2006 titled "CFI Driver Little-Endian write Issue". http://sourceforge.net/mailarchive/message.php?msg_id=36311999 If that patch applied, please discard this one. Until now , I do not see his patch is applied. So please apply this one. Signed-off-by: Yuli Barcohen Signed-off-by: Roy Zang --- drivers/cfi_flash.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c index fd0a186828..33a5822d90 100644 --- a/drivers/cfi_flash.c +++ b/drivers/cfi_flash.c @@ -2,9 +2,12 @@ * (C) Copyright 2002-2004 * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com * - * Copyright (C) 2003 Arabella Software Ltd. + * Copyright (C) 2003, 2006 Arabella Software Ltd. * Yuli Barcohen * Modified to work with AMD flashes + * Added support for byte lanes swap + * Added support for 32-bit chips consisting of two 16-bit devices + * (for example, S70GL256M00) * * Copyright (C) 2004 * Ed Okerson @@ -45,10 +48,13 @@ /* #define DEBUG */ #include + +#ifdef CFG_FLASH_CFI_DRIVER + +#include #include #include #include -#ifdef CFG_FLASH_CFI_DRIVER /* * This file implements a Common Flash Interface (CFI) driver for U-Boot. @@ -71,6 +77,10 @@ * Verify erase and program timeouts. */ +#if defined(__LITTLE_ENDIAN) && !defined(CFG_FLASH_CFI_SWAP) +#define CFG_FLASH_CFI_SWAP +#endif + #ifndef CFG_FLASH_BANKS_LIST #define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE } #endif @@ -268,7 +278,7 @@ inline uchar flash_read_uchar (flash_info_t * info, uint offset) uchar *cp; cp = flash_make_addr (info, 0, offset); -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP) return (cp[0]); #else return (cp[info->portwidth - 1]); @@ -295,7 +305,7 @@ ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset) debug ("addr[%x] = 0x%x\n", x, addr[x]); } #endif -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP) retval = ((addr[(info->portwidth)] << 8) | addr[0]); #else retval = ((addr[(2 * info->portwidth) - 1] << 8) | @@ -327,7 +337,7 @@ ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset) debug ("addr[%x] = 0x%x\n", x, addr[x]); } #endif -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP) retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) | (addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8); #else @@ -892,12 +902,22 @@ static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf) int i; uchar *cp = (uchar *) cmdbuf; -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP) for (i = info->portwidth; i > 0; i--) #else for (i = 1; i <= info->portwidth; i++) #endif *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd; +#ifdef CFG_FLASH_CFI_2x16 + if ((info->portwidth == FLASH_CFI_32BIT) && (info->chipwidth == FLASH_CFI_BY16)) + { + uchar tmp; + cp = (uchar *) cmdbuf; + tmp = cp[1]; + cp[1] = cp[2]; + cp[2] = tmp; + } +#endif /* CFG_FLASH_CFI_2x16 */ } /* -- cgit v1.2.1 From ee311214e0d216f904feea269599d0934bf71f23 Mon Sep 17 00:00:00 2001 From: roy zang Date: Fri, 1 Dec 2006 11:47:36 +0800 Subject: Clean up the code according to codestyle: (1) remove some C++ comments. (2) remove trailing white space. (3) remove trailing empty line. (4) Indentation by table. (5) remove {} in one line condition. (6) add space before '(' in function call. Remove some weird printf () output. Add necessary comments. Modified Makefile to support building in a separate directory. --- drivers/tsi108_eth.c | 835 +++++++++++++++++++++++++-------------------------- drivers/tsi108_i2c.c | 60 ++-- drivers/tsi108_pci.c | 34 +-- 3 files changed, 460 insertions(+), 469 deletions(-) (limited to 'drivers') diff --git a/drivers/tsi108_eth.c b/drivers/tsi108_eth.c index d95a047ce8..47341bee7f 100644 --- a/drivers/tsi108_eth.c +++ b/drivers/tsi108_eth.c @@ -46,7 +46,9 @@ #endif #if TSI108_ETH_DEBUG > 0 -#define debug_lev(lev, fmt, args...) if (lev <= TSI108_ETH_DEBUG) printf("%s %d: " fmt, __FUNCTION__, __LINE__, ##args) +#define debug_lev(lev, fmt, args...) \ +if (lev <= TSI108_ETH_DEBUG) \ +printf ("%s %d: " fmt, __FUNCTION__, __LINE__, ##args) #else #define debug_lev(lev, fmt, args...) do{}while(0) #endif @@ -54,322 +56,322 @@ #define RX_PRINT_ERRORS #define TX_PRINT_ERRORS -#define ETH_BASE (CFG_TSI108_CSR_BASE + 0x6000) +#define ETH_BASE (CFG_TSI108_CSR_BASE + 0x6000) -#define ETH_PORT_OFFSET 0x400 +#define ETH_PORT_OFFSET 0x400 #define __REG32(base, offset) (*((volatile u32 *)((char *)(base) + (offset)))) -#define reg_MAC_CONFIG_1(base) __REG32(base, 0x00000000) -#define MAC_CONFIG_1_TX_ENABLE (0x00000001) -#define MAC_CONFIG_1_SYNC_TX_ENABLE (0x00000002) -#define MAC_CONFIG_1_RX_ENABLE (0x00000004) -#define MAC_CONFIG_1_SYNC_RX_ENABLE (0x00000008) -#define MAC_CONFIG_1_TX_FLOW_CONTROL (0x00000010) -#define MAC_CONFIG_1_RX_FLOW_CONTROL (0x00000020) -#define MAC_CONFIG_1_LOOP_BACK (0x00000100) -#define MAC_CONFIG_1_RESET_TX_FUNCTION (0x00010000) -#define MAC_CONFIG_1_RESET_RX_FUNCTION (0x00020000) -#define MAC_CONFIG_1_RESET_TX_MAC (0x00040000) -#define MAC_CONFIG_1_RESET_RX_MAC (0x00080000) -#define MAC_CONFIG_1_SIM_RESET (0x40000000) -#define MAC_CONFIG_1_SOFT_RESET (0x80000000) - -#define reg_MAC_CONFIG_2(base) __REG32(base, 0x00000004) -#define MAC_CONFIG_2_FULL_DUPLEX (0x00000001) -#define MAC_CONFIG_2_CRC_ENABLE (0x00000002) -#define MAC_CONFIG_2_PAD_CRC (0x00000004) -#define MAC_CONFIG_2_LENGTH_CHECK (0x00000010) -#define MAC_CONFIG_2_HUGE_FRAME (0x00000020) -#define MAC_CONFIG_2_INTERFACE_MODE(val) (((val) & 0x3) << 8) -#define MAC_CONFIG_2_PREAMBLE_LENGTH(val) (((val) & 0xf) << 12) -#define INTERFACE_MODE_NIBBLE 1 /* 10/100 Mb/s MII) */ -#define INTERFACE_MODE_BYTE 2 /* 1000 Mb/s GMII/TBI */ - -#define reg_MAXIMUM_FRAME_LENGTH(base) __REG32(base, 0x00000010) - -#define reg_MII_MGMT_CONFIG(base) __REG32(base, 0x00000020) -#define MII_MGMT_CONFIG_MGMT_CLOCK_SELECT(val) ((val) & 0x7) -#define MII_MGMT_CONFIG_NO_PREAMBLE (0x00000010) -#define MII_MGMT_CONFIG_SCAN_INCREMENT (0x00000020) -#define MII_MGMT_CONFIG_RESET_MGMT (0x80000000) - -#define reg_MII_MGMT_COMMAND(base) __REG32(base, 0x00000024) -#define MII_MGMT_COMMAND_READ_CYCLE (0x00000001) -#define MII_MGMT_COMMAND_SCAN_CYCLE (0x00000002) - -#define reg_MII_MGMT_ADDRESS(base) __REG32(base, 0x00000028) -#define reg_MII_MGMT_CONTROL(base) __REG32(base, 0x0000002c) -#define reg_MII_MGMT_STATUS(base) __REG32(base, 0x00000030) - -#define reg_MII_MGMT_INDICATORS(base) __REG32(base, 0x00000034) -#define MII_MGMT_INDICATORS_BUSY (0x00000001) -#define MII_MGMT_INDICATORS_SCAN (0x00000002) -#define MII_MGMT_INDICATORS_NOT_VALID (0x00000004) - -#define reg_INTERFACE_STATUS(base) __REG32(base, 0x0000003c) -#define INTERFACE_STATUS_LINK_FAIL (0x00000008) -#define INTERFACE_STATUS_EXCESS_DEFER (0x00000200) - -#define reg_STATION_ADDRESS_1(base) __REG32(base, 0x00000040) -#define reg_STATION_ADDRESS_2(base) __REG32(base, 0x00000044) - -#define reg_PORT_CONTROL(base) __REG32(base, 0x00000200) -#define PORT_CONTROL_PRI (0x00000001) -#define PORT_CONTROL_BPT (0x00010000) -#define PORT_CONTROL_SPD (0x00040000) -#define PORT_CONTROL_RBC (0x00080000) -#define PORT_CONTROL_PRB (0x00200000) -#define PORT_CONTROL_DIS (0x00400000) -#define PORT_CONTROL_TBI (0x00800000) -#define PORT_CONTROL_STE (0x10000000) -#define PORT_CONTROL_ZOR (0x20000000) -#define PORT_CONTROL_CLR (0x40000000) -#define PORT_CONTROL_SRT (0x80000000) - -#define reg_TX_CONFIG(base) __REG32(base, 0x00000220) -#define TX_CONFIG_START_Q (0x00000003) -#define TX_CONFIG_EHP (0x00400000) -#define TX_CONFIG_CHP (0x00800000) -#define TX_CONFIG_RST (0x80000000) - -#define reg_TX_CONTROL(base) __REG32(base, 0x00000224) -#define TX_CONTROL_GO (0x00008000) -#define TX_CONTROL_MP (0x01000000) -#define TX_CONTROL_EAI (0x20000000) -#define TX_CONTROL_ABT (0x40000000) -#define TX_CONTROL_EII (0x80000000) - -#define reg_TX_STATUS(base) __REG32(base, 0x00000228) -#define TX_STATUS_QUEUE_USABLE (0x0000000f) -#define TX_STATUS_CURR_Q (0x00000300) -#define TX_STATUS_ACT (0x00008000) -#define TX_STATUS_QUEUE_IDLE (0x000f0000) -#define TX_STATUS_EOQ_PENDING (0x0f000000) - -#define reg_TX_EXTENDED_STATUS(base) __REG32(base, 0x0000022c) -#define TX_EXTENDED_STATUS_END_OF_QUEUE_CONDITION (0x0000000f) -#define TX_EXTENDED_STATUS_END_OF_FRAME_CONDITION (0x00000f00) -#define TX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) -#define TX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) - -#define reg_TX_THRESHOLDS(base) __REG32(base, 0x00000230) +#define reg_MAC_CONFIG_1(base) __REG32(base, 0x00000000) +#define MAC_CONFIG_1_TX_ENABLE (0x00000001) +#define MAC_CONFIG_1_SYNC_TX_ENABLE (0x00000002) +#define MAC_CONFIG_1_RX_ENABLE (0x00000004) +#define MAC_CONFIG_1_SYNC_RX_ENABLE (0x00000008) +#define MAC_CONFIG_1_TX_FLOW_CONTROL (0x00000010) +#define MAC_CONFIG_1_RX_FLOW_CONTROL (0x00000020) +#define MAC_CONFIG_1_LOOP_BACK (0x00000100) +#define MAC_CONFIG_1_RESET_TX_FUNCTION (0x00010000) +#define MAC_CONFIG_1_RESET_RX_FUNCTION (0x00020000) +#define MAC_CONFIG_1_RESET_TX_MAC (0x00040000) +#define MAC_CONFIG_1_RESET_RX_MAC (0x00080000) +#define MAC_CONFIG_1_SIM_RESET (0x40000000) +#define MAC_CONFIG_1_SOFT_RESET (0x80000000) + +#define reg_MAC_CONFIG_2(base) __REG32(base, 0x00000004) +#define MAC_CONFIG_2_FULL_DUPLEX (0x00000001) +#define MAC_CONFIG_2_CRC_ENABLE (0x00000002) +#define MAC_CONFIG_2_PAD_CRC (0x00000004) +#define MAC_CONFIG_2_LENGTH_CHECK (0x00000010) +#define MAC_CONFIG_2_HUGE_FRAME (0x00000020) +#define MAC_CONFIG_2_INTERFACE_MODE(val) (((val) & 0x3) << 8) +#define MAC_CONFIG_2_PREAMBLE_LENGTH(val) (((val) & 0xf) << 12) +#define INTERFACE_MODE_NIBBLE 1 /* 10/100 Mb/s MII) */ +#define INTERFACE_MODE_BYTE 2 /* 1000 Mb/s GMII/TBI */ + +#define reg_MAXIMUM_FRAME_LENGTH(base) __REG32(base, 0x00000010) + +#define reg_MII_MGMT_CONFIG(base) __REG32(base, 0x00000020) +#define MII_MGMT_CONFIG_MGMT_CLOCK_SELECT(val) ((val) & 0x7) +#define MII_MGMT_CONFIG_NO_PREAMBLE (0x00000010) +#define MII_MGMT_CONFIG_SCAN_INCREMENT (0x00000020) +#define MII_MGMT_CONFIG_RESET_MGMT (0x80000000) + +#define reg_MII_MGMT_COMMAND(base) __REG32(base, 0x00000024) +#define MII_MGMT_COMMAND_READ_CYCLE (0x00000001) +#define MII_MGMT_COMMAND_SCAN_CYCLE (0x00000002) + +#define reg_MII_MGMT_ADDRESS(base) __REG32(base, 0x00000028) +#define reg_MII_MGMT_CONTROL(base) __REG32(base, 0x0000002c) +#define reg_MII_MGMT_STATUS(base) __REG32(base, 0x00000030) + +#define reg_MII_MGMT_INDICATORS(base) __REG32(base, 0x00000034) +#define MII_MGMT_INDICATORS_BUSY (0x00000001) +#define MII_MGMT_INDICATORS_SCAN (0x00000002) +#define MII_MGMT_INDICATORS_NOT_VALID (0x00000004) + +#define reg_INTERFACE_STATUS(base) __REG32(base, 0x0000003c) +#define INTERFACE_STATUS_LINK_FAIL (0x00000008) +#define INTERFACE_STATUS_EXCESS_DEFER (0x00000200) + +#define reg_STATION_ADDRESS_1(base) __REG32(base, 0x00000040) +#define reg_STATION_ADDRESS_2(base) __REG32(base, 0x00000044) + +#define reg_PORT_CONTROL(base) __REG32(base, 0x00000200) +#define PORT_CONTROL_PRI (0x00000001) +#define PORT_CONTROL_BPT (0x00010000) +#define PORT_CONTROL_SPD (0x00040000) +#define PORT_CONTROL_RBC (0x00080000) +#define PORT_CONTROL_PRB (0x00200000) +#define PORT_CONTROL_DIS (0x00400000) +#define PORT_CONTROL_TBI (0x00800000) +#define PORT_CONTROL_STE (0x10000000) +#define PORT_CONTROL_ZOR (0x20000000) +#define PORT_CONTROL_CLR (0x40000000) +#define PORT_CONTROL_SRT (0x80000000) + +#define reg_TX_CONFIG(base) __REG32(base, 0x00000220) +#define TX_CONFIG_START_Q (0x00000003) +#define TX_CONFIG_EHP (0x00400000) +#define TX_CONFIG_CHP (0x00800000) +#define TX_CONFIG_RST (0x80000000) + +#define reg_TX_CONTROL(base) __REG32(base, 0x00000224) +#define TX_CONTROL_GO (0x00008000) +#define TX_CONTROL_MP (0x01000000) +#define TX_CONTROL_EAI (0x20000000) +#define TX_CONTROL_ABT (0x40000000) +#define TX_CONTROL_EII (0x80000000) + +#define reg_TX_STATUS(base) __REG32(base, 0x00000228) +#define TX_STATUS_QUEUE_USABLE (0x0000000f) +#define TX_STATUS_CURR_Q (0x00000300) +#define TX_STATUS_ACT (0x00008000) +#define TX_STATUS_QUEUE_IDLE (0x000f0000) +#define TX_STATUS_EOQ_PENDING (0x0f000000) + +#define reg_TX_EXTENDED_STATUS(base) __REG32(base, 0x0000022c) +#define TX_EXTENDED_STATUS_END_OF_QUEUE_CONDITION (0x0000000f) +#define TX_EXTENDED_STATUS_END_OF_FRAME_CONDITION (0x00000f00) +#define TX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) +#define TX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) + +#define reg_TX_THRESHOLDS(base) __REG32(base, 0x00000230) #define reg_TX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000270) -#define TX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) -#define TX_DIAGNOSTIC_ADDR_DFR (0x40000000) -#define TX_DIAGNOSTIC_ADDR_AI (0x80000000) - -#define reg_TX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000274) - -#define reg_TX_ERROR_STATUS(base) __REG32(base, 0x00000278) -#define TX_ERROR_STATUS (0x00000278) -#define TX_ERROR_STATUS_QUEUE_0_ERROR_RESPONSE (0x0000000f) -#define TX_ERROR_STATUS_TEA_ON_QUEUE_0 (0x00000010) -#define TX_ERROR_STATUS_RER_ON_QUEUE_0 (0x00000020) -#define TX_ERROR_STATUS_TER_ON_QUEUE_0 (0x00000040) -#define TX_ERROR_STATUS_DER_ON_QUEUE_0 (0x00000080) -#define TX_ERROR_STATUS_QUEUE_1_ERROR_RESPONSE (0x00000f00) -#define TX_ERROR_STATUS_TEA_ON_QUEUE_1 (0x00001000) -#define TX_ERROR_STATUS_RER_ON_QUEUE_1 (0x00002000) -#define TX_ERROR_STATUS_TER_ON_QUEUE_1 (0x00004000) -#define TX_ERROR_STATUS_DER_ON_QUEUE_1 (0x00008000) -#define TX_ERROR_STATUS_QUEUE_2_ERROR_RESPONSE (0x000f0000) -#define TX_ERROR_STATUS_TEA_ON_QUEUE_2 (0x00100000) -#define TX_ERROR_STATUS_RER_ON_QUEUE_2 (0x00200000) -#define TX_ERROR_STATUS_TER_ON_QUEUE_2 (0x00400000) -#define TX_ERROR_STATUS_DER_ON_QUEUE_2 (0x00800000) -#define TX_ERROR_STATUS_QUEUE_3_ERROR_RESPONSE (0x0f000000) -#define TX_ERROR_STATUS_TEA_ON_QUEUE_3 (0x10000000) -#define TX_ERROR_STATUS_RER_ON_QUEUE_3 (0x20000000) -#define TX_ERROR_STATUS_TER_ON_QUEUE_3 (0x40000000) -#define TX_ERROR_STATUS_DER_ON_QUEUE_3 (0x80000000) - -#define reg_TX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000280) -#define TX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) -#define TX_QUEUE_0_CONFIG_BSWP (0x00000400) -#define TX_QUEUE_0_CONFIG_WSWP (0x00000800) -#define TX_QUEUE_0_CONFIG_AM (0x00004000) -#define TX_QUEUE_0_CONFIG_GVI (0x00008000) -#define TX_QUEUE_0_CONFIG_EEI (0x00010000) -#define TX_QUEUE_0_CONFIG_ELI (0x00020000) -#define TX_QUEUE_0_CONFIG_ENI (0x00040000) -#define TX_QUEUE_0_CONFIG_ESI (0x00080000) -#define TX_QUEUE_0_CONFIG_EDI (0x00100000) - -#define reg_TX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000284) -#define TX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) -#define TX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) -#define TX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) -#define TX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) - -#define OCN_PORT_HLP 0 /* HLP Interface */ -#define OCN_PORT_PCI_X 1 /* PCI-X Interface */ +#define TX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) +#define TX_DIAGNOSTIC_ADDR_DFR (0x40000000) +#define TX_DIAGNOSTIC_ADDR_AI (0x80000000) + +#define reg_TX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000274) + +#define reg_TX_ERROR_STATUS(base) __REG32(base, 0x00000278) +#define TX_ERROR_STATUS (0x00000278) +#define TX_ERROR_STATUS_QUEUE_0_ERROR_RESPONSE (0x0000000f) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_0 (0x00000010) +#define TX_ERROR_STATUS_RER_ON_QUEUE_0 (0x00000020) +#define TX_ERROR_STATUS_TER_ON_QUEUE_0 (0x00000040) +#define TX_ERROR_STATUS_DER_ON_QUEUE_0 (0x00000080) +#define TX_ERROR_STATUS_QUEUE_1_ERROR_RESPONSE (0x00000f00) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_1 (0x00001000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_1 (0x00002000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_1 (0x00004000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_1 (0x00008000) +#define TX_ERROR_STATUS_QUEUE_2_ERROR_RESPONSE (0x000f0000) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_2 (0x00100000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_2 (0x00200000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_2 (0x00400000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_2 (0x00800000) +#define TX_ERROR_STATUS_QUEUE_3_ERROR_RESPONSE (0x0f000000) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_3 (0x10000000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_3 (0x20000000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_3 (0x40000000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_3 (0x80000000) + +#define reg_TX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000280) +#define TX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) +#define TX_QUEUE_0_CONFIG_BSWP (0x00000400) +#define TX_QUEUE_0_CONFIG_WSWP (0x00000800) +#define TX_QUEUE_0_CONFIG_AM (0x00004000) +#define TX_QUEUE_0_CONFIG_GVI (0x00008000) +#define TX_QUEUE_0_CONFIG_EEI (0x00010000) +#define TX_QUEUE_0_CONFIG_ELI (0x00020000) +#define TX_QUEUE_0_CONFIG_ENI (0x00040000) +#define TX_QUEUE_0_CONFIG_ESI (0x00080000) +#define TX_QUEUE_0_CONFIG_EDI (0x00100000) + +#define reg_TX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000284) +#define TX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) +#define TX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) +#define TX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) +#define TX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) + +#define OCN_PORT_HLP 0 /* HLP Interface */ +#define OCN_PORT_PCI_X 1 /* PCI-X Interface */ #define OCN_PORT_PROCESSOR_MASTER 2 /* Processor Interface (master) */ -#define OCN_PORT_PROCESSOR_SLAVE 3 /* Processor Interface (slave) */ -#define OCN_PORT_MEMORY 4 /* Memory Controller */ -#define OCN_PORT_DMA 5 /* DMA Controller */ -#define OCN_PORT_ETHERNET 6 /* Ethernet Controller */ -#define OCN_PORT_PRINT 7 /* Print Engine Interface */ - -#define reg_TX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000288) - -#define reg_TX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000028c) -#define TX_QUEUE_0_PTR_HIGH_VALID (0x80000000) - -#define reg_RX_CONFIG(base) __REG32(base, 0x00000320) -#define RX_CONFIG_DEF_Q (0x00000003) -#define RX_CONFIG_EMF (0x00000100) -#define RX_CONFIG_EUF (0x00000200) -#define RX_CONFIG_BFE (0x00000400) -#define RX_CONFIG_MFE (0x00000800) -#define RX_CONFIG_UFE (0x00001000) -#define RX_CONFIG_SE (0x00002000) -#define RX_CONFIG_ABF (0x00200000) -#define RX_CONFIG_APE (0x00400000) -#define RX_CONFIG_CHP (0x00800000) -#define RX_CONFIG_RST (0x80000000) - -#define reg_RX_CONTROL(base) __REG32(base, 0x00000324) -#define GE_E0_RX_CONTROL_QUEUE_ENABLES (0x0000000f) -#define GE_E0_RX_CONTROL_GO (0x00008000) -#define GE_E0_RX_CONTROL_EAI (0x20000000) -#define GE_E0_RX_CONTROL_ABT (0x40000000) -#define GE_E0_RX_CONTROL_EII (0x80000000) - -#define reg_RX_EXTENDED_STATUS(base) __REG32(base, 0x0000032c) -#define RX_EXTENDED_STATUS (0x0000032c) -#define RX_EXTENDED_STATUS_EOQ (0x0000000f) -#define RX_EXTENDED_STATUS_EOQ_0 (0x00000001) -#define RX_EXTENDED_STATUS_EOF (0x00000f00) -#define RX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) -#define RX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) - -#define reg_RX_THRESHOLDS(base) __REG32(base, 0x00000330) - -#define reg_RX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000370) -#define RX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) -#define RX_DIAGNOSTIC_ADDR_DFR (0x40000000) -#define RX_DIAGNOSTIC_ADDR_AI (0x80000000) - -#define reg_RX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000374) - -#define reg_RX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000380) -#define RX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) -#define RX_QUEUE_0_CONFIG_BSWP (0x00000400) -#define RX_QUEUE_0_CONFIG_WSWP (0x00000800) -#define RX_QUEUE_0_CONFIG_AM (0x00004000) -#define RX_QUEUE_0_CONFIG_EEI (0x00010000) -#define RX_QUEUE_0_CONFIG_ELI (0x00020000) -#define RX_QUEUE_0_CONFIG_ENI (0x00040000) -#define RX_QUEUE_0_CONFIG_ESI (0x00080000) -#define RX_QUEUE_0_CONFIG_EDI (0x00100000) - -#define reg_RX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000384) -#define RX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) -#define RX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) -#define RX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) -#define RX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) - -#define reg_RX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000388) - -#define reg_RX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000038c) -#define RX_QUEUE_0_PTR_HIGH_VALID (0x80000000) +#define OCN_PORT_PROCESSOR_SLAVE 3 /* Processor Interface (slave) */ +#define OCN_PORT_MEMORY 4 /* Memory Controller */ +#define OCN_PORT_DMA 5 /* DMA Controller */ +#define OCN_PORT_ETHERNET 6 /* Ethernet Controller */ +#define OCN_PORT_PRINT 7 /* Print Engine Interface */ + +#define reg_TX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000288) + +#define reg_TX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000028c) +#define TX_QUEUE_0_PTR_HIGH_VALID (0x80000000) + +#define reg_RX_CONFIG(base) __REG32(base, 0x00000320) +#define RX_CONFIG_DEF_Q (0x00000003) +#define RX_CONFIG_EMF (0x00000100) +#define RX_CONFIG_EUF (0x00000200) +#define RX_CONFIG_BFE (0x00000400) +#define RX_CONFIG_MFE (0x00000800) +#define RX_CONFIG_UFE (0x00001000) +#define RX_CONFIG_SE (0x00002000) +#define RX_CONFIG_ABF (0x00200000) +#define RX_CONFIG_APE (0x00400000) +#define RX_CONFIG_CHP (0x00800000) +#define RX_CONFIG_RST (0x80000000) + +#define reg_RX_CONTROL(base) __REG32(base, 0x00000324) +#define GE_E0_RX_CONTROL_QUEUE_ENABLES (0x0000000f) +#define GE_E0_RX_CONTROL_GO (0x00008000) +#define GE_E0_RX_CONTROL_EAI (0x20000000) +#define GE_E0_RX_CONTROL_ABT (0x40000000) +#define GE_E0_RX_CONTROL_EII (0x80000000) + +#define reg_RX_EXTENDED_STATUS(base) __REG32(base, 0x0000032c) +#define RX_EXTENDED_STATUS (0x0000032c) +#define RX_EXTENDED_STATUS_EOQ (0x0000000f) +#define RX_EXTENDED_STATUS_EOQ_0 (0x00000001) +#define RX_EXTENDED_STATUS_EOF (0x00000f00) +#define RX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION (0x000f0000) +#define RX_EXTENDED_STATUS_ERROR_FLAG (0x0f000000) + +#define reg_RX_THRESHOLDS(base) __REG32(base, 0x00000330) + +#define reg_RX_DIAGNOSTIC_ADDR(base) __REG32(base, 0x00000370) +#define RX_DIAGNOSTIC_ADDR_INDEX (0x0000007f) +#define RX_DIAGNOSTIC_ADDR_DFR (0x40000000) +#define RX_DIAGNOSTIC_ADDR_AI (0x80000000) + +#define reg_RX_DIAGNOSTIC_DATA(base) __REG32(base, 0x00000374) + +#define reg_RX_QUEUE_0_CONFIG(base) __REG32(base, 0x00000380) +#define RX_QUEUE_0_CONFIG_OCN_PORT (0x0000003f) +#define RX_QUEUE_0_CONFIG_BSWP (0x00000400) +#define RX_QUEUE_0_CONFIG_WSWP (0x00000800) +#define RX_QUEUE_0_CONFIG_AM (0x00004000) +#define RX_QUEUE_0_CONFIG_EEI (0x00010000) +#define RX_QUEUE_0_CONFIG_ELI (0x00020000) +#define RX_QUEUE_0_CONFIG_ENI (0x00040000) +#define RX_QUEUE_0_CONFIG_ESI (0x00080000) +#define RX_QUEUE_0_CONFIG_EDI (0x00100000) + +#define reg_RX_QUEUE_0_BUF_CONFIG(base) __REG32(base, 0x00000384) +#define RX_QUEUE_0_BUF_CONFIG_OCN_PORT (0x0000003f) +#define RX_QUEUE_0_BUF_CONFIG_BURST (0x00000300) +#define RX_QUEUE_0_BUF_CONFIG_BSWP (0x00000400) +#define RX_QUEUE_0_BUF_CONFIG_WSWP (0x00000800) + +#define reg_RX_QUEUE_0_PTR_LOW(base) __REG32(base, 0x00000388) + +#define reg_RX_QUEUE_0_PTR_HIGH(base) __REG32(base, 0x0000038c) +#define RX_QUEUE_0_PTR_HIGH_VALID (0x80000000) /* * PHY register definitions */ /* the first 15 PHY registers are standard. */ -#define PHY_CTRL_REG 0 /* Control Register */ -#define PHY_STATUS_REG 1 /* Status Regiser */ -#define PHY_ID1_REG 2 /* Phy Id Reg (word 1) */ -#define PHY_ID2_REG 3 /* Phy Id Reg (word 2) */ -#define PHY_AN_ADV_REG 4 /* Autoneg Advertisement */ -#define PHY_LP_ABILITY_REG 5 /* Link Partner Ability (Base Page) */ -#define PHY_AUTONEG_EXP_REG 6 /* Autoneg Expansion Reg */ -#define PHY_NEXT_PAGE_TX_REG 7 /* Next Page TX */ -#define PHY_LP_NEXT_PAGE_REG 8 /* Link Partner Next Page */ -#define PHY_1000T_CTRL_REG 9 /* 1000Base-T Control Reg */ -#define PHY_1000T_STATUS_REG 10 /* 1000Base-T Status Reg */ -#define PHY_EXT_STATUS_REG 11 /* Extended Status Reg */ +#define PHY_CTRL_REG 0 /* Control Register */ +#define PHY_STATUS_REG 1 /* Status Regiser */ +#define PHY_ID1_REG 2 /* Phy Id Reg (word 1) */ +#define PHY_ID2_REG 3 /* Phy Id Reg (word 2) */ +#define PHY_AN_ADV_REG 4 /* Autoneg Advertisement */ +#define PHY_LP_ABILITY_REG 5 /* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP_REG 6 /* Autoneg Expansion Reg */ +#define PHY_NEXT_PAGE_TX_REG 7 /* Next Page TX */ +#define PHY_LP_NEXT_PAGE_REG 8 /* Link Partner Next Page */ +#define PHY_1000T_CTRL_REG 9 /* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS_REG 10 /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS_REG 11 /* Extended Status Reg */ /* * PHY Register bit masks. */ -#define PHY_CTRL_RESET (1 << 15) -#define PHY_CTRL_LOOPBACK (1 << 14) -#define PHY_CTRL_SPEED0 (1 << 13) -#define PHY_CTRL_AN_EN (1 << 12) -#define PHY_CTRL_PWR_DN (1 << 11) -#define PHY_CTRL_ISOLATE (1 << 10) -#define PHY_CTRL_RESTART_AN (1 << 9) -#define PHY_CTRL_FULL_DUPLEX (1 << 8) -#define PHY_CTRL_CT_EN (1 << 7) -#define PHY_CTRL_SPEED1 (1 << 6) - -#define PHY_STAT_100BASE_T4 (1 << 15) -#define PHY_STAT_100BASE_X_FD (1 << 14) -#define PHY_STAT_100BASE_X_HD (1 << 13) -#define PHY_STAT_10BASE_T_FD (1 << 12) -#define PHY_STAT_10BASE_T_HD (1 << 11) -#define PHY_STAT_100BASE_T2_FD (1 << 10) -#define PHY_STAT_100BASE_T2_HD (1 << 9) -#define PHY_STAT_EXT_STAT (1 << 8) -#define PHY_STAT_RESERVED (1 << 7) -#define PHY_STAT_MFPS (1 << 6) /* Management Frames Preamble Suppression */ -#define PHY_STAT_AN_COMPLETE (1 << 5) -#define PHY_STAT_REM_FAULT (1 << 4) -#define PHY_STAT_AN_CAP (1 << 3) -#define PHY_STAT_LINK_UP (1 << 2) -#define PHY_STAT_JABBER (1 << 1) -#define PHY_STAT_EXT_CAP (1 << 0) - -#define TBI_CONTROL_2 0x11 -#define TBI_CONTROL_2_ENABLE_COMMA_DETECT 0x0001 -#define TBI_CONTROL_2_ENABLE_WRAP 0x0002 -#define TBI_CONTROL_2_G_MII_MODE 0x0010 -#define TBI_CONTROL_2_RECEIVE_CLOCK_SELECT 0x0020 -#define TBI_CONTROL_2_AUTO_NEGOTIATION_SENSE 0x0100 -#define TBI_CONTROL_2_DISABLE_TRANSMIT_RUNNING_DISPARITY 0x1000 -#define TBI_CONTROL_2_DISABLE_RECEIVE_RUNNING_DISPARITY 0x2000 -#define TBI_CONTROL_2_SHORTCUT_LINK_TIMER 0x4000 -#define TBI_CONTROL_2_SOFT_RESET 0x8000 +#define PHY_CTRL_RESET (1 << 15) +#define PHY_CTRL_LOOPBACK (1 << 14) +#define PHY_CTRL_SPEED0 (1 << 13) +#define PHY_CTRL_AN_EN (1 << 12) +#define PHY_CTRL_PWR_DN (1 << 11) +#define PHY_CTRL_ISOLATE (1 << 10) +#define PHY_CTRL_RESTART_AN (1 << 9) +#define PHY_CTRL_FULL_DUPLEX (1 << 8) +#define PHY_CTRL_CT_EN (1 << 7) +#define PHY_CTRL_SPEED1 (1 << 6) + +#define PHY_STAT_100BASE_T4 (1 << 15) +#define PHY_STAT_100BASE_X_FD (1 << 14) +#define PHY_STAT_100BASE_X_HD (1 << 13) +#define PHY_STAT_10BASE_T_FD (1 << 12) +#define PHY_STAT_10BASE_T_HD (1 << 11) +#define PHY_STAT_100BASE_T2_FD (1 << 10) +#define PHY_STAT_100BASE_T2_HD (1 << 9) +#define PHY_STAT_EXT_STAT (1 << 8) +#define PHY_STAT_RESERVED (1 << 7) +#define PHY_STAT_MFPS (1 << 6) /* Management Frames Preamble Suppression */ +#define PHY_STAT_AN_COMPLETE (1 << 5) +#define PHY_STAT_REM_FAULT (1 << 4) +#define PHY_STAT_AN_CAP (1 << 3) +#define PHY_STAT_LINK_UP (1 << 2) +#define PHY_STAT_JABBER (1 << 1) +#define PHY_STAT_EXT_CAP (1 << 0) + +#define TBI_CONTROL_2 0x11 +#define TBI_CONTROL_2_ENABLE_COMMA_DETECT 0x0001 +#define TBI_CONTROL_2_ENABLE_WRAP 0x0002 +#define TBI_CONTROL_2_G_MII_MODE 0x0010 +#define TBI_CONTROL_2_RECEIVE_CLOCK_SELECT 0x0020 +#define TBI_CONTROL_2_AUTO_NEGOTIATION_SENSE 0x0100 +#define TBI_CONTROL_2_DISABLE_TRANSMIT_RUNNING_DISPARITY 0x1000 +#define TBI_CONTROL_2_DISABLE_RECEIVE_RUNNING_DISPARITY 0x2000 +#define TBI_CONTROL_2_SHORTCUT_LINK_TIMER 0x4000 +#define TBI_CONTROL_2_SOFT_RESET 0x8000 /* marvel specific */ -#define MV1111_EXT_CTRL1_REG 16 /* PHY Specific Control Reg */ -#define MV1111_SPEC_STAT_REG 17 /* PHY Specific Status Reg */ -#define MV1111_EXT_CTRL2_REG 20 /* Extended PHY Specific Control Reg */ +#define MV1111_EXT_CTRL1_REG 16 /* PHY Specific Control Reg */ +#define MV1111_SPEC_STAT_REG 17 /* PHY Specific Status Reg */ +#define MV1111_EXT_CTRL2_REG 20 /* Extended PHY Specific Control Reg */ /* * MARVELL 88E1111 PHY register bit masks */ /* PHY Specific Status Register (MV1111_EXT_CTRL1_REG) */ -#define SPEC_STAT_SPEED_MASK (3 << 14) -#define SPEC_STAT_FULL_DUP (1 << 13) -#define SPEC_STAT_PAGE_RCVD (1 << 12) -#define SPEC_STAT_RESOLVED (1 << 11) /* Speed and Duplex Resolved */ -#define SPEC_STAT_LINK_UP (1 << 10) -#define SPEC_STAT_CABLE_LEN_MASK (7 << 7) /* Cable Length (100/1000 modes only) */ -#define SPEC_STAT_MDIX (1 << 6) -#define SPEC_STAT_POLARITY (1 << 1) -#define SPEC_STAT_JABBER (1 << 0) +#define SPEC_STAT_SPEED_MASK (3 << 14) +#define SPEC_STAT_FULL_DUP (1 << 13) +#define SPEC_STAT_PAGE_RCVD (1 << 12) +#define SPEC_STAT_RESOLVED (1 << 11) /* Speed and Duplex Resolved */ +#define SPEC_STAT_LINK_UP (1 << 10) +#define SPEC_STAT_CABLE_LEN_MASK (7 << 7)/* Cable Length (100/1000 modes only) */ +#define SPEC_STAT_MDIX (1 << 6) +#define SPEC_STAT_POLARITY (1 << 1) +#define SPEC_STAT_JABBER (1 << 0) -#define SPEED_1000 (2 << 14) -#define SPEED_100 (1 << 14) -#define SPEED_10 (0 << 14) +#define SPEED_1000 (2 << 14) +#define SPEED_100 (1 << 14) +#define SPEED_10 (0 << 14) -#define TBI_ADDR 0x1E /* Ten Bit Interface address */ +#define TBI_ADDR 0x1E /* Ten Bit Interface address */ /* negotiated link parameters */ -#define LINK_SPEED_UNKNOWN 0 -#define LINK_SPEED_10 1 -#define LINK_SPEED_100 2 -#define LINK_SPEED_1000 3 +#define LINK_SPEED_UNKNOWN 0 +#define LINK_SPEED_10 1 +#define LINK_SPEED_100 2 +#define LINK_SPEED_1000 3 -#define LINK_DUPLEX_UNKNOWN 0 -#define LINK_DUPLEX_HALF 1 -#define LINK_DUPLEX_FULL 2 +#define LINK_DUPLEX_UNKNOWN 0 +#define LINK_DUPLEX_HALF 1 +#define LINK_DUPLEX_FULL 2 static unsigned int phy_address[] = { 8, 9 }; @@ -390,56 +392,56 @@ struct dma_descriptor { }; /* last next descriptor address flag */ -#define DMA_DESCR_LAST (1 << 31) +#define DMA_DESCR_LAST (1 << 31) /* TX DMA descriptor config status bits */ -#define DMA_DESCR_TX_EOF (1 << 0) /* end of frame */ -#define DMA_DESCR_TX_SOF (1 << 1) /* start of frame */ -#define DMA_DESCR_TX_PFVLAN (1 << 2) -#define DMA_DESCR_TX_HUGE (1 << 3) -#define DMA_DESCR_TX_PAD (1 << 4) -#define DMA_DESCR_TX_CRC (1 << 5) -#define DMA_DESCR_TX_DESCR_INT (1 << 14) -#define DMA_DESCR_TX_RETRY_COUNT 0x000F0000 -#define DMA_DESCR_TX_ONE_COLLISION (1 << 20) -#define DMA_DESCR_TX_LATE_COLLISION (1 << 24) -#define DMA_DESCR_TX_UNDERRUN (1 << 25) -#define DMA_DESCR_TX_RETRY_LIMIT (1 << 26) -#define DMA_DESCR_TX_OK (1 << 30) -#define DMA_DESCR_TX_OWNER (1 << 31) +#define DMA_DESCR_TX_EOF (1 << 0) /* end of frame */ +#define DMA_DESCR_TX_SOF (1 << 1) /* start of frame */ +#define DMA_DESCR_TX_PFVLAN (1 << 2) +#define DMA_DESCR_TX_HUGE (1 << 3) +#define DMA_DESCR_TX_PAD (1 << 4) +#define DMA_DESCR_TX_CRC (1 << 5) +#define DMA_DESCR_TX_DESCR_INT (1 << 14) +#define DMA_DESCR_TX_RETRY_COUNT 0x000F0000 +#define DMA_DESCR_TX_ONE_COLLISION (1 << 20) +#define DMA_DESCR_TX_LATE_COLLISION (1 << 24) +#define DMA_DESCR_TX_UNDERRUN (1 << 25) +#define DMA_DESCR_TX_RETRY_LIMIT (1 << 26) +#define DMA_DESCR_TX_OK (1 << 30) +#define DMA_DESCR_TX_OWNER (1 << 31) /* RX DMA descriptor status bits */ -#define DMA_DESCR_RX_EOF (1 << 0) -#define DMA_DESCR_RX_SOF (1 << 1) -#define DMA_DESCR_RX_VTF (1 << 2) -#define DMA_DESCR_RX_FRAME_IS_TYPE (1 << 3) -#define DMA_DESCR_RX_SHORT_FRAME (1 << 4) -#define DMA_DESCR_RX_HASH_MATCH (1 << 7) -#define DMA_DESCR_RX_BAD_FRAME (1 << 8) -#define DMA_DESCR_RX_OVERRUN (1 << 9) -#define DMA_DESCR_RX_MAX_FRAME_LEN (1 << 11) -#define DMA_DESCR_RX_CRC_ERROR (1 << 12) -#define DMA_DESCR_RX_DESCR_INT (1 << 13) -#define DMA_DESCR_RX_OWNER (1 << 15) - -#define RX_BUFFER_SIZE PKTSIZE -#define NUM_RX_DESC PKTBUFSRX +#define DMA_DESCR_RX_EOF (1 << 0) +#define DMA_DESCR_RX_SOF (1 << 1) +#define DMA_DESCR_RX_VTF (1 << 2) +#define DMA_DESCR_RX_FRAME_IS_TYPE (1 << 3) +#define DMA_DESCR_RX_SHORT_FRAME (1 << 4) +#define DMA_DESCR_RX_HASH_MATCH (1 << 7) +#define DMA_DESCR_RX_BAD_FRAME (1 << 8) +#define DMA_DESCR_RX_OVERRUN (1 << 9) +#define DMA_DESCR_RX_MAX_FRAME_LEN (1 << 11) +#define DMA_DESCR_RX_CRC_ERROR (1 << 12) +#define DMA_DESCR_RX_DESCR_INT (1 << 13) +#define DMA_DESCR_RX_OWNER (1 << 15) + +#define RX_BUFFER_SIZE PKTSIZE +#define NUM_RX_DESC PKTBUFSRX static struct dma_descriptor tx_descriptor __attribute__ ((aligned(32))); static struct dma_descriptor rx_descr_array[NUM_RX_DESC] - __attribute__ ((aligned(32))); + __attribute__ ((aligned(32))); static struct dma_descriptor *rx_descr_current; -static int tsi108_eth_probe(struct eth_device *dev, bd_t * bis); -static int tsi108_eth_send(struct eth_device *dev, +static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis); +static int tsi108_eth_send (struct eth_device *dev, volatile void *packet, int length); -static int tsi108_eth_recv(struct eth_device *dev); -static void tsi108_eth_halt(struct eth_device *dev); -static unsigned int read_phy(unsigned int base, +static int tsi108_eth_recv (struct eth_device *dev); +static void tsi108_eth_halt (struct eth_device *dev); +static unsigned int read_phy (unsigned int base, unsigned int phy_addr, unsigned int phy_reg); -static void write_phy(unsigned int base, +static void write_phy (unsigned int base, unsigned int phy_addr, unsigned int phy_reg, unsigned int phy_data); @@ -447,15 +449,15 @@ static void write_phy(unsigned int base, /* * print phy debug infomation */ -static void dump_phy_regs(unsigned int phy_addr) +static void dump_phy_regs (unsigned int phy_addr) { int i; - printf("PHY %d registers\n", phy_addr); + printf ("PHY %d registers\n", phy_addr); for (i = 0; i <= 30; i++) { - printf("%2d 0x%04x\n", i, read_phy(ETH_BASE, phy_addr, i)); + printf ("%2d 0x%04x\n", i, read_phy (ETH_BASE, phy_addr, i)); } - printf("\n"); + printf ("\n"); } #else @@ -466,27 +468,27 @@ static void dump_phy_regs(unsigned int phy_addr) /* * print debug infomation */ -static void tx_diag_regs(unsigned int base) +static void tx_diag_regs (unsigned int base) { int i; unsigned long dummy; - printf("TX diagnostics registers\n"); + printf ("TX diagnostics registers\n"); reg_TX_DIAGNOSTIC_ADDR(base) = 0x00 | TX_DIAGNOSTIC_ADDR_AI; - udelay(1000); + udelay (1000); dummy = reg_TX_DIAGNOSTIC_DATA(base); for (i = 0x00; i <= 0x05; i++) { - udelay(1000); - printf("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); + udelay (1000); + printf ("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); } reg_TX_DIAGNOSTIC_ADDR(base) = 0x40 | TX_DIAGNOSTIC_ADDR_AI; - udelay(1000); + udelay (1000); dummy = reg_TX_DIAGNOSTIC_DATA(base); for (i = 0x40; i <= 0x47; i++) { - udelay(1000); - printf("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); + udelay (1000); + printf ("0x%02x 0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); } - printf("\n"); + printf ("\n"); } #else @@ -497,27 +499,27 @@ static void tx_diag_regs(unsigned int base) /* * print debug infomation */ -static void rx_diag_regs(unsigned int base) +static void rx_diag_regs (unsigned int base) { int i; unsigned long dummy; - printf("RX diagnostics registers\n"); + printf ("RX diagnostics registers\n"); reg_RX_DIAGNOSTIC_ADDR(base) = 0x00 | RX_DIAGNOSTIC_ADDR_AI; - udelay(1000); + udelay (1000); dummy = reg_RX_DIAGNOSTIC_DATA(base); for (i = 0x00; i <= 0x05; i++) { - udelay(1000); - printf("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); + udelay (1000); + printf ("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); } reg_RX_DIAGNOSTIC_ADDR(base) = 0x40 | RX_DIAGNOSTIC_ADDR_AI; - udelay(1000); + udelay (1000); dummy = reg_RX_DIAGNOSTIC_DATA(base); for (i = 0x08; i <= 0x0a; i++) { - udelay(1000); - printf("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); + udelay (1000); + printf ("0x%02x 0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); } - printf("\n"); + printf ("\n"); } #else @@ -528,15 +530,15 @@ static void rx_diag_regs(unsigned int base) /* * print debug infomation */ -static void debug_mii_regs(unsigned int base) +static void debug_mii_regs (unsigned int base) { - printf("MII_MGMT_CONFIG 0x%08x\n", reg_MII_MGMT_CONFIG(base)); - printf("MII_MGMT_COMMAND 0x%08x\n", reg_MII_MGMT_COMMAND(base)); - printf("MII_MGMT_ADDRESS 0x%08x\n", reg_MII_MGMT_ADDRESS(base)); - printf("MII_MGMT_CONTROL 0x%08x\n", reg_MII_MGMT_CONTROL(base)); - printf("MII_MGMT_STATUS 0x%08x\n", reg_MII_MGMT_STATUS(base)); - printf("MII_MGMT_INDICATORS 0x%08x\n", reg_MII_MGMT_INDICATORS(base)); - printf("\n"); + printf ("MII_MGMT_CONFIG 0x%08x\n", reg_MII_MGMT_CONFIG(base)); + printf ("MII_MGMT_COMMAND 0x%08x\n", reg_MII_MGMT_COMMAND(base)); + printf ("MII_MGMT_ADDRESS 0x%08x\n", reg_MII_MGMT_ADDRESS(base)); + printf ("MII_MGMT_CONTROL 0x%08x\n", reg_MII_MGMT_CONTROL(base)); + printf ("MII_MGMT_STATUS 0x%08x\n", reg_MII_MGMT_STATUS(base)); + printf ("MII_MGMT_INDICATORS 0x%08x\n", reg_MII_MGMT_INDICATORS(base)); + printf ("\n"); } #else @@ -546,15 +548,15 @@ static void debug_mii_regs(unsigned int base) /* * Wait until the phy bus is non-busy */ -static void phy_wait(unsigned int base, unsigned int condition) +static void phy_wait (unsigned int base, unsigned int condition) { int timeout; timeout = 0; while (reg_MII_MGMT_INDICATORS(base) & condition) { - udelay(10); + udelay (10); if (++timeout > 10000) { - printf("ERROR: timeout waiting for phy bus (%d)\n", + printf ("ERROR: timeout waiting for phy bus (%d)\n", condition); break; } @@ -564,12 +566,12 @@ static void phy_wait(unsigned int base, unsigned int condition) /* * read phy register */ -static unsigned int read_phy(unsigned int base, +static unsigned int read_phy (unsigned int base, unsigned int phy_addr, unsigned int phy_reg) { unsigned int value; - phy_wait(base, MII_MGMT_INDICATORS_BUSY); + phy_wait (base, MII_MGMT_INDICATORS_BUSY); reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; @@ -580,7 +582,7 @@ static unsigned int read_phy(unsigned int base, reg_MII_MGMT_COMMAND(base) = MII_MGMT_COMMAND_READ_CYCLE; /* wait for the read to complete */ - phy_wait(base, + phy_wait (base, MII_MGMT_INDICATORS_NOT_VALID | MII_MGMT_INDICATORS_BUSY); value = reg_MII_MGMT_STATUS(base); @@ -593,11 +595,11 @@ static unsigned int read_phy(unsigned int base, /* * write phy register */ -static void write_phy(unsigned int base, +static void write_phy (unsigned int base, unsigned int phy_addr, unsigned int phy_reg, unsigned int phy_data) { - phy_wait(base, MII_MGMT_INDICATORS_BUSY); + phy_wait (base, MII_MGMT_INDICATORS_BUSY); reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; @@ -611,7 +613,7 @@ static void write_phy(unsigned int base, /* * configure the marvell 88e1111 phy */ -static int marvell_88e_phy_config(struct eth_device *dev, int *speed, +static int marvell_88e_phy_config (struct eth_device *dev, int *speed, int *duplex) { unsigned long base; @@ -630,40 +632,39 @@ static int marvell_88e_phy_config(struct eth_device *dev, int *speed, phy_addr = (unsigned long)dev->priv; /* Take the PHY out of reset. */ - write_phy(ETH_BASE, phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET); + write_phy (ETH_BASE, phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET); /* Wait for the reset process to complete. */ - udelay(10); + udelay (10); timeout = 0; while ((phy_status = - read_phy(ETH_BASE, phy_addr, PHY_CTRL_REG)) & PHY_CTRL_RESET) { - udelay(10); + read_phy (ETH_BASE, phy_addr, PHY_CTRL_REG)) & PHY_CTRL_RESET) { + udelay (10); if (++timeout > 10000) { - printf("ERROR: timeout waiting for phy reset\n"); + printf ("ERROR: timeout waiting for phy reset\n"); break; } } /* TBI Configuration. */ - write_phy(base, TBI_ADDR, TBI_CONTROL_2, TBI_CONTROL_2_G_MII_MODE | + write_phy (base, TBI_ADDR, TBI_CONTROL_2, TBI_CONTROL_2_G_MII_MODE | TBI_CONTROL_2_RECEIVE_CLOCK_SELECT); /* Wait for the link to be established. */ timeout = 0; do { - udelay(20000); - phy_status = read_phy(ETH_BASE, phy_addr, PHY_STATUS_REG); + udelay (20000); + phy_status = read_phy (ETH_BASE, phy_addr, PHY_STATUS_REG); if (++timeout > 100) { debug_lev(1, "ERROR: unable to establish link!!!\n"); break; } } while ((phy_status & PHY_STAT_LINK_UP) == 0); - if ((phy_status & PHY_STAT_LINK_UP) == 0) { + if ((phy_status & PHY_STAT_LINK_UP) == 0) return 0; - } value = 0; - phy_spec_status = read_phy(ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); + phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); if (phy_spec_status & SPEC_STAT_RESOLVED) { switch (phy_spec_status & SPEC_STAT_SPEED_MASK) { case SPEED_1000: @@ -681,45 +682,41 @@ static int marvell_88e_phy_config(struct eth_device *dev, int *speed, if (phy_spec_status & SPEC_STAT_FULL_DUP) { phy_duplex = LINK_DUPLEX_FULL; value |= PHY_CTRL_FULL_DUPLEX; - } else { + } else phy_duplex = LINK_DUPLEX_HALF; - } } /* set TBI speed */ - write_phy(base, TBI_ADDR, PHY_CTRL_REG, value); - write_phy(base, TBI_ADDR, PHY_AN_ADV_REG, 0x0060); + write_phy (base, TBI_ADDR, PHY_CTRL_REG, value); + write_phy (base, TBI_ADDR, PHY_AN_ADV_REG, 0x0060); #if TSI108_ETH_DEBUG > 0 - printf("%s link is up", dev->name); - phy_spec_status = read_phy(ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); + printf ("%s link is up", dev->name); + phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); if (phy_spec_status & SPEC_STAT_RESOLVED) { switch (phy_speed) { case LINK_SPEED_1000: - printf(", 1000 Mbps"); + printf (", 1000 Mbps"); break; case LINK_SPEED_100: - printf(", 100 Mbps"); + printf (", 100 Mbps"); break; case LINK_SPEED_10: - printf(", 10 Mbps"); + printf (", 10 Mbps"); break; } - if (phy_duplex == LINK_DUPLEX_FULL) { - printf(", Full duplex"); - } else { - printf(", Half duplex"); - } + if (phy_duplex == LINK_DUPLEX_FULL) + printf (", Full duplex"); + else + printf (", Half duplex"); } - printf("\n"); + printf ("\n"); #endif - dump_phy_regs(TBI_ADDR); - if (speed) { + dump_phy_regs (TBI_ADDR); + if (speed) *speed = phy_speed; - } - if (duplex) { + if (duplex) *duplex = phy_duplex; - } return 1; } @@ -729,7 +726,7 @@ static int marvell_88e_phy_config(struct eth_device *dev, int *speed, * * register the tsi108 ethernet controllers with the multi-ethernet system */ -int tsi108_eth_initialize(bd_t * bis) +int tsi108_eth_initialize (bd_t * bis) { struct eth_device *dev; int index; @@ -737,7 +734,7 @@ int tsi108_eth_initialize(bd_t * bis) for (index = 0; index < CONFIG_TSI108_ETH_NUM_PORTS; index++) { dev = (struct eth_device *)malloc(sizeof(struct eth_device)); - sprintf(dev->name, "TSI108_eth%d", index); + sprintf (dev->name, "TSI108_eth%d", index); dev->iobase = ETH_BASE + (index * ETH_PORT_OFFSET); dev->priv = (void *)(phy_address[index]); @@ -754,7 +751,7 @@ int tsi108_eth_initialize(bd_t * bis) /* * probe for and initialize a single ethernet interface */ -static int tsi108_eth_probe(struct eth_device *dev, bd_t * bis) +static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis) { unsigned long base; unsigned long value; @@ -794,25 +791,23 @@ static int tsi108_eth_probe(struct eth_device *dev, bd_t * bis) reg_STATION_ADDRESS_2(base) = (dev->enetaddr[1] << 24) | (dev->enetaddr[0] << 16); - if (marvell_88e_phy_config(dev, &speed, &duplex) == 0) { + if (marvell_88e_phy_config(dev, &speed, &duplex) == 0) return 0; - } value = MAC_CONFIG_2_PREAMBLE_LENGTH(7) | MAC_CONFIG_2_PAD_CRC | MAC_CONFIG_2_CRC_ENABLE; - if (speed == LINK_SPEED_1000) { + if (speed == LINK_SPEED_1000) value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_BYTE); - } else { + else { value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_NIBBLE); reg_PORT_CONTROL(base) |= PORT_CONTROL_SPD; } if (duplex == LINK_DUPLEX_FULL) { value |= MAC_CONFIG_2_FULL_DUPLEX; reg_PORT_CONTROL(base) &= ~PORT_CONTROL_BPT; - } else { + } else reg_PORT_CONTROL(base) |= PORT_CONTROL_BPT; - } reg_MAC_CONFIG_2(base) = value; reg_RX_CONFIG(base) = RX_CONFIG_SE; @@ -875,7 +870,7 @@ static int tsi108_eth_probe(struct eth_device *dev, bd_t * bis) /* * send a packet */ -static int tsi108_eth_send(struct eth_device *dev, +static int tsi108_eth_send (struct eth_device *dev, volatile void *packet, int length) { unsigned long base; @@ -894,9 +889,8 @@ static int tsi108_eth_send(struct eth_device *dev, (unsigned long)tx_descr + sizeof(struct dma_descriptor)); - if (timeout != 0) { - udelay(15); - } + if (timeout != 0) + udelay (15); if (++timeout > 10000) { tx_diag_regs(base); debug_lev(1, @@ -908,7 +902,7 @@ static int tsi108_eth_send(struct eth_device *dev, status = le32_to_cpu(tx_descr->config_status); if ((status & DMA_DESCR_TX_OK) == 0) { #ifdef TX_PRINT_ERRORS - printf("TX packet error: 0x%08x\n %s%s%s%s\n", status, + printf ("TX packet error: 0x%08x\n %s%s%s%s\n", status, status & DMA_DESCR_TX_OK ? "tx error, " : "", status & DMA_DESCR_TX_RETRY_LIMIT ? "retry limit reached, " : "", @@ -918,7 +912,7 @@ static int tsi108_eth_send(struct eth_device *dev, #endif } - debug_lev(9, "sending packet %d\n", length); + debug_lev (9, "sending packet %d\n", length); tx_descr->start_addr0 = cpu_to_le32((vuint32) packet); tx_descr->start_addr1 = 0; tx_descr->next_descr_addr0 = 0; @@ -946,7 +940,7 @@ static int tsi108_eth_send(struct eth_device *dev, /* * Check for received packets and send them up the protocal stack */ -static int tsi108_eth_recv(struct eth_device *dev) +static int tsi108_eth_recv (struct eth_device *dev) { struct dma_descriptor *rx_descr; unsigned long base; @@ -957,7 +951,7 @@ static int tsi108_eth_recv(struct eth_device *dev) base = dev->iobase; /* make sure we see the changes made by the DMA engine */ - invalidate_dcache_range((unsigned long)rx_descr_array, + invalidate_dcache_range ((unsigned long)rx_descr_array, (unsigned long)rx_descr_array + sizeof(rx_descr_array)); @@ -968,7 +962,7 @@ static int tsi108_eth_recv(struct eth_device *dev) status = le32_to_cpu(rx_descr->config_status); if (status & DMA_DESCR_RX_BAD_FRAME) { #ifdef RX_PRINT_ERRORS - printf("RX packet error: 0x%08x\n %s%s%s%s%s%s\n", + printf ("RX packet error: 0x%08x\n %s%s%s%s%s%s\n", status, status & DMA_DESCR_RX_FRAME_IS_TYPE ? "too big, " : "", @@ -989,24 +983,23 @@ static int tsi108_eth_recv(struct eth_device *dev) /*** process packet ***/ buffer = (volatile uchar - *)(le32_to_cpu(rx_descr->start_addr0)); - NetReceive(buffer, length); + *)(le32_to_cpu (rx_descr->start_addr0)); + NetReceive (buffer, length); - invalidate_dcache_range((unsigned long)buffer, + invalidate_dcache_range ((unsigned long)buffer, (unsigned long)buffer + RX_BUFFER_SIZE); } /* Give this buffer back to the DMA engine */ rx_descr->vlan_byte_count = 0; - rx_descr->config_status = cpu_to_le32((RX_BUFFER_SIZE << 16) | + rx_descr->config_status = cpu_to_le32 ((RX_BUFFER_SIZE << 16) | DMA_DESCR_RX_OWNER); /* move descriptor pointer forward */ rx_descr = (struct dma_descriptor - *)(le32_to_cpu(rx_descr->next_descr_addr0)); - if (rx_descr == 0) { + *)(le32_to_cpu (rx_descr->next_descr_addr0)); + if (rx_descr == 0) rx_descr = &rx_descr_array[0]; - } } /* remember where we are for next time */ rx_descr_current = rx_descr; @@ -1026,7 +1019,7 @@ static int tsi108_eth_recv(struct eth_device *dev) /* * disable an ethernet interface */ -static void tsi108_eth_halt(struct eth_device *dev) +static void tsi108_eth_halt (struct eth_device *dev) { unsigned long base; diff --git a/drivers/tsi108_i2c.c b/drivers/tsi108_i2c.c index 08e5e3b4f5..c100cb8247 100644 --- a/drivers/tsi108_i2c.c +++ b/drivers/tsi108_i2c.c @@ -23,19 +23,18 @@ */ #include +#include #ifdef CONFIG_TSI108_I2C - -#include #include #if (CONFIG_COMMANDS & CFG_CMD_I2C) -#define I2C_DELAY 100000 +#define I2C_DELAY 100000 #undef DEBUG_I2C #ifdef DEBUG_I2C -#define DPRINT(x) printf(x) +#define DPRINT(x) printf (x) #else #define DPRINT(x) #endif @@ -43,7 +42,7 @@ /* All functions assume that Tsi108 I2C block is the only master on the bus */ /* I2C read helper function */ -static int i2c_read_byte( +static int i2c_read_byte ( uint i2c_chan, /* I2C channel number: 0 - main, 1 - SDC SPD */ uchar chip_addr,/* I2C device address on the bus */ uint byte_addr, /* Byte address within I2C device */ @@ -55,19 +54,17 @@ static int i2c_read_byte( u32 op_status = TSI108_I2C_TIMEOUT_ERR; u32 chan_offset = TSI108_I2C_OFFSET; - DPRINT(("I2C read_byte() %d 0x%02x 0x%02x\n", + DPRINT (("I2C read_byte() %d 0x%02x 0x%02x\n", i2c_chan, chip_addr, byte_addr)); - if (0 != i2c_chan) { + if (0 != i2c_chan) chan_offset = TSI108_I2C_SDRAM_OFFSET; - } /* Check if I2C operation is in progress */ temp = *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2); if (0 == (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | - I2C_CNTRL2_START)) - ) { + I2C_CNTRL2_START))) { /* Set device address and operation (read = 0) */ temp = (byte_addr << 16) | ((chip_addr & 0x07) << 8) | ((chip_addr >> 3) & 0x0F); @@ -75,7 +72,7 @@ static int i2c_read_byte( temp; /* Issue the read command - * (at this moment all other parameters are 0 + * (at this moment all other parameters are 0 * (size = 1 byte, lane = 0) */ @@ -108,7 +105,7 @@ static int i2c_read_byte( /* report HW error */ op_status = TSI108_I2C_IF_ERROR; - DPRINT(("I2C HW error reported: 0x%02x\n", temp)); + DPRINT (("I2C HW error reported: 0x%02x\n", temp)); } break; @@ -117,20 +114,20 @@ static int i2c_read_byte( } else { op_status = TSI108_I2C_IF_BUSY; - DPRINT(("I2C Transaction start failed: 0x%02x\n", temp)); + DPRINT (("I2C Transaction start failed: 0x%02x\n", temp)); } - DPRINT(("I2C read_byte() status: 0x%02x\n", op_status)); + DPRINT (("I2C read_byte() status: 0x%02x\n", op_status)); return op_status; } -/* +/* * I2C Read interface as defined in "include/i2c.h" : * chip_addr: I2C chip address, range 0..127 * (to read from SPD channel EEPROM use (0xD0 ... 0xD7) * NOTE: The bit 7 in the chip_addr serves as a channel select. * This hack is for enabling "isdram" command on Tsi108 boards - * without changes to common code. Used for I2C reads only. + * without changes to common code. Used for I2C reads only. * byte_addr: Memory or register address within the chip * alen: Number of bytes to use for addr (typically 1, 2 for larger * memories, 0 for register type devices with only one @@ -141,7 +138,8 @@ static int i2c_read_byte( * Returns: 0 on success, not 0 on failure */ -int i2c_read(uchar chip_addr, uint byte_addr, int alen, uchar * buffer, int len) +int i2c_read (uchar chip_addr, uint byte_addr, int alen, + uchar * buffer, int len) { u32 op_status = TSI108_I2C_PARAM_ERR; u32 i2c_if = 0; @@ -159,20 +157,20 @@ int i2c_read(uchar chip_addr, uint byte_addr, int alen, uchar * buffer, int len) buffer++); if (TSI108_I2C_SUCCESS != op_status) { - DPRINT(("I2C read_byte() failed: 0x%02x (%d left)\n", op_status, len)); + DPRINT (("I2C read_byte() failed: 0x%02x (%d left)\n", op_status, len)); break; } } } - DPRINT(("I2C read() status: 0x%02x\n", op_status)); + DPRINT (("I2C read() status: 0x%02x\n", op_status)); return op_status; } /* I2C write helper function */ -static int i2c_write_byte(uchar chip_addr,/* I2C device address on the bus */ +static int i2c_write_byte (uchar chip_addr,/* I2C device address on the bus */ uint byte_addr, /* Byte address within I2C device */ uchar * buffer /* pointer to data buffer */ ) @@ -210,7 +208,7 @@ static int i2c_write_byte(uchar chip_addr,/* I2C device address on the bus */ /* Wait until operation completed */ do { - // Read I2C operation status + /* Read I2C operation status */ temp = *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_CNTRL2); @@ -227,7 +225,7 @@ static int i2c_write_byte(uchar chip_addr,/* I2C device address on the bus */ /* report detected HW error */ op_status = TSI108_I2C_IF_ERROR; - DPRINT(("I2C HW error reported: 0x%02x\n", temp)); + DPRINT (("I2C HW error reported: 0x%02x\n", temp)); } break; @@ -237,13 +235,13 @@ static int i2c_write_byte(uchar chip_addr,/* I2C device address on the bus */ } else { op_status = TSI108_I2C_IF_BUSY; - DPRINT(("I2C Transaction start failed: 0x%02x\n", temp)); + DPRINT (("I2C Transaction start failed: 0x%02x\n", temp)); } return op_status; } -/* +/* * I2C Write interface as defined in "include/i2c.h" : * chip_addr: I2C chip address, range 0..127 * byte_addr: Memory or register address within the chip @@ -256,7 +254,7 @@ static int i2c_write_byte(uchar chip_addr,/* I2C device address on the bus */ * Returns: 0 on success, not 0 on failure */ -int i2c_write(uchar chip_addr, uint byte_addr, int alen, uchar * buffer, +int i2c_write (uchar chip_addr, uint byte_addr, int alen, uchar * buffer, int len) { u32 op_status = TSI108_I2C_PARAM_ERR; @@ -265,10 +263,10 @@ int i2c_write(uchar chip_addr, uint byte_addr, int alen, uchar * buffer, if (chip_addr <= 0x7F && (byte_addr + len) <= (0x01 << (alen * 8))) { while (len--) { op_status = - i2c_write_byte(chip_addr, byte_addr++, buffer++); + i2c_write_byte (chip_addr, byte_addr++, buffer++); if (TSI108_I2C_SUCCESS != op_status) { - DPRINT(("I2C write_byte() failed: 0x%02x (%d left)\n", op_status, len)); + DPRINT (("I2C write_byte() failed: 0x%02x (%d left)\n", op_status, len)); break; } @@ -278,13 +276,13 @@ int i2c_write(uchar chip_addr, uint byte_addr, int alen, uchar * buffer, return op_status; } -/* +/* * I2C interface function as defined in "include/i2c.h". * Probe the given I2C chip address by reading single byte from offset 0. * Returns 0 if a chip responded, not 0 on failure. */ -int i2c_probe(uchar chip) +int i2c_probe (uchar chip) { u32 tmp; @@ -293,8 +291,8 @@ int i2c_probe(uchar chip) * The Tsi108 HW doesn't support sending just the chip address * and checkong for an back. */ - return i2c_read(chip, 0, 1, (char *)&tmp, 1); + return i2c_read (chip, 0, 1, (char *)&tmp, 1); } -#endif /* (CONFIG_COMMANDS & CFG_CMD_I2C) */ +#endif /* (CONFIG_COMMANDS & CFG_CMD_I2C) */ #endif /* CONFIG_TSI108_I2C */ diff --git a/drivers/tsi108_pci.c b/drivers/tsi108_pci.c index f374ede662..9f606df518 100644 --- a/drivers/tsi108_pci.c +++ b/drivers/tsi108_pci.c @@ -36,7 +36,7 @@ struct pci_controller local_hose; -void tsi108_clear_pci_error(void) +void tsi108_clear_pci_error (void) { u32 err_stat, err_addr, pci_stat; @@ -79,11 +79,11 @@ void tsi108_clear_pci_error(void) return; } -unsigned int __get_pci_config_dword(u32 addr) +unsigned int __get_pci_config_dword (u32 addr) { unsigned int retval; - __asm__ __volatile__(" lwbrx %0,0,%1\n" + __asm__ __volatile__ (" lwbrx %0,0,%1\n" "1: eieio\n" "2:\n" ".section .fixup,\"ax\"\n" @@ -97,53 +97,53 @@ unsigned int __get_pci_config_dword(u32 addr) return (retval); } -static int tsi108_read_config_dword(struct pci_controller *hose, +static int tsi108_read_config_dword (struct pci_controller *hose, pci_dev_t dev, int offset, u32 * value) { dev &= (CFG_PCI_CFG_SIZE - 1); dev |= (CFG_PCI_CFG_BASE | (offset & 0xfc)); *value = __get_pci_config_dword(dev); if (0xFFFFFFFF == *value) - tsi108_clear_pci_error(); + tsi108_clear_pci_error (); return 0; } -static int tsi108_write_config_dword(struct pci_controller *hose, +static int tsi108_write_config_dword (struct pci_controller *hose, pci_dev_t dev, int offset, u32 value) { dev &= (CFG_PCI_CFG_SIZE - 1); dev |= (CFG_PCI_CFG_BASE | (offset & 0xfc)); - out_le32((volatile unsigned *)dev, value); + out_le32 ((volatile unsigned *)dev, value); return 0; } -void pci_init_board(void) +void pci_init_board (void) { struct pci_controller *hose = (struct pci_controller *)&local_hose; hose->first_busno = 0; hose->last_busno = 0xff; - pci_set_region(hose->regions + 0, + pci_set_region (hose->regions + 0, CFG_PCI_MEMORY_BUS, CFG_PCI_MEMORY_PHYS, CFG_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_MEMORY); /* PCI memory space */ - pci_set_region(hose->regions + 1, + pci_set_region (hose->regions + 1, CFG_PCI_MEM_BUS, CFG_PCI_MEM_PHYS, CFG_PCI_MEM_SIZE, PCI_REGION_MEM); /* PCI I/O space */ - pci_set_region(hose->regions + 2, + pci_set_region (hose->regions + 2, CFG_PCI_IO_BUS, CFG_PCI_IO_PHYS, CFG_PCI_IO_SIZE, PCI_REGION_IO); hose->region_count = 3; - pci_set_ops(hose, + pci_set_ops (hose, pci_hose_read_config_byte_via_dword, pci_hose_read_config_word_via_dword, tsi108_read_config_dword, @@ -151,22 +151,22 @@ void pci_init_board(void) pci_hose_write_config_word_via_dword, tsi108_write_config_dword); - pci_register_hose(hose); + pci_register_hose (hose); - hose->last_busno = pci_hose_scan(hose); + hose->last_busno = pci_hose_scan (hose); - debug("Done PCI initialization\n"); + debug ("Done PCI initialization\n"); return; } #ifdef CONFIG_OF_FLAT_TREE void -ft_pci_setup(void *blob, bd_t *bd) +ft_pci_setup (void *blob, bd_t *bd) { u32 *p; int len; - p = (u32 *)ft_get_prop(blob, "/" OF_TSI "/pci@1000/bus-range", &len); + p = (u32 *)ft_get_prop (blob, "/" OF_TSI "/pci@1000/bus-range", &len); if (p != NULL) { p[0] = local_hose.first_busno; p[1] = local_hose.last_busno; -- cgit v1.2.1 From ddd02492f43db5408f5ab9f823b0ba5796e28ef0 Mon Sep 17 00:00:00 2001 From: Dave Liu Date: Wed, 6 Dec 2006 11:38:17 +0800 Subject: mpc83xx: Fix the UEC driver bug of QE The patch prevents the GCC tool chain from striping useful code for optimization. It will make UEC ethernet driver workable, Otherwise the UEC will fail in tx when you are using gcc4.x. but the driver can work when using gcc3.4.3. CHANGELOG *Prevent the GCC from striping code for optimization, Otherwise the UEC will tx failed when you are using gcc4.x. Signed-off-by: Dave Liu --- drivers/qe/uec.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index f640c81916..c44a5be9da 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -1122,7 +1122,7 @@ static int uec_send(struct eth_device* dev, volatile void *buf, int len) uec_private_t *uec; ucc_fast_private_t *uccf; volatile qe_bd_t *bd; - volatile u16 status; + u16 status; int i; int result = 0; @@ -1131,7 +1131,7 @@ static int uec_send(struct eth_device* dev, volatile void *buf, int len) bd = uec->txBd; /* Find an empty TxBD */ - for (i = 0; BD_STATUS(bd) & TxBD_READY; i++) { + for (i = 0; bd->status & TxBD_READY; i++) { if (i > 0x100000) { printf("%s: tx buffer not ready\n", dev->name); return result; @@ -1150,13 +1150,11 @@ static int uec_send(struct eth_device* dev, volatile void *buf, int len) ucc_fast_transmit_on_demand(uccf); /* Wait for buffer to be transmitted */ - status = BD_STATUS(bd); - for (i = 0; status & TxBD_READY; i++) { + for (i = 0; bd->status & TxBD_READY; i++) { if (i > 0x100000) { printf("%s: tx error\n", dev->name); return result; } - status = BD_STATUS(bd); } /* Ok, the buffer be transimitted */ @@ -1171,12 +1169,12 @@ static int uec_recv(struct eth_device* dev) { uec_private_t *uec = dev->priv; volatile qe_bd_t *bd; - volatile u16 status; + u16 status; u16 len; u8 *data; bd = uec->rxBd; - status = BD_STATUS(bd); + status = bd->status; while (!(status & RxBD_EMPTY)) { if (!(status & RxBD_ERROR)) { @@ -1190,7 +1188,7 @@ static int uec_recv(struct eth_device* dev) BD_LENGTH_SET(bd, 0); BD_STATUS_SET(bd, status | RxBD_EMPTY); BD_ADVANCE(bd, status, uec->p_rx_bd_ring); - status = BD_STATUS(bd); + status = bd->status; } uec->rxBd = bd; -- cgit v1.2.1 From 24c3aca3f1358b113d3215adb5433b156e99f72b Mon Sep 17 00:00:00 2001 From: Dave Liu Date: Thu, 7 Dec 2006 21:13:15 +0800 Subject: mpc83xx: Add support for the MPC832XEMDS board This patch supports DUART, ETH3/4 and PCI etc. Signed-off-by: Dave Liu --- drivers/qe/qe.h | 2 +- drivers/qe/uec.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/qe/qe.h b/drivers/qe/qe.h index f7f8ed0a72..0bcd0a9573 100644 --- a/drivers/qe/qe.h +++ b/drivers/qe/qe.h @@ -30,7 +30,7 @@ #define UCC_MAX_NUM 8 #define QE_DATAONLY_BASE (uint)(128) -#define QE_DATAONLY_SIZE ((uint)(0xc000) - QE_DATAONLY_BASE) +#define QE_DATAONLY_SIZE (QE_MURAM_SIZE - QE_DATAONLY_BASE) /* QE threads SNUM */ diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index c44a5be9da..aea455b8dc 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -432,7 +432,12 @@ static int init_phy(struct eth_device *dev) } memset(mii_info, 0, sizeof(*mii_info)); - mii_info->speed = SPEED_1000; + if (uec->uec_info->uf_info.eth_type == GIGA_ETH) { + mii_info->speed = SPEED_1000; + } else { + mii_info->speed = SPEED_100; + } + mii_info->duplex = DUPLEX_FULL; mii_info->pause = 0; mii_info->link = 1; @@ -508,7 +513,8 @@ static void adjust_link(struct eth_device *dev) } if (mii_info->speed != uec->oldspeed) { - switch (mii_info->speed) { + if (uec->uec_info->uf_info.eth_type == GIGA_ETH) { + switch (mii_info->speed) { case 1000: break; case 100: @@ -531,6 +537,7 @@ static void adjust_link(struct eth_device *dev) printf("%s: Ack,Speed(%d)is illegal\n", dev->name, mii_info->speed); break; + } } printf("%s: Speed %dBT\n", dev->name, mii_info->speed); -- cgit v1.2.1 From 91e25769771c1164ed63ffca0add49f934ae3343 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 16 Jan 2007 11:38:14 -0500 Subject: mpc83xx: U-Boot support for Wind River SBC8349 I've redone the SBC8349 support to match git-current, which incorporates all the MPC834x updates from Freescale since the 1.1.6 release, including the DDR changes. I've kept all the SBC8349 files as parallel as possible to the MPC8349EMDS ones for ease of maintenance and to allow for easy inspection of what was changed to support this board. Hence the SBC8349 U-Boot has FDT support and everything else that the MPC8349EMDS has. Fortunately the Freescale updates added support for boards using CS0, but I had to change spd_sdram.c to allow for board specific settings for the sdram_clk_cntl (it is/was hard coded to zero, and that remains the default if the board doesn't specify a value.) Hopefully this should be mergeable as-is and require no whitespace cleanups or similar, but if something doesn't measure up then let me know and I'll fix it. Thanks, Paul. --- drivers/tsec.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/tsec.h | 5 ++++ 2 files changed, 89 insertions(+) (limited to 'drivers') diff --git a/drivers/tsec.c b/drivers/tsec.c index 2524e4f6d2..3f11eb03b4 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -381,6 +381,61 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) return 0; } +/* + * Parse the BCM54xx status register for speed and duplex information. + * The linux sungem_phy has this information, but in a table format. + */ +uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv) +{ + + switch((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >> MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT){ + + case 1: + printf("Enet starting in 10BT/HD\n"); + priv->duplexity = 0; + priv->speed = 10; + break; + + case 2: + printf("Enet starting in 10BT/FD\n"); + priv->duplexity = 1; + priv->speed = 10; + break; + + case 3: + printf("Enet starting in 100BT/HD\n"); + priv->duplexity = 0; + priv->speed = 100; + break; + + case 5: + printf("Enet starting in 100BT/FD\n"); + priv->duplexity = 1; + priv->speed = 100; + break; + + case 6: + printf("Enet starting in 1000BT/HD\n"); + priv->duplexity = 0; + priv->speed = 1000; + break; + + case 7: + printf("Enet starting in 1000BT/FD\n"); + priv->duplexity = 1; + priv->speed = 1000; + break; + + default: + printf("Auto-neg error, defaulting to 10BT/HD\n"); + priv->duplexity = 0; + priv->speed = 10; + break; + } + + return 0; + +} /* Parse the 88E1011's status register for speed and duplex * information */ @@ -770,6 +825,34 @@ static void tsec_halt(struct eth_device *dev) phy_run_commands(priv, priv->phyinfo->shutdown); } +/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */ +struct phy_info phy_info_BCM5461S = { + 0x02060c1, /* 5461 ID */ + "Broadcom BCM5461S", + 0, /* not clear to me what minor revisions we can shift away */ + (struct phy_cmd[]) { /* config */ + /* Reset and configure the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]) { /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, + {miim_end,} + }, + (struct phy_cmd[]) { /* shutdown */ + {miim_end,} + }, +}; + struct phy_info phy_info_M88E1011S = { 0x01410c6, "Marvell 88E1011S", @@ -1112,6 +1195,7 @@ struct phy_info phy_info_dp83865 = { struct phy_info *phy_info[] = { &phy_info_cis8204, &phy_info_cis8201, + &phy_info_BCM5461S, &phy_info_M88E1011S, &phy_info_M88E1111S, &phy_info_M88E1145, diff --git a/drivers/tsec.h b/drivers/tsec.h index cee30037db..422bc66922 100644 --- a/drivers/tsec.h +++ b/drivers/tsec.h @@ -109,6 +109,11 @@ #define MIIM_GBIT_CONTROL 0x9 #define MIIM_GBIT_CONTROL_INIT 0xe00 +/* Broadcom BCM54xx -- taken from linux sungem_phy */ +#define MIIM_BCM54xx_AUXSTATUS 0x19 +#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK 0x0700 +#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT 8 + /* Cicada Auxiliary Control/Status Register */ #define MIIM_CIS8201_AUX_CONSTAT 0x1c #define MIIM_CIS8201_AUXCONSTAT_INIT 0x0004 -- cgit v1.2.1 From a28899c910024a0226331df07207b1038c300c93 Mon Sep 17 00:00:00 2001 From: Emilian Medve Date: Tue, 30 Jan 2007 16:14:50 -0600 Subject: mpc83xx: Fix alternating tx error / tx buffer not ready bug in QE UEC The problem is not gcc4 but the code itself. The BD_STATUS() macro can't be used for busy-waiting since it strips the 'volatile' property from the bd variable. gcc3 was working by pure luck. This is a follow on patch to "Fix the UEC driver bug of QE" --- drivers/qe/uec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index aea455b8dc..c416a67c83 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -1148,7 +1148,7 @@ static int uec_send(struct eth_device* dev, volatile void *buf, int len) /* Init TxBD */ BD_DATA_SET(bd, buf); BD_LENGTH_SET(bd, len); - status = BD_STATUS(bd); + status = bd->status; status &= BD_WRAP; status |= (TxBD_READY | TxBD_LAST); BD_STATUS_SET(bd, status); -- cgit v1.2.1 From f6f5f709e5c8e4564c4dfeecfdf2279244f9c83b Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 31 Jan 2007 11:04:19 +0100 Subject: mpc83xx: Fix empty i2c reads/writes in fsl_i2c.c Fix empty i2c reads/writes, i2c_write(0x50, 0x00, 0, NULL, 0) which is used to se if an slave will ACK after receiving its address. Correct i2c probing to use this method as the old method could upset a slave as it wrote a data byte to it. Add a small delay in i2c_init() to let the controller shutdown any ongoing I2C activity. Signed-off-by: Joakim Tjernlund --- drivers/fsl_i2c.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/fsl_i2c.c b/drivers/fsl_i2c.c index c92909608a..ebae5af154 100644 --- a/drivers/fsl_i2c.c +++ b/drivers/fsl_i2c.c @@ -58,6 +58,7 @@ i2c_init(int speed, int slaveadd) dev = (struct fsl_i2c *) (CFG_IMMR + CFG_I2C_OFFSET); writeb(0, &dev->cr); /* stop I2C controller */ + udelay(5); /* let it shutdown in peace */ writeb(0x3F, &dev->fdr); /* set bus speed */ writeb(0x3F, &dev->dfsrr); /* set default filter */ writeb(slaveadd << 1, &dev->adr); /* write slave address */ @@ -191,15 +192,17 @@ __i2c_read(u8 *data, int length) int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) { - int i = 0; + int i = -1; /* signal error */ u8 *a = (u8*)&addr; if (i2c_wait4bus() >= 0 && i2c_write_addr(dev, I2C_WRITE_BIT, 0) != 0 - && __i2c_write(&a[4 - alen], alen) == alen - && i2c_write_addr(dev, I2C_READ_BIT, 1) != 0) { + && __i2c_write(&a[4 - alen], alen) == alen) + i = 0; /* No error so far */ + + if (length + && i2c_write_addr(dev, I2C_READ_BIT, 1) != 0) i = __i2c_read(data, length); - } writeb(I2C_CR_MEN, &i2c_dev[i2c_bus_num]->cr); @@ -212,7 +215,7 @@ i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) { - int i = 0; + int i = -1; /* signal error */ u8 *a = (u8*)&addr; if (i2c_wait4bus() >= 0 @@ -232,16 +235,14 @@ i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) int i2c_probe(uchar chip) { - int tmp; - - /* - * Try to read the first location of the chip. The underlying - * driver doesn't appear to support sending just the chip address - * and looking for an back. + /* For unknow reason the controller will ACK when + * probing for a slave with the same address, so skip + * it. */ - udelay(10000); + if (chip == (readb(&i2c_dev[i2c_bus_num]->adr) >> 1)) + return -1; - return i2c_read(chip, 0, 1, (uchar *)&tmp, 1); + return i2c_read(chip, 0, 0, NULL, 0); } uchar -- cgit v1.2.1 From 647d3c3eed0da1d1505eecabe0b0fab96f956e68 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sun, 4 Mar 2007 01:36:05 +0100 Subject: Some code cleanup. --- drivers/tsi108_i2c.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/tsi108_i2c.c b/drivers/tsi108_i2c.c index c100cb8247..eb52cb66c9 100644 --- a/drivers/tsi108_i2c.c +++ b/drivers/tsi108_i2c.c @@ -82,15 +82,10 @@ static int i2c_read_byte ( /* Wait until operation completed */ do { /* Read I2C operation status */ - temp = - *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + - I2C_CNTRL2); - - if (0 == - (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_START))) - { - if (0 == - (temp & + temp = *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2); + + if (0 == (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_START))) { + if (0 == (temp & (I2C_CNTRL2_I2C_CFGERR | I2C_CNTRL2_I2C_TO_ERR)) ) { @@ -152,9 +147,7 @@ int i2c_read (uchar chip_addr, uint byte_addr, int alen, /* Check for valid I2C address */ if (chip_addr <= 0x7F && (byte_addr + len) <= (0x01 << (alen * 8))) { while (len--) { - op_status = - i2c_read_byte(i2c_if, chip_addr, byte_addr++, - buffer++); + op_status = i2c_read_byte(i2c_if, chip_addr, byte_addr++, buffer++); if (TSI108_I2C_SUCCESS != op_status) { DPRINT (("I2C read_byte() failed: 0x%02x (%d left)\n", op_status, len)); @@ -182,10 +175,7 @@ static int i2c_write_byte (uchar chip_addr,/* I2C device address on the bus */ /* Check if I2C operation is in progress */ temp = *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_CNTRL2); - if (0 == - (temp & - (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) - { + if (0 == (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) { /* Place data into the I2C Tx Register */ *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_TX_DATA) = (u32) * buffer; @@ -200,7 +190,7 @@ static int i2c_write_byte (uchar chip_addr,/* I2C device address on the bus */ /* Issue the write command (at this moment all other parameters * are 0 (size = 1 byte, lane = 0) */ - + *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_CNTRL2) = (I2C_CNTRL2_START); @@ -209,15 +199,10 @@ static int i2c_write_byte (uchar chip_addr,/* I2C device address on the bus */ /* Wait until operation completed */ do { /* Read I2C operation status */ - temp = - *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + - I2C_CNTRL2); - - if (0 == - (temp & (I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) - { - if (0 == - (temp & + temp = *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_CNTRL2); + + if (0 == (temp & (I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) { + if (0 == (temp & (I2C_CNTRL2_I2C_CFGERR | I2C_CNTRL2_I2C_TO_ERR))) { op_status = TSI108_I2C_SUCCESS; -- cgit v1.2.1 From df548d3c3e2bbc40258713167859ffc2ce99a900 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Sun, 19 Nov 2006 18:06:53 +0100 Subject: AVR32: Resource management rewrite Rewrite the resource management code (i.e. I/O memory, clock gating, gpio) so it doesn't depend on any global state. This is necessary because this code is heavily used before relocation to RAM, so we can't write to any global variables. As an added bonus, this makes u-boot's memory footprint a bit smaller, although some functionality has been left out; all clocks are enabled all the time, and there's no checking for gpio line conflicts. Signed-off-by: Haavard Skinnemoen --- drivers/atmel_usart.c | 48 ++++++++++++++++++++++++++++++------------------ drivers/atmel_usart.h | 8 ++++---- 2 files changed, 34 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/atmel_usart.c b/drivers/atmel_usart.c index 41c37683d7..f35b99730f 100644 --- a/drivers/atmel_usart.c +++ b/drivers/atmel_usart.c @@ -19,7 +19,22 @@ #ifdef CONFIG_ATMEL_USART #include -#include +#include +#include + +#if defined(CONFIG_USART0) +# define USART_ID 0 +# define USART_BASE USART0_BASE +#elif defined(CONFIG_USART1) +# define USART_ID 1 +# define USART_BASE USART1_BASE +#elif defined(CONFIG_USART2) +# define USART_ID 2 +# define USART_BASE USART2_BASE +#elif defined(CONFIG_USART3) +# define USART_ID 3 +# define USART_BASE USART3_BASE +#endif #include "atmel_usart.h" @@ -35,26 +50,23 @@ void serial_setbrg(void) * Baud Rate = -------------- * 16 * CD */ - usart_hz = pm_get_clock_freq(gd->console_uart->resource[0].u.clock.id); + usart_hz = get_usart_clk_rate(USART_ID); divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate; - usart3_writel(gd->console_uart, BRGR, USART3_BF(CD, divisor)); + usart3_writel(BRGR, USART3_BF(CD, divisor)); } int serial_init(void) { - usart3_writel(gd->console_uart, CR, - USART3_BIT(RSTRX) | USART3_BIT(RSTTX)); + usart3_writel(CR, USART3_BIT(RSTRX) | USART3_BIT(RSTTX)); serial_setbrg(); - usart3_writel(gd->console_uart, CR, - USART3_BIT(RXEN) | USART3_BIT(TXEN)); - usart3_writel(gd->console_uart, MR, - USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL) - | USART3_BF(USCLKS, USART3_USCLKS_MCK) - | USART3_BF(CHRL, USART3_CHRL_8) - | USART3_BF(PAR, USART3_PAR_NONE) - | USART3_BF(NBSTOP, USART3_NBSTOP_1)); + usart3_writel(CR, USART3_BIT(RXEN) | USART3_BIT(TXEN)); + usart3_writel(MR, (USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL) + | USART3_BF(USCLKS, USART3_USCLKS_MCK) + | USART3_BF(CHRL, USART3_CHRL_8) + | USART3_BF(PAR, USART3_PAR_NONE) + | USART3_BF(NBSTOP, USART3_NBSTOP_1))); return 0; } @@ -64,8 +76,8 @@ void serial_putc(char c) if (c == '\n') serial_putc('\r'); - while (!(usart3_readl(gd->console_uart, CSR) & USART3_BIT(TXRDY))) ; - usart3_writel(gd->console_uart, THR, c); + while (!(usart3_readl(CSR) & USART3_BIT(TXRDY))) ; + usart3_writel(THR, c); } void serial_puts(const char *s) @@ -76,13 +88,13 @@ void serial_puts(const char *s) int serial_getc(void) { - while (!(usart3_readl(gd->console_uart, CSR) & USART3_BIT(RXRDY))) ; - return usart3_readl(gd->console_uart, RHR); + while (!(usart3_readl(CSR) & USART3_BIT(RXRDY))) ; + return usart3_readl(RHR); } int serial_tstc(void) { - return (usart3_readl(gd->console_uart, CSR) & USART3_BIT(RXRDY)) != 0; + return (usart3_readl(CSR) & USART3_BIT(RXRDY)) != 0; } #endif /* CONFIG_ATMEL_USART */ diff --git a/drivers/atmel_usart.h b/drivers/atmel_usart.h index fad90a8116..af3773a99f 100644 --- a/drivers/atmel_usart.h +++ b/drivers/atmel_usart.h @@ -306,9 +306,9 @@ | USART3_BF(name,value)) /* Register access macros */ -#define usart3_readl(port,reg) \ - readl((port)->regs + USART3_##reg) -#define usart3_writel(port,reg,value) \ - writel((value), (port)->regs + USART3_##reg) +#define usart3_readl(reg) \ + readl((void *)USART_BASE + USART3_##reg) +#define usart3_writel(reg,value) \ + writel((value), (void *)USART_BASE + USART3_##reg) #endif /* __DRIVERS_ATMEL_USART_H__ */ -- cgit v1.2.1 From 5c1fe1ffffd1750a7e47e5a2e2cd600c00e4f009 Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Fri, 20 Jan 2006 10:03:34 +0100 Subject: Atmel MACB ethernet driver Driver for the Atmel MACB on-chip ethernet controller. This driver has been tested on the ATSTK1000 board with a AT32AP7000 CPU. It should probably work on AT91SAM926x as well with some minor modifications. Hardware documentation can be found in the AT32AP7000 data sheet, which can be downloaded from http://www.atmel.com/dyn/products/datasheets.asp?family_id=682 Signed-off-by: Haavard Skinnemoen --- drivers/Makefile | 2 +- drivers/macb.c | 575 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/macb.h | 269 ++++++++++++++++++++++++++ 3 files changed, 845 insertions(+), 1 deletion(-) create mode 100644 drivers/macb.c create mode 100644 drivers/macb.h (limited to 'drivers') diff --git a/drivers/Makefile b/drivers/Makefile index fffc22a5e1..2eac7c8485 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -32,7 +32,7 @@ COBJS = 3c589.o 5701rls.o ali512x.o atmel_usart.o \ cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \ e1000.o eepro100.o \ i8042.o inca-ip_sw.o keyboard.o \ - lan91c96.o \ + lan91c96.o macb.o \ natsemi.o ne2000.o netarm_eth.o netconsole.o \ ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \ omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o \ diff --git a/drivers/macb.c b/drivers/macb.c new file mode 100644 index 0000000000..186ab19d35 --- /dev/null +++ b/drivers/macb.c @@ -0,0 +1,575 @@ +/* + * Copyright (C) 2005-2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + +#if defined(CONFIG_MACB) && (CONFIG_COMMANDS & (CFG_CMD_NET | CFG_CMD_MII)) + +/* + * The u-boot networking stack is a little weird. It seems like the + * networking core allocates receive buffers up front without any + * regard to the hardware that's supposed to actually receive those + * packets. + * + * The MACB receives packets into 128-byte receive buffers, so the + * buffers allocated by the core isn't very practical to use. We'll + * allocate our own, but we need one such buffer in case a packet + * wraps around the DMA ring so that we have to copy it. + * + * Therefore, define CFG_RX_ETH_BUFFER to 1 in the board-specific + * configuration header. This way, the core allocates one RX buffer + * and one TX buffer, each of which can hold a ethernet packet of + * maximum size. + * + * For some reason, the networking core unconditionally specifies a + * 32-byte packet "alignment" (which really should be called + * "padding"). MACB shouldn't need that, but we'll refrain from any + * core modifications here... + */ + +#include +#include + +#include +#include +#include +#include + +#include "macb.h" + +#define CFG_MACB_RX_BUFFER_SIZE 4096 +#define CFG_MACB_RX_RING_SIZE (CFG_MACB_RX_BUFFER_SIZE / 128) +#define CFG_MACB_TX_RING_SIZE 16 +#define CFG_MACB_TX_TIMEOUT 1000 +#define CFG_MACB_AUTONEG_TIMEOUT 5000000 + +struct macb_dma_desc { + u32 addr; + u32 ctrl; +}; + +#define RXADDR_USED 0x00000001 +#define RXADDR_WRAP 0x00000002 + +#define RXBUF_FRMLEN_MASK 0x00000fff +#define RXBUF_FRAME_START 0x00004000 +#define RXBUF_FRAME_END 0x00008000 +#define RXBUF_TYPEID_MATCH 0x00400000 +#define RXBUF_ADDR4_MATCH 0x00800000 +#define RXBUF_ADDR3_MATCH 0x01000000 +#define RXBUF_ADDR2_MATCH 0x02000000 +#define RXBUF_ADDR1_MATCH 0x04000000 +#define RXBUF_BROADCAST 0x80000000 + +#define TXBUF_FRMLEN_MASK 0x000007ff +#define TXBUF_FRAME_END 0x00008000 +#define TXBUF_NOCRC 0x00010000 +#define TXBUF_EXHAUSTED 0x08000000 +#define TXBUF_UNDERRUN 0x10000000 +#define TXBUF_MAXRETRY 0x20000000 +#define TXBUF_WRAP 0x40000000 +#define TXBUF_USED 0x80000000 + +struct macb_device { + void *regs; + + unsigned int rx_tail; + unsigned int tx_head; + unsigned int tx_tail; + + void *rx_buffer; + void *tx_buffer; + struct macb_dma_desc *rx_ring; + struct macb_dma_desc *tx_ring; + + unsigned long rx_buffer_dma; + unsigned long rx_ring_dma; + unsigned long tx_ring_dma; + + const struct device *dev; + struct eth_device netdev; + unsigned short phy_addr; +}; +#define to_macb(_nd) container_of(_nd, struct macb_device, netdev) + +static void macb_mdio_write(struct macb_device *macb, u8 reg, u16 value) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + + netctl = macb_readl(macb, NCR); + netctl |= MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + frame = (MACB_BF(SOF, 1) + | MACB_BF(RW, 1) + | MACB_BF(PHYA, macb->phy_addr) + | MACB_BF(REGA, reg) + | MACB_BF(CODE, 2) + | MACB_BF(DATA, value)); + macb_writel(macb, MAN, frame); + + do { + netstat = macb_readl(macb, NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + netctl = macb_readl(macb, NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); +} + +static u16 macb_mdio_read(struct macb_device *macb, u8 reg) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + + netctl = macb_readl(macb, NCR); + netctl |= MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + frame = (MACB_BF(SOF, 1) + | MACB_BF(RW, 2) + | MACB_BF(PHYA, macb->phy_addr) + | MACB_BF(REGA, reg) + | MACB_BF(CODE, 2)); + macb_writel(macb, MAN, frame); + + do { + netstat = macb_readl(macb, NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + frame = macb_readl(macb, MAN); + + netctl = macb_readl(macb, NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(macb, NCR, netctl); + + return MACB_BFEXT(DATA, frame); +} + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +static int macb_send(struct eth_device *netdev, volatile void *packet, + int length) +{ + struct macb_device *macb = to_macb(netdev); + unsigned long paddr, ctrl; + unsigned int tx_head = macb->tx_head; + int i; + + paddr = dma_map_single(packet, length, DMA_TO_DEVICE); + + ctrl = length & TXBUF_FRMLEN_MASK; + ctrl |= TXBUF_FRAME_END; + if (tx_head == (CFG_MACB_TX_RING_SIZE - 1)) { + ctrl |= TXBUF_WRAP; + macb->tx_head = 0; + } else + macb->tx_head++; + + macb->tx_ring[tx_head].ctrl = ctrl; + macb->tx_ring[tx_head].addr = paddr; + macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); + + /* + * I guess this is necessary because the networking core may + * re-use the transmit buffer as soon as we return... + */ + i = 0; + while (!(macb->tx_ring[tx_head].ctrl & TXBUF_USED)) { + if (i > CFG_MACB_TX_TIMEOUT) { + printf("%s: TX timeout\n", netdev->name); + break; + } + udelay(1); + i++; + } + + dma_unmap_single(packet, length, paddr); + + if (i <= CFG_MACB_TX_TIMEOUT) { + ctrl = macb->tx_ring[tx_head].ctrl; + if (ctrl & TXBUF_UNDERRUN) + printf("%s: TX underrun\n", netdev->name); + if (ctrl & TXBUF_EXHAUSTED) + printf("%s: TX buffers exhausted in mid frame\n", + netdev->name); + } + + /* No one cares anyway */ + return 0; +} + +static void reclaim_rx_buffers(struct macb_device *macb, + unsigned int new_tail) +{ + unsigned int i; + + i = macb->rx_tail; + while (i > new_tail) { + macb->rx_ring[i].addr &= ~RXADDR_USED; + i++; + if (i > CFG_MACB_RX_RING_SIZE) + i = 0; + } + + while (i < new_tail) { + macb->rx_ring[i].addr &= ~RXADDR_USED; + i++; + } + + macb->rx_tail = new_tail; +} + +static int macb_recv(struct eth_device *netdev) +{ + struct macb_device *macb = to_macb(netdev); + unsigned int rx_tail = macb->rx_tail; + void *buffer; + int length; + int wrapped = 0; + u32 status; + + for (;;) { + if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) + return -1; + + status = macb->rx_ring[rx_tail].ctrl; + if (status & RXBUF_FRAME_START) { + if (rx_tail != macb->rx_tail) + reclaim_rx_buffers(macb, rx_tail); + wrapped = 0; + } + + if (status & RXBUF_FRAME_END) { + buffer = macb->rx_buffer + 128 * macb->rx_tail; + length = status & RXBUF_FRMLEN_MASK; + if (wrapped) { + unsigned int headlen, taillen; + + headlen = 128 * (CFG_MACB_RX_RING_SIZE + - macb->rx_tail); + taillen = length - headlen; + memcpy((void *)NetRxPackets[0], + buffer, headlen); + memcpy((void *)NetRxPackets[0] + headlen, + macb->rx_buffer, taillen); + buffer = (void *)NetRxPackets[0]; + } + + NetReceive(buffer, length); + if (++rx_tail >= CFG_MACB_RX_RING_SIZE) + rx_tail = 0; + reclaim_rx_buffers(macb, rx_tail); + } else { + if (++rx_tail >= CFG_MACB_RX_RING_SIZE) { + wrapped = 1; + rx_tail = 0; + } + } + } + + return 0; +} + +static int macb_phy_init(struct macb_device *macb) +{ + struct eth_device *netdev = &macb->netdev; + u32 ncfgr; + u16 phy_id, status, adv, lpa; + int media, speed, duplex; + int i; + + /* Check if the PHY is up to snuff... */ + phy_id = macb_mdio_read(macb, MII_PHYSID1); + if (phy_id == 0xffff) { + printf("%s: No PHY present\n", netdev->name); + return 0; + } + + adv = ADVERTISE_CSMA | ADVERTISE_ALL; + macb_mdio_write(macb, MII_ADVERTISE, adv); + printf("%s: Starting autonegotiation...\n", netdev->name); + macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE + | BMCR_ANRESTART)); + +#if 0 + for (i = 0; i < 9; i++) + printf("mii%d: 0x%04x\n", i, macb_mdio_read(macb, i)); +#endif + + for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) { + status = macb_mdio_read(macb, MII_BMSR); + if (status & BMSR_ANEGCOMPLETE) + break; + udelay(100); + } + + if (status & BMSR_ANEGCOMPLETE) + printf("%s: Autonegotiation complete\n", netdev->name); + else + printf("%s: Autonegotiation timed out (status=0x%04x)\n", + netdev->name, status); + + if (!(status & BMSR_LSTATUS)) { + for (i = 0; i < CFG_MACB_AUTONEG_TIMEOUT / 100; i++) { + udelay(100); + status = macb_mdio_read(macb, MII_BMSR); + if (status & BMSR_LSTATUS) + break; + } + } + + if (!(status & BMSR_LSTATUS)) { + printf("%s: link down (status: 0x%04x)\n", + netdev->name, status); + return 0; + } else { + lpa = macb_mdio_read(macb, MII_LPA); + media = mii_nway_result(lpa & adv); + speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) + ? 1 : 0); + duplex = (media & ADVERTISE_FULL) ? 1 : 0; + printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", + netdev->name, + speed ? "100" : "10", + duplex ? "full" : "half", + lpa); + + ncfgr = macb_readl(macb, NCFGR); + ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); + if (speed) + ncfgr |= MACB_BIT(SPD); + if (duplex) + ncfgr |= MACB_BIT(FD); + macb_writel(macb, NCFGR, ncfgr); + return 1; + } +} + +static int macb_init(struct eth_device *netdev, bd_t *bd) +{ + struct macb_device *macb = to_macb(netdev); + unsigned long paddr; + u32 hwaddr_bottom; + u16 hwaddr_top; + int i; + + /* + * macb_halt should have been called at some point before now, + * so we'll assume the controller is idle. + */ + + /* initialize DMA descriptors */ + paddr = macb->rx_buffer_dma; + for (i = 0; i < CFG_MACB_RX_RING_SIZE; i++) { + if (i == (CFG_MACB_RX_RING_SIZE - 1)) + paddr |= RXADDR_WRAP; + macb->rx_ring[i].addr = paddr; + macb->rx_ring[i].ctrl = 0; + paddr += 128; + } + for (i = 0; i < CFG_MACB_TX_RING_SIZE; i++) { + macb->tx_ring[i].addr = 0; + if (i == (CFG_MACB_TX_RING_SIZE - 1)) + macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; + else + macb->tx_ring[i].ctrl = TXBUF_USED; + } + macb->rx_tail = macb->tx_head = macb->tx_tail = 0; + + macb_writel(macb, RBQP, macb->rx_ring_dma); + macb_writel(macb, TBQP, macb->tx_ring_dma); + + /* set hardware address */ + hwaddr_bottom = cpu_to_le32(*((u32 *)netdev->enetaddr)); + macb_writel(macb, SA1B, hwaddr_bottom); + hwaddr_top = cpu_to_le16(*((u16 *)(netdev->enetaddr + 4))); + macb_writel(macb, SA1T, hwaddr_top); + + /* choose RMII or MII mode. This depends on the board */ +#ifdef CONFIG_RMII + macb_writel(macb, USRIO, 0); +#else + macb_writel(macb, USRIO, MACB_BIT(MII)); +#endif + + if (!macb_phy_init(macb)) + return 0; + + /* Enable TX and RX */ + macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE)); + + return 1; +} + +static void macb_halt(struct eth_device *netdev) +{ + struct macb_device *macb = to_macb(netdev); + u32 ncr, tsr; + + /* Halt the controller and wait for any ongoing transmission to end. */ + ncr = macb_readl(macb, NCR); + ncr |= MACB_BIT(THALT); + macb_writel(macb, NCR, ncr); + + do { + tsr = macb_readl(macb, TSR); + } while (tsr & MACB_BIT(TGO)); + + /* Disable TX and RX, and clear statistics */ + macb_writel(macb, NCR, MACB_BIT(CLRSTAT)); +} + +int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) +{ + struct macb_device *macb; + struct eth_device *netdev; + unsigned long macb_hz; + u32 ncfgr; + + macb = malloc(sizeof(struct macb_device)); + if (!macb) { + printf("Error: Failed to allocate memory for MACB%d\n", id); + return -1; + } + memset(macb, 0, sizeof(struct macb_device)); + + netdev = &macb->netdev; + + macb->rx_buffer = dma_alloc_coherent(CFG_MACB_RX_BUFFER_SIZE, + &macb->rx_buffer_dma); + macb->rx_ring = dma_alloc_coherent(CFG_MACB_RX_RING_SIZE + * sizeof(struct macb_dma_desc), + &macb->rx_ring_dma); + macb->tx_ring = dma_alloc_coherent(CFG_MACB_TX_RING_SIZE + * sizeof(struct macb_dma_desc), + &macb->tx_ring_dma); + + macb->regs = regs; + macb->phy_addr = phy_addr; + + sprintf(netdev->name, "macb%d", id); + netdev->init = macb_init; + netdev->halt = macb_halt; + netdev->send = macb_send; + netdev->recv = macb_recv; + + /* + * Do some basic initialization so that we at least can talk + * to the PHY + */ + macb_hz = get_macb_pclk_rate(id); + if (macb_hz < 20000000) + ncfgr = MACB_BF(CLK, MACB_CLK_DIV8); + else if (macb_hz < 40000000) + ncfgr = MACB_BF(CLK, MACB_CLK_DIV16); + else if (macb_hz < 80000000) + ncfgr = MACB_BF(CLK, MACB_CLK_DIV32); + else + ncfgr = MACB_BF(CLK, MACB_CLK_DIV64); + + macb_writel(macb, NCFGR, ncfgr); + + eth_register(netdev); + + return 0; +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_NET) */ + +#if (CONFIG_COMMANDS & CFG_CMD_MII) + +int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + int iflag; + + iflag = disable_interrupts(); + netctl = macb_readl(&macb, EMACB_NCR); + netctl |= MACB_BIT(MPE); + macb_writel(&macb, EMACB_NCR, netctl); + if (iflag) + enable_interrupts(); + + frame = (MACB_BF(SOF, 1) + | MACB_BF(RW, 2) + | MACB_BF(PHYA, addr) + | MACB_BF(REGA, reg) + | MACB_BF(CODE, 2)); + macb_writel(&macb, EMACB_MAN, frame); + + do { + netstat = macb_readl(&macb, EMACB_NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + frame = macb_readl(&macb, EMACB_MAN); + *value = MACB_BFEXT(DATA, frame); + + iflag = disable_interrupts(); + netctl = macb_readl(&macb, EMACB_NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(&macb, EMACB_NCR, netctl); + if (iflag) + enable_interrupts(); + + return 0; +} + +int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) +{ + unsigned long netctl; + unsigned long netstat; + unsigned long frame; + int iflag; + + iflag = disable_interrupts(); + netctl = macb_readl(&macb, EMACB_NCR); + netctl |= MACB_BIT(MPE); + macb_writel(&macb, EMACB_NCR, netctl); + if (iflag) + enable_interrupts(); + + frame = (MACB_BF(SOF, 1) + | MACB_BF(RW, 1) + | MACB_BF(PHYA, addr) + | MACB_BF(REGA, reg) + | MACB_BF(CODE, 2) + | MACB_BF(DATA, value)); + macb_writel(&macb, EMACB_MAN, frame); + + do { + netstat = macb_readl(&macb, EMACB_NSR); + } while (!(netstat & MACB_BIT(IDLE))); + + iflag = disable_interrupts(); + netctl = macb_readl(&macb, EMACB_NCR); + netctl &= ~MACB_BIT(MPE); + macb_writel(&macb, EMACB_NCR, netctl); + if (iflag) + enable_interrupts(); + + return 0; +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) */ + +#endif /* CONFIG_MACB */ diff --git a/drivers/macb.h b/drivers/macb.h new file mode 100644 index 0000000000..c778e4ee49 --- /dev/null +++ b/drivers/macb.h @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2005-2006 Atmel Corporation + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef __DRIVERS_MACB_H__ +#define __DRIVERS_MACB_H__ + +/* MACB register offsets */ +#define MACB_NCR 0x0000 +#define MACB_NCFGR 0x0004 +#define MACB_NSR 0x0008 +#define MACB_TSR 0x0014 +#define MACB_RBQP 0x0018 +#define MACB_TBQP 0x001c +#define MACB_RSR 0x0020 +#define MACB_ISR 0x0024 +#define MACB_IER 0x0028 +#define MACB_IDR 0x002c +#define MACB_IMR 0x0030 +#define MACB_MAN 0x0034 +#define MACB_PTR 0x0038 +#define MACB_PFR 0x003c +#define MACB_FTO 0x0040 +#define MACB_SCF 0x0044 +#define MACB_MCF 0x0048 +#define MACB_FRO 0x004c +#define MACB_FCSE 0x0050 +#define MACB_ALE 0x0054 +#define MACB_DTF 0x0058 +#define MACB_LCOL 0x005c +#define MACB_EXCOL 0x0060 +#define MACB_TUND 0x0064 +#define MACB_CSE 0x0068 +#define MACB_RRE 0x006c +#define MACB_ROVR 0x0070 +#define MACB_RSE 0x0074 +#define MACB_ELE 0x0078 +#define MACB_RJA 0x007c +#define MACB_USF 0x0080 +#define MACB_STE 0x0084 +#define MACB_RLE 0x0088 +#define MACB_TPF 0x008c +#define MACB_HRB 0x0090 +#define MACB_HRT 0x0094 +#define MACB_SA1B 0x0098 +#define MACB_SA1T 0x009c +#define MACB_SA2B 0x00a0 +#define MACB_SA2T 0x00a4 +#define MACB_SA3B 0x00a8 +#define MACB_SA3T 0x00ac +#define MACB_SA4B 0x00b0 +#define MACB_SA4T 0x00b4 +#define MACB_TID 0x00b8 +#define MACB_TPQ 0x00bc +#define MACB_USRIO 0x00c0 +#define MACB_WOL 0x00c4 + +/* Bitfields in NCR */ +#define MACB_LB_OFFSET 0 +#define MACB_LB_SIZE 1 +#define MACB_LLB_OFFSET 1 +#define MACB_LLB_SIZE 1 +#define MACB_RE_OFFSET 2 +#define MACB_RE_SIZE 1 +#define MACB_TE_OFFSET 3 +#define MACB_TE_SIZE 1 +#define MACB_MPE_OFFSET 4 +#define MACB_MPE_SIZE 1 +#define MACB_CLRSTAT_OFFSET 5 +#define MACB_CLRSTAT_SIZE 1 +#define MACB_INCSTAT_OFFSET 6 +#define MACB_INCSTAT_SIZE 1 +#define MACB_WESTAT_OFFSET 7 +#define MACB_WESTAT_SIZE 1 +#define MACB_BP_OFFSET 8 +#define MACB_BP_SIZE 1 +#define MACB_TSTART_OFFSET 9 +#define MACB_TSTART_SIZE 1 +#define MACB_THALT_OFFSET 10 +#define MACB_THALT_SIZE 1 +#define MACB_NCR_TPF_OFFSET 11 +#define MACB_NCR_TPF_SIZE 1 +#define MACB_TZQ_OFFSET 12 +#define MACB_TZQ_SIZE 1 + +/* Bitfields in NCFGR */ +#define MACB_SPD_OFFSET 0 +#define MACB_SPD_SIZE 1 +#define MACB_FD_OFFSET 1 +#define MACB_FD_SIZE 1 +#define MACB_BIT_RATE_OFFSET 2 +#define MACB_BIT_RATE_SIZE 1 +#define MACB_JFRAME_OFFSET 3 +#define MACB_JFRAME_SIZE 1 +#define MACB_CAF_OFFSET 4 +#define MACB_CAF_SIZE 1 +#define MACB_NBC_OFFSET 5 +#define MACB_NBC_SIZE 1 +#define MACB_NCFGR_MTI_OFFSET 6 +#define MACB_NCFGR_MTI_SIZE 1 +#define MACB_UNI_OFFSET 7 +#define MACB_UNI_SIZE 1 +#define MACB_BIG_OFFSET 8 +#define MACB_BIG_SIZE 1 +#define MACB_EAE_OFFSET 9 +#define MACB_EAE_SIZE 1 +#define MACB_CLK_OFFSET 10 +#define MACB_CLK_SIZE 2 +#define MACB_RTY_OFFSET 12 +#define MACB_RTY_SIZE 1 +#define MACB_PAE_OFFSET 13 +#define MACB_PAE_SIZE 1 +#define MACB_RBOF_OFFSET 14 +#define MACB_RBOF_SIZE 2 +#define MACB_RLCE_OFFSET 16 +#define MACB_RLCE_SIZE 1 +#define MACB_DRFCS_OFFSET 17 +#define MACB_DRFCS_SIZE 1 +#define MACB_EFRHD_OFFSET 18 +#define MACB_EFRHD_SIZE 1 +#define MACB_IRXFCS_OFFSET 19 +#define MACB_IRXFCS_SIZE 1 + +/* Bitfields in NSR */ +#define MACB_NSR_LINK_OFFSET 0 +#define MACB_NSR_LINK_SIZE 1 +#define MACB_MDIO_OFFSET 1 +#define MACB_MDIO_SIZE 1 +#define MACB_IDLE_OFFSET 2 +#define MACB_IDLE_SIZE 1 + +/* Bitfields in TSR */ +#define MACB_UBR_OFFSET 0 +#define MACB_UBR_SIZE 1 +#define MACB_COL_OFFSET 1 +#define MACB_COL_SIZE 1 +#define MACB_TSR_RLE_OFFSET 2 +#define MACB_TSR_RLE_SIZE 1 +#define MACB_TGO_OFFSET 3 +#define MACB_TGO_SIZE 1 +#define MACB_BEX_OFFSET 4 +#define MACB_BEX_SIZE 1 +#define MACB_COMP_OFFSET 5 +#define MACB_COMP_SIZE 1 +#define MACB_UND_OFFSET 6 +#define MACB_UND_SIZE 1 + +/* Bitfields in RSR */ +#define MACB_BNA_OFFSET 0 +#define MACB_BNA_SIZE 1 +#define MACB_REC_OFFSET 1 +#define MACB_REC_SIZE 1 +#define MACB_OVR_OFFSET 2 +#define MACB_OVR_SIZE 1 + +/* Bitfields in ISR/IER/IDR/IMR */ +#define MACB_MFD_OFFSET 0 +#define MACB_MFD_SIZE 1 +#define MACB_RCOMP_OFFSET 1 +#define MACB_RCOMP_SIZE 1 +#define MACB_RXUBR_OFFSET 2 +#define MACB_RXUBR_SIZE 1 +#define MACB_TXUBR_OFFSET 3 +#define MACB_TXUBR_SIZE 1 +#define MACB_ISR_TUND_OFFSET 4 +#define MACB_ISR_TUND_SIZE 1 +#define MACB_ISR_RLE_OFFSET 5 +#define MACB_ISR_RLE_SIZE 1 +#define MACB_TXERR_OFFSET 6 +#define MACB_TXERR_SIZE 1 +#define MACB_TCOMP_OFFSET 7 +#define MACB_TCOMP_SIZE 1 +#define MACB_ISR_LINK_OFFSET 9 +#define MACB_ISR_LINK_SIZE 1 +#define MACB_ISR_ROVR_OFFSET 10 +#define MACB_ISR_ROVR_SIZE 1 +#define MACB_HRESP_OFFSET 11 +#define MACB_HRESP_SIZE 1 +#define MACB_PFR_OFFSET 12 +#define MACB_PFR_SIZE 1 +#define MACB_PTZ_OFFSET 13 +#define MACB_PTZ_SIZE 1 + +/* Bitfields in MAN */ +#define MACB_DATA_OFFSET 0 +#define MACB_DATA_SIZE 16 +#define MACB_CODE_OFFSET 16 +#define MACB_CODE_SIZE 2 +#define MACB_REGA_OFFSET 18 +#define MACB_REGA_SIZE 5 +#define MACB_PHYA_OFFSET 23 +#define MACB_PHYA_SIZE 5 +#define MACB_RW_OFFSET 28 +#define MACB_RW_SIZE 2 +#define MACB_SOF_OFFSET 30 +#define MACB_SOF_SIZE 2 + +/* Bitfields in USRIO */ +#define MACB_MII_OFFSET 0 +#define MACB_MII_SIZE 1 +#define MACB_EAM_OFFSET 1 +#define MACB_EAM_SIZE 1 +#define MACB_TX_PAUSE_OFFSET 2 +#define MACB_TX_PAUSE_SIZE 1 +#define MACB_TX_PAUSE_ZERO_OFFSET 3 +#define MACB_TX_PAUSE_ZERO_SIZE 1 + +/* Bitfields in WOL */ +#define MACB_IP_OFFSET 0 +#define MACB_IP_SIZE 16 +#define MACB_MAG_OFFSET 16 +#define MACB_MAG_SIZE 1 +#define MACB_ARP_OFFSET 17 +#define MACB_ARP_SIZE 1 +#define MACB_SA1_OFFSET 18 +#define MACB_SA1_SIZE 1 +#define MACB_WOL_MTI_OFFSET 19 +#define MACB_WOL_MTI_SIZE 1 + +/* Constants for CLK */ +#define MACB_CLK_DIV8 0 +#define MACB_CLK_DIV16 1 +#define MACB_CLK_DIV32 2 +#define MACB_CLK_DIV64 3 + +/* Constants for MAN register */ +#define MACB_MAN_SOF 1 +#define MACB_MAN_WRITE 1 +#define MACB_MAN_READ 2 +#define MACB_MAN_CODE 2 + +/* Bit manipulation macros */ +#define MACB_BIT(name) \ + (1 << MACB_##name##_OFFSET) +#define MACB_BF(name,value) \ + (((value) & ((1 << MACB_##name##_SIZE) - 1)) \ + << MACB_##name##_OFFSET) +#define MACB_BFEXT(name,value)\ + (((value) >> MACB_##name##_OFFSET) \ + & ((1 << MACB_##name##_SIZE) - 1)) +#define MACB_BFINS(name,value,old) \ + (((old) & ~(((1 << MACB_##name##_SIZE) - 1) \ + << MACB_##name##_OFFSET)) \ + | MACB_BF(name,value)) + +/* Register access macros */ +#define macb_readl(port,reg) \ + readl((port)->regs + MACB_##reg) +#define macb_writel(port,reg,value) \ + writel((value), (port)->regs + MACB_##reg) + +#endif /* __DRIVERS_MACB_H__ */ -- cgit v1.2.1 From 2a26ec4732efd7a308d0bbc97714c1d75ef1173b Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Wed, 18 Apr 2007 17:07:26 +0200 Subject: Cleanup, update CHANGELOG Sigend-off-by: Wolfgang Denk --- drivers/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/Makefile b/drivers/Makefile index df9fbf2aae..d68cba682b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -35,8 +35,8 @@ COBJS = 3c589.o 5701rls.o ali512x.o atmel_usart.o \ lan91c96.o macb.o \ natsemi.o ne2000.o netarm_eth.o netconsole.o \ ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \ - omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o tsi108_pci.o\ - tsi108_i2c.o pcnet.o plb2800_eth.o \ + omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o \ + pcnet.o plb2800_eth.o \ ps2ser.o ps2mult.o pc_keyb.o \ rtl8019.o rtl8139.o rtl8169.o \ s3c4510b_eth.o s3c4510b_uart.o \ @@ -45,7 +45,8 @@ COBJS = 3c589.o 5701rls.o ali512x.o atmel_usart.o \ serial_pl010.o serial_pl011.o serial_xuartlite.o \ sl811_usb.o sm501.o smc91111.o smiLynxEM.o \ status_led.o sym53c8xx.o systemace.o ahci.o \ - ti_pci1410a.o tigon3.o tsec.o tsi108_eth.o\ + ti_pci1410a.o tigon3.o tsec.o \ + tsi108_eth.o tsi108_i2c.o tsi108_pci.o \ usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o \ videomodes.o w83c553f.o \ ks8695eth.o \ -- cgit v1.2.1 From 81f481ca708ed6a56bf9c410e3191dbad581c565 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Mon, 23 Apr 2007 02:24:28 -0500 Subject: Enable 8544 support * Add support to the Makefile * Add 8544 configuration support to the tsec driver * Add 8544 SVR numbers to processor.h Signed-off-by: Ed Swarthout Signed-off-by: Jon Loeliger --- drivers/tsec.c | 6 +++++- drivers/tsec.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tsec.c b/drivers/tsec.c index 3f11eb03b4..ed35f227c1 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -5,7 +5,7 @@ * terms of the GNU Public License, Version 2, incorporated * herein by reference. * - * Copyright 2004 Freescale Semiconductor. + * Copyright 2004, 2007 Freescale Semiconductor, Inc. * (C) Copyright 2003, Motorola, Inc. * author Andy Fleming * @@ -66,7 +66,11 @@ struct tsec_info_struct { */ static struct tsec_info_struct tsec_info[] = { #if defined(CONFIG_MPC85XX_TSEC1) || defined(CONFIG_MPC83XX_TSEC1) +#if defined(CONFIG_MPC8544DS) + {TSEC1_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC1_PHYIDX}, +#else {TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX}, +#endif #elif defined(CONFIG_MPC86XX_TSEC1) {TSEC1_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC1_PHYIDX}, #else diff --git a/drivers/tsec.h b/drivers/tsec.h index 422bc66922..7bf3dee2b6 100644 --- a/drivers/tsec.h +++ b/drivers/tsec.h @@ -7,7 +7,7 @@ * terms of the GNU Public License, Version 2, incorporated * herein by reference. * - * Copyright 2004 Freescale Semiconductor. + * Copyright 2004, 2007 Freescale Semiconductor, Inc. * (C) Copyright 2003, Motorola, Inc. * maintained by Xianghua Xiao (x.xiao@motorola.com) * author Andy Fleming @@ -65,6 +65,7 @@ #define ECNTRL_INIT_SETTINGS 0x00001000 #define ECNTRL_TBI_MODE 0x00000020 #define ECNTRL_R100 0x00000008 +#define ECNTRL_SGMII_MODE 0x00000002 #define miim_end -2 #define miim_read -1 -- cgit v1.2.1 From af1c2b84bf27c8565baddc82d1abb93700d10e2e Mon Sep 17 00:00:00 2001 From: David Updegraff Date: Fri, 20 Apr 2007 14:34:48 -0500 Subject: Add support for treating unknown PHYs as generic PHYs. When bringing up u-boot on new boards, PHY support sometimes gets neglected. Most PHYs don't really need any special support, though. By adding a generic entry that always matches if nothing else does, we can provide support for "unsupported" PHYs for the tsec. The generic PHY driver supports most PHYs, including gigabit. Signed-off-by: David Updegraff Signed-off-by: Andy Fleming --- drivers/tsec.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) (limited to 'drivers') diff --git a/drivers/tsec.c b/drivers/tsec.c index ed35f227c1..25566a7338 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -385,6 +385,76 @@ uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) return 0; } +/* Generic function which updates the speed and duplex. If + * autonegotiation is enabled, it uses the AND of the link + * partner's advertised capabilities and our advertised + * capabilities. If autonegotiation is disabled, we use the + * appropriate bits in the control register. + * + * Stolen from Linux's mii.c and phy_device.c + */ +uint mii_parse_link(uint mii_reg, struct tsec_private *priv) +{ + /* We're using autonegotiation */ + if (mii_reg & PHY_BMSR_AUTN_ABLE) { + uint lpa = 0; + uint gblpa = 0; + + /* Check for gigabit capability */ + if (mii_reg & PHY_BMSR_EXT) { + /* We want a list of states supported by + * both PHYs in the link + */ + gblpa = read_phy_reg(priv, PHY_1000BTSR); + gblpa &= read_phy_reg(priv, PHY_1000BTCR) << 2; + } + + /* Set the baseline so we only have to set them + * if they're different + */ + priv->speed = 10; + priv->duplexity = 0; + + /* Check the gigabit fields */ + if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { + priv->speed = 1000; + + if (gblpa & PHY_1000BTSR_1000FD) + priv->duplexity = 1; + + /* We're done! */ + return 0; + } + + lpa = read_phy_reg(priv, PHY_ANAR); + lpa &= read_phy_reg(priv, PHY_ANLPAR); + + if (lpa & (PHY_ANLPAR_TXFD | PHY_ANLPAR_TX)) { + priv->speed = 100; + + if (lpa & PHY_ANLPAR_TXFD) + priv->duplexity = 1; + + } else if (lpa & PHY_ANLPAR_10FD) + priv->duplexity = 1; + } else { + uint bmcr = read_phy_reg(priv, PHY_BMCR); + + priv->speed = 10; + priv->duplexity = 0; + + if (bmcr & PHY_BMCR_DPLX) + priv->duplexity = 1; + + if (bmcr & PHY_BMCR_1000_MBPS) + priv->speed = 1000; + else if (bmcr & PHY_BMCR_100_MBPS) + priv->speed = 100; + } + + return 0; +} + /* * Parse the BCM54xx status register for speed and duplex information. * The linux sungem_phy has this information, but in a table format. @@ -722,6 +792,7 @@ static void startup_tsec(struct eth_device *dev) /* Start up the PHY */ if(priv->phyinfo) phy_run_commands(priv, priv->phyinfo->startup); + adjust_link(dev); /* Enable Transmit and Receive */ @@ -1092,6 +1163,27 @@ struct phy_info phy_info_dm9161 = { {miim_end,} }, }; +/* a generic flavor. */ +struct phy_info phy_info_generic = { + 0, + "Unknown/Generic PHY", + 32, + (struct phy_cmd[]) { /* config */ + {PHY_BMCR, PHY_BMCR_RESET, NULL}, + {PHY_BMCR, PHY_BMCR_AUTON|PHY_BMCR_RST_NEG, NULL}, + {miim_end,} + }, + (struct phy_cmd[]) { /* startup */ + {PHY_BMSR, miim_read, NULL}, + {PHY_BMSR, miim_read, &mii_parse_sr}, + {PHY_BMSR, miim_read, &mii_parse_link}, + {miim_end,} + }, + (struct phy_cmd[]) { /* shutdown */ + {miim_end,} + } +}; + uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv) { @@ -1207,6 +1299,7 @@ struct phy_info *phy_info[] = { &phy_info_lxt971, &phy_info_VSC8244, &phy_info_dp83865, + &phy_info_generic, NULL }; -- cgit v1.2.1 From a79886590593ba1d667c840caa4940c61639f18f Mon Sep 17 00:00:00 2001 From: Thomas Knobloch Date: Sat, 5 May 2007 07:04:42 +0200 Subject: NAND: Wrong calculation of page number in nand_block_bad() In case that there is no memory based bad block table available the function nand_block_checkbad() in drivers/mtd/nand/nand_base.c will call nand_block_bad() directly. When parameter 'getchip' is set to zero, nand_block_bad() will not right shift the offset to calculate the correct page number. Signed-off-by: Thomas Knobloch Signed-off-by: Stefan Roese --- drivers/nand/nand_base.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/nand/nand_base.c b/drivers/nand/nand_base.c index 8495829900..c6fee18222 100644 --- a/drivers/nand/nand_base.c +++ b/drivers/nand/nand_base.c @@ -427,8 +427,9 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) struct nand_chip *this = mtd->priv; u16 bad; + page = (int)(ofs >> this->page_shift) & this->pagemask; + if (getchip) { - page = (int)(ofs >> this->page_shift); chipnr = (int)(ofs >> this->chip_shift); /* Grab the lock and see if the device is available */ @@ -436,18 +437,17 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) /* Select the NAND device */ this->select_chip(mtd, chipnr); - } else - page = (int) ofs; + } if (this->options & NAND_BUSWIDTH_16) { - this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); + this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page); bad = cpu_to_le16(this->read_word(mtd)); if (this->badblockpos & 0x1) bad >>= 1; if ((bad & 0xFF) != 0xff) res = 1; } else { - this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask); + this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page); if (this->read_byte(mtd) != 0xff) res = 1; } -- cgit v1.2.1 From 2f15278c2eb911c668b4fe562130b78cf554d139 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 5 May 2007 18:23:11 +0200 Subject: Coding stylke cleanup; update CHANGELOG. Signed-off-by: Wolfgang Denk --- drivers/tsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tsec.c b/drivers/tsec.c index 25566a7338..b4187739cb 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -67,7 +67,7 @@ struct tsec_info_struct { static struct tsec_info_struct tsec_info[] = { #if defined(CONFIG_MPC85XX_TSEC1) || defined(CONFIG_MPC83XX_TSEC1) #if defined(CONFIG_MPC8544DS) - {TSEC1_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC1_PHYIDX}, + {TSEC1_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC1_PHYIDX}, #else {TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX}, #endif -- cgit v1.2.1 From ebd0a0ae05a44769c4e27458ad4e9f3438250443 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 23 Apr 2007 13:54:24 +0200 Subject: [patch] use unsigned char in smc91111 driver for mac the v_mac variable in the smc91111 driver is declared as a signed char ... this causes problems when one of the bytes in the MAC is "signed" like 0xE0 because when it gets printed out, you get a display like: 0xFFFFFFE0 and that's no good Signed-off-by: Mike Frysinger --- drivers/smc91111.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/smc91111.c b/drivers/smc91111.c index f91e4b9843..8061f12979 100644 --- a/drivers/smc91111.c +++ b/drivers/smc91111.c @@ -1538,9 +1538,9 @@ int eth_send(volatile void *packet, int length) { int smc_get_ethaddr (bd_t * bd) { int env_size, rom_valid, env_present = 0, reg; - char *s = NULL, *e, *v_mac, es[] = "11:22:33:44:55:66"; + char *s = NULL, *e, es[] = "11:22:33:44:55:66"; char s_env_mac[64]; - uchar v_env_mac[6], v_rom_mac[6]; + uchar v_env_mac[6], v_rom_mac[6], *v_mac; env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac)); if ((env_size > 0) && (env_size < sizeof (es))) { /* exit if env is bad */ @@ -1563,7 +1563,7 @@ int smc_get_ethaddr (bd_t * bd) if (!env_present) { /* if NO env */ if (rom_valid) { /* but ROM is valid */ - v_mac = (char *)v_rom_mac; + v_mac = v_rom_mac; sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X", v_mac[0], v_mac[1], v_mac[2], v_mac[3], v_mac[4], v_mac[5]); @@ -1573,7 +1573,7 @@ int smc_get_ethaddr (bd_t * bd) return (-1); } } else { /* good env, don't care ROM */ - v_mac = (char *)v_env_mac; /* always use a good env over a ROM */ + v_mac = v_env_mac; /* always use a good env over a ROM */ } if (env_present && rom_valid) { /* if both env and ROM are good */ -- cgit v1.2.1 From b7598a43f2b421a713d8135e98a42c37d9eb9df0 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 23 Apr 2007 15:30:39 +0200 Subject: [PATCH] Avoid assigning PCI resources from zero address If a PCI IDE card happens to get a zero address assigned to it, the Linux IDE core complains and IDE drivers fails to work. Also, assigning zero to a BAR was illegal according to PCI 2.1 (the later revisions seem to have excluded the sentence about "0" being considered an invalid address) -- so, use a reasonable starting value of 0x1000 (that's what the most Linux archs are using). Alternatively, one might have fixed the calls to pci_set_region() individually (some code even seems to have taken care of this issue) but that would have been a lot more work. :-) Signed-off-by: Sergei Shtylyov Acked-by: Stefan Roese --- drivers/pci_auto.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c index 969167555e..f170c2db89 100644 --- a/drivers/pci_auto.c +++ b/drivers/pci_auto.c @@ -34,7 +34,12 @@ void pciauto_region_init(struct pci_region* res) { - res->bus_lower = res->bus_start; + /* + * Avoid allocating PCI resources from address 0 -- this is illegal + * according to PCI 2.1 and moreover, this is known to cause Linux IDE + * drivers to fail. Use a reasonable starting value of 0x1000 instead. + */ + res->bus_lower = res->bus_start ? res->bus_start : 0x1000; } void pciauto_region_align(struct pci_region *res, unsigned long size) -- cgit v1.2.1