aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/acpi_amba.c122
-rw-r--r--drivers/acpi/acpi_platform.c19
-rw-r--r--drivers/acpi/apei/apei-base.c6
-rw-r--r--drivers/acpi/apei/erst.c3
-rw-r--r--drivers/acpi/bus.c26
-rw-r--r--drivers/acpi/internal.h7
-rw-r--r--drivers/acpi/osl.c158
-rw-r--r--drivers/acpi/scan.c1
-rw-r--r--drivers/acpi/tables.c2
10 files changed, 260 insertions, 85 deletions
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index cb648a49543a..edeb2d1d99be 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -43,6 +43,7 @@ acpi-y += pci_root.o pci_link.o pci_irq.o
43acpi-y += acpi_lpss.o acpi_apd.o 43acpi-y += acpi_lpss.o acpi_apd.o
44acpi-y += acpi_platform.o 44acpi-y += acpi_platform.o
45acpi-y += acpi_pnp.o 45acpi-y += acpi_pnp.o
46acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o
46acpi-y += int340x_thermal.o 47acpi-y += int340x_thermal.o
47acpi-y += power.o 48acpi-y += power.o
48acpi-y += event.o 49acpi-y += event.o
diff --git a/drivers/acpi/acpi_amba.c b/drivers/acpi/acpi_amba.c
new file mode 100644
index 000000000000..2a61b54ab968
--- /dev/null
+++ b/drivers/acpi/acpi_amba.c
@@ -0,0 +1,122 @@
1
2/*
3 * ACPI support for platform bus type.
4 *
5 * Copyright (C) 2015, Linaro Ltd
6 * Author: Graeme Gregory <graeme.gregory@linaro.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/acpi.h>
14#include <linux/amba/bus.h>
15#include <linux/clkdev.h>
16#include <linux/clk-provider.h>
17#include <linux/device.h>
18#include <linux/err.h>
19#include <linux/ioport.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22
23#include "internal.h"
24
25static const struct acpi_device_id amba_id_list[] = {
26 {"ARMH0061", 0}, /* PL061 GPIO Device */
27 {"", 0},
28};
29
30static void amba_register_dummy_clk(void)
31{
32 static struct clk *amba_dummy_clk;
33
34 /* If clock already registered */
35 if (amba_dummy_clk)
36 return;
37
38 amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL,
39 CLK_IS_ROOT, 0);
40 clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL);
41}
42
43static int amba_handler_attach(struct acpi_device *adev,
44 const struct acpi_device_id *id)
45{
46 struct amba_device *dev;
47 struct resource_entry *rentry;
48 struct list_head resource_list;
49 bool address_found = false;
50 int irq_no = 0;
51 int ret;
52
53 /* If the ACPI node already has a physical device attached, skip it. */
54 if (adev->physical_node_count)
55 return 0;
56
57 dev = amba_device_alloc(dev_name(&adev->dev), 0, 0);
58 if (!dev) {
59 dev_err(&adev->dev, "%s(): amba_device_alloc() failed\n",
60 __func__);
61 return -ENOMEM;
62 }
63
64 INIT_LIST_HEAD(&resource_list);
65 ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
66 if (ret < 0)
67 goto err_free;
68
69 list_for_each_entry(rentry, &resource_list, node) {
70 switch (resource_type(rentry->res)) {
71 case IORESOURCE_MEM:
72 if (!address_found) {
73 dev->res = *rentry->res;
74 address_found = true;
75 }
76 break;
77 case IORESOURCE_IRQ:
78 if (irq_no < AMBA_NR_IRQS)
79 dev->irq[irq_no++] = rentry->res->start;
80 break;
81 default:
82 dev_warn(&adev->dev, "Invalid resource\n");
83 break;
84 }
85 }
86
87 acpi_dev_free_resource_list(&resource_list);
88
89 /*
90 * If the ACPI node has a parent and that parent has a physical device
91 * attached to it, that physical device should be the parent of
92 * the amba device we are about to create.
93 */
94 if (adev->parent)
95 dev->dev.parent = acpi_get_first_physical_node(adev->parent);
96
97 ACPI_COMPANION_SET(&dev->dev, adev);
98
99 ret = amba_device_add(dev, &iomem_resource);
100 if (ret) {
101 dev_err(&adev->dev, "%s(): amba_device_add() failed (%d)\n",
102 __func__, ret);
103 goto err_free;
104 }
105
106 return 1;
107
108err_free:
109 amba_device_put(dev);
110 return ret;
111}
112
113static struct acpi_scan_handler amba_handler = {
114 .ids = amba_id_list,
115 .attach = amba_handler_attach,
116};
117
118void __init acpi_amba_init(void)
119{
120 amba_register_dummy_clk();
121 acpi_scan_add_handler(&amba_handler);
122}
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index 296b7a14893a..c3af1088bf6b 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -43,7 +43,6 @@ static const struct acpi_device_id forbidden_id_list[] = {
43struct platform_device *acpi_create_platform_device(struct acpi_device *adev) 43struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
44{ 44{
45 struct platform_device *pdev = NULL; 45 struct platform_device *pdev = NULL;
46 struct acpi_device *acpi_parent;
47 struct platform_device_info pdevinfo; 46 struct platform_device_info pdevinfo;
48 struct resource_entry *rentry; 47 struct resource_entry *rentry;
49 struct list_head resource_list; 48 struct list_head resource_list;
@@ -82,22 +81,8 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
82 * attached to it, that physical device should be the parent of the 81 * attached to it, that physical device should be the parent of the
83 * platform device we are about to create. 82 * platform device we are about to create.
84 */ 83 */
85 pdevinfo.parent = NULL; 84 pdevinfo.parent = adev->parent ?
86 acpi_parent = adev->parent; 85 acpi_get_first_physical_node(adev->parent) : NULL;
87 if (acpi_parent) {
88 struct acpi_device_physical_node *entry;
89 struct list_head *list;
90
91 mutex_lock(&acpi_parent->physical_node_lock);
92 list = &acpi_parent->physical_node_list;
93 if (!list_empty(list)) {
94 entry = list_first_entry(list,
95 struct acpi_device_physical_node,
96 node);
97 pdevinfo.parent = entry->dev;
98 }
99 mutex_unlock(&acpi_parent->physical_node_lock);
100 }
101 pdevinfo.name = dev_name(&adev->dev); 86 pdevinfo.name = dev_name(&adev->dev);
102 pdevinfo.id = -1; 87 pdevinfo.id = -1;
103 pdevinfo.res = resources; 88 pdevinfo.res = resources;
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index a2c8d7adb6eb..da370e1d31f4 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -536,7 +536,8 @@ int apei_resources_request(struct apei_resources *resources,
536 goto err_unmap_ioport; 536 goto err_unmap_ioport;
537 } 537 }
538 538
539 return 0; 539 goto arch_res_fini;
540
540err_unmap_ioport: 541err_unmap_ioport:
541 list_for_each_entry(res, &resources->ioport, list) { 542 list_for_each_entry(res, &resources->ioport, list) {
542 if (res == res_bak) 543 if (res == res_bak)
@@ -551,7 +552,8 @@ err_unmap_iomem:
551 release_mem_region(res->start, res->end - res->start); 552 release_mem_region(res->start, res->end - res->start);
552 } 553 }
553arch_res_fini: 554arch_res_fini:
554 apei_resources_fini(&arch_res); 555 if (arch_apei_filter_addr)
556 apei_resources_fini(&arch_res);
555nvs_res_fini: 557nvs_res_fini:
556 apei_resources_fini(&nvs_resources); 558 apei_resources_fini(&nvs_resources);
557 return rc; 559 return rc;
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 6e6bc1059301..006c3894c6ea 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -1207,6 +1207,9 @@ static int __init erst_init(void)
1207 "Failed to allocate %lld bytes for persistent store error log.\n", 1207 "Failed to allocate %lld bytes for persistent store error log.\n",
1208 erst_erange.size); 1208 erst_erange.size);
1209 1209
1210 /* Cleanup ERST Resources */
1211 apei_resources_fini(&erst_resources);
1212
1210 return 0; 1213 return 0;
1211 1214
1212err_release_erange: 1215err_release_erange:
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 891c42d1cd65..0e8567846f1a 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -479,24 +479,38 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device)
479 Device Matching 479 Device Matching
480 -------------------------------------------------------------------------- */ 480 -------------------------------------------------------------------------- */
481 481
482static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev, 482/**
483 const struct device *dev) 483 * acpi_get_first_physical_node - Get first physical node of an ACPI device
484 * @adev: ACPI device in question
485 *
486 * Return: First physical node of ACPI device @adev
487 */
488struct device *acpi_get_first_physical_node(struct acpi_device *adev)
484{ 489{
485 struct mutex *physical_node_lock = &adev->physical_node_lock; 490 struct mutex *physical_node_lock = &adev->physical_node_lock;
491 struct device *phys_dev;
486 492
487 mutex_lock(physical_node_lock); 493 mutex_lock(physical_node_lock);
488 if (list_empty(&adev->physical_node_list)) { 494 if (list_empty(&adev->physical_node_list)) {
489 adev = NULL; 495 phys_dev = NULL;
490 } else { 496 } else {
491 const struct acpi_device_physical_node *node; 497 const struct acpi_device_physical_node *node;
492 498
493 node = list_first_entry(&adev->physical_node_list, 499 node = list_first_entry(&adev->physical_node_list,
494 struct acpi_device_physical_node, node); 500 struct acpi_device_physical_node, node);
495 if (node->dev != dev) 501
496 adev = NULL; 502 phys_dev = node->dev;
497 } 503 }
498 mutex_unlock(physical_node_lock); 504 mutex_unlock(physical_node_lock);
499 return adev; 505 return phys_dev;
506}
507
508static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev,
509 const struct device *dev)
510{
511 const struct device *phys_dev = acpi_get_first_physical_node(adev);
512
513 return phys_dev && phys_dev == dev ? adev : NULL;
500} 514}
501 515
502/** 516/**
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 1e6833a5cd44..a37508ef66c1 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -20,6 +20,7 @@
20 20
21#define PREFIX "ACPI: " 21#define PREFIX "ACPI: "
22 22
23void acpi_initrd_initialize_tables(void);
23acpi_status acpi_os_initialize1(void); 24acpi_status acpi_os_initialize1(void);
24void init_acpi_device_notify(void); 25void init_acpi_device_notify(void);
25int acpi_scan_init(void); 26int acpi_scan_init(void);
@@ -29,6 +30,11 @@ void acpi_processor_init(void);
29void acpi_platform_init(void); 30void acpi_platform_init(void);
30void acpi_pnp_init(void); 31void acpi_pnp_init(void);
31void acpi_int340x_thermal_init(void); 32void acpi_int340x_thermal_init(void);
33#ifdef CONFIG_ARM_AMBA
34void acpi_amba_init(void);
35#else
36static inline void acpi_amba_init(void) {}
37#endif
32int acpi_sysfs_init(void); 38int acpi_sysfs_init(void);
33void acpi_container_init(void); 39void acpi_container_init(void);
34void acpi_memory_hotplug_init(void); 40void acpi_memory_hotplug_init(void);
@@ -106,6 +112,7 @@ bool acpi_device_is_present(struct acpi_device *adev);
106bool acpi_device_is_battery(struct acpi_device *adev); 112bool acpi_device_is_battery(struct acpi_device *adev);
107bool acpi_device_is_first_physical_node(struct acpi_device *adev, 113bool acpi_device_is_first_physical_node(struct acpi_device *adev,
108 const struct device *dev); 114 const struct device *dev);
115struct device *acpi_get_first_physical_node(struct acpi_device *adev);
109 116
110/* -------------------------------------------------------------------------- 117/* --------------------------------------------------------------------------
111 Device Matching and Notification 118 Device Matching and Notification
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 67da6fb72274..814d5f83b75e 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -602,6 +602,14 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
602 return AE_OK; 602 return AE_OK;
603} 603}
604 604
605static void acpi_table_taint(struct acpi_table_header *table)
606{
607 pr_warn(PREFIX
608 "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
609 table->signature, table->oem_table_id);
610 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
611}
612
605#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE 613#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
606#include <linux/earlycpio.h> 614#include <linux/earlycpio.h>
607#include <linux/memblock.h> 615#include <linux/memblock.h>
@@ -636,6 +644,7 @@ static const char * const table_sigs[] = {
636 644
637#define ACPI_OVERRIDE_TABLES 64 645#define ACPI_OVERRIDE_TABLES 64
638static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES]; 646static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
647static DECLARE_BITMAP(acpi_initrd_installed, ACPI_OVERRIDE_TABLES);
639 648
640#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT) 649#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT)
641 650
@@ -746,96 +755,125 @@ void __init acpi_initrd_override(void *data, size_t size)
746 } 755 }
747 } 756 }
748} 757}
749#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
750 758
751static void acpi_table_taint(struct acpi_table_header *table) 759acpi_status
760acpi_os_physical_table_override(struct acpi_table_header *existing_table,
761 acpi_physical_address *address, u32 *length)
752{ 762{
753 pr_warn(PREFIX 763 int table_offset = 0;
754 "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n", 764 int table_index = 0;
755 table->signature, table->oem_table_id); 765 struct acpi_table_header *table;
756 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE); 766 u32 table_length;
757}
758 767
768 *length = 0;
769 *address = 0;
770 if (!acpi_tables_addr)
771 return AE_OK;
759 772
760acpi_status 773 while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
761acpi_os_table_override(struct acpi_table_header * existing_table, 774 table = acpi_os_map_memory(acpi_tables_addr + table_offset,
762 struct acpi_table_header ** new_table) 775 ACPI_HEADER_SIZE);
763{ 776 if (table_offset + table->length > all_tables_size) {
764 if (!existing_table || !new_table) 777 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
765 return AE_BAD_PARAMETER; 778 WARN_ON(1);
779 return AE_OK;
780 }
766 781
767 *new_table = NULL; 782 table_length = table->length;
768 783
769#ifdef CONFIG_ACPI_CUSTOM_DSDT 784 /* Only override tables matched */
770 if (strncmp(existing_table->signature, "DSDT", 4) == 0) 785 if (test_bit(table_index, acpi_initrd_installed) ||
771 *new_table = (struct acpi_table_header *)AmlCode; 786 memcmp(existing_table->signature, table->signature, 4) ||
772#endif 787 memcmp(table->oem_table_id, existing_table->oem_table_id,
773 if (*new_table != NULL) 788 ACPI_OEM_TABLE_ID_SIZE)) {
789 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
790 goto next_table;
791 }
792
793 *length = table_length;
794 *address = acpi_tables_addr + table_offset;
774 acpi_table_taint(existing_table); 795 acpi_table_taint(existing_table);
796 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
797 set_bit(table_index, acpi_initrd_installed);
798 break;
799
800next_table:
801 table_offset += table_length;
802 table_index++;
803 }
775 return AE_OK; 804 return AE_OK;
776} 805}
777 806
778acpi_status 807void __init acpi_initrd_initialize_tables(void)
779acpi_os_physical_table_override(struct acpi_table_header *existing_table,
780 acpi_physical_address *address,
781 u32 *table_length)
782{ 808{
783#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
784 *table_length = 0;
785 *address = 0;
786 return AE_OK;
787#else
788 int table_offset = 0; 809 int table_offset = 0;
810 int table_index = 0;
811 u32 table_length;
789 struct acpi_table_header *table; 812 struct acpi_table_header *table;
790 813
791 *table_length = 0;
792 *address = 0;
793
794 if (!acpi_tables_addr) 814 if (!acpi_tables_addr)
795 return AE_OK; 815 return;
796
797 do {
798 if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
799 WARN_ON(1);
800 return AE_OK;
801 }
802 816
817 while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
803 table = acpi_os_map_memory(acpi_tables_addr + table_offset, 818 table = acpi_os_map_memory(acpi_tables_addr + table_offset,
804 ACPI_HEADER_SIZE); 819 ACPI_HEADER_SIZE);
805
806 if (table_offset + table->length > all_tables_size) { 820 if (table_offset + table->length > all_tables_size) {
807 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); 821 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
808 WARN_ON(1); 822 WARN_ON(1);
809 return AE_OK; 823 return;
810 } 824 }
811 825
812 table_offset += table->length; 826 table_length = table->length;
813 827
814 if (memcmp(existing_table->signature, table->signature, 4)) { 828 /* Skip RSDT/XSDT which should only be used for override */
815 acpi_os_unmap_memory(table, 829 if (test_bit(table_index, acpi_initrd_installed) ||
816 ACPI_HEADER_SIZE); 830 ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) ||
817 continue; 831 ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) {
818 } 832 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
819 833 goto next_table;
820 /* Only override tables with matching oem id */
821 if (memcmp(table->oem_table_id, existing_table->oem_table_id,
822 ACPI_OEM_TABLE_ID_SIZE)) {
823 acpi_os_unmap_memory(table,
824 ACPI_HEADER_SIZE);
825 continue;
826 } 834 }
827 835
828 table_offset -= table->length; 836 acpi_table_taint(table);
829 *table_length = table->length;
830 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); 837 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
831 *address = acpi_tables_addr + table_offset; 838 acpi_install_table(acpi_tables_addr + table_offset, TRUE);
832 break; 839 set_bit(table_index, acpi_initrd_installed);
833 } while (table_offset + ACPI_HEADER_SIZE < all_tables_size); 840next_table:
841 table_offset += table_length;
842 table_index++;
843 }
844}
845#else
846acpi_status
847acpi_os_physical_table_override(struct acpi_table_header *existing_table,
848 acpi_physical_address *address,
849 u32 *table_length)
850{
851 *table_length = 0;
852 *address = 0;
853 return AE_OK;
854}
855
856void __init acpi_initrd_initialize_tables(void)
857{
858}
859#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
834 860
835 if (*address != 0) 861acpi_status
862acpi_os_table_override(struct acpi_table_header *existing_table,
863 struct acpi_table_header **new_table)
864{
865 if (!existing_table || !new_table)
866 return AE_BAD_PARAMETER;
867
868 *new_table = NULL;
869
870#ifdef CONFIG_ACPI_CUSTOM_DSDT
871 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
872 *new_table = (struct acpi_table_header *)AmlCode;
873#endif
874 if (*new_table != NULL)
836 acpi_table_taint(existing_table); 875 acpi_table_taint(existing_table);
837 return AE_OK; 876 return AE_OK;
838#endif
839} 877}
840 878
841static irqreturn_t acpi_irq(int irq, void *dev_id) 879static irqreturn_t acpi_irq(int irq, void *dev_id)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 407a3760e8de..5f28cf778349 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1930,6 +1930,7 @@ int __init acpi_scan_init(void)
1930 acpi_memory_hotplug_init(); 1930 acpi_memory_hotplug_init();
1931 acpi_pnp_init(); 1931 acpi_pnp_init();
1932 acpi_int340x_thermal_init(); 1932 acpi_int340x_thermal_init();
1933 acpi_amba_init();
1933 1934
1934 acpi_scan_add_handler(&generic_device_handler); 1935 acpi_scan_add_handler(&generic_device_handler);
1935 1936
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 6c0f0794aa82..57c0a4525dba 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -32,6 +32,7 @@
32#include <linux/errno.h> 32#include <linux/errno.h>
33#include <linux/acpi.h> 33#include <linux/acpi.h>
34#include <linux/bootmem.h> 34#include <linux/bootmem.h>
35#include "internal.h"
35 36
36#define ACPI_MAX_TABLES 128 37#define ACPI_MAX_TABLES 128
37 38
@@ -456,6 +457,7 @@ int __init acpi_table_init(void)
456 status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); 457 status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
457 if (ACPI_FAILURE(status)) 458 if (ACPI_FAILURE(status))
458 return -EINVAL; 459 return -EINVAL;
460 acpi_initrd_initialize_tables();
459 461
460 check_multiple_madt(); 462 check_multiple_madt();
461 return 0; 463 return 0;