From: Al Stone al.stone@linaro.org
These patches are experimental; they do actually compile and they even seem to execute correctly. They are by no means complete. The reason for posting them is really just to stir some discussion and see if this is a truly crazy idea or if it has some potential for easing the ACPI transition.
These patches introduce GUFI: the Grand Unified Firmware Interface. Okay, yes, it is a silly name. I didn't spend a lot of time on it. What I'm most interested in is the idea and whether it is worth pursuing further, and whether or not there are better ways to do this if it does make sense.
The idea is very simple: introduce a shim layer that looks like a merge of some sort between ACPI and FDT functionality in the kernel. In that shim layer, make it possible for a driver to make a single call to a function, and with that call, retrieve configuration information stored in either ACPI tables or a DT. Further, allow the kernel to specify which has priority -- i.e., search through ACPI tables, and then through FDT if data is not found, or vice versa -- or which is exclusive, either ACPI or FDT only.
Why would I do this? As a kernel developer, this allows me to make changes in the direction of either FDT or ACPI as quickly or as slowly as I want to. Most of my config can be in FDT and I can then piecemeal convert to ACPI as I figure out ASL and/or any driver changes that may be needed. Secondly, if I do this well, the changes to convert from FDT to ACPI *should* be very small; from ACPI to FDT may be more difficult but over time that can likely be improved as well. If someone was clever, they could even add support for a specific board file and gradually convert that to FDT or ACPI. Third, in the really, really long term, maybe someone comes up with yet another hardware configuration description format that is so cool it provides sharks with laser beams on their heads and *everyone* wants to convert to it. With this layer in place, perhaps we can smooth even that transition by abstracting out the config info that's needed and the API to retrieve it.
So, what do you think?
Changes in v2: -- Took a completely different approach to the overall structure based on feedback from Tomasz Nowicki. -- Changed an assumption: originally, I wanted to absolutely minimize the changes in API between OF and GUFI. That assumption has been dropped in favor of defining a more general API that will attempt to merge the best of ACPI and OF. -- The changes to vexpress-sysreg are for only one OF call for now. The previous version was more complete, but this version works. Over time, further changes will be made as each call is converted to this newer API.
Al Stone (4): GUFI: add kernel config options for GUFI GUFI: introduce the basic framework ARM64: GUFI: add setup_arch() call to gufi_init() GUFI: MFD: initial change to use one GUFI API call in vexpress-sysreg
arch/arm64/Kconfig | 6 - arch/arm64/kernel/setup.c | 5 + drivers/Kconfig | 2 + drivers/gufi/Kconfig | 44 +++++++ drivers/gufi/Makefile | 11 ++ drivers/gufi/acpi_protocol.c | 35 +++++ drivers/gufi/acpi_protocol.h | 37 ++++++ drivers/gufi/core.c | 296 ++++++++++++++++++++++++++++++++++++++++++ drivers/gufi/of_protocol.c | 44 +++++++ drivers/gufi/of_protocol.h | 37 ++++++ drivers/mfd/vexpress-sysreg.c | 5 +- include/linux/gufi.h | 62 +++++++++ 12 files changed, 577 insertions(+), 7 deletions(-) create mode 100644 drivers/gufi/Kconfig create mode 100644 drivers/gufi/Makefile create mode 100644 drivers/gufi/acpi_protocol.c create mode 100644 drivers/gufi/acpi_protocol.h create mode 100644 drivers/gufi/core.c create mode 100644 drivers/gufi/of_protocol.c create mode 100644 drivers/gufi/of_protocol.h create mode 100644 include/linux/gufi.h
From: Al Stone al.stone@linaro.org
Introduce the kernel config options to enable the Grand Unified Firmware Interface (GUFI). Give the user the option of using only ACPI, only DT, or searching both with either ACPI or DT being searched first.
Signed-off-by: Al Stone al.stone@linaro.org --- arch/arm64/Kconfig | 6 ------ drivers/Kconfig | 2 ++ drivers/gufi/Kconfig | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 drivers/gufi/Kconfig
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 07fccb0..d42356d 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -327,12 +327,6 @@ source "drivers/acpi/Kconfig"
source "drivers/firmware/Kconfig"
-menu "Power management and ACPI options" - -source "drivers/acpi/Kconfig" - -endmenu - source "fs/Kconfig"
source "arch/arm64/kvm/Kconfig" diff --git a/drivers/Kconfig b/drivers/Kconfig index 73a4f88..d2e7f3c 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -10,6 +10,8 @@ source "drivers/mtd/Kconfig"
source "drivers/of/Kconfig"
+source "drivers/gufi/Kconfig" + source "drivers/parport/Kconfig"
source "drivers/pnp/Kconfig" diff --git a/drivers/gufi/Kconfig b/drivers/gufi/Kconfig new file mode 100644 index 0000000..cd1ed3d --- /dev/null +++ b/drivers/gufi/Kconfig @@ -0,0 +1,44 @@ +config GUFI + def_bool y + +menu "Grand Unified Firmware Interface support" + depends on GUFI + +choice + prompt "Fetching configuration info" + default GUFI_ACPI_FIRST + +config GUFI_ACPI_ONLY + bool "ONLY search ACPI tables" + depends on ACPI + help + This option forces GUFI to search for device configuration + information in the ACPI tables and methods only, ignoring + any Device Tree content. + +config GUFI_DT_ONLY + bool "ONLY search Device Tree" + depends on OF + help + This option forces GUFI to search for device configuration + information in the Device Tree only, ignoring any ACPI content. + +config GUFI_ACPI_FIRST + bool "Always search ACPI tables first" + depends on ACPI + help + This option forces GUFI to search for device configuration + information in the ACPI tables and methods first and should + that fail, look in a Device Tree, if it is enabled. + +config GUFI_DT_FIRST + bool "Always search Device Tree first" + depends on OF + help + This option forces GUFI to search for device configuration + information in the Device Tree and should that fail, look in + the ACPI tables and methods, if it is enabled. + +endchoice + +endmenu # GUFI
From: Al Stone al.stone@linaro.org
This patch introduces the basic structure of GUFI and sets up an initial API call (gufi_find_first_node(), specifically).
Signed-off-by: Al Stone al.stone@linaro.org --- drivers/gufi/Makefile | 11 ++ drivers/gufi/acpi_protocol.c | 35 +++++ drivers/gufi/acpi_protocol.h | 37 ++++++ drivers/gufi/core.c | 296 +++++++++++++++++++++++++++++++++++++++++++ drivers/gufi/of_protocol.c | 44 +++++++ drivers/gufi/of_protocol.h | 37 ++++++ include/linux/gufi.h | 62 +++++++++ 7 files changed, 522 insertions(+) create mode 100644 drivers/gufi/Makefile create mode 100644 drivers/gufi/acpi_protocol.c create mode 100644 drivers/gufi/acpi_protocol.h create mode 100644 drivers/gufi/core.c create mode 100644 drivers/gufi/of_protocol.c create mode 100644 drivers/gufi/of_protocol.h create mode 100644 include/linux/gufi.h
diff --git a/drivers/gufi/Makefile b/drivers/gufi/Makefile new file mode 100644 index 0000000..eb1b0be --- /dev/null +++ b/drivers/gufi/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the Grand Unified Firmware Interface +# + +CFLAGS_core.o += -DDEBUG +CFLAGS_of_protocol.o += -DDEBUG +CFLAGS_acpi_protocol.o += -DDEBUG + +obj-$(CONFIG_GUFI) += core.o +obj-$(CONFIG_GUFI) += of_protocol.o +obj-$(CONFIG_GUFI) += acpi_protocol.o diff --git a/drivers/gufi/acpi_protocol.c b/drivers/gufi/acpi_protocol.c new file mode 100644 index 0000000..6b75387 --- /dev/null +++ b/drivers/gufi/acpi_protocol.c @@ -0,0 +1,35 @@ +/* + * Grand Unified Firmware Interface + * + * Copyright (C) 2014 Al Stone al.stone@linaro.org + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#ifdef CONFIG_GUFI + +#include "acpi_protocol.h" + +struct gufi_device_node *gufi_acpi_find_first_node(const char *name) +{ + /* TODO */ + return NULL; +} + +#endif /* CONFIG_GUFI */ diff --git a/drivers/gufi/acpi_protocol.h b/drivers/gufi/acpi_protocol.h new file mode 100644 index 0000000..5688f26 --- /dev/null +++ b/drivers/gufi/acpi_protocol.h @@ -0,0 +1,37 @@ +/* + * Grand Unified Firmware Interface + * + * Copyright (C) 2014 Al Stone al.stone@linaro.org + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#ifndef _GUFI_ACPI_PROTOCOL_H +#define _GUFI_ACPI_PROTOCOL_H + +#ifdef CONFIG_GUFI + +#include <linux/gufi.h> +#include <linux/of.h> + +extern struct gufi_device_node *gufi_acpi_find_first_node(const char *name); + +#endif /* CONFIG_GUFI */ + +#endif /*_GUFI_ACPI_PROTOCOL_H */ diff --git a/drivers/gufi/core.c b/drivers/gufi/core.c new file mode 100644 index 0000000..c46af6b --- /dev/null +++ b/drivers/gufi/core.c @@ -0,0 +1,296 @@ +/* + * Grand Unified Firmware Interface + * + * Copyright (C) 2014 Al Stone al.stone@linaro.org + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#ifdef CONFIG_GUFI + +#include <linux/gufi.h> +#include <linux/init.h> +#include <linux/spinlock.h> + +#include "of_protocol.h" +#include "acpi_protocol.h" + +/* + * TODO list: + * + * (1) how do we sync up with the ACPI interpreter being enabled? + * or do we? i think we will have to so that we can execute methods + * properly. but, does that delay all the other drivers from getting + * initialized? + * + */ + +enum search_preference { + SEARCH_ACPI_ONLY, + SEARCH_DT_ONLY, + SEARCH_ACPI_FIRST, + SEARCH_DT_FIRST +}; + +#if IS_ENABLED(CONFIG_GUFI_ACPI_ONLY) +#define DEFAULT_PREFERENCE SEARCH_ACPI_ONLY +#elif IS_ENABLED(CONFIG_GUFI_DT_ONLY) +#define DEFAULT_PREFERENCE SEARCH_DT_ONLY +#elif IS_ENABLED(CONFIG_GUFI_ACPI_FIRST) +#define DEFAULT_PREFERENCE SEARCH_ACPI_FIRST +#elif IS_ENABLED(CONFIG_GUFI_DT_FIRST) +#define DEFAULT_PREFERENCE SEARCH_DT_FIRST +#else +#define DEFAULT_PREFERENCE SEARCH_ACPI_FIRST +#endif + +static enum search_preference howto_search = DEFAULT_PREFERENCE; + +static LIST_HEAD(__protocols); +static LIST_HEAD(__gdn_list); + +static DEFINE_SPINLOCK(__gdn_list_lock); + +/*********************************************************************** + * + * Functions to get different mechanisms registered for finding + * configuration information for a device. + * + ***********************************************************************/ + +int gufi_register_protocol(struct gufi_protocol *prot) +{ + struct gufi_protocol *p; + struct gufi_protocol *tmp = NULL; + + if (!prot) + return -ENODEV; + pr_debug("%s: registering %s\n", __func__, prot->name); + + list_for_each_entry(p, &__protocols, entry) { + if (!strcmp(prot->name, p->name)) { + tmp = p; + break; + } + } + + if (!tmp) + list_add_tail(&prot->entry, &__protocols); + + return 0; +} +EXPORT_SYMBOL(gufi_register_protocol); + +void gufi_unregister_protocol(struct gufi_protocol *prot) +{ + struct gufi_protocol *p; + struct gufi_protocol *tmp = NULL; + + if (!prot) + return; + pr_debug("%s: unregistering %s\n", __func__, prot->name); + + list_for_each_entry(p, &__protocols, entry) { + if (!strcmp(prot->name, p->name)) { + tmp = p; + break; + } + } + + if (tmp) + list_del(&tmp->entry); + + return; +} +EXPORT_SYMBOL(gufi_unregister_protocol); + +/*********************************************************************** + * + * General utility functions + * + ***********************************************************************/ + +/** + * __gufi_look_for_acpi - All gufi_device_nodes are kept in a list. + * Given an acpi_device, search the list for + * a matching node. + * @an: struct acpi_device to look for + * + * Returns a pointer to the node found, if any. + */ +static struct gufi_device_node *__gufi_look_for_acpi(struct acpi_device *an) +{ + struct gufi_device_node *pos; + + if (!an) + return NULL; + + list_for_each_entry(pos, &__gdn_list, entry) { + if (pos->an == an) { + return pos; + } + } + + return NULL; +} + +/** + * __gufi_look_for_dt - All gufi_device_nodes are kept in a list. + * Given an DT device node, search the list for + * a matching node. + * @dn: struct device_node to look for + * + * Returns a pointer to the node found, if any. + */ +static struct gufi_device_node *__gufi_look_for_dt(struct device_node *dn) +{ + struct gufi_device_node *pos; + + if (!dn) + return NULL; + + list_for_each_entry(pos, &__gdn_list, entry) { + if (pos->dn == dn) { + return pos; + } + } + + return NULL; +} + +/** + * gufi_look_for_node - All gufi_device_nodes a kept in a list. + * Given either a device_node or acpi_device + * (or both), search the list for a matching + * node. If there is no node, make one and + * add it to the list. + * @dn: struct device_node to look for + * @an: struct acpi_device to look for + * + * Returns a pointer to the node found, if any, or creates a new node + * and returns the address to it. + */ +struct gufi_device_node *gufi_look_for_node(struct device_node *dn, + struct acpi_device *an) +{ + struct gufi_device_node *gdn = NULL; + struct gufi_device_node *ga = NULL; + struct gufi_device_node *gd = NULL; + unsigned long lock_flags; + + pr_debug("GUFI: entering gufi_look_for_node\n"); + pr_debug("GUFI: gufi_look_for_node: dn = 0x%p\n", dn); + pr_debug("GUFI: gufi_look_for_node: an = 0x%p\n", an); + + spin_lock_irqsave(&__gdn_list_lock, lock_flags); + + ga = __gufi_look_for_acpi(an); + gd = __gufi_look_for_dt(dn); + pr_debug("GUFI: gufi_look_for_node: ga = 0x%p\n", ga); + pr_debug("GUFI: gufi_look_for_node: gd = 0x%p\n", gd); + + if ((ga || gd ) && (ga == gd)) + return ga ? ga : gd; + + if (!(ga || gd)) { + gdn = kzalloc(sizeof(struct gufi_device_node), GFP_KERNEL); + if (gdn) { + gdn->dn = dn; + gdn->an = an; + pr_debug("GUFI: gufi_look_for_node: gdn = 0x%p\n", gdn); + pr_debug("GUFI: gufi_look_for_node: gdn->an = 0x%p\n", gdn->an); + pr_debug("GUFI: gufi_look_for_node: gdn->dn = 0x%p\n", gdn->dn); + kref_init(&gdn->kref); + list_add_tail(&gdn->entry, &__gdn_list); + } + } + spin_unlock_irqrestore(&__gdn_list_lock, lock_flags); + + pr_debug("GUFI: leaving gufi_look_for_node\n"); + + return gdn; +} +EXPORT_SYMBOL(gufi_look_for_node); + + +/*********************************************************************** + * + * Functions that implement the elements of the GUFI API + * + ***********************************************************************/ + +struct gufi_device_node *gufi_find_first_node(const char *name) +{ + struct gufi_device_node *result = NULL; + struct gufi_protocol *p; + + list_for_each_entry(p, &__protocols, entry) { + if (p->find_first_node) + result = p->find_first_node(name); + if (result) + break; + } + + return result; +} +EXPORT_SYMBOL(gufi_find_first_node); + +static struct gufi_protocol acpi_protocol = { + .name = "ACPI", + .find_first_node = gufi_acpi_find_first_node, +}; + +static struct gufi_protocol of_protocol = { + .name = "OF", + .find_first_node = gufi_of_find_first_node, +}; + +int __init gufi_init(void) +{ + /* + * TODO: enable a kernel parameter that would allow + * this to be switched at boot time. + */ + + switch (howto_search) { + case SEARCH_ACPI_ONLY: + gufi_register_protocol(&acpi_protocol); + break; + ;; + case SEARCH_DT_ONLY: + gufi_register_protocol(&of_protocol); + break; + ;; + case SEARCH_ACPI_FIRST: + gufi_register_protocol(&acpi_protocol); + gufi_register_protocol(&of_protocol); + break; + ;; + case SEARCH_DT_FIRST: + gufi_register_protocol(&of_protocol); + gufi_register_protocol(&acpi_protocol); + break; + ;; + } + + return 0; +} +EXPORT_SYMBOL(gufi_init); + +#endif /* CONFIG_GUFI */ diff --git a/drivers/gufi/of_protocol.c b/drivers/gufi/of_protocol.c new file mode 100644 index 0000000..20af559 --- /dev/null +++ b/drivers/gufi/of_protocol.c @@ -0,0 +1,44 @@ +/* + * Grand Unified Firmware Interface + * + * Copyright (C) 2014 Al Stone al.stone@linaro.org + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#ifdef CONFIG_GUFI + +#include <linux/gufi.h> +#include <linux/of.h> + +#include "of_protocol.h" + +struct gufi_device_node *gufi_of_find_first_node(const char *name) +{ + struct device_node *node; + struct gufi_device_node *gdn; + + node = of_find_compatible_node(NULL, NULL, name); + + gdn = gufi_look_for_node(node, NULL); + + return gdn; +} + +#endif /* CONFIG_GUFI */ diff --git a/drivers/gufi/of_protocol.h b/drivers/gufi/of_protocol.h new file mode 100644 index 0000000..3051bb6 --- /dev/null +++ b/drivers/gufi/of_protocol.h @@ -0,0 +1,37 @@ +/* + * Grand Unified Firmware Interface + * + * Copyright (C) 2014 Al Stone al.stone@linaro.org + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#ifndef _GUFI_OF_PROTOCOL_H +#define _GUFI_OF_PROTOCOL_H + +#ifdef CONFIG_GUFI + +#include <linux/gufi.h> +#include <linux/of.h> + +extern struct gufi_device_node *gufi_of_find_first_node(const char *name); + +#endif /* CONFIG_GUFI */ + +#endif /*_GUFI_OF_PROTOCOL_H */ diff --git a/include/linux/gufi.h b/include/linux/gufi.h new file mode 100644 index 0000000..baf8650 --- /dev/null +++ b/include/linux/gufi.h @@ -0,0 +1,62 @@ +/* + * gufi.h - Grand Unified Firmware Interface + * + * Copyright (C) 2014 Al Stone al.stone@linaro.org + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#ifndef _LINUX_GUFI_H +#define _LINUX_GUFI_H + +#ifdef CONFIG_GUFI + +#include <linux/acpi.h> +#include <linux/errno.h> +#include <linux/kref.h> +#include <linux/list.h> +#include <linux/of.h> +#include <linux/types.h> + +struct gufi_device_node { + struct device_node *dn; + struct acpi_device *an; + struct kref kref; + struct list_head entry; +}; + +struct gufi_protocol { + const char *name; + struct list_head entry; + + struct gufi_device_node *(*find_first_node)(const char *name); +}; + +extern int gufi_init(void); +extern int gufi_register_protocol(struct gufi_protocol *prot); +extern void gufi_unregister_protocol(struct gufi_protocol *prot); + +extern struct gufi_device_node *gufi_look_for_node(struct device_node *dn, + struct acpi_device *an); + +extern struct gufi_device_node *gufi_find_first_node(const char *name); + +#endif /* CONFIG_GUFI */ + +#endif /*_LINUX_GUFI_H */
From: Al Stone al.stone@linaro.org
GUFI needs to be initialized after ACPI tables are read, and after the DT has been unflattened, but before devices get configured. Insert the proper call to gufi_init() in setup_arch().
Signed-off-by: Al Stone al.stone@linaro.org --- arch/arm64/kernel/setup.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index e1c9a8b..b00dbeb 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -43,6 +43,7 @@ #include <linux/of_platform.h> #include <linux/efi.h> #include <linux/acpi.h> +#include <linux/gufi.h>
#include <asm/fixmap.h> #include <asm/cputype.h> @@ -290,6 +291,10 @@ void __init setup_arch(char **cmdline_p)
psci_init();
+#ifdef CONFIG_GUFI + gufi_init(); +#endif + cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; #ifdef CONFIG_SMP smp_init_cpus();
From: Al Stone al.stone@linaro.org
Replace a call to of_find_compatible_node() with a GUFI API call.
Signed-off-by: Al Stone al.stone@linaro.org --- drivers/mfd/vexpress-sysreg.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 31f60ff..f8b61ce 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -23,6 +23,7 @@ #include <linux/timer.h> #include <linux/vexpress.h> #include <linux/acpi.h> +#include <linux/gufi.h>
#define SYS_ID 0x000 #define SYS_SW 0x004 @@ -340,11 +341,13 @@ void __init vexpress_sysreg_early_init(void __iomem *base) void __init vexpress_sysreg_of_early_init(void) { struct device_node *node; + struct gufi_device_node *gdn;
if (vexpress_sysreg_base) return;
- node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg"); + gdn = gufi_find_first_node("arm,vexpress-sysreg"); + node = gdn->dn; if (node) { vexpress_sysreg_base = of_iomap(node, 0); vexpress_sysreg_setup(node);