[RFC,part1,5/7] ARM64 / ACPI: Introduce arm_core.c and its related head file

Message ID 1386088611-2801-6-git-send-email-hanjun.guo@linaro.org
State New
Headers show

Commit Message

Hanjun Guo Dec. 3, 2013, 4:36 p.m.
introduce arm_core.c and its related head file, after this patch,
we can get ACPI tables from BIOS on ARM64 now.

Signed-off-by: Al Stone <al.stone@linaro.org>
Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
---
 arch/arm64/include/asm/acpi.h |   57 +++++++++++
 arch/arm64/kernel/setup.c     |    8 ++
 drivers/acpi/Makefile         |    2 +
 drivers/acpi/plat/Makefile    |    1 +
 drivers/acpi/plat/arm-core.c  |  219 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 287 insertions(+)
 create mode 100644 drivers/acpi/plat/Makefile
 create mode 100644 drivers/acpi/plat/arm-core.c

Comments

Mark Rutland Dec. 3, 2013, 6:03 p.m. | #1
On Tue, Dec 03, 2013 at 04:36:49PM +0000, Hanjun Guo wrote:
> introduce arm_core.c and its related head file, after this patch,
> we can get ACPI tables from BIOS on ARM64 now.
> 
> Signed-off-by: Al Stone <al.stone@linaro.org>
> Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> ---
>  arch/arm64/include/asm/acpi.h |   57 +++++++++++
>  arch/arm64/kernel/setup.c     |    8 ++
>  drivers/acpi/Makefile         |    2 +
>  drivers/acpi/plat/Makefile    |    1 +
>  drivers/acpi/plat/arm-core.c  |  219 +++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 287 insertions(+)
>  create mode 100644 drivers/acpi/plat/Makefile
>  create mode 100644 drivers/acpi/plat/arm-core.c
> 
> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> index c186f5b..e9444e4 100644
> --- a/arch/arm64/include/asm/acpi.h
> +++ b/arch/arm64/include/asm/acpi.h
> @@ -19,6 +19,43 @@
>  #ifndef _ASM_ARM_ACPI_H
>  #define _ASM_ARM_ACPI_H
>  
> +#include <asm/cacheflush.h>
> +
> +#include <linux/init.h>
> +
> +#define COMPILER_DEPENDENT_INT64	long long
> +#define COMPILER_DEPENDENT_UINT64	unsigned long long

Given we've already pulled in linux/init.h, which has pulled in
linux/types.h, is there any reason we can't use s64 and u64 here?

If we can, then why don't we unify this further up so each arch doesn't
have to define this redundantly?

> +
> +/*
> + * Calling conventions:
> + *
> + * ACPI_SYSTEM_XFACE        - Interfaces to host OS (handlers, threads)
> + * ACPI_EXTERNAL_XFACE      - External ACPI interfaces
> + * ACPI_INTERNAL_XFACE      - Internal ACPI interfaces
> + * ACPI_INTERNAL_VAR_XFACE  - Internal variable-parameter list interfaces
> + */
> +#define ACPI_SYSTEM_XFACE
> +#define ACPI_EXTERNAL_XFACE
> +#define ACPI_INTERNAL_XFACE
> +#define ACPI_INTERNAL_VAR_XFACE
> +
> +/* Asm macros */
> +#define ACPI_FLUSH_CPU_CACHE() flush_cache_all()

Can you elaborate on when ACPI needs to use this? 

Thanks,
Mark.
Zheng, Lv Dec. 4, 2013, 5:46 a.m. | #2
> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-owner@vger.kernel.org] On Behalf Of Hanjun Guo
> Sent: Wednesday, December 04, 2013 12:37 AM
> 
> introduce arm_core.c and its related head file, after this patch,
> we can get ACPI tables from BIOS on ARM64 now.
> 
> Signed-off-by: Al Stone <al.stone@linaro.org>
> Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> ---
>  arch/arm64/include/asm/acpi.h |   57 +++++++++++
>  arch/arm64/kernel/setup.c     |    8 ++
>  drivers/acpi/Makefile         |    2 +
>  drivers/acpi/plat/Makefile    |    1 +
>  drivers/acpi/plat/arm-core.c  |  219 +++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 287 insertions(+)
>  create mode 100644 drivers/acpi/plat/Makefile
>  create mode 100644 drivers/acpi/plat/arm-core.c
> 
> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> index c186f5b..e9444e4 100644
> --- a/arch/arm64/include/asm/acpi.h
> +++ b/arch/arm64/include/asm/acpi.h
> @@ -19,6 +19,43 @@
>  #ifndef _ASM_ARM_ACPI_H
>  #define _ASM_ARM_ACPI_H
> 
> +#include <asm/cacheflush.h>
> +
> +#include <linux/init.h>
> +
> +#define COMPILER_DEPENDENT_INT64	long long
> +#define COMPILER_DEPENDENT_UINT64	unsigned long long
> +
> +/*
> + * Calling conventions:
> + *
> + * ACPI_SYSTEM_XFACE        - Interfaces to host OS (handlers, threads)
> + * ACPI_EXTERNAL_XFACE      - External ACPI interfaces
> + * ACPI_INTERNAL_XFACE      - Internal ACPI interfaces
> + * ACPI_INTERNAL_VAR_XFACE  - Internal variable-parameter list interfaces
> + */
> +#define ACPI_SYSTEM_XFACE
> +#define ACPI_EXTERNAL_XFACE
> +#define ACPI_INTERNAL_XFACE
> +#define ACPI_INTERNAL_VAR_XFACE
> +
> +/* Asm macros */
> +#define ACPI_FLUSH_CPU_CACHE() flush_cache_all()

