diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h index c442b5868f..fd6d842625 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h @@ -53,11 +53,12 @@ typedef enum { } ADCName; typedef enum { - SPI_0 = (int)MPS2_SSP0_BASE, - SPI_1 = (int)MPS2_SSP1_BASE, - SPI_2 = (int)MPS2_SSP2_BASE, - SPI_3 = (int)MPS2_SSP3_BASE, - SPI_4 = (int)MPS2_SSP4_BASE + SPI_0 = 0, + SPI_1, + SPI_2, + SPI_3, + SPI_4, + SPI_NC = (SPI_4 + 1) } SPIName; typedef enum { diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/SMM_MPS2.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/SMM_MPS2.h index 0920930a2d..462e740ea9 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/SMM_MPS2.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/SMM_MPS2.h @@ -1,6 +1,6 @@ /* MPS2 CMSIS Library * - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -153,154 +153,6 @@ typedef struct // } MPS2_SCC_TypeDef; -/******************************************************************************/ -/* SSP Peripheral declaration */ -/******************************************************************************/ - -typedef struct // Document DDI0194G_ssp_pl022_r1p3_trm.pdf -{ - __IO uint32_t CR0; // Offset: 0x000 (R/W) Control register 0 - // [31:16] : Reserved - // [15:8] : Serial clock rate - // [7] : SSPCLKOUT phase, applicable to Motorola SPI frame format only - // [6] : SSPCLKOUT polarity, applicable to Motorola SPI frame format only - // [5:4] : Frame format - // [3:0] : Data Size Select - __IO uint32_t CR1; // Offset: 0x004 (R/W) Control register 1 - // [31:4] : Reserved - // [3] : Slave-mode output disable - // [2] : Master or slave mode select - // [1] : Synchronous serial port enable - // [0] : Loop back mode - __IO uint32_t DR; // Offset: 0x008 (R/W) Data register - // [31:16] : Reserved - // [15:0] : Transmit/Receive FIFO - __I uint32_t SR; // Offset: 0x00C (R/ ) Status register - // [31:5] : Reserved - // [4] : PrimeCell SSP busy flag - // [3] : Receive FIFO full - // [2] : Receive FIFO not empty - // [1] : Transmit FIFO not full - // [0] : Transmit FIFO empty - __IO uint32_t CPSR; // Offset: 0x010 (R/W) Clock prescale register - // [31:8] : Reserved - // [8:0] : Clock prescale divisor - __IO uint32_t IMSC; // Offset: 0x014 (R/W) Interrupt mask set or clear register - // [31:4] : Reserved - // [3] : Transmit FIFO interrupt mask - // [2] : Receive FIFO interrupt mask - // [1] : Receive timeout interrupt mask - // [0] : Receive overrun interrupt mask - __I uint32_t RIS; // Offset: 0x018 (R/ ) Raw interrupt status register - // [31:4] : Reserved - // [3] : raw interrupt state, prior to masking, of the SSPTXINTR interrupt - // [2] : raw interrupt state, prior to masking, of the SSPRXINTR interrupt - // [1] : raw interrupt state, prior to masking, of the SSPRTINTR interrupt - // [0] : raw interrupt state, prior to masking, of the SSPRORINTR interrupt - __I uint32_t MIS; // Offset: 0x01C (R/ ) Masked interrupt status register - // [31:4] : Reserved - // [3] : transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt - // [2] : receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt - // [1] : receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt - // [0] : receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt - __O uint32_t ICR; // Offset: 0x020 ( /W) Interrupt clear register - // [31:2] : Reserved - // [1] : Clears the SSPRTINTR interrupt - // [0] : Clears the SSPRORINTR interrupt - __IO uint32_t DMACR; // Offset: 0x024 (R/W) DMA control register - // [31:2] : Reserved - // [1] : Transmit DMA Enable - // [0] : Receive DMA Enable -} MPS2_SSP_TypeDef; - - -// SSP_CR0 Control register 0 -#define SSP_CR0_DSS_Pos 0 // Data Size Select -#define SSP_CR0_DSS_Msk (0xF<bit_rate is 0 + */ +static uint32_t spi_calc_clock_rate( + const struct spi_pl022_ctrl_cfg_t* ctrl_cfg, + uint32_t sys_clk, volatile uint32_t *cr0) +{ + uint32_t clkps_dvsr; /* clock prescale divisor */ + uint32_t scr; /* serial clock rate */ + + for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE; + clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) { + + /* Calculate clock rate based on the new clock prescale divisor */ + scr = (sys_clk / (clkps_dvsr * ctrl_cfg->bit_rate)) - 1; + + /* Checks if it can be supported by the divider */ + if (scr <= SPI_PL022_MAX_SCR_VALUE) { + *cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK; + *cr0 |= (scr << SPI_PL022_SSPCR0_SCR_POS); + return clkps_dvsr; + } + } + + /* no good value was found */ + *cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK; + return SPI_PL022_INVALID_SSPCPSR_VALUE; +} + +void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK; +} + +void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK; +} + +uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + return p_spi->sspsr; +} + +/* + * \brief Configures the SPI PL022 device. + * + * \param[in] spi_dev Pointer to SPI memory map \ref spi_pl022_dev_reg_map_t + * \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t + * \param[in] sys_clk System clock. + * + * \return Error code from \ref spi_pl022_error_t + */ +static enum spi_pl022_error_t spi_set_configuration( + struct spi_pl022_dev_reg_map_t* spi_dev, + const struct spi_pl022_ctrl_cfg_t* ctrl_cfg, + uint32_t sys_clk) +{ + uint32_t tmp_cr0, tmp_cr1; + uint32_t clk_dvsr; + + if(!sys_clk || !ctrl_cfg->bit_rate) { + return SPI_PL022_ERR_INVALID_ARGS; + } + + /* Word size */ + tmp_cr0 = ((ctrl_cfg->word_size -1) << SPI_PL022_SSPCR0_DSS_POS) + & SPI_PL022_SSPCR0_DSS_MSK; + + /* Frame format is stored in the least 2 bits*/ + switch(ctrl_cfg->frame_format & 0x3ul) + { + case SPI_PL022_CFG_FRF_MOT: + tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MOT_SPI << SPI_PL022_SSPCR0_FRF_POS) + & SPI_PL022_SSPCR0_FRF_MSK; + /* Add motorola phase & polarity */ + tmp_cr0 |= (SPI_PL022_SSPCR0_SPO_MSK & SPI_PL022_SSPCR0_SPH_MSK); + break; + case SPI_PL022_CFG_FRF_TI: + tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_TI_SS << SPI_PL022_SSPCR0_FRF_POS) + & SPI_PL022_SSPCR0_FRF_MSK; + break; + case SPI_PL022_CFG_FRF_MICROWIRE: + tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MICROWIRE << SPI_PL022_SSPCR0_FRF_POS) + & SPI_PL022_SSPCR0_FRF_MSK; + break; + default: + return SPI_PL022_ERR_BAD_CONFIG; + /* break; */ + } + + /* Clock logic */ + clk_dvsr = spi_calc_clock_rate(ctrl_cfg, sys_clk, &tmp_cr0); + + if (SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) { + return SPI_PL022_ERR_BAD_CONFIG; + } + + /* Enable device and set configured mode */ + tmp_cr1 = (0x1 << SPI_PL022_SSPCR1_SSE_POS) & SPI_PL022_SSPCR1_SSE_MSK; + tmp_cr1 |= ((ctrl_cfg->spi_mode << SPI_PL022_SSPCR1_MS_POS) + & SPI_PL022_SSPCR1_MS_MSK); + + + /* Start initialization by disabling the device */ + spi_dev->sspcr1 = 0; + + /* Set the value received for the configuration */ + spi_dev->sspcpsr = clk_dvsr; + spi_dev->sspcr0 = tmp_cr0; + + /* Default setup hard coded */ + spi_dev->sspimsc = 0; + spi_dev->sspdmacr = 0; + spi_dev->sspicr = (SPI_PL022_SSPICR_RORIC_MSK | SPI_PL022_SSPICR_RTIC_MSK); + + spi_dev->sspcr1 = tmp_cr1; + + return SPI_PL022_ERR_NONE; +} + +enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev, + uint32_t sys_clk) +{ + enum spi_pl022_error_t ret; + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + ret = spi_set_configuration(p_spi, &dev->cfg->default_ctrl_cfg, sys_clk); + + if(ret != SPI_PL022_ERR_NONE) { + return ret; + } + + dev->data->sys_clk = sys_clk; + + /* Initilizes current SPI control configuration */ + memcpy(&dev->data->ctrl_cfg, &dev->cfg->default_ctrl_cfg, + sizeof(struct spi_pl022_ctrl_cfg_t)); + + dev->data->state = SPI_PL022_INITIALIZED; + + return ret; +} + +enum spi_pl022_error_t spi_pl022_set_ctrl_cfg(struct spi_pl022_dev_t* dev, + const struct spi_pl022_ctrl_cfg_t* ctrl_cfg) +{ + enum spi_pl022_error_t ret; + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + if(!(dev->data->state & SPI_PL022_INITIALIZED)) { + return SPI_PL022_ERR_NOT_INIT; + } + + if(ctrl_cfg == NULL) { + return SPI_PL022_ERR_INVALID_ARGS; + } + + ret = spi_set_configuration(p_spi, ctrl_cfg, dev->data->sys_clk); + + if(ret != SPI_PL022_ERR_NONE) { + return ret; + } + + /* Updates current SPI control configuration */ + memcpy(&dev->data->ctrl_cfg, ctrl_cfg, + sizeof(struct spi_pl022_ctrl_cfg_t)); + + return SPI_PL022_ERR_NONE; +} + +enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev, + struct spi_pl022_ctrl_cfg_t* ctrl_cfg) +{ + if(!(dev->data->state & SPI_PL022_INITIALIZED)) { + return SPI_PL022_ERR_NOT_INIT; + } + + if(ctrl_cfg == NULL) { + return SPI_PL022_ERR_INVALID_ARGS; + } + + /* Copy current SPI control configuration */ + memcpy(ctrl_cfg, &dev->data->ctrl_cfg, + sizeof(struct spi_pl022_ctrl_cfg_t)); + + return SPI_PL022_ERR_NONE; +} + +void spi_pl022_select_mode(struct spi_pl022_dev_t* dev, + enum spi_pl022_mode_select_t mode) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + + /* Disable device */ + p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK; + /* Set mode */ + p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_MS_MSK) + | (mode << SPI_PL022_SSPCR1_MS_POS); + dev->data->ctrl_cfg.spi_mode = mode; + /* Re-enable device */ + p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK; +} + +void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev, + enum spi_pl022_slave_output_mode_t mode) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_SOD_MSK) + | (mode << SPI_PL022_SSPCR1_SOD_POS); +} + +void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev, + enum spi_pl022_loopback_select_t mode) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_LBM_MSK) + | (mode << SPI_PL022_SSPCR1_LBM_POS); +} + +void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev, + uint32_t irq_mask) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspimsc |= (irq_mask & SPI_PL022_SSPIMSC_VALID_MSK); +} + +void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev, + uint32_t irq_mask) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspimsc &= ~(irq_mask & SPI_PL022_SSPIMSC_VALID_MSK); +} + +uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + return (p_spi->sspris & SPI_PL022_SSPRIS_VALID_MSK); +} + +uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + return (p_spi->sspmis & SPI_PL022_SSPMIS_VALID_MSK); +} + +void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev, + uint32_t irq_mask) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspicr = (irq_mask & SPI_PL022_SSPICR_VALID_MSK); +} + +void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev, + uint32_t dma) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspdmacr |= (dma & SPI_PL022_SSPDMACR_VALID_MSK); +} + +void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev, + uint32_t dma) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspdmacr &= ~(dma & SPI_PL022_SSPDMACR_VALID_MSK); +} + +void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev, + struct spi_pl022_periphid_t* periphid) +{ + uint32_t tempid, tempid2; + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + tempid = p_spi->sspperiphid0 & SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK; + tempid2 = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK) + << SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE; + periphid->partNumber = tempid | tempid2; + + tempid = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK) + >> SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS; + tempid2 = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK) + << SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE; + periphid->designerID = tempid | tempid2; + + tempid = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK) + >> SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE; + periphid->revision = tempid; + + tempid = p_spi->sspperiphid3 & SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK; + periphid->configuration = tempid; +} + +void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev, + struct spi_pl022_primecell_id_t* cellid) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + cellid->cellid0 = (uint8_t) p_spi->ssppcellid0; + cellid->cellid1 = (uint8_t) p_spi->ssppcellid1; + cellid->cellid2 = (uint8_t) p_spi->ssppcellid2; + cellid->cellid3 = (uint8_t) p_spi->ssppcellid3; +} + +enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev, + uint32_t sys_clk) +{ + uint32_t clk_dvsr; + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + if(!(dev->data->state & SPI_PL022_INITIALIZED)) { + return SPI_PL022_ERR_NOT_INIT; + } + + if(!sys_clk) { + return SPI_PL022_ERR_INVALID_ARGS; + } + + clk_dvsr = spi_calc_clock_rate(&dev->data->ctrl_cfg, sys_clk, &p_spi->sspcr0); + + if(SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) { + return SPI_PL022_ERR_BAD_CONFIG; + } + + p_spi->sspcpsr = clk_dvsr; + dev->data->sys_clk = sys_clk; + + return SPI_PL022_ERR_NONE; +} + +enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev, + void *rx_ptr) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + if(p_spi->sspsr & SPI_PL022_SSPSR_RNE_MSK) { + if(dev->data->ctrl_cfg.word_size <= 8) { + *(uint8_t*)rx_ptr = p_spi->sspdr & WORD_1BYTE_MASK; + } else { + *(uint16_t*)rx_ptr = p_spi->sspdr & WORD_2BYTES_MASK; + } + return SPI_PL022_ERR_NONE; + } + return SPI_PL022_ERR_NO_RX; +} + +uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + uint32_t data; + + if(dev->data->ctrl_cfg.word_size <= 8) { + data = p_spi->sspdr & WORD_1BYTE_MASK; + } else { + data = p_spi->sspdr & WORD_2BYTES_MASK; + } + return data; +} + +enum spi_pl022_error_t spi_pl022_write(struct spi_pl022_dev_t* dev, + const enum spi_pl022_mode_select_t mode, + const void *tx_ptr) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + if(p_spi->sspsr & SPI_PL022_SSPSR_TNF_MSK){ + if(dev->data->ctrl_cfg.word_size <= 8) { + p_spi->sspdr = *(const uint8_t*)tx_ptr; + } else { + p_spi->sspdr = *(const uint16_t*)tx_ptr; + } + /* Wait for write to go through */ + if (mode == SPI_PL022_MASTER_SELECT) { + while(p_spi->sspsr & SPI_PL022_SSPSR_BSY_MSK) {}; + } + return SPI_PL022_ERR_NONE; + } + return SPI_PL022_ERR_NO_TX; +} + +enum spi_pl022_error_t spi_pl022_txrx_blocking(struct spi_pl022_dev_t* dev, + const void *tx_ptr, + uint32_t *tx_len_ptr, + void *rx_ptr, + uint32_t *rx_len_ptr) +{ + uint32_t i; + enum spi_pl022_error_t retval = SPI_PL022_ERR_NONE; + uint8_t word_size = 1; + uint32_t rx_data, tx_data, total_len; + + if(dev->data->ctrl_cfg.word_size > 8) { + word_size = 2; + /* return error if sizes are not word_size aligned */ + if ((*tx_len_ptr & 0x1) || (*rx_len_ptr & 0x1)) { + return SPI_PL022_ERR_INVALID_ARGS; + } + } + + total_len = (*tx_len_ptr > *rx_len_ptr) ? *tx_len_ptr : *rx_len_ptr; + + for(i=0;idata->ctrl_cfg.spi_mode, &tx_data); + if(retval != SPI_PL022_ERR_NONE) { + *tx_len_ptr = i; + *rx_len_ptr = i; + break; + } + if(i < *tx_len_ptr) { + tx_ptr = (const uint8_t*)tx_ptr + word_size; + } + retval = spi_pl022_read(dev, &rx_data); + if(retval != SPI_PL022_ERR_NONE) { + /* send went through, align tx_len to the updated tx_ptr */ + *tx_len_ptr = i + word_size; + /* don't update rx_len if there is an overflow */ + if (i < *rx_len_ptr) { + *rx_len_ptr = i; + } + break; + } + /* do not overflow rx buffer */ + if(i<*rx_len_ptr) { + if (word_size == 1) { + *(uint8_t*)rx_ptr = (uint8_t) rx_data; + } else { + *(uint16_t*)rx_ptr = (uint16_t) rx_data; + } + rx_ptr = (uint8_t*)rx_ptr + word_size; + } + } + + return retval; +} + +/* + * TEST APIs + */ +void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + p_spi->ssptcr |= SPI_PL022_SSPTCR_TESTFIFO_MSK; +} + +void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + p_spi->ssptcr &= ~SPI_PL022_SSPTCR_TESTFIFO_MSK; +} + +void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + p_spi->ssptcr |= SPI_PL022_SSPTCR_ITEN_MSK; +} + +void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + p_spi->ssptcr &= ~SPI_PL022_SSPTCR_ITEN_MSK; +} + + +void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev, + void *tx_ptr) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + if(dev->data->ctrl_cfg.word_size <= 8) { + p_spi->ssptdr = *(const uint8_t*)tx_ptr; + } else { + p_spi->ssptdr = *(const uint16_t*)tx_ptr; + } +} + +uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + return p_spi->sspitop; +} + diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/spi_pl022_drv.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/spi_pl022_drv.h new file mode 100644 index 0000000000..49864bb445 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/spi_pl022_drv.h @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file spi_pl022_drv.h + * \brief Generic driver for ARM SPI PL022. + */ + +#ifndef __SPI_PL022_DRV_H__ +#define __SPI_PL022_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Frame format */ +#define SPI_PL022_CFG_FRF_MOT 0 +#define SPI_PL022_CFG_FRF_TI 1 +#define SPI_PL022_CFG_FRF_MICROWIRE 2 + +enum spi_pl022_mode_select_t { + SPI_PL022_MASTER_SELECT = 0, + SPI_PL022_SLAVE_SELECT, +}; + +enum spi_pl022_slave_output_mode_t { + SPI_PL022_SLAVE_OUTPUT_EN = 0, + SPI_PL022_SLAVE_OUTPUT_DIS, +}; + +enum spi_pl022_loopback_select_t { + SPI_PL022_LOOPBACK_MODE_DIS = 0, + SPI_PL022_LOOPBACK_MODE_EN, +}; + +struct spi_pl022_periphid_t { + uint32_t partNumber; + uint32_t designerID; + uint32_t revision; + uint32_t configuration; +}; + +struct spi_pl022_primecell_id_t { + uint8_t cellid0; + uint8_t cellid1; + uint8_t cellid2; + uint8_t cellid3; +}; + +/* ARM SPI PL022 device control configuration structure */ +struct spi_pl022_ctrl_cfg_t { + enum spi_pl022_mode_select_t spi_mode; /*!< master-slave */ + uint8_t frame_format; /*!< frame format bitmap + clock phase [7] polarity [6] + reserved [5:3] + frame_format [1:0] */ + uint8_t word_size; /*!< value 4 to 16 */ + uint8_t reserved[2]; /*!< to keep 32 bits aligned */ + uint32_t bit_rate; /*!< required bit rate */ +}; + +/* ARM SPI PL022 device configuration structure */ +struct spi_pl022_dev_cfg_t { + const uint32_t base; /*!< SPI PL022 base address */ + const struct spi_pl022_ctrl_cfg_t default_ctrl_cfg; /*!< Default SPI + configuration */ +}; + +/* ARM SPI PL022 device data structure */ +struct spi_pl022_dev_data_t { + uint32_t state; /*!< SPI driver state */ + uint32_t sys_clk; /*!< System clock frequency */ + struct spi_pl022_ctrl_cfg_t ctrl_cfg; /*!< SPI control + configuration data */ +}; + +/* ARM SPI PL022 device structure */ +struct spi_pl022_dev_t { + const struct spi_pl022_dev_cfg_t* const cfg; /*!< SPI driver + configuration */ + struct spi_pl022_dev_data_t* const data; /*!< SPI driver data */ +}; + +enum spi_pl022_error_t { + SPI_PL022_ERR_NONE = 0, /*!< No error */ + SPI_PL022_ERR_INVALID_ARGS, /*!< Invalid input arguments */ + SPI_PL022_ERR_NOT_INIT, /*!< SPI driver is not initialized */ + SPI_PL022_ERR_NO_TX, /*!< SPI transm FIFO full */ + SPI_PL022_ERR_NO_RX, /*!< SPI receive FIFO empty */ + SPI_PL022_ERR_BAD_CONFIG, /*!< Bad SPI configuration */ +}; + + +/* Interrupt mask defines for the interrupt APIs */ + +/* Receive Overrun Interrupt */ +#define SPI_PL022_RX_OR_INTR_POS 0 +#define SPI_PL022_RX_OR_INTR_MSK (0x1ul< #include "spi_api.h" -#include "spi_def.h" -#include "cmsis.h" #include "pinmap.h" #include "mbed_error.h" #include "mbed_wait_api.h" +#include "platform_devices.h" -#define SPI_PL022_MIN_SSPCPSR_VALUE 2 -#define SPI_PL022_MAX_SSPCPSR_VALUE 254 -#define SPI_PL022_MAX_SRC_VALUE 255 -#define SPI_PL022_SSPCR0_SCR_POS 8 -#define SPI_PL022_SSPCR0_SCR_MSK (0xFFul<spi = &SPI0_PL022_DEV; + return 0; +#endif /* ARM_SPI0 */ +#ifdef ARM_SPI1 + case SPI_1: + obj->spi = &SPI1_PL022_DEV; + return 0; +#endif /* ARM_SPI1 */ +#ifdef ARM_SPI2 + case SPI_2: + obj->spi = &SPI2_PL022_DEV; + return 0; +#endif /* ARM_SPI2 */ +#ifdef ARM_SPI3 + case SPI_3: + obj->spi = &SPI3_PL022_DEV; + return 0; +#endif /* ARM_SPI3 */ +#ifdef ARM_SPI4 + case SPI_4: + obj->spi = &SPI4_PL022_DEV; + return 0; +#endif /* ARM_SPI4 */ + default: + error("Can not assign valid SPI peripheral to the pins given"); + return 1; + } +} void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { - /* Determine the SPI to use */ - SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); - SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); - SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); - SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); - SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); - SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); - - obj->spi = (MPS2_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl); - if ((int)obj->spi == NC) { - error("SPI pinout mapping failed"); + if (spi_fill_object(obj, mosi, miso, sclk, ssel) != 0) { + return; } - /* Enable power and clocking */ - switch ((int)obj->spi) { - case SPI_0: - obj->spi->CR1 = 0; - obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8; - obj->spi->CPSR = SSP_CPSR_DFLT; - obj->spi->IMSC = 0x8; - obj->spi->DMACR = 0; - obj->spi->CR1 = SSP_CR1_SSE_Msk; - obj->spi->ICR = 0x3; - break; - case SPI_1: /* Configure SSP used for LCD */ - obj->spi->CR1 = 0; /* Synchronous serial port disable */ - obj->spi->DMACR = 0; /* Disable FIFO DMA */ - obj->spi->IMSC = 0; /* Mask all FIFO/IRQ interrupts */ - obj->spi->ICR = ((1ul << 0) | /* Clear SSPRORINTR interrupt */ - (1ul << 1) ); /* Clear SSPRTINTR interrupt */ - obj->spi->CR0 = ((7ul << 0) | /* 8 bit data size */ - (0ul << 4) | /* Motorola frame format */ - (0ul << 6) | /* CPOL = 0 */ - (0ul << 7) | /* CPHA = 0 */ - (1ul << 8) ); /* Set serial clock rate */ - obj->spi->CPSR = (2ul << 0); /* set SSP clk to 6MHz (6.6MHz max) */ - obj->spi->CR1 = ((1ul << 1) | /* Synchronous serial port enable */ - (0ul << 2) ); /* Device configured as master */ - break; - case SPI_2: /* Shield ADC SPI */ - case SPI_3: /* Shield 0 SPI */ - case SPI_4: /* Shield 1 SPI */ - obj->spi->CR1 = 0; - obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8; - obj->spi->CPSR = SSP_CPSR_DFLT; - obj->spi->IMSC = 0x8; - obj->spi->DMACR = 0; - obj->spi->CR1 = SSP_CR1_SSE_Msk; - obj->spi->ICR = 0x3; - /* Set pin function as an alt-function */ - if (mosi != NC) { - pin_function(mosi, ALTERNATE_FUNC); - } - if (miso != NC) { - pin_function(miso, ALTERNATE_FUNC); - } - if (sclk != NC) { - pin_function(sclk, ALTERNATE_FUNC); - } - if (ssel != NC) { - pin_function(ssel, ALTERNATE_FUNC); - } - break; + (void)spi_pl022_init(obj->spi, SystemCoreClock); + + /* + * If the pins are not linked to a GPIO, + * pin_function will have no effect. + * Mosi, miso and ssel pins are allowed to be NC, + * call pin_function only if they are connected + */ + if (mosi != NC) { + pin_function(mosi, pinmap_function(mosi, PinMap_SPI_MOSI)); } - - /* Set default format and frequency */ - if (ssel == NC) { - spi_format(obj, 8, 0, 0); /* 8 bits, mode 0, master */ - } else { - spi_format(obj, 8, 0, 1); /* 8 bits, mode 0, slave */ + if (miso != NC) { + pin_function(miso, pinmap_function(miso, PinMap_SPI_MISO)); } - - /* Default SPI frequency */ - spi_frequency(obj, 1000000); - - /* Enable the ssp channel */ - ssp_enable(obj); + if (ssel != NC) { + pin_function(ssel, pinmap_function(ssel, PinMap_SPI_SSEL)); + } + pin_function(sclk, pinmap_function(sclk, PinMap_SPI_SCLK)); } void spi_free(spi_t *obj) { - error("SPI free error"); + /* No need to implement free function, this API is intentionally blank */ } void spi_format(spi_t *obj, int bits, int mode, int slave) { - ssp_disable(obj); - if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) { + uint32_t polarity, phase, frame_format; + struct spi_pl022_ctrl_cfg_t ctrl_cfg; + + if (!(bits >= SPI_BITS_MIN_VALUE && bits <= SPI_BITS_MAX_VALUE) || + (mode & ~SPI_MODE_MAX_VALUE_MSK)) { error("SPI format error"); + return; } - int polarity = (mode & 0x2) ? 1 : 0; - int phase = (mode & 0x1) ? 1 : 0; + spi_pl022_dev_disable(obj->spi); + if (spi_pl022_get_ctrl_cfg(obj->spi, &ctrl_cfg) != 0) { + error("SPI not initialized"); + return; + }; - // set it up - int DSS = bits - 1; /* DSS (data select size) */ - int SPO = (polarity) ? 1 : 0; /* SPO - clock out polarity */ - int SPH = (phase) ? 1 : 0; /* SPH - clock out phase */ + polarity = (mode & SPI_MODE_POLARITY_BIT_MSK) ? 1u : 0; + phase = (mode & SPI_MODE_PHASE_BIT_MSK) ? 1u : 0; + frame_format = (SPI_PL022_CFG_FRF_MOT << 0 | + polarity << 6 | + phase << 7); - int FRF = 0; /* FRF (frame format) = SPI */ - uint32_t tmp = obj->spi->CR0; - tmp &= ~(0xFFFF); - tmp |= DSS << 0 - | FRF << 4 - | SPO << 6 - | SPH << 7; - obj->spi->CR0 = tmp; + ctrl_cfg.frame_format = (uint8_t) frame_format; + ctrl_cfg.word_size = (uint8_t) bits; + ctrl_cfg.spi_mode = + slave ? SPI_PL022_SLAVE_SELECT : SPI_PL022_MASTER_SELECT; - tmp = obj->spi->CR1; - tmp &= ~(0xD); - tmp |= 0 << 0 /* LBM - loop back mode - off */ - | ((slave) ? 1 : 0) << 2 /* MS - master slave mode, 1 = slave */ - | 0 << 3; /* SOD - slave output disable - na */ - obj->spi->CR1 = tmp; + if (spi_pl022_set_ctrl_cfg(obj->spi, &ctrl_cfg) != 0) { + error("SPI configuration failed"); + } - ssp_enable(obj); + spi_pl022_dev_enable(obj->spi); } void spi_frequency(spi_t *obj, int hz) { - uint32_t clkps_dvsr, scr; - uint32_t sys_clk = SystemCoreClock; + spi_pl022_dev_disable(obj->spi); - for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE; - clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) { - - /* Calculate clock rate based on the new clock prescale divisor */ - scr = (sys_clk / (clkps_dvsr * hz)) - 1; - - /* Checks if it can be supported by the divider */ - if (scr <= SPI_PL022_MAX_SRC_VALUE) { - ssp_disable(obj); - obj->spi->CPSR = clkps_dvsr; - obj->spi->CR0 &= ~SPI_PL022_SSPCR0_SCR_MSK; - obj->spi->CR0 |= (scr << SPI_PL022_SSPCR0_SCR_POS); - ssp_enable(obj); - return; - } + obj->spi->data->ctrl_cfg.bit_rate = hz; + if (spi_pl022_set_sys_clk(obj->spi, SystemCoreClock) != 0) { + error("SPI frequency config failed"); } - error("Couldn't setup requested SPI frequency %dHz", hz); -} - -static inline int ssp_disable(spi_t *obj) -{ - return obj->spi->CR1 &= ~(1 << 1); -} - -static inline int ssp_enable(spi_t *obj) -{ - return obj->spi->CR1 |= SSP_CR1_SSE_Msk; -} - -static inline int ssp_readable(spi_t *obj) -{ - return obj->spi->SR & (1 << 2); -} - -static inline int ssp_writeable(spi_t *obj) -{ - return obj->spi->SR & SSP_SR_BSY_Msk; -} - -static inline void ssp_write(spi_t *obj, int value) -{ - obj->spi->DR = value; - while (ssp_writeable(obj)); -} -static inline int ssp_read(spi_t *obj) -{ - int read_DR = obj->spi->DR; - return read_DR; -} - -static inline int ssp_busy(spi_t *obj) -{ - return (obj->spi->SR & (1 << 4)) ? (1) : (0); + spi_pl022_dev_enable(obj->spi); } int spi_master_write(spi_t *obj, int value) { - ssp_write(obj, value); - while (obj->spi->SR & SSP_SR_BSY_Msk); /* Wait for send to finish */ - return (ssp_read(obj)); + int32_t rx_data = 0; + uint32_t size = 1; + + if(obj->spi->data->ctrl_cfg.word_size > 8) { + size = 2; + } + + if (spi_pl022_txrx_blocking(obj->spi, &value, &size, &rx_data, &size) ) { + return 0; + } + + return rx_data; } int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill) { - int total = (tx_length > rx_length) ? tx_length : rx_length; - char out, in; - - for (int i = 0; i < total; i++) { - out = (i < tx_length) ? tx_buffer[i] : write_fill; - in = spi_master_write(obj, out); - if (i < rx_length) { - rx_buffer[i] = in; - } + if (spi_pl022_txrx_blocking(obj->spi, tx_buffer, (uint32_t*)&tx_length, + rx_buffer, (uint32_t*)&rx_length)) { + return 0; } - return total; + return ((tx_length > rx_length) ? tx_length : rx_length); } int spi_slave_receive(spi_t *obj) { - return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0); + int32_t status = spi_pl022_get_status(obj->spi); + /* Rx FIFO not empty and device not busy */ + int32_t ret = ((status & SPI_PL022_SSPSR_RNE_MSK) && + !(status & SPI_PL022_SSPSR_BSY_MSK)); + return ret; +} + +uint8_t spi_get_module(spi_t *obj) +{ + if (obj->spi == &SPI0_PL022_DEV) { + return SPI_0; + } else if (obj->spi == &SPI1_PL022_DEV) { + return SPI_1; + } else if (obj->spi == &SPI2_PL022_DEV) { + return SPI_2; + } else if (obj->spi == &SPI3_PL022_DEV) { + return SPI_3; + } else if (obj->spi == &SPI4_PL022_DEV) { + return SPI_4; + } else { + error("SPI object is not initialized"); + return (SPI_NC); + } } int spi_slave_read(spi_t *obj) { - return obj->spi->DR; + while(spi_slave_receive(obj) == 0) {}; + return spi_pl022_slave_read(obj->spi); } void spi_slave_write(spi_t *obj, int value) { - while (ssp_writeable(obj) == 0); - obj->spi->DR = value; + (void)spi_pl022_write(obj->spi, SPI_PL022_SLAVE_SELECT, &value); } int spi_busy(spi_t *obj) { - return ssp_busy(obj); + int32_t status = spi_pl022_get_status(obj->spi); + return (status & SPI_PL022_SSPSR_BSY_MSK); } diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_def.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_def.h deleted file mode 100644 index ca8e450be8..0000000000 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_def.h +++ /dev/null @@ -1,174 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ---------------------------------------------------------------- - * File: spi_def.h - * Release: Version 2.0 - * ---------------------------------------------------------------- - * - * SSP interface Support - * ===================== - */ - -#define SSPCS_BASE (0x4002804C) // SSP chip select register -#define SSP_BASE (0x40020000) // SSP Prime Cell - -#define SSPCR0 ((volatile unsigned int *)(SSP_BASE + 0x00)) -#define SSPCR1 ((volatile unsigned int *)(SSP_BASE + 0x04)) -#define SSPDR ((volatile unsigned int *)(SSP_BASE + 0x08)) -#define SSPSR ((volatile unsigned int *)(SSP_BASE + 0x0C)) -#define SSPCPSR ((volatile unsigned int *)(SSP_BASE + 0x10)) -#define SSPIMSC ((volatile unsigned int *)(SSP_BASE + 0x14)) -#define SSPRIS ((volatile unsigned int *)(SSP_BASE + 0x18)) -#define SSPMIS ((volatile unsigned int *)(SSP_BASE + 0x1C)) -#define SSPICR ((volatile unsigned int *)(SSP_BASE + 0x20)) -#define SSPDMACR ((volatile unsigned int *)(SSP_BASE + 0x24)) -#define SSPCS ((volatile unsigned int *)(SSPCS_BASE)) - -// SSPCR0 Control register 0 -#define SSPCR0_SCR_DFLT 0x0300 // Serial Clock Rate (divide), default set at 3 -#define SSPCR0_SPH 0x0080 // SSPCLKOUT phase -#define SSPCR0_SPO 0x0040 // SSPCLKOUT polarity -#define SSPCR0_FRF_MOT 0x0000 // Frame format, Motorola -#define SSPCR0_DSS_8 0x0007 // Data packet size, 8bits -#define SSPCR0_DSS_16 0x000F // Data packet size, 16bits - -// SSPCR1 Control register 1 -#define SSPCR1_SOD 0x0008 // Slave Output mode Disable -#define SSPCR1_MS 0x0004 // Master or Slave mode -#define SSPCR1_SSE 0x0002 // Serial port enable -#define SSPCR1_LBM 0x0001 // Loop Back Mode - -// SSPSR Status register -#define SSPSR_BSY 0x0010 // Busy -#define SSPSR_RFF 0x0008 // Receive FIFO full -#define SSPSR_RNE 0x0004 // Receive FIFO not empty -#define SSPSR_TNF 0x0002 // Transmit FIFO not full -#define SSPSR_TFE 0x0001 // Transmit FIFO empty - -// SSPCPSR Clock prescale register -#define SSPCPSR_DFLT 0x0008 // Clock prescale (use with SCR), default set at 8 - -// SSPIMSC Interrupt mask set and clear register -#define SSPIMSC_TXIM 0x0008 // Transmit FIFO not Masked -#define SSPIMSC_RXIM 0x0004 // Receive FIFO not Masked -#define SSPIMSC_RTIM 0x0002 // Receive timeout not Masked -#define SSPIMSC_RORIM 0x0001 // Receive overrun not Masked - -// SSPRIS Raw interrupt status register -#define SSPRIS_TXRIS 0x0008 // Raw Transmit interrupt flag -#define SSPRIS_RXRIS 0x0004 // Raw Receive interrupt flag -#define SSPRIS_RTRIS 0x0002 // Raw Timemout interrupt flag -#define SSPRIS_RORRIS 0x0001 // Raw Overrun interrupt flag - -// SSPMIS Masked interrupt status register -#define SSPMIS_TXMIS 0x0008 // Masked Transmit interrupt flag -#define SSPMIS_RXMIS 0x0004 // Masked Receive interrupt flag -#define SSPMIS_RTMIS 0x0002 // Masked Timemout interrupt flag -#define SSPMIS_RORMIS 0x0001 // Masked Overrun interrupt flag - -// SSPICR Interrupt clear register -#define SSPICR_RTIC 0x0002 // Clears Timeout interrupt flag -#define SSPICR_RORIC 0x0001 // Clears Overrun interrupt flag - -// SSPDMACR DMA control register -#define SSPDMACR_TXDMAE 0x0002 // Enable Transmit FIFO DMA -#define SSPDMACR_RXDMAE 0x0001 // Enable Receive FIFO DMA - -// SPICS register (0=Chip Select low) -#define SSPCS_nCS1 0x0002 // nCS1 (SPI_nSS) - -// SPI defaults -#define SSPMAXTIME 1000 // Maximum time to wait for SSP (10*10uS) - -// EEPROM instruction set -#define EEWRSR 0x0001 // Write status -#define EEWRITE 0x0002 // Write data -#define EEREAD 0x0003 // Read data -#define EEWDI 0x0004 // Write disable -#define EEWREN 0x0006 // Write enable -#define EERDSR 0x0005 // Read status - -// EEPROM status register flags -#define EERDSR_WIP 0x0001 // Write in process -#define EERDSR_WEL 0x0002 // Write enable latch -#define EERDSR_BP0 0x0004 // Block protect 0 -#define EERDSR_BP1 0x0008 // Block protect 1 -#define EERDSR_WPEN 0x0080 // Write protect enable - - /* ---------------------------------------------------------------- - * - * Color LCD Support - * ================= - */ - -// Color LCD Controller Internal Register addresses -#define LSSPCS_BASE (0x4002804C) // LSSP chip select register -#define LSSP_BASE (0x40021000) // LSSP Prime Cell - -#define LSSPCR0 ((volatile unsigned int *)(LSSP_BASE + 0x00)) -#define LSSPCR1 ((volatile unsigned int *)(LSSP_BASE + 0x04)) -#define LSSPDR ((volatile unsigned int *)(LSSP_BASE + 0x08)) -#define LSSPSR ((volatile unsigned int *)(LSSP_BASE + 0x0C)) -#define LSSPCPSR ((volatile unsigned int *)(LSSP_BASE + 0x10)) -#define LSSPIMSC ((volatile unsigned int *)(LSSP_BASE + 0x14)) -#define LSSPRIS ((volatile unsigned int *)(LSSP_BASE + 0x18)) -#define LSSPMIS ((volatile unsigned int *)(LSSP_BASE + 0x1C)) -#define LSSPICR ((volatile unsigned int *)(LSSP_BASE + 0x20)) -#define LSSPDMACR ((volatile unsigned int *)(LSSP_BASE + 0x24)) -#define LSSPCS ((volatile unsigned int *)(LSSPCS_BASE)) - -// LSSPCR0 Control register 0 -#define LSSPCR0_SCR_DFLT 0x0100 // Serial Clock Rate (divide), CLK/(CPSR*(1+SCR)) -#define LSSPCR0_SPH 0x0080 // LSSPCLKOUT phase -#define LSSPCR0_SPO 0x0040 // LSSPCLKOUT polarity -#define LSSPCR0_FRF_MOT 0x0000 // Frame format, Motorola -#define LSSPCR0_DSS_8 0x0007 // Data packet size, 8bits -#define LSSPCR0_DSS_16 0x000F // Data packet size, 16bits - -// LSSPCR1 Control register 1 -#define LSSPCR1_SOD 0x0008 // Slave Output mode Disable -#define LSSPCR1_MS 0x0004 // Master or Slave mode -#define LSSPCR1_SSE 0x0002 // Serial port enable -#define LSSPCR1_LBM 0x0001 // Loop Back Mode - -// LSSPSR Status register -#define LSSPSR_BSY 0x0010 // Busy -#define LSSPSR_RFF 0x0008 // Receive FIFO full -#define LSSPSR_RNE 0x0004 // Receive FIFO not empty -#define LSSPSR_TNF 0x0002 // Transmit FIFO not full -#define LSSPSR_TFE 0x0001 // Transmit FIFO empty - -// LSSPCPSR Clock prescale register -#define LSSPCPSR_DFLT 0x0002 // Clock prescale (use with SCR) - -// SPICS register -#define LSSPCS_nCS0 0x0001 // nCS0 (CLCD_CS) -#define LSSPCS_nCS2 0x0004 // nCS2 (CLCD_T_CS) -#define LCD_RESET 0x0008 // RESET (CLCD_RESET) -#define LCD_RS 0x0010 // RS (CLCD_RS) -#define LCD_RD 0x0020 // RD (CLCD_RD) -#define LCD_BL 0x0040 // Backlight (CLCD_BL_CTRL) - -// SPI defaults -#define LSSPMAXTIME 10000 // Maximum time to wait for LSSP (10*10uS) -#define LSPI_START (0x70) // Start byte for SPI transfer -#define LSPI_RD (0x01) // WR bit 1 within start -#define LSPI_WR (0x00) // WR bit 0 within start -#define LSPI_DATA (0x02) // RS bit 1 within start byte -#define LSPI_INDEX (0x00) // RS bit 0 within start byte - -// Screen size -#define LCD_WIDTH 320 // Screen Width (in pixels) -#define LCD_HEIGHT 240 // Screen Height (in pixels)