1 /**
2   ******************************************************************************
3   * @file    stm32h7xx_ll_delayblock.c
4   * @author  MCD Application Team
5   * @brief   DelayBlock Low Layer HAL module driver.
6   *
7   *          This file provides firmware functions to manage the following
8   *          functionalities of the Delay Block peripheral:
9   *           + input clock frequency range 25MHz to 208MHz
10   *           + up to 12 oversampling phases
11   *
12   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2017 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   ******************************************************************************
23   @verbatim
24   ==============================================================================
25                        ##### DelayBlock peripheral features #####
26   ==============================================================================
27     [..] The Delay block is used to generate an Output clock which is de-phased from the Input
28           clock. The phase of the Output clock is programmed by FW. The Output clock is then used
29           to clock the receive data in i.e. a SDMMC or QSPI interface.
30          The delay is Voltage and Temperature dependent, which may require FW to do re-tuning
31           and recenter the Output clock phase to the receive data.
32 
33     [..] The Delay Block features include the following:
34          (+) Input clock frequency range 25MHz to 208MHz.
35          (+) Up to 12 oversampling phases.
36 
37                            ##### How to use this driver #####
38   ==============================================================================
39     [..]
40       This driver is a considered as a driver of service for external devices drivers
41       that interfaces with the DELAY peripheral.
42       The DelayBlock_Enable() function, enables the DelayBlock instance, configure the delay line length
43       and configure the Output clock phase.
44       The DelayBlock_Disable() function, disables the DelayBlock instance by setting DEN flag to 0.
45 
46 
47   @endverbatim
48   */
49 
50 /* Includes ------------------------------------------------------------------*/
51 #include "stm32h7xx_hal.h"
52 
53 /** @addtogroup STM32H7xx_HAL_Driver
54   * @{
55   */
56 
57 /** @defgroup DELAYBLOCK_LL DELAYBLOCK_LL
58   * @brief Low layer module for Delay Block
59   * @{
60   */
61 
62 #if defined(HAL_SD_MODULE_ENABLED) || defined(HAL_QSPI_MODULE_ENABLED)
63 
64 /* Private typedef -----------------------------------------------------------*/
65 /* Private define ------------------------------------------------------------*/
66 /** @defgroup DelayBlock_LL_Private_Defines Delay Block Low Layer Private Defines
67   * @{
68   */
69 #define DLYB_TIMEOUT 0xFFU
70 /**
71   * @}
72   */
73 /* Private macro -------------------------------------------------------------*/
74 /* Private variables ---------------------------------------------------------*/
75 /* Private function prototypes -----------------------------------------------*/
76 /* Exported functions --------------------------------------------------------*/
77 
78 /** @defgroup DelayBlock_LL_Exported_Functions Delay Block Low Layer Exported Functions
79   * @{
80   */
81 
82 /** @defgroup HAL_DELAY_LL_Group1 Initialization de-initialization functions
83  *  @brief    Initialization and Configuration functions
84  *
85 @verbatim
86  ===============================================================================
87               ##### Initialization and de-initialization functions #####
88  ===============================================================================
89     [..]  This section provides functions allowing to:
90 
91 @endverbatim
92   * @{
93   */
94 
95 
96 /**
97   * @brief  Enable the Delay Block instance.
98   * @param  DLYBx: Pointer to DLYB instance.
99   * @retval HAL status
100   */
DelayBlock_Enable(DLYB_TypeDef * DLYBx)101 HAL_StatusTypeDef DelayBlock_Enable(DLYB_TypeDef *DLYBx)
102 {
103   uint32_t unit = 0U;
104   uint32_t sel = 0U;
105   uint32_t sel_current;
106   uint32_t unit_current;
107   uint32_t tuning;
108   uint32_t lng_mask;
109   uint32_t tickstart;
110 
111   DLYBx->CR = DLYB_CR_DEN | DLYB_CR_SEN;
112 
113   for (sel_current = 0U; sel_current < DLYB_MAX_SELECT; sel_current++)
114   {
115     /* lng_mask is the mask bit for the LNG field to check the output of the UNITx*/
116     lng_mask = DLYB_CFGR_LNG_0 << sel_current;
117     tuning = 0U;
118     for (unit_current = 0U; unit_current < DLYB_MAX_UNIT; unit_current++)
119     {
120       /* Set the Delay of the UNIT(s)*/
121       DLYBx->CFGR = DLYB_MAX_SELECT | (unit_current << DLYB_CFGR_UNIT_Pos);
122 
123       /* Waiting for a LNG valid value */
124       tickstart =  HAL_GetTick();
125       while ((DLYBx->CFGR & DLYB_CFGR_LNGF) == 0U)
126       {
127         if((HAL_GetTick() - tickstart) >=  DLYB_TIMEOUT)
128         {
129           return HAL_TIMEOUT;
130         }
131       }
132       if (tuning == 0U)
133       {
134         if ((DLYBx->CFGR & lng_mask) != 0U)
135         {
136           /* 1/2 period HIGH is detected */
137           tuning = 1U;
138         }
139       }
140       else
141       {
142         /* 1/2 period LOW detected after the HIGH 1/2 period => FULL PERIOD passed*/
143         if((DLYBx->CFGR & lng_mask ) == 0U)
144         {
145           /* Save the first result */
146           if( unit == 0U )
147           {
148             unit = unit_current;
149             sel  = sel_current + 1U;
150           }
151           break;
152         }
153       }
154     }
155   }
156 
157   /* Apply the Tuning settings */
158   DLYBx->CR   = 0U;
159   DLYBx->CR   = DLYB_CR_DEN | DLYB_CR_SEN;
160   DLYBx->CFGR = sel | (unit << DLYB_CFGR_UNIT_Pos);
161   DLYBx->CR   = DLYB_CR_DEN;
162 
163   return HAL_OK;
164 }
165 
166 /**
167   * @brief  Disable the Delay Block instance.
168   * @param  DLYBx: Pointer to DLYB instance.
169   * @retval HAL status
170   */
DelayBlock_Disable(DLYB_TypeDef * DLYBx)171 HAL_StatusTypeDef DelayBlock_Disable(DLYB_TypeDef *DLYBx)
172 {
173   /* Disable DLYB */
174   DLYBx->CR = 0U;
175   return HAL_OK;
176 }
177 
178 /**
179   * @brief  Configure the Delay Block instance.
180   * @param  DLYBx: Pointer to DLYB instance.
181   * @param  PhaseSel: Phase selection [0..11].
182   * @param  Units: Delay units[0..127].
183   * @retval HAL status
184   */
DelayBlock_Configure(DLYB_TypeDef * DLYBx,uint32_t PhaseSel,uint32_t Units)185 HAL_StatusTypeDef DelayBlock_Configure(DLYB_TypeDef *DLYBx,uint32_t PhaseSel, uint32_t Units )
186 {
187   /* Apply the delay settings */
188 
189   DLYBx->CR   = 0U;
190   DLYBx->CR   = DLYB_CR_DEN | DLYB_CR_SEN;
191   DLYBx->CFGR = PhaseSel | (Units << DLYB_CFGR_UNIT_Pos);
192   DLYBx->CR   = DLYB_CR_DEN;
193 
194   return HAL_OK;
195 }
196 
197 
198 /**
199   * @}
200   */
201 
202 /**
203   * @}
204   */
205 
206 #endif /* (HAL_SD_MODULE_ENABLED) & (HAL_QSPI_MODULE_ENABLED)*/
207 /**
208   * @}
209   */
210 
211 /**
212   * @}
213   */
214 
215