diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2008-07-14 16:15:28 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2008-07-14 16:15:28 +0000 |
commit | 574fb675105b77dfe9598915207f1f32790f905f (patch) | |
tree | fce34dc59687abc02a692c650ec3c86f05259025 /c/src/lib/libcpu/powerpc/mpc83xx | |
parent | added haleakala BSP contributed by Michael Hamel (diff) | |
download | rtems-574fb675105b77dfe9598915207f1f32790f905f.tar.bz2 |
updated gen83xx BSP
updated haleakala BSP
added MPC55xx BSP
Diffstat (limited to 'c/src/lib/libcpu/powerpc/mpc83xx')
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c | 274 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c | 12 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc83xx/include/gtm.h | 66 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c | 87 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c | 8 | ||||
-rw-r--r-- | c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.h | 1 |
6 files changed, 422 insertions, 26 deletions
diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c b/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c new file mode 100644 index 0000000000..ddb175d30a --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc83xx/gtm/gtm.c @@ -0,0 +1,274 @@ +/** + * @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.com/license/LICENSE. + */ + +#include <rtems/bspIo.h> + +#include <mpc83xx/mpc83xx.h> +#include <mpc83xx/gtm.h> + +#define RTEMS_STATUS_CHECKS_USE_PRINTK + +#include <rtems/status-checks.h> + +#define MPC83XX_GTM_CHECK_INDEX( timer) \ + if (( timer) < 0 || ( timer) >= MPC83XX_GTM_NUMBER) { \ + return RTEMS_INVALID_NUMBER; \ + } + +#define MPC83XX_GTM_VARIABLES( timer) \ + int module = (timer) / 4; \ + int module_timer = (timer) % 4; \ + int high = module_timer / 2; \ + int low = module_timer % 2; \ + rtems_interrupt_level level; + +#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 }; + +static const uint8_t mpc83xx_gmt_interrupt_priority_table [MPC83XX_GTM_NUMBER] = { 113, 77, 95, 59, 116, 80, 98, 62 }; + +rtems_status_code mpc83xx_gtm_initialize( int timer, int clock) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + MPC83XX_GTM_VARIABLES( timer); + + uint8_t mask = 0xf << (low * 4); + uint8_t flags = 0x3 << (low * 4); + uint16_t reg = 0; + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + + reg = mpc83xx.gtm [module].gtcfr [high].reg; + mpc83xx.gtm [module].gtcfr [high].reg = (reg & ~mask) | flags; + + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] = 0; + + rtems_interrupt_enable( level); + + sc = mpc83xx_gtm_set_clock( timer, clock); + CHECK_SC( sc, "Set clock"); + + sc = mpc83xx_gtm_set_value( timer, 0); + CHECK_SC( sc, "Set value"); + + sc = mpc83xx_gtm_set_reference( timer, 0); + CHECK_SC( sc, "Set reference"); + + sc = mpc83xx_gtm_set_prescale( timer, 0); + CHECK_SC( sc, "Set prescale"); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_enable_restart( int timer, bool enable) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + + if (enable) { + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] |= 0x0008; + } else { + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] &= ~0x0008; + } + + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_set_clock( int timer, int clock) +{ + MPC83XX_GTM_VARIABLES( timer); + + 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 [module].gt_tim_regs [high].gtmdr [low]; + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] = (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_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + *clock = mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] & MPC83XX_GTM_CLOCK_MASK; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_start( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + uint8_t flags = 0x2 << (low * 4); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + mpc83xx.gtm [module].gtcfr [high].reg &= ~flags; + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_stop( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + uint8_t flags = 0x2 << (low * 4); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + mpc83xx.gtm [module].gtcfr [high].reg |= flags; + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_set_value( int timer, uint16_t value) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + mpc83xx.gtm [module].gt_tim_regs [high].gtcnr [low] = value; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_get_value( int timer, uint16_t *value) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + *value = mpc83xx.gtm [module].gt_tim_regs [high].gtcnr [low]; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_set_reference( int timer, uint16_t reference) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + mpc83xx.gtm [module].gt_tim_regs [high].gtrfr [low] = reference; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_get_reference( int timer, uint16_t *reference) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + reference = mpc83xx.gtm [module].gt_tim_regs [high].gtrfr [low]; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_set_prescale( int timer, uint8_t prescale) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + mpc83xx.gtm [module].gtpsr [module_timer] = prescale; + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_get_prescale( int timer, uint8_t *prescale) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + prescale = mpc83xx.gtm [module].gtpsr [module_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) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] |= 0x0010; + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_interrupt_disable( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + rtems_interrupt_disable( level); + mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] &= ~0x0010; + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_gtm_interrupt_clear( int timer) +{ + MPC83XX_GTM_VARIABLES( timer); + + MPC83XX_GTM_CHECK_INDEX( timer); + + mpc83xx.gtm [module].gtevr [module_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 index af408dd5f6..35e9ae237d 100644 --- a/c/src/lib/libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c +++ b/c/src/lib/libcpu/powerpc/mpc83xx/i2c/mpc83xx_i2cdrv.c @@ -619,11 +619,11 @@ static int mpc83xx_i2c_write_bytes } 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, + .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/include/gtm.h b/c/src/lib/libcpu/powerpc/mpc83xx/include/gtm.h new file mode 100644 index 0000000000..4c7f7995b3 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/mpc83xx/include/gtm.h @@ -0,0 +1,66 @@ +/** + * @file + * + * @brief Header 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.com/license/LICENSE. + */ + +#ifndef LIBBSP_POWERPC_MPC83XX_TIMER_H +#define LIBBSP_POWERPC_MPC83XX_TIMER_H + +#include <stdint.h> +#include <stdbool.h> + +#include <rtems.h> + +#define MPC83XX_GTM_NUMBER 8 + +#define MPC83XX_GTM_CLOCK_CASCADED 0x0000 +#define MPC83XX_GTM_CLOCK_SYSTEM 0x0002 +#define MPC83XX_GTM_CLOCK_SYSTEM_SLOW 0x0004 +#define MPC83XX_GTM_CLOCK_EXTERN 0x0006 + +rtems_status_code mpc83xx_gtm_initialize( int timer, int clock); + +rtems_status_code mpc83xx_gtm_enable_restart( int timer, bool enable); + +rtems_status_code mpc83xx_gtm_set_clock( int timer, int clock); + +rtems_status_code mpc83xx_gtm_get_clock( int timer, int *clock); + +rtems_status_code mpc83xx_gtm_start( int timer); + +rtems_status_code mpc83xx_gtm_stop( int timer); + +rtems_status_code mpc83xx_gtm_set_value( int timer, uint16_t value); + +rtems_status_code mpc83xx_gtm_get_value( int timer, uint16_t *value); + +rtems_status_code mpc83xx_gtm_set_reference( int timer, uint16_t reference); + +rtems_status_code mpc83xx_gtm_get_reference( int timer, uint16_t *reference); + +rtems_status_code mpc83xx_gtm_set_prescale( int timer, uint8_t prescale); + +rtems_status_code mpc83xx_gtm_get_prescale( int timer, uint8_t *prescale); + +rtems_status_code mpc83xx_gtm_interrupt_get_vector( int timer, rtems_vector_number *vector); + +rtems_status_code mpc83xx_gtm_interrupt_enable( int timer); + +rtems_status_code mpc83xx_gtm_interrupt_disable( int timer); + +rtems_status_code mpc83xx_gtm_interrupt_clear( int timer); + +#endif /* LIBBSP_POWERPC_MPC83XX_TIMER_H */ diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c b/c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c index 501b31e4ec..32812114ab 100644 --- a/c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c +++ b/c/src/lib/libcpu/powerpc/mpc83xx/network/tsec.c @@ -27,6 +27,7 @@ #include <bsp/irq.h> #include <mpc83xx/mpc83xx.h> #include <mpc83xx/tsec.h> +#include <libcpu/spr.h> #include <rtems/error.h> #include <rtems/bspIo.h> #include <rtems/rtems_bsdnet.h> @@ -43,6 +44,13 @@ #include <netinet/if_ether.h> #include <stdio.h> +/* System Version Register */ +#define SVR 286 +SPR_RO( SVR) + +/* Processor Version Register */ +SPR_RO( PVR) + #define CLREVENT_IN_IRQ #define TSEC_WATCHDOG_TIMEOUT 5 /* check media every 5 seconds */ @@ -57,7 +65,8 @@ struct mpc83xx_tsec_struct { /* * HW links: (filled from rtems_bsdnet_ifconfig */ - m83xxTSEC_Registers_t *reg_ptr; /* pointer to TSEC register block */ + m83xxTSEC_Registers_t *reg_ptr; /* pointer to TSEC register block */ + m83xxTSEC_Registers_t *mdio_ptr; /* pointer to TSEC register block which is responsible for MDIO communication */ int irq_num_tx; /* tx irq number */ int irq_num_rx; /* rx irq number */ int irq_num_err; /* error irq number */ @@ -192,7 +201,7 @@ static void mpc83xx_tsec_hwinit { m83xxTSEC_Registers_t *reg_ptr = sc->reg_ptr; /* pointer to TSEC registers*/ uint8_t *mac_addr; - int i; + size_t i; /* * init ECNTL register @@ -272,9 +281,9 @@ static void mpc83xx_tsec_hwinit /* * init MACCFG2 register */ - reg_ptr->maccfg2 = ((reg_ptr->maccfg2 & M83xx_TSEC_MACCFG2_IFMODE_MSK) - | M83xx_TSEC_MACCFG2_PRELEN(7) - | M83xx_TSEC_MACCFG2_FULLDUPLEX); + reg_ptr->maccfg2 = (reg_ptr->maccfg2 & M83xx_TSEC_MACCFG2_IFMODE_MSK) + | M83xx_TSEC_MACCFG2_PRELEN( 7) + | M83xx_TSEC_MACCFG2_FULLDUPLEX; /* * init station address register @@ -324,10 +333,19 @@ static void mpc83xx_tsec_mdio_init | <none> | \*=========================================================================*/ { + + /* Set TSEC registers for MDIO communication */ + + /* + * FIXME: Not clear if this works for all boards. + * Tested only on MPC8313ERDB. + */ + sc->mdio_ptr = &mpc83xx.tsec [0]; + /* * set clock divider */ - sc->reg_ptr->miimcfg = 3; + sc->mdio_ptr->miimcfg = 3; } /*=========================================================================*\ @@ -351,10 +369,10 @@ int mpc83xx_tsec_mdio_read | 0, if ok, else error | \*=========================================================================*/ { - struct mpc83xx_tsec_struct *sc = uarg;/* control structure */ - m83xxTSEC_Registers_t *reg_ptr; /* pointer to TSEC registers */ + struct mpc83xx_tsec_struct *sc = uarg;/* control structure */ - reg_ptr = sc->reg_ptr; + /* pointer to TSEC registers */ + m83xxTSEC_Registers_t *reg_ptr = sc->mdio_ptr; /* * make sure we work with a valid phy @@ -419,10 +437,10 @@ int mpc83xx_tsec_mdio_write | 0, if ok, else error | \*=========================================================================*/ { - struct mpc83xx_tsec_struct *sc = uarg;/* control structure */ - m83xxTSEC_Registers_t *reg_ptr; /* pointer to TSEC registers */ + struct mpc83xx_tsec_struct *sc = uarg;/* control structure */ - reg_ptr = sc->reg_ptr; + /* pointer to TSEC registers */ + m83xxTSEC_Registers_t *reg_ptr = sc->mdio_ptr; /* * make sure we work with a valid phy @@ -1685,9 +1703,9 @@ int rtems_mpc83xx_tsec_mode_adapt | 0, if success | \*=========================================================================*/ { - int result; - int media; + int result = 0; struct mpc83xx_tsec_struct *sc = ifp->if_softc; + int media = IFM_MAKEWORD( 0, 0, 0, sc->phy_default); #ifdef DEBUG printf("c"); @@ -1819,6 +1837,8 @@ static int mpc83xx_tsec_driver_attach struct ifnet *ifp; int unitNumber; char *unitName; + uint32_t svr = _read_SVR(); + uint32_t pvr = _read_PVR(); /* * Parse driver name @@ -1865,10 +1885,30 @@ static int mpc83xx_tsec_driver_attach /* get pointer to TSEC register block */ sc->reg_ptr = &mpc83xx.tsec[unitNumber-1]; - /* get base interrupt number (for Tx irq, Rx=base+1,Err=base+2) */ - sc->irq_num_tx = config->irno + 0; /* tx irq number from BSP */ - sc->irq_num_rx = config->irno + 1; /* rx irq number from BSP */ - sc->irq_num_err = config->irno + 2; /* err irq number from BSP */ + + if (svr == 0x80b00010 && pvr == 0x80850010) { + /* + * This is a special case for MPC8313ERDB with silicon revision 1. Look in + * "MPC8313ECE Rev. 3, 3/2008" errata for "IPIC 1". + */ + if (unitNumber == 1) { + sc->irq_num_tx = 37; + sc->irq_num_rx = 36; + sc->irq_num_err = 35; + } else if (unitNumber == 2) { + sc->irq_num_tx = 34; + sc->irq_num_rx = 33; + sc->irq_num_err = 32; + } else { + return 0; + } + } else { + /* get base interrupt number (for Tx irq, Rx=base+1,Err=base+2) */ + sc->irq_num_tx = config->irno + 0; /* tx irq number from BSP */ + sc->irq_num_rx = config->irno + 1; /* rx irq number from BSP */ + sc->irq_num_err = config->irno + 2; /* err irq number from BSP */ + } + if (config->irno == 0) { rtems_panic("TSEC: interupt base number irno not defined"); } @@ -1878,11 +1918,22 @@ static int mpc83xx_tsec_driver_attach sc->mdio_info.mdio_r = mpc83xx_tsec_mdio_read; sc->mdio_info.mdio_w = mpc83xx_tsec_mdio_write; sc->mdio_info.has_gmii = 1; /* we support gigabit IF */ + /* * XXX: Although most hardware builders will assign the PHY addresses * like this, this should be more configurable */ +#ifdef MPC8313ERDB + if (unitNumber == 2) { + sc->phy_default = 4; + } else { + /* TODO */ + return 0; + } +#else /* MPC8313ERDB */ sc->phy_default = unitNumber-1; +#endif /* MPC8313ERDB */ + /* * Set up network interface values */ diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c b/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c index e94c72e7f6..2d46fc13ca 100644 --- a/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c +++ b/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.c @@ -434,9 +434,9 @@ int mpc83xx_spi_read_write_bytes #endif if (tbuf == NULL) { /* - * perform dummy write to read byte + * perform idle char write to read byte */ - softc_ptr->reg_ptr->spitd = 0; + softc_ptr->reg_ptr->spitd = softc_ptr->idle_char << bit_shift; } else { switch(bytes_per_char) { @@ -583,6 +583,10 @@ rtems_status_code mpc83xx_spi_set_tfr_mode 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 */ diff --git a/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.h b/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.h index 475419959d..ba98d3413c 100644 --- a/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.h +++ b/c/src/lib/libcpu/powerpc/mpc83xx/spi/mpc83xx_spidrv.h @@ -35,6 +35,7 @@ typedef struct mpc83xx_spi_softc { uint32_t base_frq; /* input frq for baud rate divider */ rtems_id irq_sema_id; uint32_t curr_addr; /* current spi address */ + uint32_t idle_char; uint8_t bytes_per_char; uint8_t bit_shift; } mpc83xx_spi_softc_t ; |