Well, you may need to check the following environments defined in <acpi/platform/aclinux.h> is sufficient for ARM targets:
49 #define ACPI_USE_SYSTEM_CLIBRARY
50 #define ACPI_USE_DO_WHILE_0
51 #define ACPI_MUTEX_TYPE             ACPI_BINARY_SEMAPHORE

70 #define ACPI_MACHINE_WIDTH          BITS_PER_LONG
Will this zap IO addresses on ARM32 platforms?

And following default settings in <acpi/platform/acenv.h> and <acpi/acxxx.h> is sufficient for ARM targets:
179 #if defined (__IA64__) || defined (__ia64__)
180 #define ACPI_MISALIGNMENT_NOT_SUPPORTED
181 #endif
Will this cause any exceptions on ARM by executing ACPICA name functions?

444 #if ACPI_MACHINE_WIDTH == 64
445 #define ACPI_USE_NATIVE_DIVIDE  /* Use compiler native 64-bit divide */
446 #endif
I think you may see build breakage on ARM32 as you haven't implemented the following ACPICA macros for ARM:
67 #define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32)
74 #define ACPI_SHIFT_RIGHT_64(n_hi, n_lo)
Have you tested this yet?

I'm not sure if all global lock code blocks are not referenced by ACPI_REDUCED_HARDWARE and I'm not sure what mechanism is implemented on ARM ACPI platforms to offer the synchronization mechanism between firmware and OSPM.  So you may need to implement the following synchronization protocol in <asm/acpi.h>:
58 #define ACPI_ACQUIRE_GLOBAL_LOCK(facs, Acq)
61 #define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq)

I only reviewed the ACPICA stuffs in <asm/acpi.h>, I didn't take a look at your Linux ACPI stuff in <asm/acpi.h>.  You may need more instructions on the porting issues from Linux ACPI guys.

Thanks and best regards
-Lv

