[PATCH 17/17] bsp/altera-cyclone-v: Implement BSP

Ralf Kirchner ralf.kirchner at embedded-brains.de
Mon Mar 3 08:42:10 UTC 2014


Hi Gedare,
Thanks for you review. I have corrected this locally.

Kind Regards
	Ralf Kirchner

Am 26.02.2014 20:19, schrieb Gedare Bloom:
> Please choose and stick with one mnemonic for the new BSP. You have
> used altera-cyclone-v as the BSP group name, but used cylone_v_ and
> altcycv_ for the bsp namespace functions, and CYCLONE_V and ALTCYCV
> for the prefix of cpp defines. the bsp namespace should be
> altera_cyclone_v and cpp should be ALTERA_CYCLONE_V if the bsp is
> named altera-cyclone-v.
> -Gedare
> 
> On Wed, Feb 26, 2014 at 5:52 AM, Ralf Kirchner
> <ralf.kirchner at embedded-brains.de> wrote:
>> Implemented so far:
>> - nocache heap for uncached RAM
>> - basic timer
>> - level 1 cache handling for arm cache controller
>>   in arm-cache-l1.h
>> - level 2 L2C-310 cache controller
>> - MMU
>> - DWMAC 1000 ethernet controller
>> - counts for BSP objects
>> - basic errata handling
>> - smp startup for second core
>> ---
>>  c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am  |   16 +-
>>  c/src/lib/libbsp/arm/altera-cyclone-v/README       |    3 +
>>  c/src/lib/libbsp/arm/altera-cyclone-v/configure.ac |   11 +-
>>  .../arm/altera-cyclone-v/console/console-config.c  |  167 ++-
>>  .../lib/libbsp/arm/altera-cyclone-v/include/bsp.h  |   46 +-
>>  .../lib/libbsp/arm/altera-cyclone-v/include/irq.h  |   69 +-
>>  .../libbsp/arm/altera-cyclone-v/include/network.h  |   59 +
>>  .../arm/altera-cyclone-v/include/nocache-heap.h    |   49 +
>>  .../libbsp/arm/altera-cyclone-v/network/network.c  | 1241 ++++++++++++++++++++
>>  .../lib/libbsp/arm/altera-cyclone-v/preinstall.am  |   20 +
>>  .../libbsp/arm/altera-cyclone-v/startup/bspreset.c |   10 +-
>>  .../libbsp/arm/altera-cyclone-v/startup/bspstart.c |  112 +-
>>  .../arm/altera-cyclone-v/startup/bspstarthooks.c   |  231 +++-
>>  .../startup/linkcmds.altcycv_devkit                |   16 +-
>>  .../arm/altera-cyclone-v/startup/nocache-heap.c    |   87 ++
>>  15 Dateien geändert, 1944 Zeilen hinzugefügt(+), 193 Zeilen entfernt(-)
>>  create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/include/network.h
>>  create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/include/nocache-heap.h
>>  create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/network/network.c
>>  create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/startup/nocache-heap.c
>>
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
>> index 6b1749b..1cd92af 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
>> @@ -33,15 +33,20 @@ include_bsp_HEADERS += ../../shared/include/irq-info.h
>>  include_bsp_HEADERS += ../../shared/include/stackalloc.h
>>  include_bsp_HEADERS += ../../shared/tod.h
>>  include_bsp_HEADERS += ../shared/include/start.h
>> +include_bsp_HEADERS += ../shared/include/arm-a9mpcore-clock.h
>>  include_bsp_HEADERS += ../shared/include/arm-a9mpcore-irq.h
>>  include_bsp_HEADERS += ../shared/include/arm-a9mpcore-regs.h
>>  include_bsp_HEADERS += ../shared/include/arm-a9mpcore-start.h
>>  include_bsp_HEADERS += ../shared/include/arm-cp15-start.h
>> +include_bsp_HEADERS += ../shared/include/arm-errata.h
>>  include_bsp_HEADERS += ../shared/include/arm-gic.h
>>  include_bsp_HEADERS += ../shared/include/arm-gic-irq.h
>>  include_bsp_HEADERS += ../shared/include/arm-gic-regs.h
>>  include_bsp_HEADERS += ../shared/include/arm-gic-tm27.h
>> +include_bsp_HEADERS += ../shared/include/arm-release-id.h
>>  include_bsp_HEADERS += include/irq.h
>> +include_bsp_HEADERS += include/network.h
>> +include_bsp_HEADERS += include/nocache-heap.h
>>
>>  # Altera hwlib
>>  include_bsp_HEADERS += hwlib/include/alt_16550_uart.h
>> @@ -139,6 +144,7 @@ libbsp_a_SOURCES += ../shared/arm-cp15-set-ttb-entries.c
>>  # Startup
>>  libbsp_a_SOURCES += startup/bspreset.c
>>  libbsp_a_SOURCES += startup/bspstart.c
>> +libbsp_a_SOURCES += startup/nocache-heap.c
>>
>>  # IRQ
>>  libbsp_a_SOURCES += ../../shared/src/irq-default-handler.c
>> @@ -149,6 +155,9 @@ libbsp_a_SOURCES += ../../shared/src/irq-server.c
>>  libbsp_a_SOURCES += ../../shared/src/irq-shell.c
>>  libbsp_a_SOURCES += ../shared/arm-gic-irq.c
>>
>> +# Network
>> +libbsp_a_SOURCES += network/network.c
>> +
>>  # Console
>>  libbsp_a_SOURCES += ../../shared/console.c
>>  libbsp_a_SOURCES += ../../shared/console_control.c
>> @@ -163,10 +172,9 @@ libbsp_a_SOURCES += ../shared/arm-a9mpcore-clock-config.c
>>
>>  # Cache
>>  libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c
>> -libbsp_a_SOURCES += ../../../libcpu/arm/shared/include/cache_.h
>> -libbsp_a_CPPFLAGS += -I$(srcdir)/../../../libcpu/arm/shared/include
>> -#libbsp_a_CPPFLAGS += -I$(srcdir)/startup/linux
>> -#libbsp_a_SOURCES += startup/linux/cache-l2x0.c
>> +libbsp_a_SOURCES += ../shared/include/arm-cache-l1.h
>> +libbsp_a_SOURCES += ../shared/arm-l2c-310/cache_.h
>> +libbsp_a_CPPFLAGS += -I$(srcdir)/../shared/arm-l2c-310
>>
>>  # Start hooks
>>  libbsp_a_SOURCES += startup/bspstarthooks.c
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/README b/c/src/lib/libbsp/arm/altera-cyclone-v/README
>> index e69de29..575b72e 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/README
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/README
>> @@ -0,0 +1,3 @@
>> +Evaluation board for this BSP:
>> +- Cyclone V SoC FPGA Development Kit
>> +- DK-DEV-5CSXC6N/ES-0L
>> \ No newline at end of file
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/configure.ac b/c/src/lib/libbsp/arm/altera-cyclone-v/configure.ac
>> index bcf5b10..561a192 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/configure.ac
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/configure.ac
>> @@ -24,7 +24,7 @@ AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
>>  RTEMS_BSPOPTS_SET([BSP_START_RESET_VECTOR],[*],[])
>>  RTEMS_BSPOPTS_HELP([BSP_START_RESET_VECTOR],[reset vector address for BSP start])
>>
>> -RTEMS_BSPOPTS_SET([BSP_ARM_A9MPCORE_PERIPHCLK],[altcycv_devkit*],[666666667U])
>> +RTEMS_BSPOPTS_SET([BSP_ARM_A9MPCORE_PERIPHCLK],[altcycv_devkit*],[200000000U])
>>  RTEMS_BSPOPTS_SET([BSP_ARM_A9MPCORE_PERIPHCLK],[*],[100000000U])
>>  RTEMS_BSPOPTS_HELP([BSP_ARM_A9MPCORE_PERIPHCLK],[ARM Cortex-A9 MPCore PERIPHCLK clock frequency in Hz])
>>
>> @@ -37,6 +37,15 @@ simulation times.])
>>  RTEMS_BSPOPTS_SET([BSP_CONSOLE_MINOR],[*],[0])
>>  RTEMS_BSPOPTS_HELP([BSP_CONSOLE_MINOR],[minor number of console device])
>>
>> +RTEMS_BSPOPTS_SET([CYCLONE_V_CONFIG_CONSOLE],[*],[0])
>> +RTEMS_BSPOPTS_HELP([CYCLONE_V_CONFIG_CONSOLE],[configuration for console (UART 0)])
>> +
>> +RTEMS_BSPOPTS_SET([CYCLONE_V_CONFIG_UART_1],[*],[0])
>> +RTEMS_BSPOPTS_HELP([CYCLONE_V_CONFIG_UART_1],[configuration for UART 1])
>> +
>> +RTEMS_BSPOPTS_SET([CYCLONE_V_UART_BAUD],[*],[115200U])
>> +RTEMS_BSPOPTS_HELP([CYCLONE_V_UART_BAUD],[baud for UARTs])
>> +
>>  RTEMS_CHECK_SMP
>>  AM_CONDITIONAL(HAS_SMP,[test "$rtems_cv_HAS_SMP" = "yes"])
>>
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
>> index acad744..7e4dad9 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
>> @@ -12,56 +12,151 @@
>>   * http://www.rtems.com/license/LICENSE.
>>   */
>>
>> +#include <assert.h>
>> +#include <stdint.h>
>> +#include <stdbool.h>
>>  #include <libchip/serial.h>
>> +#include <libchip/ns16550.h>
>>
>>  #include <bsp.h>
>>  #include <bsp/irq.h>
>> +#include <bsp/alt_16550_uart.h>
>> +#include <socal/alt_rstmgr.h>
>> +#include <socal/socal.h>
>> +#include <socal/alt_uart.h>
>> +#include <socal/hps.h>
>> +
>> +bool cyclone_v_uart_probe( int minor );
>> +
>> +static uint8_t cyclone_v_uart_get_register(uintptr_t addr, uint8_t i)
>> +{
>> +  volatile uint32_t *reg = (volatile uint32_t *) addr;
>> +
>> +  return (uint8_t) reg [i];
>> +}
>> +
>> +static void cyclone_v_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
>> +{
>> +  volatile uint32_t *reg = (volatile uint32_t *) addr;
>> +
>> +  reg [i] = val;
>> +}
>>
>>  console_tbl Console_Configuration_Ports[] = {
>> -#if 0
>> +#ifdef CYCLONE_V_CONFIG_CONSOLE
>> +  {
>> +    .sDeviceName   = "/dev/ttyS0",
>> +    .deviceType    = SERIAL_NS16550,
>> +    .pDeviceFns    = &ns16550_fns,
>> +    .deviceProbe   = cyclone_v_uart_probe,
>> +    .pDeviceFlow   = NULL,
>> +    .ulMargin      = 16,
>> +    .ulHysteresis  = 8,
>> +    .pDeviceParams = (void *)CYCLONE_V_UART_BAUD,
>> +    .ulCtrlPort1   = (uint32_t)ALT_UART0_ADDR,
>> +    .ulCtrlPort2   = 0,
>> +    .ulDataPort    = (uint32_t)ALT_UART0_ADDR,
>> +    .getRegister   = cyclone_v_uart_get_register,
>> +    .setRegister   = cyclone_v_uart_set_register,
>> +    .getData       = NULL,
>> +    .setData       = NULL,
>> +    .ulClock       = 0,
>> +    .ulIntVector   = ALT_INT_INTERRUPT_UART0
>> +  },
>> +#endif
>> +#ifdef CYCLONE_V_CONFIG_UART_1
>>    {
>> -    .sDeviceName = "/dev/ttyS0",
>> -    .deviceType = SERIAL_CUSTOM,
>> -    .pDeviceFns = &altcycv_uart_fns,
>> -    .deviceProbe = NULL,
>> -    .pDeviceFlow = NULL,
>> -    .ulMargin = 0,
>> -    .ulHysteresis = 0,
>> -    .pDeviceParams = (void *) 115200,
>> -    .ulCtrlPort1 = 0xe0000000,
>> -    .ulCtrlPort2 = 0,
>> -    .ulDataPort = 0,
>> -    .getRegister = NULL,
>> -    .setRegister = NULL,
>> -    .getData = NULL,
>> -    .setData = NULL,
>> -    .ulClock = 0,
>> -    .ulIntVector = ALTCYCV_IRQ_UART_0
>> -  }, {
>> -    .sDeviceName = "/dev/ttyS1",
>> -    .deviceType = SERIAL_CUSTOM,
>> -    .pDeviceFns = &altcycv_uart_fns,
>> -    .deviceProbe = NULL,
>> -    .pDeviceFlow = NULL,
>> -    .ulMargin = 0,
>> -    .ulHysteresis = 0,
>> -    .pDeviceParams = (void *) 115200,
>> -    .ulCtrlPort1 = 0xe0001000,
>> -    .ulCtrlPort2 = 0,
>> -    .ulDataPort = 0,
>> -    .getRegister = NULL,
>> -    .setRegister = NULL,
>> -    .getData = NULL,
>> -    .setData = NULL,
>> -    .ulClock = 0,
>> -    .ulIntVector = ALTCYCV_IRQ_UART_1
>> +    .sDeviceName   = "/dev/ttyS1",
>> +    .deviceType    = SERIAL_NS16550,
>> +    .pDeviceFns    = &ns16550_fns,
>> +    .deviceProbe   = cyclone_v_uart_probe,
>> +    .pDeviceFlow   = NULL,
>> +    .ulMargin      = 16,
>> +    .ulHysteresis  = 8,
>> +    .pDeviceParams = (void *)CYCLONE_V_UART_BAUD,
>> +    .ulCtrlPort1   = (uint32_t)ALT_UART1_ADDR,
>> +    .ulCtrlPort2   = 0,
>> +    .ulDataPort    = (uint32_t)ALT_UART1_ADDR,
>> +    .getRegister   = cyclone_v_uart_get_register,
>> +    .setRegister   = cyclone_v_uart_set_register,
>> +    .getData       = NULL,
>> +    .setData       = NULL,
>> +    .ulClock       = 0,
>> +    .ulIntVector   = ALT_INT_INTERRUPT_UART1
>>    }
>>  #endif
>>  };
>>
>> +
>>  unsigned long Console_Configuration_Count =
>>    RTEMS_ARRAY_SIZE(Console_Configuration_Ports);
>>
>> +bool cyclone_v_uart_probe(int minor)
>> +{
>> +  bool            ret           = true;
>> +  uint32_t        uart_set_mask;
>> +  uint32_t        ucr;
>> +  ALT_STATUS_CODE sc;
>> +  void*           location;
>> +
>> +  // The ALT_CLK_L4_SP is required for all SoCFPGA UARTs. Check that it's enabled.
>> +  assert( alt_clk_is_enabled(ALT_CLK_L4_SP) == ALT_E_TRUE );
>> +  if ( alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE ) {
>> +    ret = false;
>> +  }
>> +
>> +  if ( ret ) {
>> +    switch(minor)
>> +    {
>> +      case(0):
>> +        /* UART 0 */
>> +        uart_set_mask = ALT_RSTMGR_PERMODRST_UART0_SET_MSK;
>> +        location      = ALT_UART0_ADDR;
>> +      break;
>> +      case(1):
>> +        /* UART 1 */
>> +        uart_set_mask = ALT_RSTMGR_PERMODRST_UART1_SET_MSK;
>> +        location      = ALT_UART1_ADDR;
>> +      break;
>> +      default:
>> +        /* Unknown case */
>> +        assert( minor == 0 || minor == 1 );
>> +        ret = false;
>> +      break;
>> +    }
>> +  }
>> +  if ( ret ) {
>> +    sc = alt_clk_freq_get(ALT_CLK_L4_SP, &Console_Configuration_Ports[minor].ulClock);
>> +    assert( sc == ALT_E_SUCCESS );
>> +    if ( sc != ALT_E_SUCCESS ) {
>> +      ret = false;
>> +    }
>> +  }
>> +
>> +  if ( ret ) {
>> +    // Bring UART out of reset.
>> +    alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, uart_set_mask);
>> +
>> +    // Verify the UCR (UART Component Version)
>> +    ucr = alt_read_word( ALT_UART_UCV_ADDR( location ) );
>> +
>> +    assert( ucr == ALT_UART_UCV_UART_COMPONENT_VER_RESET );
>> +    if ( ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET ) {
>> +      ret = false;
>> +    }
>> +  }
>> +
>> +  if ( ret ) {
>> +    // Write SRR::UR (Shadow Reset Register :: UART Reset)
>> +    alt_write_word( ALT_UART_SRR_ADDR( location ), ALT_UART_SRR_UR_SET_MSK );
>> +
>> +    // Read the MSR to work around case:119085.
>> +    (void)alt_read_word( ALT_UART_MSR_ADDR( location ) );
>> +  }
>> +
>> +  return ret;
>> +}
>> +
>>  static void output_char(char c)
>>  {
>>    int minor = (int) Console_Port_Minor;
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/include/bsp.h b/c/src/lib/libbsp/arm/altera-cyclone-v/include/bsp.h
>> index 8d872ee..6f08ed5 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/include/bsp.h
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/include/bsp.h
>> @@ -26,25 +26,51 @@
>>  #include <rtems/clockdrv.h>
>>
>>  #include <bsp/default-initial-extension.h>
>> +#include <bsp/arm-release-id.h>
>> +#if defined(RTEMS_NETWORKING)
>> +  #include <bsp/network.h>
>> +#endif /* defined(RTEMS_NETWORKING) */
>>
>>  #ifdef __cplusplus
>>  extern "C" {
>>  #endif /* __cplusplus */
>>
>> -#define BSP_ARM_A9MPCORE_SCU_BASE 0xf8f00000
>> +#define BSP_ARM_A9MPCORE_SCU_BASE 0xFFFEC000
>>
>> -#define BSP_ARM_GIC_CPUIF_BASE 0xf8f00100
>> +#define BSP_ARM_GIC_CPUIF_BASE ( BSP_ARM_A9MPCORE_SCU_BASE + 0x00000100 )
>>
>> -#define BSP_ARM_A9MPCORE_PT_BASE 0xf8f00600
>> +#define BSP_ARM_A9MPCORE_GT_BASE ( BSP_ARM_A9MPCORE_SCU_BASE + 0x00000200 )
>>
>> -#define BSP_ARM_GIC_DIST_BASE 0xf8f01000
>> +#define BSP_ARM_GIC_DIST_BASE ( BSP_ARM_A9MPCORE_SCU_BASE + 0x00001000 )
>>
>> -typedef enum {
>> -  BSP_ARM_A9MPCORE_FATAL_CLOCK_IRQ_INSTALL,
>> -  BSP_ARM_A9MPCORE_FATAL_CLOCK_IRQ_REMOVE
>> -} altcycv_fatal_code;
>> +#define BSP_ARM_L2CC_BASE 0xFFFEF000U
>> +#define BSP_ARM_MAX_CORES_PER_CONTROLLER 2
>>
>> -void altcycv_fatal(altcycv_fatal_code code) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
>> +#ifndef RTEMS_NETWORKING
>> +  /** @brief Number of semaphores created by the driver */
>> +  #define BSP_NETWORK_SEMAPHORE_COUNT 0
>> +
>> +  /** @brief Number of tasks created by the driver */
>> +  #define BSP_NETWORK_TASK_COUNT 0
>> +
>> +  /* Network #defines from bsp/network.h */
>> +  #define RTEMS_BSP_NETWORK_DRIVER_ATTACH
>> +  #define RTEMS_BSP_NETWORK_DRIVER_NAME
>> +#else
>> +  /* Network #defines from bsp/network.h */
>> +  #define RTEMS_BSP_NETWORK_DRIVER_ATTACH NETWORK_IF_ATTACH_DETACH
>> +  #define RTEMS_BSP_NETWORK_DRIVER_NAME NETWORK_IF_NAME
>> +#endif /* RTEMS_NETWORKING */
>> +
>> +#define BSP_SEMAPHORE_COUNT \
>> +  ( \
>> +    BSP_NETWORK_SEMAPHORE_COUNT \
>> +  )
>> +
>> +#define BSP_TASK_COUNT \
>> +  ( \
>> +    BSP_NETWORK_TASK_COUNT \
>> +  )
>>
>>  #ifdef __cplusplus
>>  }
>> @@ -52,4 +78,4 @@ void altcycv_fatal(altcycv_fatal_code code) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
>>
>>  #endif /* ASM */
>>
>> -#endif /* LIBBSP_ARM_ALTCYCV_BSP_H */
>> +#endif /* LIBBSP_ARM_ALTCYCV_BSP_H */
>> \ No newline at end of file
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/include/irq.h b/c/src/lib/libbsp/arm/altera-cyclone-v/include/irq.h
>> index d548e5b..aeee41e 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/include/irq.h
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/include/irq.h
>> @@ -22,74 +22,15 @@
>>
>>  #include <bsp/arm-a9mpcore-irq.h>
>>  #include <bsp/arm-gic-irq.h>
>> +#include <bsp/alt_interrupt_common.h>
>>
>>  #ifdef __cplusplus
>>  extern "C" {
>>  #endif /* __cplusplus */
>>
>> -#define ALTCYCV_IRQ_CPU_0 32
>> -#define ALTCYCV_IRQ_CPU_1 33
>> -#define ALTCYCV_IRQ_L2_CACHE 34
>> -#define ALTCYCV_IRQ_OCM 35
>> -#define ALTCYCV_IRQ_PMU_0 37
>> -#define ALTCYCV_IRQ_PMU_1 38
>> -#define ALTCYCV_IRQ_XADC 39
>> -#define ALTCYCV_IRQ_DVI 40
>> -#define ALTCYCV_IRQ_SWDT 41
>> -#define ALTCYCV_IRQ_TTC_0_0 42
>> -#define ALTCYCV_IRQ_TTC_1_0 43
>> -#define ALTCYCV_IRQ_TTC_2_0 44
>> -#define ALTCYCV_IRQ_DMAC_ABORT 45
>> -#define ALTCYCV_IRQ_DMAC_0 46
>> -#define ALTCYCV_IRQ_DMAC_1 47
>> -#define ALTCYCV_IRQ_DMAC_2 48
>> -#define ALTCYCV_IRQ_DMAC_3 49
>> -#define ALTCYCV_IRQ_SMC 50
>> -#define ALTCYCV_IRQ_QUAD_SPI 51
>> -#define ALTCYCV_IRQ_GPIO 52
>> -#define ALTCYCV_IRQ_USB_0 53
>> -#define ALTCYCV_IRQ_ETHERNET_0 54
>> -#define ALTCYCV_IRQ_ETHERNET_0_WAKEUP 55
>> -#define ALTCYCV_IRQ_SDIO_0 56
>> -#define ALTCYCV_IRQ_I2C_0 57
>> -#define ALTCYCV_IRQ_SPI_0 58
>> -#define ALTCYCV_IRQ_UART_0 59
>> -#define ALTCYCV_IRQ_CAN_0 60
>> -#define ALTCYCV_IRQ_FPGA_0 61
>> -#define ALTCYCV_IRQ_FPGA_1 62
>> -#define ALTCYCV_IRQ_FPGA_2 63
>> -#define ALTCYCV_IRQ_FPGA_3 64
>> -#define ALTCYCV_IRQ_FPGA_4 65
>> -#define ALTCYCV_IRQ_FPGA_5 66
>> -#define ALTCYCV_IRQ_FPGA_6 67
>> -#define ALTCYCV_IRQ_FPGA_7 68
>> -#define ALTCYCV_IRQ_TTC_0_1 69
>> -#define ALTCYCV_IRQ_TTC_1_1 70
>> -#define ALTCYCV_IRQ_TTC_2_1 71
>> -#define ALTCYCV_IRQ_DMAC_4 72
>> -#define ALTCYCV_IRQ_DMAC_5 73
>> -#define ALTCYCV_IRQ_DMAC_6 74
>> -#define ALTCYCV_IRQ_DMAC_7 75
>> -#define ALTCYCV_IRQ_USB_1 76
>> -#define ALTCYCV_IRQ_ETHERNET_1 77
>> -#define ALTCYCV_IRQ_ETHERNET_1_WAKEUP 78
>> -#define ALTCYCV_IRQ_SDIO_1 79
>> -#define ALTCYCV_IRQ_I2C_1 80
>> -#define ALTCYCV_IRQ_SPI_1 81
>> -#define ALTCYCV_IRQ_UART_1 82
>> -#define ALTCYCV_IRQ_CAN_1 83
>> -#define ALTCYCV_IRQ_FPGA_8 84
>> -#define ALTCYCV_IRQ_FPGA_9 85
>> -#define ALTCYCV_IRQ_FPGA_10 86
>> -#define ALTCYCV_IRQ_FPGA_11 87
>> -#define ALTCYCV_IRQ_FPGA_12 88
>> -#define ALTCYCV_IRQ_FPGA_13 89
>> -#define ALTCYCV_IRQ_FPGA_14 90
>> -#define ALTCYCV_IRQ_FPGA_15 91
>> -#define ALTCYCV_IRQ_PARITY 92
>> -
>> -#define BSP_INTERRUPT_VECTOR_MIN 0
>> -#define BSP_INTERRUPT_VECTOR_MAX 92
>> +/* Use interrupt IDs as defined in alt_interrupt_common.h */
>> +#define BSP_INTERRUPT_VECTOR_MIN ALT_INT_INTERRUPT_SGI0
>> +#define BSP_INTERRUPT_VECTOR_MAX ALT_INT_INTERRUPT_RAM_ECC_UNCORRECTED_IRQ
>>
>>  #ifdef __cplusplus
>>  }
>> @@ -97,4 +38,4 @@ extern "C" {
>>
>>  #endif /* ASM */
>>
>> -#endif /* LIBBSP_ARM_ALTCYCV_IRQ_H */
>> +#endif /* LIBBSP_ARM_ALTCYCV_IRQ_H */
>> \ No newline at end of file
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/include/network.h b/c/src/lib/libbsp/arm/altera-cyclone-v/include/network.h
>> new file mode 100644
>> index 0000000..7a4553b
>> --- /dev/null
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/include/network.h
>> @@ -0,0 +1,59 @@
>> +/**
>> + * @file network.h
>> + *
>> + * @ingroup [GROUP NAME]
>> + *
>> + * @brief Network Driver
>> + *
>> + * API header for the network driver of this BSP
>> + */
>> +
>> +/*
>> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
>> + *
>> + *  embedded brains GmbH
>> + *  Dornierstr. 4
>> + *  82178 Puchheim
>> + *  Germany
>> + *  <rtems at embedded-brains.de>
>> + *
>> + * The license and distribution terms for this file may be
>> + * found in the file LICENSE in this distribution or at
>> + * http://www.rtems.org/license/LICENSE.
>> + */
>> +
>> +#ifndef NETWORK_H_
>> +#define NETWORK_H_
>> +
>> +#include <rtems/rtems_bsdnet.h>
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif /* __cplusplus */
>> +
>> +/** @brief Number of semaphores created by the driver */
>> +#define BSP_NETWORK_SEMAPHORE_COUNT 1
>> +
>> +/** @brief Number of tasks created by the driver */
>> +#define BSP_NETWORK_TASK_COUNT 2
>> +
>> +/** @brief Network interface attach detach
>> + *
>> + * Attaches a network interface.
>> + * NOTE: Detaching is not supported!
>> + */
>> +int network_if_attach_detach(
>> +  struct rtems_bsdnet_ifconfig *config,
>> +  int                           attaching );
>> +
>> +/** @brief Alias */
>> +#define NETWORK_IF_ATTACH_DETACH network_if_attach_detach
>> +
>> +/** @brief Interface name */
>> +#define NETWORK_IF_NAME "eth0"
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif /* __cplusplus */
>> +
>> +#endif /* NETWORK_H_ */
>> \ No newline at end of file
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/include/nocache-heap.h b/c/src/lib/libbsp/arm/altera-cyclone-v/include/nocache-heap.h
>> new file mode 100644
>> index 0000000..d827584
>> --- /dev/null
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/include/nocache-heap.h
>> @@ -0,0 +1,49 @@
>> +/**
>> + * @file nocache-heap.h
>> + *
>> + * @ingroup [GROUP NAME]
>> + *
>> + * @brief Heap handling for uncached RAM
>> + */
>> +
>> +/*
>> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
>> + *
>> + *  embedded brains GmbH
>> + *  Dornierstr. 4
>> + *  82178 Puchheim
>> + *  Germany
>> + *  <rtems at embedded-brains.de>
>> + *
>> + * The license and distribution terms for this file may be
>> + * found in the file LICENSE in this distribution or at
>> + * http://www.rtems.org/license/LICENSE.
>> + */
>> +
>> +#ifndef NOCACHE_HEAP_H_
>> +#define NOCACHE_HEAP_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif /* __cplusplus */
>> +
>> +/** @brief Nocache alloc.
>> + *
>> + * Allocate memory from uncached heap.
>> + * @param   size  Number of bytes to be allocated.
>> + * @retval  Pointer to the allocated memory.
>> + */
>> +void *nocache_malloc( const size_t size );
>> +
>> +/** @brief Nocache free.
>> + *
>> + * Release memory from uncached heap.
>> + * @param ptr Address of the memory to be released.
>> + */
>> +void nocache_free( void *ptr );
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif /* __cplusplus */
>> +
>> +#endif /* NOCACHE_HEAP_H_ */
>> \ No newline at end of file
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/network/network.c b/c/src/lib/libbsp/arm/altera-cyclone-v/network/network.c
>> new file mode 100644
>> index 0000000..e1a0b29
>> --- /dev/null
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/network/network.c
>> @@ -0,0 +1,1241 @@
>> +/**
>> + * @file network.c
>> + *
>> + * @ingroup [GROUP NAME]
>> + *
>> + * @brief Network Driver
>> + *
>> + * This driver is a wrapper for the DWMAC 1000 driver from libchip.
>> + * The DWMAC 1000 driver is an on-chip Synopsys IP Ethernet controllers
>> + */
>> +
>> +/*
>> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
>> + *
>> + *  embedded brains GmbH
>> + *  Dornierstr. 4
>> + *  82178 Puchheim
>> + *  Germany
>> + *  <rtems at embedded-brains.de>
>> + *
>> + * The license and distribution terms for this file may be
>> + * found in the file LICENSE in this distribution or at
>> + * http://www.rtems.org/license/LICENSE.
>> + */
>> +
>> +
>> +#include <rtems.h>
>> +
>> +#if defined(RTEMS_NETWORKING)
>> +
>> +#include <assert.h>
>> +#include <stdint.h>
>> +#include <stdlib.h>
>> +#include <errno.h>
>> +#include <rtems.h>
>> +#include <rtems/config.h>
>> +#include <bsp.h>
>> +#include <bsp/irq.h>
>> +#include <bsp/linker-symbols.h>
>> +#include <bsp/alt_clock_manager.h>
>> +#include <bsp/alt_interrupt_common.h>
>> +#include <bsp/alt_generalpurpose_io.h>
>> +
>> +//#include <bsp/network.h>
>> +#include "socal/alt_emac.h"
>> +#include "socal/alt_rstmgr.h"
>> +#include "socal/alt_sysmgr.h"
>> +#include "socal/hps.h"
>> +#include "socal/socal.h"
>> +#include <libchip/dwmac.h>
>> +#include "../include/nocache-heap.h" /* TODO: Convert to #include <bsp/nocache-heap.h> */
>> +
>> +/** @brief Pin mask for the interrupt from the ethernet PHY */
>> +#define NETWORK_PIN_MASK_PHY_INTERRUPT 0x00000040U
>> +
>> +/** @brief Ethernet PHY status */
>> +typedef enum {
>> +  /** @brief The ethernet PHY is off */
>> +  NETWORK_IF_PHY_STATUS_OFF,
>> +
>> +  /** @brief The ethernet PHY is on an initialized, but stopped */
>> +  NETWORK_IF_PHY_STATUS_STOPPED,
>> +
>> +  /** @brief The ethernet PHY is started and will generate requested events */
>> +  NETWORK_IF_PHY_STATUS_STARTED,
>> +
>> +  /** @brief Number of ethernet PHY statuses */
>> +  NETWORK_IF_PHY_STATUS_COUNT
>> +} network_if_phy_status;
>> +
>> +/** @brief Phy context
>> + *
>> + * ethernet PHY device context
>> + */
>> +typedef struct {
>> +  /** @brief PHY device status */
>> +  network_if_phy_status status;
>> +
>> +  /** @brief An interrupt mask which corresponds to currently requested events */
>> +  uint16_t irq_mask;
>> +} network_if_phy_context;
>> +
>> +/** @brief Phy context initializer
>> + *
>> + * @retval Initialized network PHY context
>> + */
>> +#define NETWORK_IF_PHY_CONTEXT_INITIALIZER( \
>> +    ) \
>> +  { \
>> +    NETWORK_IF_PHY_STATUS_OFF, \
>> +    0 \
>> +  }
>> +
>> +/** @brief Network interface controller ID
>> + *
>> + * Identifies the network interface controller handled by the driver
>> + */
>> +typedef enum {
>> +  /** @brief ID for EMAC0 */
>> +  NETWORK_IF_NIC_ID_EMAC0,
>> +
>> +  /** @brief ID for EMAC1 */
>> +  NETWORK_IF_NIC_ID_EMAC1,
>> +
>> +  /** @brief Number of network interface controller IDs */
>> +  NETWORK_IF_NIC_ID_COUNT
>> +} network_if_nic_id;
>> +
>> +/** @brief Network interface context
>> + *
>> + * Context for the micro controller specific part of the DWMAC 1000 n
>> + * etwork driver
>> + */
>> +typedef struct {
>> +  /** @brief Network interface controller ID */
>> +  network_if_nic_id nic_id;
>> +
>> +  /** @brief Driver context
>> +   *
>> +   * Address of the context of the low level DWMAC 1000 driver from libchip */
>> +  void *driver_context;
>> +
>> +  /** @brief Ethernet PHY context */
>> +  network_if_phy_context phy;
>> +
>> +  /* TODO: Create network context on micro controller level */
>> +} network_if_context;
>> +
>> +/** @brief Network interface context initializer
>> + *
>> + * Initializer for the context of a network interface
>> + * @param nic_id          ID of the network interface controller
>> + * @param driver_context Address of the context of the low level DWMAC 1000
>> + *                       driver from libchip
>> + * @retval Initialized network interface context
>> + */
>> +#define NETWORK_IF_CONTEXT_INITIALIZER( \
>> +    nic_id, \
>> +    driver_context \
>> +    ) \
>> +  { \
>> +    nic_id, \
>> +    driver_context, \
>> +    NETWORK_IF_PHY_CONTEXT_INITIALIZER() \
>> +  }
>> +
>> +/*********************************************************************************
>> +* Helper Methods
>> +*********************************************************************************/
>> +
>> +/** @brief Altera status code to errno
>> + *
>> + * Convert Altera status code to errno error number
>> + * @param status  Altera status code as returned by methods from Alteras HWLib
>> + * @retval Converted errno error number from errno.h
>> + */
>> +static int network_if_altera_status_code_to_errno( ALT_STATUS_CODE status )
>> +{
>> +  int eno = 0;
>> +
>> +  switch ( status ) {
>> +    /*!
>> +     * Indicates a FALSE condition.
>> +     */
>> +    case ALT_E_FALSE:
>> +
>> +    /*!
>> +     * Indicates a TRUE condition.
>> +     */
>> +    case ALT_E_TRUE:
>> +
>> +      /*! The operation was successful. */
>> +      /* case ALT_E_SUCCESS: */
>> +      eno = 0;
>> +      break;
>> +
>> +    /*! The operation failed. */
>> +    case ALT_E_ERROR:
>> +
>> +    /*! An invalid option was selected. */
>> +    case ALT_E_INV_OPTION:
>> +      eno = EIO; /* I/O error */
>> +      break;
>> +
>> +    /*! FPGA configuration error detected.*/
>> +    case ALT_E_FPGA_CFG:
>> +      eno = ECANCELED; /* Operation canceled */
>> +      break;
>> +
>> +    /*! FPGA CRC error detected. */
>> +    case ALT_E_FPGA_CRC:
>> +
>> +    /*! An error occurred on the FPGA configuration bitstream input source. */
>> +    case ALT_E_FPGA_CFG_STM:
>> +      eno = EPROTO; /* Protocol error */
>> +      break;
>> +
>> +    /*! The FPGA is powered off. */
>> +    case ALT_E_FPGA_PWR_OFF:
>> +      eno = ENODEV; /* No such device */
>> +      break;
>> +
>> +    /*! The SoC does not currently control the FPGA. */
>> +    case ALT_E_FPGA_NO_SOC_CTRL:
>> +
>> +    /*! The FPGA is not in USER mode. */
>> +    case ALT_E_FPGA_NOT_USER_MODE:
>> +      eno = EPERM; /* Not super-user */
>> +      break;
>> +
>> +    /*! An argument violates a range constraint. */
>> +    case ALT_E_ARG_RANGE:
>> +
>> +    /*! A bad argument value was passed. */
>> +    case ALT_E_BAD_ARG:
>> +
>> +    /*! The argument value is reserved or unavailable. */
>> +    case ALT_E_RESERVED:
>> +      eno = EINVAL; /* Invalid argument */
>> +      break;
>> +
>> +    /*! The operation is invalid or illegal. */
>> +    case ALT_E_BAD_OPERATION:
>> +
>> +    /*! The version ID is invalid. */
>> +    case ALT_E_BAD_VERSION:
>> +      eno = EFAULT; /* Bad address */
>> +      break;
>> +
>> +    /*! An operation or response timeout period expired. */
>> +    case ALT_E_TMO:
>> +
>> +    /*! A clock is not enabled or violates an operational constraint. */
>> +    case ALT_E_BAD_CLK:
>> +      eno = ETIME; /* Timer expired */
>> +      break;
>> +
>> +    /*! The buffer does not contain enough free space for the operation. */
>> +    case ALT_E_BUF_OVF:
>> +      eno = ENOMEM; /* Not enough core */
>> +      break;
>> +    default:
>> +
>> +      /* Unknown case. Implement it! */
>> +      assert( 0 == 1 );
>> +      eno = EIO;
>> +      break;
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/** @brief PHY check chip ID
>> + *
>> + * Check the chip-ID of the KSZ8842 ethernet PHY.
>> + * @param context Address of the network context
>> + * @retval  0 if chip could be identified, error code from errno.h otherwise.
>> + */
>> +static int network_if_phy_check_chip_id( network_if_context *context )
>> +{
>> +  int      eno;
>> +  uint16_t reg;
>> +
>> +  eno = dwmac_if_read_from_phy(
>> +    context->driver_context,
>> +    2,
>> +    &reg
>> +    );
>> +
>> +  if ( eno == 0 ) {
>> +    if ( reg != 0x0022 ) { /* PHY ID part 1 */
>> +      eno = ENXIO;
>> +    } else {
>> +      eno = dwmac_if_read_from_phy(
>> +        context->driver_context,
>> +        3,
>> +        &reg
>> +        );
>> +
>> +      if ( eno == 0 ) {
>> +        if ( ( ( reg & 0xFC00 ) >> 10 ) != 0x0005 ) { /* PHY ID part 2 */
>> +          eno = ENXIO;
>> +        } else if ( ( ( reg & 0x03F0 ) >> 4 ) != 0x0021 ) { /* Manufacturers model number */
>> +          eno = ENXIO;
>> +        }
>> +      }
>> +    }
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/*********************************************************************************
>> +* Callback Methods
>> +*********************************************************************************/
>> +
>> +/** @brief NIC enable
>> + *
>> + * Enables (powers up) the network interface card.
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +static int network_if_nic_enable( void *arg )
>> +{
>> +  int                 eno               = 0;
>> +  network_if_context *context           = (network_if_context *) arg;
>> +  ALT_CLK_t           module_clk        = ALT_CLK_EMAC0;
>> +  uint32_t            permodrst_clr_msk = ALT_RSTMGR_PERMODRST_EMAC0_CLR_MSK;
>> +
>> +  switch ( context->nic_id ) {
>> +    case NETWORK_IF_NIC_ID_EMAC0:
>> +    {
>> +      module_clk        = ALT_CLK_EMAC0;
>> +      permodrst_clr_msk = ALT_RSTMGR_PERMODRST_EMAC0_CLR_MSK;
>> +    }
>> +    break;
>> +    case NETWORK_IF_NIC_ID_EMAC1:
>> +    {
>> +      module_clk        = ALT_CLK_EMAC1;
>> +      permodrst_clr_msk = ALT_RSTMGR_PERMODRST_EMAC1_CLR_MSK;
>> +    }
>> +    break;
>> +
>> +    case NETWORK_IF_NIC_ID_COUNT:
>> +
>> +      /* Invalid case */
>> +      eno = ENODEV;
>> +      break;
>> +    default:
>> +
>> +      /* Unknown case */
>> +      eno = ENOTSUP;
>> +      break;
>> +  }
>> +
>> +  /* Pin mux configuration is handled by the Preloader. Thus no
>> +   * pin mux configuration here. */
>> +
>> +  /* Enable the clock for the EMAC module */
>> +  if ( eno == 0 ) {
>> +    if ( ALT_E_FALSE == alt_clk_is_enabled( module_clk ) ) {
>> +      ALT_STATUS_CODE status = alt_clk_clock_enable( module_clk );
>> +      eno = network_if_altera_status_code_to_errno( status );
>> +    }
>> +  }
>> +
>> +  /* Finish reset for the EMAC module */
>> +  if ( eno == 0 ) {
>> +    uint32_t reg = alt_read_word( ALT_RSTMGR_PERMODRST_ADDR );
>> +    alt_write_word( ALT_RSTMGR_PERMODRST_ADDR, reg & permodrst_clr_msk );
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/** @brief NIC disable.
>> + *
>> + * Disables (powers down) the network interface card.
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +static int network_if_nic_disable( void *arg )
>> +{
>> +  int                 eno               = 0;
>> +  network_if_context *context           = (network_if_context *) arg;
>> +  ALT_CLK_t           module_clk        = ALT_CLK_EMAC0;
>> +  uint32_t            permodrst_set_msk = ALT_RSTMGR_PERMODRST_EMAC0_SET_MSK;
>> +
>> +  switch ( context->nic_id ) {
>> +    case NETWORK_IF_NIC_ID_EMAC0:
>> +      module_clk        = ALT_CLK_EMAC0;
>> +      permodrst_set_msk = ALT_RSTMGR_PERMODRST_EMAC0_SET_MSK;
>> +      break;
>> +    case NETWORK_IF_NIC_ID_EMAC1:
>> +      module_clk        = ALT_CLK_EMAC1;
>> +      permodrst_set_msk = ALT_RSTMGR_PERMODRST_EMAC1_SET_MSK;
>> +      break;
>> +
>> +    case NETWORK_IF_NIC_ID_COUNT:
>> +
>> +      /* Invalid case */
>> +      eno = ENODEV;
>> +      break;
>> +    default:
>> +
>> +      /* Unknown case */
>> +      eno = ENOTSUP;
>> +      break;
>> +  }
>> +
>> +  /* Enter rest status for the EMAC module */
>> +  if ( eno == 0 ) {
>> +    uint32_t reg = alt_read_word( ALT_RSTMGR_PERMODRST_ADDR );
>> +    alt_write_word( ALT_RSTMGR_PERMODRST_ADDR, reg | permodrst_set_msk );
>> +  }
>> +
>> +  /* Disable the clock for the EMAC module */
>> +  if ( eno == 0 ) {
>> +    if ( ALT_E_TRUE == alt_clk_is_enabled( module_clk ) ) {
>> +      ALT_STATUS_CODE status = alt_clk_clock_disable( module_clk );
>> +      eno = network_if_altera_status_code_to_errno( status );
>> +    }
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/** @brief PHY disable.
>> + *
>> + * Disables (powers down) the network PHY.
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +static int network_if_phy_disable( void *arg )
>> +{
>> +  int                 eno  = 0;
>> +  network_if_context *self = (network_if_context *) arg;
>> +  uint32_t            mask;
>> +  ALT_STATUS_CODE     status_code;
>> +
>> +  /* The power pin of the PHY is hard wire to board power control and
>> +   * the PHY supports interrupts, This means we can not power it down
>> +   * and we don't need to stop a timer for polling PHY events. */
>> +
>> +  status_code = alt_gpio_port_int_mask_set(
>> +    ALT_GPIO_PORTB,
>> +    NETWORK_PIN_MASK_PHY_INTERRUPT,
>> +    NETWORK_PIN_MASK_PHY_INTERRUPT
>> +    );
>> +  eno = network_if_altera_status_code_to_errno( status_code );
>> +
>> +  if ( eno == 0 ) {
>> +    mask        = alt_gpio_port_int_enable_get( ALT_GPIO_PORTB );
>> +    status_code = alt_gpio_port_int_enable(
>> +      ALT_GPIO_PORTB,
>> +      mask & ~NETWORK_PIN_MASK_PHY_INTERRUPT
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    status_code = alt_gpio_port_int_status_clear(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    self->phy.status = NETWORK_IF_PHY_STATUS_OFF;
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/** @brief PHY enable.
>> + *
>> + * Enables (powers up) the network PHY.
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +static int network_if_phy_enable( void *arg )
>> +{
>> +  int                 eno  = 0;
>> +  network_if_context *self = (network_if_context *) arg;
>> +  ALT_STATUS_CODE     status_code;
>> +
>> +  /* The power pin of the PHY is hard wire to board power control and
>> +   * the PHY supports interrupts, This means we can not power it up
>> +   * and we don't need to start a timer for polling PHY events. */
>> +
>> +  eno = network_if_phy_check_chip_id( self );
>> +
>> +  if ( eno == 0 ) {
>> +    /* The phy is already enabled and we will reset it */
>> +    eno = network_if_phy_disable( self );
>> +
>> +    if ( eno == 0 ) {
>> +      rtems_task_wake_after( rtems_clock_get_ticks_per_second() / 100 );
>> +    }
>> +  } else {
>> +    eno = 0;
>> +  }
>> +
>> +  status_code = alt_gpio_port_datadir_set(
>> +    ALT_GPIO_PORTB,
>> +    NETWORK_PIN_MASK_PHY_INTERRUPT,
>> +    0
>> +    );
>> +  eno = network_if_altera_status_code_to_errno( status_code );
>> +
>> +  if ( eno == 0 ) {
>> +    status_code = alt_gpio_port_int_type_set(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT,
>> +      0
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    status_code = alt_gpio_port_int_pol_set(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT,
>> +      1
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    status_code = alt_gpio_port_debounce_set(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT,
>> +      0
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    status_code = alt_gpio_port_int_enable(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    status_code = alt_gpio_port_int_mask_set(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT,
>> +      0
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    status_code = alt_gpio_port_int_status_clear(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    self->phy.status = NETWORK_IF_PHY_STATUS_STOPPED;
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/** @brief Clear phy event status.
>> + *
>> + * Clears all PHY event statuses.
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +int network_if_phy_event_status_clear( void *arg )
>> +{
>> +  int             eno;
>> +  ALT_STATUS_CODE status_code;
>> +
>> +  (void) arg;
>> +
>> +  /* Clear the interrupt status */
>> +  status_code = alt_gpio_port_int_status_clear(
>> +    ALT_GPIO_PORTB,
>> +    NETWORK_PIN_MASK_PHY_INTERRUPT
>> +    );
>> +  eno = network_if_altera_status_code_to_errno( status_code );
>> +
>> +  if ( eno == 0 ) {
>> +    /* Unmask the interrupt (was masked within interrupt handler) */
>> +    status_code = alt_gpio_port_int_mask_set(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT,
>> +      0
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/**
>> + * @brief Get the PHY event status.
>> + *
>> + * Reports status on PHY events (e.g. PHY interrupts).
>> + * @param[in]  arg        The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @param[out] event_set  Pointer to a buffer for a set of events for which a
>> + *                        PHY status change was detected.
>> + *                        For events see @see dwmac_phy_event.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +int network_if_phy_events_status_get(
>> +  void            *arg,
>> +  dwmac_phy_event *event_set )
>> +{
>> +  int                 eno  = 0;
>> +  uint16_t            reg  = 0;
>> +  network_if_context *self = (network_if_context *) arg;
>> +
>> +  eno = dwmac_if_read_from_phy(
>> +    self->driver_context,
>> +    0x1B,
>> +    &reg
>> +    );
>> +
>> +  if ( eno == 0 ) {
>> +    if ( ( reg & 0x80 ) != 0 ) {
>> +      *event_set |= PHY_EVENT_JABBER;
>> +    }
>> +
>> +    if ( ( reg & 0x40 ) != 0 ) {
>> +      *event_set |= PHY_EVENT_RECEIVE_ERROR;
>> +    }
>> +
>> +    if ( ( reg & 0x20 ) != 0 ) {
>> +      *event_set |= PHY_EVENT_PAGE_RECEIVE;
>> +    }
>> +
>> +    if ( ( reg & 0x10 ) != 0 ) {
>> +      *event_set |= PHY_EVENT_PARALLEL_DETECT_FAULT;
>> +    }
>> +
>> +    if ( ( reg & 0x08 ) != 0 ) {
>> +      *event_set |= PHY_EVENT_LINK_PARTNER_ACK;
>> +    }
>> +
>> +    if ( ( reg & 0x04 ) != 0 ) {
>> +      *event_set |= PHY_EVENT_LINK_DOWN;
>> +    }
>> +
>> +    if ( ( reg & 0x02 ) != 0 ) {
>> +      *event_set |= PHY_EVENT_REMOTE_FAULT;
>> +    }
>> +
>> +    if ( ( reg & 0x01 ) != 0 ) {
>> +      *event_set |= PHY_EVENT_LINK_UP;
>> +    }
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/** @brief Network PHY interrupt handler
>> + *
>> + * Handling method for interrupts from the PHY.
>> + * @param arg Address of the network interface context
>> + */
>> +static void network_if_phy_interrupt_handler( void *arg )
>> +{
>> +  int                 eno  = 0;
>> +  network_if_context *self = (network_if_context *) arg;
>> +  uint32_t            reg;
>> +
>> +  reg = alt_gpio_port_int_status_get( ALT_GPIO_PORTB );
>> +
>> +  if ( reg & NETWORK_PIN_MASK_PHY_INTERRUPT ) {
>> +    /* We have a level interrupt and we expect the driver to do
>> +     * the actual interrupt handling from within a task context.
>> +     * Thus we have to mask the interrupt. A call to
>> +     * network_if_phy_event_status_clear() will unmask it */
>> +    ALT_STATUS_CODE status_code = alt_gpio_port_int_mask_set(
>> +      ALT_GPIO_PORTB,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT,
>> +      NETWORK_PIN_MASK_PHY_INTERRUPT
>> +      );
>> +    eno = network_if_altera_status_code_to_errno( status_code );
>> +
>> +    if ( eno == 0 ) {
>> +      eno = dwmac_if_handle_phy_event(
>> +        self->driver_context
>> +        );
>> +    }
>> +  }
>> +
>> +  assert( eno == 0 );
>> +}
>> +
>> +/** @brief PHY event enable.
>> + *
>> + * Enables generation of events for an event set.
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @param[in] event_set   Set of events. For these events shall get generated
>> + *                        upon PHY status change.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +static int network_if_phy_event_enable(
>> +  void                 *arg,
>> +  const dwmac_phy_event event_set )
>> +{
>> +  int                   eno        = 0;
>> +  uint16_t              reg        = 0;
>> +  network_if_context   *self       = (network_if_context *) arg;
>> +  network_if_phy_status old_status = self->phy.status;
>> +
>> +  if ( arg != NULL ) {
>> +    switch ( self->phy.status ) {
>> +      case NETWORK_IF_PHY_STATUS_OFF:
>> +        break;
>> +      case NETWORK_IF_PHY_STATUS_STOPPED:
>> +        break;
>> +      case NETWORK_IF_PHY_STATUS_STARTED:
>> +      {
>> +        eno = dwmac_if_read_from_phy(
>> +          self->driver_context,
>> +          0x1B,
>> +          &reg
>> +          );
>> +
>> +        if ( eno == 0 ) {
>> +          /* Disable all interrupts, but leave interrupt status bits untouched */
>> +          reg &= 0x00FF;
>> +          eno  = dwmac_if_write_to_phy(
>> +            self->driver_context,
>> +            0x1B,
>> +            reg
>> +            );
>> +        }
>> +
>> +        if ( eno == 0 ) {
>> +          self->phy.irq_mask = 0;
>> +          self->phy.status   = NETWORK_IF_PHY_STATUS_STOPPED;
>> +        }
>> +      }
>> +      break;
>> +      case NETWORK_IF_PHY_STATUS_COUNT:
>> +      {
>> +        /* Invalid case */
>> +        assert( self->phy.status != NETWORK_IF_PHY_STATUS_COUNT );
>> +        eno = ENOTSUP;
>> +      }
>> +      break;
>> +      default:
>> +      {
>> +        /* Unknown case */
>> +        assert(
>> +          self->phy.status == NETWORK_IF_PHY_STATUS_OFF
>> +          || self->phy.status == NETWORK_IF_PHY_STATUS_STOPPED
>> +          || self->phy.status == NETWORK_IF_PHY_STATUS_STARTED
>> +          );
>> +        eno = ENOTSUP;
>> +      }
>> +      break;
>> +    }
>> +
>> +    if ( eno == 0 ) {
>> +      /* Select interrupts to enable */
>> +      if ( ( event_set & PHY_EVENT_JABBER ) != 0 ) {
>> +        reg |= 0x8000;
>> +      }
>> +
>> +      if ( ( event_set & PHY_EVENT_RECEIVE_ERROR ) != 0 ) {
>> +        reg |= 0x4000;
>> +      }
>> +
>> +      if ( ( event_set & PHY_EVENT_PAGE_RECEIVE ) != 0 ) {
>> +        reg |= 0x2000;
>> +      }
>> +
>> +      if ( ( event_set & PHY_EVENT_PARALLEL_DETECT_FAULT ) != 0 ) {
>> +        reg |= 0x1000;
>> +      }
>> +
>> +      if ( ( event_set & PHY_EVENT_LINK_PARTNER_ACK ) != 0 ) {
>> +        reg |= 0x0800;
>> +      }
>> +
>> +      if ( ( event_set & PHY_EVENT_LINK_DOWN ) != 0 ) {
>> +        reg |= 0x0400;
>> +      }
>> +
>> +      if ( ( event_set & PHY_EVENT_REMOTE_FAULT ) != 0 ) {
>> +        reg |= 0x0200;
>> +      }
>> +
>> +      if ( ( event_set & PHY_EVENT_LINK_UP ) != 0 ) {
>> +        reg |= 0x100;
>> +      }
>> +
>> +      switch ( old_status ) {
>> +        case NETWORK_IF_PHY_STATUS_OFF:
>> +          break;
>> +        case NETWORK_IF_PHY_STATUS_STOPPED:
>> +          break;
>> +        case NETWORK_IF_PHY_STATUS_STARTED:
>> +        {
>> +          if ( eno == 0 ) {
>> +            /* Modify interrupt enable bits, but leave interrupt status bits untouched */
>> +            eno = dwmac_if_write_to_phy(
>> +              self->driver_context,
>> +              0x1B,
>> +              reg & 0xFF00
>> +              );
>> +          }
>> +        }
>> +        break;
>> +        case NETWORK_IF_PHY_STATUS_COUNT:
>> +        {
>> +          /* Invalid case */
>> +          assert( self->phy.status != NETWORK_IF_PHY_STATUS_COUNT );
>> +          eno = ENOTSUP;
>> +        }
>> +        break;
>> +        default:
>> +        {
>> +          /* Unknown case */
>> +          assert(
>> +            self->phy.status == NETWORK_IF_PHY_STATUS_OFF
>> +            || self->phy.status == NETWORK_IF_PHY_STATUS_STOPPED
>> +            || self->phy.status == NETWORK_IF_PHY_STATUS_STARTED
>> +            );
>> +          eno = ENOTSUP;
>> +        }
>> +        break;
>> +      }
>> +
>> +      if ( eno == 0 ) {
>> +        self->phy.irq_mask = reg & 0xFF00;
>> +      }
>> +    }
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/**
>> + * @brief Stop the network PHY.
>> + *
>> + * Do anything necessary to stop the network PHY (stop generating events, ...).
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +int network_if_phy_stop( void *arg )
>> +{
>> +  int                 eno  = 0;
>> +  rtems_status_code   sc   = RTEMS_SUCCESSFUL;
>> +  network_if_context *self = (network_if_context *) arg;
>> +
>> +  switch ( self->phy.status ) {
>> +    case NETWORK_IF_PHY_STATUS_OFF:
>> +      break;
>> +    case NETWORK_IF_PHY_STATUS_STOPPED:
>> +      break;
>> +    case NETWORK_IF_PHY_STATUS_STARTED:
>> +    {
>> +      /* Remove any selected interrupts */
>> +      eno = dwmac_if_write_to_phy(
>> +        self->driver_context,
>> +        0x1B,
>> +        0
>> +        );
>> +
>> +      if ( eno == 0 ) {
>> +        uint16_t reg;
>> +
>> +        /* Clear interrupt status bits by reading them */
>> +        eno = dwmac_if_read_from_phy(
>> +          self->driver_context,
>> +          0x1B,
>> +          &reg
>> +          );
>> +      }
>> +
>> +      if ( eno == 0 ) {
>> +        self->phy.irq_mask = 0;
>> +
>> +        /* Remove interrupt handler */
>> +        sc = rtems_interrupt_handler_remove(
>> +          ALT_INT_INTERRUPT_GPIO1,
>> +          network_if_phy_interrupt_handler,
>> +          self
>> +          );
>> +        eno = rtems_status_code_to_errno( sc );
>> +
>> +        if ( eno == 0 ) {
>> +          self->phy.status = NETWORK_IF_PHY_STATUS_STOPPED;
>> +        }
>> +      }
>> +    }
>> +    break;
>> +    case NETWORK_IF_PHY_STATUS_COUNT:
>> +    {
>> +      /* Invalid case */
>> +      assert( self->phy.status != NETWORK_IF_PHY_STATUS_COUNT );
>> +      eno = ENOTSUP;
>> +    }
>> +    break;
>> +    default:
>> +    {
>> +      /* Unknown case */
>> +      assert(
>> +        self->phy.status == NETWORK_IF_PHY_STATUS_OFF
>> +        || self->phy.status == NETWORK_IF_PHY_STATUS_STOPPED
>> +        || self->phy.status == NETWORK_IF_PHY_STATUS_STARTED
>> +        );
>> +      eno = ENOTSUP;
>> +    }
>> +    break;
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/**
>> + * @brief Start the network PHY.
>> + *
>> + * Do anything necessary to start the network PHY (start generating
>> + * events, ...).
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +int network_if_phy_start( void *arg )
>> +{
>> +  int                 eno  = 0;
>> +  rtems_status_code   sc   = RTEMS_SUCCESSFUL;
>> +  network_if_context *self = (network_if_context *) arg;
>> +
>> +  switch ( self->phy.status ) {
>> +    case NETWORK_IF_PHY_STATUS_OFF:
>> +    {
>> +      assert( self->phy.status != NETWORK_IF_PHY_STATUS_OFF );
>> +      eno = EHOSTDOWN;
>> +    }
>> +    break;
>> +    case NETWORK_IF_PHY_STATUS_STOPPED:
>> +
>> +      /* Disable all interrupts */
>> +      eno = dwmac_if_write_to_phy(
>> +        self->driver_context,
>> +        0x1B,
>> +        0
>> +        );
>> +
>> +      if ( eno == 0 ) {
>> +      }
>> +
>> +      if ( eno == 0 ) {
>> +        /* Install interrupt handler */
>> +        sc = rtems_interrupt_handler_install(
>> +          ALT_INT_INTERRUPT_GPIO1,
>> +          NULL,
>> +          RTEMS_INTERRUPT_SHARED,
>> +          network_if_phy_interrupt_handler,
>> +          self
>> +          );
>> +        eno = rtems_status_code_to_errno( sc );
>> +      }
>> +
>> +      if ( eno == 0 ) {
>> +        /* Enable interrupts */
>> +        eno = dwmac_if_write_to_phy(
>> +          self->driver_context,
>> +          0x1B,
>> +          self->phy.irq_mask
>> +          );
>> +      }
>> +
>> +      break;
>> +    case NETWORK_IF_PHY_STATUS_STARTED:
>> +    {
>> +      uint16_t irq_mask = self->phy.irq_mask;
>> +
>> +      /* Re-start the phy */
>> +      eno = network_if_phy_stop( self );
>> +
>> +      if ( eno == 0 ) {
>> +        self->phy.irq_mask = irq_mask;
>> +
>> +        eno                = network_if_phy_start(
>> +          self
>> +          );
>> +      }
>> +    }
>> +    break;
>> +
>> +    case NETWORK_IF_PHY_STATUS_COUNT:
>> +    {
>> +      /* Invalid case */
>> +      assert( self->phy.status != NETWORK_IF_PHY_STATUS_COUNT );
>> +      eno = ENOTSUP;
>> +    }
>> +    break;
>> +    default:
>> +    {
>> +      /* Unknown case */
>> +      assert(
>> +        self->phy.status == NETWORK_IF_PHY_STATUS_OFF
>> +        || self->phy.status == NETWORK_IF_PHY_STATUS_STOPPED
>> +        || self->phy.status == NETWORK_IF_PHY_STATUS_STARTED
>> +        );
>> +      eno = ENOTSUP;
>> +    }
>> +    break;
>> +  }
>> +
>> +  if ( eno == 0 ) {
>> +    self->phy.status = NETWORK_IF_PHY_STATUS_STARTED;
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/**
>> + * @brief Allocate nocache RAM.
>> + *
>> + * Allocate uncached RAM.
>> + * @param[in]  arg        The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @param[out] memory     Pointer of a buffer to write the address of the
>> + *                        allocated memory to.
>> + * @param[in]  size       Number of bytes to be allocated
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +int network_if_mem_alloc_nocache(
>> +  void        *arg,
>> +  void       **memory,
>> +  const size_t size )
>> +{
>> +  int eno = EINVAL;
>> +
>> +  (void) arg;
>> +
>> +  assert( memory != NULL );
>> +
>> +  if ( memory != NULL ) {
>> +    *memory = nocache_malloc( size );
>> +
>> +    if ( *memory != NULL ) {
>> +      eno = 0;
>> +    } else {
>> +      eno = ENOMEM;
>> +    }
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/**
>> + * @brief Free nocache RAM.
>> + *
>> + * Release uncached RAM.
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @param[in] memory      Pointer to the memory to be freed.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +int network_if_mem_free_nocache(
>> +  void *arg,
>> +  void *memory )
>> +{
>> +  int eno = EINVAL;
>> +
>> +  (void) arg;
>> +
>> +  assert( memory != NULL );
>> +
>> +  if ( memory != NULL ) {
>> +    nocache_free( memory );
>> +    eno = 0;
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/**
>> + * @brief Bus setup.
>> + *
>> + * Callback method for setting up the system bus for the network driver.
>> + * @param[in] arg         The void pointer argument passed to
>> + *                        dwmac_network_if_attach_detach.
>> + * @retval 0 on success, error code from errno.h on failure.
>> + */
>> +int network_if_bus_setup( void *arg )
>> +{
>> +  (void) arg;
>> +
>> +  /* Nothing to be done */
>> +  return 0;
>> +}
>> +
>> +/*********************************************************************************
>> +* Context Data
>> +*********************************************************************************/
>> +
>> +/** @brief Network interface context */
>> +static network_if_context context = NETWORK_IF_CONTEXT_INITIALIZER(
>> +
>> +  /** @brief Use EMAC1 */
>> +  NETWORK_IF_NIC_ID_EMAC1,
>> +
>> +  /** @brief Address of driver context
>> +   *
>> +   * To be assigned with return value of dwmac_network_if_attach_detach */
>> +  NULL
>> +  );
>> +
>> +/** @brief Network driver DMA configuration data */
>> +static const dwmac_dma_cfg NETWORK_DMA_CFG = DWMAC_DMA_CFG_INITIALIZER(
>> +
>> +  /** @brief Bus mode burst length */
>> +  DWMAC_DMA_CFG_BUS_MODE_BURST_LENGTH_64,
>> +
>> +  /** @brief Bus mode fixed burst? */
>> +  DWMAC_DMA_CFG_BUS_MODE_BURST_MODE_SINGLE_OR_INCR,
>> +
>> +  /** @brief Bus mode mixed burst? */
>> +  DWMAC_DMA_CFG_BUS_MODE_BURST_NOT_MIXED,
>> +
>> +  /** @brief Permit AXI burst length of 4 */
>> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_4_NOT_SUPPORTED,
>> +
>> +  /** @brief Permit AXI burst length of 8 */
>> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_8_NOT_SUPPORTED,
>> +
>> +  /** @brief Permit AXI burst length of 16 */
>> +  DWMAC_DMA_CFG_AXI_BURST_LENGTH_16_NOT_SUPPORTED,
>> +
>> +  /** @brief Select boundary crossing mode */
>> +  DWMAC_DMA_CFG_AXI_BURST_BOUNDARY_4_KB
>> +  );
>> +
>> +/** @brief Network driver configuration data */
>> +static const dwmac_cfg NETWORK_DRIVER_CFG = DWMAC_CFG_INITIALIZER(
>> +
>> +  /** @brief GMII clock rate */
>> +  75000000,
>> +
>> +  /** @brief Address of the GMAC registers for emac1 */
>> +  ALT_EMAC1_GMACGRP_ADDR,
>> +
>> +  /** @brief Address of the DMA registers for emac1 */
>> +  ALT_EMAC1_DMAGRP_ADDR,
>> +
>> +  /** @brief Address of the PHY on the mdio bus */
>> +  4,
>> +
>> +  /** @brief Bytes per L1 cache line */
>> +  32,
>> +
>> +  /** @brief Interrupt number for the EMAC */
>> +  ALT_INT_INTERRUPT_EMAC1_IRQ,
>> +
>> +  /** @brief Set to true if prefetching into cache via PLD is supported */
>> +  false,
>> +
>> +  /** @brief DMA configuration */
>> +  &NETWORK_DMA_CFG,
>> +
>> +  /** @brief Callback method for enabling the network controller */
>> +  network_if_nic_enable,
>> +
>> +  /** @brief Callback method for disabling the network controller */
>> +  network_if_nic_disable,
>> +
>> +  /** @brief Callback method for enabling the PHY */
>> +  network_if_phy_enable,
>> +
>> +  /** @brief Callback method for disabling the PHY */
>> +  network_if_phy_disable,
>> +
>> +  /** @brief Callback which enables PHY events for forwarding to driver */
>> +  network_if_phy_event_enable,
>> +
>> +  /** @brief Callback method for clearing PHY interrupt status */
>> +  network_if_phy_event_status_clear,
>> +
>> +  /** @brief Callback method for getting a set of events from the PHY */
>> +  network_if_phy_events_status_get,
>> +
>> +  /** @brief Callback method for making the PHY start forwarding events */
>> +  network_if_phy_start,
>> +
>> +  /** @brief Callback method for making the PHY stop forwarding events */
>> +  network_if_phy_stop,
>> +
>> +  /** @brief Callback method for allocating uncached memory */
>> +  network_if_mem_alloc_nocache,
>> +
>> +  /** @brief Callback method for freeing uncached memory */
>> +  network_if_mem_free_nocache,
>> +
>> +  /** @brief Callback method for setting up bus upon driver startup */
>> +  network_if_bus_setup,
>> +
>> +  /** @brief Operations for the ethernet mac 1000 */
>> +  &DWMAC_1000_ETHERNET_MAC_OPS,
>> +
>> +  /** @brief Operations for the enhanced DMA descriptors */
>> +  &DWMAC_DESCRIPTOR_OPS_ENHANCED
>> +  );
>> +
>> +/*********************************************************************************
>> +* API
>> +*********************************************************************************/
>> +
>> +/** @brief Network interface attach/detach
>> + *
>> + * The standard attach/detach method for network interfaces.
>> + * This methods will call the DWMAC 1000 attach/detach method and pass
>> + * configuration data and callback methods into it. Via these  the general
>> + * DWMAC 1000 driver is able the handle micro controller specific things.
>> + * NOTE: Detaching is NOT supported!
>> + * @param config    Configuration parameters from and for the BSD network stack.
>> + * @param attaching True if attaching the driver to the network stack, false if.
>> + *                  detaching
>> + * @retval 0 if successful, error code from errno.h if not.
>> + */
>> +int network_if_attach_detach(
>> +  struct rtems_bsdnet_ifconfig *config,
>> +  int                           attaching )
>> +{
>> +  int eno = 0;
>> +
>> +  assert( config != NULL );
>> +
>> +  /* Network controller initialization */
>> +  context.driver_context = dwmac_network_if_attach_detach(
>> +    config,
>> +    &NETWORK_DRIVER_CFG,
>> +    &context,
>> +    attaching
>> +    );
>> +
>> +  if ( context.driver_context == NULL ) {
>> +    eno = EFAULT;
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +#endif /* defined(RTEMS_NETWORKING) */
>> \ No newline at end of file
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am b/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am
>> index d59525a..5d4fd83 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am
>> @@ -86,6 +86,10 @@ $(PROJECT_INCLUDE)/bsp/start.h: ../shared/include/start.h $(PROJECT_INCLUDE)/bsp
>>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/start.h
>>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/start.h
>>
>> +$(PROJECT_INCLUDE)/bsp/arm-a9mpcore-clock.h: ../shared/include/arm-a9mpcore-clock.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>> +       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-clock.h
>> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-clock.h
>> +
>>  $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-irq.h: ../shared/include/arm-a9mpcore-irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-irq.h
>>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-a9mpcore-irq.h
>> @@ -102,6 +106,10 @@ $(PROJECT_INCLUDE)/bsp/arm-cp15-start.h: ../shared/include/arm-cp15-start.h $(PR
>>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-cp15-start.h
>>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-cp15-start.h
>>
>> +$(PROJECT_INCLUDE)/bsp/arm-errata.h: ../shared/include/arm-errata.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>> +       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-errata.h
>> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-errata.h
>> +
>>  $(PROJECT_INCLUDE)/bsp/arm-gic.h: ../shared/include/arm-gic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-gic.h
>>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-gic.h
>> @@ -118,10 +126,22 @@ $(PROJECT_INCLUDE)/bsp/arm-gic-tm27.h: ../shared/include/arm-gic-tm27.h $(PROJEC
>>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-gic-tm27.h
>>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-gic-tm27.h
>>
>> +$(PROJECT_INCLUDE)/bsp/arm-release-id.h: ../shared/include/arm-release-id.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>> +       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/arm-release-id.h
>> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/arm-release-id.h
>> +
>>  $(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
>>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
>>
>> +$(PROJECT_INCLUDE)/bsp/network.h: include/network.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>> +       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/network.h
>> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/network.h
>> +
>> +$(PROJECT_INCLUDE)/bsp/nocache-heap.h: include/nocache-heap.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>> +       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/nocache-heap.h
>> +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/nocache-heap.h
>> +
>>  $(PROJECT_INCLUDE)/bsp/alt_16550_uart.h: hwlib/include/alt_16550_uart.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
>>         $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_16550_uart.h
>>  PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_16550_uart.h
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspreset.c b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspreset.c
>> index 658f870..6a60db7 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspreset.c
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspreset.c
>> @@ -13,14 +13,10 @@
>>   */
>>
>>  #include <bsp/bootcard.h>
>> +#include <bsp/alt_reset_manager.h>
>>
>>  void bsp_reset(void)
>>  {
>> -  volatile uint32_t *slcr_unlock = (volatile uint32_t *) 0xf8000008;
>> -  volatile uint32_t *pss_rst_ctrl = (volatile uint32_t *) 0xf8000200;
>> -
>> -  while (true) {
>> -    *slcr_unlock = 0xdf0d;
>> -    *pss_rst_ctrl = 0x1;
>> -  }
>> +  /* Simply call the reset method from alteras HWLIB */
>> +  (void) alt_reset_cold_reset();
>>  }
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstart.c b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstart.c
>> index 40459bb..58f38b9 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstart.c
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstart.c
>> @@ -12,16 +12,120 @@
>>   * http://www.rtems.com/license/LICENSE.
>>   */
>>
>> +/*#define DEBUG_ECC_ERROR*/  /* TODO: Delete DEBUG_ECC_ERROR after implementation phase */
>> +
>> +#include <assert.h>
>> +#include <stdint.h>
>>  #include <bsp.h>
>>  #include <bsp/bootcard.h>
>>  #include <bsp/irq-generic.h>
>> +#include <bsp/alt_interrupt_common.h>
>> +#include <bsp/linker-symbols.h>
>> +#include <bsp/start.h>
>> +#include <rtems/config.h>
>> +#include <socal/alt_rstmgr.h>
>> +#include <socal/alt_sysmgr.h>
>> +#include <socal/hps.h>
>> +#ifdef DEBUG_ECC_ERROR
>> +  #include <rtems/irq-extension.h>
>> +  #include <socal/socal.h>
>> +  #include <socal/alt_sdr.h>
>> +#endif /* DEBUG_ECC_ERROR */
>> +
>> +#ifndef MIN
>> +#define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
>> +#endif
>>
>> -void altcycv_fatal(altcycv_fatal_code code)
>> +#ifdef DEBUG_ECC_ERROR
>> +static void irq_handler_ddr_ecc_error( void *arg )
>>  {
>> -  rtems_fatal(RTEMS_FATAL_SOURCE_BSP_SPECIFIC, code);
>> +  (void) arg;
>> +  uint32_t cal_success                      =
>> +    ALT_SDR_CTL_DRAMSTS_CALSUCCESS_GET(
>> +      *( (uint32_t *) ALT_SDR_CTL_DRAMSTS_ADDR ) );
>> +  uint32_t          cal_fail                = ALT_SDR_CTL_DRAMSTS_CALFAIL_GET(
>> +    *( (uint32_t *) ALT_SDR_CTL_DRAMSTS_ADDR ) );
>> +  uint32_t          single_bit_error        =
>> +    ALT_SDR_CTL_DRAMSTS_SBEERR_GET( *( (uint32_t *) ALT_SDR_CTL_DRAMSTS_ADDR ) );
>> +  uint32_t          double_bit_error        =
>> +    ALT_SDR_CTL_DRAMSTS_DBEERR_GET( *( (uint32_t *) ALT_SDR_CTL_DRAMSTS_ADDR ) );
>> +  uint32_t          auto_correction_dropped = ALT_SDR_CTL_DRAMSTS_CORRDROP_GET(
>> +    *( (uint32_t *) ALT_SDR_CTL_DRAMSTS_ADDR ) );
>> +  volatile uint32_t erraddr                 =
>> +    ALT_SDR_CTL_ERRADDR_ADDR_GET(
>> +      *(volatile uint32_t *) ALT_SDR_CTL_ERRADDR_ADDR );
>> +
>> +  /* Simply avoid a compiler warning */
>> +  ++cal_success;
>> +  ++cal_fail;
>> +  ++single_bit_error;
>> +  ++double_bit_error;
>> +  ++auto_correction_dropped;
>> +  ++erraddr;
>> +
>> +  alt_setbits_word( ALT_SDR_CTL_DRAMINTR_ADDR,
>> +                    ALT_SDR_CTL_DRAMINTR_INTRCLR_SET_MSK );
>>  }
>>
>> -void bsp_start(void)
>> +static void setup_ecc_interrupt( void )
>>  {
>> -  bsp_interrupt_initialize();
>> +  rtems_status_code sc = rtems_interrupt_handler_install(
>> +    ALT_INT_INTERRUPT_DDR_ECC_ERROR_IRQ,
>> +    NULL,
>> +    RTEMS_INTERRUPT_UNIQUE,
>> +    irq_handler_ddr_ecc_error,
>> +    NULL
>> +    );
>> +
>> +
>> +  assert( sc == RTEMS_SUCCESSFUL );
>>  }
>> +
>> +#else
>> +  #define setup_ecc_interrupt()
>> +#endif /* DEBUG_ECC_ERROR */
>> +
>> +static unsigned int bspstart_cores_started = 1;
>> +
>> +#ifdef RTEMS_SMP
>> +static void bsp_start_secondary_cores( void )
>> +{
>> +  volatile uint32_t *mpumodrst       = ALT_RSTMGR_MPUMODRST_ADDR;
>> +  uint32_t          *cpu1_start_addr = (
>> +    ALT_SYSMGR_ROMCODE_ADDR + ALT_SYSMGR_ROMCODE_CPU1STARTADDR_OFST );
>> +  const uint32_t     CORES           = MIN(
>> +    (uintptr_t) bsp_processor_count,
>> +    rtems_configuration_get_maximum_processors() );
>> +  unsigned int       index;
>> +
>> +
>> +  /* Memory would get overwritten if a too small processor count
>> +   * would be specified */
>> +  assert( (uintptr_t) bsp_processor_count >= BSP_ARM_MAX_CORES_PER_CONTROLLER );
>> +
>> +  if ( (uintptr_t) bsp_processor_count >= BSP_ARM_MAX_CORES_PER_CONTROLLER
>> +       && bspstart_cores_started < CORES ) {
>> +    for ( index = 1; index < CORES; ++index ) {
>> +      /* set the start address from where the core will execute */
>> +      (*cpu1_start_addr) = ALT_SYSMGR_ROMCODE_CPU1STARTADDR_VALUE_SET(
>> +        (uintptr_t) _start );
>> +
>> +      /* Make the core finish it's reset */
>> +      (*mpumodrst) &= ~ALT_RSTMGR_MPUMODRST_CPU1_SET_MSK;
>> +      ++bspstart_cores_started;
>> +    }
>> +  }
>> +}
>> +
>> +#else
>> +
>> +/* Nothing to be done */
>> +  #define bsp_start_secondary_cores()
>> +#endif /* #ifdef RTEMS_SMP */
>> +
>> +void bsp_start( void )
>> +{
>> +  bsp_interrupt_initialize();
>> +  setup_ecc_interrupt();
>> +  bsp_start_secondary_cores();
>> +}
>> \ No newline at end of file
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstarthooks.c b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstarthooks.c
>> index 9831084..dd3821b 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstarthooks.c
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/bspstarthooks.c
>> @@ -17,6 +17,13 @@
>>  #include <bsp/arm-cp15-start.h>
>>  #include <bsp/arm-a9mpcore-start.h>
>>  #include <bsp/linker-symbols.h>
>> +#include <socal/alt_sdr.h>
>> +#include <alt_address_space.h>
>> +#include <socal/socal.h>
>> +#include <socal/hps.h>
>> +#include "../include/arm-cache-l1.h"
>> +
>> +/*#define DEBUG_ECC_ERROR*/ /* TODO: Delete DEBUG_ECC_ERROR after the implementation phase */
>>
>>  #ifdef RTEMS_SMP
>>    #define MMU_DATA_READ_WRITE ARMV7_MMU_DATA_READ_WRITE_SHAREABLE
>> @@ -24,84 +31,178 @@
>>    #define MMU_DATA_READ_WRITE ARMV7_MMU_DATA_READ_WRITE_CACHED
>>  #endif
>>
>> +/* 1 MB reset default value for address filtering start */
>> +#define BSPSTART_L2_CACHE_ADDR_FILTERING_START_RESET 0x100000
>> +
>> +#ifndef BSPSTARTHOOKS_MIN
>> +#define BSPSTARTHOOKS_MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
>> +#endif
>> +
>> +LINKER_SYMBOL( bsp_section_nocache_size );
>> +LINKER_SYMBOL( bsp_section_nocache_end );
>> +LINKER_SYMBOL( bsp_section_nocache_begin );
>> +
>>  BSP_START_DATA_SECTION static const arm_cp15_start_section_config
>> -altcycv_mmu_config_table[] = {
>> +  altcycv_mmu_config_table[] = {
>> +  ARMV7_CP15_START_DEFAULT_SECTIONS,
>>    {
>> -    .begin = (uint32_t) bsp_section_fast_text_begin,
>> -    .end = (uint32_t) bsp_section_fast_text_end,
>> -    .flags = ARMV7_MMU_CODE_CACHED
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_fast_data_begin,
>> -    .end = (uint32_t) bsp_section_fast_data_end,
>> -    .flags = MMU_DATA_READ_WRITE
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_start_begin,
>> -    .end = (uint32_t) bsp_section_start_end,
>> -    .flags = ARMV7_MMU_CODE_CACHED
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_vector_begin,
>> -    .end = (uint32_t) bsp_section_vector_end,
>> -    .flags = MMU_DATA_READ_WRITE
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_text_begin,
>> -    .end = (uint32_t) bsp_section_text_end,
>> -    .flags = ARMV7_MMU_CODE_CACHED
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_rodata_begin,
>> -    .end = (uint32_t) bsp_section_rodata_end,
>> -    .flags = ARMV7_MMU_DATA_READ_ONLY_CACHED
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_data_begin,
>> -    .end = (uint32_t) bsp_section_data_end,
>> -    .flags = MMU_DATA_READ_WRITE
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_bss_begin,
>> -    .end = (uint32_t) bsp_section_bss_end,
>> -    .flags = MMU_DATA_READ_WRITE
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_work_begin,
>> -    .end = (uint32_t) bsp_section_work_end,
>> -    .flags = MMU_DATA_READ_WRITE
>> -  }, {
>> -    .begin = (uint32_t) bsp_section_stack_begin,
>> -    .end = (uint32_t) bsp_section_stack_end,
>> -    .flags = MMU_DATA_READ_WRITE
>> -  }, {
>> -    .begin = 0xe0000000U,
>> -    .end = 0xe0200000U,
>> -    .flags = ARMV7_MMU_DEVICE
>> -  }, {
>> -    .begin = 0xf8000000U,
>> -    .end = 0xf9000000U,
>> +    .begin = (uint32_t) bsp_section_nocache_begin,
>> +    .end   = (uint32_t) bsp_section_nocache_end,
>> +
>> +    .flags = ARMV7_MMU_DATA_READ_WRITE | ARM_MMU_SECT_TEX_0
>> +  }, { /* Periphery area */
>> +    .begin = 0xFC000000U,
>> +    .end   = 0x00000000U,
>>      .flags = ARMV7_MMU_DEVICE
>>    }
>>  };
>>
>> -BSP_START_TEXT_SECTION static void setup_mmu_and_cache(void)
>> +BSP_START_TEXT_SECTION static void setup_mmu_and_cache( const uint32_t CPU_ID )
>>  {
>> -  uint32_t ctrl = arm_cp15_start_setup_mmu_and_cache(
>> -    ARM_CP15_CTRL_A,
>> -    ARM_CP15_CTRL_AFE | ARM_CP15_CTRL_Z
>> -  );
>> -
>> -  arm_cp15_start_setup_translation_table_and_enable_mmu_and_cache(
>> -    ctrl,
>> -    (uint32_t *) bsp_translation_table_base,
>> -    ARM_MMU_DEFAULT_CLIENT_DOMAIN,
>> -    &altcycv_mmu_config_table[0],
>> -    RTEMS_ARRAY_SIZE(altcycv_mmu_config_table)
>> -  );
>> +  uint32_t       ctrl  = arm_cp15_get_control();
>> +  const uint32_t CORES = BSPSTARTHOOKS_MIN(
>> +    (uintptr_t) bsp_processor_count,
>> +    rtems_configuration_get_maximum_processors() );
>> +
>> +  /* We expect the L1 caches and program flow prediction to be off */
>> +  assert( ( ctrl & ARM_CP15_CTRL_I ) == 0 );
>> +  assert( ( ctrl & ARM_CP15_CTRL_C ) == 0 );
>> +  assert( ( ctrl & ARM_CP15_CTRL_Z ) == 0 );
>> +
>> +  ctrl = arm_cp15_start_setup_mmu_and_cache(
>> +    ARM_CP15_CTRL_A | ARM_CP15_CTRL_M,
>> +    ARM_CP15_CTRL_AFE
>> +    );
>> +
>> +  if( CPU_ID == 0 ) {
>> +    arm_cp15_start_setup_translation_table(
>> +      (uint32_t *) bsp_translation_table_base,
>> +      ARM_MMU_DEFAULT_CLIENT_DOMAIN,
>> +      &altcycv_mmu_config_table[0],
>> +      RTEMS_ARRAY_SIZE( altcycv_mmu_config_table )
>> +    );
>> +  } else {
>> +    /* FIXME: Sharing the translation table between processors is brittle */
>> +    arm_cp15_set_translation_table_base((uint32_t *) bsp_translation_table_base);
>> +  }
>> +
>> +  /* Enable MMU */
>> +  ctrl |= ARM_CP15_CTRL_M;
>> +
>> +  arm_cp15_set_control( ctrl );
>> +
>> +  if( CPU_ID == (CORES - 1) ) {
>> +    /* Enable all cache levels for the last core */
>> +    rtems_cache_enable_instruction();
>> +    rtems_cache_enable_data();
>> +  } else {
>> +    /* Enable only L1 cache */
>> +    arm_cache_l1_enable_data();
>> +    arm_cache_l1_enable_instruction();
>> +  }
>> +
>> +  /* Enable flow control prediction aka. branch prediction */
>> +
>> +/* TODO: With the current network stack 06-Feb2014 in_checksum()
>> + * becomes a severe performance bottle neck with branch prediction enabled
>> +   ctrl |= ARM_CP15_CTRL_Z;
>> +   arm_cp15_set_control(ctrl);*/
>>  }
>>
>> -BSP_START_TEXT_SECTION void bsp_start_hook_0(void)
>> +BSP_START_TEXT_SECTION void bsp_start_hook_0( void )
>>  {
>> -  arm_a9mpcore_start_hook_0();
>> +  uint32_t ctrl;
>> +  volatile a9mpcore_scu *scu    = (volatile a9mpcore_scu *) BSP_ARM_A9MPCORE_SCU_BASE;
>> +  uint32_t               cpu_id = arm_cortex_a9_get_multiprocessor_cpu_id();
>> +  const uint32_t         CORES  = BSPSTARTHOOKS_MIN(
>> +    (uintptr_t) bsp_processor_count,
>> +    rtems_configuration_get_maximum_processors() );
>> +
>> +  assert( cpu_id < CORES );
>> +
>> +  if( cpu_id < CORES ) {
>> +
>> +    (void)arm_cp15_mmu_disable( 32 );
>> +
>> +    ctrl = arm_cp15_get_control();
>> +    ctrl &= ~( ARM_CP15_CTRL_I | ARM_CP15_CTRL_C | ARM_CP15_CTRL_Z );
>> +    arm_cp15_set_control( ctrl );
>> +
>> +    if( cpu_id == 0 ) {
>> +      /* Enable Snoop Control Unit (SCU) */
>> +      arm_a9mpcore_start_scu_enable( scu );
>> +    }
>> +
>> +#ifdef RTEMS_SMP
>> +    /* Enable cache coherency support for this processor */
>> +    uint32_t actlr = arm_cp15_get_auxiliary_control();
>> +    actlr |= ARM_CORTEX_A9_ACTL_SMP;
>> +    arm_cp15_set_auxiliary_control(actlr);
>> +#endif
>> +
>> +    if (cpu_id == 0) {
>> +      arm_a9mpcore_start_scu_invalidate(cpu_id, 0xF);
>> +    }
>> +
>> +    setup_mmu_and_cache( cpu_id );
>> +
>> +#ifdef RTEMS_SMP
>> +    if (cpu_id != 0) {
>> +      arm_a9mpcore_start_set_vector_base();
>> +
>> +      arm_gic_irq_initialize_secondary_cpu();
>> +
>> +      arm_cp15_set_domain_access_control(
>> +        ARM_CP15_DAC_DOMAIN(ARM_MMU_DEFAULT_CLIENT_DOMAIN, ARM_CP15_DAC_CLIENT)
>> +      );
>> +      _SMP_Start_multitasking_on_secondary_processor();
>> +    }
>> +#endif
>> +  } else {
>> +    /* FIXME: Shutdown processor */
>> +    while (1) {
>> +      __asm__ volatile ("wfi");
>> +    }
>> +  }
>>  }
>>
>> -BSP_START_TEXT_SECTION void bsp_start_hook_1(void)
>> +BSP_START_TEXT_SECTION void bsp_start_hook_1( void )
>>  {
>> +  uint32_t addr_filt_start;
>> +  uint32_t addr_filt_end;
>> +
>> +
>> +#ifndef DEBUG_ECC_ERROR
>> +
>> +  /* FIXME: Disable ECC. Preloader respectively UBoot enable ECC.
>> +     But they do run without interrupts. Our BSP will enable interrupts
>> +     and get spurious ECC error interrupts. Thus we disasable ECC
>> +     until we either know about a better handling or Altera has modified
>> +     it's SDRAM settings to not create possibly false ECC errors */
>> +  uint32_t ctlcfg = alt_read_word( ALT_SDR_CTL_CTLCFG_ADDR );
>> +  ctlcfg &= ALT_SDR_CTL_CTLCFG_ECCEN_CLR_MSK;
>> +  alt_write_word( ALT_SDR_CTL_CTLCFG_ADDR, ctlcfg );
>> +#endif
>> +
>> +  /* Perform L3 remap register programming first by setting the desired new MPU
>> +     address space 0 mapping. Assume BOOTROM in order to be able to boot the second core. */
>> +  alt_addr_space_remap(
>> +    ALT_ADDR_SPACE_MPU_ZERO_AT_BOOTROM,
>> +    ALT_ADDR_SPACE_NONMPU_ZERO_AT_SDRAM,
>> +    ALT_ADDR_SPACE_H2F_ACCESSIBLE,
>> +    ALT_ADDR_SPACE_LWH2F_ACCESSIBLE );
>> +
>> +  /* Next, adjust the L2 cache address filtering range. Set the start address to
>> +     the default reset value and retain the existing end address configuration. */
>> +  alt_l2_addr_filter_cfg_get( &addr_filt_start, &addr_filt_end );
>> +
>> +  if ( addr_filt_start != BSPSTART_L2_CACHE_ADDR_FILTERING_START_RESET ) {
>> +    alt_l2_addr_filter_cfg_set( BSPSTART_L2_CACHE_ADDR_FILTERING_START_RESET,
>> +                                addr_filt_end );
>> +  }
>> +
>>    arm_a9mpcore_start_hook_1();
>>    bsp_start_copy_sections();
>> -  setup_mmu_and_cache();
>> +
>>    bsp_start_clear_bss();
>> -}
>> +}
>> \ No newline at end of file
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit
>> index 2bb0f82..60f99a0 100644
>> --- a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/linkcmds.altcycv_devkit
>> @@ -1,6 +1,18 @@
>>  MEMORY {
>> -   RAM_MMU   : ORIGIN = 0x00100000, LENGTH = 16k
>> -   RAM       : ORIGIN = 0x00104000, LENGTH = 512M - 1M - 16k
>> +   RAM_MMU : ORIGIN = 0x00100000, LENGTH = 16k
>> +   NOCACHE : ORIGIN = 0x00200000, LENGTH = 1M
>> +   RAM     : ORIGIN = 0x00300000, LENGTH = 1024M - 1M - 1M - 1M
>> +}
>> +
>> +SECTIONS {
>> +  .nocache : {
>> +    bsp_section_nocache_begin = .;
>> +    *(SORT(.bsp_nocache*))
>> +    bsp_section_nocache_end = .;
>> +  } > NOCACHE AT > NOCACHE
>> +  bsp_section_nocache_size = bsp_section_nocache_end - bsp_section_nocache_begin;
>> +  bsp_section_nocache_load_begin = LOADADDR (.nocache);
>> +  bsp_section_nocache_load_end = bsp_section_nocache_load_begin + bsp_section_nocache_size;
>>  }
>>
>>  INCLUDE linkcmds.altcycv
>> diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/startup/nocache-heap.c b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/nocache-heap.c
>> new file mode 100644
>> index 0000000..0c5e526
>> --- /dev/null
>> +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/startup/nocache-heap.c
>> @@ -0,0 +1,87 @@
>> +/**
>> + * @file nocache-heap.c
>> + *
>> + * @ingroup [GROUP NAME]
>> + *
>> + * @brief Heap handling for uncached RAM
>> + */
>> +
>> +/*
>> + * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
>> + *
>> + *  embedded brains GmbH
>> + *  Dornierstr. 4
>> + *  82178 Puchheim
>> + *  Germany
>> + *  <rtems at embedded-brains.de>
>> + *
>> + * The license and distribution terms for this file may be
>> + * found in the file LICENSE in this distribution or at
>> + * http://www.rtems.org/license/LICENSE.
>> + */
>> +
>> +#include <assert.h>
>> +#include <errno.h>
>> +#include <bsp/linker-symbols.h>
>> +#include "../include/nocache-heap.h" /* TODO: Convert to #include <bsp/nocache-heap.h> */
>> +#include <rtems/score/heapimpl.h>
>> +
>> +/** @brief Uncached RAM pool
>> + *
>> + * Allocate the whole bsp_nocache for the nocache heap */
>> +static char nocache_pool[1024
>> +                         * 1024] __attribute__( ( section( ".bsp_nocache" ) ) );
>> +
>> +/** @brief Nocache heap
>> + *
>> + * Heap control for the uncached RAM heap */
>> +static Heap_Control nocache_heap;
>> +
>> +/** @brief Init nocache heap
>> + *
>> + * Constructor for the uncached RAM heap
>> + * @retval 0 on succuss, error code from errno.h on failure
>> + */
>> +__attribute__( ( constructor ) ) int nocache_init_heap( void )
>> +{
>> +  int       eno         = 0;
>> +  uintptr_t heap_status = 0;
>> +
>> +
>> +  heap_status = _Heap_Initialize(
>> +    &nocache_heap,
>> +    &nocache_pool[0],
>> +    sizeof( nocache_pool ),
>> +    0
>> +    );
>> +
>> +  if ( heap_status == 0 ) {
>> +    eno = ENOMEM;
>> +  }
>> +
>> +  return eno;
>> +}
>> +
>> +/** @brief Allocate uncached RAM
>> + *
>> + * Allocates RAM from the uncached heap
>> + * @param size  Number of bytes to be allocated
>> + * @retval  Pointer to the allocated RAM
>> + */
>> +void *nocache_malloc( const size_t size )
>> +{
>> +  return _Heap_Allocate( &nocache_heap, size );
>> +}
>> +
>> +/** @brief Free uncached RAM
>> + *
>> + * Releases RAM from the uncached heap
>> + * @param ptr Address of the RAM to be released
>> + */
>> +void nocache_free( void *ptr )
>> +{
>> +  if ( ptr != NULL ) {
>> +    bool ok = _Heap_Free( &nocache_heap, ptr );
>> +    assert( ok );
>> +  }
>> +}
>> \ No newline at end of file
>> --
>> 1.7.10.4
>>
>> _______________________________________________
>> rtems-devel mailing list
>> rtems-devel at rtems.org
>> http://www.rtems.org/mailman/listinfo/rtems-devel


-- 
--------------------------------------------
Embedded Brains GmbH
Ralf Kirchner          Dornierstr. 4
D-82178 Puchheim       Germany
email: ralf.kirchner at embedded-brains.de
Phone: +49-89-18 94 741-17
Fax:   +49-89-18 94 741-08

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.



More information about the devel mailing list