From 6d10f951d5c5ebae58f7c24df1066a479b68d5fa Mon Sep 17 00:00:00 2001 From: Victor Mignot Date: Thu, 24 Jul 2025 13:54:25 +0200 Subject: nrf52832: add clock driver --- src/clock.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/clock.c (limited to 'src/clock.c') diff --git a/src/clock.c b/src/clock.c new file mode 100644 index 0000000..5603693 --- /dev/null +++ b/src/clock.c @@ -0,0 +1,79 @@ +#include "clock.h" +#include "types.h" +#include "peripherals.h" + +#define WRITE_CLK_REG(reg, value) (WRITE_REGISTER(CLOCK, reg, value)) +#define READ_CLK_REG(reg) (READ_REGISTER(CLOCK, reg)) + +enum hfclk_src { + HFINT = 0, + HFXO = 1, +}; + +enum lfclk_src { + LFRC = 0, + LFXO = 1, + LFSYNT = 2, +}; + +/** + * Memory-mapped registers for the CLOCK peripheral with their offset from its base address, + * Check the nrf52832's manual for their description. + */ +enum clock_registers { + TASKS_HFCLKSTART = 0x000, + TASKS_HFCLKSTOP = 0x004, + TASKS_LFCLKSTART = 0x008, + TASKS_LFCLKSTOP = 0x00c, + TASKS_CAL = 0x010, + TASKS_CTSTART = 0x014, + TASKS_CTSTOP = 0x018, + EVENTS_HFCLKSTARTED = 0x100, + EVENTS_LFCLKSTARTED = 0x104, + EVENTS_DONE = 0x10c, + EVENTS_CTTO = 0x110, + INTENSET = 0x304, + INTENCLR = 0x308, + HFCLKRUN = 0x408, + HFCLKSTAT = 0x40c, + LFCLKRUN = 0x414, + LFCLKSTAT = 0x418, + LFCLKSRCCOPY = 0x41c, + LFCLKSRC = 0x518, + CTIV = 0x538, + TRACECONFIG = 0x55c, +}; + +static bool init_hfclk() { + /* We just assert that the source clock is running with the CPU internal clock + * as source */ + u32 hfclk_status = READ_CLK_REG(HFCLKSTAT); + int clk_src = hfclk_status & 0x1; + bool clk_running = (hfclk_status >> 16) & 0x1; + + return (clk_src == HFINT) && clk_running; +} + +static bool init_lfclk() { + bool clk_started = false; + enum lfclk_src src = LFRC; + + /* LFCLK use the LFRC clock by default, so it should be ready + * to be started directly */ + WRITE_CLK_REG(TASKS_LFCLKSTART, 0x1); + + /* Wait for the LFCLK to be started */ + /* TODO: We should rely on the IRQ for the LFCLKSTARTED event instead */ + do { + u32 lfclk_stat = READ_CLK_REG(LFCLKSTAT); + + clk_started = (lfclk_stat >> 16) & 0x1; + src = lfclk_stat & 0x2; + } while (!clk_started); + + return src == LFRC; +} + +bool init_clock() { + return init_hfclk() && init_lfclk(); +} -- cgit v1.2.3