Some checks failed
Basic Checks / license-check (push) Has been cancelled
Basic Checks / include-check (push) Has been cancelled
Basic Checks / style-check (push) Has been cancelled
Basic Checks / docs-check (push) Has been cancelled
Basic Checks / python-tests (push) Has been cancelled
Basic Checks / pin-validation (push) Has been cancelled
Basic Checks / cmake-checks (push) Has been cancelled
Basic Checks / frozen-tools-check (push) Has been cancelled
Publish or Update docker image for head of branch / prepare-tags (push) Has been cancelled
Release or update docker image for a released mbed-os version / prepare-tags (push) Has been cancelled
Publish or Update docker image for head of branch / build-container (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/amd64) (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/arm64) (push) Has been cancelled
Publish or Update docker image for head of branch / deploy-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / build-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/amd64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/arm64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / deploy-container (push) Has been cancelled
Prune temporary docker images / prune-images (push) Has been cancelled
1620 lines
55 KiB
C
1620 lines
55 KiB
C
/*******************************************************************************
|
|
* File Name: cyhal_clock.c
|
|
*
|
|
* Description:
|
|
* Provides an implementation for high level interface for interacting with the
|
|
* Cypress Clocks. This is a wrapper around the lower level PDL API.
|
|
*
|
|
********************************************************************************
|
|
* \copyright
|
|
* Copyright 2018-2021 Cypress Semiconductor Corporation
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*******************************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include "cy_sysclk.h"
|
|
#include "cy_utils.h"
|
|
#include "cyhal_clock.h"
|
|
#include "cyhal_utils.h"
|
|
#include "cyhal_hwmgr.h"
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#define _CYHAL_CLOCK_FLL_LOCK_TIME (200000UL)
|
|
#define _CYHAL_CLOCK_PLL_LOCK_TIME (10000UL)
|
|
|
|
/******************************************************************************
|
|
****************************** Clock Resources *******************************
|
|
*****************************************************************************/
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_IMO = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_IMO, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_EXT = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_EXT, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_ILO = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_ILO, 0 };
|
|
|
|
const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_0_P = {CYHAL_TOLERANCE_PERCENT, 0};
|
|
const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_1_P = {CYHAL_TOLERANCE_PERCENT, 1};
|
|
const cyhal_clock_tolerance_t CYHAL_CLOCK_TOLERANCE_5_P = {CYHAL_TOLERANCE_PERCENT, 5};
|
|
|
|
#if SRSS_ECO_PRESENT
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_ECO = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_ECO, 0 };
|
|
#endif
|
|
#if SRSS_ALTHF_PRESENT
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_ALTHF = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_ALTHF, 0 };
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_ALTLF = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_ALTLF, 0 };
|
|
#endif
|
|
#if SRSS_PILO_PRESENT
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_PILO = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PILO, 0 };
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_WCO = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_WCO, 0 };
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_MFO = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_MFO, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_MF = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_MF, 0 };
|
|
#endif
|
|
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_LF = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_LF, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_PUMP = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PUMP, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_BAK = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_BAK, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_FAST = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_FAST, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_PERI = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PERI, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_TIMER = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_TIMER, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_SLOW = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_SLOW, 0 };
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_ALT_SYS_TICK = { CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_ALT_SYS_TICK, 0 };
|
|
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_PATHMUX[SRSS_NUM_CLKPATH] =
|
|
{
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 0 },
|
|
#if (SRSS_NUM_CLKPATH > 1)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 1 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 2)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 2 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 3)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 3 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 4)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 4 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 5)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 5 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 6)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 6 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 7)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 7 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 8)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 8 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 9)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 9 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 10)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 10 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 11)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 11 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 12)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 12 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 13)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 13 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 14)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 14 },
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 15)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PATHMUX, 15 },
|
|
#endif
|
|
};
|
|
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_FLL = { CYHAL_RSC_CLOCK, CYHAL_CLOCK_BLOCK_FLL, 0 };
|
|
#if (SRSS_NUM_PLL > 0)
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_PLL[SRSS_NUM_PLL] =
|
|
{
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 0 },
|
|
#if (SRSS_NUM_PLL > 1)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 1 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 2)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 2 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 3)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 3 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 4)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 4 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 5)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 5 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 6)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 6 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 7)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 7 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 8)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 8 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 9)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 9 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 10)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 10 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 11)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 11 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 12)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 12 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 13)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 13 },
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 14)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_PLL, 14 },
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
const cyhal_resource_inst_t CYHAL_CLOCK_HF[SRSS_NUM_HFROOT] =
|
|
{
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 0 },
|
|
#if (SRSS_NUM_HFROOT > 1)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 1 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 2)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 2 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 3)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 3 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 4)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 4 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 5)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 5 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 6)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 6 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 7)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 7 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 8)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 8 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 9)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 9 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 10)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 10 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 11)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 11 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 12)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 12 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 13)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 13 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 14)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 14 },
|
|
#endif
|
|
#if (SRSS_NUM_HFROOT > 15)
|
|
{ CYHAL_RSC_CLOCK, (uint8_t)CYHAL_CLOCK_BLOCK_HF, 15 },
|
|
#endif
|
|
};
|
|
|
|
/******************************************************************************
|
|
***************************** Support Functions*******************************
|
|
*****************************************************************************/
|
|
static void _cyhal_clock_setup_inst(cyhal_clock_t *clock, const cyhal_resource_inst_t* resource, bool reserved)
|
|
{
|
|
clock->div_type = (cy_en_divider_types_t)resource->block_num;
|
|
clock->div_num = resource->channel_num;
|
|
clock->block = (cyhal_clock_block_t)resource->block_num;
|
|
clock->channel = resource->channel_num;
|
|
clock->reserved = reserved;
|
|
}
|
|
|
|
static cy_rslt_t _cyhal_clock_compute_div(uint32_t input_hz, uint32_t desired_hz, uint32_t divider_bits, const cyhal_clock_tolerance_t *tolerance, uint32_t *div)
|
|
{
|
|
uint32_t max_div = (1 << divider_bits);
|
|
*div = (input_hz + (desired_hz / 2)) / desired_hz;
|
|
if (*div > max_div)
|
|
*div = max_div;
|
|
|
|
uint32_t diff = (tolerance != NULL)
|
|
? (uint32_t)abs(_cyhal_utils_calculate_tolerance(tolerance->type, desired_hz, input_hz / *div))
|
|
: 0;
|
|
|
|
return (tolerance != NULL && diff > tolerance->value)
|
|
? CYHAL_CLOCK_RSLT_ERR_FREQ
|
|
: CY_RSLT_SUCCESS;
|
|
}
|
|
|
|
static uint32_t _cyhal_clock_get_lf_frequency(void)
|
|
{
|
|
cy_en_clklf_in_sources_t source = Cy_SysClk_ClkLfGetSource();
|
|
switch (source)
|
|
{
|
|
case CY_SYSCLK_CLKLF_IN_ILO:
|
|
return CY_SYSCLK_ILO_FREQ;
|
|
#if SRSS_PILO_PRESENT
|
|
case CY_SYSCLK_CLKLF_IN_PILO:
|
|
return CY_SYSCLK_PILO_FREQ;
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
case CY_SYSCLK_CLKLF_IN_WCO:
|
|
return CY_SYSCLK_WCO_FREQ;
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
case CY_SYSCLK_CLKLF_IN_ALTLF:
|
|
return Cy_SysClk_AltLfGetFrequency();
|
|
#endif
|
|
default:
|
|
CY_ASSERT(false);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static uint32_t _cyhal_clock_get_channel_count(cyhal_clock_block_t block)
|
|
{
|
|
switch (block)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT:
|
|
return PERI_DIV_8_NR;
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT:
|
|
return PERI_DIV_16_NR;
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT:
|
|
return PERI_DIV_16_5_NR;
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT:
|
|
return PERI_DIV_24_5_NR;
|
|
case CYHAL_CLOCK_BLOCK_PATHMUX:
|
|
return SRSS_NUM_CLKPATH;
|
|
case CYHAL_CLOCK_BLOCK_PLL:
|
|
return SRSS_NUM_PLL;
|
|
case CYHAL_CLOCK_BLOCK_HF:
|
|
return SRSS_NUM_HFROOT;
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
static void _cyhal_clock_update_system_state(bool before_change, uint32_t old_sysclk_freq_hz, uint32_t new_sysclk_freq_hz)
|
|
{
|
|
// If increasing the clock frequency we need to update the speeds
|
|
// before the change. If decreasing the frequency we need to update
|
|
// after the change.
|
|
if ((before_change == (bool)(new_sysclk_freq_hz > old_sysclk_freq_hz)) ||
|
|
(!before_change == (new_sysclk_freq_hz < old_sysclk_freq_hz)))
|
|
{
|
|
bool is_ulp = Cy_SysPm_IsSystemUlp();
|
|
Cy_SysLib_SetWaitStates(is_ulp, new_sysclk_freq_hz / 1000000);
|
|
}
|
|
|
|
// If after the change, update the clock
|
|
if (!before_change)
|
|
SystemCoreClockUpdate();
|
|
}
|
|
|
|
static inline cy_rslt_t _cyhal_clock_set_hfclk_div(uint8_t clk, uint32_t div_val)
|
|
{
|
|
cy_en_clkhf_dividers_t new_div;
|
|
switch (div_val)
|
|
{
|
|
case 1:
|
|
new_div = CY_SYSCLK_CLKHF_NO_DIVIDE;
|
|
break;
|
|
case 2:
|
|
new_div = CY_SYSCLK_CLKHF_DIVIDE_BY_2;
|
|
break;
|
|
case 4:
|
|
new_div = CY_SYSCLK_CLKHF_DIVIDE_BY_4;
|
|
break;
|
|
case 8:
|
|
new_div = CY_SYSCLK_CLKHF_DIVIDE_BY_8;
|
|
break;
|
|
default:
|
|
return CYHAL_CLOCK_RSLT_ERR_FREQ;
|
|
}
|
|
|
|
/* Only used if updating HFClk 0 */
|
|
uint32_t old_div = (uint32_t)Cy_SysClk_ClkHfGetDivider(0);
|
|
uint32_t src = (uint32_t)Cy_SysClk_ClkHfGetSource(0);
|
|
uint32_t path_freq = Cy_SysClk_ClkPathGetFrequency(src);
|
|
uint32_t old_freq = path_freq >> old_div;
|
|
uint32_t new_freq = path_freq >> ((uint32_t)new_div);
|
|
|
|
if (0 == clk)
|
|
_cyhal_clock_update_system_state(true, old_freq, new_freq);
|
|
|
|
cy_rslt_t rslt = (cy_rslt_t)Cy_SysClk_ClkHfSetDivider(clk, new_div);
|
|
|
|
if (0 == clk)
|
|
{
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
_cyhal_clock_update_system_state(false, old_freq, new_freq);
|
|
else // revert the change if there was one
|
|
_cyhal_clock_update_system_state(false, new_freq, old_freq);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
static inline cy_rslt_t _cyhal_clock_set_hfclk_source(uint8_t clk, const cyhal_clock_t *source)
|
|
{
|
|
uint32_t new_src;
|
|
if (source->block == CYHAL_CLOCK_BLOCK_PATHMUX || source->block == CYHAL_CLOCK_BLOCK_FLL)
|
|
new_src = source->channel;
|
|
else if (source->block == CYHAL_CLOCK_BLOCK_PLL)
|
|
new_src = source->channel + 1;
|
|
else
|
|
return CYHAL_CLOCK_RSLT_ERR_SOURCE;
|
|
|
|
/* Only used if updating HFClk 0 */
|
|
uint32_t div = (uint32_t)Cy_SysClk_ClkHfGetDivider(0);
|
|
uint32_t old_src = (uint32_t)Cy_SysClk_ClkHfGetSource(0);
|
|
uint32_t old_freq = Cy_SysClk_ClkPathGetFrequency(old_src) >> div;
|
|
uint32_t new_freq = Cy_SysClk_ClkPathGetFrequency(new_src) >> div;
|
|
|
|
if (0 == clk)
|
|
_cyhal_clock_update_system_state(true, old_freq, new_freq);
|
|
|
|
cy_rslt_t rslt = Cy_SysClk_ClkHfSetSource(clk, (cy_en_clkhf_in_sources_t)new_src);
|
|
|
|
if (0 == clk)
|
|
{
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
_cyhal_clock_update_system_state(false, old_freq, new_freq);
|
|
else // revert the change if there was one
|
|
_cyhal_clock_update_system_state(false, new_freq, old_freq);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
static inline cy_rslt_t _cyhal_clock_set_pathmux_source(uint8_t mux, cyhal_clock_block_t source)
|
|
{
|
|
uint32_t new_freq;
|
|
cy_en_clkpath_in_sources_t clkpath_src;
|
|
switch (source)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_IMO:
|
|
clkpath_src = CY_SYSCLK_CLKPATH_IN_IMO;
|
|
new_freq = CY_SYSCLK_IMO_FREQ;
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_EXT:
|
|
clkpath_src = CY_SYSCLK_CLKPATH_IN_EXT;
|
|
new_freq = Cy_SysClk_ExtClkGetFrequency();
|
|
break;
|
|
#if SRSS_ECO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ECO:
|
|
clkpath_src = CY_SYSCLK_CLKPATH_IN_ECO;
|
|
new_freq = Cy_SysClk_EcoGetFrequency();
|
|
break;
|
|
#endif
|
|
#if SRSS_ALTHF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTHF:
|
|
clkpath_src = CY_SYSCLK_CLKPATH_IN_ALTHF;
|
|
new_freq = Cy_SysClk_AltHfGetFrequency();
|
|
break;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_ILO:
|
|
clkpath_src = CY_SYSCLK_CLKPATH_IN_ILO;
|
|
new_freq = CY_SYSCLK_ILO_FREQ;
|
|
break;
|
|
#if SRSS_BACKUP_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_WCO:
|
|
clkpath_src = CY_SYSCLK_CLKPATH_IN_WCO;
|
|
new_freq = CY_SYSCLK_WCO_FREQ;
|
|
break;
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTLF:
|
|
clkpath_src = CY_SYSCLK_CLKPATH_IN_ALTLF;
|
|
new_freq = Cy_SysClk_AltLfGetFrequency();
|
|
break;
|
|
#endif
|
|
#if SRSS_PILO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_PILO:
|
|
clkpath_src = CY_SYSCLK_CLKPATH_IN_PILO;
|
|
new_freq = CY_SYSCLK_PILO_FREQ;
|
|
break;
|
|
#endif
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return CYHAL_CLOCK_RSLT_ERR_SOURCE;
|
|
}
|
|
|
|
uint32_t old_hf_freq = Cy_SysClk_ClkHfGetFrequency(0);
|
|
uint32_t new_hf_freq = new_freq >> ((uint8_t)Cy_SysClk_ClkHfGetDivider(0));
|
|
bool is_sysclk_path = (mux == (uint32_t)Cy_SysClk_ClkHfGetSource(0));
|
|
|
|
if (is_sysclk_path)
|
|
_cyhal_clock_update_system_state(true, old_hf_freq, new_hf_freq);
|
|
|
|
cy_rslt_t rslt = Cy_SysClk_ClkPathSetSource(mux, clkpath_src);
|
|
|
|
if (is_sysclk_path)
|
|
{
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
_cyhal_clock_update_system_state(false, old_hf_freq, new_hf_freq);
|
|
else // revert the change if there was one
|
|
_cyhal_clock_update_system_state(false, new_hf_freq, old_hf_freq);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
static inline cy_rslt_t _cyhal_clock_change_fll_enablement(bool enable, bool wait_for_lock)
|
|
{
|
|
cy_stc_fll_manual_config_t cfg;
|
|
Cy_SysClk_FllGetConfiguration(&cfg);
|
|
uint32_t new_freq, old_freq;
|
|
uint32_t div = (uint32_t)Cy_SysClk_ClkHfGetDivider(0);
|
|
uint32_t src_freq = Cy_SysClk_ClkPathMuxGetFrequency(0);
|
|
uint32_t fll_freq = CY_SYSLIB_DIV_ROUND((uint64_t)src_freq * (uint64_t)cfg.fllMult, (uint32_t)cfg.refDiv * ((cfg.enableOutputDiv) ? 2UL : 1UL));
|
|
if (enable)
|
|
{
|
|
new_freq = fll_freq >> div;
|
|
old_freq = src_freq >> div;
|
|
}
|
|
else
|
|
{
|
|
new_freq = src_freq >> div;
|
|
old_freq = fll_freq >> div;
|
|
}
|
|
|
|
bool fll_sources_hf0 = (0 == (uint32_t)Cy_SysClk_ClkHfGetSource(0));
|
|
if (fll_sources_hf0)
|
|
_cyhal_clock_update_system_state(true, old_freq, new_freq);
|
|
|
|
cy_rslt_t rslt = (enable)
|
|
? Cy_SysClk_FllEnable(wait_for_lock ? _CYHAL_CLOCK_FLL_LOCK_TIME : 0UL)
|
|
: Cy_SysClk_FllDisable();
|
|
|
|
if (fll_sources_hf0)
|
|
{
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
_cyhal_clock_update_system_state(false, old_freq, new_freq);
|
|
else // revert the change if there was one
|
|
_cyhal_clock_update_system_state(false, new_freq, old_freq);
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
static inline cy_rslt_t _cyhal_clock_set_fll_freq(uint32_t new_freq)
|
|
{
|
|
cy_rslt_t rslt = CY_RSLT_SUCCESS;
|
|
cy_stc_fll_manual_config_t cfg;
|
|
Cy_SysClk_FllGetConfiguration(&cfg);
|
|
uint32_t src_freq = Cy_SysClk_ClkPathMuxGetFrequency(0);
|
|
|
|
if (0 == src_freq)
|
|
rslt = CYHAL_CLOCK_RSLT_ERR_SOURCE;
|
|
else
|
|
{
|
|
uint32_t old_freq = CY_SYSLIB_DIV_ROUND((uint64_t)src_freq * (uint64_t)cfg.fllMult, (uint32_t)cfg.refDiv * ((cfg.enableOutputDiv) ? 2UL : 1UL));
|
|
uint32_t div = (uint32_t)Cy_SysClk_ClkHfGetDivider(0);
|
|
uint32_t old_hf_freq = old_freq >> div;
|
|
uint32_t new_hf_freq = new_freq >> div;
|
|
|
|
bool fll_sources_hf0 = (0 == (uint32_t)Cy_SysClk_ClkHfGetSource(0));
|
|
if (fll_sources_hf0)
|
|
_cyhal_clock_update_system_state(true, old_hf_freq, new_hf_freq);
|
|
|
|
bool enabled = Cy_SysClk_FllIsEnabled();
|
|
if (enabled)
|
|
rslt = Cy_SysClk_FllDisable();
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
{
|
|
rslt = Cy_SysClk_FllConfigure(src_freq, new_freq, CY_SYSCLK_FLLPLL_OUTPUT_AUTO);
|
|
|
|
if (enabled)
|
|
{
|
|
cy_rslt_t rslt2 = Cy_SysClk_FllEnable(_CYHAL_CLOCK_FLL_LOCK_TIME);
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
rslt = rslt2;
|
|
}
|
|
}
|
|
|
|
if (fll_sources_hf0)
|
|
{
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
_cyhal_clock_update_system_state(false, old_hf_freq, new_hf_freq);
|
|
else // revert the change if there was one
|
|
_cyhal_clock_update_system_state(false, new_hf_freq, old_hf_freq);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
#if (SRSS_NUM_PLL > 0)
|
|
//pll_idx is the path mux index (eg PLL number + 1) as used by PDL APIs
|
|
static inline cy_rslt_t _cyhal_clock_change_pll_enablement(uint8_t pll_idx, bool enable, bool wait_for_lock)
|
|
{
|
|
cy_stc_pll_manual_config_t cfg;
|
|
cy_rslt_t rslt = Cy_SysClk_PllGetConfiguration(pll_idx, &cfg);
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
{
|
|
uint32_t new_freq, old_freq;
|
|
uint32_t div = (uint32_t)Cy_SysClk_ClkHfGetDivider(0);
|
|
uint32_t src_freq = Cy_SysClk_ClkPathMuxGetFrequency(pll_idx);
|
|
uint32_t pll_freq = CY_SYSLIB_DIV_ROUND((uint64_t)src_freq * (uint64_t)cfg.feedbackDiv, (uint32_t)cfg.referenceDiv * (uint32_t)cfg.outputDiv);
|
|
if (enable)
|
|
{
|
|
new_freq = pll_freq >> div;
|
|
old_freq = src_freq >> div;
|
|
}
|
|
else
|
|
{
|
|
new_freq = src_freq >> div;
|
|
old_freq = pll_freq >> div;
|
|
}
|
|
|
|
bool pll_sources_hf0 = (pll_idx == (uint32_t)Cy_SysClk_ClkHfGetSource(0));
|
|
if (pll_sources_hf0)
|
|
_cyhal_clock_update_system_state(true, old_freq, new_freq);
|
|
|
|
rslt = (enable)
|
|
? Cy_SysClk_PllEnable(pll_idx, wait_for_lock ? _CYHAL_CLOCK_PLL_LOCK_TIME : 0UL)
|
|
: Cy_SysClk_PllDisable(pll_idx);
|
|
|
|
if (pll_sources_hf0)
|
|
{
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
_cyhal_clock_update_system_state(false, old_freq, new_freq);
|
|
else // revert the change if there was one
|
|
_cyhal_clock_update_system_state(false, new_freq, old_freq);
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
static inline cy_rslt_t _cyhal_clock_set_pll_freq(uint8_t pll_idx, uint32_t new_freq)
|
|
{
|
|
cy_stc_pll_manual_config_t cfg;
|
|
cy_rslt_t rslt = Cy_SysClk_PllGetConfiguration(pll_idx, &cfg);
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
{
|
|
bool enabled = Cy_SysClk_PllIsEnabled(pll_idx);
|
|
if (enabled)
|
|
rslt = Cy_SysClk_PllDisable(pll_idx);
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
{
|
|
uint32_t src_freq = Cy_SysClk_ClkPathMuxGetFrequency(pll_idx);
|
|
uint32_t old_freq = CY_SYSLIB_DIV_ROUND((uint64_t)src_freq * (uint64_t)cfg.feedbackDiv, (uint32_t)cfg.referenceDiv * (uint32_t)cfg.outputDiv);
|
|
|
|
uint32_t div = (uint32_t)Cy_SysClk_ClkHfGetDivider(0);
|
|
uint32_t old_hf_freq = old_freq >> div;
|
|
uint32_t new_hf_freq = new_freq >> div;
|
|
|
|
bool pll_sources_hf0 = (pll_idx == (uint32_t)Cy_SysClk_ClkHfGetSource(0));
|
|
if (pll_sources_hf0)
|
|
_cyhal_clock_update_system_state(true, old_hf_freq, new_hf_freq);
|
|
|
|
uint32_t input_hz = Cy_SysClk_ClkPathMuxGetFrequency(pll_idx);
|
|
cy_stc_pll_config_t cfg =
|
|
{
|
|
.inputFreq = input_hz,
|
|
.outputFreq = new_freq,
|
|
.lfMode = false,
|
|
.outputMode = CY_SYSCLK_FLLPLL_OUTPUT_AUTO,
|
|
};
|
|
rslt = Cy_SysClk_PllConfigure(pll_idx, &cfg);
|
|
|
|
if (enabled)
|
|
{
|
|
cy_rslt_t rslt2 = Cy_SysClk_PllEnable(pll_idx, _CYHAL_CLOCK_PLL_LOCK_TIME);
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
rslt = rslt2;
|
|
}
|
|
|
|
if (pll_sources_hf0)
|
|
{
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
_cyhal_clock_update_system_state(false, old_hf_freq, new_hf_freq);
|
|
else // revert the change if there was one
|
|
_cyhal_clock_update_system_state(false, new_hf_freq, old_hf_freq);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
**************************** Public API (clocks) *****************************
|
|
*****************************************************************************/
|
|
cy_rslt_t cyhal_clock_get(cyhal_clock_t *clock, const cyhal_resource_inst_t *resource)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(NULL != resource);
|
|
CY_ASSERT(CYHAL_RSC_CLOCK == resource->type);
|
|
|
|
_cyhal_clock_setup_inst(clock, resource, false);
|
|
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
|
|
cy_rslt_t cyhal_clock_allocate(cyhal_clock_t *clock, cyhal_clock_block_t block)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
|
|
uint8_t maxChannels = (uint8_t)_cyhal_clock_get_channel_count(block);
|
|
for (uint8_t i = 0; i < maxChannels; i++)
|
|
{
|
|
cyhal_resource_inst_t clock_resource = { CYHAL_RSC_CLOCK, block, i };
|
|
if (CY_RSLT_SUCCESS == cyhal_hwmgr_reserve(&clock_resource))
|
|
{
|
|
_cyhal_clock_setup_inst(clock, &clock_resource, true);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
}
|
|
return CYHAL_HWMGR_RSLT_ERR_NONE_FREE;
|
|
}
|
|
|
|
cy_rslt_t cyhal_clock_init(cyhal_clock_t *clock)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
cyhal_resource_inst_t resource = { CYHAL_RSC_CLOCK, clock->block, clock->channel };
|
|
cy_rslt_t rslt = cyhal_hwmgr_reserve(&resource);
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
{
|
|
clock->reserved = true;
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|
|
cyhal_clock_feature_t cyhal_clock_get_features(const cyhal_clock_t *clock)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
switch (clock->block)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_IMO:
|
|
#if SRSS_ALTHF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTHF:
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTLF:
|
|
#endif
|
|
return CYHAL_CLOCK_FEATURE_NONE;
|
|
|
|
case CYHAL_CLOCK_BLOCK_ILO:
|
|
#if SRSS_ECO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ECO: //We don't allow setting frequency because we don't have the necessary args
|
|
#endif
|
|
#if SRSS_PILO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_PILO:
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_WCO:
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MFO:
|
|
#endif
|
|
return CYHAL_CLOCK_FEATURE_ENABLE;
|
|
|
|
case CYHAL_CLOCK_BLOCK_EXT:
|
|
return CYHAL_CLOCK_FEATURE_FREQUENCY;
|
|
|
|
case CYHAL_CLOCK_BLOCK_FLL:
|
|
#if (SRSS_NUM_PLL > 0)
|
|
case CYHAL_CLOCK_BLOCK_PLL:
|
|
#endif
|
|
return (cyhal_clock_feature_t)(CYHAL_CLOCK_FEATURE_ENABLE | CYHAL_CLOCK_FEATURE_FREQUENCY);
|
|
|
|
case CYHAL_CLOCK_BLOCK_FAST:
|
|
case CYHAL_CLOCK_BLOCK_PERI:
|
|
case CYHAL_CLOCK_BLOCK_SLOW:
|
|
return (cyhal_clock_feature_t)(CYHAL_CLOCK_FEATURE_DIVIDER | CYHAL_CLOCK_FEATURE_FREQUENCY);
|
|
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MF:
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT:
|
|
return (cyhal_clock_feature_t)(CYHAL_CLOCK_FEATURE_ENABLE | CYHAL_CLOCK_FEATURE_DIVIDER | CYHAL_CLOCK_FEATURE_FREQUENCY);
|
|
|
|
case CYHAL_CLOCK_BLOCK_HF:
|
|
if (clock->channel == 0) // HF0 cannot be disabled
|
|
return (cyhal_clock_feature_t)(CYHAL_CLOCK_FEATURE_SOURCE | CYHAL_CLOCK_FEATURE_DIVIDER);
|
|
return (cyhal_clock_feature_t)(CYHAL_CLOCK_FEATURE_ENABLE | CYHAL_CLOCK_FEATURE_SOURCE | CYHAL_CLOCK_FEATURE_DIVIDER);
|
|
case CYHAL_CLOCK_BLOCK_PUMP:
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
return (cyhal_clock_feature_t)(CYHAL_CLOCK_FEATURE_ENABLE | CYHAL_CLOCK_FEATURE_SOURCE | CYHAL_CLOCK_FEATURE_DIVIDER);
|
|
|
|
case CYHAL_CLOCK_BLOCK_PATHMUX:
|
|
case CYHAL_CLOCK_BLOCK_LF:
|
|
case CYHAL_CLOCK_BLOCK_BAK:
|
|
case CYHAL_CLOCK_BLOCK_ALT_SYS_TICK:
|
|
return CYHAL_CLOCK_FEATURE_SOURCE;
|
|
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return CYHAL_CLOCK_FEATURE_NONE;
|
|
}
|
|
}
|
|
|
|
bool cyhal_clock_is_enabled(const cyhal_clock_t *clock)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
switch (clock->block)
|
|
{
|
|
#if SRSS_ECO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ECO:
|
|
return 0u != (SRSS_CLK_ECO_CONFIG & SRSS_CLK_ECO_CONFIG_ECO_EN_Msk);
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_EXT:
|
|
return (Cy_SysClk_ExtClkGetFrequency() > 0);
|
|
#if SRSS_ALTHF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTHF:
|
|
return (Cy_SysClk_AltHfGetFrequency() > 0);
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTLF:
|
|
return Cy_SysClk_AltLfIsEnabled();
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_ILO:
|
|
return Cy_SysClk_IloIsEnabled();
|
|
#if SRSS_PILO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_PILO:
|
|
return Cy_SysClk_PiloIsEnabled();
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_WCO:
|
|
return 0u != (BACKUP_CTL & BACKUP_CTL_WCO_EN_Msk);
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MFO:
|
|
return Cy_SysClk_MfoIsEnabled();
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_FLL:
|
|
return Cy_SysClk_FllIsEnabled();
|
|
#if (SRSS_NUM_PLL > 0)
|
|
case CYHAL_CLOCK_BLOCK_PLL:
|
|
return Cy_SysClk_PllIsEnabled(clock->channel + 1);
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MF:
|
|
return Cy_SysClk_ClkMfIsEnabled();
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_HF:
|
|
return Cy_SysClk_ClkHfIsEnabled(clock->channel);
|
|
case CYHAL_CLOCK_BLOCK_PUMP:
|
|
return Cy_SysClk_ClkPumpIsEnabled();
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
return Cy_SysClk_ClkTimerIsEnabled();
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT:
|
|
return Cy_SysClk_PeriphGetDividerEnabled((cy_en_divider_types_t)clock->block, clock->channel);
|
|
case CYHAL_CLOCK_BLOCK_IMO:
|
|
case CYHAL_CLOCK_BLOCK_PATHMUX:
|
|
case CYHAL_CLOCK_BLOCK_LF:
|
|
case CYHAL_CLOCK_BLOCK_BAK:
|
|
case CYHAL_CLOCK_BLOCK_ALT_SYS_TICK:
|
|
case CYHAL_CLOCK_BLOCK_FAST:
|
|
case CYHAL_CLOCK_BLOCK_PERI:
|
|
case CYHAL_CLOCK_BLOCK_SLOW:
|
|
return true;
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return false;
|
|
}
|
|
}
|
|
|
|
cy_rslt_t cyhal_clock_set_enabled(cyhal_clock_t *clock, bool enabled, bool wait_for_lock)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
/* Timeout values are from the device datasheet. */
|
|
|
|
switch (clock->block)
|
|
{
|
|
#if SRSS_ECO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ECO:
|
|
if (enabled)
|
|
{
|
|
if (0u != (SRSS_CLK_ECO_CONFIG & SRSS_CLK_ECO_CONFIG_ECO_EN_Msk))
|
|
{
|
|
// Already enabled
|
|
if (wait_for_lock)
|
|
{
|
|
for (int t = 0; t < 3 && Cy_SysClk_EcoGetStatus() != CY_SYSCLK_ECOSTAT_STABLE; ++t)
|
|
{
|
|
Cy_SysLib_DelayUs(1000UL);
|
|
}
|
|
return Cy_SysClk_EcoGetStatus() == CY_SYSCLK_ECOSTAT_STABLE
|
|
? CY_RSLT_SUCCESS
|
|
: CY_SYSCLK_TIMEOUT;
|
|
}
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return Cy_SysClk_EcoEnable(wait_for_lock ? 3000UL : 0UL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Cy_SysClk_EcoDisable();
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_ILO:
|
|
if (enabled)
|
|
Cy_SysClk_IloEnable();
|
|
else
|
|
Cy_SysClk_IloDisable();
|
|
return CY_RSLT_SUCCESS;
|
|
#if SRSS_PILO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_PILO:
|
|
if (enabled)
|
|
Cy_SysClk_PiloEnable();
|
|
else
|
|
Cy_SysClk_PiloDisable();
|
|
return CY_RSLT_SUCCESS;
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_WCO:
|
|
if (enabled)
|
|
{
|
|
cy_rslt_t rslt = Cy_SysClk_WcoEnable(wait_for_lock ? 1000000UL : 0UL);
|
|
// Ignore CY_SYSCLK_TIMEOUT unless wait_for_lock is true
|
|
return wait_for_lock ? rslt : CY_RSLT_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Cy_SysClk_WcoDisable();
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MFO:
|
|
if (enabled)
|
|
Cy_SysClk_MfoEnable(true);
|
|
else
|
|
Cy_SysClk_MfoDisable();
|
|
return CY_RSLT_SUCCESS;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_FLL:
|
|
return _cyhal_clock_change_fll_enablement(enabled, wait_for_lock);
|
|
|
|
#if (SRSS_NUM_PLL > 0)
|
|
case CYHAL_CLOCK_BLOCK_PLL:
|
|
return _cyhal_clock_change_pll_enablement(clock->channel + 1, enabled, wait_for_lock);
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MF:
|
|
if (enabled)
|
|
Cy_SysClk_ClkMfEnable();
|
|
else
|
|
Cy_SysClk_ClkMfDisable();
|
|
return CY_RSLT_SUCCESS;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_HF:
|
|
return (enabled)
|
|
? Cy_SysClk_ClkHfEnable(clock->channel)
|
|
: Cy_SysClk_ClkHfDisable(clock->channel);
|
|
case CYHAL_CLOCK_BLOCK_PUMP:
|
|
if (enabled)
|
|
Cy_SysClk_ClkPumpEnable();
|
|
else
|
|
Cy_SysClk_ClkPumpDisable();
|
|
return CY_RSLT_SUCCESS;
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
if (enabled)
|
|
Cy_SysClk_ClkTimerEnable();
|
|
else
|
|
Cy_SysClk_ClkTimerDisable();
|
|
return CY_RSLT_SUCCESS;
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT:
|
|
return (enabled)
|
|
? Cy_SysClk_PeriphEnableDivider((cy_en_divider_types_t)clock->block, clock->channel)
|
|
: Cy_SysClk_PeriphDisableDivider((cy_en_divider_types_t)clock->block, clock->channel);
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return CYHAL_CLOCK_RSLT_ERR_RESOURCE;
|
|
}
|
|
}
|
|
|
|
uint32_t cyhal_clock_get_frequency(const cyhal_clock_t *clock)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
if (!cyhal_clock_is_enabled(clock))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
switch (clock->block)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_IMO:
|
|
return CY_SYSCLK_IMO_FREQ;
|
|
#if SRSS_ECO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ECO:
|
|
return Cy_SysClk_EcoGetFrequency();
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_EXT:
|
|
return Cy_SysClk_ExtClkGetFrequency();
|
|
#if SRSS_ALTHF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTHF:
|
|
return Cy_SysClk_AltHfGetFrequency();
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTLF:
|
|
return Cy_SysClk_AltLfGetFrequency();
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MFO:
|
|
return CY_SYSCLK_MFO_FREQ;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_ILO:
|
|
return CY_SYSCLK_ILO_FREQ;
|
|
#if SRSS_PILO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_PILO:
|
|
return CY_SYSCLK_PILO_FREQ;
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_WCO:
|
|
return CY_SYSCLK_WCO_FREQ;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_PATHMUX:
|
|
return Cy_SysClk_ClkPathMuxGetFrequency(clock->channel);
|
|
case CYHAL_CLOCK_BLOCK_FLL:
|
|
return Cy_SysClk_FllIsEnabled()
|
|
? Cy_SysClk_ClkPathGetFrequency(0)
|
|
: 0;
|
|
#if (SRSS_NUM_PLL > 0)
|
|
case CYHAL_CLOCK_BLOCK_PLL:
|
|
return Cy_SysClk_PllIsEnabled(clock->channel + 1)
|
|
? Cy_SysClk_ClkPathGetFrequency(clock->channel + 1)
|
|
: 0;
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MF:
|
|
return Cy_SysClk_ClkMfGetFrequency();
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_HF:
|
|
return Cy_SysClk_ClkHfGetFrequency(clock->channel);
|
|
case CYHAL_CLOCK_BLOCK_PUMP:
|
|
return Cy_SysClk_ClkPumpGetFrequency();
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
return Cy_SysClk_ClkTimerGetFrequency();
|
|
case CYHAL_CLOCK_BLOCK_LF:
|
|
return _cyhal_clock_get_lf_frequency();
|
|
case CYHAL_CLOCK_BLOCK_BAK:
|
|
{
|
|
cy_en_clkbak_in_sources_t src = Cy_SysClk_ClkBakGetSource();
|
|
#if SRSS_BACKUP_PRESENT
|
|
if (src == CY_SYSCLK_BAK_IN_WCO)
|
|
return CY_SYSCLK_WCO_FREQ;
|
|
else
|
|
#endif
|
|
return _cyhal_clock_get_lf_frequency();
|
|
}
|
|
case CYHAL_CLOCK_BLOCK_FAST:
|
|
return Cy_SysClk_ClkFastGetFrequency();
|
|
case CYHAL_CLOCK_BLOCK_PERI:
|
|
return Cy_SysClk_ClkPeriGetFrequency();
|
|
case CYHAL_CLOCK_BLOCK_SLOW:
|
|
return Cy_SysClk_ClkSlowGetFrequency();
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT:
|
|
return Cy_SysClk_PeriphGetFrequency((cy_en_divider_types_t)clock->block, clock->channel);
|
|
case CYHAL_CLOCK_BLOCK_ALT_SYS_TICK:
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
cy_rslt_t cyhal_clock_set_frequency(cyhal_clock_t *clock, uint32_t hz, const cyhal_clock_tolerance_t *tolerance)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
switch (clock->block)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_EXT:
|
|
Cy_SysClk_ExtClkSetFrequency(hz);
|
|
return CY_RSLT_SUCCESS;
|
|
case CYHAL_CLOCK_BLOCK_FLL:
|
|
return _cyhal_clock_set_fll_freq(hz);
|
|
#if (SRSS_NUM_PLL > 0)
|
|
case CYHAL_CLOCK_BLOCK_PLL:
|
|
return _cyhal_clock_set_pll_freq(clock->channel + 1, hz);
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MF:
|
|
{
|
|
uint32_t div;
|
|
cy_rslt_t rslt = _cyhal_clock_compute_div(CY_SYSCLK_MFO_FREQ, hz, 8, tolerance, &div);
|
|
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
Cy_SysClk_ClkMfSetDivider(div);
|
|
|
|
return rslt;
|
|
}
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_FAST:
|
|
case CYHAL_CLOCK_BLOCK_PERI:
|
|
{
|
|
uint32_t div;
|
|
uint32_t input_hz = Cy_SysClk_ClkHfGetFrequency(0);
|
|
cy_rslt_t rslt = _cyhal_clock_compute_div(input_hz, hz, 8, tolerance, &div);
|
|
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
{
|
|
if (CYHAL_CLOCK_BLOCK_PERI == clock->block)
|
|
Cy_SysClk_ClkPeriSetDivider((uint8_t)(div - 1));
|
|
else
|
|
Cy_SysClk_ClkFastSetDivider((uint8_t)(div - 1));
|
|
|
|
SystemCoreClockUpdate();
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
case CYHAL_CLOCK_BLOCK_SLOW:
|
|
{
|
|
uint32_t div;
|
|
uint32_t input_hz = Cy_SysClk_ClkPeriGetFrequency();
|
|
cy_rslt_t rslt = _cyhal_clock_compute_div(input_hz, hz, 8, tolerance, &div);
|
|
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
{
|
|
Cy_SysClk_ClkSlowSetDivider((uint8_t)(div - 1));
|
|
SystemCoreClockUpdate();
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT:
|
|
{
|
|
uint32_t div;
|
|
uint32_t input_hz = Cy_SysClk_ClkPeriGetFrequency();
|
|
uint32_t bits = (clock->block == CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT) ? 8 : 16;
|
|
cy_rslt_t rslt = _cyhal_clock_compute_div(input_hz, hz, bits, tolerance, &div);
|
|
return (CY_RSLT_SUCCESS == rslt)
|
|
? Cy_SysClk_PeriphSetDivider((cy_en_divider_types_t)clock->block, clock->channel, (div - 1))
|
|
: rslt;
|
|
}
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT:
|
|
{
|
|
uint32_t div;
|
|
uint32_t input_hz = Cy_SysClk_ClkPeriGetFrequency();
|
|
// Multiply input by 32 so we can treat the 5 fractional bits as though they are extentions of the integer divider
|
|
// Leave the the desired frequency alone, so we can just strip out the integer & fractional bits at the end.
|
|
uint32_t bits = (clock->block == CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT) ? 21 : 29; // Integer bits + 5
|
|
cy_rslt_t rslt = _cyhal_clock_compute_div(input_hz << 5, hz, bits, tolerance, &div);
|
|
if (CY_RSLT_SUCCESS == rslt)
|
|
{
|
|
uint32_t div_int = (div >> 5) - 1;
|
|
uint32_t div_frac = div & 0x1F;
|
|
return Cy_SysClk_PeriphSetFracDivider((cy_en_divider_types_t)clock->block, clock->channel, div_int, div_frac);
|
|
}
|
|
else
|
|
return rslt;
|
|
}
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return CYHAL_CLOCK_RSLT_ERR_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
cy_rslt_t cyhal_clock_set_divider(cyhal_clock_t *clock, uint32_t divider)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
switch (clock->block)
|
|
{
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MF:
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_FAST:
|
|
case CYHAL_CLOCK_BLOCK_PERI:
|
|
case CYHAL_CLOCK_BLOCK_SLOW:
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
if (divider <= 256)
|
|
{
|
|
uint32_t divVal = divider - 1;
|
|
switch ((uint8_t)clock->block)
|
|
{
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MF:
|
|
Cy_SysClk_ClkMfSetDivider(divVal);
|
|
return CY_RSLT_SUCCESS;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_FAST:
|
|
Cy_SysClk_ClkFastSetDivider((uint8_t)divVal);
|
|
SystemCoreClockUpdate();
|
|
return CY_RSLT_SUCCESS;
|
|
case CYHAL_CLOCK_BLOCK_SLOW:
|
|
Cy_SysClk_ClkSlowSetDivider((uint8_t)divVal);
|
|
SystemCoreClockUpdate();
|
|
return CY_RSLT_SUCCESS;
|
|
case CYHAL_CLOCK_BLOCK_PERI:
|
|
Cy_SysClk_ClkPeriSetDivider((uint8_t)divVal);
|
|
SystemCoreClockUpdate();
|
|
return CY_RSLT_SUCCESS;
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
Cy_SysClk_ClkTimerSetDivider((uint8_t)divVal);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
}
|
|
return CYHAL_CLOCK_RSLT_ERR_FREQ;
|
|
|
|
case CYHAL_CLOCK_BLOCK_HF:
|
|
return _cyhal_clock_set_hfclk_div(clock->channel, divider);
|
|
case CYHAL_CLOCK_BLOCK_PUMP:
|
|
{
|
|
cy_en_clkpump_divide_t divVal;
|
|
switch (divider)
|
|
{
|
|
case 1:
|
|
divVal = CY_SYSCLK_PUMP_NO_DIV;
|
|
break;
|
|
case 2:
|
|
divVal = CY_SYSCLK_PUMP_DIV_2;
|
|
break;
|
|
case 4:
|
|
divVal = CY_SYSCLK_PUMP_DIV_4;
|
|
break;
|
|
case 8:
|
|
divVal = CY_SYSCLK_PUMP_DIV_8;
|
|
break;
|
|
case 16:
|
|
divVal = CY_SYSCLK_PUMP_DIV_16;
|
|
break;
|
|
default:
|
|
return CYHAL_CLOCK_RSLT_ERR_FREQ;
|
|
}
|
|
Cy_SysClk_ClkPumpSetDivider(divVal);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT:
|
|
return Cy_SysClk_PeriphSetDivider((cy_en_divider_types_t)clock->block, clock->channel, divider - 1);
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT:
|
|
return Cy_SysClk_PeriphSetFracDivider((cy_en_divider_types_t)clock->block, clock->channel, divider - 1, 0);
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return CYHAL_CLOCK_RSLT_ERR_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
cy_rslt_t cyhal_clock_get_sources(const cyhal_clock_t *clock, const cyhal_resource_inst_t **sources[], uint32_t *count)
|
|
{
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_PATHMUX[] =
|
|
{
|
|
&CYHAL_CLOCK_IMO,
|
|
#if SRSS_ECO_PRESENT
|
|
&CYHAL_CLOCK_ECO,
|
|
#endif
|
|
&CYHAL_CLOCK_EXT,
|
|
#if SRSS_ALTHF_PRESENT
|
|
&CYHAL_CLOCK_ALTHF,
|
|
#endif
|
|
&CYHAL_CLOCK_ILO,
|
|
#if SRSS_PILO_PRESENT
|
|
&CYHAL_CLOCK_PILO,
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
&CYHAL_CLOCK_WCO,
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
&CYHAL_CLOCK_ALTLF,
|
|
#endif
|
|
};
|
|
#if SRSS_MFO_PRESENT
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_MFO[] =
|
|
{
|
|
&CYHAL_CLOCK_IMO,
|
|
};
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_MF[] =
|
|
{
|
|
&CYHAL_CLOCK_MFO,
|
|
};
|
|
#endif
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_SLOW[] =
|
|
{
|
|
&CYHAL_CLOCK_PERI,
|
|
};
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_FAST[] =
|
|
{
|
|
&CYHAL_CLOCK_HF[0],
|
|
};
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_TIMER[] =
|
|
{
|
|
&CYHAL_CLOCK_IMO,
|
|
&CYHAL_CLOCK_HF[0],
|
|
};
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_ALT_SYS_TICK[] =
|
|
{
|
|
&CYHAL_CLOCK_IMO,
|
|
#if SRSS_ECO_PRESENT
|
|
&CYHAL_CLOCK_ECO,
|
|
#endif
|
|
&CYHAL_CLOCK_TIMER,
|
|
&CYHAL_CLOCK_LF,
|
|
&CYHAL_CLOCK_FAST,
|
|
&CYHAL_CLOCK_SLOW,
|
|
};
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_BAK[] =
|
|
{
|
|
&CYHAL_CLOCK_LF,
|
|
#if SRSS_BACKUP_PRESENT
|
|
&CYHAL_CLOCK_WCO,
|
|
#endif
|
|
};
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_LF[] =
|
|
{
|
|
&CYHAL_CLOCK_ILO,
|
|
#if SRSS_PILO_PRESENT
|
|
&CYHAL_CLOCK_PILO,
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
&CYHAL_CLOCK_WCO,
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
&CYHAL_CLOCK_ALTLF,
|
|
#endif
|
|
};
|
|
static const cyhal_resource_inst_t *_CYHAL_CLOCK_SOURCE_HF[] =
|
|
{
|
|
&CYHAL_CLOCK_FLL,
|
|
#if (SRSS_NUM_PLL > 0)
|
|
&CYHAL_CLOCK_PLL[0],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 1)
|
|
&CYHAL_CLOCK_PLL[1],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 2)
|
|
&CYHAL_CLOCK_PLL[2],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 3)
|
|
&CYHAL_CLOCK_PLL[3],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 4)
|
|
&CYHAL_CLOCK_PLL[4],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 5)
|
|
&CYHAL_CLOCK_PLL[5],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 6)
|
|
&CYHAL_CLOCK_PLL[6],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 7)
|
|
&CYHAL_CLOCK_PLL[7],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 8)
|
|
&CYHAL_CLOCK_PLL[8],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 9)
|
|
&CYHAL_CLOCK_PLL[9],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 10)
|
|
&CYHAL_CLOCK_PLL[10],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 11)
|
|
&CYHAL_CLOCK_PLL[11],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 12)
|
|
&CYHAL_CLOCK_PLL[12],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 13)
|
|
&CYHAL_CLOCK_PLL[13],
|
|
#endif
|
|
#if (SRSS_NUM_PLL > 14)
|
|
&CYHAL_CLOCK_PLL[14],
|
|
#endif
|
|
&CYHAL_CLOCK_PATHMUX[0],
|
|
#if (SRSS_NUM_CLKPATH > 1)
|
|
&CYHAL_CLOCK_PATHMUX[1],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 2)
|
|
&CYHAL_CLOCK_PATHMUX[2],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 3)
|
|
&CYHAL_CLOCK_PATHMUX[3],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 4)
|
|
&CYHAL_CLOCK_PATHMUX[4],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 5)
|
|
&CYHAL_CLOCK_PATHMUX[5],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 6)
|
|
&CYHAL_CLOCK_PATHMUX[6],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 7)
|
|
&CYHAL_CLOCK_PATHMUX[7],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 8)
|
|
&CYHAL_CLOCK_PATHMUX[8],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 9)
|
|
&CYHAL_CLOCK_PATHMUX[9],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 10)
|
|
&CYHAL_CLOCK_PATHMUX[10],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 11)
|
|
&CYHAL_CLOCK_PATHMUX[11],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 12)
|
|
&CYHAL_CLOCK_PATHMUX[12],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 13)
|
|
&CYHAL_CLOCK_PATHMUX[13],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 14)
|
|
&CYHAL_CLOCK_PATHMUX[14],
|
|
#endif
|
|
#if (SRSS_NUM_CLKPATH > 15)
|
|
&CYHAL_CLOCK_PATHMUX[15],
|
|
#endif
|
|
};
|
|
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
switch (clock->block)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_IMO:
|
|
#if SRSS_ECO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ECO:
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_EXT:
|
|
#if SRSS_ALTHF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTHF:
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTLF:
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_ILO:
|
|
#if SRSS_PILO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_PILO:
|
|
#endif
|
|
#if SRSS_BACKUP_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_WCO:
|
|
*count = 0;
|
|
break;
|
|
#endif
|
|
#if SRSS_MFO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_MFO:
|
|
*sources = _CYHAL_CLOCK_SOURCE_MFO;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_MFO) / sizeof(_CYHAL_CLOCK_SOURCE_MFO[0]);
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_MF:
|
|
*sources = _CYHAL_CLOCK_SOURCE_MF;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_MF) / sizeof(_CYHAL_CLOCK_SOURCE_MF[0]);
|
|
break;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_PATHMUX:
|
|
*sources = _CYHAL_CLOCK_SOURCE_PATHMUX;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_PATHMUX) / sizeof(_CYHAL_CLOCK_SOURCE_PATHMUX[0]);
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_FLL:
|
|
*sources = &(_CYHAL_CLOCK_SOURCE_HF[1 + SRSS_NUM_PLL]); /* PATHMUX[0] entry is after the FLL/PLLs */
|
|
*count = 1;
|
|
break;
|
|
#if (SRSS_NUM_PLL > 0)
|
|
case CYHAL_CLOCK_BLOCK_PLL:
|
|
*sources = &(_CYHAL_CLOCK_SOURCE_HF[2 + SRSS_NUM_PLL + clock->channel]); /* PATHMUX[n] entry is after the FLL/PLLs + 1 for FLL path */
|
|
*count = 1;
|
|
break;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_LF:
|
|
*sources = _CYHAL_CLOCK_SOURCE_LF;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_LF) / sizeof(_CYHAL_CLOCK_SOURCE_LF[0]);
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_HF:
|
|
case CYHAL_CLOCK_BLOCK_PUMP:
|
|
*sources = _CYHAL_CLOCK_SOURCE_HF;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_HF) / sizeof(_CYHAL_CLOCK_SOURCE_HF[0]);
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_BAK:
|
|
*sources = _CYHAL_CLOCK_SOURCE_BAK;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_BAK) / sizeof(_CYHAL_CLOCK_SOURCE_BAK[0]);
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_FAST:
|
|
case CYHAL_CLOCK_BLOCK_PERI:
|
|
*sources = _CYHAL_CLOCK_SOURCE_FAST;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_FAST) / sizeof(_CYHAL_CLOCK_SOURCE_FAST[0]);
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
*sources = _CYHAL_CLOCK_SOURCE_TIMER;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_TIMER) / sizeof(_CYHAL_CLOCK_SOURCE_TIMER[0]);
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_SLOW:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_8BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_16_5BIT:
|
|
case CYHAL_CLOCK_BLOCK_PERIPHERAL_24_5BIT:
|
|
*sources = _CYHAL_CLOCK_SOURCE_SLOW;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_SLOW) / sizeof(_CYHAL_CLOCK_SOURCE_SLOW[0]);
|
|
break;
|
|
case CYHAL_CLOCK_BLOCK_ALT_SYS_TICK:
|
|
*sources = _CYHAL_CLOCK_SOURCE_ALT_SYS_TICK;
|
|
*count = sizeof(_CYHAL_CLOCK_SOURCE_ALT_SYS_TICK) / sizeof(_CYHAL_CLOCK_SOURCE_ALT_SYS_TICK[0]);
|
|
break;
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
*count = 0;
|
|
return CYHAL_CLOCK_RSLT_ERR_RESOURCE;
|
|
}
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
|
|
cy_rslt_t cyhal_clock_set_source(cyhal_clock_t *clock, const cyhal_clock_t *source)
|
|
{
|
|
CY_ASSERT(NULL != clock && NULL != source);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
switch (clock->block)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_HF:
|
|
return _cyhal_clock_set_hfclk_source(clock->channel, source);
|
|
case CYHAL_CLOCK_BLOCK_PUMP:
|
|
if (source->block == CYHAL_CLOCK_BLOCK_PATHMUX || source->block == CYHAL_CLOCK_BLOCK_FLL)
|
|
{
|
|
Cy_SysClk_ClkPumpSetSource((cy_en_clkpump_in_sources_t)source->channel);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
else if (source->block == CYHAL_CLOCK_BLOCK_PLL)
|
|
{
|
|
Cy_SysClk_ClkPumpSetSource((cy_en_clkpump_in_sources_t)(source->channel + 1));
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
else
|
|
return CYHAL_CLOCK_RSLT_ERR_SOURCE;
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
if (source->block == CYHAL_CLOCK_BLOCK_IMO)
|
|
{
|
|
Cy_SysClk_ClkTimerSetSource(CY_SYSCLK_CLKTIMER_IN_IMO);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
else if (source->block == CYHAL_CLOCK_BLOCK_HF && source->channel == 0)
|
|
{
|
|
Cy_SysClk_ClkTimerSetSource(CY_SYSCLK_CLKTIMER_IN_HF0_NODIV);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
return CYHAL_CLOCK_RSLT_ERR_SOURCE;
|
|
case CYHAL_CLOCK_BLOCK_PATHMUX:
|
|
return _cyhal_clock_set_pathmux_source(clock->channel, source->block);
|
|
case CYHAL_CLOCK_BLOCK_LF:
|
|
switch (source->block)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_ILO:
|
|
Cy_SysClk_ClkLfSetSource(CY_SYSCLK_CLKLF_IN_ILO);
|
|
return CY_RSLT_SUCCESS;
|
|
#if SRSS_BACKUP_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_WCO:
|
|
Cy_SysClk_ClkLfSetSource(CY_SYSCLK_CLKLF_IN_WCO);
|
|
return CY_RSLT_SUCCESS;
|
|
#endif
|
|
#if SRSS_ALTLF_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ALTLF:
|
|
Cy_SysClk_ClkLfSetSource(CY_SYSCLK_CLKLF_IN_ALTLF);
|
|
return CY_RSLT_SUCCESS;
|
|
#endif
|
|
#if SRSS_PILO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_PILO:
|
|
Cy_SysClk_ClkLfSetSource(CY_SYSCLK_CLKLF_IN_PILO);
|
|
return CY_RSLT_SUCCESS;
|
|
#endif
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return CYHAL_CLOCK_RSLT_ERR_SOURCE;
|
|
}
|
|
case CYHAL_CLOCK_BLOCK_BAK:
|
|
if (source->block == CYHAL_CLOCK_BLOCK_LF)
|
|
{
|
|
Cy_SysClk_ClkBakSetSource(CY_SYSCLK_BAK_IN_CLKLF);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
#if SRSS_BACKUP_PRESENT
|
|
else if (source->block == CYHAL_CLOCK_BLOCK_WCO)
|
|
{
|
|
Cy_SysClk_ClkBakSetSource(CY_SYSCLK_BAK_IN_WCO);
|
|
return CY_RSLT_SUCCESS;
|
|
}
|
|
#endif
|
|
return CYHAL_CLOCK_RSLT_ERR_SOURCE;
|
|
case CYHAL_CLOCK_BLOCK_ALT_SYS_TICK:
|
|
switch (source->block)
|
|
{
|
|
case CYHAL_CLOCK_BLOCK_LF:
|
|
Cy_SysTick_SetClockSource(CY_SYSTICK_CLOCK_SOURCE_CLK_LF);
|
|
return CY_RSLT_SUCCESS;
|
|
case CYHAL_CLOCK_BLOCK_IMO:
|
|
Cy_SysTick_SetClockSource(CY_SYSTICK_CLOCK_SOURCE_CLK_IMO);
|
|
return CY_RSLT_SUCCESS;
|
|
#if SRSS_ECO_PRESENT
|
|
case CYHAL_CLOCK_BLOCK_ECO:
|
|
Cy_SysTick_SetClockSource(CY_SYSTICK_CLOCK_SOURCE_CLK_ECO);
|
|
return CY_RSLT_SUCCESS;
|
|
#endif
|
|
case CYHAL_CLOCK_BLOCK_TIMER:
|
|
Cy_SysTick_SetClockSource(CY_SYSTICK_CLOCK_SOURCE_CLK_TIMER);
|
|
return CY_RSLT_SUCCESS;
|
|
case CYHAL_CLOCK_BLOCK_FAST:
|
|
case CYHAL_CLOCK_BLOCK_SLOW:
|
|
Cy_SysTick_SetClockSource(CY_SYSTICK_CLOCK_SOURCE_CLK_CPU);
|
|
return CY_RSLT_SUCCESS;
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return CYHAL_CLOCK_RSLT_ERR_SOURCE;
|
|
}
|
|
default:
|
|
CY_ASSERT(false); //Unhandled clock
|
|
return CYHAL_CLOCK_RSLT_ERR_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
void cyhal_clock_free(cyhal_clock_t *clock)
|
|
{
|
|
CY_ASSERT(NULL != clock);
|
|
CY_ASSERT(_cyhal_utils_is_new_clock_format(clock));
|
|
|
|
cyhal_resource_inst_t rsc = { CYHAL_RSC_CLOCK, clock->block, clock->channel };
|
|
cyhal_hwmgr_free(&rsc);
|
|
clock->reserved = false;
|
|
}
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|