From 29032caf40b2f5f6d43daa95cc9f648368582ce4 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 19 Aug 2021 14:51:54 +0200 Subject: [PATCH] lx_emul: support CLK_OF_DECLARE initcall mechanism Clock providers such as drivers/clk/sunxi-ng/ccu-sun8i-r.c don't use regular init calls but declare their init functions via CLK_OF_DECLARE, which fill the __clk_of_table. Linux populates the table statically by using special sections declared in the linker script. In contrast, we populate the table by expanding the macro to global constructor functions. The __clk_of_table is then processed by the call of of_clk_init(NULL). Issue #4253 --- repos/dde_linux/src/include/lx_emul/init.h | 2 ++ .../src/include/lx_emul/shadow/linux/of.h | 27 +++++++++++++++++ repos/dde_linux/src/lib/lx_emul/clocksource.c | 29 ++++++++++++++++++- .../src/lib/lx_emul/shadow/drivers/clk/clk.c | 7 +++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 repos/dde_linux/src/include/lx_emul/shadow/linux/of.h diff --git a/repos/dde_linux/src/include/lx_emul/init.h b/repos/dde_linux/src/include/lx_emul/init.h index f8511008c1..cf37c47568 100644 --- a/repos/dde_linux/src/include/lx_emul/init.h +++ b/repos/dde_linux/src/include/lx_emul/init.h @@ -28,6 +28,8 @@ int lx_emul_init_task_function(void * dtb); extern void * lx_emul_init_task_struct; +void lx_emul_register_of_clk_initcall(char const *compat, void *fn); + #ifdef __cplusplus } #endif diff --git a/repos/dde_linux/src/include/lx_emul/shadow/linux/of.h b/repos/dde_linux/src/include/lx_emul/shadow/linux/of.h new file mode 100644 index 0000000000..78462e967e --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/shadow/linux/of.h @@ -0,0 +1,27 @@ +/* + * \brief Shadow copy of linux/of.h + * \author Norman Feske + * \date 2021-08-19 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _LX_EMUL__SHADOW__LINUX__OF_H_ +#define _LX_EMUL__SHADOW__LINUX__OF_H_ + +#include_next +#include + +#undef OF_DECLARE_1 + +#define OF_DECLARE_1(table, name, compat, fn) \ + static void __of_declare_initcall_##fn##name(void)__attribute__((constructor)); \ + static void __of_declare_initcall_##fn##name() { \ + lx_emul_register_of_##table##_initcall(compat, fn); }; + +#endif /* _LX_EMUL__SHADOW__LINUX__OF_H_ */ diff --git a/repos/dde_linux/src/lib/lx_emul/clocksource.c b/repos/dde_linux/src/lib/lx_emul/clocksource.c index 0ac39a5df4..046025c0d4 100644 --- a/repos/dde_linux/src/lib/lx_emul/clocksource.c +++ b/repos/dde_linux/src/lib/lx_emul/clocksource.c @@ -15,8 +15,10 @@ #include #include #include +#include #include #include +#include static u32 dde_timer_rate = 1000000; /* we use microseconds as rate */ @@ -93,6 +95,10 @@ void lx_emul_time_init() timecounter_init(&timecounter, &cyclecounter, start_count); clockevents_config_and_register(&clock_event_device, dde_timer_rate, 0xf, 0x7fffffff); sched_clock_register(dde_timer_read_counter, 64, dde_timer_rate); + + /* execute setup calls of clock providers in __clk_of_table */ + of_clk_init(NULL); + } @@ -102,4 +108,25 @@ void lx_emul_time_handle(void) } -struct of_device_id __clk_of_table[] = { }; +enum { LX_EMUL_MAX_OF_CLOCK_PROVIDERS = 256 }; + + +struct of_device_id __clk_of_table[LX_EMUL_MAX_OF_CLOCK_PROVIDERS] = { }; + + +void lx_emul_register_of_clk_initcall(char const *compat, void *fn) +{ + static unsigned count; + + if (count == LX_EMUL_MAX_OF_CLOCK_PROVIDERS) { + printk("lx_emul_register_of_clk_initcall: __clk_of_table exhausted\n"); + return; + } + + strncpy(__clk_of_table[count].compatible, compat, + sizeof(__clk_of_table[count].compatible)); + + __clk_of_table[count].data = fn; + + count++; +} diff --git a/repos/dde_linux/src/lib/lx_emul/shadow/drivers/clk/clk.c b/repos/dde_linux/src/lib/lx_emul/shadow/drivers/clk/clk.c index f7b9cd2967..1d4195c516 100644 --- a/repos/dde_linux/src/lib/lx_emul/shadow/drivers/clk/clk.c +++ b/repos/dde_linux/src/lib/lx_emul/shadow/drivers/clk/clk.c @@ -45,3 +45,10 @@ void clk_disable(struct clk * clk) { } void clk_unprepare(struct clk * clk) { } + + +struct of_device_id; + + +void of_clk_init(const struct of_device_id *matches) { } +