drivers: clock_control: nrf: Make use of related nrfx drivers

Update the driver implementation to use nrfx_clock and nrfx_power
drivers. Update also revisions of the hal_nordic and nrf_hw_models
modules, so that it is actually possible to use those drivers.

Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
Krzysztof Chruscinski 2020-08-10 13:38:29 +02:00 committed by Carles Cufí
parent d2027b3b98
commit d8da2e59c8
7 changed files with 119 additions and 175 deletions

View File

@ -14,6 +14,11 @@ config BOARD_NRF52_BSIM
# of it), so that the corresponding driver becomes available (see
# dependencies of the ENTROPY_NRF5_RNG option).
select HAS_HW_NRF_RNG
# Do the same for the CLOCK and POWER peripherals, so that the nrfx
# drivers for them can be used.
select HAS_HW_NRF_CLOCK
select HAS_HW_NRF_POWER
select HAS_NRFX
help
Will produce a console Linux process which can be executed natively.
It needs the BabbleSim simulator both in compile time and to execute

View File

@ -14,6 +14,8 @@ menuconfig CLOCK_CONTROL_NRF
bool "NRF Clock controller support"
depends on SOC_COMPATIBLE_NRF
depends on !CLOCK_CONTROL_NRF_FORCE_ALT
select NRFX_CLOCK
select NRFX_POWER
default y
help
Enable support for the Nordic Semiconductor nRFxx series SoC clock

View File

@ -7,7 +7,7 @@
#include <drivers/clock_control.h>
#include "nrf_clock_calibration.h"
#include <drivers/clock_control/nrf_clock_control.h>
#include <hal/nrf_clock.h>
#include <nrfx_clock.h>
#include <logging/log.h>
#include <stdlib.h>
@ -109,7 +109,7 @@ static void start_hw_cal(void)
*(volatile uint32_t *)0x40000C34 = 0x00000002;
}
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_CAL);
nrfx_clock_calibration_start();
calib_skip_cnt = CONFIG_CLOCK_CONTROL_NRF_CALIBRATION_MAX_SKIP;
}
@ -166,19 +166,6 @@ static void cal_hf_callback(struct onoff_manager *mgr,
}
}
static void on_hw_cal_done(void)
{
/* Workaround for Errata 192 */
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF52X)) {
*(volatile uint32_t *)0x40000C34 = 0x00000000;
}
total_cnt++;
LOG_DBG("Calibration done.");
start_cycle();
}
/* Convert sensor value to 0.25'C units. */
static inline int16_t sensor_value_to_temp_unit(struct sensor_value *val)
{
@ -249,12 +236,6 @@ static inline struct device *temp_device(void)
void z_nrf_clock_calibration_init(struct onoff_manager *onoff_mgrs)
{
/* Anomaly 36: After watchdog timeout reset, CPU lockup reset, soft
* reset, or pin reset EVENTS_DONE and EVENTS_CTTO are not reset.
*/
nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_DONE);
nrf_clock_int_enable(NRF_CLOCK, NRF_CLOCK_INT_DONE_MASK);
mgrs = onoff_mgrs;
total_cnt = 0;
total_skips_cnt = 0;
@ -298,12 +279,12 @@ void z_nrf_clock_calibration_lfclk_stopped(void)
LOG_DBG("Calibration stopped");
}
void z_nrf_clock_calibration_isr(void)
void z_nrf_clock_calibration_done_handler(void)
{
if (nrf_clock_event_check(NRF_CLOCK, NRF_CLOCK_EVENT_DONE)) {
nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_DONE);
on_hw_cal_done();
}
total_cnt++;
LOG_DBG("Calibration done.");
start_cycle();
}
int z_nrf_clock_calibration_count(void)

View File