> +
> +/* Basic configuration for ACPI */
> +#ifdef	CONFIG_ACPI
> +extern int acpi_disabled;
> +extern int acpi_noirq;
> +extern int acpi_pci_disabled;
> +extern int acpi_strict;
> +
> +static inline void disable_acpi(void)
> +{
> +	acpi_disabled = 1;
> +	acpi_pci_disabled = 1;
> +	acpi_noirq = 1;
> +}
> +
>  static inline bool arch_has_acpi_pdc(void)
>  {
>  	return false;	/* always false for now */
> @@ -29,4 +66,24 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf)
>  	return;
>  }
> 
> +static inline void acpi_noirq_set(void) { acpi_noirq = 1; }
> +static inline void acpi_disable_pci(void)
> +{
> +	acpi_pci_disabled = 1;
> +	acpi_noirq_set();
> +}
> +
> +/* FIXME: this function should be moved to topology.h when it's ready */
> +void arch_fix_phys_package_id(int num, u32 slot);
> +
> +/* temperally define -1 to make acpi core compilerable */
> +#define cpu_physical_id(cpu) -1
> +
> +#else	/* !CONFIG_ACPI */
> +#define acpi_disabled 1		/* ACPI sometimes enabled on ARM */
> +#define acpi_noirq 1		/* ACPI sometimes enabled on ARM */
> +#define acpi_pci_disabled 1	/* ACPI PCI sometimes enabled on ARM */
> +#define acpi_strict 1		/* no ACPI spec workarounds on ARM */
> +#endif
> +
>  #endif /*_ASM_ARM_ACPI_H*/
> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
> index bd9bbd0..8199360 100644
> --- a/arch/arm64/kernel/setup.c
> +++ b/arch/arm64/kernel/setup.c
> @@ -41,6 +41,7 @@
>  #include <linux/memblock.h>
>  #include <linux/of_fdt.h>
>  #include <linux/of_platform.h>
> +#include <linux/acpi.h>
> 
>  #include <asm/cputype.h>
>  #include <asm/elf.h>
> @@ -225,6 +226,13 @@ void __init setup_arch(char **cmdline_p)
> 
>  	arm64_memblock_init();
> 
> +	/*
> +	 * Parse the ACPI tables for possible boot-time configuration
> +	 */
> +	acpi_boot_table_init();
> +	early_acpi_boot_init();
> +	acpi_boot_init();
> +
>  	paging_init();
>  	request_standard_resources();
> 
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index d8cebe3..9fbba50 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -83,3 +83,5 @@ obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
>  obj-$(CONFIG_ACPI_APEI)		+= apei/
> 
>  obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
> +
> +obj-y				+= plat/
> diff --git a/drivers/acpi/plat/Makefile b/drivers/acpi/plat/Makefile
> new file mode 100644
> index 0000000..46bc65e
> --- /dev/null
> +++ b/drivers/acpi/plat/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_ARM64)	+= arm-core.o
> diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
> new file mode 100644
> index 0000000..7b8e64a
> --- /dev/null
> +++ b/drivers/acpi/plat/arm-core.c
> @@ -0,0 +1,219 @@
> +/*
> + *  ARM/ARM64 Specific Low-Level ACPI Boot Support
> + *
> + *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
> + *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
> + *  Copyright (C) 2013, Al Stone <al.stone@linaro.org> (ARM version)
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + *  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.
> + *
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + */
> +
> +#include <linux/init.h>
> +#include <linux/acpi.h>
> +#include <linux/acpi_pmtmr.h>
> +#include <linux/efi.h>
> +#include <linux/cpumask.h>
> +#include <linux/memblock.h>
> +#include <linux/module.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/slab.h>
> +#include <linux/bootmem.h>
> +#include <linux/ioport.h>
> +#include <linux/pci.h>
> +
> +#include <asm/pgtable.h>
> +#include <asm/io.h>
> +#include <asm/smp.h>
> +
> +/*
> + * We never plan to use RSDT on arm/arm64 as its deprecated in spec but this
> + * variable is still required by the ACPI core
> + */
> +u32 acpi_rsdt_forced;
> +
> +int acpi_noirq;			/* skip ACPI IRQ initialization */
> +int acpi_strict;
> +int acpi_disabled;
> +EXPORT_SYMBOL(acpi_disabled);
> +
> +int acpi_pci_disabled;		/* skip ACPI PCI scan and IRQ initialization */
> +EXPORT_SYMBOL(acpi_pci_disabled);
> +
> +#define PREFIX			"ACPI: "
> +
> +/* FIXME: this function should be moved to topology.c when it is ready */
> +void arch_fix_phys_package_id(int num, u32 slot)
> +{
> +	return;
> +}
> +EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
> +
> +/*
> + * Boot-time Configuration
> + */
> +
> +enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
> +
> +static unsigned int gsi_to_irq(unsigned int gsi)
> +{
> +	int irq = irq_create_mapping(NULL, gsi);
> +
> +	return irq;
> +}
> +
> +/*
> + * __acpi_map_table() will be called before page_init(), so early_ioremap()
> + * or early_memremap() should be called here.
> + *
> + * FIXME: early_io/memremap()/early_iounmap() are not upstream yet on ARM64,
> + * just wait for Mark Salter's patchset accepted by mainline
> + */
> +char *__init __acpi_map_table(unsigned long phys, unsigned long size)
> +{
> +	if (!phys || !size)
> +		return NULL;
> +
> +	/*
> +	 * temporarily use phys_to_virt(),
> +	 * should be early_memremap(phys, size) here
> +	 */
> +	return phys_to_virt(phys);
> +}
> +
> +void __init __acpi_unmap_table(char *map, unsigned long size)
> +{
> +	if (!map || !size)
> +		return;
> +
> +	/* should be early_iounmap(map, size); */
> +	return;
> +}
> +
> +int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
> +{
> +	*irq = gsi_to_irq(gsi);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
> +
> +/*
> + * success: return IRQ number (>=0)
> + * failure: return < 0
> + */
> +int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
> +{
> +	return -1;
> +}
> +EXPORT_SYMBOL_GPL(acpi_register_gsi);
> +
> +void acpi_unregister_gsi(u32 gsi)
> +{
> +}
> +EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> +
> +static int __init acpi_parse_fadt(struct acpi_table_header *table)
> +{
> +	return 0;
> +}
> +
> +static void __init early_acpi_process_madt(void)
> +{
> +	return;
> +}
> +
> +static void __init acpi_process_madt(void)
> +{
> +	return;
> +}
> +
> +/*
> + * acpi_boot_table_init() and acpi_boot_init()
> + *  called from setup_arch(), always.
> + *	1. checksums all tables
> + *	2. enumerates lapics
> + *	3. enumerates io-apics
> + *
> + * acpi_table_init() is separated to allow reading SRAT without
> + * other side effects.
> + */
> +void __init acpi_boot_table_init(void)
> +{
> +	/*
> +	 * If acpi_disabled, bail out
> +	 */
> +	if (acpi_disabled)
> +		return;
> +
> +	/*
> +	 * Initialize the ACPI boot-time table parser.
> +	 */
> +	if (acpi_table_init()) {
> +		disable_acpi();
> +		return;
> +	}
> +}
> +
> +int __init early_acpi_boot_init(void)
> +{
> +	/*
> +	 * If acpi_disabled, bail out
> +	 */
> +	if (acpi_disabled)
> +		return 1;
> +
> +	/*
> +	 * Process the Multiple APIC Description Table (MADT), if present
> +	 */
> +	early_acpi_process_madt();
> +
> +	return 0;
> +}
> +
> +int __init acpi_boot_init(void)
> +{
> +	/*
> +	 * If acpi_disabled, bail out
> +	 */
> +	if (acpi_disabled)
> +		return 1;
> +
> +	acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt);
> +
> +	/*
> +	 * Process the Multiple APIC Description Table (MADT), if present
> +	 */
> +	acpi_process_madt();
> +
> +	return 0;
> +}
> +
> +static int __init parse_acpi(char *arg)
> +{
> +	if (!arg)
> +		return -EINVAL;
> +
> +	/* "acpi=off" disables both ACPI table parsing and interpreter */
> +	if (strcmp(arg, "off") == 0) {
> +		disable_acpi();
> +	}
> +	/* acpi=strict disables out-of-spec workarounds */
> +	else if (strcmp(arg, "strict") == 0) {
> +		acpi_strict = 1;
> +	}
> +	return 0;
> +}
> +early_param("acpi", parse_acpi);
> --
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hanjun Guo Dec. 4, 2013, 3:48 p.m. | #3
+CC Lv Zheng

