* clock/clock-config.c: Fixes to pass psnsext01.
	* startup/bspstart.c: Workaround for GCC 4.6 bug.
	* include/smsc9218i.h, network/smsc9218i.c, Makefile.am: Changes
	throughout.
This commit is contained in:
Sebastian Huber
2011-06-07 09:14:06 +00:00
parent 1343dfa314
commit a44752776d
6 changed files with 274 additions and 259 deletions

View File

@@ -1,3 +1,10 @@
2011-06-07 Sebastian Huber <sebastian.huber@embedded-brains.de>
* clock/clock-config.c: Fixes to pass psnsext01.
* startup/bspstart.c: Workaround for GCC 4.6 bug.
* include/smsc9218i.h, network/smsc9218i.c, Makefile.am: Changes
throughout.
2011-02-11 Ralf Corsépius <ralf.corsepius@rtems.org> 2011-02-11 Ralf Corsépius <ralf.corsepius@rtems.org>
* network/smsc9218i.c, startup/bspstart.c: * network/smsc9218i.c, startup/bspstart.c:

View File

@@ -70,10 +70,7 @@ libbsp_a_SOURCES += i2c/i2c_init.c \
# Network # Network
if HAS_NETWORKING if HAS_NETWORKING
noinst_PROGRAMS += network.rel libbsp_a_SOURCES += network/smsc9218i.c
network_rel_SOURCES = network/smsc9218i.c
network_rel_CPPFLAGS = $(AM_CPPFLAGS) -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ -D__BSD_VISIBLE
network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif endif
# BSP library # BSP library
@@ -91,9 +88,6 @@ libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel \
../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \ ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \ ../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \
../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/timer.rel ../../../libcpu/@RTEMS_CPU@/@RTEMS_CPU_MODEL@/timer.rel
if HAS_NETWORKING
libbsp_a_LIBADD += network.rel
endif
include $(srcdir)/preinstall.am include $(srcdir)/preinstall.am
include $(top_srcdir)/../../../../automake/local.am include $(top_srcdir)/../../../../automake/local.am

View File