@ -20,11 +20,11 @@ extern "C" {
void z_nrf_clock_calibration_init(struct onoff_manager *mgrs);
/**
* @brief Calibration interrupts handler
* @brief Calibration done handler
*
* Must be called from clock interrupt context.
* Must be called from clock event handler.
*/
void z_nrf_clock_calibration_isr(void);
void z_nrf_clock_calibration_done_handler(void);
/**
* @brief Notify calibration module about LF clock start

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019 Nordic Semiconductor ASA
* Copyright (c) 2016-2020 Nordic Semiconductor ASA
* Copyright (c) 2016 Vinayak Kariappa Chettimada
*
* SPDX-License-Identifier: Apache-2.0
@ -10,8 +10,9 @@
#include <drivers/clock_control.h>
#include <drivers/clock_control/nrf_clock_control.h>
#include "nrf_clock_calibration.h"
#include <nrfx_clock.h>
#include <nrfx_power.h>
#include <logging/log.h>
#include <hal/nrf_power.h>
#include <shell/shell.h>
LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
@ -79,33 +80,6 @@ static atomic_t hfclk_users;
static uint64_t hf_start_tstamp;
static uint64_t hf_stop_tstamp;
/* Return true if given event has enabled interrupt and is triggered. Event
* is cleared.
*/
static bool clock_event_check_and_clean(nrf_clock_event_t evt, uint32_t intmask)
{
bool ret = nrf_clock_event_check(NRF_CLOCK, evt) &&
nrf_clock_int_enable_check(NRF_CLOCK, intmask);
if (ret) {
nrf_clock_event_clear(NRF_CLOCK, evt);
}
return ret;
}
static void clock_irqs_enable(void)
{
nrf_clock_int_enable(NRF_CLOCK,
(NRF_CLOCK_INT_HF_STARTED_MASK |
NRF_CLOCK_INT_LF_STARTED_MASK |
COND_CODE_1(CONFIG_USB_NRFX,
(NRF_POWER_INT_USBDETECTED_MASK |
NRF_POWER_INT_USBREMOVED_MASK |
NRF_POWER_INT_USBPWRRDY_MASK),
(0))));
}
static struct nrf_clock_control_sub_data *get_sub_data(struct device *dev,
enum clock_control_nrf_type type)
{
@ -229,7 +203,7 @@ static void lfclk_start(void)
anomaly_132_workaround();
}
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART);
nrfx_clock_lfclk_start();
}
static void lfclk_stop(void)
@ -238,8 +212,7 @@ static void lfclk_stop(void)
z_nrf_clock_calibration_lfclk_stopped();
}
nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_LFCLKSTARTED);
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTOP);
nrfx_clock_lfclk_stop();
}
static void hfclk_start(void)
@ -248,7 +221,7 @@ static void hfclk_start(void)
hf_start_tstamp = k_uptime_get();
}
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART);
nrfx_clock_hfclk_start();
}
static void hfclk_stop(void)
@ -257,8 +230,7 @@ static void hfclk_stop(void)
hf_stop_tstamp = k_uptime_get();
}
nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED);
nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP);
nrfx_clock_hfclk_stop();
}
static uint32_t *get_hf_flags(void)
@ -276,8 +248,7 @@ static void generic_hfclk_start(void)
hfclk_users |= HF_USER_GENERIC;
if (hfclk_users & HF_USER_BT) {
(void)nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_HFCLK,
&type);
(void)nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, &type);
if (type == NRF_CLOCK_HFCLK_HIGH_ACCURACY) {
already_started = true;
/* Set on state in case clock interrupt comes and we
@ -458,8 +429,7 @@ static void lfclk_spinwait(nrf_clock_lfclk_t t)
nrf_clock_domain_t d = NRF_CLOCK_DOMAIN_LFCLK;
nrf_clock_lfclk_t type;
while (!(nrf_clock_is_running(NRF_CLOCK, d, (void *)&type)
&& (type == t))) {
while (!(nrfx_clock_is_running(d, (void *)&type) && (type == t))) {
/* empty */
}
}
@ -497,18 +467,69 @@ void z_nrf_clock_control_lf_on(enum nrf_lfclk_start_mode start_mode)
}
}
/* Note: this function has public linkage, and MUST have this
* particular name. The platform architecture itself doesn't care,
* but there is a test (tests/kernel/arm_irq_vector_table) that needs
* to find it to it can set it in a custom vector table. Should
* probably better abstract that at some point (e.g. query and reset
* it by pointer at runtime, maybe?) so we don't have this leaky
* symbol.
*/
void nrf_power_clock_isr(void *arg);
static void clock_event_handler(nrfx_clock_evt_type_t event)
{
struct device *dev = DEVICE_GET(clock_nrf);
switch (event) {
case NRFX_CLOCK_EVT_HFCLK_STARTED:
{
struct nrf_clock_control_sub_data *data =
get_sub_data(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK);
/* Check needed due to anomaly 201:
* HFCLKSTARTED may be generated twice.
*/
if (GET_STATUS(data->flags) == CLOCK_CONTROL_STATUS_STARTING) {
clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK);
}
break;
}
case NRFX_CLOCK_EVT_LFCLK_STARTED:
if (IS_ENABLED(
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
z_nrf_clock_calibration_lfclk_started();
}
clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_LFCLK);
break;
case NRFX_CLOCK_EVT_CAL_DONE:
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
z_nrf_clock_calibration_done_handler();
}
break;
default:
__ASSERT_NO_MSG(0);
break;
}
}
#if defined(CONFIG_USB_NRFX)
static void usb_event_handler(nrfx_power_usb_evt_t event)
{
extern void usb_dc_nrfx_power_event_callback(nrf_power_event_t evt);
switch (event) {
case NRFX_POWER_USB_EVT_DETECTED:
usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBDETECTED);
break;
case NRFX_POWER_USB_EVT_REMOVED:
usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBREMOVED);
break;
case NRFX_POWER_USB_EVT_READY:
usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBPWRRDY);
break;
default:
__ASSERT_NO_MSG(0);
break;
}
}
#endif
static int clk_init(struct device *dev)
{
nrfx_err_t nrfx_err;
int err;
static const struct onoff_transitions transitions = {
.start = onoff_start,
@ -516,11 +537,22 @@ static int clk_init(struct device *dev)
};
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
nrf_power_clock_isr, 0, 0);
nrfx_isr, nrfx_power_clock_irq_handler, 0);
irq_enable(DT_INST_IRQN(0));
nrf_clock_lf_src_set(NRF_CLOCK, CLOCK_CONTROL_NRF_K32SRC);
#if defined(CONFIG_USB_NRFX) && defined(CONFIG_SOC_SERIES_NRF53X)
/* Use CLOCK/POWER priority for compatibility with other series where
* USB events are handled by CLOCK interrupt handler.
*/
IRQ_CONNECT(USBREGULATOR_IRQn, DT_INST_IRQ(0, priority),
nrfx_usbreg_irq_handler, 0, 0);
irq_enable(USBREGULATOR_IRQn);
#endif
nrfx_err = nrfx_clock_init(clock_event_handler);
if (nrfx_err != NRFX_SUCCESS) {
return -EIO;
}
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
struct nrf_clock_control_data *data = dev->data;
@ -528,7 +560,13 @@ static int clk_init(struct device *dev)
z_nrf_clock_calibration_init(data->mgr);
}
clock_irqs_enable();
nrfx_clock_enable();
static const nrfx_power_usbevt_config_t config = {
.handler = usb_event_handler
};
nrfx_power_usbevt_init(&config);
for (enum clock_control_nrf_type i = 0;
i < CLOCK_CONTROL_NRF_TYPE_COUNT; i++) {
@ -546,6 +584,7 @@ static int clk_init(struct device *dev)
return 0;
}
static const struct clock_control_driver_api clock_control_api = {
.on = api_blocking_start,
.off = api_stop,
@ -575,94 +614,13 @@ DEVICE_AND_API_INIT(clock_nrf, DT_INST_LABEL(0),
CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&clock_control_api);
#if defined(CONFIG_USB_NRFX)
static bool power_event_check_and_clean(nrf_power_event_t evt, uint32_t intmask)
{
bool ret = nrf_power_event_check(NRF_POWER, evt) &&
nrf_power_int_enable_check(NRF_POWER, intmask);
if (ret) {
nrf_power_event_clear(NRF_POWER, evt);
}
return ret;
}
#endif
static void usb_power_isr(void)
{
#if defined(CONFIG_USB_NRFX)
extern void usb_dc_nrfx_power_event_callback(nrf_power_event_t event);
if (power_event_check_and_clean(NRF_POWER_EVENT_USBDETECTED,
NRF_POWER_INT_USBDETECTED_MASK)) {
usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBDETECTED);
}
if (power_event_check_and_clean(NRF_POWER_EVENT_USBPWRRDY,
NRF_POWER_INT_USBPWRRDY_MASK)) {
usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBPWRRDY);
}
if (power_event_check_and_clean(NRF_POWER_EVENT_USBREMOVED,
NRF_POWER_INT_USBREMOVED_MASK)) {
usb_dc_nrfx_power_event_callback(NRF_POWER_EVENT_USBREMOVED);
}
#endif
}
void nrf_power_clock_isr(void *arg)
{
ARG_UNUSED(arg);
struct device *dev = DEVICE_GET(clock_nrf);
if (clock_event_check_and_clean(NRF_CLOCK_EVENT_HFCLKSTARTED,
NRF_CLOCK_INT_HF_STARTED_MASK)) {
struct nrf_clock_control_sub_data *data =
get_sub_data(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK);
/* Check needed due to anomaly 201:
* HFCLKSTARTED may be generated twice.
*
* Also software should be notified about clock being on only
* if generic request occured.
*/
if ((GET_STATUS(data->flags) == CLOCK_CONTROL_STATUS_STARTING)
&& (hfclk_users & HF_USER_GENERIC)) {
clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK);
}
}
if (clock_event_check_and_clean(NRF_CLOCK_EVENT_LFCLKSTARTED,
NRF_CLOCK_INT_LF_STARTED_MASK)) {
if (IS_ENABLED(
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
z_nrf_clock_calibration_lfclk_started();
}
clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_LFCLK);
}
usb_power_isr();
if (IS_ENABLED(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION)) {
z_nrf_clock_calibration_isr();
}
}
#ifdef CONFIG_USB_NRFX
void nrf5_power_usb_power_int_enable(bool enable)
{
uint32_t mask;
mask = NRF_POWER_INT_USBDETECTED_MASK |
NRF_POWER_INT_USBREMOVED_MASK |
NRF_POWER_INT_USBPWRRDY_MASK;
if (enable) {
nrf_power_int_enable(NRF_POWER, mask);
irq_enable(DT_INST_IRQN(0));
nrfx_power_usbevt_enable();
} else {
nrf_power_int_disable(NRF_POWER, mask);
nrfx_power_usbevt_disable();
}
}
#endif
@ -671,8 +629,7 @@ static int cmd_status(const struct shell *shell, size_t argc, char **argv)
{
nrf_clock_hfclk_t hfclk_src;
bool hf_status;
bool lf_status =
nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_LFCLK, NULL);
bool lf_status = nrfx_clock_is_running(NRF_CLOCK_DOMAIN_LFCLK, NULL);
struct onoff_manager *hf_mgr =
get_onoff_manager(DEVICE_GET(clock_nrf),
CLOCK_CONTROL_NRF_TYPE_HFCLK);
@ -683,8 +640,7 @@ static int cmd_status(const struct shell *shell, size_t argc, char **argv)
int key = irq_lock();
uint64_t now = k_uptime_get();
(void)nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_HFCLK,
(void *)&hfclk_src);
(void)nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, (void *)&hfclk_src);
hf_status = (hfclk_src == NRF_CLOCK_HFCLK_HIGH_ACCURACY);
abs_start = hf_start_tstamp;