On 2013年12月04日 02:03, Mark Rutland wrote:
> On Tue, Dec 03, 2013 at 04:36:49PM +0000, Hanjun Guo wrote:
>> introduce arm_core.c and its related head file, after this patch,
>> we can get ACPI tables from BIOS on ARM64 now.
>>
>> Signed-off-by: Al Stone <al.stone@linaro.org>
>> Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> ---
>>   arch/arm64/include/asm/acpi.h |   57 +++++++++++
>>   arch/arm64/kernel/setup.c     |    8 ++
>>   drivers/acpi/Makefile         |    2 +
>>   drivers/acpi/plat/Makefile    |    1 +
>>   drivers/acpi/plat/arm-core.c  |  219 +++++++++++++++++++++++++++++++++++++++++
>>   5 files changed, 287 insertions(+)
>>   create mode 100644 drivers/acpi/plat/Makefile
>>   create mode 100644 drivers/acpi/plat/arm-core.c
>>
>> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
>> index c186f5b..e9444e4 100644
>> --- a/arch/arm64/include/asm/acpi.h
>> +++ b/arch/arm64/include/asm/acpi.h
>> @@ -19,6 +19,43 @@
>>   #ifndef _ASM_ARM_ACPI_H
>>   #define _ASM_ARM_ACPI_H
>>   
>> +#include <asm/cacheflush.h>
>> +
>> +#include <linux/init.h>
>> +
>> +#define COMPILER_DEPENDENT_INT64	long long
>> +#define COMPILER_DEPENDENT_UINT64	unsigned long long
> Given we've already pulled in linux/init.h, which has pulled in
> linux/types.h, is there any reason we can't use s64 and u64 here?
>
> If we can, then why don't we unify this further up so each arch doesn't
> have to define this redundantly?

It make sense to me, I didn't notice that before, Lv, any comments about it?

>> +
>> +/*
>> + * Calling conventions:
>> + *
>> + * ACPI_SYSTEM_XFACE        - Interfaces to host OS (handlers, threads)
>> + * ACPI_EXTERNAL_XFACE      - External ACPI interfaces
>> + * ACPI_INTERNAL_XFACE      - Internal ACPI interfaces
>> + * ACPI_INTERNAL_VAR_XFACE  - Internal variable-parameter list interfaces
>> + */
>> +#define ACPI_SYSTEM_XFACE
>> +#define ACPI_EXTERNAL_XFACE
>> +#define ACPI_INTERNAL_XFACE
>> +#define ACPI_INTERNAL_VAR_XFACE
>> +
>> +/* Asm macros */
>> +#define ACPI_FLUSH_CPU_CACHE() flush_cache_all()
> Can you elaborate on when ACPI needs to use this?

Mainly used in two cases:

1) system sleep, there are sleep states defined
in ACPI, such as S0, S1, S2, S3 and etc.
when system enter sleep states, flush cache is needed.

2) When CPU enter idle states deeper than C3.

Thanks
hanjun
Hanjun Guo Dec. 4, 2013, 3:53 p.m. | #4
On 2013年12月04日 13:46, Zheng, Lv wrote:
>> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-owner@vger.kernel.org] On Behalf Of Hanjun Guo
>> Sent: Wednesday, December 04, 2013 12:37 AM
>>
>> introduce arm_core.c and its related head file, after this patch,
>> we can get ACPI tables from BIOS on ARM64 now.
>>
>> Signed-off-by: Al Stone <al.stone@linaro.org>
>> Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> ---
>>   arch/arm64/include/asm/acpi.h |   57 +++++++++++
>>   arch/arm64/kernel/setup.c     |    8 ++
>>   drivers/acpi/Makefile         |    2 +
>>   drivers/acpi/plat/Makefile    |    1 +
>>   drivers/acpi/plat/arm-core.c  |  219 +++++++++++++++++++++++++++++++++++++++++
>>   5 files changed, 287 insertions(+)
>>   create mode 100644 drivers/acpi/plat/Makefile
>>   create mode 100644 drivers/acpi/plat/arm-core.c
>>
>> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
>> index c186f5b..e9444e4 100644
>> --- a/arch/arm64/include/asm/acpi.h
>> +++ b/arch/arm64/include/asm/acpi.h
>> @@ -19,6 +19,43 @@
>>   #ifndef _ASM_ARM_ACPI_H
>>   #define _ASM_ARM_ACPI_H
>>
>> +#include <asm/cacheflush.h>
>> +
>> +#include <linux/init.h>
>> +
>> +#define COMPILER_DEPENDENT_INT64	long long
>> +#define COMPILER_DEPENDENT_UINT64	unsigned long long
>> +
>> +/*
>> + * Calling conventions:
>> + *
>> + * ACPI_SYSTEM_XFACE        - Interfaces to host OS (handlers, threads)
>> + * ACPI_EXTERNAL_XFACE      - External ACPI interfaces
>> + * ACPI_INTERNAL_XFACE      - Internal ACPI interfaces
>> + * ACPI_INTERNAL_VAR_XFACE  - Internal variable-parameter list interfaces
>> + */
>> +#define ACPI_SYSTEM_XFACE
>> +#define ACPI_EXTERNAL_XFACE
>> +#define ACPI_INTERNAL_XFACE
>> +#define ACPI_INTERNAL_VAR_XFACE
>> +
>> +/* Asm macros */
>> +#define ACPI_FLUSH_CPU_CACHE() flush_cache_all()
> Well, you may need to check the following environments defined in <acpi/platform/aclinux.h> is sufficient for ARM targets:
> 49 #define ACPI_USE_SYSTEM_CLIBRARY
> 50 #define ACPI_USE_DO_WHILE_0
> 51 #define ACPI_MUTEX_TYPE             ACPI_BINARY_SEMAPHORE
>
> 70 #define ACPI_MACHINE_WIDTH          BITS_PER_LONG
> Will this zap IO addresses on ARM32 platforms?

In this patch set, we only implemented ACPI for ARM64, and ARM32 is
not included in this patch set.

My bad, sorry for the vague changelog.

> And following default settings in <acpi/platform/acenv.h> and <acpi/acxxx.h> is sufficient for ARM targets:
> 179 #if defined (__IA64__) || defined (__ia64__)
> 180 #define ACPI_MISALIGNMENT_NOT_SUPPORTED
> 181 #endif
> Will this cause any exceptions on ARM by executing ACPICA name functions?
>
> 444 #if ACPI_MACHINE_WIDTH == 64
> 445 #define ACPI_USE_NATIVE_DIVIDE  /* Use compiler native 64-bit divide */
> 446 #endif
> I think you may see build breakage on ARM32 as you haven't implemented the following ACPICA macros for ARM:
> 67 #define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32)
> 74 #define ACPI_SHIFT_RIGHT_64(n_hi, n_lo)
> Have you tested this yet?

Yes, we tested on ARM32 and it works fine on linaro-acpi, but patches
for ARM32 is not sent out for upstream yet, that's why you can't see
the code you needed.


>
> I'm not sure if all global lock code blocks are not referenced by ACPI_REDUCED_HARDWARE and I'm not sure what mechanism is implemented on ARM ACPI platforms to offer the synchronization mechanism between firmware and OSPM.  So you may need to implement the following synchronization protocol in <asm/acpi.h>:
> 58 #define ACPI_ACQUIRE_GLOBAL_LOCK(facs, Acq)
> 61 #define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq)

