From 0cab067f1cd3349907d4cc62e8812f0a5e146d75 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 23 Mar 2018 15:54:12 +0100 Subject: bsps/powerpc: Move libcpu content to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libcpu/powerpc/Makefile.am | 54 - c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c | 262 --- .../libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c | 668 ------- c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c | 1936 -------------------- .../libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c | 675 ------- 5 files changed, 3595 deletions(-) delete mode 100644 c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c delete mode 100644 c/src/lib/libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c delete mode 100644 c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c delete mode 100644 c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c (limited to 'c/src/lib/libcpu/powerpc') diff --git a/c/src/lib/libcpu/powerpc/Makefile.am b/c/src/lib/libcpu/powerpc/Makefile.am index b2f03b64fe..6bef20975a 100644 --- a/c/src/lib/libcpu/powerpc/Makefile.am +++ b/c/src/lib/libcpu/powerpc/Makefile.am @@ -130,58 +130,4 @@ mpc8260_mmu_rel_CPPFLAGS = $(AM_CPPFLAGS) mpc8260_mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) endif -############################################################################## -# START: MPC83XX # -############################################################################## -if mpc83xx - -# Includes - -# Network -if HAS_NETWORKING -noinst_PROGRAMS += mpc83xx/tsec.rel -mpc83xx_tsec_rel_SOURCES = mpc83xx/network/tsec.c -mpc83xx_tsec_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) -endif - -# i2c -noinst_PROGRAMS += mpc83xx/i2c.rel -mpc83xx_i2c_rel_SOURCES = mpc83xx/i2c/mpc83xx_i2cdrv.c \ - mpc83xx/i2c/mpc83xx_i2cdrv.h -mpc83xx_i2c_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) - -# SPI -noinst_PROGRAMS += mpc83xx/spi.rel -mpc83xx_spi_rel_SOURCES = mpc83xx/spi/mpc83xx_spidrv.c \ - mpc83xx/spi/mpc83xx_spidrv.h -mpc83xx_spi_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) - -# GTM -noinst_PROGRAMS += mpc83xx/gtm.rel -mpc83xx_gtm_rel_SOURCES = mpc83xx/gtm/gtm.c \ - mpc83xx/include/gtm.h -mpc83xx_gtm_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) - -endif -############################################################################## -# END: MPC83XX # -############################################################################## - -############################################################################## -# START: QorIQ # -############################################################################## -if qoriq - -# Network -if HAS_NETWORKING -noinst_PROGRAMS += tsec.rel -tsec_rel_SOURCES = mpc83xx/network/tsec.c -tsec_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) -endif - -endif -############################################################################## -# END: QorIQ # -############################################################################## - include $(top_srcdir)/../../../automake/local.am diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c b/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c deleted file mode 100644 index 2f13a1d8cd..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c +++ /dev/null @@ -1,262 +0,0 @@ -/** - * @file - * - * @brief Source file for timer functions. - */ - -/* - * Copyright (c) 2008 - * Embedded Brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * rtems@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 - -#include -#include - -#define RTEMS_STATUS_CHECKS_USE_PRINTK - -#include - -#define MPC83XX_GTM_CHECK_INDEX( timer) \ - if (( timer) < 0 || ( timer) >= MPC83XX_GTM_NUMBER) { \ - return RTEMS_INVALID_NUMBER; \ - } - -#define GTM_MODULE(timer) ((timer)/4) -#define GTM_MODULE_TIMER(timer) ((timer)%4) -#define GTM_HIGH(timer) (GTM_MODULE_TIMER(timer)/2) -#define GTM_LOW(timer) (GTM_MODULE_TIMER(timer)%2) - -#define MPC83XX_GTM_CLOCK_MASK MPC83XX_GTM_CLOCK_EXTERN - -static const uint8_t mpc83xx_gmt_interrupt_vector_table [MPC83XX_GTM_NUMBER] = { 90, 78, 84, 72, 91, 79, 85, 73 }; - -rtems_status_code mpc83xx_gtm_initialize( int timer, int clock) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - rtems_interrupt_level level; - - unsigned mask = 0xfU << (GTM_LOW(timer) * 4); - unsigned flags = 0x3U << (GTM_LOW(timer) * 4); - uint8_t reg = 0; - - MPC83XX_GTM_CHECK_INDEX( timer); - - rtems_interrupt_disable( level); - - reg = mpc83xx.gtm [GTM_MODULE(timer)].gtcfr [GTM_HIGH(timer)].reg; - mpc83xx.gtm [GTM_MODULE(timer)].gtcfr [GTM_HIGH(timer)].reg = - (uint8_t) ((reg & ~mask) | flags); - - mpc83xx.gtm [GTM_MODULE(timer)] - .gt_tim_regs [GTM_HIGH(timer)] - .gtmdr [GTM_LOW(timer)] = 0; - - rtems_interrupt_enable( level); - - sc = mpc83xx_gtm_set_clock( timer, clock); - RTEMS_CHECK_SC( sc, "Set clock"); - - sc = mpc83xx_gtm_set_value( timer, 0); - RTEMS_CHECK_SC( sc, "Set value"); - - sc = mpc83xx_gtm_set_reference( timer, 0); - RTEMS_CHECK_SC( sc, "Set reference"); - - sc = mpc83xx_gtm_set_prescale( timer, 0); - RTEMS_CHECK_SC( sc, "Set prescale"); - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_enable_restart( int timer, bool enable) -{ - rtems_interrupt_level level; - MPC83XX_GTM_CHECK_INDEX( timer); - - rtems_interrupt_disable( level); - - if (enable) { - mpc83xx.gtm [GTM_MODULE(timer)] - .gt_tim_regs [GTM_HIGH(timer)] - .gtmdr [GTM_LOW(timer)] |= 0x0008; - } else { - mpc83xx.gtm [GTM_MODULE(timer)] - .gt_tim_regs [GTM_HIGH(timer)] - .gtmdr [GTM_LOW(timer)] &= ~0x0008; - } - - rtems_interrupt_enable( level); - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_set_clock( int timer, int clock) -{ - rtems_interrupt_level level; - uint16_t reg = 0; - - MPC83XX_GTM_CHECK_INDEX( timer); - - if (clock & ~MPC83XX_GTM_CLOCK_MASK) { - return RTEMS_INVALID_CLOCK; - } - - rtems_interrupt_disable( level); - - reg = mpc83xx.gtm [GTM_MODULE(timer)] - .gt_tim_regs [GTM_HIGH(timer)] - .gtmdr [GTM_LOW(timer)]; - mpc83xx.gtm [GTM_MODULE(timer)] - .gt_tim_regs [GTM_HIGH(timer)] - .gtmdr [GTM_LOW(timer)] = (reg & ~MPC83XX_GTM_CLOCK_MASK) | clock; - - rtems_interrupt_enable( level); - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_get_clock( int timer, int *clock) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - *clock = mpc83xx.gtm [GTM_MODULE(timer)] - .gt_tim_regs [GTM_HIGH(timer)] - .gtmdr [GTM_LOW(timer)] & MPC83XX_GTM_CLOCK_MASK; - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_start( int timer) -{ - rtems_interrupt_level level; - uint8_t flags = 0x2 << (GTM_LOW(timer) * 4); - - MPC83XX_GTM_CHECK_INDEX( timer); - - rtems_interrupt_disable( level); - mpc83xx.gtm [GTM_MODULE(timer)] -.gtcfr [GTM_HIGH(timer)].reg &= ~flags; - rtems_interrupt_enable( level); - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_stop( int timer) -{ - rtems_interrupt_level level; - uint8_t flags = 0x2 << (GTM_LOW(timer) * 4); - - MPC83XX_GTM_CHECK_INDEX( timer); - - rtems_interrupt_disable( level); - mpc83xx.gtm [GTM_MODULE(timer)].gtcfr [GTM_HIGH(timer)].reg |= flags; - rtems_interrupt_enable( level); - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_set_value( int timer, uint16_t value) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - mpc83xx.gtm [GTM_MODULE(timer)].gt_tim_regs [GTM_HIGH(timer)].gtcnr [GTM_LOW(timer)] = value; - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_get_value( int timer, uint16_t *value) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - *value = mpc83xx.gtm [GTM_MODULE(timer)].gt_tim_regs [GTM_HIGH(timer)].gtcnr [GTM_LOW(timer)]; - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_set_reference( int timer, uint16_t reference) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - mpc83xx.gtm [GTM_MODULE(timer)].gt_tim_regs [GTM_HIGH(timer)].gtrfr [GTM_LOW(timer)] = reference; - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_get_reference( int timer, uint16_t *reference) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - *reference = mpc83xx.gtm [GTM_MODULE(timer)].gt_tim_regs [GTM_HIGH(timer)].gtrfr [GTM_LOW(timer)]; - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_set_prescale( int timer, uint8_t prescale) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - mpc83xx.gtm [GTM_MODULE(timer)].gtpsr [GTM_MODULE_TIMER(timer)] = prescale; - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_get_prescale( int timer, uint8_t *prescale) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - *prescale = mpc83xx.gtm [GTM_MODULE(timer)].gtpsr [GTM_MODULE_TIMER(timer)]; - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_interrupt_get_vector( int timer, rtems_vector_number *vector) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - *vector = mpc83xx_gmt_interrupt_vector_table [timer]; - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_interrupt_enable( int timer) -{ - rtems_interrupt_level level; - MPC83XX_GTM_CHECK_INDEX( timer); - - rtems_interrupt_disable( level); - mpc83xx.gtm [GTM_MODULE(timer)].gt_tim_regs [GTM_HIGH(timer)].gtmdr [GTM_LOW(timer)] |= 0x0010; - rtems_interrupt_enable( level); - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_interrupt_disable( int timer) -{ - rtems_interrupt_level level; - MPC83XX_GTM_CHECK_INDEX( timer); - - rtems_interrupt_disable( level); - mpc83xx.gtm [GTM_MODULE(timer)].gt_tim_regs [GTM_HIGH(timer)].gtmdr [GTM_LOW(timer)] &= ~0x0010; - rtems_interrupt_enable( level); - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_gtm_interrupt_clear( int timer) -{ - MPC83XX_GTM_CHECK_INDEX( timer); - - mpc83xx.gtm [GTM_MODULE(timer)].gtevr [GTM_MODULE_TIMER(timer)] = 0x0002; - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c b/c/src/lib/libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c deleted file mode 100644 index b4c3d477f7..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c +++ /dev/null @@ -1,668 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS support for MPC83xx | -+-----------------------------------------------------------------+ -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@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. | -| | -+-----------------------------------------------------------------+ -| this file contains the MPC83xx I2C driver | -\*===============================================================*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG - -#if defined(LIBBSP_POWERPC_GEN83XX_BSP_H) - #define I2CCR_MEN (1 << 7) /* module enable */ -#elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H) - #define I2CCR_MDIS (1 << 7) /* module disable */ -#endif -#define I2CCR_MIEN (1 << 6) /* module interrupt enable */ -#define I2CCR_MSTA (1 << 5) /* 0->1 generates a start condiiton, 1->0 a stop */ -#define I2CCR_MTX (1 << 4) /* 0 = receive mode, 1 = transmit mode */ -#define I2CCR_TXAK (1 << 3) /* 0 = send ack 1 = send nak during receive */ -#define I2CCR_RSTA (1 << 2) /* 1 = send repeated start condition */ -#define I2CCR_BCST (1 << 0) /* 0 = disable 1 = enable broadcast accept */ - -#define I2CSR_MCF (1 << 7) /* data transfer (0=transfer in progres) */ -#define I2CSR_MAAS (1 << 6) /* addessed as slave */ -#define I2CSR_MBB (1 << 5) /* bus busy */ -#define I2CSR_MAL (1 << 4) /* arbitration lost */ -#define I2CSR_BCSTM (1 << 3) /* broadcast match */ -#define I2CSR_SRW (1 << 2) /* slave read/write */ -#define I2CSR_MIF (1 << 1) /* module interrupt */ -#define I2CSR_RXAK (1 << 0) /* receive acknowledge */ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code mpc83xx_i2c_find_clock_divider -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| determine proper divider value | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - uint8_t *result, /* result value */ - int divider /* requested divider */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - int i; - int fdr_val; - rtems_status_code sc = RTEMS_SUCCESSFUL; - struct { - int divider; - int fdr_val; - } dividers[] ={ -#if defined(LIBBSP_POWERPC_GEN83XX_BSP_H) - { 256,0x20 }, { 288,0x21 }, { 320,0x22 }, { 352,0x23 }, - { 384,0x00 }, { 416,0x01 }, { 448,0x25 }, { 480,0x02 }, - { 512,0x26 }, { 576,0x03 }, { 640,0x04 }, { 704,0x05 }, - { 768,0x29 }, { 832,0x06 }, { 896,0x2a }, { 1024,0x07 }, - { 1152,0x08 }, { 1280,0x09 }, { 1536,0x0A }, { 1792,0x2E }, - { 1920,0x0B }, { 2048,0x2F }, { 2304,0x0C }, { 2560,0x0D }, - { 3072,0x0E }, { 3584,0x32 }, { 3840,0x0F }, { 4096,0x33 }, - { 4608,0x10 }, { 5120,0x11 }, { 6144,0x12 }, { 7168,0x36 }, - { 7680,0x13 }, { 8192,0x37 }, { 9216,0x14 }, {10240,0x15 }, - {12288,0x16 }, {14336,0x3A }, {15360,0x17 }, {16384,0x3B }, - {18432,0x18 }, {20480,0x19 }, {24576,0x1A }, {28672,0x3E }, - {30720,0x1B }, {32768,0x3F }, {36864,0x1C }, {40960,0x1D }, - {49152,0x1E }, {61440,0x1F } -#elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H) - { 768, 0x31 } -#endif - }; - - if (divider <= 0) { - sc = RTEMS_INVALID_NUMBER; - } - - if (sc == RTEMS_SUCCESSFUL) { - sc = RTEMS_INVALID_NUMBER; - for (i = 0, fdr_val = -1; i < sizeof(dividers)/sizeof(dividers[0]); i++) { - fdr_val = dividers[i].fdr_val; - if (dividers[i].divider >= divider) - { - sc = RTEMS_SUCCESSFUL; - *result = fdr_val; - break; - } - } - } - return sc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int mpc83xx_i2c_wait -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| wait for i2c to become idle | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - mpc83xx_i2c_softc_t *softc_ptr, /* handle */ - uint8_t desired_status, /* desired status word */ - uint8_t status_mask /* status word mask */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - uint8_t act_status; - rtems_status_code rc; - uint32_t tout; - -#if defined(DEBUG) - printk("mpc83xx_i2c_wait called... "); -#endif - - if (softc_ptr->initialized) { - /* - * enable interrupt mask - */ - softc_ptr->reg_ptr->i2ccr |= I2CCR_MIEN; - rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id,RTEMS_WAIT,100); - if (rc != RTEMS_SUCCESSFUL) { - return rc; - } - } - else { - tout = 0; - do { - if (tout++ > 1000000) { -#if defined(DEBUG) - printk("... exit with RTEMS_TIMEOUT\r\n"); -#endif - return RTEMS_TIMEOUT; - } - } while (!(softc_ptr->reg_ptr->i2csr & I2CSR_MIF)); - } - softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MIEN; - - act_status = softc_ptr->reg_ptr->i2csr; - if ((act_status & status_mask) != desired_status) { -#if defined(DEBUG) - printk("... exit with RTEMS_IO_ERROR\r\n"); -#endif - return RTEMS_IO_ERROR; - } -#if defined(DEBUG) - printk("... exit OK\r\n"); -#endif - return RTEMS_SUCCESSFUL; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void mpc83xx_i2c_irq_handler -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle interrupts | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_irq_hdl_param handle /* handle, is softc_ptr structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - mpc83xx_i2c_softc_t *softc_ptr = (mpc83xx_i2c_softc_t *)handle; - - /* - * clear IRQ flag - */ - #if defined(LIBBSP_POWERPC_GEN83XX_BSP_H) - softc_ptr->reg_ptr->i2csr &= ~I2CSR_MIF; - #elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H) - softc_ptr->reg_ptr->i2csr = I2CSR_MIF; - #endif - - /* - * disable interrupt mask - */ - softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MIEN; - if (softc_ptr->initialized) { - rtems_semaphore_release(softc_ptr->irq_sema_id); - } -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void mpc83xx_i2c_irq_on_off -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| enable/disable interrupts (void, handled at different position) | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - const - rtems_irq_connect_data *irq_conn_data /* irq connect data */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ -} - - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int mpc83xx_i2c_irq_isOn -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| check state of interrupts, void, done differently | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - const - rtems_irq_connect_data *irq_conn_data /* irq connect data */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| TRUE, if enabled | -\*=========================================================================*/ -{ - return (TRUE); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void mpc83xx_i2c_install_irq_handler -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| (un-)install the interrupt handler | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - mpc83xx_i2c_softc_t *softc_ptr, /* ptr to control structure */ - int install /* TRUE: install, FALSE: remove */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - - rtems_irq_connect_data irq_conn_data = { - softc_ptr->irq_number, - mpc83xx_i2c_irq_handler, /* rtems_irq_hdl */ - (rtems_irq_hdl_param)softc_ptr, /* (rtems_irq_hdl_param) */ - mpc83xx_i2c_irq_on_off, /* (rtems_irq_enable) */ - mpc83xx_i2c_irq_on_off, /* (rtems_irq_disable) */ - mpc83xx_i2c_irq_isOn /* (rtems_irq_is_enabled) */ - }; - - /* - * (un-)install handler for I2C device - */ - if (install) { - /* - * create semaphore for IRQ synchronization - */ - rc = rtems_semaphore_create(rtems_build_name('i','2','c','s'), - 0, - RTEMS_FIFO - | RTEMS_SIMPLE_BINARY_SEMAPHORE, - 0, - &softc_ptr->irq_sema_id); - if (rc != RTEMS_SUCCESSFUL) { - rtems_panic("I2C: cannot create semaphore"); - } - if (!BSP_install_rtems_irq_handler (&irq_conn_data)) { - rtems_panic("I2C: cannot install IRQ handler"); - } - } - else { - if (!BSP_remove_rtems_irq_handler (&irq_conn_data)) { - rtems_panic("I2C: cannot uninstall IRQ handler"); - } - /* - * delete sync semaphore - */ - if (softc_ptr->irq_sema_id != 0) { - rc = rtems_semaphore_delete(softc_ptr->irq_sema_id); - if (rc != RTEMS_SUCCESSFUL) { - rtems_panic("I2C: cannot delete semaphore"); - } - } - } -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code mpc83xx_i2c_init -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| initialize the driver | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh /* bus specifier structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc); - uint8_t fdr_val; - int errval; -#if defined(DEBUG) - printk("mpc83xx_i2c_init called... "); -#endif - /* - * init HW registers - */ - /* - * init frequency divider to 100kHz - */ - errval = mpc83xx_i2c_find_clock_divider(&fdr_val, - softc_ptr->base_frq/100000); - if (errval != 0) { - return errval; - } - softc_ptr->reg_ptr->i2cfdr = fdr_val; - /* - * init digital filter sampling rate - */ - softc_ptr->reg_ptr->i2cdfsrr = 0x10 ; /* no special filtering needed */ - /* - * set own slave address to broadcast (0x00) - */ - softc_ptr->reg_ptr->i2cadr = 0x00 ; - - /* - * set control register to module enable - */ - #if defined(LIBBSP_POWERPC_GEN83XX_BSP_H) - softc_ptr->reg_ptr->i2ccr = I2CCR_MEN; - #elif defined(LIBBSP_POWERPC_MPC55XXEVB_BSP_H) - softc_ptr->reg_ptr->i2ccr = 0; - #endif - - /* - * init interrupt stuff - */ - mpc83xx_i2c_install_irq_handler(softc_ptr,TRUE); - - /* - * mark, that we have initialized - */ - softc_ptr->initialized = TRUE; -#if defined(DEBUG) - printk("... exit OK\r\n"); -#endif - return RTEMS_SUCCESSFUL; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code mpc83xx_i2c_send_start -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| send a start condition to bus | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh /* bus specifier structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc); - -#if defined(DEBUG) - printk("mpc83xx_i2c_send_start called... "); -#endif - if (0 != (softc_ptr->reg_ptr->i2ccr & I2CCR_MSTA)) { - /* - * already started, so send a "repeated start" - */ - softc_ptr->reg_ptr->i2ccr |= I2CCR_RSTA; - } - else { - softc_ptr->reg_ptr->i2ccr |= I2CCR_MSTA; - } - -#if defined(DEBUG) - printk("... exit OK\r\n"); -#endif - return 0; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code mpc83xx_i2c_send_stop -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| send a stop condition to bus | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh /* bus specifier structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc); - -#if defined(DEBUG) - printk("mpc83xx_i2c_send_stop called... "); -#endif - softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MSTA; - /* - * wait, 'til stop has been executed - */ - while (0 != (softc_ptr->reg_ptr->i2csr & I2CSR_MBB)) { - rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); - } -#if defined(DEBUG) - printk("... exit OK\r\n"); -#endif - return 0; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code mpc83xx_i2c_send_addr -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| address a slave device on the bus | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh, /* bus specifier structure */ - uint32_t addr, /* address to send on bus */ - int rw /* 0=write,1=read */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc); - uint8_t addr_byte; - rtems_status_code rc; - -#if defined(DEBUG) - printk("mpc83xx_i2c_send_addr called... "); -#endif - softc_ptr->reg_ptr->i2ccr |= I2CCR_MTX; - /* - * determine, whether short or long address is needed, determine rd/wr - */ - if (addr > 0x7f) { - addr_byte = (0xf0 - | ((addr >> 7) & 0x06) - | ((rw) ? 1 : 0)); - /* - * send first byte - */ - softc_ptr->reg_ptr->i2cdr = addr_byte; - /* - * wait for successful transfer - */ - rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | I2CSR_RXAK); - if (rc != RTEMS_SUCCESSFUL) { -#if defined(DEBUG) - printk("... exit rc=%d\r\n",rc); -#endif - return rc; - } - } - /* - * send (final) byte - */ - addr_byte = ((addr << 1) - | ((rw) ? 1 : 0)); - - softc_ptr->reg_ptr->i2cdr = addr_byte; - /* - * wait for successful transfer - */ - rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | I2CSR_RXAK); - -#if defined(DEBUG) - printk("... exit rc=%d\r\n",rc); -#endif - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int mpc83xx_i2c_read_bytes -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| receive some bytes from I2C device | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh, /* bus specifier structure */ - unsigned char *buf, /* buffer to store bytes */ - int len /* number of bytes to receive */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| number of bytes received or (negative) error code | -\*=========================================================================*/ -{ - mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc); - rtems_status_code rc; - unsigned char *p = buf; - -#if defined(DEBUG) - printk("mpc83xx_i2c_read_bytes called... "); -#endif - softc_ptr->reg_ptr->i2ccr &= ~I2CCR_MTX; - softc_ptr->reg_ptr->i2ccr &= ~I2CCR_TXAK; - /* - * FIXME: do we need to deactivate TXAK from the start, - * when only one byte is to be received? - */ - /* - * we need a dummy transfer here to start the first read - */ - softc_ptr->reg_ptr->i2cdr; - - while (len-- > 0) { - if (len == 0) { - /* - * last byte is not acknowledged - */ - softc_ptr->reg_ptr->i2ccr |= I2CCR_TXAK; - } - /* - * wait 'til end of transfer - */ - rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF); - if (rc != RTEMS_SUCCESSFUL) { -#if defined(DEBUG) - printk("... exit rc=%d\r\n",-rc); -#endif - return -rc; - } - *p++ = softc_ptr->reg_ptr->i2cdr; - - } - - /* - * wait 'til end of last transfer - */ - rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF); - -#if defined(DEBUG) - printk("... exit OK, rc=%d\r\n",p-buf); -#endif - return p - buf; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int mpc83xx_i2c_write_bytes -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| send some bytes to I2C device | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh, /* bus specifier structure */ - unsigned char *buf, /* buffer to send */ - int len /* number of bytes to send */ - -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| number of bytes sent or (negative) error code | -\*=========================================================================*/ -{ - mpc83xx_i2c_softc_t *softc_ptr = &(((mpc83xx_i2c_desc_t *)(bh))->softc); - rtems_status_code rc; - unsigned char *p = buf; - -#if defined(DEBUG) - printk("mpc83xx_i2c_write_bytes called... "); -#endif - softc_ptr->reg_ptr->i2ccr = - (softc_ptr->reg_ptr->i2ccr & ~I2CCR_TXAK) | I2CCR_MTX; - while (len-- > 0) { - int rxack = len != 0 ? I2CSR_RXAK : 0; - - softc_ptr->reg_ptr->i2cdr = *p++; - /* - * wait 'til end of transfer - */ - rc = mpc83xx_i2c_wait(softc_ptr, I2CSR_MCF, I2CSR_MCF | rxack); - if (rc != RTEMS_SUCCESSFUL) { -#if defined(DEBUG) - printk("... exit rc=%d\r\n",-rc); -#endif - return -rc; - } - } -#if defined(DEBUG) - printk("... exit OK, rc=%d\r\n",p-buf); -#endif - return p - buf; -} - -rtems_libi2c_bus_ops_t mpc83xx_i2c_ops = { - .init = mpc83xx_i2c_init, - .send_start = mpc83xx_i2c_send_start, - .send_stop = mpc83xx_i2c_send_stop, - .send_addr = mpc83xx_i2c_send_addr, - .read_bytes = mpc83xx_i2c_read_bytes, - .write_bytes = mpc83xx_i2c_write_bytes, -}; - diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c b/c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c deleted file mode 100644 index ea1c29052e..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c +++ /dev/null @@ -1,1936 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS support for MPC83xx | -+-----------------------------------------------------------------+ -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@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. | -| | -+-----------------------------------------------------------------+ -| this file contains the MPC83xx TSEC networking driver | -\*===============================================================*/ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CLREVENT_IN_IRQ - -#define TSEC_WATCHDOG_TIMEOUT 5 /* check media every 5 seconds */ - -#ifdef DEBUG - #define PF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__) -#else - #define PF(...) -#endif - -/* - * Device data - */ -struct tsec_struct { - struct arpcom arpcom; - int acceptBroadcast; - - /* - * HW links: (filled from rtems_bsdnet_ifconfig - */ - volatile tsec_registers *reg_ptr; /* pointer to TSEC register block */ - volatile tsec_registers *mdio_ptr; /* pointer to TSEC register block which is responsible for MDIO communication */ - rtems_irq_number irq_num_tx; - rtems_irq_number irq_num_rx; - rtems_irq_number irq_num_err; - - rtems_interrupt_lock lock; - - /* - * BD management - */ - int rxBdCount; - int txBdCount; - PQBufferDescriptor_t *Rx_Frst_BD; - PQBufferDescriptor_t *Rx_Last_BD; - PQBufferDescriptor_t *Rx_NxtUsed_BD; /* First BD, which is in Use */ - PQBufferDescriptor_t *Rx_NxtFill_BD; /* BD to be filled next */ - struct mbuf **Rx_mBuf_Ptr; /* Storage for mbufs */ - - PQBufferDescriptor_t *Tx_Frst_BD; - PQBufferDescriptor_t *Tx_Last_BD; - PQBufferDescriptor_t *Tx_NxtUsed_BD; /* First BD, which is in Use */ - PQBufferDescriptor_t *Tx_NxtFill_BD; /* BD to be filled next */ - struct mbuf **Tx_mBuf_Ptr; /* Storage for mbufs */ - /* - * Daemon IDs - */ - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * MDIO/Phy info - */ - struct rtems_mdio_info mdio_info; - int phy_default; - int media_state; /* (last detected) state of media */ - /* - * statistic counters Rx - */ - unsigned long rxInterrupts; - unsigned long rxErrors; - /* - * statistic counters Tx - */ - unsigned long txInterrupts; - unsigned long txErrors; - }; - -static struct tsec_struct tsec_driver[TSEC_COUNT]; - -/* - * default numbers for buffers - */ -#define RX_BUF_COUNT 64 -#define TX_BUF_COUNT 64 - -/* - * mask for all Tx interrupts - */ -#define IEVENT_TXALL (TSEC_IEVENT_GTSC \ - | TSEC_IEVENT_TXC \ - /*| TSEC_IEVENT_TXB*/ \ - | TSEC_IEVENT_TXF ) - -/* - * mask for all Rx interrupts - */ -#define IEVENT_RXALL (TSEC_IEVENT_RXC \ - /* | TSEC_IEVENT_RXB */ \ - | TSEC_IEVENT_GRSC \ - | TSEC_IEVENT_RXF ) - -/* - * mask for all Error interrupts - */ -#define IEVENT_ERRALL (TSEC_IEVENT_BABR \ - | TSEC_IEVENT_BSY \ - | TSEC_IEVENT_EBERR \ - | TSEC_IEVENT_MSRO \ - | TSEC_IEVENT_BABT \ - | TSEC_IEVENT_TXE \ - | TSEC_IEVENT_LC \ - | TSEC_IEVENT_CRL_XDA \ - | TSEC_IEVENT_XFUN ) - -static void TSEC_IMASK_SET(struct tsec_struct *sc, uint32_t mask, uint32_t val) -{ - volatile uint32_t *reg = &sc->reg_ptr->imask; - rtems_interrupt_lock_context lock_context; - - rtems_interrupt_lock_acquire(&sc->lock, &lock_context); - *reg = (*reg & ~mask) | (val & mask); - rtems_interrupt_lock_release(&sc->lock, &lock_context); -} - -#define TSEC_ALIGN_BUFFER(buf,align) \ - ((void *)( (((uint32_t)(buf))+(align)-1) \ - -(((uint32_t)(buf))+(align)-1)%align)) - -/* - * RTEMS event used by interrupt handler to signal daemons. - * This must *not* be the same event used by the TCP/IP task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 -#define FATAL_INT_EVENT RTEMS_EVENT_3 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -static int tsec_ioctl -( - struct ifnet *ifp, /* interface information */ - ioctl_command_t command, /* ioctl command code */ - caddr_t data /* optional data */ - ); - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_hwinit -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| initialize hardware register | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - volatile tsec_registers *reg_ptr = sc->reg_ptr; /* pointer to TSEC registers*/ - uint8_t *mac_addr; - size_t i; - - /* Clear interrupt mask and all pending events */ - reg_ptr->imask = 0; - reg_ptr->ievent = 0xffffffff; - - /* - * init ECNTL register - * - clear statistics counters - * - enable statistics - * NOTE: do not clear bits set in BSP init function - */ - reg_ptr->ecntrl = ((reg_ptr->ecntrl & ~TSEC_ECNTRL_AUTOZ) - | TSEC_ECNTRL_CLRCNT - | TSEC_ECNTRL_STEN - | TSEC_ECNTRL_R100M); - - /* - * init DMA control register: - * - enable snooping - * - write BD status before interrupt request - * - do not poll TxBD, but wait for TSTAT[THLT] to be written - */ - reg_ptr->dmactrl = (TSEC_DMACTL_TDSEN - | TSEC_DMACTL_TBDSEN - | TSEC_DMACTL_WWR - | TSEC_DMACTL_WOP); - - /* - * init Attribute register: - * - enable read snooping for data and BD - */ - reg_ptr->attr = (TSEC_ATTR_RDSEN - | TSEC_ATTR_RBDSEN); - - - reg_ptr->mrblr = MCLBYTES-64; /* take care of buffer size lost - * due to alignment */ - - /* - * init EDIS register: disable all error reportings - */ - reg_ptr->edis = (TSEC_EDIS_BSYDIS | - TSEC_EDIS_EBERRDIS | - TSEC_EDIS_TXEDIS | - TSEC_EDIS_LCDIS | - TSEC_EDIS_CRLXDADIS | - TSEC_EDIS_FUNDIS); - /* - * init minimum frame length register - */ - reg_ptr->minflr = 64; - /* - * init maximum frame length register - */ - reg_ptr->maxfrm = 1536; - /* - * define physical address of TBI - */ - reg_ptr->tbipa = 0x1e; - /* - * init transmit interrupt coalescing register - */ - reg_ptr->txic = (TSEC_TXIC_ICEN - | TSEC_TXIC_ICFCT(2) - | TSEC_TXIC_ICTT(32)); - /* - * init receive interrupt coalescing register - */ -#if 0 - reg_ptr->rxic = (TSEC_RXIC_ICEN - | TSEC_RXIC_ICFCT(2) - | TSEC_RXIC_ICTT(32)); -#else - reg_ptr->rxic = 0; -#endif - /* - * init MACCFG1 register - */ - reg_ptr->maccfg1 = (TSEC_MACCFG1_RX_FLOW - | TSEC_MACCFG1_TX_FLOW); - - /* - * init MACCFG2 register - */ - reg_ptr->maccfg2 = ((reg_ptr->maccfg2 & TSEC_MACCFG2_IFMODE_MSK) - | TSEC_MACCFG2_IFMODE_BYT - | TSEC_MACCFG2_PRELEN( 7) - | TSEC_MACCFG2_FULLDUPLEX); - - /* - * init station address register - */ - mac_addr = sc->arpcom.ac_enaddr; - - reg_ptr->macstnaddr[0] = ((mac_addr[5] << 24) - | (mac_addr[4] << 16) - | (mac_addr[3] << 8) - | (mac_addr[2] << 0)); - reg_ptr->macstnaddr[1] = ((mac_addr[1] << 24) - | (mac_addr[0] << 16)); - /* - * clear hash filters - */ - for (i = 0; - i < sizeof(reg_ptr->iaddr)/sizeof(reg_ptr->iaddr[0]); - i++) { - reg_ptr->iaddr[i] = 0; - } - for (i = 0; - i < sizeof(reg_ptr->gaddr)/sizeof(reg_ptr->gaddr[0]); - i++) { - reg_ptr->gaddr[i] = 0; - } -} - -/***************************************************************************\ -| MII Management access functions | -\***************************************************************************/ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_mdio_init -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| initialize the MIIM interface | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - static const uint8_t divider [] = { 32, 32, 48, 64, 80, 112, 160, 224 }; - size_t n = sizeof(divider) / sizeof(divider [0]); - size_t i = 0; - uint32_t mii_clock = UINT32_MAX; - uint32_t tsec_system_clock = BSP_bus_frequency / 2; - - /* Set TSEC registers for MDIO communication */ - - /* - * set clock divider - */ - for (i = 0; i < n && mii_clock > 2500000; ++i) { - mii_clock = tsec_system_clock / divider [i]; - } - - sc->mdio_ptr->miimcfg = i; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int tsec_mdio_read -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| read register of a phy | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - int phy, /* PHY number to access or -1 */ - void *uarg, /* unit argument */ - unsigned reg, /* register address */ - uint32_t *pval /* ptr to read buffer */ - ) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| 0, if ok, else error | -\*=========================================================================*/ -{ - struct tsec_struct *sc = uarg;/* control structure */ - - /* pointer to TSEC registers */ - volatile tsec_registers *reg_ptr = sc->mdio_ptr; - PF("%u\n", reg); - - /* - * make sure we work with a valid phy - */ - if (phy == -1) { - phy = sc->phy_default; - } - if ( (phy < 0) || (phy > 31)) { - /* - * invalid phy number - */ - return EINVAL; - } - /* - * set PHY/reg address - */ - reg_ptr->miimadd = (TSEC_MIIMADD_PHY(phy) - | TSEC_MIIMADD_REGADDR(reg)); - /* - * start read cycle - */ - reg_ptr->miimcom = 0; - reg_ptr->miimcom = TSEC_MIIMCOM_READ; - - /* - * wait for cycle to terminate - */ - do { - rtems_task_wake_after(2); - } while (0 != (reg_ptr->miimind & TSEC_MIIMIND_BUSY)); - reg_ptr->miimcom = 0; - /* - * fetch read data, if available - */ - if (pval != NULL) { - *pval = reg_ptr->miimstat; - } - return 0; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int tsec_mdio_write -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| write register of a phy | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - int phy, /* PHY number to access or -1 */ - void *uarg, /* unit argument */ - unsigned reg, /* register address */ - uint32_t val /* write value */ - ) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| 0, if ok, else error | -\*=========================================================================*/ -{ - struct tsec_struct *sc = uarg;/* control structure */ - - /* pointer to TSEC registers */ - volatile tsec_registers *reg_ptr = sc->mdio_ptr; - PF("%u\n", reg); - - /* - * make sure we work with a valid phy - */ - if (phy == -1) { - /* - * set default phy number: 0 for TSEC1, 1 for TSEC2 - */ - phy = sc->phy_default; - } - if ( (phy < 0) || (phy > 31)) { - /* - * invalid phy number - */ - return EINVAL; - } - /* - * set PHY/reg address - */ - reg_ptr->miimadd = (TSEC_MIIMADD_PHY(phy) - | TSEC_MIIMADD_REGADDR(reg)); - /* - * start write cycle - */ - reg_ptr->miimcon = val; - - /* - * wait for cycle to terminate - */ - do { - rtems_task_wake_after(2); - } while (0 != (reg_ptr->miimind & TSEC_MIIMIND_BUSY)); - reg_ptr->miimcom = 0; - return 0; -} - - -/***************************************************************************\ -| RX receive functions | -\***************************************************************************/ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_event_set tsec_rx_wait_for_events -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle all rx events | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc, /* control structure */ - rtems_event_set event_mask /* events to wait for */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| event set received | -\*=========================================================================*/ -{ - rtems_event_set events; /* events received */ - /* - * enable Rx interrupts, make sure this is not interrupted :-) - */ - TSEC_IMASK_SET(sc,IEVENT_RXALL,~0); - - /* - * wait for events to come in - */ - rtems_bsdnet_event_receive(event_mask, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - return events; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void mpc83xx_rxbd_alloc_clear -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| allocate space for Rx BDs, clear them | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - char *alloc_ptr; - PQBufferDescriptor_t *BD_ptr; - /* - * allocate proper space for Rx BDs - */ - alloc_ptr = calloc((sc->rxBdCount+1),sizeof(PQBufferDescriptor_t)); - if (alloc_ptr == NULL) { - rtems_panic("TSEC: cannot allocate space for Rx BDs"); - } - alloc_ptr = (void *)((uint32_t )((alloc_ptr + (sizeof(PQBufferDescriptor_t)-1))) - & ~(sizeof(PQBufferDescriptor_t)-1)); - /* - * store pointers to certain positions in BD chain - */ - sc->Rx_Last_BD = ((PQBufferDescriptor_t *)alloc_ptr)+sc->rxBdCount-1; - sc->Rx_Frst_BD = (PQBufferDescriptor_t *)alloc_ptr; - sc->Rx_NxtUsed_BD = sc->Rx_Frst_BD; - sc->Rx_NxtFill_BD = sc->Rx_Frst_BD; - - /* - * clear all BDs - */ - for (BD_ptr = sc->Rx_Frst_BD; - BD_ptr <= sc->Rx_Last_BD; - BD_ptr++) { - BD_ptr->status = 0; - } - /* - * Init BD chain registers - */ - sc->reg_ptr->rbase = (uint32_t) (sc->Rx_Frst_BD); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_receive_packets -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| process any received packets | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - PQBufferDescriptor_t *BD_ptr; - struct mbuf *m,*n; - bool finished = false; - uint16_t status; - struct ether_header *eh; - int bd_idx; - - BD_ptr = sc->Rx_NxtUsed_BD; - - while ((0 == ((status = BD_ptr->status) & BD_EMPTY)) && - !finished && - (BD_ptr->buffer != NULL)) { - /* - * get mbuf associated with BD - */ - bd_idx = BD_ptr - sc->Rx_Frst_BD; - m = sc->Rx_mBuf_Ptr[bd_idx]; - sc->Rx_mBuf_Ptr[bd_idx] = NULL; - - /* - * Check that packet is valid - */ - if ((status & (BD_LAST | - BD_FIRST_IN_FRAME | - BD_LONG | - BD_NONALIGNED | - BD_CRC_ERROR | - BD_OVERRUN )) - == (BD_LAST | - BD_FIRST_IN_FRAME ) ) { - /* - * send mbuf of this buffer to ether_input() - */ - m->m_len = m->m_pkthdr.len = (BD_ptr->length - - sizeof(uint32_t) - - sizeof(struct ether_header)); - eh = mtod(m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - PF("RX[%08x] (%i)\n", BD_ptr, m->m_len); - ether_input(&sc->arpcom.ac_if,eh,m); - } - else { - /* - * throw away mbuf - */ - MFREE(m,n); - (void) n; - } - /* - * mark buffer as non-allocated (for refill) - */ - BD_ptr->buffer = NULL; - /* - * Advance BD_ptr to next BD - */ - BD_ptr = ((BD_ptr == sc->Rx_Last_BD) - ? sc->Rx_Frst_BD - : BD_ptr+1); - } - sc->Rx_NxtUsed_BD = BD_ptr; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_refill_rxbds -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| link new buffers to rx BDs | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - PQBufferDescriptor_t *BD_ptr; - struct mbuf *m,*n; - bool finished = false; - int bd_idx; - - BD_ptr = sc->Rx_NxtFill_BD; - while ((BD_ptr->buffer == NULL) && - !finished) { - /* - * get new mbuf and attach a cluster - */ - MGETHDR(m,M_DONTWAIT,MT_DATA); - if (m != NULL) { - MCLGET(m,M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - MFREE(m,n); - (void) n; - m = NULL; - } - } - if (m == NULL) { - finished = true; - } - else { - bd_idx = BD_ptr - sc->Rx_Frst_BD; - sc->Rx_mBuf_Ptr[bd_idx] = m; - - m->m_pkthdr.rcvif= &sc->arpcom.ac_if; - m->m_data = TSEC_ALIGN_BUFFER(m->m_ext.ext_buf,64); - BD_ptr->buffer = m->m_data; - BD_ptr->length = 0; - BD_ptr->status = (BD_EMPTY - | BD_INTERRUPT - | ((BD_ptr == sc->Rx_Last_BD) - ? BD_WRAP - : 0)); - /* - * Advance BD_ptr to next BD - */ - BD_ptr = ((BD_ptr == sc->Rx_Last_BD) - ? sc->Rx_Frst_BD - : BD_ptr+1); - } - } - sc->Rx_NxtFill_BD = BD_ptr; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_rxDaemon -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle all rx buffers and events | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - void * arg /* argument, is sc structure ptr */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = - (struct tsec_struct *)arg; - bool finished = false; -#if !defined(CLREVENT_IN_IRQ) - uint32_t irq_events; -#endif - /* - * enable Rx in MACCFG1 register - */ - sc->reg_ptr->maccfg1 |= TSEC_MACCFG1_RXEN; - while (!finished) { - /* - * fetch MBufs, associate them to RxBDs - */ - tsec_refill_rxbds(sc); - /* - * wait for events to come in - */ - tsec_rx_wait_for_events(sc,INTERRUPT_EVENT); -#if !defined(CLREVENT_IN_IRQ) - /* - * clear any pending RX events - */ - irq_events = sc->reg_ptr->ievent & IEVENT_RXALL; - sc->reg_ptr->ievent = irq_events; -#endif - /* - * fetch any completed buffers/packets received - * and stuff them into the TCP/IP Stack - */ - tsec_receive_packets(sc); - } - /* - * disable Rx in MACCFG1 register - */ - sc->reg_ptr->maccfg1 &= ~TSEC_MACCFG1_RXEN; - /* - * terminate daemon - */ - sc->rxDaemonTid = 0; - rtems_task_delete(RTEMS_SELF); -} - -/***************************************************************************\ -| TX Transmit functions | -\***************************************************************************/ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void mpc83xx_txbd_alloc_clear -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| allocate space for Tx BDs, clear them | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - char *alloc_ptr; - PQBufferDescriptor_t *BD_ptr; - /* - * allocate proper space for Tx BDs - */ - alloc_ptr = calloc((sc->txBdCount+1),sizeof(PQBufferDescriptor_t)); - if (alloc_ptr == NULL) { - rtems_panic("TSEC: cannot allocate space for Tx BDs"); - } - alloc_ptr = (void *)((uint32_t )((alloc_ptr + (sizeof(PQBufferDescriptor_t)-1))) - & ~(sizeof(PQBufferDescriptor_t)-1)); - /* - * store pointers to certain positions in BD chain - */ - sc->Tx_Last_BD = ((PQBufferDescriptor_t *)alloc_ptr)+sc->txBdCount-1; - sc->Tx_Frst_BD = (PQBufferDescriptor_t *)alloc_ptr; - sc->Tx_NxtUsed_BD = sc->Tx_Frst_BD; - sc->Tx_NxtFill_BD = sc->Tx_Frst_BD; - - /* - * clear all BDs - */ - for (BD_ptr = sc->Tx_Frst_BD; - BD_ptr <= sc->Tx_Last_BD; - BD_ptr++) { - BD_ptr->status = 0; - } - /* - * Init BD chain registers - */ - sc->reg_ptr->tbase = (uint32_t)(sc->Tx_Frst_BD); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_tx_start -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| start transmission | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ -struct ifnet *ifp -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = ifp->if_softc; - - ifp->if_flags |= IFF_OACTIVE; - - rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_event_set tsec_tx_wait_for_events -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle all tx events | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc, /* control structure */ - rtems_event_set event_mask /* events to wait for */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| event set received | -\*=========================================================================*/ -{ - rtems_event_set events; /* events received */ - /* - * enable Tx interrupts, make sure this is not interrupted :-) - */ - TSEC_IMASK_SET(sc,IEVENT_TXALL,~0); - - /* - * wait for events to come in - */ - rtems_bsdnet_event_receive(event_mask, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - return events; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_tx_retire -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle all tx events | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - PQBufferDescriptor_t *RetBD; - RetBD = sc->Tx_NxtUsed_BD; - int bd_idx; - struct mbuf *m,*n; - /* - * check next BDs to be empty - */ - while ((RetBD->buffer != NULL) /* BD is filled */ - && (0 == (RetBD->status & BD_READY ))) {/* BD no longer ready*/ - - bd_idx = RetBD - sc->Tx_Frst_BD; - m = sc->Tx_mBuf_Ptr[bd_idx]; - sc->Tx_mBuf_Ptr[bd_idx] = NULL; - - MFREE(m,n); - (void) n; - RetBD->buffer = NULL; - /* - * Advance CurrBD to next BD - */ - RetBD = ((RetBD == sc->Tx_Last_BD) - ? sc->Tx_Frst_BD - : RetBD+1); - } - sc->Tx_NxtUsed_BD = RetBD; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_sendpacket -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle all tx events | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc, /* control structure */ - struct mbuf *m /* start of packet to send */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - PQBufferDescriptor_t *FrstBD = NULL; - PQBufferDescriptor_t *CurrBD; - uint16_t status; - struct mbuf *l = NULL; /* ptr to last non-freed (non-empty) mbuf */ - int bd_idx; - /* - * get next Tx BD - */ - CurrBD = sc->Tx_NxtFill_BD; - while (m) { - if(m->m_len == 0) { - /* - * Just toss empty mbufs - */ - struct mbuf *n; - MFREE(m, n); - m = n; - if(l != NULL) { - l->m_next = m; - } - } - else { - /* - * this mbuf is non-empty, so send it - */ - /* - * Is CurrBD still in Use/not yet retired? - */ - while (CurrBD->buffer != NULL) { - /* - * Then try to retire it - * and to return its mbuf - */ - tsec_tx_retire(sc); - if (CurrBD->buffer != NULL) { - /* - * Wait for anything to happen... - */ - tsec_tx_wait_for_events(sc,INTERRUPT_EVENT); - } - } - status = ((BD_PAD_CRC | BD_TX_CRC) - | ((m->m_next == NULL) - ? BD_LAST | BD_INTERRUPT - : 0) - | ((CurrBD == sc->Tx_Last_BD) ? BD_WRAP : 0)); - - /* - * link buffer to BD - */ - CurrBD->buffer = mtod(m, void *); - CurrBD->length = (uint32_t)m->m_len; - l = m; /* remember: we use this mbuf */ - PF("TX[%08x] (%i)\n", CurrBD, m->m_len); - - bd_idx = CurrBD - sc->Tx_Frst_BD; - sc->Tx_mBuf_Ptr[bd_idx] = m; - - m = m->m_next; /* advance to next mbuf of this packet */ - /* - * is this the first BD of the packet? - * then don't set it to "READY" state, - * and remember this BD position - */ - if (FrstBD == NULL) { - FrstBD = CurrBD; - } - else { - status |= BD_READY; - } - CurrBD->status = status; - /* - * Advance CurrBD to next BD - */ - CurrBD = ((CurrBD == sc->Tx_Last_BD) - ? sc->Tx_Frst_BD - : CurrBD+1); - } - } - /* - * mbuf chain of this packet - * has been translated - * to BD chain, so set first BD ready now - */ - if (FrstBD != NULL) { - FrstBD->status |= BD_READY; - } - sc->Tx_NxtFill_BD = CurrBD; - /* - * wake up transmitter (clear TSTAT[THLT]) - */ - sc->reg_ptr->tstat = TSEC_TSTAT_THLT; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_txDaemon -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle all tx events | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - void * arg /* argument, is sc structure ptr */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = - (struct tsec_struct *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - bool finished = false; -#if !defined(CLREVENT_IN_IRQ) - uint32_t irq_events; -#endif - - /* - * enable Tx in MACCFG1 register - * FIXME: make this irq save - */ - sc->reg_ptr->maccfg1 |= TSEC_MACCFG1_TXEN; - while (!finished) { - /* - * wait for events to come in - */ - tsec_tx_wait_for_events(sc, - START_TRANSMIT_EVENT - | INTERRUPT_EVENT); -#if !defined(CLREVENT_IN_IRQ) - /* - * clear any pending TX events - */ - irq_events = sc->reg_ptr->ievent & IEVENT_TXALL; - sc->reg_ptr->ievent = irq_events; -#endif - /* - * retire any sent tx BDs - */ - tsec_tx_retire(sc); - /* - * Send packets till queue is empty - */ - do { - /* - * Get the next mbuf chain to transmit. - */ - IF_DEQUEUE(&ifp->if_snd, m); - - if (m) { - tsec_sendpacket(sc,m); - } - } while (m != NULL); - - ifp->if_flags &= ~IFF_OACTIVE; - } - /* - * disable Tx in MACCFG1 register - */ - sc->reg_ptr->maccfg1 &= ~TSEC_MACCFG1_TXEN; - /* - * terminate daemon - */ - sc->txDaemonTid = 0; - rtems_task_delete(RTEMS_SELF); -} - -/***************************************************************************\ -| Interrupt handlers and management routines | -\***************************************************************************/ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_tx_irq_handler -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle tx interrupts | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_irq_hdl_param handle /* handle, is sc structure ptr */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = - (struct tsec_struct *)handle; -#if defined(CLREVENT_IN_IRQ) - uint32_t irq_events; -#endif - - PF("TXIRQ\n"); - sc->txInterrupts++; - /* - * disable tx interrupts - */ - TSEC_IMASK_SET(sc,IEVENT_TXALL,0); - -#if defined(CLREVENT_IN_IRQ) - /* - * clear any pending TX events - */ - irq_events = sc->reg_ptr->ievent & IEVENT_TXALL; - sc->reg_ptr->ievent = irq_events; -#endif - /* - * wake up tx Daemon - */ - rtems_bsdnet_event_send(sc->txDaemonTid, INTERRUPT_EVENT); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_rx_irq_handler -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle rx interrupts | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_irq_hdl_param handle /* handle, is sc structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = - (struct tsec_struct *)handle; -#if defined(CLREVENT_IN_IRQ) - uint32_t irq_events; -#endif - - sc->rxInterrupts++; - PF("RXIRQ\n"); - /* - * disable rx interrupts - */ - TSEC_IMASK_SET(sc,IEVENT_RXALL,0); -#if defined(CLREVENT_IN_IRQ) - /* - * clear any pending RX events - */ - irq_events = sc->reg_ptr->ievent & IEVENT_RXALL; - sc->reg_ptr->ievent = irq_events; -#endif - /* - * wake up rx Daemon< - */ - rtems_bsdnet_event_send(sc->rxDaemonTid, INTERRUPT_EVENT); -} - - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_err_irq_handler -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle error interrupts | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_irq_hdl_param handle /* handle, is sc structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = - (struct tsec_struct *)handle; - PF("ERIRQ\n"); - /* - * clear error events in IEVENT - */ - sc->reg_ptr->ievent = IEVENT_ERRALL; - /* - * has Rx been stopped? then restart it - */ - if (0 != (sc->reg_ptr->rstat & TSEC_RSTAT_QHLT)) { - sc->rxErrors++; - sc->reg_ptr->rstat = TSEC_RSTAT_QHLT; - } - /* - * has Tx been stopped? then restart it - */ - if (0 != (sc->reg_ptr->tstat & TSEC_TSTAT_THLT)) { - sc->txErrors++; - sc->reg_ptr->tstat = TSEC_TSTAT_THLT; - } -} - - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static uint32_t tsec_irq_mask -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| determine irq mask for given interrupt number | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - int irqnum, - struct tsec_struct *sc -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| interrupt mask (for ievent/imask register) | -\*=========================================================================*/ -{ - return ((irqnum == sc->irq_num_tx) - ? IEVENT_TXALL - : ((irqnum == sc->irq_num_rx) - ? IEVENT_RXALL - : ((irqnum == sc->irq_num_err) - ? IEVENT_ERRALL - : 0))); -} -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_irq_on -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| enable interrupts in TSEC mask register | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - const - rtems_irq_connect_data *irq_conn_data /* irq connect data */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = - (struct tsec_struct *)(irq_conn_data->handle); - - TSEC_IMASK_SET(sc, - tsec_irq_mask(irq_conn_data->name,sc), - ~0); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_irq_off -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| disable TX interrupts in TSEC mask register | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - const - rtems_irq_connect_data *irq_conn_data /* irq connect data */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = - (struct tsec_struct *)irq_conn_data->handle; - - TSEC_IMASK_SET(sc, - tsec_irq_mask(irq_conn_data->name,sc), - 0); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int tsec_irq_isOn -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| check state of interrupts in TSEC mask register | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - const - rtems_irq_connect_data *irq_conn_data /* irq connect data */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - struct tsec_struct *sc = - (struct tsec_struct *)irq_conn_data->handle; - - return (0 != (sc->reg_ptr->imask - & tsec_irq_mask(irq_conn_data->name,sc))); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_install_irq_handlers -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| (un-)install the interrupt handlers | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc, /* ptr to control structure */ - bool install /* true: install, false: remove */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - size_t i; - - rtems_irq_connect_data irq_conn_data[3] = { - { - sc->irq_num_tx, - tsec_tx_irq_handler, /* rtems_irq_hdl */ - (rtems_irq_hdl_param)sc, /* (rtems_irq_hdl_param) */ - tsec_irq_on, /* (rtems_irq_enable) */ - tsec_irq_off, /* (rtems_irq_disable) */ - tsec_irq_isOn /* (rtems_irq_is_enabled) */ - },{ - sc->irq_num_rx, - tsec_rx_irq_handler, /* rtems_irq_hdl */ - (rtems_irq_hdl_param)sc, /* (rtems_irq_hdl_param) */ - tsec_irq_on, /* (rtems_irq_enable) */ - tsec_irq_off, /* (rtems_irq_disable) */ - tsec_irq_isOn /* (rtems_irq_is_enabled) */ - },{ - sc->irq_num_err, - tsec_err_irq_handler, /* rtems_irq_hdl */ - (rtems_irq_hdl_param)sc, /* (rtems_irq_hdl_param) */ - tsec_irq_on, /* (rtems_irq_enable) */ - tsec_irq_off, /* (rtems_irq_disable) */ - tsec_irq_isOn /* (rtems_irq_is_enabled) */ - } - }; - - /* - * (un-)install handler for Tx/Rx/Error - */ - for (i = 0; - i < sizeof(irq_conn_data)/sizeof(irq_conn_data[0]); - i++) { - if (install) { - if (!BSP_install_rtems_irq_handler (&irq_conn_data[i])) { - rtems_panic("TSEC: cannot install IRQ handler"); - } - } - else { - if (!BSP_remove_rtems_irq_handler (&irq_conn_data[i])) { - rtems_panic("TSEC: cannot uninstall IRQ handler"); - } - } - } -} - -/***************************************************************************\ -| Initialization and interface routines | -\***************************************************************************/ - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_init -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| initialize the driver and the hardware | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - void *arg /* argument pointer, contains *sc */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| zero, if success | -\*=========================================================================*/ -{ - struct tsec_struct *sc = (struct tsec_struct *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - /* - * check, whether device is not yet running - */ - if (0 == sc->rxDaemonTid) { - /* - * allocate rx/tx BDs - */ - mpc83xx_rxbd_alloc_clear(sc); - mpc83xx_txbd_alloc_clear(sc); - /* - * allocate storage for mbuf ptrs - */ - sc->Rx_mBuf_Ptr = calloc(sc->rxBdCount,sizeof(struct mbuf *)); - sc->Tx_mBuf_Ptr = calloc(sc->txBdCount,sizeof(struct mbuf *)); - if ((sc->Rx_mBuf_Ptr == NULL) || - (sc->Tx_mBuf_Ptr == NULL)) { - rtems_panic("TSEC: cannot allocate buffers for mbuf management"); - - } - - /* - * initialize TSEC hardware: - * - set interrupt coalescing to BDCount/8, Time of 8 frames - * - enable DMA snooping - */ - tsec_hwinit(sc); - /* - * init access to phys - */ - tsec_mdio_init(sc); - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc("TStx", - 4096, - tsec_txDaemon, - sc); - sc->rxDaemonTid = rtems_bsdnet_newproc("TSrx", 4096, - tsec_rxDaemon, - sc); - /* - * install interrupt handlers - */ - tsec_install_irq_handlers(sc,true); - } - /* - * Set flags appropriately - */ - if(ifp->if_flags & IFF_PROMISC) { - sc->reg_ptr->rctrl |= TSEC_RCTRL_PROM; - } - else { - sc->reg_ptr->rctrl &= ~TSEC_RCTRL_PROM; - } - -#if defined(MPC83XX_BOARD_HSC_CM01) - /* - * for HSC CM01: we need to configure the PHY to use maximum skew adjust - */ - - tsec_mdio_write(-1,sc,23,0x0100); -#endif - - /* - * init timer so the "watchdog function gets called periodically - */ - ifp->if_timer = 1; - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_off -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| deinitialize the driver and the hardware | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* ptr to control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - /* - * deinitialize driver? - */ -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_stats -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| print statistics | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct tsec_struct *sc /* ptr to control structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - if (sc->phy_default >= 0) { - int media; - int result; - /* - * fetch/print media info - */ - media = IFM_MAKEWORD(0,0,0,sc->phy_default); /* fetch from default phy */ - - result = tsec_ioctl(&(sc->arpcom.ac_if), - SIOCGIFMEDIA, - (caddr_t)&media); - if (result == 0) { - rtems_ifmedia2str(media,NULL,0); - printf ("\n"); - } else { - printf ("PHY communication error\n"); - } - } -#if 0 /* print all PHY registers */ - { - int reg; - uint32_t reg_val; - printf("****** PHY register values****\n"); - for (reg = 0;reg <= 31;reg++) { - tsec_mdio_read(-1,sc,reg,®_val); - printf("%02d:0x%04x%c",reg,reg_val, - (((reg % 4) == 3) ? '\n' : ' ')); - } - } -#endif - /* - * print some statistics - */ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Rx Errors:%-8lu", sc->rxErrors); - printf (" Rx packets:%-8lu\n", - sc->reg_ptr->rmon_mib[TSEC_RMON_RPKT]); - printf (" Rx broadcasts:%-8lu", - sc->reg_ptr->rmon_mib[TSEC_RMON_RBCA]); - printf (" Rx multicasts:%-8lu", - sc->reg_ptr->rmon_mib[TSEC_RMON_RMCA]); - printf (" Giant:%-8lu\n", - sc->reg_ptr->rmon_mib[TSEC_RMON_ROVR]); - printf (" Non-octet:%-8lu", - sc->reg_ptr->rmon_mib[TSEC_RMON_RALN]); - printf (" Bad CRC:%-8lu", - sc->reg_ptr->rmon_mib[TSEC_RMON_RFCS]); - printf (" Overrun:%-8lu\n", - sc->reg_ptr->rmon_mib[TSEC_RMON_RDRP]); - - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Tx Errors:%-8lu", sc->txErrors); - printf (" Tx packets:%-8lu\n", - sc->reg_ptr->rmon_mib[TSEC_RMON_TPKT]); - printf (" Deferred:%-8lu", - sc->reg_ptr->rmon_mib[TSEC_RMON_TDFR]); - printf (" Late Collision:%-8lu", - sc->reg_ptr->rmon_mib[TSEC_RMON_TLCL]); - printf ("Retransmit Limit:%-8lu\n", - sc->reg_ptr->rmon_mib[TSEC_RMON_TEDF]); - printf (" Underrun:%-8lu\n", - sc->reg_ptr->rmon_mib[TSEC_RMON_TUND]); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int tsec_ioctl -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| perform io control functions | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct ifnet *ifp, /* interface information */ - ioctl_command_t command, /* ioctl command code */ - caddr_t data /* optional data */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| zero, if success | -\*=========================================================================*/ -{ - struct tsec_struct *sc = ifp->if_softc; - int error = 0; - - switch(command) { - /* - * access PHY via MII - */ - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - rtems_mii_ioctl (&(sc->mdio_info),sc,command,(void *)data); - break; - case SIOCGIFADDR: - case SIOCSIFADDR: - /* - * pass through to general ether_ioctl - */ - ether_ioctl(ifp, command, data); - break; - - case SIOCSIFFLAGS: - /* - * adjust active state - */ - if (ifp->if_flags & IFF_RUNNING) { - tsec_off(sc); - } - if (ifp->if_flags & IFF_UP) { - tsec_init(sc); - } - break; - - case SIO_RTEMS_SHOW_STATS: - /* - * show interface statistics - */ - tsec_stats(sc); - break; - - /* - * All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - - return error; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int tsec_mode_adapt -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| init the PHY and adapt TSEC settings | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct ifnet *ifp -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| 0, if success | -\*=========================================================================*/ -{ - int result = 0; - struct tsec_struct *sc = ifp->if_softc; - int media = IFM_MAKEWORD( 0, 0, 0, sc->phy_default); - - /* In case no PHY is available stop now */ - if (sc->phy_default < 0) { - return 0; - } - - /* - * fetch media status - */ - result = tsec_ioctl(ifp,SIOCGIFMEDIA,(caddr_t)&media); - if (result != 0) { - return result; - } - - /* - * status is unchanged? then do nothing - */ - if (media == sc->media_state) { - return 0; - } - /* - * otherwise: for the first call, try to negotiate mode - */ - if (sc->media_state == 0) { - /* - * set media status: set auto negotiation -> start auto-negotiation - */ - media = IFM_MAKEWORD(0,IFM_AUTO,0,sc->phy_default); - result = tsec_ioctl(ifp,SIOCSIFMEDIA,(caddr_t)&media); - if (result != 0) { - return result; - } - /* - * check auto-negotiation status - */ - media = IFM_MAKEWORD(0,0,0,sc->phy_default); - result = tsec_ioctl(ifp,SIOCGIFMEDIA,(caddr_t)&media); - if (result != 0 || IFM_NONE == IFM_SUBTYPE(media)) { - return result; - } - } - - /* - * now set HW according to media results: - */ - /* - * if we are 1000MBit, then switch IF to byte mode - */ - if (IFM_1000_T == IFM_SUBTYPE(media)) { - sc->reg_ptr->maccfg2 = - ((sc->reg_ptr->maccfg2 & ~TSEC_MACCFG2_IFMODE_MSK) - | TSEC_MACCFG2_IFMODE_BYT); - } - else { - sc->reg_ptr->maccfg2 = - ((sc->reg_ptr->maccfg2 & ~TSEC_MACCFG2_IFMODE_MSK) - | TSEC_MACCFG2_IFMODE_NIB); - } - /* - * if we are 10MBit, then switch rate to 10M - */ - if (IFM_10_T == IFM_SUBTYPE(media)) { - sc->reg_ptr->ecntrl &= ~TSEC_ECNTRL_R100M; - } - else { - sc->reg_ptr->ecntrl |= TSEC_ECNTRL_R100M; - } - /* - * if we are half duplex then switch to half duplex - */ - if (0 == (IFM_FDX & IFM_OPTIONS(media))) { - sc->reg_ptr->maccfg2 &= ~TSEC_MACCFG2_FULLDUPLEX; - } - else { - sc->reg_ptr->maccfg2 |= TSEC_MACCFG2_FULLDUPLEX; - } - /* - * store current media state for future compares - */ - sc->media_state = media; - - return 0; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void tsec_watchdog -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| periodically poll the PHY. if mode has changed, | -| then adjust the TSEC settings | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - struct ifnet *ifp -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| 1, if success | -\*=========================================================================*/ -{ - tsec_mode_adapt(ifp); - ifp->if_timer = TSEC_WATCHDOG_TIMEOUT; -} - -static int tsec_driver_attach(struct rtems_bsdnet_ifconfig *config) -{ - tsec_config *tsec_cfg = config->drv_ctrl; - int unitNumber = tsec_cfg->unit_number; - char *unitName = tsec_cfg->unit_name; - struct tsec_struct *sc; - struct ifnet *ifp; - - /* - * Is driver free? - */ - if ((unitNumber <= 0) || (unitNumber > TSEC_COUNT)) { - - printk ("Bad TSEC unit number.\n"); - return 0; - - } - - sc = &tsec_driver[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - - if(ifp->if_softc != NULL) { - printk ("Driver already in use.\n"); - return 0; - } - - /* - * Process options - */ - if(config->hardware_address) { - memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - else { - rtems_panic("TSEC: No Ethernet address specified!\n"); - } - - sc->rxBdCount = (config->rbuf_count > 0) ? config->rbuf_count : RX_BUF_COUNT; - sc->txBdCount = (config->xbuf_count > 0) ? config->xbuf_count : TX_BUF_COUNT; - sc->acceptBroadcast = !config->ignore_broadcast; - - /* get pointer to TSEC register block */ - sc->reg_ptr = tsec_cfg->reg_ptr; - sc->mdio_ptr = tsec_cfg->mdio_ptr; - - /* IRQ numbers */ - sc->irq_num_tx = tsec_cfg->irq_num_tx; - sc->irq_num_rx = tsec_cfg->irq_num_rx; - sc->irq_num_err = tsec_cfg->irq_num_err; - - /* - * setup info about mdio interface - */ - sc->mdio_info.mdio_r = tsec_mdio_read; - sc->mdio_info.mdio_w = tsec_mdio_write; - sc->mdio_info.has_gmii = 1; /* we support gigabit IF */ - - /* PHY address */ - sc->phy_default = tsec_cfg->phy_default; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = (config->mtu > 0) ? config->mtu : ETHERMTU; - ifp->if_init = tsec_init; - ifp->if_ioctl = tsec_ioctl; - ifp->if_start = tsec_tx_start; - ifp->if_output = ether_output; - ifp->if_watchdog = tsec_watchdog; /* XXX: timer is set in "init" */ - - ifp->if_flags = (config->ignore_broadcast) ? 0 : IFF_BROADCAST; - /*ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;*/ - - if(ifp->if_snd.ifq_maxlen == 0) { - ifp->if_snd.ifq_maxlen = ifqmaxlen; - } - - /* - * Attach the interface - */ - if_attach(ifp); - - ether_ifattach(ifp); - - return 1; -} - -int tsec_driver_attach_detach( - struct rtems_bsdnet_ifconfig *config, - int attaching -) -{ - if (attaching) { - return tsec_driver_attach(config); - } else { - return 0; - } -} diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c b/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c deleted file mode 100644 index 5534b4b72a..0000000000 --- a/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c +++ /dev/null @@ -1,675 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS support for MPC83xx | -+-----------------------------------------------------------------+ -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@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. | -| | -+-----------------------------------------------------------------+ -| this file contains the MPC83xx SPI driver | -| NOTE: it uses the same API as the I2C driver | -\*===============================================================*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code mpc83xx_spi_baud_to_mode -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| determine proper divider value | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - uint32_t baudrate, /* desired baudrate */ - uint32_t base_frq, /* input frequency */ - uint32_t *spimode /* result value */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - uint32_t divider; - uint32_t tmpmode = 0; - /* - * determine clock divider and DIV16 bit - */ - divider = (base_frq+baudrate-1)/baudrate; - if (divider > 64) { - tmpmode = MPC83XX_SPIMODE_DIV16; - divider /= 16; - } - if ((divider < 1) || - (divider > 64)) { - return RTEMS_INVALID_NUMBER; - } - else { - tmpmode |= MPC83XX_SPIMODE_PM(divider/4-1); - } - *spimode = tmpmode; - return RTEMS_SUCCESSFUL; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static rtems_status_code mpc83xx_spi_char_mode -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| determine proper value for character size | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - mpc83xx_spi_softc_t *softc_ptr, /* handle */ - uint32_t bits_per_char, /* bits per character */ - bool lsb_first, /* TRUE: send LSB first */ - uint32_t *spimode /* result value */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - uint32_t tmpmode; - - if (bits_per_char == 32) { - tmpmode = 0; - softc_ptr->bytes_per_char = 4; - softc_ptr->bit_shift = 0; - } - else { - if (lsb_first) { - /* - * non-reversed data (LSB first): 4..16 bits valid - * always aligned to bit 16 of data register - */ - if ((bits_per_char >= 4) && - (bits_per_char <= 16)) { - tmpmode = MPC83XX_SPIMODE_LEN( bits_per_char-1); - softc_ptr->bytes_per_char = (bits_per_char > 8) ? 2 : 1; - softc_ptr->bit_shift = 16-bits_per_char; - } - else { - return RTEMS_INVALID_NUMBER; - } - } - else { - /* - * reversed data (MSB first): only 8/16/32 bits valid, - * always in lowest bits of data register - */ - if (bits_per_char == 8) { - tmpmode = MPC83XX_SPIMODE_LEN(8-1); - softc_ptr->bytes_per_char = 1; - softc_ptr->bit_shift = 0; - } - else if (bits_per_char == 16) { - tmpmode = MPC83XX_SPIMODE_LEN(16-1); - softc_ptr->bytes_per_char = 2; - softc_ptr->bit_shift = 0; - } - else { - return RTEMS_INVALID_NUMBER; - } - } - } - - *spimode = tmpmode; - return 0; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int mpc83xx_spi_wait -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| wait for spi to become idle | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - mpc83xx_spi_softc_t *softc_ptr, /* handle */ - uint32_t irq_mask, /* irq mask to use */ - uint32_t desired_status, /* desired status word */ - uint32_t status_mask /* status word mask */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - uint32_t act_status; - rtems_status_code rc; - uint32_t tout; - -#if defined(DEBUG) - printk("mpc83xx_spi_wait called... "); -#endif - if (softc_ptr->initialized) { - /* - * allow interrupts, when receiver is not empty - */ - softc_ptr->reg_ptr->spim = irq_mask; - rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id,RTEMS_WAIT,100); - if (rc != RTEMS_SUCCESSFUL) { - return rc; - } - } - else { - tout = 0; - do { - if (tout++ > 1000000) { -#if defined(DEBUG) - printk("... exit with RTEMS_TIMEOUT\r\n"); -#endif - return RTEMS_TIMEOUT; - } - /* - * wait for SPI to terminate - */ - } while (!(softc_ptr->reg_ptr->spie & MPC83XX_SPIE_NE)); - } - - act_status = softc_ptr->reg_ptr->spie; - if ((act_status & status_mask)!= desired_status) { -#if defined(DEBUG) - printk("... exit with RTEMS_IO_ERROR," - "act_status=0x%04x,mask=0x%04x,desired_status=0x%04x\r\n", - act_status,status_mask,desired_status); -#endif - return RTEMS_IO_ERROR; - } -#if defined(DEBUG) - printk("... exit OK\r\n"); -#endif - return RTEMS_SUCCESSFUL; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void mpc83xx_spi_irq_handler -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| handle interrupts | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_irq_hdl_param handle /* handle, is softc_ptr structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - mpc83xx_spi_softc_t *softc_ptr = (mpc83xx_spi_softc_t *)handle; - - /* - * disable interrupt mask - */ - softc_ptr->reg_ptr->spim = 0; - if (softc_ptr->initialized) { - rtems_semaphore_release(softc_ptr->irq_sema_id); - } -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void mpc83xx_spi_irq_on_off -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| enable/disable interrupts (void, handled at different position) | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - const - rtems_irq_connect_data *irq_conn_data /* irq connect data */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ -} - - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static int mpc83xx_spi_irq_isOn -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| check state of interrupts, void, done differently | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - const - rtems_irq_connect_data *irq_conn_data /* irq connect data */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| TRUE, if enabled | -\*=========================================================================*/ -{ - return (TRUE); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -static void mpc83xx_spi_install_irq_handler -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| (un-)install the interrupt handler | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - mpc83xx_spi_softc_t *softc_ptr, /* ptr to control structure */ - int install /* TRUE: install, FALSE: remove */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - - rtems_irq_connect_data irq_conn_data = { - softc_ptr->irq_number, - mpc83xx_spi_irq_handler, /* rtems_irq_hdl */ - (rtems_irq_hdl_param)softc_ptr, /* (rtems_irq_hdl_param) */ - mpc83xx_spi_irq_on_off, /* (rtems_irq_enable) */ - mpc83xx_spi_irq_on_off, /* (rtems_irq_disable) */ - mpc83xx_spi_irq_isOn /* (rtems_irq_is_enabled) */ - }; - - /* - * (un-)install handler for SPI device - */ - if (install) { - /* - * create semaphore for IRQ synchronization - */ - rc = rtems_semaphore_create(rtems_build_name('s','p','i','s'), - 0, - RTEMS_FIFO - | RTEMS_SIMPLE_BINARY_SEMAPHORE, - 0, - &softc_ptr->irq_sema_id); - if (rc != RTEMS_SUCCESSFUL) { - rtems_panic("SPI: cannot create semaphore"); - } - if (!BSP_install_rtems_irq_handler (&irq_conn_data)) { - rtems_panic("SPI: cannot install IRQ handler"); - } - } - else { - if (!BSP_remove_rtems_irq_handler (&irq_conn_data)) { - rtems_panic("SPI: cannot uninstall IRQ handler"); - } - /* - * delete sync semaphore - */ - if (softc_ptr->irq_sema_id != 0) { - rc = rtems_semaphore_delete(softc_ptr->irq_sema_id); - if (rc != RTEMS_SUCCESSFUL) { - rtems_panic("SPI: cannot delete semaphore"); - } - } - } -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_status_code mpc83xx_spi_init -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| initialize the driver | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh /* bus specifier structure */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - mpc83xx_spi_softc_t *softc_ptr = &(((mpc83xx_spi_desc_t *)(bh))->softc); -#if defined(DEBUG) - printk("mpc83xx_spi_init called... "); -#endif - /* - * init HW registers: - */ - /* - * FIXME: set default mode in SPIM - */ - - /* - * init interrupt stuff - */ - mpc83xx_spi_install_irq_handler(softc_ptr,TRUE); - - /* - * mark, that we have initialized - */ - softc_ptr->initialized = TRUE; -#if defined(DEBUG) - printk("... exit OK\r\n"); -#endif - return RTEMS_SUCCESSFUL; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -int mpc83xx_spi_read_write_bytes -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| transmit/receive some bytes from SPI device | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh, /* bus specifier structure */ - unsigned char *rbuf, /* buffer to store bytes */ - const unsigned char *tbuf, /* buffer to send bytes */ - int len /* number of bytes to transceive */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| number of bytes received or (negative) error code | -\*=========================================================================*/ -{ - mpc83xx_spi_softc_t *softc_ptr = &(((mpc83xx_spi_desc_t *)(bh))->softc); - rtems_status_code rc; - int bc = 0; - int bytes_per_char = softc_ptr->bytes_per_char; - int bit_shift = softc_ptr->bit_shift; - uint32_t spird_val; - -#if defined(DEBUG) - printk("mpc83xx_spi_read_write_bytes called... "); -#endif - - while (len > bytes_per_char-1) { - len -= bytes_per_char; - /* - * mark last byte in SPCOM - */ -#if defined(USE_LAST_BIT) - softc_ptr->reg_ptr->spcom = (len < bytes_per_char) ? MPC83XX_SPCOM_LST : 0; -#else - softc_ptr->reg_ptr->spcom = 0; -#endif - if (tbuf == NULL) { - /* - * perform idle char write to read byte - */ - softc_ptr->reg_ptr->spitd = softc_ptr->idle_char << bit_shift; - } - else { - switch(bytes_per_char) { - case 1: - softc_ptr->reg_ptr->spitd = (*(uint8_t *)tbuf) << bit_shift; - break; - case 2: - softc_ptr->reg_ptr->spitd = (*(uint16_t *)tbuf) << bit_shift; - break; - case 4: - softc_ptr->reg_ptr->spitd = (*(uint32_t *)tbuf) << bit_shift; - break; - } - tbuf += softc_ptr->bytes_per_char; - } - /* - * wait 'til end of transfer - */ -#if defined(USE_LAST_BIT) - rc = mpc83xx_spi_wait(softc_ptr, - ((len == 0) - ? MPC83XX_SPIE_LT - : MPC83XX_SPIE_NE), - ((len == 0) - ? MPC83XX_SPIE_LT - : MPC83XX_SPIE_NF) - | MPC83XX_SPIE_NE, - MPC83XX_SPIE_LT - | MPC83XX_SPIE_OV - | MPC83XX_SPIE_UN - | MPC83XX_SPIE_NE - | MPC83XX_SPIE_NF); - if (len == 0) { - /* - * clear the "last transfer complete" event - */ - softc_ptr->reg_ptr->spie = MPC83XX_SPIE_LT; - } -#else - rc = mpc83xx_spi_wait(softc_ptr, - MPC83XX_SPIE_NE, - MPC83XX_SPIE_NF - | MPC83XX_SPIE_NE, - MPC83XX_SPIE_OV - | MPC83XX_SPIE_UN - | MPC83XX_SPIE_NE - | MPC83XX_SPIE_NF); -#endif - if (rc != RTEMS_SUCCESSFUL) { -#if defined(DEBUG) - printk("... exit rc=%d\r\n",-rc); -#endif - return -rc; - } - spird_val = softc_ptr->reg_ptr->spird; - if (rbuf != NULL) { - switch(bytes_per_char) { - case 1: - (*(uint8_t *)rbuf) = spird_val >> bit_shift; - break; - case 2: - (*(uint16_t *)rbuf) = spird_val >> bit_shift; - break; - case 4: - (*(uint32_t *)rbuf) = spird_val >> bit_shift; - break; - } - rbuf += bytes_per_char; - } - bc += bytes_per_char; - } -#if defined(DEBUG) - printk("... exit OK, rc=%d\r\n",bc); -#endif - return bc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -int mpc83xx_spi_read_bytes -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| receive some bytes from SPI device | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh, /* bus specifier structure */ - unsigned char *buf, /* buffer to store bytes */ - int len /* number of bytes to receive */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| number of bytes received or (negative) error code | -\*=========================================================================*/ -{ - return mpc83xx_spi_read_write_bytes(bh,buf,NULL,len); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -int mpc83xx_spi_write_bytes -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| send some bytes to SPI device | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh, /* bus specifier structure */ - unsigned char *buf, /* buffer to send */ - int len /* number of bytes to send */ - -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| number of bytes sent or (negative) error code | -\*=========================================================================*/ -{ - return mpc83xx_spi_read_write_bytes(bh,NULL,buf,len); -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_status_code mpc83xx_spi_set_tfr_mode -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| set SPI to desired baudrate/clock mode/character mode | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh, /* bus specifier structure */ - const rtems_libi2c_tfr_mode_t *tfr_mode /* transfer mode info */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - mpc83xx_spi_softc_t *softc_ptr = &(((mpc83xx_spi_desc_t *)(bh))->softc); - uint32_t spimode_baud,spimode; - rtems_status_code rc = RTEMS_SUCCESSFUL; - - /* Set idle character */ - softc_ptr->idle_char = tfr_mode->idle_char; - - /* - * FIXME: set proper mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = mpc83xx_spi_baud_to_mode(tfr_mode->baudrate, - softc_ptr->base_frq, - &spimode_baud); - } - if (rc == RTEMS_SUCCESSFUL) { - rc = mpc83xx_spi_char_mode(softc_ptr, - tfr_mode->bits_per_char, - tfr_mode->lsb_first, - &spimode); - } - if (rc == RTEMS_SUCCESSFUL) { - spimode |= spimode_baud; - spimode |= MPC83XX_SPIMODE_M_S; /* set master mode */ - if (!tfr_mode->lsb_first) { - spimode |= MPC83XX_SPIMODE_REV; - } - if (tfr_mode->clock_inv) { - spimode |= MPC83XX_SPIMODE_CI; - } - if (tfr_mode->clock_phs) { - spimode |= MPC83XX_SPIMODE_CP; - } - } - - if (rc == RTEMS_SUCCESSFUL) { - /* - * disable SPI - */ - softc_ptr->reg_ptr->spmode &= ~MPC83XX_SPIMODE_EN; - /* - * set new mode and reenable SPI - */ - softc_ptr->reg_ptr->spmode = spimode | MPC83XX_SPIMODE_EN; - } - return rc; -} - - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -int mpc83xx_spi_ioctl -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| perform selected ioctl function for SPI | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_libi2c_bus_t *bh, /* bus specifier structure */ - int cmd, /* ioctl command code */ - void *arg /* additional argument array */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| rtems_status_code | -\*=========================================================================*/ -{ - int ret_val = -1; - - switch(cmd) { - case RTEMS_LIBI2C_IOCTL_SET_TFRMODE: - ret_val = - -mpc83xx_spi_set_tfr_mode(bh, - (const rtems_libi2c_tfr_mode_t *)arg); - break; - case RTEMS_LIBI2C_IOCTL_READ_WRITE: - ret_val = - mpc83xx_spi_read_write_bytes(bh, - ((rtems_libi2c_read_write_t *)arg)->rd_buf, - ((rtems_libi2c_read_write_t *)arg)->wr_buf, - ((rtems_libi2c_read_write_t *)arg)->byte_cnt); - break; - default: - ret_val = -RTEMS_NOT_DEFINED; - break; - } - return ret_val; -} - - - -- cgit v1.2.3