1 /***************************************************************************//**
2  * @file
3  * @brief External Bus Interface (EBI) Peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #include "em_ebi.h"
32 #if defined(EBI_COUNT) && (EBI_COUNT > 0)
33 #include "sl_assert.h"
34 #include "em_bus.h"
35 
36 /***************************************************************************//**
37  * @addtogroup ebi EBI - External Bus Interface
38  * @brief EBI External Bus Interface (EBI) Peripheral API
39  * @details
40  *  This module contains functions to control the EBI peripheral of Silicon
41  *  Labs 32-bit MCUs and SoCs. The EBI is used for accessing external parallel
42  *  devices. The devices appear as part of the internal memory map of the MCU.
43  * @{
44  ******************************************************************************/
45 
46 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
47 
48 /* The ROUTE register has been renamed in the newest platform so these register
49  * field names have been created to make it easier to work with both
50  * the new and the old names in a generic way. */
51 #if defined(_EBI_ROUTE_MASK)
52 #define _EBI_GENERIC_ALEPEN_SHIFT  _EBI_ROUTE_ALEPEN_SHIFT
53 #define _EBI_GENERIC_BLPEN_SHIFT   _EBI_ROUTE_BLPEN_SHIFT
54 #define _EBI_GENERIC_EBIPEN_SHIFT  _EBI_ROUTE_EBIPEN_SHIFT
55 #define _EBI_GENERIC_CS0PEN_SHIFT  _EBI_ROUTE_CS0PEN_SHIFT
56 #define _EBI_GENERIC_CS1PEN_SHIFT  _EBI_ROUTE_CS1PEN_SHIFT
57 #define _EBI_GENERIC_CS2PEN_SHIFT  _EBI_ROUTE_CS2PEN_SHIFT
58 #define _EBI_GENERIC_CS3PEN_SHIFT  _EBI_ROUTE_CS3PEN_SHIFT
59 #define _EBI_GENERIC_RESETVALUE    _EBI_ROUTE_RESETVALUE
60 #define EBI_GENERIC_ROUTE_REG     EBI->ROUTE
61 #define _EBI_GENERIC_ALB_MASK      _EBI_ROUTE_ALB_MASK
62 #define _EBI_GENERIC_APEN_MASK     _EBI_ROUTE_APEN_MASK
63 #define EBI_GENERIC_TFTPEN        EBI_ROUTE_TFTPEN
64 #else
65 #define _EBI_GENERIC_ALEPEN_SHIFT  _EBI_ROUTEPEN_ALEPEN_SHIFT
66 #define _EBI_GENERIC_BLPEN_SHIFT   _EBI_ROUTEPEN_BLPEN_SHIFT
67 #define _EBI_GENERIC_EBIPEN_SHIFT  _EBI_ROUTEPEN_EBIPEN_SHIFT
68 #define _EBI_GENERIC_CS0PEN_SHIFT  _EBI_ROUTEPEN_CS0PEN_SHIFT
69 #define _EBI_GENERIC_CS1PEN_SHIFT  _EBI_ROUTEPEN_CS1PEN_SHIFT
70 #define _EBI_GENERIC_CS2PEN_SHIFT  _EBI_ROUTEPEN_CS2PEN_SHIFT
71 #define _EBI_GENERIC_CS3PEN_SHIFT  _EBI_ROUTEPEN_CS3PEN_SHIFT
72 #define _EBI_GENERIC_RESETVALUE    _EBI_ROUTEPEN_RESETVALUE
73 #define EBI_GENERIC_ROUTE_REG     EBI->ROUTEPEN
74 #define _EBI_GENERIC_ALB_MASK      _EBI_ROUTEPEN_ALB_MASK
75 #define _EBI_GENERIC_NANDPEN_MASK  _EBI_ROUTEPEN_NANDPEN_MASK
76 #define _EBI_GENERIC_APEN_MASK     _EBI_ROUTEPEN_APEN_MASK
77 #define EBI_GENERIC_TFTPEN        EBI_ROUTEPEN_TFTPEN
78 #endif
79 
80 /***************************************************************************//**
81  * @brief
82  *   Perform a single-bit write operation on an EBI route register.
83  *
84  * @param[in] bit
85  *   bit Bit position to write, 0-31.
86  *
87  * @param[in] val
88  *   0 to clear bit and 1 to set bit.
89  ******************************************************************************/
EBI_RouteBitWrite(uint32_t bit,uint32_t val)90 __STATIC_INLINE void EBI_RouteBitWrite(uint32_t bit, uint32_t val)
91 {
92   BUS_RegBitWrite(&(EBI_GENERIC_ROUTE_REG), bit, val);
93 }
94 /** @endcond */
95 
96 /***************************************************************************//**
97  * @brief
98  *   Configure and enable the External Bus Interface.
99  *
100  * @param[in] ebiInit
101  *   The EBI configuration structure.
102  *
103  * @note
104  *   GPIO lines must be configured as a PUSH_PULL for the correct operation.
105  *   GPIO and EBI clocks must be enabled in the CMU.
106  ******************************************************************************/
EBI_Init(const EBI_Init_TypeDef * ebiInit)107 void EBI_Init(const EBI_Init_TypeDef *ebiInit)
108 {
109   uint32_t ctrl = EBI->CTRL;
110 
111 #if defined(_EFM32_GECKO_FAMILY)
112   /* Set polarity of address ready */
113   EBI_PolaritySet(ebiLineARDY, ebiInit->ardyPolarity);
114   /* Set polarity of address latch enable */
115   EBI_PolaritySet(ebiLineALE, ebiInit->alePolarity);
116   /* Set polarity of write enable */
117   EBI_PolaritySet(ebiLineWE, ebiInit->wePolarity);
118   /* Set polarity of read enable */
119   EBI_PolaritySet(ebiLineRE, ebiInit->rePolarity);
120   /* Set polarity of chip select lines */
121   EBI_PolaritySet(ebiLineCS, ebiInit->csPolarity);
122 #else
123   /* Enable Independent Timing for devices that support it. */
124   ctrl |= EBI_CTRL_ITS;
125 
126   /* Set the polarity of address ready. */
127   EBI_BankPolaritySet(ebiInit->banks, ebiLineARDY, ebiInit->ardyPolarity);
128   /* Set the polarity of address latch enable. */
129   EBI_BankPolaritySet(ebiInit->banks, ebiLineALE, ebiInit->alePolarity);
130   /* Set polarity of write enable */
131   EBI_BankPolaritySet(ebiInit->banks, ebiLineWE, ebiInit->wePolarity);
132   /* Set polarity of read enable */
133   EBI_BankPolaritySet(ebiInit->banks, ebiLineRE, ebiInit->rePolarity);
134   /* Set polarity of chip select lines */
135   EBI_BankPolaritySet(ebiInit->banks, ebiLineCS, ebiInit->csPolarity);
136   /* Set polarity of byte lane line */
137   EBI_BankPolaritySet(ebiInit->banks, ebiLineBL, ebiInit->blPolarity);
138 #endif
139 
140   /* Configure EBI mode and control settings.  */
141 #if defined(_EFM32_GECKO_FAMILY)
142   ctrl &= ~(_EBI_CTRL_MODE_MASK
143             | _EBI_CTRL_ARDYEN_MASK
144             | _EBI_CTRL_ARDYTODIS_MASK
145             | _EBI_CTRL_BANK0EN_MASK
146             | _EBI_CTRL_BANK1EN_MASK
147             | _EBI_CTRL_BANK2EN_MASK
148             | _EBI_CTRL_BANK3EN_MASK);
149   if ( ebiInit->enable) {
150     if ( ebiInit->banks & EBI_BANK0 ) {
151       ctrl |= EBI_CTRL_BANK0EN;
152     }
153     if ( ebiInit->banks & EBI_BANK1 ) {
154       ctrl |= EBI_CTRL_BANK1EN;
155     }
156     if ( ebiInit->banks & EBI_BANK2 ) {
157       ctrl |= EBI_CTRL_BANK2EN;
158     }
159     if ( ebiInit->banks & EBI_BANK3 ) {
160       ctrl |= EBI_CTRL_BANK3EN;
161     }
162   }
163   ctrl |= ebiInit->mode;
164   ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDYEN_SHIFT);
165   ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTODIS_SHIFT);
166 #else
167   if (ebiInit->banks & EBI_BANK0) {
168     ctrl &= ~(_EBI_CTRL_MODE_MASK
169               | _EBI_CTRL_ARDYEN_MASK
170               | _EBI_CTRL_ARDYTODIS_MASK
171               | _EBI_CTRL_BL_MASK
172               | _EBI_CTRL_NOIDLE_MASK
173               | _EBI_CTRL_BANK0EN_MASK);
174     ctrl |= (ebiInit->mode << _EBI_CTRL_MODE_SHIFT);
175     ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDYEN_SHIFT);
176     ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTODIS_SHIFT);
177     ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL_SHIFT);
178     ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE_SHIFT);
179     if ( ebiInit->enable) {
180       ctrl |= EBI_CTRL_BANK0EN;
181     }
182   }
183   if (ebiInit->banks & EBI_BANK1) {
184     ctrl &= ~(_EBI_CTRL_BL1_MASK
185               | _EBI_CTRL_MODE1_MASK
186               | _EBI_CTRL_ARDY1EN_MASK
187               | _EBI_CTRL_ARDYTO1DIS_MASK
188               | _EBI_CTRL_NOIDLE1_MASK
189               | _EBI_CTRL_BANK1EN_MASK);
190     ctrl |= (ebiInit->mode << _EBI_CTRL_MODE1_SHIFT);
191     ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY1EN_SHIFT);
192     ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO1DIS_SHIFT);
193     ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL1_SHIFT);
194     ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE1_SHIFT);
195     if ( ebiInit->enable) {
196       ctrl |= EBI_CTRL_BANK1EN;
197     }
198   }
199   if (ebiInit->banks & EBI_BANK2) {
200     ctrl &= ~(_EBI_CTRL_BL2_MASK
201               | _EBI_CTRL_MODE2_MASK
202               | _EBI_CTRL_ARDY2EN_MASK
203               | _EBI_CTRL_ARDYTO2DIS_MASK
204               | _EBI_CTRL_NOIDLE2_MASK
205               | _EBI_CTRL_BANK2EN_MASK);
206     ctrl |= (ebiInit->mode << _EBI_CTRL_MODE2_SHIFT);
207     ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY2EN_SHIFT);
208     ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO2DIS_SHIFT);
209     ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL2_SHIFT);
210     ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE2_SHIFT);
211     if ( ebiInit->enable) {
212       ctrl |= EBI_CTRL_BANK2EN;
213     }
214   }
215   if (ebiInit->banks & EBI_BANK3) {
216     ctrl &= ~(_EBI_CTRL_BL3_MASK
217               | _EBI_CTRL_MODE3_MASK
218               | _EBI_CTRL_ARDY3EN_MASK
219               | _EBI_CTRL_ARDYTO3DIS_MASK
220               | _EBI_CTRL_NOIDLE3_MASK
221               | _EBI_CTRL_BANK3EN_MASK);
222     ctrl |= (ebiInit->mode << _EBI_CTRL_MODE3_SHIFT);
223     ctrl |= (ebiInit->ardyEnable << _EBI_CTRL_ARDY3EN_SHIFT);
224     ctrl |= (ebiInit->ardyDisableTimeout << _EBI_CTRL_ARDYTO3DIS_SHIFT);
225     ctrl |= (ebiInit->blEnable << _EBI_CTRL_BL3_SHIFT);
226     ctrl |= (ebiInit->noIdle << _EBI_CTRL_NOIDLE3_SHIFT);
227     if ( ebiInit->enable) {
228       ctrl |= EBI_CTRL_BANK3EN;
229     }
230   }
231 #endif
232 
233   /* Configure timing. */
234 #if defined(_EFM32_GECKO_FAMILY)
235   EBI_ReadTimingSet(ebiInit->readSetupCycles,
236                     ebiInit->readStrobeCycles,
237                     ebiInit->readHoldCycles);
238   EBI_WriteTimingSet(ebiInit->writeSetupCycles,
239                      ebiInit->writeStrobeCycles,
240                      ebiInit->writeHoldCycles);
241   EBI_AddressTimingSet(ebiInit->addrSetupCycles,
242                        ebiInit->addrHoldCycles);
243 #else
244   EBI_BankReadTimingSet(ebiInit->banks,
245                         ebiInit->readSetupCycles,
246                         ebiInit->readStrobeCycles,
247                         ebiInit->readHoldCycles);
248   EBI_BankReadTimingConfig(ebiInit->banks,
249                            ebiInit->readPageMode,
250                            ebiInit->readPrefetch,
251                            ebiInit->readHalfRE);
252   EBI_BankWriteTimingSet(ebiInit->banks,
253                          ebiInit->writeSetupCycles,
254                          ebiInit->writeStrobeCycles,
255                          ebiInit->writeHoldCycles);
256   EBI_BankWriteTimingConfig(ebiInit->banks,
257                             ebiInit->writeBufferDisable,
258                             ebiInit->writeHalfWE);
259   EBI_BankAddressTimingSet(ebiInit->banks,
260                            ebiInit->addrSetupCycles,
261                            ebiInit->addrHoldCycles);
262   EBI_BankAddressTimingConfig(ebiInit->banks,
263                               ebiInit->addrHalfALE);
264 #endif
265 
266   /* Activate the new configuration. */
267   EBI->CTRL = ctrl;
268 
269   /* Configure Address Latch Enable. */
270   switch (ebiInit->mode) {
271     case ebiModeD16A16ALE:
272     case ebiModeD8A24ALE:
273       /* Address Latch Enable. */
274       EBI_RouteBitWrite(_EBI_GENERIC_ALEPEN_SHIFT, 1);
275       break;
276 #if defined(EBI_CTRL_MODE_D16)
277     case ebiModeD16:
278 #endif
279     case ebiModeD8A8:
280       /* Make sure that Address Latch is disabled. */
281       EBI_RouteBitWrite(_EBI_GENERIC_ALEPEN_SHIFT, 0);
282       break;
283   }
284 
285 #if !defined(_EFM32_GECKO_FAMILY)
286   /* Limit the pin enable. */
287   EBI_GENERIC_ROUTE_REG = (EBI_GENERIC_ROUTE_REG & ~_EBI_GENERIC_ALB_MASK) | ebiInit->aLow;
288   EBI_GENERIC_ROUTE_REG = (EBI_GENERIC_ROUTE_REG & ~_EBI_GENERIC_APEN_MASK) | ebiInit->aHigh;
289 #if defined(_EBI_ROUTE_LOCATION_MASK)
290   /* Location. */
291   EBI->ROUTE = (EBI->ROUTE & ~_EBI_ROUTE_LOCATION_MASK) | ebiInit->location;
292 #endif
293 
294   /* Enable the EBI BL pin if necessary. */
295   if (ctrl & (_EBI_CTRL_BL_MASK | _EBI_CTRL_BL1_MASK | _EBI_CTRL_BL2_MASK | _EBI_CTRL_BL3_MASK)) {
296     EBI_RouteBitWrite(_EBI_GENERIC_BLPEN_SHIFT, ebiInit->blEnable);
297   }
298 #endif
299 
300   /* Enable EBI pins EBI_WEn and EBI_REn. */
301   EBI_RouteBitWrite(_EBI_GENERIC_EBIPEN_SHIFT, 1);
302 
303   /* Enable chip select lines. */
304   EBI_ChipSelectEnable(ebiInit->csLines, true);
305 }
306 
307 /***************************************************************************//**
308  * @brief
309  *   Disable External Bus Interface
310  ******************************************************************************/
EBI_Disable(void)311 void EBI_Disable(void)
312 {
313   /* Disable pins */
314   EBI_GENERIC_ROUTE_REG = _EBI_GENERIC_RESETVALUE;
315   /* Disable banks */
316   EBI->CTRL = _EBI_CTRL_RESETVALUE;
317 }
318 
319 /***************************************************************************//**
320  * @brief
321  *   Enable or disable EBI Bank.
322  *
323  * @param[in] banks
324  *   Banks to reconfigure, mask of EBI_BANK<n> flags.
325  *
326  * @param[in] enable
327  *   True to enable, false to disable.
328  ******************************************************************************/
EBI_BankEnable(uint32_t banks,bool enable)329 void EBI_BankEnable(uint32_t banks, bool enable)
330 {
331   if (banks & EBI_BANK0) {
332     BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK0EN_SHIFT, enable);
333   }
334   if (banks & EBI_BANK1) {
335     BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK1EN_SHIFT, enable);
336   }
337   if (banks & EBI_BANK2) {
338     BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK2EN_SHIFT, enable);
339   }
340   if (banks & EBI_BANK3) {
341     BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BANK3EN_SHIFT, enable);
342   }
343 }
344 
345 /***************************************************************************//**
346  * @brief
347  *   Return the base address of the EBI bank.
348  *
349  * @param[in] bank
350  *   A bank to return the start address for.
351  *
352  * @return
353  *   an absolute address of the bank.
354  ******************************************************************************/
EBI_BankAddress(uint32_t bank)355 uint32_t EBI_BankAddress(uint32_t bank)
356 {
357 #if defined (EBI_CTRL_ALTMAP)
358   if (EBI->CTRL & EBI_CTRL_ALTMAP) {
359     switch (bank) {
360       case EBI_BANK0:
361         return EBI_MEM_BASE;
362 
363       case EBI_BANK1:
364         return EBI_MEM_BASE + 0x10000000UL;
365 
366       case EBI_BANK2:
367         return EBI_MEM_BASE + 0x20000000UL;
368 
369       case EBI_BANK3:
370         return EBI_MEM_BASE + 0x30000000UL;
371 
372       default:
373         EFM_ASSERT(0);
374         break;
375     }
376   }
377 #endif
378   switch (bank) {
379     case EBI_BANK0:
380       return EBI_MEM_BASE;
381 
382     case EBI_BANK1:
383       return EBI_MEM_BASE + 0x04000000UL;
384 
385     case EBI_BANK2:
386       return EBI_MEM_BASE + 0x08000000UL;
387 
388     case EBI_BANK3:
389       return EBI_MEM_BASE + 0x0C000000UL;
390 
391     default:
392       EFM_ASSERT(0);
393       break;
394   }
395   return 0;
396 }
397 
398 #if defined(_EBI_NANDCTRL_MASK)
399 /***************************************************************************//**
400  * @brief
401  *   Enable or disable EBI NAND Flash Support
402  *
403  * @param[in] banks
404  *   Banks to reconfigure, mask of EBI_BANK<n> flags.
405  *
406  * @param[in] enable
407  *   True to enable, false to disable.
408  ******************************************************************************/
EBI_NANDFlashEnable(uint32_t banks,bool enable)409 void EBI_NANDFlashEnable(uint32_t banks, bool enable)
410 {
411   if (banks & EBI_BANK0) {
412     BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_BANKSEL_SHIFT, _EBI_NANDCTRL_BANKSEL_BANK0);
413   }
414   if (banks & EBI_BANK1) {
415     BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_BANKSEL_SHIFT, _EBI_NANDCTRL_BANKSEL_BANK1);
416   }
417   if (banks & EBI_BANK2) {
418     BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_BANKSEL_SHIFT, _EBI_NANDCTRL_BANKSEL_BANK2);
419   }
420   if (banks & EBI_BANK3) {
421     BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_BANKSEL_SHIFT, _EBI_NANDCTRL_BANKSEL_BANK3);
422   }
423   BUS_RegBitWrite(&(EBI->NANDCTRL), _EBI_NANDCTRL_EN_SHIFT, enable);
424 }
425 #endif
426 
427 /***************************************************************************//**
428  * @brief
429  *   Enable or disable EBI Chip Select.
430  *
431  * @param[in] cs
432  *   ChipSelect lines to reconfigure, mask of EBI_CS<n> flags.
433  *
434  * @param[in] enable
435  *   True to enable, false to disable.
436  ******************************************************************************/
EBI_ChipSelectEnable(uint32_t cs,bool enable)437 void EBI_ChipSelectEnable(uint32_t cs, bool enable)
438 {
439   if (cs & EBI_CS0) {
440     EBI_RouteBitWrite(_EBI_GENERIC_CS0PEN_SHIFT, enable);
441   }
442   if (cs & EBI_CS1) {
443     EBI_RouteBitWrite(_EBI_GENERIC_CS1PEN_SHIFT, enable);
444   }
445   if (cs & EBI_CS2) {
446     EBI_RouteBitWrite(_EBI_GENERIC_CS2PEN_SHIFT, enable);
447   }
448   if (cs & EBI_CS3) {
449     EBI_RouteBitWrite(_EBI_GENERIC_CS3PEN_SHIFT, enable);
450   }
451 }
452 
453 /***************************************************************************//**
454  * @brief
455  *   Configure EBI pin polarity.
456  *
457  * @param[in] line
458  *   Which pin/line to configure.
459  *
460  * @param[in] polarity
461  *   Active high or active low.
462  ******************************************************************************/
EBI_PolaritySet(EBI_Line_TypeDef line,EBI_Polarity_TypeDef polarity)463 void EBI_PolaritySet(EBI_Line_TypeDef line, EBI_Polarity_TypeDef polarity)
464 {
465   switch (line) {
466     case ebiLineARDY:
467       BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_ARDYPOL_SHIFT, polarity);
468       break;
469     case ebiLineALE:
470       BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_ALEPOL_SHIFT, polarity);
471       break;
472     case ebiLineWE:
473       BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_WEPOL_SHIFT, polarity);
474       break;
475     case ebiLineRE:
476       BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_REPOL_SHIFT, polarity);
477       break;
478     case ebiLineCS:
479       BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_CSPOL_SHIFT, polarity);
480       break;
481 #if defined(_EBI_POLARITY_BLPOL_MASK)
482     case ebiLineBL:
483       BUS_RegBitWrite(&EBI->POLARITY, _EBI_POLARITY_BLPOL_SHIFT, polarity);
484       break;
485 #endif
486 #if defined (_EBI_TFTPOLARITY_MASK)
487     case ebiLineTFTVSync:
488       BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity);
489       break;
490     case ebiLineTFTHSync:
491       BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity);
492       break;
493     case ebiLineTFTDataEn:
494       BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity);
495       break;
496     case ebiLineTFTDClk:
497       BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity);
498       break;
499     case ebiLineTFTCS:
500       BUS_RegBitWrite(&EBI->TFTPOLARITY, _EBI_TFTPOLARITY_CSPOL_SHIFT, polarity);
501       break;
502 #endif
503     default:
504       EFM_ASSERT(0);
505       break;
506   }
507 }
508 
509 /***************************************************************************//**
510  * @brief
511  *   Configure timing values of read bus accesses.
512  *
513  * @param[in] setupCycles
514  *   A number of clock cycles for the address setup before REn is asserted.
515  *
516  * @param[in] strobeCycles
517  *   The number of cycles the REn is held active. After the specified number of
518  *   cycles, data is read. If set to 0, 1 cycle is inserted by hardware.
519  *
520  * @param[in] holdCycles
521  *   The number of cycles CSn is held active after the REn is deasserted.
522  ******************************************************************************/
EBI_ReadTimingSet(uint32_t setupCycles,uint32_t strobeCycles,uint32_t holdCycles)523 void EBI_ReadTimingSet(uint32_t setupCycles, uint32_t strobeCycles, uint32_t holdCycles)
524 {
525   uint32_t readTiming;
526 
527   /* Check that timings are within limits */
528   EFM_ASSERT(setupCycles <= _EBI_RDTIMING_RDSETUP_MASK >> _EBI_RDTIMING_RDSETUP_SHIFT);
529   EFM_ASSERT(strobeCycles <= _EBI_RDTIMING_RDSTRB_MASK >> _EBI_RDTIMING_RDSTRB_SHIFT);
530   EFM_ASSERT(holdCycles <= _EBI_RDTIMING_RDHOLD_MASK >> _EBI_RDTIMING_RDHOLD_SHIFT);
531 
532   /* Configure timing values */
533   readTiming = (setupCycles << _EBI_RDTIMING_RDSETUP_SHIFT)
534                | (strobeCycles << _EBI_RDTIMING_RDSTRB_SHIFT)
535                | (holdCycles << _EBI_RDTIMING_RDHOLD_SHIFT);
536 
537   EBI->RDTIMING = (EBI->RDTIMING
538                    & ~(_EBI_RDTIMING_RDSETUP_MASK
539                        | _EBI_RDTIMING_RDSTRB_MASK
540                        | _EBI_RDTIMING_RDHOLD_MASK))
541                   | readTiming;
542 }
543 
544 /***************************************************************************//**
545  * @brief
546  *   Configure timing values of write bus accesses.
547  *
548  * @param[in] setupCycles
549  *   A number of clock cycles for the address setup before WEn is asserted.
550  *
551  * @param[in] strobeCycles
552  *   A number of cycles WEn is held active. If set to 0, 1 cycle is inserted by hardware.
553  *
554  * @param[in] holdCycles
555  *   A number of cycles CSn is held active after the WEn is deasserted.
556  ******************************************************************************/
EBI_WriteTimingSet(uint32_t setupCycles,uint32_t strobeCycles,uint32_t holdCycles)557 void EBI_WriteTimingSet(uint32_t setupCycles, uint32_t strobeCycles, uint32_t holdCycles)
558 {
559   uint32_t writeTiming;
560 
561   /* Check that timings are within limits */
562   EFM_ASSERT(setupCycles <= _EBI_WRTIMING_WRSETUP_MASK >> _EBI_WRTIMING_WRSETUP_SHIFT);
563   EFM_ASSERT(strobeCycles <= _EBI_WRTIMING_WRSTRB_MASK >> _EBI_WRTIMING_WRSTRB_SHIFT);
564   EFM_ASSERT(holdCycles <= _EBI_WRTIMING_WRHOLD_MASK >> _EBI_WRTIMING_WRHOLD_SHIFT);
565 
566   /* Configure timing values. */
567   writeTiming = (setupCycles << _EBI_WRTIMING_WRSETUP_SHIFT)
568                 | (strobeCycles << _EBI_WRTIMING_WRSTRB_SHIFT)
569                 | (holdCycles << _EBI_WRTIMING_WRHOLD_SHIFT);
570 
571   EBI->WRTIMING = (EBI->WRTIMING
572                    & ~(_EBI_WRTIMING_WRSETUP_MASK
573                        | _EBI_WRTIMING_WRSTRB_MASK
574                        | _EBI_WRTIMING_WRHOLD_MASK))
575                   | writeTiming;
576 }
577 
578 /***************************************************************************//**
579  * @brief
580  *   Configure timing values of address latch bus accesses.
581  *
582  * @param[in] setupCycles
583  *   Sets the number of cycles the address is held after ALE is asserted.
584  *
585  * @param[in] holdCycles
586  *   Sets the number of cycles the address is driven onto the ADDRDAT bus before
587  *   ALE is asserted. If set 0, 1 cycle is inserted by hardware.
588  ******************************************************************************/
EBI_AddressTimingSet(uint32_t setupCycles,uint32_t holdCycles)589 void EBI_AddressTimingSet(uint32_t setupCycles, uint32_t holdCycles)
590 {
591   uint32_t addressLatchTiming;
592 
593   /* Check that timings are within limits */
594   EFM_ASSERT(setupCycles <= _EBI_ADDRTIMING_ADDRSETUP_MASK >> _EBI_ADDRTIMING_ADDRSETUP_SHIFT);
595   EFM_ASSERT(holdCycles <= _EBI_ADDRTIMING_ADDRHOLD_MASK >> _EBI_ADDRTIMING_ADDRHOLD_SHIFT);
596 
597   /* Configure address latch timing values. */
598   addressLatchTiming = (setupCycles << _EBI_ADDRTIMING_ADDRSETUP_SHIFT)
599                        | (holdCycles << _EBI_ADDRTIMING_ADDRHOLD_SHIFT);
600 
601   EBI->ADDRTIMING = (EBI->ADDRTIMING
602                      & ~(_EBI_ADDRTIMING_ADDRSETUP_MASK
603                          | _EBI_ADDRTIMING_ADDRHOLD_MASK))
604                     | addressLatchTiming;
605 }
606 
607 #if defined(_EBI_TFTCTRL_MASK)
608 /***************************************************************************//**
609  * @brief
610  *   Configure and initialize TFT Direct Drive.
611  *
612  * @param[in] ebiTFTInit
613  *   The TFT Initialization structure.
614  ******************************************************************************/
EBI_TFTInit(const EBI_TFTInit_TypeDef * ebiTFTInit)615 void EBI_TFTInit(const EBI_TFTInit_TypeDef *ebiTFTInit)
616 {
617   uint32_t ctrl;
618 
619   /* Configure the base address for the frame buffer offset to the EBI bank. */
620   EBI_TFTFrameBaseSet(ebiTFTInit->addressOffset);
621 
622   /* Configure the display size and porch areas. */
623   EBI_TFTSizeSet(ebiTFTInit->hsize,
624                  ebiTFTInit->vsize);
625   EBI_TFTHPorchSet(ebiTFTInit->hPorchFront,
626                    ebiTFTInit->hPorchBack,
627                    ebiTFTInit->hPulseWidth);
628   EBI_TFTVPorchSet(ebiTFTInit->vPorchFront,
629                    ebiTFTInit->vPorchBack,
630                    ebiTFTInit->vPulseWidth);
631 
632   /* Configure timing settings. */
633   EBI_TFTTimingSet(ebiTFTInit->dclkPeriod,
634                    ebiTFTInit->startPosition,
635                    ebiTFTInit->setupCycles,
636                    ebiTFTInit->holdCycles);
637 
638   /* Configure line polarity settings. */
639   EBI_PolaritySet(ebiLineTFTCS, ebiTFTInit->csPolarity);
640   EBI_PolaritySet(ebiLineTFTDClk, ebiTFTInit->dclkPolarity);
641   EBI_PolaritySet(ebiLineTFTDataEn, ebiTFTInit->dataenPolarity);
642   EBI_PolaritySet(ebiLineTFTVSync, ebiTFTInit->vsyncPolarity);
643   EBI_PolaritySet(ebiLineTFTHSync, ebiTFTInit->hsyncPolarity);
644 
645   /* Main control, EBI bank select, mask and blending configuration. */
646   ctrl = (uint32_t)ebiTFTInit->bank
647          | (uint32_t)ebiTFTInit->width
648          | (uint32_t)ebiTFTInit->colSrc
649          | (uint32_t)ebiTFTInit->interleave
650          | (uint32_t)ebiTFTInit->fbTrigger
651          | (uint32_t)(ebiTFTInit->shiftDClk == true
652                       ? (1 << _EBI_TFTCTRL_SHIFTDCLKEN_SHIFT) : 0)
653          | (uint32_t)ebiTFTInit->maskBlend
654          | (uint32_t)ebiTFTInit->driveMode;
655 
656   EBI->TFTCTRL = ctrl;
657 
658   /* Enable TFT pins. */
659   if (ebiTFTInit->driveMode != ebiTFTDDModeDisabled) {
660     EBI_GENERIC_ROUTE_REG |= EBI_GENERIC_TFTPEN;
661   }
662 }
663 
664 /***************************************************************************//**
665  * @brief
666  *   Configure and initialize TFT size settings.
667  *
668  * @param[in] horizontal
669  *   TFT display horizontal size in pixels.
670  * @param[in] vertical
671  *   TFT display vertical size in pixels.
672  ******************************************************************************/
EBI_TFTSizeSet(uint32_t horizontal,uint32_t vertical)673 void EBI_TFTSizeSet(uint32_t horizontal, uint32_t vertical)
674 {
675   EFM_ASSERT((horizontal - 1) <= _EBI_TFTSIZE_HSZ_MASK >> _EBI_TFTSIZE_HSZ_SHIFT);
676   EFM_ASSERT((vertical - 1) <= _EBI_TFTSIZE_VSZ_MASK >> _EBI_TFTSIZE_VSZ_SHIFT);
677 
678   EBI->TFTSIZE = ((horizontal - 1) << _EBI_TFTSIZE_HSZ_SHIFT)
679                  | ((vertical - 1) << _EBI_TFTSIZE_VSZ_SHIFT);
680 }
681 
682 /***************************************************************************//**
683  * @brief
684  *   Configure and initialize Horizontal Porch Settings.
685  *
686  * @param[in] front
687  *   Horizontal front porch size in pixels.
688  * @param[in] back
689  *   Horizontal back porch size in pixels.
690  * @param[in] pulseWidth
691  *   Horizontal synchronization pulse width. Set to required -1.
692  ******************************************************************************/
EBI_TFTHPorchSet(uint32_t front,uint32_t back,uint32_t pulseWidth)693 void EBI_TFTHPorchSet(uint32_t front, uint32_t back, uint32_t pulseWidth)
694 {
695   EFM_ASSERT(front <= _EBI_TFTHPORCH_HFPORCH_MASK >> _EBI_TFTHPORCH_HFPORCH_SHIFT);
696   EFM_ASSERT(back <= _EBI_TFTHPORCH_HBPORCH_MASK >> _EBI_TFTHPORCH_HBPORCH_SHIFT);
697   EFM_ASSERT((pulseWidth - 1) <= _EBI_TFTHPORCH_HSYNC_MASK >> _EBI_TFTHPORCH_HSYNC_SHIFT);
698 
699   EBI->TFTHPORCH = (front << _EBI_TFTHPORCH_HFPORCH_SHIFT)
700                    | (back << _EBI_TFTHPORCH_HBPORCH_SHIFT)
701                    | ((pulseWidth - 1) << _EBI_TFTHPORCH_HSYNC_SHIFT);
702 }
703 
704 /***************************************************************************//**
705  * @brief
706  *   Configure Vertical Porch Settings.
707  *
708  * @param[in] front
709  *   Vertical front porch size in pixels.
710  * @param[in] back
711  *   Vertical back porch size in pixels.
712  * @param[in] pulseWidth
713  *   Vertical synchronization pulse width. Set to required -1.
714  ******************************************************************************/
EBI_TFTVPorchSet(uint32_t front,uint32_t back,uint32_t pulseWidth)715 void EBI_TFTVPorchSet(uint32_t front, uint32_t back, uint32_t pulseWidth)
716 {
717   EFM_ASSERT(front <= _EBI_TFTVPORCH_VFPORCH_MASK >> _EBI_TFTVPORCH_VFPORCH_SHIFT);
718   EFM_ASSERT(back <= _EBI_TFTVPORCH_VBPORCH_MASK >> _EBI_TFTVPORCH_VBPORCH_SHIFT);
719   EFM_ASSERT((pulseWidth - 1) <= _EBI_TFTVPORCH_VSYNC_MASK >> _EBI_TFTVPORCH_VSYNC_SHIFT);
720 
721   EBI->TFTVPORCH = (front << _EBI_TFTVPORCH_VFPORCH_SHIFT)
722                    | (back << _EBI_TFTVPORCH_VBPORCH_SHIFT)
723                    | ((pulseWidth - 1) << _EBI_TFTVPORCH_VSYNC_SHIFT);
724 }
725 
726 /***************************************************************************//**
727  * @brief
728  *   Configure TFT Direct Drive Timing Settings.
729  *
730  * @param[in] dclkPeriod
731  *   DCLK period in internal cycles.
732  *
733  * @param[in] start
734  *   A starting position of the external direct drive, relative to the DCLK inactive edge.
735  *
736  * @param[in] setup
737  *   A number of cycles that RGB data is driven before the active edge of DCLK.
738  *
739  * @param[in] hold
740  *   A number of cycles that RGB data is held after the active edge of DCLK.
741  ******************************************************************************/
EBI_TFTTimingSet(uint32_t dclkPeriod,uint32_t start,uint32_t setup,uint32_t hold)742 void EBI_TFTTimingSet(uint32_t dclkPeriod, uint32_t start, uint32_t setup, uint32_t hold)
743 {
744   /* Check that timings are within limits */
745   EFM_ASSERT(dclkPeriod <= _EBI_TFTTIMING_DCLKPERIOD_MASK >> _EBI_TFTTIMING_DCLKPERIOD_SHIFT);
746   EFM_ASSERT(start <= _EBI_TFTTIMING_TFTSTART_MASK >> _EBI_TFTTIMING_TFTSTART_SHIFT);
747   EFM_ASSERT(setup <= _EBI_TFTTIMING_TFTSETUP_MASK >> _EBI_TFTTIMING_TFTSETUP_SHIFT);
748   EFM_ASSERT(hold <= _EBI_TFTTIMING_TFTHOLD_MASK >> _EBI_TFTTIMING_TFTHOLD_SHIFT);
749 
750   EBI->TFTTIMING = (dclkPeriod << _EBI_TFTTIMING_DCLKPERIOD_SHIFT)
751                    | (start << _EBI_TFTTIMING_TFTSTART_SHIFT)
752                    | (setup << _EBI_TFTTIMING_TFTSETUP_SHIFT)
753                    | (hold << _EBI_TFTTIMING_TFTHOLD_SHIFT);
754 }
755 #endif
756 
757 #if !defined(_EFM32_GECKO_FAMILY)
758 /***************************************************************************//**
759  * @brief
760  *   Configure read operation parameters for a selected bank.
761  *
762  * @param[in] banks
763  *   A mask of memory bank(s) to configure write timing for.
764  *
765  * @param[in] pageMode
766  *   Enables or disables the half cycle WE strobe in the last strobe cycle.
767  *
768  * @param[in] prefetch
769  *   Enables or disables the half cycle WE strobe in the last strobe cycle.
770  *
771  * @param[in] halfRE
772  *   Enables or disables the half cycle WE strobe in the last strobe cycle.
773  ******************************************************************************/
EBI_BankReadTimingConfig(uint32_t banks,bool pageMode,bool prefetch,bool halfRE)774 void EBI_BankReadTimingConfig(uint32_t banks, bool pageMode, bool prefetch, bool halfRE)
775 {
776   /* Verify only valid banks are used */
777   EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
778 
779   /* Configure read operation parameters. */
780   if ( banks & EBI_BANK0 ) {
781     BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode);
782     BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch);
783     BUS_RegBitWrite(&EBI->RDTIMING, _EBI_RDTIMING_HALFRE_SHIFT, halfRE);
784   }
785   if ( banks & EBI_BANK1 ) {
786     BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode);
787     BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch);
788     BUS_RegBitWrite(&EBI->RDTIMING1, _EBI_RDTIMING_HALFRE_SHIFT, halfRE);
789   }
790   if ( banks & EBI_BANK2 ) {
791     BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode);
792     BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch);
793     BUS_RegBitWrite(&EBI->RDTIMING2, _EBI_RDTIMING_HALFRE_SHIFT, halfRE);
794   }
795   if ( banks & EBI_BANK3 ) {
796     BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_PAGEMODE_SHIFT, pageMode);
797     BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_PREFETCH_SHIFT, prefetch);
798     BUS_RegBitWrite(&EBI->RDTIMING3, _EBI_RDTIMING_HALFRE_SHIFT, halfRE);
799   }
800 }
801 
802 /***************************************************************************//**
803  * @brief
804  *   Configure timing values of read bus accesses.
805  *
806  * @param[in] banks
807  *   A mask of memory bank(s) to configure timing for.
808  *
809  * @param[in] setupCycles
810  *   A number of clock cycles for address setup before REn is asserted.
811  *
812  * @param[in] strobeCycles
813  *   The number of cycles the REn is held active. After the specified number of
814  *   cycles, data is read. If set to 0, 1 cycle is inserted by hardware.
815  *
816  * @param[in] holdCycles
817  *   The number of cycles CSn is held active after the REn is deasserted.
818  ******************************************************************************/
EBI_BankReadTimingSet(uint32_t banks,uint32_t setupCycles,uint32_t strobeCycles,uint32_t holdCycles)819 void EBI_BankReadTimingSet(uint32_t banks, uint32_t setupCycles, uint32_t strobeCycles, uint32_t holdCycles)
820 {
821   uint32_t readTiming;
822 
823   /* Verify only valid banks are used. */
824   EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
825 
826   /* Check that timings are within limits */
827   EFM_ASSERT(setupCycles <= _EBI_RDTIMING_RDSETUP_MASK >> _EBI_RDTIMING_RDSETUP_SHIFT);
828   EFM_ASSERT(strobeCycles <= _EBI_RDTIMING_RDSTRB_MASK >> _EBI_RDTIMING_RDSTRB_SHIFT);
829   EFM_ASSERT(holdCycles <= _EBI_RDTIMING_RDHOLD_MASK >> _EBI_RDTIMING_RDHOLD_SHIFT);
830 
831   /* Configure timing values. */
832   readTiming = (setupCycles << _EBI_RDTIMING_RDSETUP_SHIFT)
833                | (strobeCycles << _EBI_RDTIMING_RDSTRB_SHIFT)
834                | (holdCycles << _EBI_RDTIMING_RDHOLD_SHIFT);
835 
836   if (banks & EBI_BANK0) {
837     EBI->RDTIMING = (EBI->RDTIMING
838                      & ~(_EBI_RDTIMING_RDSETUP_MASK
839                          | _EBI_RDTIMING_RDSTRB_MASK
840                          | _EBI_RDTIMING_RDHOLD_MASK))
841                     | readTiming;
842   }
843   if (banks & EBI_BANK1) {
844     EBI->RDTIMING1 = (EBI->RDTIMING1
845                       & ~(_EBI_RDTIMING1_RDSETUP_MASK
846                           | _EBI_RDTIMING1_RDSTRB_MASK
847                           | _EBI_RDTIMING1_RDHOLD_MASK))
848                      | readTiming;
849   }
850   if (banks & EBI_BANK2) {
851     EBI->RDTIMING2 = (EBI->RDTIMING2
852                       & ~(_EBI_RDTIMING2_RDSETUP_MASK
853                           | _EBI_RDTIMING2_RDSTRB_MASK
854                           | _EBI_RDTIMING2_RDHOLD_MASK))
855                      | readTiming;
856   }
857   if (banks & EBI_BANK3) {
858     EBI->RDTIMING3 = (EBI->RDTIMING3
859                       & ~(_EBI_RDTIMING3_RDSETUP_MASK
860                           | _EBI_RDTIMING3_RDSTRB_MASK
861                           | _EBI_RDTIMING3_RDHOLD_MASK))
862                      | readTiming;
863   }
864 }
865 
866 /***************************************************************************//**
867  * @brief
868  *   Configure write operation parameters for a selected bank.
869  *
870  * @param[in] banks
871  *   A mask of memory bank(s) to configure write timing for.
872  *
873  * @param[in] writeBufDisable
874  *   If true, disable the write buffer.
875  *
876  * @param[in] halfWE
877  *   Enables or disables half cycle WE strobe in the last strobe cycle.
878  ******************************************************************************/
EBI_BankWriteTimingConfig(uint32_t banks,bool writeBufDisable,bool halfWE)879 void EBI_BankWriteTimingConfig(uint32_t banks, bool writeBufDisable, bool halfWE)
880 {
881   /* Verify only valid banks are used. */
882   EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
883 
884   /* Configure write operation parameters. */
885   if ( banks & EBI_BANK0 ) {
886     BUS_RegBitWrite(&EBI->WRTIMING, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable);
887     BUS_RegBitWrite(&EBI->WRTIMING, _EBI_WRTIMING_HALFWE_SHIFT, halfWE);
888   }
889   if ( banks & EBI_BANK1 ) {
890     BUS_RegBitWrite(&EBI->WRTIMING1, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable);
891     BUS_RegBitWrite(&EBI->WRTIMING1, _EBI_WRTIMING_HALFWE_SHIFT, halfWE);
892   }
893   if ( banks & EBI_BANK2 ) {
894     BUS_RegBitWrite(&EBI->WRTIMING2, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable);
895     BUS_RegBitWrite(&EBI->WRTIMING2, _EBI_WRTIMING_HALFWE_SHIFT, halfWE);
896   }
897   if ( banks & EBI_BANK3 ) {
898     BUS_RegBitWrite(&EBI->WRTIMING3, _EBI_WRTIMING_WBUFDIS_SHIFT, writeBufDisable);
899     BUS_RegBitWrite(&EBI->WRTIMING3, _EBI_WRTIMING_HALFWE_SHIFT, halfWE);
900   }
901 }
902 
903 /***************************************************************************//**
904  * @brief
905  *   Configure timing values of write bus accesses.
906  *
907  * @param[in] banks
908  *   A mask of memory bank(s) to configure write timing for.
909  *
910  * @param[in] setupCycles
911  *   A number of clock cycles for address setup before WEn is asserted.
912  *
913  * @param[in] strobeCycles
914  *   A number of cycles WEn is held active. If set to 0, 1 cycle is inserted by hardware.
915  *
916  * @param[in] holdCycles
917  *   Number of cycles CSn is held active after  WEn is deasserted.
918  ******************************************************************************/
EBI_BankWriteTimingSet(uint32_t banks,uint32_t setupCycles,uint32_t strobeCycles,uint32_t holdCycles)919 void EBI_BankWriteTimingSet(uint32_t banks, uint32_t setupCycles, uint32_t strobeCycles, uint32_t holdCycles)
920 {
921   uint32_t writeTiming;
922 
923   /* Verify only valid banks are used.*/
924   EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
925 
926   /* Check that timings are within limits */
927   EFM_ASSERT(setupCycles <= _EBI_WRTIMING_WRSETUP_MASK >> _EBI_WRTIMING_WRSETUP_SHIFT);
928   EFM_ASSERT(strobeCycles <= _EBI_WRTIMING_WRSTRB_MASK >> _EBI_WRTIMING_WRSTRB_SHIFT);
929   EFM_ASSERT(holdCycles <= _EBI_WRTIMING_WRHOLD_MASK >> _EBI_WRTIMING_WRHOLD_SHIFT);
930 
931   /* Configure timing values. */
932   writeTiming = (setupCycles << _EBI_WRTIMING_WRSETUP_SHIFT)
933                 | (strobeCycles << _EBI_WRTIMING_WRSTRB_SHIFT)
934                 | (holdCycles << _EBI_WRTIMING_WRHOLD_SHIFT);
935 
936   if (banks & EBI_BANK0) {
937     EBI->WRTIMING = (EBI->WRTIMING
938                      & ~(_EBI_WRTIMING_WRSETUP_MASK
939                          | _EBI_WRTIMING_WRSTRB_MASK
940                          | _EBI_WRTIMING_WRHOLD_MASK))
941                     | writeTiming;
942   }
943   if (banks & EBI_BANK1) {
944     EBI->WRTIMING1 = (EBI->WRTIMING1
945                       & ~(_EBI_WRTIMING1_WRSETUP_MASK
946                           | _EBI_WRTIMING1_WRSTRB_MASK
947                           | _EBI_WRTIMING1_WRHOLD_MASK))
948                      | writeTiming;
949   }
950   if (banks & EBI_BANK2) {
951     EBI->WRTIMING2 = (EBI->WRTIMING2
952                       & ~(_EBI_WRTIMING2_WRSETUP_MASK
953                           | _EBI_WRTIMING2_WRSTRB_MASK
954                           | _EBI_WRTIMING2_WRHOLD_MASK))
955                      | writeTiming;
956   }
957   if (banks & EBI_BANK3) {
958     EBI->WRTIMING3 = (EBI->WRTIMING3
959                       & ~(_EBI_WRTIMING3_WRSETUP_MASK
960                           | _EBI_WRTIMING3_WRSTRB_MASK
961                           | _EBI_WRTIMING3_WRHOLD_MASK))
962                      | writeTiming;
963   }
964 }
965 
966 /***************************************************************************//**
967  * @brief
968  *   Configure address operation parameters for a selected bank.
969  *
970  * @param[in] banks
971  *   A mask of memory bank(s) to configure write timing for.
972  *
973  * @param[in] halfALE
974  *   Enables or disables the half cycle ALE strobe in the last strobe cycle.
975  ******************************************************************************/
EBI_BankAddressTimingConfig(uint32_t banks,bool halfALE)976 void EBI_BankAddressTimingConfig(uint32_t banks, bool halfALE)
977 {
978   /* Verify only valid banks are used */
979   EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
980 
981   if ( banks & EBI_BANK0 ) {
982     BUS_RegBitWrite(&EBI->ADDRTIMING, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE);
983   }
984   if ( banks & EBI_BANK1 ) {
985     BUS_RegBitWrite(&EBI->ADDRTIMING1, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE);
986   }
987   if ( banks & EBI_BANK2 ) {
988     BUS_RegBitWrite(&EBI->ADDRTIMING2, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE);
989   }
990   if ( banks & EBI_BANK3 ) {
991     BUS_RegBitWrite(&EBI->ADDRTIMING3, _EBI_ADDRTIMING_HALFALE_SHIFT, halfALE);
992   }
993 }
994 
995 /***************************************************************************//**
996  * @brief
997  *   Configure timing values of address latch bus accesses.
998  *
999  * @param[in] banks
1000  *   A mask of memory bank(s) to configure address timing for.
1001  *
1002  * @param[in] setupCycles
1003  *   Sets the number of cycles the address is held after ALE is asserted.
1004  *
1005  * @param[in] holdCycles
1006  *   Sets the number of cycles the address is driven onto the ADDRDAT bus before
1007  *   ALE is asserted. If set 0, 1 cycle is inserted by hardware.
1008  ******************************************************************************/
EBI_BankAddressTimingSet(uint32_t banks,uint32_t setupCycles,uint32_t holdCycles)1009 void EBI_BankAddressTimingSet(uint32_t banks, uint32_t setupCycles, uint32_t holdCycles)
1010 {
1011   uint32_t addressLatchTiming;
1012 
1013   /* Verify only valid banks are used. */
1014   EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
1015 
1016   /* Check that timings are within limits */
1017   EFM_ASSERT(setupCycles <= _EBI_ADDRTIMING_ADDRSETUP_MASK >> _EBI_ADDRTIMING_ADDRSETUP_SHIFT);
1018   EFM_ASSERT(holdCycles <= _EBI_ADDRTIMING_ADDRHOLD_MASK >> _EBI_ADDRTIMING_ADDRHOLD_SHIFT);
1019 
1020   /* Configure address latch timing values. */
1021   addressLatchTiming = (setupCycles << _EBI_ADDRTIMING_ADDRSETUP_SHIFT)
1022                        | (holdCycles << _EBI_ADDRTIMING_ADDRHOLD_SHIFT);
1023 
1024   if (banks & EBI_BANK0) {
1025     EBI->ADDRTIMING = (EBI->ADDRTIMING
1026                        & ~(_EBI_ADDRTIMING_ADDRSETUP_MASK
1027                            | _EBI_ADDRTIMING_ADDRHOLD_MASK))
1028                       | addressLatchTiming;
1029   }
1030   if (banks & EBI_BANK1) {
1031     EBI->ADDRTIMING1 = (EBI->ADDRTIMING1
1032                         & ~(_EBI_ADDRTIMING1_ADDRSETUP_MASK
1033                             | _EBI_ADDRTIMING1_ADDRHOLD_MASK))
1034                        | addressLatchTiming;
1035   }
1036   if (banks & EBI_BANK2) {
1037     EBI->ADDRTIMING2 = (EBI->ADDRTIMING2
1038                         & ~(_EBI_ADDRTIMING2_ADDRSETUP_MASK
1039                             | _EBI_ADDRTIMING2_ADDRHOLD_MASK))
1040                        | addressLatchTiming;
1041   }
1042   if (banks & EBI_BANK3) {
1043     EBI->ADDRTIMING3 = (EBI->ADDRTIMING3
1044                         & ~(_EBI_ADDRTIMING3_ADDRSETUP_MASK
1045                             | _EBI_ADDRTIMING3_ADDRHOLD_MASK))
1046                        | addressLatchTiming;
1047   }
1048 }
1049 
1050 /***************************************************************************//**
1051  * @brief
1052  *   Configure EBI pin polarity for selected bank(s) for devices with individual
1053  *   timing support.
1054  *
1055  * @param[in] banks
1056  *   A mask of memory bank(s) to configure polarity for.
1057  *
1058  * @param[in] line
1059  *   Which pin/line to configure.
1060  *
1061  * @param[in] polarity
1062  *   Active high, or active low.
1063  ******************************************************************************/
EBI_BankPolaritySet(uint32_t banks,EBI_Line_TypeDef line,EBI_Polarity_TypeDef polarity)1064 void EBI_BankPolaritySet(uint32_t banks, EBI_Line_TypeDef line, EBI_Polarity_TypeDef polarity)
1065 {
1066   uint32_t bankSet = 0;
1067   volatile uint32_t *polRegister = 0;
1068 
1069   /* Verify that only valid banks are used. */
1070   EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
1071 
1072   while (banks) {
1073     if (banks & EBI_BANK0) {
1074       polRegister = &EBI->POLARITY;
1075       bankSet = EBI_BANK0;
1076     }
1077     if (banks & EBI_BANK1) {
1078       polRegister = &EBI->POLARITY1;
1079       bankSet = EBI_BANK1;
1080     }
1081     if (banks & EBI_BANK2) {
1082       polRegister = &EBI->POLARITY2;
1083       bankSet = EBI_BANK2;
1084     }
1085     if (banks & EBI_BANK3) {
1086       polRegister = &EBI->POLARITY3;
1087       bankSet = EBI_BANK3;
1088     }
1089 
1090     /* What line to configure. */
1091     switch (line) {
1092       case ebiLineARDY:
1093         BUS_RegBitWrite(polRegister, _EBI_POLARITY_ARDYPOL_SHIFT, polarity);
1094         break;
1095       case ebiLineALE:
1096         BUS_RegBitWrite(polRegister, _EBI_POLARITY_ALEPOL_SHIFT, polarity);
1097         break;
1098       case ebiLineWE:
1099         BUS_RegBitWrite(polRegister, _EBI_POLARITY_WEPOL_SHIFT, polarity);
1100         break;
1101       case ebiLineRE:
1102         BUS_RegBitWrite(polRegister, _EBI_POLARITY_REPOL_SHIFT, polarity);
1103         break;
1104       case ebiLineCS:
1105         BUS_RegBitWrite(polRegister, _EBI_POLARITY_CSPOL_SHIFT, polarity);
1106         break;
1107       case ebiLineBL:
1108         BUS_RegBitWrite(polRegister, _EBI_POLARITY_BLPOL_SHIFT, polarity);
1109         break;
1110       case ebiLineTFTVSync:
1111         BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_VSYNCPOL_SHIFT, polarity);
1112         break;
1113       case ebiLineTFTHSync:
1114         BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_HSYNCPOL_SHIFT, polarity);
1115         break;
1116       case ebiLineTFTDataEn:
1117         BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DATAENPOL_SHIFT, polarity);
1118         break;
1119       case ebiLineTFTDClk:
1120         BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_DCLKPOL_SHIFT, polarity);
1121         break;
1122       case ebiLineTFTCS:
1123         BUS_RegBitWrite(&(EBI->TFTPOLARITY), _EBI_TFTPOLARITY_CSPOL_SHIFT, polarity);
1124         break;
1125       default:
1126         EFM_ASSERT(0);
1127         break;
1128     }
1129     banks = banks & ~bankSet;
1130   }
1131 }
1132 
1133 /***************************************************************************//**
1134  * @brief
1135  *   Configure Byte Lane Enable for select banks
1136  *   timing support.
1137  *
1138  * @param[in] banks
1139  *   A mask of memory bank(s) to configure polarity for.
1140  *
1141  * @param[in] enable
1142  *   A flag
1143  ******************************************************************************/
EBI_BankByteLaneEnable(uint32_t banks,bool enable)1144 void EBI_BankByteLaneEnable(uint32_t banks, bool enable)
1145 {
1146   /* Verify only valid banks are used */
1147   EFM_ASSERT((banks & ~(EBI_BANK0 | EBI_BANK1 | EBI_BANK2 | EBI_BANK3)) == 0);
1148 
1149   /* Configure byte lane support for each selected bank */
1150   if (banks & EBI_BANK0) {
1151     BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL_SHIFT, enable);
1152   }
1153   if (banks & EBI_BANK1) {
1154     BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL1_SHIFT, enable);
1155   }
1156   if (banks & EBI_BANK2) {
1157     BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL2_SHIFT, enable);
1158   }
1159   if (banks & EBI_BANK3) {
1160     BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_BL3_SHIFT, enable);
1161   }
1162 }
1163 
1164 /***************************************************************************//**
1165  * @brief
1166  *   Configure the Alternate Address Map support.
1167  *   Enables or disables 256 MB address range for all banks.
1168  *
1169  * @param[in] enable
1170  *   Set or clear the address map extension.
1171  ******************************************************************************/
EBI_AltMapEnable(bool enable)1172 void EBI_AltMapEnable(bool enable)
1173 {
1174   BUS_RegBitWrite(&(EBI->CTRL), _EBI_CTRL_ALTMAP_SHIFT, enable);
1175 }
1176 
1177 #endif
1178 
1179 /** @} (end addtogroup ebi) */
1180 
1181 #endif /* defined(EBI_COUNT) && (EBI_COUNT > 0) */
1182