In reduced hardware mode, No hardware resource sharing between
OSPM and other asynchronous operating environments, such as
UEFI Runtime Services or System Management Mode. (The Global Lock
is not supported)
  
please refer to chapter 3.11.1 of ACPI 5.0.


>
> I only reviewed the ACPICA stuffs in <asm/acpi.h>, I didn't take a look at your Linux ACPI stuff in <asm/acpi.h>.  You may need more instructions on the porting issues from Linux ACPI guys.

Yes, I will. Thank you for the review and guidance, and you are the expert
for ACPICA, we need your instructions too

Thanks
Hanjun
Al Stone Dec. 4, 2013, 7:47 p.m. | #5
On 12/04/2013 08:53 AM, Hanjun Guo wrote:
> On 2013年12月04日 13:46, Zheng, Lv wrote:
>>> From: linux-acpi-owner@vger.kernel.org
>>> [mailto:linux-acpi-owner@vger.kernel.org] On Behalf Of Hanjun Guo
>>> Sent: Wednesday, December 04, 2013 12:37 AM
>>>
>>> introduce arm_core.c and its related head file, after this patch,
>>> we can get ACPI tables from BIOS on ARM64 now.
>>>
>>> Signed-off-by: Al Stone <al.stone@linaro.org>
>>> Signed-off-by: Graeme Gregory <graeme.gregory@linaro.org>
>>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>>> ---
>>>   arch/arm64/include/asm/acpi.h |   57 +++++++++++
>>>   arch/arm64/kernel/setup.c     |    8 ++
>>>   drivers/acpi/Makefile         |    2 +
>>>   drivers/acpi/plat/Makefile    |    1 +
>>>   drivers/acpi/plat/arm-core.c  |  219
>>> +++++++++++++++++++++++++++++++++++++++++
>>>   5 files changed, 287 insertions(+)
>>>   create mode 100644 drivers/acpi/plat/Makefile
>>>   create mode 100644 drivers/acpi/plat/arm-core.c
>>>

[...]

>>
>> I'm not sure if all global lock code blocks are not referenced by
>> ACPI_REDUCED_HARDWARE and I'm not sure what mechanism is implemented
>> on ARM ACPI platforms to offer the synchronization mechanism between
>> firmware and OSPM.  So you may need to implement the following
>> synchronization protocol in <asm/acpi.h>:
>> 58 #define ACPI_ACQUIRE_GLOBAL_LOCK(facs, Acq)
>> 61 #define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq)
>
> In reduced hardware mode, No hardware resource sharing between
> OSPM and other asynchronous operating environments, such as
> UEFI Runtime Services or System Management Mode. (The Global Lock
> is not supported)
>
> please refer to chapter 3.11.1 of ACPI 5.0.

I agree with Hanjun; the spec clearly states that the ACPI global lock
is not supported in reduced HW mode.  The only similar lock I recall
from the spec is for ECs (Embedded Controllers, section 12) but is very
specific to controlling the interaction with the EC.

If the intent is to use SMI, again, in reduced HW mode, 3.11.1 does
not allow SMI_CMD, and 5.2.9 indicates SMI_CMD is to be ignored.
Arnd Bergmann Dec. 5, 2013, 3:38 a.m. | #6
On Tuesday 03 December 2013, Hanjun Guo wrote:
> +static unsigned int gsi_to_irq(unsigned int gsi)
> +{
> +       int irq = irq_create_mapping(NULL, gsi);
> +
> +       return irq;
> +}

I think this could use a comment regarding your plans for IRQ domains.

Do you expect that all ACPI systems would have only a single GIC IRQ
controller and a single domain, or do you plan to add irqdomain code
later?

	Arnd
Hanjun Guo Dec. 5, 2013, 1:51 p.m. | #7
On 2013年12月05日 11:38, Arnd Bergmann wrote:
> On Tuesday 03 December 2013, Hanjun Guo wrote:
>> +static unsigned int gsi_to_irq(unsigned int gsi)
>> +{
>> +       int irq = irq_create_mapping(NULL, gsi);
>> +
>> +       return irq;
>> +}
> I think this could use a comment regarding your plans for IRQ domains.
>
> Do you expect that all ACPI systems would have only a single GIC IRQ
> controller and a single domain, or do you plan to add irqdomain code
> later?

we added irqdomain code in the part2 patch set, is that the code ok
with you?

Thanks
Hanjun
Arnd Bergmann Dec. 5, 2013, 8:40 p.m. | #8
On Thursday 05 December 2013, Hanjun Guo wrote:
> On 2013年12月05日 11:38, Arnd Bergmann wrote:
> > On Tuesday 03 December 2013, Hanjun Guo wrote:
> >> +static unsigned int gsi_to_irq(unsigned int gsi)
> >> +{
> >> +       int irq = irq_create_mapping(NULL, gsi);
> >> +
> >> +       return irq;
> >> +}
> > I think this could use a comment regarding your plans for IRQ domains.
> >
> > Do you expect that all ACPI systems would have only a single GIC IRQ
> > controller and a single domain, or do you plan to add irqdomain code
> > later?
> 
> we added irqdomain code in the part2 patch set, is that the code ok
> with you?