View File

@ -186,16 +186,16 @@ typedef void (*vth)(void); /* Vector Table Handler */
* Note: qemu_cortex_m0 uses TIMER0 to implement system timer.
*/
void rtc_nrf_isr(void);
void nrf_power_clock_isr(void);
void nrfx_clock_irq_handler(void);
#if defined(CONFIG_SOC_SERIES_NRF51X) || defined(CONFIG_SOC_SERIES_NRF52X)
#if defined(CONFIG_BOARD_QEMU_CORTEX_M0)
void timer0_nrf_isr(void);
vth __irq_vector_table _irq_vector_table[] = {
nrf_power_clock_isr, 0, 0, 0, 0, 0, 0, 0, timer0_nrf_isr, isr0, isr1, isr2
nrfx_clock_irq_handler, 0, 0, 0, 0, 0, 0, 0, timer0_nrf_isr, isr0, isr1, isr2
};
#else
vth __irq_vector_table _irq_vector_table[] = {
nrf_power_clock_isr,
nrfx_clock_irq_handler,
isr0, isr1, isr2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
rtc_nrf_isr
@ -204,14 +204,14 @@ vth __irq_vector_table _irq_vector_table[] = {
#elif defined(CONFIG_SOC_SERIES_NRF53X) || defined(CONFIG_SOC_SERIES_NRF91X)
#ifndef CONFIG_SOC_NRF5340_CPUNET
vth __irq_vector_table _irq_vector_table[] = {
0, 0, 0, 0, 0, nrf_power_clock_isr, 0, 0,
0, 0, 0, 0, 0, nrfx_clock_irq_handler, 0, 0,
isr0, isr1, isr2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
rtc_nrf_isr
};
#else
vth __irq_vector_table _irq_vector_table[] = {
0, 0, 0, 0, 0, nrf_power_clock_isr, 0, 0,
0, 0, 0, 0, 0, nrfx_clock_irq_handler, 0, 0,
isr0, isr1, isr2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
rtc_nrf_isr

View File

@ -56,7 +56,7 @@ manifest:
revision: f1fa8241f8786198ba41155413243de36ed878a5
path: modules/hal/infineon
- name: hal_nordic
revision: 4be2a1eadc99511e0271b6de6e0be459a4cf0cef
revision: f32e904fb9ea0309f7319cf121dd22ad16233df0
path: modules/hal/nordic
- name: hal_openisa
revision: 40d049f69c50b58ea20473bee14cf93f518bf262
@ -126,7 +126,7 @@ manifest:
revision: 957d46bc3ce0d5f628f0d525196bb4db207672ee
- name: nrf_hw_models
path: modules/bsim_hw_models/nrf_hw_models
revision: 9e594dace1af29252903938064b8ecb1b8b77678
revision: f86079a7333968f0ba71fe1266e241295a4e9943
- name: hal_xtensa
revision: e7a57d0c252f9c5f3cab9d5ceadda8753cacee5b
path: modules/hal/xtensa