summaryrefslogtreecommitdiff
path: root/src/oracle/clkrst_ref.c
blob: b35436cce4ac26491019740b6649227add720929 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/* ESP-IDF's own bus-clock and reset control, as the reference for src/hal/clkrst.zig.
 *
 * This suite exists because of a specific bug. `clkrst.zig` maps each peripheral to the register and
 * bit that gate and reset it, and that table is hand-written: the field macros do not say which
 * register they live in, so every row is a transcription from ESP-IDF's LL source. Two rows were
 * wrong. The second batch - timg0, timg1, systimer and twai0 - had their APB clock enables in
 * HP_SYS_CLKRST_PERI_CLK_CTRL21 instead of SOC_CLK_CTRL2, so `setClockEnabled` poked a bit of an
 * unrelated register.
 *
 * It survived a hardware test, which is the point. `examples/halcheck.zig` printed exactly the
 * expected `twai0 boot=0 on=1 off=0`, because the write and the read-back both went through the same
 * wrong address: a self-consistent test that would have passed with the chip unplugged.
 *
 * IDF reaches these bits by a completely independent path - its own generated struct definitions -
 * so comparing against it is the check that a read-back cannot be.
 */

/* IDF shadows every clock/reset LL function with a macro that references this identifier, which it
 * deliberately never defines, so that an unguarded call fails to compile: the only legal caller
 * holds a spinlock. There is no FreeRTOS here and core 1 is held in reset at power-on, so declaring
 * the name is exactly as safe as the lock would be. IDF's own bootloader does the same thing
 * (bootloader_support/src/bootloader_console.c:53). */
static int __DECLARE_RCC_ATOMIC_ENV __attribute__((unused));
/* IDF uses a second name for the same trick on the peripherals whose gate lives in a register shared
 * with the CPU's own clocking - systimer among them. Same reasoning applies. */
static int __DECLARE_RCC_RC_ATOMIC_ENV __attribute__((unused));

#include "hal/timg_ll.h"
#include "hal/systimer_ll.h"
#include "hal/uart_ll.h"

void oracle_clkrst_timg_bus_clock(unsigned group, int enable)
{
    _timg_ll_enable_bus_clock(group, enable != 0);
}

void oracle_clkrst_timg_reset(unsigned group)
{
    _timg_ll_reset_register(group);
}

void oracle_clkrst_systimer_bus_clock(int enable)
{
    systimer_ll_enable_bus_clock(enable != 0);
}

void oracle_clkrst_systimer_reset(void)
{
    systimer_ll_reset_register();
}

void oracle_clkrst_uart_bus_clock(unsigned port, int enable)
{
    _uart_ll_enable_bus_clock(port, enable != 0);
}