I don't see where it gets added. Do you mean "[RFC part2 PATCH 8/9] ACPI /
ARM64: Update acpi_register_gsi to register with the core IRQ subsystem"?
That still just uses a single domain.

When we talked about ACPI support at Linaro connect, someone mentioned
that the ACPI spec does have the concept of IRQ domains, but it seems
they are not implemented by Linux.

How do you get a mapping for an IRQ on a secondary irqchip such as
a GPIO extender?

	Arnd

Patch

diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index c186f5b..e9444e4 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -19,6 +19,43 @@ 
 #ifndef _ASM_ARM_ACPI_H
 #define _ASM_ARM_ACPI_H
 
+#include <asm/cacheflush.h>
+
+#include <linux/init.h>
+
+#define COMPILER_DEPENDENT_INT64	long long
+#define COMPILER_DEPENDENT_UINT64	unsigned long long
+
+/*
+ * Calling conventions:
+ *
+ * ACPI_SYSTEM_XFACE        - Interfaces to host OS (handlers, threads)
+ * ACPI_EXTERNAL_XFACE      - External ACPI interfaces
+ * ACPI_INTERNAL_XFACE      - Internal ACPI interfaces
+ * ACPI_INTERNAL_VAR_XFACE  - Internal variable-parameter list interfaces
+ */
+#define ACPI_SYSTEM_XFACE
+#define ACPI_EXTERNAL_XFACE
+#define ACPI_INTERNAL_XFACE
+#define ACPI_INTERNAL_VAR_XFACE
+
+/* Asm macros */
+#define ACPI_FLUSH_CPU_CACHE() flush_cache_all()
+
+/* Basic configuration for ACPI */
+#ifdef	CONFIG_ACPI
+extern int acpi_disabled;
+extern int acpi_noirq;
+extern int acpi_pci_disabled;
+extern int acpi_strict;
+
+static inline void disable_acpi(void)
+{
+	acpi_disabled = 1;
+	acpi_pci_disabled = 1;
+	acpi_noirq = 1;
+}
+
 static inline bool arch_has_acpi_pdc(void)
 {
 	return false;	/* always false for now */
@@ -29,4 +66,24 @@  static inline void arch_acpi_set_pdc_bits(u32 *buf)
 	return;
 }
 
+static inline void acpi_noirq_set(void) { acpi_noirq = 1; }
+static inline void acpi_disable_pci(void)
+{
+	acpi_pci_disabled = 1;
+	acpi_noirq_set();
+}
+
+/* FIXME: this function should be moved to topology.h when it's ready */
+void arch_fix_phys_package_id(int num, u32 slot);
+
+/* temperally define -1 to make acpi core compilerable */
+#define cpu_physical_id(cpu) -1
+
+#else	/* !CONFIG_ACPI */
+#define acpi_disabled 1		/* ACPI sometimes enabled on ARM */
+#define acpi_noirq 1		/* ACPI sometimes enabled on ARM */
+#define acpi_pci_disabled 1	/* ACPI PCI sometimes enabled on ARM */
+#define acpi_strict 1		/* no ACPI spec workarounds on ARM */
+#endif
+
 #endif /*_ASM_ARM_ACPI_H*/
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index bd9bbd0..8199360 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -41,6 +41,7 @@ 
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
+#include <linux/acpi.h>
 
 #include <asm/cputype.h>
 #include <asm/elf.h>
@@ -225,6 +226,13 @@  void __init setup_arch(char **cmdline_p)
 
 	arm64_memblock_init();
 
+	/*
+	 * Parse the ACPI tables for possible boot-time configuration
+	 */
+	acpi_boot_table_init();
+	early_acpi_boot_init();
+	acpi_boot_init();
+
 	paging_init();
 	request_standard_resources();
 
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index d8cebe3..9fbba50 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -83,3 +83,5 @@  obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
 obj-$(CONFIG_ACPI_APEI)		+= apei/
 
 obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