@@ -43,6 +43,8 @@ rtems_isr Clock_isr( rtems_vector_number vector);
EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.R = csr.R; \ EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.R = csr.R; \
} while (0) } while (0)
static uint64_t mpc55xx_clock_factor;
static void mpc55xx_clock_handler_install( rtems_isr_entry isr, static void mpc55xx_clock_handler_install( rtems_isr_entry isr,
rtems_isr_entry *old_isr) rtems_isr_entry *old_isr)
{ {
@@ -69,6 +71,8 @@ static void mpc55xx_clock_initialize( void)
uint64_t interval = ((uint64_t) bsp_clock_speed uint64_t interval = ((uint64_t) bsp_clock_speed
* (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000; * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000;
mpc55xx_clock_factor = (1000000000ULL << 32) / bsp_clock_speed;
/* Apply prescaler */ /* Apply prescaler */
if (prescaler > 0) { if (prescaler > 0) {
interval /= (uint64_t) prescaler; interval /= (uint64_t) prescaler;
@@ -131,11 +135,16 @@ static void mpc55xx_clock_cleanup( void)
static uint32_t mpc55xx_clock_nanoseconds_since_last_tick( void) static uint32_t mpc55xx_clock_nanoseconds_since_last_tick( void)
{ {
uint64_t clicks = EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CCNTR.R; volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
uint64_t clock = bsp_clock_speed; uint64_t c = regs->CCNTR.R;
uint64_t ns = (clicks * 1000000000) / clock; union EMIOS_CSR_tag csr = { .R = regs->CSR.R };
uint64_t k = mpc55xx_clock_factor;
return (uint32_t) ns; if (csr.B.FLAG != 0) {
c = regs->CCNTR.R + regs->CADR.R + 1;
}
return (uint32_t) ((c * k) >> 32);
} }
#define Clock_driver_support_initialize_hardware() mpc55xx_clock_initialize() #define Clock_driver_support_initialize_hardware() mpc55xx_clock_initialize()

View File

@@ -189,62 +189,32 @@ volatile smsc9218i_registers *const smsc9218i = (volatile smsc9218i_registers *)
/** @} */ /** @} */
/** /**
* @name Interrupt Status * @name Interrupt Enable and Status
* @{ * @{
*/ */
#define SMSC9218I_INT_STS_SW SMSC9218I_FLAG(31) #define SMSC9218I_INT_SW SMSC9218I_FLAG(31)
#define SMSC9218I_INT_STS_TXSTOP SMSC9218I_FLAG(25) #define SMSC9218I_INT_TXSTOP SMSC9218I_FLAG(25)
#define SMSC9218I_INT_STS_RXSTOP SMSC9218I_FLAG(24) #define SMSC9218I_INT_RXSTOP SMSC9218I_FLAG(24)
#define SMSC9218I_INT_STS_RXDFH SMSC9218I_FLAG(23) #define SMSC9218I_INT_RXDFH SMSC9218I_FLAG(23)
#define SMSC9218I_INT_STS_TIOC SMSC9218I_FLAG(21) #define SMSC9218I_INT_TIOC SMSC9218I_FLAG(21)
#define SMSC9218I_INT_STS_RXD SMSC9218I_FLAG(20) #define SMSC9218I_INT_RXD SMSC9218I_FLAG(20)
#define SMSC9218I_INT_STS_GPT SMSC9218I_FLAG(19) #define SMSC9218I_INT_GPT SMSC9218I_FLAG(19)
#define SMSC9218I_INT_STS_PHY SMSC9218I_FLAG(18) #define SMSC9218I_INT_PHY SMSC9218I_FLAG(18)
#define SMSC9218I_INT_STS_PME SMSC9218I_FLAG(17) #define SMSC9218I_INT_PME SMSC9218I_FLAG(17)
#define SMSC9218I_INT_STS_TXSO SMSC9218I_FLAG(16) #define SMSC9218I_INT_TXSO SMSC9218I_FLAG(16)
#define SMSC9218I_INT_STS_RWT SMSC9218I_FLAG(15) #define SMSC9218I_INT_RWT SMSC9218I_FLAG(15)
#define SMSC9218I_INT_STS_RXE SMSC9218I_FLAG(14) #define SMSC9218I_INT_RXE SMSC9218I_FLAG(14)
#define SMSC9218I_INT_STS_TXE SMSC9218I_FLAG(13) #define SMSC9218I_INT_TXE SMSC9218I_FLAG(13)
#define SMSC9218I_INT_STS_TDFO SMSC9218I_FLAG(10) #define SMSC9218I_INT_TDFO SMSC9218I_FLAG(10)
#define SMSC9218I_INT_STS_TDFA SMSC9218I_FLAG(9) #define SMSC9218I_INT_TDFA SMSC9218I_FLAG(9)
#define SMSC9218I_INT_STS_TSFF SMSC9218I_FLAG(8) #define SMSC9218I_INT_TSFF SMSC9218I_FLAG(8)
#define SMSC9218I_INT_STS_TSFL SMSC9218I_FLAG(7) #define SMSC9218I_INT_TSFL SMSC9218I_FLAG(7)
#define SMSC9218I_INT_STS_RSFF SMSC9218I_FLAG(4) #define SMSC9218I_INT_RSFF SMSC9218I_FLAG(4)
#define SMSC9218I_INT_STS_RSFL SMSC9218I_FLAG(3) #define SMSC9218I_INT_RSFL SMSC9218I_FLAG(3)
#define SMSC9218I_INT_STS_GPIO2 SMSC9218I_FLAG(2) #define SMSC9218I_INT_GPIO2 SMSC9218I_FLAG(2)
#define SMSC9218I_INT_STS_GPIO1 SMSC9218I_FLAG(1) #define SMSC9218I_INT_GPIO1 SMSC9218I_FLAG(1)
#define SMSC9218I_INT_STS_GPIO0 SMSC9218I_FLAG(0) #define SMSC9218I_INT_GPIO0 SMSC9218I_FLAG(0)
/** @} */
/**
* @name Interrupt Enable
* @{
*/
#define SMSC9218I_INT_EN_SW SMSC9218I_FLAG(31)
#define SMSC9218I_INT_EN_TXSTOP SMSC9218I_FLAG(25)
#define SMSC9218I_INT_EN_RXSTOP SMSC9218I_FLAG(24)
#define SMSC9218I_INT_EN_RXDFH SMSC9218I_FLAG(23)
#define SMSC9218I_INT_EN_TIOC SMSC9218I_FLAG(21)
#define SMSC9218I_INT_EN_RXD SMSC9218I_FLAG(20)
#define SMSC9218I_INT_EN_GPT SMSC9218I_FLAG(19)
#define SMSC9218I_INT_EN_PHY SMSC9218I_FLAG(18)
#define SMSC9218I_INT_EN_PME SMSC9218I_FLAG(17)
#define SMSC9218I_INT_EN_TXSO SMSC9218I_FLAG(16)
#define SMSC9218I_INT_EN_RWT SMSC9218I_FLAG(15)
#define SMSC9218I_INT_EN_RXE SMSC9218I_FLAG(14)
#define SMSC9218I_INT_EN_TXE SMSC9218I_FLAG(13)
#define SMSC9218I_INT_EN_TDFO SMSC9218I_FLAG(10)
#define SMSC9218I_INT_EN_TDFA SMSC9218I_FLAG(9)
#define SMSC9218I_INT_EN_TSFF SMSC9218I_FLAG(8)
#define SMSC9218I_INT_EN_TSFL SMSC9218I_FLAG(7)
#define SMSC9218I_INT_EN_RSFF SMSC9218I_FLAG(4)
#define SMSC9218I_INT_EN_RSFL SMSC9218I_FLAG(3)
#define SMSC9218I_INT_EN_GPIO2 SMSC9218I_FLAG(2)
#define SMSC9218I_INT_EN_GPIO1 SMSC9218I_FLAG(1)
#define SMSC9218I_INT_EN_GPIO0 SMSC9218I_FLAG(0)
/** @} */ /** @} */
@@ -438,6 +408,15 @@ volatile smsc9218i_registers *const smsc9218i = (volatile smsc9218i_registers *)
/** @} */ /** @} */
/**
* @name EEPROM Command Register
* @{
*/
#define SMSC9218I_E2P_CMD_EPC_BUSY SMSC9218I_FLAG(31)
/** @} */
/** /**
* @name MAC Control and Status Synchronizer Command * @name MAC Control and Status Synchronizer Command
* @{ * @{
@@ -598,52 +577,12 @@ volatile smsc9218i_registers *const smsc9218i = (volatile smsc9218i_registers *)
/** @} */ /** @} */
/**
* @name Basic Control
* @{
*/
#define SMSC9218I_PHY_BCR 0x00000000U
#define SMSC9218I_PHY_BCR_RST 0x00008000U
#define SMSC9218I_PHY_BCR_LOOPBK 0x00004000U
#define SMSC9218I_PHY_BCR_SS 0x00002000U
#define SMSC9218I_PHY_BCR_ANE 0x00001000U
#define SMSC9218I_PHY_BCR_PWRDN 0x00000800U
#define SMSC9218I_PHY_BCR_RSTAN 0x00000200U
#define SMSC9218I_PHY_BCR_FDPLX 0x00000100U
#define SMSC9218I_PHY_BCR_COLLTST 0x00000080U
/** @} */
/**
* @name Basic Status
* @{
*/
#define SMSC9218I_PHY_BSR 0x00000001U
#define SMSC9218I_PHY_BSR_100_T4_ABLE 0x00008000U
#define SMSC9218I_PHY_BSR_100_TX_FDPLX 0x00004000U
#define SMSC9218I_PHY_BSR_100_TX_HDPLX 0x00002000U
#define SMSC9218I_PHY_BSR_10_FDPLX 0x00001000U
#define SMSC9218I_PHY_BSR_10_HDPLX 0x00000800U
#define SMSC9218I_PHY_BSR_ANC 0x00000020U
#define SMSC9218I_PHY_BSR_REM_FAULT 0x00000010U
#define SMSC9218I_PHY_BSR_AN_ABLE 0x00000008U
#define SMSC9218I_PHY_BSR_LINK_STATUS 0x00000004U
#define SMSC9218I_PHY_BSR_JAB_DET 0x00000002U
#define SMSC9218I_PHY_BSR_EXT_CAP 0x00000001U
/** @} */
/** /**
* @name PHY Identifier 1 * @name PHY Identifier 1
* @{ * @{
*/ */
#define SMSC9218I_PHY_ID1 0x00000002U #define SMSC9218I_PHY_ID1_LAN9118 0x7
#define SMSC9218I_PHY_ID1_MASK 0x0000ffffU
#define SMSC9218I_PHY_ID1_LAN9118 0x00000007U
#define SMSC9218I_PHY_ID1_LAN9218 (PHY_ID1_LAN9118)
/** @} */ /** @} */
@@ -652,65 +591,7 @@ volatile smsc9218i_registers *const smsc9218i = (volatile smsc9218i_registers *)
* @{ * @{
*/ */
#define SMSC9218I_PHY_ID2 0x00000003U #define SMSC9218I_PHY_ID2_LAN9218 0xc0c3
#define SMSC9218I_PHY_ID2_MASK 0x0000ffffU
#define SMSC9218I_PHY_ID2_MODEL_MASK 0x000003f0U
#define SMSC9218I_PHY_ID2_REV_MASK 0x0000000fU
#define SMSC9218I_PHY_ID2_LAN9118 0x0000c0d1U
#define SMSC9218I_PHY_ID2_LAN9218 0x0000c0c3U
/** @} */
/**
* @name Auto-negotiation Advertisment
* @{
*/
#define SMSC9218I_PHY_ANAR 0x00000004U
#define SMSC9218I_PHY_ANAR_NXTPG_CAP 0x00008000U
#define SMSC9218I_PHY_ANAR_REM_FAULT 0x00002000U
#define SMSC9218I_PHY_ANAR_PAUSE_OP_MASK 0x00000c00U
#define SMSC9218I_PHY_ANAR_PAUSE_OP_NONE 0x00000000U
#define SMSC9218I_PHY_ANAR_PAUSE_OP_ASLP 0x00000400U
#define SMSC9218I_PHY_ANAR_PAUSE_OP_SLP 0x00000800U
#define SMSC9218I_PHY_ANAR_PAUSE_OP_BOTH 0x00000c00U
#define SMSC9218I_PHY_ANAR_100_T4_ABLE 0x00000200U
#define SMSC9218I_PHY_ANAR_100_TX_FDPLX 0x00000100U
#define SMSC9218I_PHY_ANAR_100_TX_ABLE 0x00000080U
#define SMSC9218I_PHY_ANAR_10_FDPLX 0x00000040U
#define SMSC9218I_PHY_ANAR_10_ABLE 0x00000020U
/** @} */
/**
* @name Auto-negotiation Link Partner Ability
* @{
*/
#define SMSC9218I_PHY_ANLPAR 0x00000005U
#define SMSC9218I_PHY_ANLPAR_NXTPG_CAP 0x00008000U
#define SMSC9218I_PHY_ANLPAR_ACK 0x00004000U
#define SMSC9218I_PHY_ANLPAR_REM_FAULT 0x00002000U
#define SMSC9218I_PHY_ANLPAR_PAUSE_CAP 0x00000400U
#define SMSC9218I_PHY_ANLPAR_100_T4_ABLE 0x00000200U
#define SMSC9218I_PHY_ANLPAR_100_TX_FDPLX 0x00000100U
#define SMSC9218I_PHY_ANLPAR_100_TX_ABLE 0x00000080U
#define SMSC9218I_PHY_ANLPAR_10_FDPLX 0x00000040U
#define SMSC9218I_PHY_ANLPAR_10_ABLE 0x00000020U
/** @} */
/**
* @name Auto-negotiation Expansion
* @{
*/
#define SMSC9218I_PHY_ANEXPR 0x00000006U
#define SMSC9218I_PHY_ANEXPR_PARDET_FAULT 0x00000010U
#define SMSC9218I_PHY_ANEXPR_LP_NXTPG_CAP 0x00000008U
#define SMSC9218I_PHY_ANEXPR_NXTPG_CAP 0x00000004U
#define SMSC9218I_PHY_ANEXPR_NEWPG_REC 0x00000002U
#define SMSC9218I_PHY_ANEXPR_LP_AN_ABLE 0x00000001U
/** @} */ /** @} */

View File

@@ -7,18 +7,24 @@
*/ */
/* /*
* Copyright (c) 2009 * Copyright (c) 2009-2011 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH * embedded brains GmbH
* Obere Lagerstr. 30 * Obere Lagerstr. 30
* D-82178 Puchheim * 82178 Puchheim
* Germany * Germany
* rtems@embedded-brains.de * <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be * The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE. * http://www.rtems.com/license/LICENSE.
*
* $Id$
*/ */
#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1
#define __BSD_VISIBLE 1
#include <mpc55xx/regs.h> #include <mpc55xx/regs.h>
#include <errno.h> #include <errno.h>
@@ -76,7 +82,7 @@
/* Adjust by two bytes for proper IP header alignment */ /* Adjust by two bytes for proper IP header alignment */
#define SMSC9218I_RX_DATA_OFFSET 2 #define SMSC9218I_RX_DATA_OFFSET 2
#define SMSC9218I_TX_JOBS 16U #define SMSC9218I_TX_JOBS 128U
#define SMSC9218I_TX_JOBS_MAX (SMSC9218I_TX_JOBS - 1U) #define SMSC9218I_TX_JOBS_MAX (SMSC9218I_TX_JOBS - 1U)
@@ -88,13 +94,13 @@
#define SMSC9218I_IRQ_CFG_GLOBAL_DISABLE SMSC9218I_IRQ_CFG_IRQ_TYPE #define SMSC9218I_IRQ_CFG_GLOBAL_DISABLE SMSC9218I_IRQ_CFG_IRQ_TYPE
#define SMSC9218I_EDMA_RX_CHANNEL 48 #define SMSC9218I_EDMA_RX_CHANNEL 49
#define SMSC9218I_EDMA_RX_TCD_CDF 0x10004 #define SMSC9218I_EDMA_RX_TCD_CDF 0x10004
#define SMSC9218I_EDMA_RX_TCD_BMF 0x10003 #define SMSC9218I_EDMA_RX_TCD_BMF 0x10003
#define SMSC9218I_EDMA_TX_CHANNEL 49 #define SMSC9218I_EDMA_TX_CHANNEL 48
#define SMSC9218I_EDMA_TX_TCD_BMF_LINK 0x10011 #define SMSC9218I_EDMA_TX_TCD_BMF_LINK 0x10011
@@ -102,6 +108,12 @@
#define SMSC9218I_EDMA_TX_TCD_BMF_CLEAR 0x10000 #define SMSC9218I_EDMA_TX_TCD_BMF_CLEAR 0x10000
#define SMSC9218I_ERROR_INTERRUPTS \
(SMSC9218I_INT_TXSO \
| SMSC9218I_INT_RWT \
| SMSC9218I_INT_RXE \
| SMSC9218I_INT_TXE)
#ifdef DEBUG #ifdef DEBUG
#define SMSC9218I_PRINTF(...) printf(__VA_ARGS__) #define SMSC9218I_PRINTF(...) printf(__VA_ARGS__)
#define SMSC9218I_PRINTK(...) printk(__VA_ARGS__) #define SMSC9218I_PRINTK(...) printk(__VA_ARGS__)
@@ -119,7 +131,7 @@ typedef enum {
typedef struct { typedef struct {
struct arpcom arpcom; struct arpcom arpcom;
struct rtems_mdio_info mdio_info; struct rtems_mdio_info mdio;
smsc9218i_state state; smsc9218i_state state;
rtems_id receive_task; rtems_id receive_task;
rtems_id transmit_task; rtems_id transmit_task;
@@ -129,11 +141,16 @@ typedef struct {
unsigned receive_interrupts; unsigned receive_interrupts;
unsigned transmitted_frames; unsigned transmitted_frames;
unsigned transmit_interrupts; unsigned transmit_interrupts;
unsigned receiver_errors;
unsigned receive_too_long_errors; unsigned receive_too_long_errors;
unsigned receive_collision_errors; unsigned receive_collision_errors;
unsigned receive_crc_errors; unsigned receive_crc_errors;
unsigned receive_edma_errors; unsigned receive_edma_errors;
unsigned transmit_errors; unsigned receive_drop;
unsigned receive_watchdog_timeouts;
unsigned transmitter_errors;
unsigned transmit_status_overflows;
unsigned transmit_frame_errors;
unsigned transmit_edma_errors; unsigned transmit_edma_errors;
} smsc9218i_driver_entry; } smsc9218i_driver_entry;
@@ -160,6 +177,8 @@ typedef struct {
uint32_t command_b; uint32_t command_b;
uint16_t tag; uint16_t tag;
bool done; bool done;
unsigned fixme_tiny_fragments;
unsigned fixme_too_many;
} smsc9218i_transmit_job_control; } smsc9218i_transmit_job_control;
static void smsc9218i_edma_done( static void smsc9218i_edma_done(
@@ -390,13 +409,13 @@ static void smsc9218i_register_dump(volatile smsc9218i_registers *regs)
printf("mac: wuff: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_WUFF)); printf("mac: wuff: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_WUFF));
printf("mac: wucsr: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_WUCSR)); printf("mac: wucsr: 0x%08" PRIx32 "\n", smsc9218i_mac_read(regs, SMSC9218I_MAC_WUCSR));
printf("phy: bcr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_BCR)); printf("phy: bcr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, MII_BMCR));
printf("phy: bsr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_BSR)); printf("phy: bsr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, MII_BMSR));
printf("phy: id1: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ID1)); printf("phy: id1: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, MII_PHYIDR1));
printf("phy: id2: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ID2)); printf("phy: id2: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, MII_PHYIDR2));
printf("phy: anar: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ANAR)); printf("phy: anar: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, MII_ANAR));
printf("phy: anlpar: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ANLPAR)); printf("phy: anlpar: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, MII_ANLPAR));
printf("phy: anexpr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_ANEXPR)); printf("phy: anexpr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, MII_ANER));
printf("phy: mcsr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_MCSR)); printf("phy: mcsr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_MCSR));
printf("phy: spmodes: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_SPMODES)); printf("phy: spmodes: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_SPMODES));
printf("phy: cisr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_CSIR)); printf("phy: cisr: 0x%08" PRIx32 "\n", smsc9218i_phy_read(regs, SMSC9218I_PHY_CSIR));
@@ -435,15 +454,31 @@ static void smsc9218i_interrupt_handler(void *arg)
/* Clear interrupts */ /* Clear interrupts */
regs->int_sts = int_sts; regs->int_sts = int_sts;
/* Error interrupts */
if ((int_sts & SMSC9218I_ERROR_INTERRUPTS) != 0) {
if ((int_sts & SMSC9218I_INT_TXSO) != 0) {
++e->transmit_status_overflows;
}
if ((int_sts & SMSC9218I_INT_RWT) != 0) {
++e->receive_watchdog_timeouts;
}
if ((int_sts & SMSC9218I_INT_RXE) != 0) {
++e->receiver_errors;
}
if ((int_sts & SMSC9218I_INT_TXE) != 0) {
++e->transmitter_errors;
}
}
/* Check receive interrupts */ /* Check receive interrupts */
if ((int_sts & SMSC9218I_INT_STS_RSFL) != 0) { if ((int_sts & SMSC9218I_INT_RSFL) != 0) {
int_en &= ~SMSC9218I_INT_EN_RSFL; int_en &= ~SMSC9218I_INT_RSFL;
re = SMSC9218I_EVENT_RX; re = SMSC9218I_EVENT_RX;
} }
/* Check PHY interrupts */ /* Check PHY interrupts */
if ((int_sts & SMSC9218I_INT_STS_PHY) != 0) { if ((int_sts & SMSC9218I_INT_PHY) != 0) {
int_en &= ~SMSC9218I_INT_EN_PHY; int_en &= ~SMSC9218I_INT_PHY;
re |= SMSC9218I_EVENT_PHY; re |= SMSC9218I_EVENT_PHY;
} }
@@ -455,8 +490,8 @@ static void smsc9218i_interrupt_handler(void *arg)
} }
/* Check transmit interrupts */ /* Check transmit interrupts */
if ((int_sts & SMSC9218I_INT_STS_TDFA) != 0) { if ((int_sts & SMSC9218I_INT_TDFA) != 0) {
int_en &= ~SMSC9218I_INT_EN_TDFA; int_en &= ~SMSC9218I_INT_TDFA;
te = SMSC9218I_EVENT_TX; te = SMSC9218I_EVENT_TX;
} }
@@ -481,7 +516,7 @@ static void smsc9218i_enable_receive_interrupts(
rtems_interrupt_level level; rtems_interrupt_level level;
rtems_interrupt_disable(level); rtems_interrupt_disable(level);
regs->int_en |= SMSC9218I_INT_EN_RSFL; regs->int_en |= SMSC9218I_INT_RSFL;
rtems_interrupt_enable(level); rtems_interrupt_enable(level);
} }
@@ -492,7 +527,7 @@ static void smsc9218i_enable_transmit_interrupts(
rtems_interrupt_level level; rtems_interrupt_level level;
rtems_interrupt_disable(level); rtems_interrupt_disable(level);
regs->int_en |= SMSC9218I_INT_EN_TDFA; regs->int_en |= SMSC9218I_INT_TDFA;
rtems_interrupt_enable(level); rtems_interrupt_enable(level);
} }
@@ -503,29 +538,56 @@ static void smsc9218i_enable_phy_interrupts(
rtems_interrupt_level level; rtems_interrupt_level level;
rtems_interrupt_disable(level); rtems_interrupt_disable(level);
regs->int_en |= SMSC9218I_INT_EN_PHY; regs->int_en |= SMSC9218I_INT_PHY;
rtems_interrupt_enable(level); rtems_interrupt_enable(level);
} }
static struct mbuf *smsc9218i_new_mbuf(struct ifnet *ifp, bool wait) static void smsc9218i_phy_clear_interrupts(
volatile smsc9218i_registers *regs
)
{ {
struct mbuf *m = NULL; smsc9218i_phy_read(regs, SMSC9218I_PHY_ISR);
int mw = wait ? M_WAIT : M_DONTWAIT; }
static bool smsc9218i_media_status(smsc9218i_driver_entry *e, int *media)
{
struct ifnet *ifp = &e->arpcom.ac_if;
*media = IFM_MAKEWORD(0, 0, 0, SMSC9218I_MAC_MII_ACC_PHY_DEFAULT);
return (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t) media) == 0;
}
static void smsc9218i_media_status_change(
smsc9218i_driver_entry *e,
volatile smsc9218i_registers *regs
)
{
int media = 0;
bool media_ok = false;
uint32_t mac_cr = 0;
smsc9218i_phy_clear_interrupts(regs);
smsc9218i_enable_phy_interrupts(regs);
media_ok = smsc9218i_media_status(e, &media);
mac_cr = smsc9218i_mac_read(regs, SMSC9218I_MAC_CR);
if (media_ok && (IFM_OPTIONS(media) & IFM_FDX) == 0) {
mac_cr &= ~SMSC9218I_MAC_CR_FDPX;
} else {
mac_cr |= SMSC9218I_MAC_CR_FDPX;
}
smsc9218i_mac_write(regs, SMSC9218I_MAC_CR, mac_cr);
}
static struct mbuf *smsc9218i_new_mbuf(struct ifnet *ifp)
{
struct mbuf *m = m_gethdr(M_WAIT, MT_DATA);
MGETHDR(m, mw, MT_DATA);
if (m != NULL) {
MCLGET(m, mw);
if ((m->m_flags & M_EXT) != 0) {
/* Set receive interface */
m->m_pkthdr.rcvif = ifp; m->m_pkthdr.rcvif = ifp;
MCLGET(m, M_WAIT);
return m; return m;
} else {
m_freem(m);
}
}
return NULL;
} }
static void smsc9218i_receive_task(void *arg) static void smsc9218i_receive_task(void *arg)
@@ -592,13 +654,7 @@ static void smsc9218i_receive_task(void *arg)
RTEMS_CLEANUP_SC(sc, cleanup, "wait for events"); RTEMS_CLEANUP_SC(sc, cleanup, "wait for events");
if ((events & SMSC9218I_EVENT_PHY) != 0) { if ((events & SMSC9218I_EVENT_PHY) != 0) {
uint32_t phy_isr = smsc9218i_phy_read(regs, SMSC9218I_PHY_ISR); smsc9218i_media_status_change(e, regs);
/* TODO */
printf("rx: PHY event: 0x%08" PRIx32 "\n", phy_isr);
smsc9218i_enable_phy_interrupts(regs);
} }
rx_fifo_inf = regs->rx_fifo_inf; rx_fifo_inf = regs->rx_fifo_inf;
@@ -631,7 +687,7 @@ static void smsc9218i_receive_task(void *arg)
); );
if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR) == 0) { if ((rx_fifo_status & SMSC9218I_RX_STS_ERROR) == 0) {
struct mbuf *m = smsc9218i_new_mbuf(ifp, true); struct mbuf *m = smsc9218i_new_mbuf(ifp);
struct ether_header *eh = (struct ether_header *) struct ether_header *eh = (struct ether_header *)
(mtod(m, char *) + SMSC9218I_RX_DATA_OFFSET); (mtod(m, char *) + SMSC9218I_RX_DATA_OFFSET);
int mbuf_length = (int) frame_length - ETHER_HDR_LEN - ETHER_CRC_LEN; int mbuf_length = (int) frame_length - ETHER_HDR_LEN - ETHER_CRC_LEN;
@@ -706,7 +762,7 @@ static void smsc9218i_receive_task(void *arg)
} }
/* Clear FIFO level status */ /* Clear FIFO level status */
regs->int_sts = SMSC9218I_INT_STS_RSFL; regs->int_sts = SMSC9218I_INT_RSFL;
/* Next FIFO status */ /* Next FIFO status */
rx_fifo_inf = regs->rx_fifo_inf; rx_fifo_inf = regs->rx_fifo_inf;
@@ -821,7 +877,7 @@ static struct mbuf *smsc9218i_next_transmit_fragment(
frame_length += (uint32_t) len; frame_length += (uint32_t) len;
if (len < 4) { if (len < 4) {
printf("FIXME\n"); ++jc->fixme_tiny_fragments;
} }
/* Next fragment */ /* Next fragment */
@@ -841,7 +897,7 @@ static struct mbuf *smsc9218i_next_transmit_fragment(
} while (n != NULL); } while (n != NULL);
if (fragments > SMSC9218I_TX_FRAGMENT_MAX) { if (fragments > SMSC9218I_TX_FRAGMENT_MAX) {
printf("FIXME\n"); ++jc->fixme_too_many;
} }
/* Set frame length */ /* Set frame length */
@@ -920,8 +976,6 @@ static void smsc9218i_transmit_create_jobs(
data_length data_length
); );
__asm__ volatile ( "sync");
/* Remember fragement */ /* Remember fragement */
jc->fragment_table [c] = m; jc->fragment_table [c] = m;
@@ -989,7 +1043,7 @@ static void smsc9218i_transmit_do_jobs(
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
struct tcd_t *tcd = &jc->data_tcd_table [c]; struct tcd_t *tcd = &jc->data_tcd_table [c];
uint32_t data_length = tcd->NBYTES; uint32_t data_length = tcd->NBYTES + 14;
if (data_length <= data_free) { if (data_length <= data_free) {
/* Reduce free FIFO space */ /* Reduce free FIFO space */
@@ -1042,6 +1096,7 @@ static void smsc9218i_transmit_do_jobs(
/* Cache flush for last data TCD */ /* Cache flush for last data TCD */
rtems_cache_flush_multiple_data_lines(last, sizeof(*last)); rtems_cache_flush_multiple_data_lines(last, sizeof(*last));
ppc_synchronize_data();
/* Start eDMA transfer */ /* Start eDMA transfer */
channel->SADDR = start->SADDR; channel->SADDR = start->SADDR;
@@ -1088,7 +1143,7 @@ static void smsc9218i_transmit_finish_jobs(
if ((tx_fifo_status & SMSC9218I_TX_STS_ERROR) == 0) { if ((tx_fifo_status & SMSC9218I_TX_STS_ERROR) == 0) {
++e->transmitted_frames; ++e->transmitted_frames;
} else { } else {
++e->transmit_errors; ++e->transmit_frame_errors;
} }
SMSC9218I_PRINTF( SMSC9218I_PRINTF(
@@ -1296,6 +1351,13 @@ static void smsc9218i_test_macros(void)
} }
#endif #endif
static void smsc9218i_wait_for_eeprom_access(volatile smsc9218i_registers *regs)
{
while ((regs->e2p_cmd & SMSC9218I_E2P_CMD_EPC_BUSY) != 0) {
/* Wait */
}
}
static void smsc9218i_set_mac_address( static void smsc9218i_set_mac_address(
volatile smsc9218i_registers *regs, volatile smsc9218i_registers *regs,
unsigned char address [6] unsigned char address [6]
@@ -1314,6 +1376,7 @@ static void smsc9218i_set_mac_address(
); );
} }
#if defined(DEBUG)
static void smsc9218i_mac_address_dump(volatile smsc9218i_registers *regs) static void smsc9218i_mac_address_dump(volatile smsc9218i_registers *regs)
{ {
uint32_t low = smsc9218i_mac_read(regs, SMSC9218I_MAC_ADDRL); uint32_t low = smsc9218i_mac_read(regs, SMSC9218I_MAC_ADDRL);
@@ -1330,6 +1393,7 @@ static void smsc9218i_mac_address_dump(volatile smsc9218i_registers *regs)
(high >> 8) & 0xff (high >> 8) & 0xff
); );
} }
#endif
static void smsc9218i_interrupt_init( static void smsc9218i_interrupt_init(
smsc9218i_driver_entry *e, smsc9218i_driver_entry *e,
@@ -1415,6 +1479,9 @@ static void smsc9218i_interrupt_init(
/* Enable interrupts and use push-pull driver (active low) */ /* Enable interrupts and use push-pull driver (active low) */
regs->irq_cfg = SMSC9218I_IRQ_CFG_GLOBAL_ENABLE; regs->irq_cfg = SMSC9218I_IRQ_CFG_GLOBAL_ENABLE;
/* Enable error interrupts */
regs->int_en = SMSC9218I_ERROR_INTERRUPTS;
} }
static void smsc9218i_reset_signal(bool signal) static void smsc9218i_reset_signal(bool signal)
@@ -1441,6 +1508,18 @@ static void smsc9218i_reset_signal_init(void)
SIU.PCR [186].R = pcr.R; SIU.PCR [186].R = pcr.R;
} }
static void smsc9218i_hardware_reset(volatile smsc9218i_registers *regs)
{
smsc9218i_reset_signal_init();
smsc9218i_reset_signal(false);
rtems_bsp_delay(200);
smsc9218i_reset_signal(true);
while ((regs->pmt_ctrl & SMSC9218I_PMT_CTRL_READY) == 0) {
/* Wait */
}
}
static void smsc9218i_interface_init(void *arg) static void smsc9218i_interface_init(void *arg)
{ {
smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg; smsc9218i_driver_entry *e = (smsc9218i_driver_entry *) arg;
@@ -1450,11 +1529,7 @@ static void smsc9218i_interface_init(void *arg)
SMSC9218I_PRINTF("%s\n", __func__); SMSC9218I_PRINTF("%s\n", __func__);
if (e->state == SMSC9218I_CONFIGURED) { if (e->state == SMSC9218I_CONFIGURED) {
/* Hardware reset */ smsc9218i_hardware_reset(regs);
smsc9218i_reset_signal_init();
smsc9218i_reset_signal(false);
rtems_bsp_delay(200);
smsc9218i_reset_signal(true);
#if defined(DEBUG) #if defined(DEBUG)
/* Register dump */ /* Register dump */
@@ -1465,8 +1540,18 @@ static void smsc9218i_interface_init(void *arg)
regs->hw_cfg = SMSC9218I_HW_CFG_MBO | SMSC9218I_HW_CFG_TX_FIF_SZ(5); regs->hw_cfg = SMSC9218I_HW_CFG_MBO | SMSC9218I_HW_CFG_TX_FIF_SZ(5);
/* MAC address */ /* MAC address */
smsc9218i_wait_for_eeprom_access(regs);
smsc9218i_set_mac_address(regs, e->arpcom.ac_enaddr); smsc9218i_set_mac_address(regs, e->arpcom.ac_enaddr);
#if defined(DEBUG)
smsc9218i_mac_address_dump(regs); smsc9218i_mac_address_dump(regs);
#endif
/* Auto-negotiation advertisment */
smsc9218i_phy_write(
regs,
MII_ANAR,
ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA
);
/* Initialize interrupts */ /* Initialize interrupts */
smsc9218i_interrupt_init(e, regs); smsc9218i_interrupt_init(e, regs);
@@ -1477,6 +1562,9 @@ static void smsc9218i_interface_init(void *arg)
/* Set FIFO interrupts */ /* Set FIFO interrupts */
regs->fifo_int = SMSC9218I_FIFO_INT_TDAL(32); regs->fifo_int = SMSC9218I_FIFO_INT_TDAL(32);
/* Clear receive drop counter */
regs->rx_drop;
/* Start receive task */ /* Start receive task */
if (e->receive_task == RTEMS_ID_NONE) { if (e->receive_task == RTEMS_ID_NONE) {
e->receive_task = rtems_bsdnet_newproc( e->receive_task = rtems_bsdnet_newproc(
@@ -1519,18 +1607,67 @@ static void smsc9218i_interface_init(void *arg)
} }
} }
static void smsc9218i_interface_stats(const smsc9218i_driver_entry *e) static int smsc9218i_mdio_read(
int phy,
void *arg,
unsigned phy_reg,
uint32_t *val
)
{ {
volatile smsc9218i_registers *const regs = smsc9218i;
*val = smsc9218i_phy_read(regs, phy_reg);
return 0;
}
static int smsc9218i_mdio_write(
int phy,
void *arg,
unsigned phy_reg,
uint32_t data
)
{
volatile smsc9218i_registers *const regs = smsc9218i;
smsc9218i_phy_write(regs, phy_reg, data);
return 0;
}
static void smsc9218i_interface_stats(smsc9218i_driver_entry *e)
{
volatile smsc9218i_registers *const regs = smsc9218i;
smsc9218i_transmit_job_control *jc = &smsc_jc;
int media = 0;
bool media_ok = smsc9218i_media_status(e, &media);
if (media_ok) {
rtems_ifmedia2str(media, NULL, 0);
printf ("\n");
} else {
printf ("PHY communication error\n");
}
e->receive_drop += SMSC9218I_SWAP(regs->rx_drop);
printf("received frames: %u\n", e->received_frames); printf("received frames: %u\n", e->received_frames);
printf("receive interrupts: %u\n", e->receive_interrupts); printf("receive interrupts: %u\n", e->receive_interrupts);
printf("transmitted frames: %u\n", e->transmitted_frames); printf("transmitted frames: %u\n", e->transmitted_frames);
printf("transmit interrupts: %u\n", e->transmit_interrupts); printf("transmit interrupts: %u\n", e->transmit_interrupts);
printf("receiver errors: %u\n", e->receiver_errors);
printf("receive to long errors: %u\n", e->receive_too_long_errors); printf("receive to long errors: %u\n", e->receive_too_long_errors);
printf("receive collision errors: %u\n", e->receive_collision_errors); printf("receive collision errors: %u\n", e->receive_collision_errors);
printf("receive CRC errors: %u\n", e->receive_crc_errors); printf("receive CRC errors: %u\n", e->receive_crc_errors);
printf("receive eDMA errors: %u\n", e->receive_edma_errors); printf("receive eDMA errors: %u\n", e->receive_edma_errors);
printf("transmit errors: %u\n", e->transmit_errors); printf("receive drops: %u\n", e->receive_drop);
printf("receive watchdog timeouts: %u\n", e->receive_watchdog_timeouts);
printf("transmitter errors: %u\n", e->transmitter_errors);
printf("transmit status overflows: %u\n", e->transmit_status_overflows);
printf("transmit frame errors: %u\n", e->transmit_frame_errors);
printf("transmit eDMA errors: %u\n", e->transmit_edma_errors); printf("transmit eDMA errors: %u\n", e->transmit_edma_errors);
printf("fixme tiny fragments: %u\n", jc->fixme_tiny_fragments);
printf("fixme too many: %u\n", jc->fixme_too_many);
} }
static int smsc9218i_interface_ioctl( static int smsc9218i_interface_ioctl(
@@ -1546,7 +1683,7 @@ static int smsc9218i_interface_ioctl(
switch (command) { switch (command) {
case SIOCGIFMEDIA: case SIOCGIFMEDIA:
case SIOCSIFMEDIA: case SIOCSIFMEDIA:
rtems_mii_ioctl(&e->mdio_info, e, (int) command, (int *) data); rtems_mii_ioctl(&e->mdio, e, (int) command, (int *) data);
break; break;
case SIOCGIFADDR: case SIOCGIFADDR:
case SIOCSIFADDR: case SIOCSIFADDR:
@@ -1640,6 +1777,10 @@ static int smsc9218i_attach(struct rtems_bsdnet_ifconfig *config)
ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_timer = 0; ifp->if_timer = 0;
/* MDIO */
e->mdio.mdio_r = smsc9218i_mdio_read;
e->mdio.mdio_w = smsc9218i_mdio_write;
/* Change status */ /* Change status */
e->state = SMSC9218I_CONFIGURED; e->state = SMSC9218I_CONFIGURED;

View File

@@ -478,27 +478,10 @@ static const struct MMU_tag mmu_setup[] = {
#else /* default, MPC55xxEVB */ #else /* default, MPC55xxEVB */
{ {
/* External Ethernet Controller (3 wait states, 64kB) */ /* External Ethernet Controller (3 wait states, 64kB) */
{ .MAS0 = { .R = 0x10050000 },
.B.TLBSEL = 1, /* MAS0 */ .MAS1 = { .R = 0xc0000100 },
.B.ESEL = 5 .MAS2 = { .R = 0x3fff800a },
}, .MAS3 = { .R = 0x3fff800f }
{
.B.VALID = 1, /* MAS1 */
.B.IPROT = 1,
.B.TSIZ = 1
},
{
.B.EPN = 0x3fff8, /* MAS2 */
.B.I = 1,
.B.G = 1
},
{
.B.RPN = 0x3fff8, /* MAS3 */
.B.UW = 1,
.B.SW = 1,
.B.UR = 1,
.B.SR = 1
}
} }
#endif /* MMU setup */ #endif /* MMU setup */
}; };