/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
  *         parameters in the RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals clocks(RTC/LCD clock).
  * @retval HAL status
  * @note   If HAL_ERROR returned, first switch-OFF HSE clock oscillator with @ref HAL_RCC_OscConfig()
  *         to possibly update HSE divider.
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tickstart = 0;
    uint32_t temp_reg = 0;

    /* Check the parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

    /*------------------------------- RTC/LCD Configuration ------------------------*/
    if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
#if defined(LCD)
            || (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
#endif /* LCD */
       )
    {
        /* check for RTC Parameters used to output RTCCLK */
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
        {
            assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
        }

#if defined(LCD)
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
        {
            assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->LCDClockSelection));
        }
#endif /* LCD */

        /* As soon as function is called to change RTC clock source, activation of the
           power domain is done. */
        /* Enable Power Clock*/
        __HAL_RCC_PWR_CLK_ENABLE();

        /* Enable write access to Backup domain */
        SET_BIT(PWR->CR, PWR_CR_DBP);

        /* Wait for Backup domain Write protection disable */
        tickstart = HAL_GetTick();

        while((PWR->CR & PWR_CR_DBP) == RESET)
        {
            if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
            {
                return HAL_TIMEOUT;
            }
        }

        /* Check if user wants to change HSE RTC prescaler whereas HSE is enabled */
        temp_reg = (RCC->CR & RCC_CR_RTCPRE);
        if ((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CR_RTCPRE))
#if defined (LCD)
                || (temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CR_RTCPRE))
#endif /* LCD */
           )
        {   /* Check HSE State */
            if (((PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL) == RCC_CSR_RTCSEL_HSE) && HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
            {
                /* To update HSE divider, first switch-OFF HSE clock oscillator*/
                return HAL_ERROR;
            }
        }

        /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
        temp_reg = (RCC->CSR & RCC_CSR_RTCSEL);

        if((temp_reg != 0x00000000U) && (((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL)) \
                                          && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
#if defined(LCD)
                                         || ((temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CSR_RTCSEL)) \
                                             && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD))
#endif /* LCD */
                                        ))
        {
            /* Store the content of CSR register before the reset of Backup Domain */
            temp_reg = (RCC->CSR & ~(RCC_CSR_RTCSEL));

            /* RTC Clock selection can be changed only if the Backup Domain is reset */
            __HAL_RCC_BACKUPRESET_FORCE();
            __HAL_RCC_BACKUPRESET_RELEASE();

            /* Restore the Content of CSR register */
            RCC->CSR = temp_reg;

            /* Wait for LSERDY if LSE was enabled */
            if (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSERDY))
            {
                /* Get Start Tick */
                tickstart = HAL_GetTick();

                /* Wait till LSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }

        }
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }

    return HAL_OK;
}
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
  *         parameters in the RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals clocks(RTC/LCD clock).
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
  uint32_t tickstart = 0;
  uint32_t temp_reg = 0;
  
  /* Check the parameters */
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
  
  /*------------------------------- RTC/LCD Configuration ------------------------*/ 
  if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) 
#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC)\
 || defined(STM32L152xB) || defined(STM32L152xBA) || defined(STM32L152xC)\
 || defined(STM32L162xC) || defined(STM32L152xCA) || defined(STM32L152xD)\
 || defined(STM32L162xCA) || defined(STM32L162xD) || defined(STM32L152xE) || defined(STM32L152xDX)\
 || defined(STM32L162xE) || defined(STM32L162xDX)
      || (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
#endif /* STM32L100xB || STM32L152xBA || ... || STM32L152xE || STM32L152xDX || STM32L162xE || STM32L162xDX */
    )
  {
    /* check for RTC Parameters used to output RTCCLK */
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
    {
      assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
    }

#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC)\
 || defined(STM32L152xB) || defined(STM32L152xBA) || defined(STM32L152xC)\
 || defined(STM32L162xC) || defined(STM32L152xCA) || defined(STM32L152xD)\
 || defined(STM32L162xCA) || defined(STM32L162xD) || defined(STM32L152xE) || defined(STM32L152xDX)\
 || defined(STM32L162xE) || defined(STM32L162xDX)
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
    {
      assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->LCDClockSelection));
    }
#endif /* STM32L100xB || STM32L152xBA || ... || STM32L152xE || STM32L152xDX || STM32L162xE || STM32L162xDX */

    /* Enable Power Clock*/
    __HAL_RCC_PWR_CLK_ENABLE();
    
    /* Enable write access to Backup domain */
    SET_BIT(PWR->CR, PWR_CR_DBP);
    
    /* Wait for Backup domain Write protection disable */
    tickstart = HAL_GetTick();
    
    while((PWR->CR & PWR_CR_DBP) == RESET)
    {
      if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
      {
        return HAL_TIMEOUT;
      }
    }
    
    /* Reset the Backup domain only if the RTC Clock source selection is modified */ 
    temp_reg = (RCC->CSR & RCC_CSR_RTCSEL);
    
    if(((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL)) \
      && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC)\
 || defined(STM32L152xB) || defined(STM32L152xBA) || defined(STM32L152xC)\
 || defined(STM32L162xC) || defined(STM32L152xCA) || defined(STM32L152xD)\
 || defined(STM32L162xCA) || defined(STM32L162xD) || defined(STM32L152xE) || defined(STM32L152xDX)\
 || defined(STM32L162xE) || defined(STM32L162xDX)
      || ((temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CSR_RTCSEL)) \
       && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD))
#endif /* STM32L100xB || STM32L152xBA || ... || STM32L152xE || STM32L152xDX || STM32L162xE || STM32L162xDX */
     )
    {
      /* Store the content of CSR register before the reset of Backup Domain */
      temp_reg = (RCC->CSR & ~(RCC_CSR_RTCSEL));
      
      /* RTC Clock selection can be changed only if the Backup Domain is reset */
      __HAL_RCC_BACKUPRESET_FORCE();
      __HAL_RCC_BACKUPRESET_RELEASE();
      
      /* Restore the Content of CSR register */
      RCC->CSR = temp_reg;
      
       /* Wait for LSERDY if LSE was enabled */
      if (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSERDY))
      {
        /* Get Start Tick */
        tickstart = HAL_GetTick();
        
        /* Wait till LSE is ready */  
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
        {
          if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
      
      __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
  }
  
  return HAL_OK;
}