+
+obj-y				+= plat/
diff --git a/drivers/acpi/plat/Makefile b/drivers/acpi/plat/Makefile
new file mode 100644
index 0000000..46bc65e
--- /dev/null
+++ b/drivers/acpi/plat/Makefile
@@ -0,0 +1 @@ 
+obj-$(CONFIG_ARM64)	+= arm-core.o
diff --git a/drivers/acpi/plat/arm-core.c b/drivers/acpi/plat/arm-core.c
new file mode 100644
index 0000000..7b8e64a
--- /dev/null
+++ b/drivers/acpi/plat/arm-core.c
@@ -0,0 +1,219 @@ 
+/*
+ *  ARM/ARM64 Specific Low-Level ACPI Boot Support
+ *
+ *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+ *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
+ *  Copyright (C) 2013, Al Stone <al.stone@linaro.org> (ARM version)
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/acpi_pmtmr.h>
+#include <linux/efi.h>
+#include <linux/cpumask.h>
+#include <linux/memblock.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+
+/*
+ * We never plan to use RSDT on arm/arm64 as its deprecated in spec but this
+ * variable is still required by the ACPI core
+ */
+u32 acpi_rsdt_forced;
+
+int acpi_noirq;			/* skip ACPI IRQ initialization */
+int acpi_strict;
+int acpi_disabled;
+EXPORT_SYMBOL(acpi_disabled);
+
+int acpi_pci_disabled;		/* skip ACPI PCI scan and IRQ initialization */
+EXPORT_SYMBOL(acpi_pci_disabled);
+
+#define PREFIX			"ACPI: "
+
+/* FIXME: this function should be moved to topology.c when it is ready */
+void arch_fix_phys_package_id(int num, u32 slot)
+{
+	return;
+}
+EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
+
+/*
+ * Boot-time Configuration
+ */
+
+enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
+
+static unsigned int gsi_to_irq(unsigned int gsi)
+{
+	int irq = irq_create_mapping(NULL, gsi);
+
+	return irq;
+}
+
+/*
+ * __acpi_map_table() will be called before page_init(), so early_ioremap()
+ * or early_memremap() should be called here.
+ *
+ * FIXME: early_io/memremap()/early_iounmap() are not upstream yet on ARM64,
+ * just wait for Mark Salter's patchset accepted by mainline
+ */
+char *__init __acpi_map_table(unsigned long phys, unsigned long size)
+{
+	if (!phys || !size)
+		return NULL;
+
+	/*
+	 * temporarily use phys_to_virt(),
+	 * should be early_memremap(phys, size) here
+	 */
+	return phys_to_virt(phys);
+}
+
+void __init __acpi_unmap_table(char *map, unsigned long size)
+{
+	if (!map || !size)
+		return;
+
+	/* should be early_iounmap(map, size); */
+	return;
+}
+
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+{
+	*irq = gsi_to_irq(gsi);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
+
+/*
+ * success: return IRQ number (>=0)
+ * failure: return < 0
+ */
+int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
+{
+	return -1;
+}
+EXPORT_SYMBOL_GPL(acpi_register_gsi);
+
+void acpi_unregister_gsi(u32 gsi)
+{
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
+
+static int __init acpi_parse_fadt(struct acpi_table_header *table)
+{
+	return 0;
+}
+
+static void __init early_acpi_process_madt(void)
+{
+	return;
+}
+
+static void __init acpi_process_madt(void)
+{
+	return;
+}
+
+/*
+ * acpi_boot_table_init() and acpi_boot_init()
+ *  called from setup_arch(), always.
+ *	1. checksums all tables
+ *	2. enumerates lapics
+ *	3. enumerates io-apics
+ *
+ * acpi_table_init() is separated to allow reading SRAT without
+ * other side effects.
+ */
+void __init acpi_boot_table_init(void)
+{
+	/*
+	 * If acpi_disabled, bail out
+	 */
+	if (acpi_disabled)
+		return;
+
+	/*
+	 * Initialize the ACPI boot-time table parser.
+	 */
+	if (acpi_table_init()) {
+		disable_acpi();
+		return;
+	}
+}
+
+int __init early_acpi_boot_init(void)
+{
+	/*
+	 * If acpi_disabled, bail out
+	 */
+	if (acpi_disabled)
+		return 1;
+
+	/*
+	 * Process the Multiple APIC Description Table (MADT), if present
+	 */
+	early_acpi_process_madt();
+
+	return 0;
+}
+
+int __init acpi_boot_init(void)
+{
+	/*
+	 * If acpi_disabled, bail out
+	 */
+	if (acpi_disabled)
+		return 1;
+
+	acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt);
+
+	/*
+	 * Process the Multiple APIC Description Table (MADT), if present
+	 */
+	acpi_process_madt();
+
+	return 0;
+}
+
+static int __init parse_acpi(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+
+	/* "acpi=off" disables both ACPI table parsing and interpreter */
+	if (strcmp(arg, "off") == 0) {
+		disable_acpi();
+	}
+	/* acpi=strict disables out-of-spec workarounds */
+	else if (strcmp(arg, "strict") == 0) {
+		acpi_strict = 1;
+	}
+	return 0;
+}
+early_param("acpi", parse_acpi);