mirror of https://github.com/ARMmbed/mbed-os.git
CM3DS: update SPI implementation
This commit adds the SPI driver which is now called by the SPI HAL implementation. It also removes legacy definitions. Change-Id: Iadb20dda9dfa571db3de66c3a1ce45d80d8b81b6 Signed-off-by: Tamas Kaman <tamas.kaman@arm.com>pull/6170/head
parent
3abc3faba2
commit
37cf802a7a
|
@ -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 {
|
||||
|
|
|
@ -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<<SSP_CR0_DSS_Pos)
|
||||
#define SSP_CR0_FRF_Pos 4 // Frame Format Select
|
||||
#define SSP_CR0_FRF_Msk (3UL<<SSP_CR0_FRM_Pos)
|
||||
#define SSP_CR0_SPO_Pos 6 // SSPCLKOUT polarity
|
||||
#define SSP_CR0_SPO_Msk (1UL<<SSP_CR0_SPO_Pos)
|
||||
#define SSP_CR0_SPH_Pos 7 // SSPCLKOUT phase
|
||||
#define SSP_CR0_SPH_Msk (1UL<<SSP_CR0_SPH_Pos)
|
||||
#define SSP_CR0_SCR_Pos 8 // Serial Clock Rate (divide)
|
||||
#define SSP_CR0_SCR_Msk (0xFF<<SSP_CR0_SCR_Pos)
|
||||
|
||||
#define SSP_CR0_SCR_DFLT 0x0300 // Serial Clock Rate (divide), default set at 3
|
||||
#define SSP_CR0_FRF_MOT 0x0000 // Frame format, Motorola
|
||||
#define SSP_CR0_DSS_8 0x0007 // Data packet size, 8bits
|
||||
#define SSP_CR0_DSS_16 0x000F // Data packet size, 16bits
|
||||
|
||||
// SSP_CR1 Control register 1
|
||||
#define SSP_CR1_LBM_Pos 0 // Loop Back Mode
|
||||
#define SSP_CR1_LBM_Msk (1UL<<SSP_CR1_LBM_Pos)
|
||||
#define SSP_CR1_SSE_Pos 1 // Serial port enable
|
||||
#define SSP_CR1_SSE_Msk (1UL<<SSP_CR1_SSE_Pos)
|
||||
#define SSP_CR1_MS_Pos 2 // Master or Slave mode
|
||||
#define SSP_CR1_MS_Msk (1UL<<SSP_CR1_MS_Pos)
|
||||
#define SSP_CR1_SOD_Pos 3 // Slave Output mode Disable
|
||||
#define SSP_CR1_SOD_Msk (1UL<<SSP_CR1_SOD_Pos)
|
||||
|
||||
// SSP_SR Status register
|
||||
#define SSP_SR_TFE_Pos 0 // Transmit FIFO empty
|
||||
#define SSP_SR_TFE_Msk (1UL<<SSP_SR_TFE_Pos)
|
||||
#define SSP_SR_TNF_Pos 1 // Transmit FIFO not full
|
||||
#define SSP_SR_TNF_Msk (1UL<<SSP_SR_TNF_Pos)
|
||||
#define SSP_SR_RNE_Pos 2 // Receive FIFO not empty
|
||||
#define SSP_SR_RNE_Msk (1UL<<SSP_SR_RNE_Pos)
|
||||
#define SSP_SR_RFF_Pos 3 // Receive FIFO full
|
||||
#define SSP_SR_RFF_Msk (1UL<<SSP_SR_RFF_Pos)
|
||||
#define SSP_SR_BSY_Pos 4 // Busy
|
||||
#define SSP_SR_BSY_Msk (1UL<<SSP_SR_BSY_Pos)
|
||||
|
||||
// SSP_CPSR Clock prescale register
|
||||
#define SSP_CPSR_CPD_Pos 0 // Clock prescale divisor
|
||||
#define SSP_CPSR_CPD_Msk (0xFF<<SSP_CPSR_CDP_Pos)
|
||||
|
||||
#define SSP_CPSR_DFLT 0x0008 // Clock prescale (use with SCR), default set at 8
|
||||
|
||||
// SSPIMSC Interrupt mask set and clear register
|
||||
#define SSP_IMSC_RORIM_Pos 0 // Receive overrun not Masked
|
||||
#define SSP_IMSC_RORIM_Msk (1UL<<SSP_IMSC_RORIM_Pos)
|
||||
#define SSP_IMSC_RTIM_Pos 1 // Receive timeout not Masked
|
||||
#define SSP_IMSC_RTIM_Msk (1UL<<SSP_IMSC_RTIM_Pos)
|
||||
#define SSP_IMSC_RXIM_Pos 2 // Receive FIFO not Masked
|
||||
#define SSP_IMSC_RXIM_Msk (1UL<<SSP_IMSC_RXIM_Pos)
|
||||
#define SSP_IMSC_TXIM_Pos 3 // Transmit FIFO not Masked
|
||||
#define SSP_IMSC_TXIM_Msk (1UL<<SSP_IMSC_TXIM_Pos)
|
||||
|
||||
// SSPRIS Raw interrupt status register
|
||||
#define SSP_RIS_RORRIS_Pos 0 // Raw Overrun interrupt flag
|
||||
#define SSP_RIS_RORRIS_Msk (1UL<<SSP_RIS_RORRIS_Pos)
|
||||
#define SSP_RIS_RTRIS_Pos 1 // Raw Timemout interrupt flag
|
||||
#define SSP_RIS_RTRIS_Msk (1UL<<SSP_RIS_RTRIS_Pos)
|
||||
#define SSP_RIS_RXRIS_Pos 2 // Raw Receive interrupt flag
|
||||
#define SSP_RIS_RXRIS_Msk (1UL<<SSP_RIS_RXRIS_Pos)
|
||||
#define SSP_RIS_TXRIS_Pos 3 // Raw Transmit interrupt flag
|
||||
#define SSP_RIS_TXRIS_Msk (1UL<<SSP_RIS_TXRIS_Pos)
|
||||
|
||||
// SSPMIS Masked interrupt status register
|
||||
#define SSP_MIS_RORMIS_Pos 0 // Masked Overrun interrupt flag
|
||||
#define SSP_MIS_RORMIS_Msk (1UL<<SSP_MIS_RORMIS_Pos)
|
||||
#define SSP_MIS_RTMIS_Pos 1 // Masked Timemout interrupt flag
|
||||
#define SSP_MIS_RTMIS_Msk (1UL<<SSP_MIS_RTMIS_Pos)
|
||||
#define SSP_MIS_RXMIS_Pos 2 // Masked Receive interrupt flag
|
||||
#define SSP_MIS_RXMIS_Msk (1UL<<SSP_MIS_RXMIS_Pos)
|
||||
#define SSP_MIS_TXMIS_Pos 3 // Masked Transmit interrupt flag
|
||||
#define SSP_MIS_TXMIS_Msk (1UL<<SSP_MIS_TXMIS_Pos)
|
||||
|
||||
// SSPICR Interrupt clear register
|
||||
#define SSP_ICR_RORIC_Pos 0 // Clears Overrun interrupt flag
|
||||
#define SSP_ICR_RORIC_Msk (1UL<<SSP_ICR_RORIC_Pos)
|
||||
#define SSP_ICR_RTIC_Pos 1 // Clears Timemout interrupt flag
|
||||
#define SSP_ICR_RTIC_Msk (1UL<<SSP_ICR_RTIC_Pos)
|
||||
|
||||
// SSPDMACR DMA control register
|
||||
#define SSP_DMACR_RXDMAE_Pos 0 // Enable Receive FIFO DMA
|
||||
#define SSP_DMACR_RXDMAE_Msk (1UL<<SSP_DMACR_RXDMAE_Pos)
|
||||
#define SSP_DMACR_TXDMAE_Pos 1 // Enable Transmit FIFO DMA
|
||||
#define SSP_DMACR_TXDMAE_Msk (1UL<<SSP_DMACR_TXDMAE_Pos)
|
||||
|
||||
/******************************************************************************/
|
||||
/* Audio and Touch Screen (I2C) Peripheral declaration */
|
||||
/******************************************************************************/
|
||||
|
@ -577,11 +429,6 @@ __IO uint32_t E2P_DATA; // EEPROM Data (offset 0xB4)
|
|||
#define MPS2_AAIC_I2S ((MPS2_I2S_TypeDef *) MPS2_AAIC_I2S_BASE )
|
||||
#define MPS2_FPGAIO ((MPS2_FPGAIO_TypeDef *) MPS2_FPGAIO_BASE )
|
||||
#define MPS2_SCC ((MPS2_SCC_TypeDef *) MPS2_SCC_BASE )
|
||||
#define MPS2_SSP0 ((MPS2_SSP_TypeDef *) MPS2_SSP0_BASE )
|
||||
#define MPS2_SSP1 ((MPS2_SSP_TypeDef *) MPS2_SSP1_BASE )
|
||||
#define MPS2_SSP2 ((MPS2_SSP_TypeDef *) MPS2_SSP2_BASE )
|
||||
#define MPS2_SSP3 ((MPS2_SSP_TypeDef *) MPS2_SSP3_BASE )
|
||||
#define MPS2_SSP4 ((MPS2_SSP_TypeDef *) MPS2_SSP4_BASE )
|
||||
|
||||
/******************************************************************************/
|
||||
/* General Function Definitions */
|
||||
|
|
|
@ -42,4 +42,12 @@
|
|||
/* ARM MPS2 IO SCC */
|
||||
#define ARM_MPS2_IO_SCC
|
||||
|
||||
/* ARM SPI PL022 */
|
||||
#define DEFAULT_SPI_SPEED_HZ 4000000U /* 4MHz */
|
||||
#define ARM_SPI0
|
||||
#define ARM_SPI1
|
||||
#define ARM_SPI2
|
||||
#define ARM_SPI3
|
||||
#define ARM_SPI4
|
||||
|
||||
#endif /* __ARM_LTD_DEVICE_CFG_H__ */
|
||||
|
|
|
@ -0,0 +1,870 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "spi_pl022_drv.h"
|
||||
|
||||
/******************************************************************************
|
||||
* PL022 device specific definitions based on DDI0194H_ssp_pl022_trm.pdf which
|
||||
* is available from infocenter.arm.com.
|
||||
*
|
||||
* This version of driver aims at necessary functionality for MPS2 board only
|
||||
*****************************************************************************/
|
||||
|
||||
/* Structure for the SSP Primary Cell device registers */
|
||||
struct spi_pl022_dev_reg_map_t {
|
||||
volatile uint32_t sspcr0; /* Control register 0 */
|
||||
volatile uint32_t sspcr1; /* Control register 1 */
|
||||
volatile uint32_t sspdr; /* Data register */
|
||||
volatile uint32_t sspsr; /* Status register */
|
||||
volatile uint32_t sspcpsr; /* Clock prescale register */
|
||||
volatile uint32_t sspimsc; /* Interrupt mask set or clear register */
|
||||
volatile uint32_t sspris; /* Raw interrupt status register */
|
||||
volatile uint32_t sspmis; /* Masked interrupt status register */
|
||||
volatile uint32_t sspicr; /* Interrupt clear register */
|
||||
volatile uint32_t sspdmacr; /* DMA control register */
|
||||
volatile uint32_t reserved[1006];/* Reserved from Base+0x28-0xFE0 */
|
||||
volatile uint32_t sspperiphid0; /* Peripheral id register 0 */
|
||||
volatile uint32_t sspperiphid1; /* Peripheral id register 1 */
|
||||
volatile uint32_t sspperiphid2; /* Peripheral id register 2 */
|
||||
volatile uint32_t sspperiphid3; /* Peripheral id register 3 */
|
||||
volatile uint32_t ssppcellid0; /* Primary cell id register 0 */
|
||||
volatile uint32_t ssppcellid1; /* Primary cell id register 1 */
|
||||
volatile uint32_t ssppcellid2; /* Primary cell id register 2 */
|
||||
volatile uint32_t ssppcellid3; /* Primary cell id register 3 */
|
||||
};
|
||||
|
||||
/*--- SSP Control Register 0 ---*/
|
||||
|
||||
/* Data Size Select {0x3=4 ... 0xF=16} */
|
||||
#define SPI_PL022_SSPCR0_DSS_POS 0
|
||||
#define SPI_PL022_SSPCR0_DSS_MSK 0xF
|
||||
|
||||
/* Frame format */
|
||||
#define SPI_PL022_SSPCR0_FRF_POS 4
|
||||
#define SPI_PL022_SSPCR0_FRF_MSK (0x3ul<<SPI_PL022_SSPCR0_FRF_POS)
|
||||
#define SPI_PL022_SSPCR0_FRF_MOT_SPI 0x0
|
||||
#define SPI_PL022_SSPCR0_FRF_TI_SS 0x1
|
||||
#define SPI_PL022_SSPCR0_FRF_MICROWIRE 0x2
|
||||
#define SPI_PL022_SSPCR0_FRF_RES 0x3
|
||||
|
||||
/* Clock polarity applicable to Motorola SPI format only */
|
||||
#define SPI_PL022_SSPCR0_SPO_POS 6
|
||||
#define SPI_PL022_SSPCR0_SPO_MSK (0x1ul<<SPI_PL022_SSPCR0_SPO_POS)
|
||||
|
||||
/* Clock phase applicable to Motorola SPI format only */
|
||||
#define SPI_PL022_SSPCR0_SPH_POS 7
|
||||
#define SPI_PL022_SSPCR0_SPH_MSK (0x1ul<<SPI_PL022_SSPCR0_SPH_POS)
|
||||
|
||||
/* Serial clock rate */
|
||||
#define SPI_PL022_SSPCR0_SCR_POS 8
|
||||
#define SPI_PL022_SSPCR0_SCR_MSK (0xFFul<<SPI_PL022_SSPCR0_SCR_POS)
|
||||
|
||||
/*--- SSP Control Register 1 ---*/
|
||||
|
||||
/* Loopback mode*/
|
||||
#define SPI_PL022_SSPCR1_LBM_POS 0
|
||||
#define SPI_PL022_SSPCR1_LBM_MSK (0x1ul<<SPI_PL022_SSPCR1_LBM_POS)
|
||||
|
||||
/* Syncrhonous serial port enable*/
|
||||
#define SPI_PL022_SSPCR1_SSE_POS 1
|
||||
#define SPI_PL022_SSPCR1_SSE_MSK (0x1ul<<SPI_PL022_SSPCR1_SSE_POS)
|
||||
|
||||
/* Master or Slave select */
|
||||
#define SPI_PL022_SSPCR1_MS_POS 2
|
||||
#define SPI_PL022_SSPCR1_MS_MSK (0x1ul<<SPI_PL022_SSPCR1_MS_POS)
|
||||
|
||||
/* Slave mode output disable */
|
||||
#define SPI_PL022_SSPCR1_SOD_POS 3
|
||||
#define SPI_PL022_SSPCR1_SOD_MSK (0x1ul<<SPI_PL022_SSPCR1_SOD_POS)
|
||||
|
||||
/*--- Clock PreScale Register ---*/
|
||||
|
||||
/* Divisor */
|
||||
#define SPI_PL022_SSPCPSR_CPSDVSR_POS 0
|
||||
#define SPI_PL022_SSPCPSR_CPSDVSR_MSK (0xFFul<<SPI_PL022_SSPCPSR_CPSDVSR_POS)
|
||||
#define SPI_PL022_INVALID_SSPCPSR_VALUE 0
|
||||
#define SPI_PL022_MIN_SSPCPSR_VALUE 2
|
||||
#define SPI_PL022_MAX_SSPCPSR_VALUE 254
|
||||
#define SPI_PL022_MAX_SCR_VALUE 255
|
||||
|
||||
|
||||
/*--- Interrupt Mask Set or Clear Register --- */
|
||||
|
||||
/* Receive Overrun Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RORIM_POS 0
|
||||
#define SPI_PL022_SSPIMSC_RORIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RORIM_POS)
|
||||
|
||||
/* Receive Timeout Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RTIM_POS 1
|
||||
#define SPI_PL022_SSPIMSC_RTIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RTIM_POS)
|
||||
|
||||
/* Receive FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RXIM_POS 2
|
||||
#define SPI_PL022_SSPIMSC_RXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RXIM_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_TXIM_POS 3
|
||||
#define SPI_PL022_SSPIMSC_TXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_TXIM_POS)
|
||||
|
||||
/*--- Interrupt Mask Set or Clear Register ---*/
|
||||
|
||||
/* Receive Overrun Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RORIM_POS 0
|
||||
#define SPI_PL022_SSPIMSC_RORIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RORIM_POS)
|
||||
|
||||
/* Receive Timeout Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RTIM_POS 1
|
||||
#define SPI_PL022_SSPIMSC_RTIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RTIM_POS)
|
||||
|
||||
/* Receive FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_RXIM_POS 2
|
||||
#define SPI_PL022_SSPIMSC_RXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_RXIM_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt Mask */
|
||||
#define SPI_PL022_SSPIMSC_TXIM_POS 3
|
||||
#define SPI_PL022_SSPIMSC_TXIM_MSK (0x1ul<<SPI_PL022_SSPIMSC_TXIM_POS)
|
||||
|
||||
#define SPI_PL022_SSPIMSC_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPIMSC_TXIM_POS+1))-1)
|
||||
|
||||
/*--- Raw Interrupt Status Register ---*/
|
||||
|
||||
/* SSPRORINTR */
|
||||
#define SPI_PL022_SSPRIS_RORRIS_POS 0
|
||||
#define SPI_PL022_SSPRIS_RORRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RORRIS_POS)
|
||||
|
||||
/* SSPRTINTR */
|
||||
#define SPI_PL022_SSPRIS_RTRIS_POS 1
|
||||
#define SPI_PL022_SSPRIS_RTRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RTRIS_POS)
|
||||
|
||||
/* SSPRXINTR */
|
||||
#define SPI_PL022_SSPRIS_RXRIS_POS 2
|
||||
#define SPI_PL022_SSPRIS_RXRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_RXRIS_POS)
|
||||
|
||||
/* SSPTXINTR */
|
||||
#define SPI_PL022_SSPRIS_TXRIS_POS 3
|
||||
#define SPI_PL022_SSPRIS_TXRIS_MSK (0x1ul<<SPI_PL022_SSPRIS_TXRIS_POS)
|
||||
|
||||
#define SPI_PL022_SSPRIS_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPRIS_TXRIS_POS+1))-1)
|
||||
|
||||
/*--- Masked Interrupt Status Register ---*/
|
||||
|
||||
/* SSPRORINTR */
|
||||
#define SPI_PL022_SSPMIS_RORMIS_POS 0
|
||||
#define SPI_PL022_SSPMIS_RORMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RORMIS_POS)
|
||||
|
||||
/* SSPRTINTR */
|
||||
#define SPI_PL022_SSPMIS_RTMIS_POS 1
|
||||
#define SPI_PL022_SSPMIS_RTMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RTMIS_POS)
|
||||
|
||||
/* SSPRXINTR */
|
||||
#define SPI_PL022_SSPMIS_RXMIS_POS 2
|
||||
#define SPI_PL022_SSPMIS_RXMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_RXMIS_POS)
|
||||
|
||||
/* SSPTXINTR */
|
||||
#define SPI_PL022_SSPMIS_TXMIS_POS 3
|
||||
#define SPI_PL022_SSPMIS_TXMIS_MSK (0x1ul<<SPI_PL022_SSPMIS_TXMIS_POS)
|
||||
|
||||
#define SPI_PL022_SSPMIS_VALID_MSK \
|
||||
((0x1ul<<(SPI_PL022_SSPMIS_TXMIS_POS+1))-1)
|
||||
|
||||
/*--- Interrupt Clear Register --- */
|
||||
|
||||
/* SSPRORINTR Clear */
|
||||
#define SPI_PL022_SSPICR_RORIC_POS 0
|
||||
#define SPI_PL022_SSPICR_RORIC_MSK (0x1ul<<SPI_PL022_SSPICR_RORIC_POS)
|
||||
|
||||
/* SSPRTINTR Clear */
|
||||
#define SPI_PL022_SSPICR_RTIC_POS 1
|
||||
#define SPI_PL022_SSPICR_RTIC_MSK (0x1ul<<SPI_PL022_SSPICR_RTIC_POS)
|
||||
|
||||
#define SPI_PL022_SSPICR_VALID_MSK ((0x1ul<<(SPI_PL022_SSPICR_RTIC_POS+1))-1)
|
||||
|
||||
/*--- DMA Control Register --- */
|
||||
|
||||
/* Receive DMA Enable */
|
||||
#define SPI_PL022_SSPDMACR_RXDMAE_POS 0
|
||||
#define SPI_PL022_SSPDMACR_RXDMAE_MSK (0x1ul<<SPI_PL022_SSPDMACR_RXDMAE_POS)
|
||||
|
||||
/* Transmit DMA Enable */
|
||||
#define SPI_PL022_SSPDMACR_TXDMAE_POS 1
|
||||
#define SPI_PL022_SSPDMACR_TXDMAE_MSK (0x1ul<<SPI_PL022_SSPDMACR_TXDMAE_POS)
|
||||
|
||||
#define SPI_PL022_SSPDMACR_VALID_MSK ((0x1ul<<(SPI_PL022_SSPDMACR_TXDMAE_POS+1))-1)
|
||||
|
||||
/*--- Peripheral Identification Registers ---*/
|
||||
|
||||
#define SPI_PL022_SSPPERIPH_ID_OFFSET (0xFE0ul)
|
||||
|
||||
/* Part Number 0 */
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE 8
|
||||
#define SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK \
|
||||
(0xFFul<<SPI_PL022_SSPPERIPH_ID0_PARTNO_0_POS)
|
||||
|
||||
/* Part Number 1 */
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_SIZE 0
|
||||
#define SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID1_PARTNO_1_POS)
|
||||
|
||||
/* Designer 0 */
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS 4
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS)
|
||||
|
||||
/* Designer 1 */
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_POS)
|
||||
|
||||
/* Revision */
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVISION_POS 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE 4
|
||||
#define SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK \
|
||||
(0xFul<<SPI_PL022_SSPPERIPH_ID2_REVISION_POS)
|
||||
|
||||
/* Config */
|
||||
#define SPI_PL022_SSPPERIPH_ID3_CONFIG_POS 0
|
||||
#define SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK \
|
||||
(0xFFul<<SPI_PL022_SSPPERIPH_ID3_CONFIG_POS)
|
||||
|
||||
/*--- PrimeCell Identification Registers ---*/
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID_OFFSET (0xFF0ul)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID0_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID0_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID0_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID1_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID1_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID1_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID2_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID2_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID2_POS)
|
||||
|
||||
#define SPI_PL022_SSPPCELL_ID3_POS 0
|
||||
#define SPI_PL022_SSPPCELL_ID3_MSK (0xFFul<<SPI_PL022_SSPPCELL_ID3_POS)
|
||||
|
||||
/* ARM SPI PL022 state definitions */
|
||||
#define SPI_PL022_INITIALIZED (1 << 0)
|
||||
|
||||
#define WORD_1BYTE_MASK (0xFFul)
|
||||
#define WORD_2BYTES_MASK (0xFFFFul)
|
||||
|
||||
|
||||
/************************* PL022 TEST Definitions ******************************/
|
||||
#define SPI_PL022_TEST_REG_BASE (0x80ul)
|
||||
|
||||
struct spi_pl022_dev_test_reg_map_t {
|
||||
volatile uint32_t ssptcr; /* Test Control register */
|
||||
volatile uint32_t sspitip; /* Integration test input register */
|
||||
volatile uint32_t sspitop; /* Integration test output register */
|
||||
volatile uint32_t ssptdr; /* Test data register */
|
||||
};
|
||||
|
||||
/* Test control register */
|
||||
#define SPI_PL022_SSPTCR_ITEN_POS 0
|
||||
#define SPI_PL022_SSPTCR_ITEN_MSK (0x1ul<<SPI_PL022_SSPTCR_ITEN_POS)
|
||||
|
||||
#define SPI_PL022_SSPTCR_TESTFIFO_POS 1
|
||||
#define SPI_PL022_SSPTCR_TESTFIFO_MSK (0x1ul<<SPI_PL022_SSPTCR_TESTFIFO_POS)
|
||||
|
||||
|
||||
/* Integration test input register */
|
||||
#define SPI_PL022_SSPITIP_RXD_POS 0
|
||||
#define SPI_PL022_SSPITIP_RXD_MSK (0x1ul<<SPI_PL022_SSPITIP_RXD_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_FSSIN_POS 1
|
||||
#define SPI_PL022_SSPITIP_FSSIN_MSK (0x1ul<<SPI_PL022_SSPITIP_FSSIN_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_CLKIN_POS 2
|
||||
#define SPI_PL022_SSPITIP_CLKIN_MSK (0x1ul<<SPI_PL022_SSPITIP_CLKIN_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_RXDMACLR_POS 3
|
||||
#define SPI_PL022_SSPITIP_RXDMACLR_MSK (0x1ul<<SPI_PL022_SSPITIP_RXDMACLR_POS)
|
||||
|
||||
#define SPI_PL022_SSPITIP_TXDMACLR_POS 4
|
||||
#define SPI_PL022_SSPITIP_TXDMACLR_MSK (0x1ul<<SPI_PL022_SSPITIP_TXDMACLR_POS)
|
||||
|
||||
/* Integration test output register */
|
||||
#define SPI_PL022_SSPITOP_RXDMABREQ_POS 10
|
||||
#define SPI_PL022_SSPITOP_RXDMABREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_RXDMABREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_RXDMASREQ_POS 11
|
||||
#define SPI_PL022_SSPITOP_RXDMASREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_RXDMASREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_TXDMABREQ_POS 12
|
||||
#define SPI_PL022_SSPITOP_TXDMABREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_TXDMABREQ_POS)
|
||||
|
||||
#define SPI_PL022_SSPITOP_TXDMASREQ_POS 13
|
||||
#define SPI_PL022_SSPITOP_TXDMASREQ_MSK (0x1ul<<SPI_PL022_SSPITOP_TXDMASREQ_POS)
|
||||
|
||||
/************************* PL022 Definitions End ******************************/
|
||||
|
||||
|
||||
/*
|
||||
* \brief Calculates clock prescale divisor and sets serial clock rate
|
||||
* for the SPI PL022 device.
|
||||
*
|
||||
* \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t
|
||||
* \param[in] sys_clk System clock.
|
||||
* \param[in/out] cr0 Pointer to PL022 control register 0
|
||||
* \ref spi_pl022_dev_reg_map_t
|
||||
*
|
||||
* \return Value of the SSPCPSR register \ref spi_pl022_dev_reg_map_t
|
||||
*
|
||||
* \note This function doesn't check if sys_clk or ctrl_cfg->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;i<total_len;i+=word_size){
|
||||
if (i<*tx_len_ptr) {
|
||||
tx_data = *(const uint16_t*)tx_ptr;
|
||||
} else {
|
||||
/* send FF if there is no more valid data to send */
|
||||
tx_data = 0xFFFF;
|
||||
}
|
||||
retval = spi_pl022_write(dev, dev->data->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;
|
||||
}
|
||||
|
|
@ -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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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<<SPI_PL022_RX_OR_INTR_POS)
|
||||
|
||||
/* Receive Timeout Interrupt */
|
||||
#define SPI_PL022_RX_TO_INTR_POS 1
|
||||
#define SPI_PL022_RX_TO_INTR_MSK (0x1ul<<SPI_PL022_RX_TO_INTR_POS)
|
||||
|
||||
/* Receive FIFO Interrupt */
|
||||
#define SPI_PL022_RX_FIFO_INTR_POS 2
|
||||
#define SPI_PL022_RX_FIFO_INTR_MSK (0x1ul<<SPI_PL022_RX_FIFO_INTR_POS)
|
||||
|
||||
/* Transmit FIFO Interrupt */
|
||||
#define SPI_PL022_TX_FIFO_INTR_POS 3
|
||||
#define SPI_PL022_TX_FIFO_INTR_MSK (0x1ul<<SPI_PL022_TX_FIFO_INTR_POS)
|
||||
|
||||
#define SPI_PL022_ALL_INTR_MSK \
|
||||
((0x1ul<<(SPI_PL022_TX_FIFO_INTR_POS+1))-1)
|
||||
|
||||
/* Status register bit defines */
|
||||
|
||||
/* Transmit FIFO empty */
|
||||
#define SPI_PL022_SSPSR_TFE_POS 0
|
||||
#define SPI_PL022_SSPSR_TFE_MSK (0x1ul<<SPI_PL022_SSPSR_TFE_POS)
|
||||
|
||||
/* Transmit FIFO not full */
|
||||
#define SPI_PL022_SSPSR_TNF_POS 1
|
||||
#define SPI_PL022_SSPSR_TNF_MSK (0x1ul<<SPI_PL022_SSPSR_TNF_POS)
|
||||
|
||||
/* Receive FIFO not empty */
|
||||
#define SPI_PL022_SSPSR_RNE_POS 2
|
||||
#define SPI_PL022_SSPSR_RNE_MSK (0x1ul<<SPI_PL022_SSPSR_RNE_POS)
|
||||
|
||||
/* Receive FIFO full */
|
||||
#define SPI_PL022_SSPSR_RFF_POS 3
|
||||
#define SPI_PL022_SSPSR_RFF_MSK (0x1ul<<SPI_PL022_SSPSR_RFF_POS)
|
||||
|
||||
/* Busy either tx/rx or transmit fifo not empty */
|
||||
#define SPI_PL022_SSPSR_BSY_POS 4
|
||||
#define SPI_PL022_SSPSR_BSY_MSK (0x1ul<<SPI_PL022_SSPSR_BSY_POS)
|
||||
|
||||
/**
|
||||
* \brief Enables PL022 SPI device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables PL022 SPI device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Returns SPI status register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Initializes the SPI PL022 device.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] sys_clk System clock.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk);
|
||||
|
||||
/**
|
||||
* \brief Sets the SPI PL022 device configuration.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] ctrl_cfg SPI control configuration.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* \brief Gets the SPI PL022 device configuration.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] ctrl_cfg Pointer to fill the SPI control configuration.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_ctrl_cfg_t* ctrl_cfg);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Selects SPI PL022 device as Master or Slave
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_mode_select_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_select_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_mode_select_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables/disables SPI PL022 Slave device output
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_slave_output_mode_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
* \note This function doesn't check if dev is Slave or Master
|
||||
*/
|
||||
void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_slave_output_mode_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables SPI PL022 device in loopback mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Mode selection \ref spi_pl022_loopback_select_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev,
|
||||
enum spi_pl022_loopback_select_t mode);
|
||||
|
||||
/**
|
||||
* \brief Clears interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to enable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to disable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Gets raw interrupt status of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns raw interrupt status value
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Gets masked interrupt status of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns masked interrupt status value
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Sets interrupt mask of SPI PL022
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] irq_mask Selection of interrupts to disable
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev,
|
||||
uint32_t irq_mask);
|
||||
|
||||
/**
|
||||
* \brief Enables transmit or receive DMA
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] dma Selects the DMA to be enabled
|
||||
* - bit position 0 - Receive DMA
|
||||
* - bit position 1 - Transmit DMA
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma);
|
||||
|
||||
/**
|
||||
* \brief Disables transmit or receive DMA
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] dma Selects the DMA to be disabled
|
||||
* - bit position 0 - Receive DMA
|
||||
* - bit position 1 - Transmit DMA
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev,
|
||||
uint32_t dma);
|
||||
|
||||
/**
|
||||
* \brief Gets peripheral identification of the device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] periphid Pointer to fill peripheral ids
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_periphid_t* periphid);
|
||||
|
||||
/**
|
||||
* \brief Gets PrimeCell identification of the device
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] cellid Pointer to fill PrimeCell ids
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev,
|
||||
struct spi_pl022_primecell_id_t* cellid);
|
||||
|
||||
/**
|
||||
* \brief Sets system clock.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] sys_clk System clock.
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev,
|
||||
uint32_t sys_clk);
|
||||
|
||||
/**
|
||||
* \brief Reads single data from SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[out] rx_ptr Buffer pointer to be filled
|
||||
* must be enough for configured word size
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev,
|
||||
void *rx_ptr);
|
||||
|
||||
/**
|
||||
* \brief Reads single data from slave SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \return Returns data value from the device
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* does not validate whether there is any data in the RX buffer
|
||||
*/
|
||||
uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Writes single data to SPI. Non blocking.
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] mode Master or slave \ref spi_pl022_mode_select_t
|
||||
* \param[out] tx_ptr Pointer to the data to be sent
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* \brief Transmit and Receive data on SPI in a blocking call
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
* \param[in] tx_ptr Buffer pointer to be filled
|
||||
* \param[in/out] tx_len_ptr Num values to transfer (updated on error)
|
||||
* need to be multiples of transfer word length
|
||||
* \param[out] rx_ptr Buffer pointer to be filled
|
||||
* \param[in/out] rx_len_ptr Num values to receive (updated on error)
|
||||
* need to be multiples of transfer word length
|
||||
*
|
||||
* \return Error code from \ref spi_pl022_error_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* if the driver is initialized to reduce the number of checks and
|
||||
* make the function execution faster.
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
/************************** TEST APIs ****************************/
|
||||
|
||||
/**
|
||||
* \brief Enables Test FIFO mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables Test FIFO mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enables Integration Test mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disables Integration Test mode
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Writes data to Test data register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL and
|
||||
* whether Test FIFO mode is enabled
|
||||
*/
|
||||
void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev, void *tx_ptr);
|
||||
|
||||
/**
|
||||
* \brief Reads integration test output register
|
||||
*
|
||||
* \param[in] dev SPI device structure \ref spi_pl022_dev_t
|
||||
*
|
||||
* \note This function doesn't check if dev is NULL
|
||||
*/
|
||||
uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __SPI_PL022_DRV_H__ */
|
|
@ -97,3 +97,114 @@ static const struct arm_mps2_io_dev_cfg_t ARM_MPS2_IO_SCC_DEV_CFG = {
|
|||
.type = ARM_MPS2_IO_TYPE_SCC};
|
||||
struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV = {&(ARM_MPS2_IO_SCC_DEV_CFG)};
|
||||
#endif /* ARM_MPS2_IO_SCC */
|
||||
|
||||
/* ARM SPI driver structure */
|
||||
#ifdef ARM_SPI0
|
||||
static const struct spi_pl022_dev_cfg_t SPI0_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP0_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI0_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI0_PL022_DEV = {&(SPI0_PL022_DEV_CFG),
|
||||
&(SPI0_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI0 */
|
||||
|
||||
#ifdef ARM_SPI1
|
||||
static const struct spi_pl022_dev_cfg_t SPI1_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP1_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI1_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI1_PL022_DEV = {&(SPI1_PL022_DEV_CFG),
|
||||
&(SPI1_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI1 */
|
||||
|
||||
#ifdef ARM_SPI2
|
||||
static const struct spi_pl022_dev_cfg_t SPI2_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP2_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI2_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI2_PL022_DEV = {&(SPI2_PL022_DEV_CFG),
|
||||
&(SPI2_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI2 */
|
||||
|
||||
#ifdef ARM_SPI3
|
||||
static const struct spi_pl022_dev_cfg_t SPI3_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP3_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI3_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI3_PL022_DEV = {&(SPI3_PL022_DEV_CFG),
|
||||
&(SPI3_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI3 */
|
||||
|
||||
#ifdef ARM_SPI4
|
||||
static const struct spi_pl022_dev_cfg_t SPI4_PL022_DEV_CFG = {
|
||||
.base = MPS2_SSP4_BASE,
|
||||
.default_ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = SPI_PL022_CFG_FRF_MOT,
|
||||
.word_size = 8,
|
||||
.bit_rate = DEFAULT_SPI_SPEED_HZ
|
||||
}};
|
||||
static struct spi_pl022_dev_data_t SPI4_PL022_DEV_DATA = {
|
||||
.state = 0,
|
||||
.sys_clk = 0,
|
||||
.ctrl_cfg = {
|
||||
.spi_mode = SPI_PL022_MASTER_SELECT,
|
||||
.frame_format = 0,
|
||||
.word_size = 0,
|
||||
.bit_rate = 0
|
||||
}};
|
||||
struct spi_pl022_dev_t SPI4_PL022_DEV = {&(SPI4_PL022_DEV_CFG),
|
||||
&(SPI4_PL022_DEV_DATA)};
|
||||
#endif /* ARM_SPI4 */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "timer_cmsdk_drv.h"
|
||||
#include "arm_gpio_drv.h"
|
||||
#include "arm_mps2_io_drv.h"
|
||||
#include "spi_pl022_drv.h"
|
||||
|
||||
/* ======= Defines peripheral configuration structures ======= */
|
||||
|
||||
|
@ -59,4 +60,21 @@ extern struct arm_mps2_io_dev_t ARM_MPS2_IO_FPGAIO_DEV;
|
|||
extern struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV;
|
||||
#endif
|
||||
|
||||
/* ARM SPI driver structures */
|
||||
#ifdef ARM_SPI0
|
||||
extern struct spi_pl022_dev_t SPI0_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI1
|
||||
extern struct spi_pl022_dev_t SPI1_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI2
|
||||
extern struct spi_pl022_dev_t SPI2_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI3
|
||||
extern struct spi_pl022_dev_t SPI3_PL022_DEV;
|
||||
#endif
|
||||
#ifdef ARM_SPI4
|
||||
extern struct spi_pl022_dev_t SPI4_PL022_DEV;
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */
|
||||
|
|
|
@ -66,11 +66,7 @@ struct audio_s {
|
|||
};
|
||||
|
||||
struct spi_s {
|
||||
MPS2_SSP_TypeDef *spi;
|
||||
};
|
||||
|
||||
struct clcd_s {
|
||||
MPS2_SSP_TypeDef *clcd;
|
||||
struct spi_pl022_dev_t *spi;
|
||||
};
|
||||
|
||||
struct analogin_s {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2017-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.
|
||||
|
@ -13,20 +13,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <math.h>
|
||||
|
||||
#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_PL022_SSPCR0_SCR_POS)
|
||||
|
||||
static const PinMap PinMap_SPI_SCLK[] = {
|
||||
{SPI_SCLK, SPI_0, 0},
|
||||
|
@ -64,231 +57,209 @@ static const PinMap PinMap_SPI_SSEL[] = {
|
|||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static inline int ssp_disable(spi_t *obj);
|
||||
static inline int ssp_enable(spi_t *obj);
|
||||
/* SPI configuration values */
|
||||
#define SPI_BITS_MIN_VALUE 4
|
||||
#define SPI_BITS_MAX_VALUE 16
|
||||
#define SPI_MODE_PHASE_BIT 0
|
||||
#define SPI_MODE_PHASE_BIT_MSK (0x1ul << SPI_MODE_PHASE_BIT)
|
||||
#define SPI_MODE_POLARITY_BIT 1
|
||||
#define SPI_MODE_POLARITY_BIT_MSK (0x1ul << SPI_MODE_POLARITY_BIT)
|
||||
#define SPI_MODE_MAX_VALUE_MSK ((0x1ul << (SPI_MODE_POLARITY_BIT+1))-1)
|
||||
|
||||
static uint32_t spi_fill_object(spi_t *obj, PinName mosi, PinName miso,
|
||||
PinName sclk, PinName ssel)
|
||||
{
|
||||
/* Determine the SPI to use */
|
||||
uint32_t spi_mosi = pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
||||
uint32_t spi_miso = pinmap_peripheral(miso, PinMap_SPI_MISO);
|
||||
uint32_t spi_sclk = pinmap_peripheral(sclk, PinMap_SPI_SCLK);
|
||||
uint32_t spi_ssel = pinmap_peripheral(ssel, PinMap_SPI_SSEL);
|
||||
uint32_t spi_data = pinmap_merge(spi_mosi, spi_miso);
|
||||
uint32_t spi_cntl = pinmap_merge(spi_sclk, spi_ssel);
|
||||
uint32_t spi_index = pinmap_merge(spi_data, spi_cntl);
|
||||
if ((spi_data == (uint32_t)NC) || (spi_index == (uint32_t)NC)) {
|
||||
/* Both miso and mosi or all 4 pins are NC */
|
||||
error("SPI pinout mapping failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (spi_index) {
|
||||
#ifdef ARM_SPI0
|
||||
case SPI_0:
|
||||
obj->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 */
|
||||
(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, ALTERNATE_FUNC);
|
||||
pin_function(mosi, pinmap_function(mosi, PinMap_SPI_MOSI));
|
||||
}
|
||||
if (miso != NC) {
|
||||
pin_function(miso, ALTERNATE_FUNC);
|
||||
}
|
||||
if (sclk != NC) {
|
||||
pin_function(sclk, ALTERNATE_FUNC);
|
||||
pin_function(miso, pinmap_function(miso, PinMap_SPI_MISO));
|
||||
}
|
||||
if (ssel != NC) {
|
||||
pin_function(ssel, ALTERNATE_FUNC);
|
||||
pin_function(ssel, pinmap_function(ssel, PinMap_SPI_SSEL));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
/* Default SPI frequency */
|
||||
spi_frequency(obj, 1000000);
|
||||
|
||||
/* Enable the ssp channel */
|
||||
ssp_enable(obj);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue