blob: ab4f2e5a39707ce3ddf15182f5c785b95b9f1615 [file] [log] [blame]
/***************************************************************************//**
* @file em_ebi.c
* @brief External Bus Interface (EBI) Peripheral API
* @version 5.6.0
*******************************************************************************
* # License
* <b>Copyright 2016 Silicon Laboratories, Inc. www.silabs.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#include "em_ebi.h"
#if defined(EBI_COUNT) && (EBI_COUNT > 0)
#include "em_assert.h"
#include "em_bus.h"
/***************************************************************************//**
* @addtogroup emlib
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup EBI
* @brief EBI External Bus Interface (EBI) Peripheral API
* @details
* This module contains functions to control the EBI peripheral of Silicon
* Labs 32-bit MCUs and SoCs. The EBI is used for accessing external parallel
* devices. The devices appear as part of the internal memory map of the MCU.
* @{
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/* The ROUTE register has been renamed in the newest platform so these register
* field names have been created to make it easier to work with both
* the new and the old names in a generic way. */
#if defined(_EBI_ROUTE_MASK)
#define _EBI_GENERIC_ALEPEN_SHIFT _EBI_ROUTE_ALEPEN_SHIFT
#define _EBI_GENERIC_BLPEN_SHIFT _EBI_ROUTE_BLPEN_SHIFT
#define _EBI_GENERIC_EBIPEN_SHIFT _EBI_ROUTE_EBIPEN_SHIFT
#define _EBI_GENERIC_CS0PEN_SHIFT _EBI_ROUTE_CS0PEN_SHIFT
#define _EBI_GENERIC_CS1PEN_SHIFT _EBI_ROUTE_CS1PEN_SHIFT
#define _EBI_GENERIC_CS2PEN_SHIFT _EBI_ROUTE_CS2PEN_SHIFT
#define _EBI_GENERIC_CS3PEN_SHIFT _EBI_ROUTE_CS3PEN_SHIFT
#define _EBI_GENERIC_RESETVALUE _EBI_ROUTE_RESETVALUE
#define EBI_GENERIC_ROUTE_REG EBI->ROUTE
#define _EBI_GENERIC_ALB_MASK _EBI_ROUTE_ALB_MASK
#define _EBI_GENERIC_APEN_MASK _EBI_ROUTE_APEN_MASK
#define EBI_GENERIC_TFTPEN EBI_ROUTE_TFTPEN
#else
#define _EBI_GENERIC_ALEPEN_SHIFT _EBI_ROUTEPEN_ALEPEN_SHIFT
#define _EBI_GENERIC_BLPEN_SHIFT _EBI_ROUTEPEN_BLPEN_SHIFT
#define _EBI_GENERIC_EBIPEN_SHIFT _EBI_ROUTEPEN_EBIPEN_SHIFT
#define _EBI_GENERIC_CS0PEN_SHIFT _EBI_ROUTEPEN_CS0PEN_SHIFT
#define _EBI_GENERIC_CS1PEN_SHIFT _EBI_ROUTEPEN_CS1PEN_SHIFT
#define _EBI_GENERIC_CS2PEN_SHIFT _EBI_ROUTEPEN_CS2PEN_SHIFT
#define _EBI_GENERIC_CS3PEN_SHIFT _EBI_ROUTEPEN_CS3PEN_SHIFT
#define _EBI_GENERIC_RESETVALUE _EBI_ROUTEPEN_RESETVALUE
#define EBI_GENERIC_ROUTE_REG EBI->ROUTEPEN
#define _EBI_GENERIC_ALB_MASK _EBI_ROUTEPEN_ALB_MASK
#define _EBI_GENERIC_NANDPEN_MASK _EBI_ROUTEPEN_NANDPEN_MASK
#define _EBI_GENERIC_APEN_MASK _EBI_ROUTEPEN_APEN_MASK
#define EBI_GENERIC_TFTPEN EBI_ROUTEPEN_TFTPEN
#endif
/***************************************************************************//**
* @brief
* Perform a single-bit write operation on an EBI route register.
*
* @param[in] bit
* bit Bit position to write, 0-31.
*
* @param[in] val
* 0 to clear bit and 1 to set bit.
******************************************************************************/
__STATIC_INLINE void EBI_RouteBitWrite(uint32_t bit, uint32_t val)
{
BUS_RegBitWrite(&(EBI_GENERIC_ROUTE_REG), bit, val);
}
/** @endcond */
/***************************************************************************//**
* @brief
* Configure and enable the External Bus Interface.
*
* @param[in] ebiInit
* The EBI configuration structure.
*
* @note
* GPIO lines must be configured as a PUSH_PULL for the correct operation.
* GPIO and EBI clocks must be enabled in the CMU.
******************************************************************************/
void EBI_Init(const EBI_Init_TypeDef *ebiInit)
{
uint32_t ctrl = EBI->CTRL;
#if defined(_EFM32_GECKO_FAMILY)
/* Set polarity of address ready */
EBI_PolaritySet(ebiLineARDY, ebiInit->ardyPolarity);
/* Set polarity of address latch enable */
EBI_PolaritySet(ebiLineALE, ebiInit->alePolarity);
/* Set polarity of write enable */
EBI_PolaritySet(ebiLineWE, ebiInit->wePolarity);
/* Set polarity of read enable */
EBI_PolaritySet(ebiLineRE, ebiInit->rePolarity);
/* Set polarity of chip select lines */
EBI_PolaritySet(ebiLineCS, ebiInit->csPolarity);
#else
/* Enable Independent Timing for devices that support it. */
ctrl |= EBI_CTRL_ITS;
/* Set the polarity of address ready. */
EBI_BankPolaritySet(ebiInit->banks, ebiLineARDY, ebiInit->ardyPolarity);
/* Set the polarity of address latch enable. */
EBI_BankPolaritySet(ebiInit->banks, ebiLineALE, ebiInit->alePolarity);
/* Set polarity of write enable */
EBI_BankPolaritySet(ebiInit->banks, ebiLineWE, ebiInit->wePolarity);
/* Set polarity of read enable */
EBI_BankPolaritySet(ebiInit->banks, ebiLineRE, ebiInit->rePolarity);
/* Set polarity of chip select lines */
EBI_BankPolaritySet(ebiInit->banks, ebiLineCS, ebiInit->csPolarity);
/* Set polarity of byte lane line */
EBI_BankPolaritySet(ebiInit->banks, ebiLineBL, ebiInit->blPolarity);
#endif
/* Configure EBI mode and control settings. */
#if defined(_EFM32_GECKO_FAMILY)
ctrl &= ~(_EBI_CTRL_MODE_MASK
| _EBI_CTRL_ARDYEN_MASK
| _EBI_CTRL_ARDYTODIS_MASK
| _EBI_CTRL_BANK0EN_MASK
| _EBI_CTRL_BANK1EN_MASK
| _EBI_CTRL_BANK2EN_MASK
| _EBI_CTRL_BANK3EN_MASK);
if ( ebiInit->enable) {
if ( ebiInit->banks & EBI_BANK0 ) {
ctrl |= EBI_CTRL_BANK0EN;
}
if ( ebiInit->banks & EBI_BANK1 ) {
ctrl |= EBI_CTRL_BANK1EN;
}
if ( ebiInit->banks & EBI_BANK2 ) {
ctrl |= EBI_CTRL_BANK2EN;
}
if ( ebiInit->banks & EBI_BANK3 ) {
ctrl |= EBI_CTRL_BANK3EN;
}
}
ctrl |= ebiInit->mode;
ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDYEN_SHIFT);
ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTODIS_SHIFT);
#else
if (ebiInit->banks & EBI_BANK0) {
ctrl &= ~(_EBI_CTRL_MODE_MASK
| _EBI_CTRL_ARDYEN_MASK
| _EBI_CTRL_ARDYTODIS_MASK
| _EBI_CTRL_BL_MASK
| _EBI_CTRL_NOIDLE_MASK
| _EBI_CTRL_BANK0EN_MASK);
ctrl |= (ebiInit->mode << _EBI_CTRL_MODE_SHIFT);
ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDYEN_SHIFT);
ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTODIS_SHIFT);
ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL_SHIFT);
ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE_SHIFT);
if ( ebiInit->enable) {
ctrl |= EBI_CTRL_BANK0EN;
}
}
if (ebiInit->banks & EBI_BANK1) {
ctrl &= ~(_EBI_CTRL_BL1_MASK
| _EBI_CTRL_MODE1_MASK
| _EBI_CTRL_ARDY1EN_MASK
| _EBI_CTRL_ARDYTO1DIS_MASK
| _EBI_CTRL_NOIDLE1_MASK
| _EBI_CTRL_BANK1EN_MASK);
ctrl |= (ebiInit->mode << _EBI_CTRL_MODE1_SHIFT);
ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY1EN_SHIFT);
ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO1DIS_SHIFT);
ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL1_SHIFT);
ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE1_SHIFT);
if ( ebiInit->enable) {
ctrl |= EBI_CTRL_BANK1EN;
}
}
if (ebiInit->banks & EBI_BANK2) {
ctrl &= ~(_EBI_CTRL_BL2_MASK
| _EBI_CTRL_MODE2_MASK
| _EBI_CTRL_ARDY2EN_MASK
| _EBI_CTRL_ARDYTO2DIS_MASK
| _EBI_CTRL_NOIDLE2_MASK
| _EBI_CTRL_BANK2EN_MASK);
ctrl |= (ebiInit->mode << _EBI_CTRL_MODE2_SHIFT);
ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY2EN_SHIFT);
ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO2DIS_SHIFT);
ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL2_SHIFT);
ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE2_SHIFT);
if ( ebiInit->enable) {
ctrl |= EBI_CTRL_BANK2EN;
}
}
if (ebiInit->banks & EBI_BANK3) {
ctrl &= ~(_EBI_CTRL_BL3_MASK
| _EBI_CTRL_MODE3_MASK
| _EBI_CTRL_ARDY3EN_MASK
| _EBI_CTRL_ARDYTO3DIS_MASK
| _EBI_CTRL_NOIDLE3_MASK
| _EBI_CTRL_BANK3EN_MASK);
ctrl |= (ebiInit->mode << _EBI_CTRL_MODE3_SHIFT);
ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY3EN_SHIFT);
ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO3DIS_SHIFT);
ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL3_SHIFT);
ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE3_SHIFT);
if ( ebiInit->enable) {
ctrl |= EBI_CTRL_BANK3EN;
}
}
#endif
/* Configure timing. */
#if defined(_EFM32_GECKO_FAMILY)
EBI_ReadTimingSet(ebiInit->readSetupCycles,
ebiInit->readStrobeCycles,
ebiInit->readHoldCycles);
EBI_WriteTimingSet(ebiInit->writeSetupCycles,
ebiInit->writeStrobeCycles,
ebiInit->writeHoldCycles);
EBI_AddressTimingSet(ebiInit->addrSetupCycles,
ebiInit->addrHoldCycles);
#else
EBI_BankReadTimingSet(ebiInit->banks,
ebiInit->readSetupCycles,
ebiInit->readStrobeCycles,
ebiInit->readHoldCycles);
EBI_BankReadTimingConfig(ebiInit->banks,
ebiInit->readPageMode,
ebiInit->readPrefetch,
ebiInit->readHalfRE);
EBI_BankWriteTimingSet(ebiInit->banks,
ebiInit->writeSetupCycles,
ebiInit->writeStrobeCycles,
ebiInit->writeHoldCycles);
EBI_BankWriteTimingConfig(ebiInit->banks,
ebiInit->writeBufferDisable,
ebiInit->writeHalfWE);
EBI_BankAddressTimingSet(ebiInit->banks,
ebiInit->addrSetupCycles,
ebiInit->addrHoldCycles);
EBI_BankAddressTimingConfig(ebiInit->banks,
ebiInit->addrHalfALE);
#endif
/* Activate the new configuration. */
EBI->CTRL = ctrl;
/* Configure Address Latch Enable. */
switch (ebiInit->mode) {
case ebiModeD16A16ALE:
case ebiModeD8A24ALE:
/* Address Latch Enable. */
EBI_RouteBitWrite(_EBI_GENERIC_ALEPEN_SHIFT, 1);
break;
#if defined(EBI_CTRL_MODE_D16)
case ebiModeD16:
#endif
case ebiModeD8A8:
/* Make sure that Address Latch is disabled. */
EBI_RouteBitWrite(_EBI_GENERIC_ALEPEN_SHIFT, 0);
break;
}
#if !defined(_EFM32_GECKO_FAMILY)
/* Limit the pin enable. */
EBI_GENERIC_ROUTE_REG = (EBI_GENERIC_ROUTE_REG & ~_EBI_GENERIC_ALB_MASK) | ebiInit->aLow;
EBI_GENERIC_ROUTE_REG = (EBI_GENERIC_ROUTE_REG & ~_EBI_GENERIC_APEN_MASK) | ebiInit->aHigh;
#if defined(_EBI_ROUTE_LOCATION_MASK)
/* Location. */
EBI->ROUTE = (EBI->ROUTE & ~_EBI_ROUTE_LOCATION_MASK) | ebiInit->location;
#endif
/* Enable the EBI BL pin if necessary. */
if (ctrl & (_EBI_CTRL_BL_MASK | _EBI_CTRL_BL1_MASK | _EBI_CTRL_BL2_MASK | _EBI_CTRL_BL3_MASK)) {
EBI_RouteBitWrite(_EBI_GENERIC_BLPEN_SHIFT, ebiInit->blEnable);
}
#endif
/* Enable EBI pins EBI_WEn and EBI_REn. */
EBI_RouteBitWrite(_EBI_GENERIC_EBIPEN_SHIFT, 1);
/* Enable chip select lines. */
EBI_ChipSelectEnable(ebiInit->csLines, true);
}
/***************************************************************************//**
* @brief
* Disable External Bus Interface
******************************************************************************/
void EBI_Disable(void)
{
/* Disable pins */
EBI_GENERIC_ROUTE_REG = _EBI_GENERIC_RESETVALUE;
/* Disable banks */
EBI->CTRL = _EBI_CTRL_RESETVALUE;
}
/***************************************************************************//**
* @brief
* Enable or disable EBI Bank.
*
* @param[in] banks
* Banks to reconfigure, mask of EBI_BANK<n> flags.
*
* @param[in] enable
* True to enable, false to disable.
******************************************************************************/
void EBI_BankEnable(uint32_t banks, bool enable)
{
if (banks & EBI_BANK0) {
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK0EN_SHIFT, enable);
}
if (banks & EBI_BANK1) {
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK1EN_SHIFT, enable);
}
if (banks & EBI_BANK2) {
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK2EN_SHIFT, enable);
}
if (banks & EBI_BANK3) {
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK3EN_SHIFT, enable);
}
}
/***************************************************************************//**
* @brief
* Return the base address of the EBI bank.
*
* @param[in] bank
* A bank to return the start address for.
*
* @return
* an absolute address of the bank.
******************************************************************************/
uint32_t EBI_BankAddress(uint32_t bank)
{
#if defined (EBI_CTRL_ALTMAP)
if (EBI->CTRL & EBI_CTRL_ALTMAP) {
switch (bank) {
case EBI_BANK0:
return EBI_MEM_BASE;
case EBI_BANK1:
return EBI_MEM_BASE + 0x10000000UL;
case EBI_BANK2:
return EBI_MEM_BASE + 0x20000000UL;
case EBI_BANK3:
return EBI_MEM_BASE + 0x30000000UL;
default:
EFM_ASSERT(0);
break;
}
}
#endif
switch (bank) {
case EBI_BANK0:
return EBI_MEM_BASE;
case EBI_BANK1:
return EBI_MEM_BASE + 0x04000000UL;
case EBI_BANK2:
return EBI_MEM_BASE + 0x08000000UL;
case EBI_BANK3:
return EBI_MEM_BASE + 0x0C000000UL;
default:
EFM_ASSERT(0);
break;
}
return 0;
}
#if defined(_EBI_NANDCTRL_MASK)
/***************************************************************************//**
* @brief
* Enable or disable EBI NAND Flash Support
*
* @param[in] banks
* Banks to reconfigure, mask of EBI_BANK<n> flags.
*
* @param[in] enable
* True to enable, false to disable.
******************************************************************************/
void EBI_NANDFlashEnable(uint32_t banks, bool enable)
{
if (banks & EBI_BANK0) {
BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_BANKSEL_SHIFT, _EBI_NANDCTRL_BANKSEL_BANK0);
}
if (banks & EBI_BANK1) {
BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_BANKSEL_SHIFT, _EBI_NANDCTRL_BANKSEL_BANK1);
}
if (banks & EBI_BANK2) {
BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_BANKSEL_SHIFT, _EBI_NANDCTRL_BANKSEL_BANK2);
}
if (banks & EBI_BANK3) {
BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_BANKSEL_SHIFT, _EBI_NANDCTRL_BANKSEL_BANK3);
}
BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_EN_SHIFT, enable);
}
#endif
/***************************************************************************//**
* @brief
* Enable or disable EBI Chip Select.
*
* @param[in] cs
* ChipSelect lines to reconfigure, mask of EBI_CS<n> flags.
*
* @param[in] enable
* True to enable, false to disable.
******************************************************************************/
void EBI_ChipSelectEnable(uint32_t cs, bool enable)
{
if (cs & EBI_CS0) {
EBI_RouteBitWrite(_EBI_GENERIC_CS0PEN_SHIFT, enable);
}
if (cs & EBI_CS1) {
EBI_RouteBitWrite(_EBI_GENERIC_CS1PEN_SHIFT, enable);
}
if (cs & EBI_CS2) {
EBI_RouteBitWrite(_EBI_GENERIC_CS2PEN_SHIFT, enable);
}
if (cs & EBI_CS3) {
EBI_RouteBitWrite(_EBI_GENERIC_CS3PEN_SHIFT, enable);
}
}
/***************************************************************************//**
* @brief
* Configure EBI pin polarity.
*
* @param[in] line
* Which pin/line to configure.
*
* @param[in] polarity
* Active high or active low.
******************************************************************************/
void EBI_PolaritySet(EBI_Line_TypeDef line, EBI_Polarity_TypeDef polarity)
{
switch (line) {
case ebiLineARDY:
BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_ARDYPOL_SHIFT, polarity);
break;
case ebiLineALE:
BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_ALEPOL_SHIFT, polarity);
break;
case ebiLineWE:
BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_WEPOL_SHIFT, polarity);
break;
case ebiLineRE:
BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_REPOL_SHIFT, polarity);
break;
case ebiLineCS:
BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_CSPOL_SHIFT, polarity);
break;
#if defined(_EBI_POLARITY_BLPOL_MASK)
case ebiLineBL:
BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_BLPOL_SHIFT, polarity);
break;
#endif
#if defined (_EBI_TFTPOLARITY_MASK)
case ebiLineTFTVSync:
BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity);
break;
case ebiLineTFTHSync:
BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity);
break;
case ebiLineTFTDataEn:
BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity);
break;
case ebiLineTFTDClk:
BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity);
break;
case ebiLineTFTCS:
BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_CSPOL_SHIFT, polarity);
break;
#endif
default:
EFM_ASSERT(0);
break;
}
}
/***************************************************************************//**
* @brief
* Configure timing values of read bus accesses.
*
* @param[in] setupCycles
* A number of clock cycles for the address setup before REn is asserted.
*
* @param[in] strobeCycles
* The number of cycles the REn is held active. After the specified number of
* cycles, data is read. If set to 0, 1 cycle is inserted by hardware.
*
* @param[in] holdCycles
* The number of cycles CSn is held active after the REn is deasserted.
******************************************************************************/
void EBI_ReadTimingSet(uint32_t setupCycles, uint32_t strobeCycles, uint32_t holdCycles)
{
uint32_t readTiming;
/* Check that timings are within limits */
EFM_ASSERT(setupCycles <= _EBI_RDTIMING_RDSETUP_MASK >> _EBI_RDTIMING_RDSETUP_SHIFT);
EFM_ASSERT(strobeCycles <= _EBI_RDTIMING_RDSTRB_MASK >> _EBI_RDTIMING_RDSTRB_SHIFT);
EFM_ASSERT(holdCycles <= _EBI_RDTIMING_RDHOLD_MASK >> _EBI_RDTIMING_RDHOLD_SHIFT);
/* Configure timing values */
readTiming = (setupCycles << _EBI_RDTIMING_RDSETUP_SHIFT)
| (strobeCycles << _EBI_RDTIMING_RDSTRB_SHIFT)
| (holdCycles << _EBI_RDTIMING_RDHOLD_SHIFT);
EBI->RDTIMING = (EBI->RDTIMING
& ~(_EBI_RDTIMING_RDSETUP_MASK
| _EBI_RDTIMING_RDSTRB_MASK
| _EBI_RDTIMING_RDHOLD_MASK))
| readTiming;
}
/***************************************************************************//**
* @brief
* Configure timing values of write bus accesses.
*
* @param[in] setupCycles
* A number of clock cycles for the address setup before WEn is asserted.
*
* @param[in] strobeCycles
* A number of cycles WEn is held active. If set to 0, 1 cycle is inserted by hardware.
*
* @param[in] holdCycles
* A number of cycles CSn is held active after the WEn is deasserted.
******************************************************************************/
void EBI_WriteTimingSet(uint32_t setupCycles, uint32_t strobeCycles, uint32_t holdCycles)
{
uint32_t writeTiming;
/* Check that timings are within limits */
EFM_ASSERT(setupCycles <= _EBI_WRTIMING_WRSETUP_MASK >> _EBI_WRTIMING_WRSETUP_SHIFT);
EFM_ASSERT(strobeCycles <= _EBI_WRTIMING_WRSTRB_MASK >> _EBI_WRTIMING_WRSTRB_SHIFT);
EFM_ASSERT(holdCycles <= _EBI_WRTIMING_WRHOLD_MASK >> _EBI_WRTIMING_WRHOLD_SHIFT);
/* Configure timing values. */
writeTiming = (setupCycles << _EBI_WRTIMING_WRSETUP_SHIFT)
| (strobeCycles << _EBI_WRTIMING_WRSTRB_SHIFT)
| (holdCycles << _EBI_WRTIMING_WRHOLD_SHIFT);
EBI->WRTIMING = (EBI->WRTIMING
& ~(_EBI_WRTIMING_WRSETUP_MASK
| _EBI_WRTIMING_WRSTRB_MASK
| _EBI_WRTIMING_WRHOLD_MASK))
| writeTiming;
}
/***************************************************************************//**
* @brief
* Configure timing values of address latch bus accesses.
*
* @param[in] setupCycles
* Sets the number of cycles the address is held after ALE is asserted.
*
* @param[in] holdCycles
* Sets the number of cycles the address is driven onto the ADDRDAT bus before
* ALE is asserted. If set 0, 1 cycle is inserted by hardware.
******************************************************************************/
void EBI_AddressTimingSet(uint32_t setupCycles, uint32_t holdCycles)
{
uint32_t addressLatchTiming;
/* Check that timings are within limits */
EFM_ASSERT(setupCycles <= _EBI_ADDRTIMING_ADDRSETUP_MASK >> _EBI_ADDRTIMING_ADDRSETUP_SHIFT);
EFM_ASSERT(holdCycles <= _EBI_ADDRTIMING_ADDRHOLD_MASK >> _EBI_ADDRTIMING_ADDRHOLD_SHIFT);
/* Configure address latch timing values. */
addressLatchTiming = (setupCycles << _EBI_ADDRTIMING_ADDRSETUP_SHIFT)
| (holdCycles << _EBI_ADDRTIMING_ADDRHOLD_SHIFT);
EBI->ADDRTIMING = (EBI->ADDRTIMING
& ~(_EBI_ADDRTIMING_ADDRSETUP_MASK
| _EBI_ADDRTIMING_ADDRHOLD_MASK))
| addressLatchTiming;
}
#if defined(_EBI_TFTCTRL_MASK)
/***************************************************************************//**
* @brief
* Configure and initialize TFT Direct Drive.
*
* @param[in] ebiTFTInit
* The TFT Initialization structure.
******************************************************************************/
void EBI_TFTInit(const EBI_TFTInit_TypeDef *ebiTFTInit)
{
uint32_t ctrl;
/* Configure the base address for the frame buffer offset to the EBI bank. */
EBI_TFTFrameBaseSet(ebiTFTInit->addressOffset);
/* Configure the display size and porch areas. */
EBI_TFTSizeSet(ebiTFTInit->hsize,
ebiTFTInit->vsize);
EBI_TFTHPorchSet(ebiTFTInit->hPorchFront,
ebiTFTInit->hPorchBack,
ebiTFTInit->hPulseWidth);
EBI_TFTVPorchSet(ebiTFTInit->vPorchFront,
ebiTFTInit->vPorchBack,
ebiTFTInit->vPulseWidth);
/* Configure timing settings. */
EBI_TFTTimingSet(ebiTFTInit->dclkPeriod,
ebiTFTInit->startPosition,
ebiTFTInit->setupCycles,
ebiTFTInit->holdCycles);
/* Configure line polarity settings. */
EBI_PolaritySet(ebiLineTFTCS, ebiTFTInit->csPolarity);
EBI_PolaritySet(ebiLineTFTDClk, ebiTFTInit->dclkPolarity);
EBI_PolaritySet(ebiLineTFTDataEn, ebiTFTInit->dataenPolarity);
EBI_PolaritySet(ebiLineTFTVSync, ebiTFTInit->vsyncPolarity);
EBI_PolaritySet(ebiLineTFTHSync, ebiTFTInit->hsyncPolarity);
/* Main control, EBI bank select, mask and blending configuration. */
ctrl = (uint32_t)ebiTFTInit->bank
| (uint32_t)ebiTFTInit->width
| (uint32_t)ebiTFTInit->colSrc
| (uint32_t)ebiTFTInit->interleave
| (uint32_t)ebiTFTInit->fbTrigger
| (uint32_t)(ebiTFTInit->shiftDClk == true
? (1 << _EBI_TFTCTRL_SHIFTDCLKEN_SHIFT) : 0)
| (uint32_t)ebiTFTInit->maskBlend
| (uint32_t)ebiTFTInit->driveMode;
EBI->TFTCTRL = ctrl;
/* Enable TFT pins. */
if (ebiTFTInit->driveMode != ebiTFTDDModeDisabled) {
EBI_GENERIC_ROUTE_REG |= EBI_GENERIC_TFTPEN;
}
}
/***************************************************************************//**
* @brief
* Configure and initialize TFT size settings.
*
* @param[in] horizontal
* TFT display horizontal size in pixels.
* @param[in] vertical
* TFT display vertical size in pixels.
******************************************************************************/
void EBI_TFTSizeSet(uint32_t horizontal, uint32_t vertical)
{
EFM_ASSERT((horizontal - 1) <= _EBI_TFTSIZE_HSZ_MASK >> _EBI_TFTSIZE_HSZ_SHIFT);
EFM_ASSERT((vertical - 1) <= _EBI_TFTSIZE_VSZ_MASK >> _EBI_TFTSIZE_VSZ_SHIFT);
EBI->TFTSIZE = ((horizontal - 1) << _EBI_TFTSIZE_HSZ_SHIFT)
| ((vertical - 1) << _EBI_TFTSIZE_VSZ_SHIFT);
}
/***************************************************************************//**
* @brief
* Configure and initialize Horizontal Porch Settings.
*
* @param[in] front
* Horizontal front porch size in pixels.
* @param[in] back
* Horizontal back porch size in pixels.
* @param[in] pulseWidth
* Horizontal synchronization pulse width. Set to required -1.
******************************************************************************/
void EBI_TFTHPorchSet(uint32_t front, uint32_t back, uint32_t pulseWidth)
{
EFM_ASSERT(front <= _EBI_TFTHPORCH_HFPORCH_MASK >> _EBI_TFTHPORCH_HFPORCH_SHIFT);
EFM_ASSERT(back <= _EBI_TFTHPORCH_HBPORCH_MASK >> _EBI_TFTHPORCH_HBPORCH_SHIFT);
EFM_ASSERT((pulseWidth - 1) <= _EBI_TFTHPORCH_HSYNC_MASK >> _EBI_TFTHPORCH_HSYNC_SHIFT);
EBI->TFTHPORCH = (front << _EBI_TFTHPORCH_HFPORCH_SHIFT)
| (back << _EBI_TFTHPORCH_HBPORCH_SHIFT)
| ((pulseWidth - 1) << _EBI_TFTHPORCH_HSYNC_SHIFT);
}
/***************************************************************************//**
* @brief
* Configure Vertical Porch Settings.
*
* @param[in] front
* Vertical front porch size in pixels.
* @param[in] back
* Vertical back porch size in pixels.
* @param[in] pulseWidth
* Vertical synchronization pulse width. Set to required -1.
******************************************************************************/
void EBI_TFTVPorchSet(uint32_t front, uint32_t back, uint32_t pulseWidth)
{
EFM_ASSERT(front <= _EBI_TFTVPORCH_VFPORCH_MASK >> _EBI_TFTVPORCH_VFPORCH_SHIFT);
EFM_ASSERT(back <= _EBI_TFTVPORCH_VBPORCH_MASK >> _EBI_TFTVPORCH_VBPORCH_SHIFT);
EFM_ASSERT((pulseWidth - 1) <= _EBI_TFTVPORCH_VSYNC_MASK >> _EBI_TFTVPORCH_VSYNC_SHIFT);
EBI->TFTVPORCH = (front << _EBI_TFTVPORCH_VFPORCH_SHIFT)
| (back << _EBI_TFTVPORCH_VBPORCH_SHIFT)
| ((pulseWidth - 1) << _EBI_TFTVPORCH_VSYNC_SHIFT);
}
/***************************************************************************//**
* @brief
* Configure TFT Direct Drive Timing Settings.
*
* @param[in] dclkPeriod
* DCLK period in internal cycles.
*
* @param[in] start
* A starting position of the external direct drive, relative to the DCLK inactive edge.
*
* @param[in] setup
* A number of cycles that RGB data is driven before the active edge of DCLK.
*
* @param[in] hold
* A number of cycles that RGB data is held after the active edge of DCLK.
******************************************************************************/
void EBI_TFTTimingSet(uint32_t dclkPeriod, uint32_t start, uint32_t setup, uint32_t hold)
{
/* Check that timings are within limits */
EFM_ASSERT(dclkPeriod <= _EBI_TFTTIMING_DCLKPERIOD_MASK >> _EBI_TFTTIMING_DCLKPERIOD_SHIFT);
EFM_ASSERT(start <= _EBI_TFTTIMING_TFTSTART_MASK >> _EBI_TFTTIMING_TFTSTART_SHIFT);
EFM_ASSERT(setup <= _EBI_TFTTIMING_TFTSETUP_MASK >> _EBI_TFTTIMING_TFTSETUP_SHIFT);
EFM_ASSERT(hold <= _EBI_TFTTIMING_TFTHOLD_MASK >> _EBI_TFTTIMING_TFTHOLD_SHIFT);
EBI->TFTTIMING = (dclkPeriod << _EBI_TFTTIMING_DCLKPERIOD_SHIFT)
| (start << _EBI_TFTTIMING_TFTSTART_SHIFT)
| (setup << _EBI_TFTTIMING_TFTSETUP_SHIFT)
| (hold << _EBI_TFTTIMING_TFTHOLD_SHIFT);
}
#endif
#if !defined(_EFM32_GECKO_FAMILY)
/***************************************************************************//**
* @brief
* Configure read operation parameters for a selected bank.
*
* @param[in] banks
* A mask of memory bank(s) to configure write timing for.
*
* @param[in] pageMode
* Enables or disables the half cycle WE strobe in the last strobe cycle.
*
* @param[in] prefetch
* Enables or disables the half cycle WE strobe in the last strobe cycle.
*
* @param[in] halfRE
* Enables or disables the half cycle WE strobe in the last strobe cycle.
******************************************************************************/
void EBI_BankReadTimingConfig(uint32_t banks, bool pageMode, bool prefetch, bool halfRE)
{
/* Verify only valid banks are used */
EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
/* Configure read operation parameters. */
if ( banks & EBI_BANK0 ) {
BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode);
BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch);
BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_HALFRE_SHIFT, halfRE);
}
if ( banks & EBI_BANK1 ) {
BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode);
BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch);
BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_HALFRE_SHIFT, halfRE);
}
if ( banks & EBI_BANK2 ) {
BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode);
BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch);
BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_HALFRE_SHIFT, halfRE);
}
if ( banks & EBI_BANK3 ) {
BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode);
BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch);
BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_HALFRE_SHIFT, halfRE);
}
}
/***************************************************************************//**
* @brief
* Configure timing values of read bus accesses.
*
* @param[in] banks
* A mask of memory bank(s) to configure timing for.
*
* @param[in] setupCycles
* A number of clock cycles for address setup before REn is asserted.
*
* @param[in] strobeCycles
* The number of cycles the REn is held active. After the specified number of
* cycles, data is read. If set to 0, 1 cycle is inserted by hardware.
*
* @param[in] holdCycles
* The number of cycles CSn is held active after the REn is deasserted.
******************************************************************************/
void EBI_BankReadTimingSet(uint32_t banks, uint32_t setupCycles, uint32_t strobeCycles, uint32_t holdCycles)
{
uint32_t readTiming;
/* Verify only valid banks are used. */
EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
/* Check that timings are within limits */
EFM_ASSERT(setupCycles <= _EBI_RDTIMING_RDSETUP_MASK >> _EBI_RDTIMING_RDSETUP_SHIFT);
EFM_ASSERT(strobeCycles <= _EBI_RDTIMING_RDSTRB_MASK >> _EBI_RDTIMING_RDSTRB_SHIFT);
EFM_ASSERT(holdCycles <= _EBI_RDTIMING_RDHOLD_MASK >> _EBI_RDTIMING_RDHOLD_SHIFT);
/* Configure timing values. */
readTiming = (setupCycles << _EBI_RDTIMING_RDSETUP_SHIFT)
| (strobeCycles << _EBI_RDTIMING_RDSTRB_SHIFT)
| (holdCycles << _EBI_RDTIMING_RDHOLD_SHIFT);
if (banks & EBI_BANK0) {
EBI->RDTIMING = (EBI->RDTIMING
& ~(_EBI_RDTIMING_RDSETUP_MASK
| _EBI_RDTIMING_RDSTRB_MASK
| _EBI_RDTIMING_RDHOLD_MASK))
| readTiming;
}
if (banks & EBI_BANK1) {
EBI->RDTIMING1 = (EBI->RDTIMING1
& ~(_EBI_RDTIMING1_RDSETUP_MASK
| _EBI_RDTIMING1_RDSTRB_MASK
| _EBI_RDTIMING1_RDHOLD_MASK))
| readTiming;
}
if (banks & EBI_BANK2) {
EBI->RDTIMING2 = (EBI->RDTIMING2
& ~(_EBI_RDTIMING2_RDSETUP_MASK
| _EBI_RDTIMING2_RDSTRB_MASK
| _EBI_RDTIMING2_RDHOLD_MASK))
| readTiming;
}
if (banks & EBI_BANK3) {
EBI->RDTIMING3 = (EBI->RDTIMING3
& ~(_EBI_RDTIMING3_RDSETUP_MASK
| _EBI_RDTIMING3_RDSTRB_MASK
| _EBI_RDTIMING3_RDHOLD_MASK))
| readTiming;
}
}
/***************************************************************************//**
* @brief
* Configure write operation parameters for a selected bank.
*
* @param[in] banks
* A mask of memory bank(s) to configure write timing for.
*
* @param[in] writeBufDisable
* If true, disable the write buffer.
*
* @param[in] halfWE
* Enables or disables half cycle WE strobe in the last strobe cycle.
******************************************************************************/
void EBI_BankWriteTimingConfig(uint32_t banks, bool writeBufDisable, bool halfWE)
{
/* Verify only valid banks are used. */
EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
/* Configure write operation parameters. */
if ( banks & EBI_BANK0 ) {
BUS_RegBitWrite(&EBI->WRTIMING, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable);
BUS_RegBitWrite(&EBI->WRTIMING, _EBI_WRTIMING_HALFWE_SHIFT, halfWE);
}
if ( banks & EBI_BANK1 ) {
BUS_RegBitWrite(&EBI->WRTIMING1, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable);
BUS_RegBitWrite(&EBI->WRTIMING1, _EBI_WRTIMING_HALFWE_SHIFT, halfWE);
}
if ( banks & EBI_BANK2 ) {
BUS_RegBitWrite(&EBI->WRTIMING2, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable);
BUS_RegBitWrite(&EBI->WRTIMING2, _EBI_WRTIMING_HALFWE_SHIFT, halfWE);
}
if ( banks & EBI_BANK3 ) {
BUS_RegBitWrite(&EBI->WRTIMING3, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable);
BUS_RegBitWrite(&EBI->WRTIMING3, _EBI_WRTIMING_HALFWE_SHIFT, halfWE);
}
}
/***************************************************************************//**
* @brief
* Configure timing values of write bus accesses.
*
* @param[in] banks
* A mask of memory bank(s) to configure write timing for.
*
* @param[in] setupCycles
* A number of clock cycles for address setup before WEn is asserted.
*
* @param[in] strobeCycles
* A number of cycles WEn is held active. If set to 0, 1 cycle is inserted by hardware.
*
* @param[in] holdCycles
* Number of cycles CSn is held active after WEn is deasserted.
******************************************************************************/
void EBI_BankWriteTimingSet(uint32_t banks, uint32_t setupCycles, uint32_t strobeCycles, uint32_t holdCycles)
{
uint32_t writeTiming;
/* Verify only valid banks are used.*/
EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
/* Check that timings are within limits */
EFM_ASSERT(setupCycles <= _EBI_WRTIMING_WRSETUP_MASK >> _EBI_WRTIMING_WRSETUP_SHIFT);
EFM_ASSERT(strobeCycles <= _EBI_WRTIMING_WRSTRB_MASK >> _EBI_WRTIMING_WRSTRB_SHIFT);
EFM_ASSERT(holdCycles <= _EBI_WRTIMING_WRHOLD_MASK >> _EBI_WRTIMING_WRHOLD_SHIFT);
/* Configure timing values. */
writeTiming = (setupCycles << _EBI_WRTIMING_WRSETUP_SHIFT)
| (strobeCycles << _EBI_WRTIMING_WRSTRB_SHIFT)
| (holdCycles << _EBI_WRTIMING_WRHOLD_SHIFT);
if (banks & EBI_BANK0) {
EBI->WRTIMING = (EBI->WRTIMING
& ~(_EBI_WRTIMING_WRSETUP_MASK
| _EBI_WRTIMING_WRSTRB_MASK
| _EBI_WRTIMING_WRHOLD_MASK))
| writeTiming;
}
if (banks & EBI_BANK1) {
EBI->WRTIMING1 = (EBI->WRTIMING1
& ~(_EBI_WRTIMING1_WRSETUP_MASK
| _EBI_WRTIMING1_WRSTRB_MASK
| _EBI_WRTIMING1_WRHOLD_MASK))
| writeTiming;
}
if (banks & EBI_BANK2) {
EBI->WRTIMING2 = (EBI->WRTIMING2
& ~(_EBI_WRTIMING2_WRSETUP_MASK
| _EBI_WRTIMING2_WRSTRB_MASK
| _EBI_WRTIMING2_WRHOLD_MASK))
| writeTiming;
}
if (banks & EBI_BANK3) {
EBI->WRTIMING3 = (EBI->WRTIMING3
& ~(_EBI_WRTIMING3_WRSETUP_MASK
| _EBI_WRTIMING3_WRSTRB_MASK
| _EBI_WRTIMING3_WRHOLD_MASK))
| writeTiming;
}
}
/***************************************************************************//**
* @brief
* Configure address operation parameters for a selected bank.
*
* @param[in] banks
* A mask of memory bank(s) to configure write timing for.
*
* @param[in] halfALE
* Enables or disables the half cycle ALE strobe in the last strobe cycle.
******************************************************************************/
void EBI_BankAddressTimingConfig(uint32_t banks, bool halfALE)
{
/* Verify only valid banks are used */
EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
if ( banks & EBI_BANK0 ) {
BUS_RegBitWrite(&EBI->ADDRTIMING, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE);
}
if ( banks & EBI_BANK1 ) {
BUS_RegBitWrite(&EBI->ADDRTIMING1, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE);
}
if ( banks & EBI_BANK2 ) {
BUS_RegBitWrite(&EBI->ADDRTIMING2, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE);
}
if ( banks & EBI_BANK3 ) {
BUS_RegBitWrite(&EBI->ADDRTIMING3, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE);
}
}
/***************************************************************************//**
* @brief
* Configure timing values of address latch bus accesses.
*
* @param[in] banks
* A mask of memory bank(s) to configure address timing for.
*
* @param[in] setupCycles
* Sets the number of cycles the address is held after ALE is asserted.
*
* @param[in] holdCycles
* Sets the number of cycles the address is driven onto the ADDRDAT bus before
* ALE is asserted. If set 0, 1 cycle is inserted by hardware.
******************************************************************************/
void EBI_BankAddressTimingSet(uint32_t banks, uint32_t setupCycles, uint32_t holdCycles)
{
uint32_t addressLatchTiming;
/* Verify only valid banks are used. */
EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
/* Check that timings are within limits */
EFM_ASSERT(setupCycles <= _EBI_ADDRTIMING_ADDRSETUP_MASK >> _EBI_ADDRTIMING_ADDRSETUP_SHIFT);
EFM_ASSERT(holdCycles <= _EBI_ADDRTIMING_ADDRHOLD_MASK >> _EBI_ADDRTIMING_ADDRHOLD_SHIFT);
/* Configure address latch timing values. */
addressLatchTiming = (setupCycles << _EBI_ADDRTIMING_ADDRSETUP_SHIFT)
| (holdCycles << _EBI_ADDRTIMING_ADDRHOLD_SHIFT);
if (banks & EBI_BANK0) {
EBI->ADDRTIMING = (EBI->ADDRTIMING
& ~(_EBI_ADDRTIMING_ADDRSETUP_MASK
| _EBI_ADDRTIMING_ADDRHOLD_MASK))
| addressLatchTiming;
}
if (banks & EBI_BANK1) {
EBI->ADDRTIMING1 = (EBI->ADDRTIMING1
& ~(_EBI_ADDRTIMING1_ADDRSETUP_MASK
| _EBI_ADDRTIMING1_ADDRHOLD_MASK))
| addressLatchTiming;
}
if (banks & EBI_BANK2) {
EBI->ADDRTIMING2 = (EBI->ADDRTIMING2
& ~(_EBI_ADDRTIMING2_ADDRSETUP_MASK
| _EBI_ADDRTIMING2_ADDRHOLD_MASK))
| addressLatchTiming;
}
if (banks & EBI_BANK3) {
EBI->ADDRTIMING3 = (EBI->ADDRTIMING3
& ~(_EBI_ADDRTIMING3_ADDRSETUP_MASK
| _EBI_ADDRTIMING3_ADDRHOLD_MASK))
| addressLatchTiming;
}
}
/***************************************************************************//**
* @brief
* Configure EBI pin polarity for selected bank(s) for devices with individual
* timing support.
*
* @param[in] banks
* A mask of memory bank(s) to configure polarity for.
*
* @param[in] line
* Which pin/line to configure.
*
* @param[in] polarity
* Active high, or active low.
******************************************************************************/
void EBI_BankPolaritySet(uint32_t banks, EBI_Line_TypeDef line, EBI_Polarity_TypeDef polarity)
{
uint32_t bankSet = 0;
volatile uint32_t *polRegister = 0;
/* Verify that only valid banks are used. */
EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
while (banks) {
if (banks & EBI_BANK0) {
polRegister = &EBI->POLARITY;
bankSet = EBI_BANK0;
}
if (banks & EBI_BANK1) {
polRegister = &EBI->POLARITY1;
bankSet = EBI_BANK1;
}
if (banks & EBI_BANK2) {
polRegister = &EBI->POLARITY2;
bankSet = EBI_BANK2;
}
if (banks & EBI_BANK3) {
polRegister = &EBI->POLARITY3;
bankSet = EBI_BANK3;
}
/* What line to configure. */
switch (line) {
case ebiLineARDY:
BUS_RegBitWrite(polRegister, _EBI_POLARITY_ARDYPOL_SHIFT, polarity);
break;
case ebiLineALE:
BUS_RegBitWrite(polRegister, _EBI_POLARITY_ALEPOL_SHIFT, polarity);
break;
case ebiLineWE:
BUS_RegBitWrite(polRegister, _EBI_POLARITY_WEPOL_SHIFT, polarity);
break;
case ebiLineRE:
BUS_RegBitWrite(polRegister, _EBI_POLARITY_REPOL_SHIFT, polarity);
break;
case ebiLineCS:
BUS_RegBitWrite(polRegister, _EBI_POLARITY_CSPOL_SHIFT, polarity);
break;
case ebiLineBL:
BUS_RegBitWrite(polRegister, _EBI_POLARITY_BLPOL_SHIFT, polarity);
break;
case ebiLineTFTVSync:
BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity);
break;
case ebiLineTFTHSync:
BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity);
break;
case ebiLineTFTDataEn:
BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity);
break;
case ebiLineTFTDClk:
BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity);
break;
case ebiLineTFTCS:
BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_CSPOL_SHIFT, polarity);
break;
default:
EFM_ASSERT(0);
break;
}
banks = banks & ~bankSet;
}
}
/***************************************************************************//**
* @brief
* Configure Byte Lane Enable for select banks
* timing support.
*
* @param[in] banks
* A mask of memory bank(s) to configure polarity for.
*
* @param[in] enable
* A flag
******************************************************************************/
void EBI_BankByteLaneEnable(uint32_t banks, bool enable)
{
/* Verify only valid banks are used */
EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
/* Configure byte lane support for each selected bank */
if (banks & EBI_BANK0) {
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL_SHIFT, enable);
}
if (banks & EBI_BANK1) {
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL1_SHIFT, enable);
}
if (banks & EBI_BANK2) {
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL2_SHIFT, enable);
}
if (banks & EBI_BANK3) {
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL3_SHIFT, enable);
}
}
/***************************************************************************//**
* @brief
* Configure the Alternate Address Map support.
* Enables or disables 256 MB address range for all banks.
*
* @param[in] enable
* Set or clear the address map extension.
******************************************************************************/
void EBI_AltMapEnable(bool enable)
{
BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_ALTMAP_SHIFT, enable);
}
#endif
/** @} (end addtogroup EBI) */
/** @} (end addtogroup emlib) */
#endif /* defined(EBI_COUNT) && (EBI_COUNT > 0) */