drivers: clock_control: nrf54h-lfclk: use values from BICR
The real, applicable and trusted values are the ones flashed into BICR. So, drop DT properties that replicate BICR and use runtime reads to BICR instead. Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
This commit is contained in:
parent
d5041aecec
commit
f267c339f7
3 changed files with 64 additions and 67 deletions
|
|
@ -15,7 +15,4 @@
|
|||
|
||||
&lfxo {
|
||||
status = "okay";
|
||||
accuracy-ppm = <20>;
|
||||
startup-time-us = <600000>;
|
||||
mode = "crystal";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "clock_control_nrf2_common.h"
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
|
||||
#include <hal/nrf_bicr.h>
|
||||
#include <nrfs_clock.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
|
@ -16,30 +17,25 @@ LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
|
|||
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
|
||||
"multiple instances not supported");
|
||||
|
||||
#define LFCLK_LFXO_NODE DT_INST_PHANDLE_BY_NAME(0, clocks, lfxo)
|
||||
#define LFCLK_HFXO_NODE DT_INST_PHANDLE_BY_NAME(0, clocks, hfxo)
|
||||
|
||||
#define LFCLK_HAS_LFXO DT_NODE_HAS_STATUS_OKAY(LFCLK_LFXO_NODE)
|
||||
|
||||
#define LFCLK_LFLPRC_ACCURACY DT_INST_PROP(0, lflprc_accuracy_ppm)
|
||||
#define LFCLK_LFRC_ACCURACY DT_INST_PROP(0, lfrc_accuracy_ppm)
|
||||
#define LFCLK_LFXO_ACCURACY DT_PROP(LFCLK_LFXO_NODE, accuracy_ppm)
|
||||
#define LFCLK_HFXO_ACCURACY DT_PROP(LFCLK_HFXO_NODE, accuracy_ppm)
|
||||
|
||||
#if LFCLK_HAS_LFXO
|
||||
#define LFCLK_MAX_ACCURACY LFCLK_LFXO_ACCURACY
|
||||
#else
|
||||
#define LFCLK_MAX_ACCURACY LFCLK_HFXO_ACCURACY
|
||||
#endif
|
||||
#define LFCLK_MAX_OPTS 5
|
||||
#define LFCLK_DEF_OPTS 3
|
||||
|
||||
#define NRFS_CLOCK_TIMEOUT K_MSEC(CONFIG_CLOCK_CONTROL_NRF2_NRFS_CLOCK_TIMEOUT_MS)
|
||||
|
||||
#define BICR (NRF_BICR_Type *)DT_REG_ADDR(DT_NODELABEL(bicr))
|
||||
|
||||
/* Clock options sorted from lowest to highest accuracy/precision */
|
||||
static const struct clock_options {
|
||||
static struct clock_options {
|
||||
uint16_t accuracy : 15;
|
||||
uint16_t precision : 1;
|
||||
nrfs_clock_src_t src;
|
||||
} clock_options[] = {
|
||||
} clock_options[LFCLK_MAX_OPTS] = {
|
||||
{
|
||||
.accuracy = LFCLK_LFLPRC_ACCURACY,
|
||||
.precision = 0,
|
||||
|
|
@ -56,43 +52,13 @@ static const struct clock_options {
|
|||
.precision = 1,
|
||||
.src = NRFS_CLOCK_SRC_LFCLK_SYNTH,
|
||||
},
|
||||
#if LFCLK_HAS_LFXO
|
||||
#if DT_ENUM_HAS_VALUE(LFCLK_LFXO_NODE, mode, crystal)
|
||||
{
|
||||
.accuracy = LFCLK_LFXO_ACCURACY,
|
||||
.src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE,
|
||||
},
|
||||
{
|
||||
.accuracy = LFCLK_LFXO_ACCURACY,
|
||||
.precision = 1,
|
||||
.src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE_HP,
|
||||
},
|
||||
#elif DT_ENUM_HAS_VALUE(LFCLK_LFXO_NODE, mode, external_sine)
|
||||
{
|
||||
.accuracy = LFCLK_LFXO_ACCURACY,
|
||||
.precision = 0,
|
||||
.src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE,
|
||||
},
|
||||
{
|
||||
.accuracy = LFCLK_LFXO_ACCURACY,
|
||||
.precision = 1,
|
||||
.src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE_HP,
|
||||
},
|
||||
#elif DT_ENUM_HAS_VALUE(LFCLK_LFXO_NODE, mode, external_square)
|
||||
{
|
||||
.accuracy = LFCLK_LFXO_ACCURACY,
|
||||
.precision = 0,
|
||||
.src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SQUARE,
|
||||
},
|
||||
#else
|
||||
#error "unsupported LFXO mode"
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct lfclk_dev_data {
|
||||
STRUCT_CLOCK_CONFIG(lfclk, ARRAY_SIZE(clock_options)) clk_cfg;
|
||||
struct k_timer timer;
|
||||
uint16_t max_accuracy;
|
||||
uint8_t clock_options_cnt;
|
||||
};
|
||||
|
||||
struct lfclk_dev_config {
|
||||
|
|
@ -156,10 +122,10 @@ static struct onoff_manager *lfclk_find_mgr(const struct device *dev,
|
|||
}
|
||||
|
||||
accuracy = spec->accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX
|
||||
? LFCLK_MAX_ACCURACY
|
||||
? dev_data->max_accuracy
|
||||
: spec->accuracy;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(clock_options); ++i) {
|
||||
for (int i = 0; i < dev_data->clock_options_cnt; ++i) {
|
||||
if ((accuracy &&
|
||||
accuracy < clock_options[i].accuracy) ||
|
||||
spec->precision > clock_options[i].precision) {
|
||||
|
|
@ -227,6 +193,7 @@ static int api_get_rate_lfclk(const struct device *dev,
|
|||
static int lfclk_init(const struct device *dev)
|
||||
{
|
||||
struct lfclk_dev_data *dev_data = dev->data;
|
||||
nrf_bicr_lfosc_mode_t lfosc_mode;
|
||||
nrfs_err_t res;
|
||||
|
||||
res = nrfs_clock_init(clock_evt_handler);
|
||||
|
|
@ -234,6 +201,58 @@ static int lfclk_init(const struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
dev_data->clock_options_cnt = LFCLK_DEF_OPTS;
|
||||
|
||||
lfosc_mode = nrf_bicr_lfosc_mode_get(BICR);
|
||||
|
||||
if (lfosc_mode == NRF_BICR_LFOSC_MODE_UNCONFIGURED ||
|
||||
lfosc_mode == NRF_BICR_LFOSC_MODE_DISABLED) {
|
||||
dev_data->max_accuracy = LFCLK_HFXO_ACCURACY;
|
||||
} else {
|
||||
int ret;
|
||||
|
||||
ret = lfosc_get_accuracy(&dev_data->max_accuracy);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("LFOSC enabled with invalid accuracy");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (lfosc_mode) {
|
||||
case NRF_BICR_LFOSC_MODE_CRYSTAL:
|
||||
clock_options[LFCLK_MAX_OPTS - 2].accuracy = dev_data->max_accuracy;
|
||||
clock_options[LFCLK_MAX_OPTS - 2].precision = 0;
|
||||
clock_options[LFCLK_MAX_OPTS - 2].src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE;
|
||||
|
||||
clock_options[LFCLK_MAX_OPTS - 1].accuracy = dev_data->max_accuracy;
|
||||
clock_options[LFCLK_MAX_OPTS - 1].precision = 1;
|
||||
clock_options[LFCLK_MAX_OPTS - 1].src = NRFS_CLOCK_SRC_LFCLK_XO_PIERCE_HP;
|
||||
|
||||
dev_data->clock_options_cnt += 2;
|
||||
break;
|
||||
case NRF_BICR_LFOSC_MODE_EXTSINE:
|
||||
clock_options[LFCLK_MAX_OPTS - 2].accuracy = dev_data->max_accuracy;
|
||||
clock_options[LFCLK_MAX_OPTS - 2].precision = 0;
|
||||
clock_options[LFCLK_MAX_OPTS - 2].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE;
|
||||
|
||||
clock_options[LFCLK_MAX_OPTS - 1].accuracy = dev_data->max_accuracy;
|
||||
clock_options[LFCLK_MAX_OPTS - 1].precision = 1;
|
||||
clock_options[LFCLK_MAX_OPTS - 1].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE_HP;
|
||||
|
||||
dev_data->clock_options_cnt += 2;
|
||||
break;
|
||||
case NRF_BICR_LFOSC_MODE_EXTSQUARE:
|
||||
clock_options[LFCLK_MAX_OPTS - 2].accuracy = dev_data->max_accuracy;
|
||||
clock_options[LFCLK_MAX_OPTS - 2].precision = 0;
|
||||
clock_options[LFCLK_MAX_OPTS - 2].src = NRFS_CLOCK_SRC_LFCLK_XO_EXT_SQUARE;
|
||||
|
||||
dev_data->clock_options_cnt += 1;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unexpected LFOSC mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
k_timer_init(&dev_data->timer, lfclk_update_timeout_handler, NULL);
|
||||
|
||||
return clock_config_init(&dev_data->clk_cfg,
|
||||
|
|
|
|||
|
|
@ -10,22 +10,3 @@ include: fixed-clock.yaml
|
|||
properties:
|
||||
clock-frequency:
|
||||
const: 32768
|
||||
|
||||
accuracy-ppm:
|
||||
type: int
|
||||
description: Clock accuracy in parts per million
|
||||
required: true
|
||||
|
||||
startup-time-us:
|
||||
type: int
|
||||
description: Clock startup time in micro seconds
|
||||
required: true
|
||||
|
||||
mode:
|
||||
type: string
|
||||
description: LFXO operational mode
|
||||
required: true
|
||||
enum:
|
||||
- "crystal"
|
||||
- "external-sine"
|
||||
- "external-square"
|
||||
|
|
|
|||
Loading…
Reference in a new issue