summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/include/asm/acpi.h12
-rw-r--r--arch/arm64/include/asm/fixmap.h7
-rw-r--r--arch/arm64/mm/mmu.c4
-rw-r--r--arch/x86/include/asm/fixmap.h6
-rw-r--r--arch/x86/kernel/acpi/apei.c5
-rw-r--r--drivers/acpi/Kconfig16
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/apei/erst.c2
-rw-r--r--drivers/acpi/apei/ghes.c117
-rw-r--r--drivers/acpi/pmic/tps68470_pmic.c455
-rw-r--r--drivers/acpi/x86/utils.c18
-rw-r--r--include/acpi/apei.h1
12 files changed, 530 insertions, 115 deletions
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 59cca1d6ec54..32f465a80e4e 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -126,18 +126,6 @@ static inline const char *acpi_get_enable_method(int cpu)
126 */ 126 */
127#define acpi_disable_cmcff 1 127#define acpi_disable_cmcff 1
128pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr); 128pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
129
130/*
131 * Despite its name, this function must still broadcast the TLB
132 * invalidation in order to ensure other CPUs don't end up with junk
133 * entries as a result of speculation. Unusually, its also called in
134 * IRQ context (ghes_iounmap_irq) so if we ever need to use IPIs for
135 * TLB broadcasting, then we're in trouble here.
136 */
137static inline void arch_apei_flush_tlb_one(unsigned long addr)
138{
139 flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
140}
141#endif /* CONFIG_ACPI_APEI */ 129#endif /* CONFIG_ACPI_APEI */
142 130
143#ifdef CONFIG_ACPI_NUMA 131#ifdef CONFIG_ACPI_NUMA
diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
index caf86be815ba..4052ec39e8db 100644
--- a/arch/arm64/include/asm/fixmap.h
+++ b/arch/arm64/include/asm/fixmap.h
@@ -51,6 +51,13 @@ enum fixed_addresses {
51 51
52 FIX_EARLYCON_MEM_BASE, 52 FIX_EARLYCON_MEM_BASE,
53 FIX_TEXT_POKE0, 53 FIX_TEXT_POKE0,
54
55#ifdef CONFIG_ACPI_APEI_GHES
56 /* Used for GHES mapping from assorted contexts */
57 FIX_APEI_GHES_IRQ,
58 FIX_APEI_GHES_NMI,
59#endif /* CONFIG_ACPI_APEI_GHES */
60
54 __end_of_permanent_fixed_addresses, 61 __end_of_permanent_fixed_addresses,
55 62
56 /* 63 /*
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index f1eb15e0e864..267d2b79d52d 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -778,6 +778,10 @@ void __init early_fixmap_init(void)
778 } 778 }
779} 779}
780 780
781/*
782 * Unusually, this is also called in IRQ context (ghes_iounmap_irq) so if we
783 * ever need to use IPIs for TLB broadcasting, then we're in trouble here.
784 */
781void __set_fixmap(enum fixed_addresses idx, 785void __set_fixmap(enum fixed_addresses idx,
782 phys_addr_t phys, pgprot_t flags) 786 phys_addr_t phys, pgprot_t flags)
783{ 787{
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index dcd9fb55e679..b0c505fe9a95 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -104,6 +104,12 @@ enum fixed_addresses {
104 FIX_GDT_REMAP_BEGIN, 104 FIX_GDT_REMAP_BEGIN,
105 FIX_GDT_REMAP_END = FIX_GDT_REMAP_BEGIN + NR_CPUS - 1, 105 FIX_GDT_REMAP_END = FIX_GDT_REMAP_BEGIN + NR_CPUS - 1,
106 106
107#ifdef CONFIG_ACPI_APEI_GHES
108 /* Used for GHES mapping from assorted contexts */
109 FIX_APEI_GHES_IRQ,
110 FIX_APEI_GHES_NMI,
111#endif
112
107 __end_of_permanent_fixed_addresses, 113 __end_of_permanent_fixed_addresses,
108 114
109 /* 115 /*
diff --git a/arch/x86/kernel/acpi/apei.c b/arch/x86/kernel/acpi/apei.c
index ea3046e0b0cf..bb8d300fecbd 100644
--- a/arch/x86/kernel/acpi/apei.c
+++ b/arch/x86/kernel/acpi/apei.c
@@ -52,8 +52,3 @@ void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
52 apei_mce_report_mem_error(sev, mem_err); 52 apei_mce_report_mem_error(sev, mem_err);
53#endif 53#endif
54} 54}
55
56void arch_apei_flush_tlb_one(unsigned long addr)
57{
58 __flush_tlb_one(addr);
59}
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 5b1938f4b626..c9781175e59e 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -536,4 +536,20 @@ if ARM64
536source "drivers/acpi/arm64/Kconfig" 536source "drivers/acpi/arm64/Kconfig"
537endif 537endif
538 538
539config TPS68470_PMIC_OPREGION
540 bool "ACPI operation region support for TPS68470 PMIC"
541 depends on MFD_TPS68470
542 help
543 This config adds ACPI operation region support for TI TPS68470 PMIC.
544 TPS68470 device is an advanced power management unit that powers
545 a Compact Camera Module (CCM), generates clocks for image sensors,
546 drives a dual LED for flash and incorporates two LED drivers for
547 general purpose indicators.
548 This driver enables ACPI operation region support control voltage
549 regulators and clocks.
550
551 This option is a bool as it provides an ACPI operation
552 region, which must be available before any of the devices
553 using this, are probed.
554
539endif # ACPI 555endif # ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index cd1abc9bc325..709c1120f315 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -108,6 +108,8 @@ obj-$(CONFIG_CHT_WC_PMIC_OPREGION) += pmic/intel_pmic_chtwc.o
108 108
109obj-$(CONFIG_ACPI_CONFIGFS) += acpi_configfs.o 109obj-$(CONFIG_ACPI_CONFIGFS) += acpi_configfs.o
110 110
111obj-$(CONFIG_TPS68470_PMIC_OPREGION) += pmic/tps68470_pmic.o
112
111video-objs += acpi_video.o video_detect.o 113video-objs += acpi_video.o video_detect.o
112obj-y += dptf/ 114obj-y += dptf/
113 115
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 2c462beee551..6742f6c68034 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -1061,7 +1061,7 @@ static int erst_writer(struct pstore_record *record)
1061 rcd->hdr.error_severity = CPER_SEV_FATAL; 1061 rcd->hdr.error_severity = CPER_SEV_FATAL;
1062 /* timestamp valid. platform_id, partition_id are invalid */ 1062 /* timestamp valid. platform_id, partition_id are invalid */
1063 rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP; 1063 rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP;
1064 rcd->hdr.timestamp = get_seconds(); 1064 rcd->hdr.timestamp = ktime_get_real_seconds();
1065 rcd->hdr.record_length = sizeof(*rcd) + record->size; 1065 rcd->hdr.record_length = sizeof(*rcd) + record->size;
1066 rcd->hdr.creator_id = CPER_CREATOR_PSTORE; 1066 rcd->hdr.creator_id = CPER_CREATOR_PSTORE;
1067 rcd->hdr.notification_type = CPER_NOTIFY_MCE; 1067 rcd->hdr.notification_type = CPER_NOTIFY_MCE;
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 3c3a37b8503b..f14695e744d0 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -51,6 +51,7 @@
51#include <acpi/actbl1.h> 51#include <acpi/actbl1.h>
52#include <acpi/ghes.h> 52#include <acpi/ghes.h>
53#include <acpi/apei.h> 53#include <acpi/apei.h>
54#include <asm/fixmap.h>
54#include <asm/tlbflush.h> 55#include <asm/tlbflush.h>
55#include <ras/ras_event.h> 56#include <ras/ras_event.h>
56 57
@@ -112,22 +113,10 @@ static DEFINE_MUTEX(ghes_list_mutex);
112 * Because the memory area used to transfer hardware error information 113 * Because the memory area used to transfer hardware error information
113 * from BIOS to Linux can be determined only in NMI, IRQ or timer 114 * from BIOS to Linux can be determined only in NMI, IRQ or timer
114 * handler, but general ioremap can not be used in atomic context, so 115 * handler, but general ioremap can not be used in atomic context, so
115 * a special version of atomic ioremap is implemented for that. 116 * the fixmap is used instead.
116 */ 117 *
117 118 * These 2 spinlocks are used to prevent the fixmap entries from being used
118/* 119 * simultaneously.
119 * Two virtual pages are used, one for IRQ/PROCESS context, the other for
120 * NMI context (optionally).
121 */
122#define GHES_IOREMAP_PAGES 2
123#define GHES_IOREMAP_IRQ_PAGE(base) (base)
124#define GHES_IOREMAP_NMI_PAGE(base) ((base) + PAGE_SIZE)
125
126/* virtual memory area for atomic ioremap */
127static struct vm_struct *ghes_ioremap_area;
128/*
129 * These 2 spinlock is used to prevent atomic ioremap virtual memory
130 * area from being mapped simultaneously.
131 */ 120 */
132static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi); 121static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi);
133static DEFINE_SPINLOCK(ghes_ioremap_lock_irq); 122static DEFINE_SPINLOCK(ghes_ioremap_lock_irq);
@@ -140,71 +129,38 @@ static atomic_t ghes_estatus_cache_alloced;
140 129
141static int ghes_panic_timeout __read_mostly = 30; 130static int ghes_panic_timeout __read_mostly = 30;
142 131
143static int ghes_ioremap_init(void)
144{
145 ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES,
146 VM_IOREMAP, VMALLOC_START, VMALLOC_END);
147 if (!ghes_ioremap_area) {
148 pr_err(GHES_PFX "Failed to allocate virtual memory area for atomic ioremap.\n");
149 return -ENOMEM;
150 }
151
152 return 0;
153}
154
155static void ghes_ioremap_exit(void)
156{
157 free_vm_area(ghes_ioremap_area);
158}
159
160static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn) 132static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
161{ 133{
162 unsigned long vaddr;
163 phys_addr_t paddr; 134 phys_addr_t paddr;
164 pgprot_t prot; 135 pgprot_t prot;
165 136
166 vaddr = (unsigned long)GHES_IOREMAP_NMI_PAGE(ghes_ioremap_area->addr);
167
168 paddr = pfn << PAGE_SHIFT; 137 paddr = pfn << PAGE_SHIFT;
169 prot = arch_apei_get_mem_attribute(paddr); 138 prot = arch_apei_get_mem_attribute(paddr);
170 ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot); 139 __set_fixmap(FIX_APEI_GHES_NMI, paddr, prot);
171 140
172 return (void __iomem *)vaddr; 141 return (void __iomem *) fix_to_virt(FIX_APEI_GHES_NMI);
173} 142}
174 143
175static void __iomem *ghes_ioremap_pfn_irq(u64 pfn) 144static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
176{ 145{
177 unsigned long vaddr, paddr; 146 phys_addr_t paddr;
178 pgprot_t prot; 147 pgprot_t prot;
179 148
180 vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
181
182 paddr = pfn << PAGE_SHIFT; 149 paddr = pfn << PAGE_SHIFT;
183 prot = arch_apei_get_mem_attribute(paddr); 150 prot = arch_apei_get_mem_attribute(paddr);
151 __set_fixmap(FIX_APEI_GHES_IRQ, paddr, prot);
184 152
185 ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot); 153 return (void __iomem *) fix_to_virt(FIX_APEI_GHES_IRQ);
186
187 return (void __iomem *)vaddr;
188} 154}
189 155
190static void ghes_iounmap_nmi(void __iomem *vaddr_ptr) 156static void ghes_iounmap_nmi(void)
191{ 157{
192 unsigned long vaddr = (unsigned long __force)vaddr_ptr; 158 clear_fixmap(FIX_APEI_GHES_NMI);
193 void *base = ghes_ioremap_area->addr;
194
195 BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base));
196 unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
197 arch_apei_flush_tlb_one(vaddr);
198} 159}
199 160
200static void ghes_iounmap_irq(void __iomem *vaddr_ptr) 161static void ghes_iounmap_irq(void)
201{ 162{
202 unsigned long vaddr = (unsigned long __force)vaddr_ptr; 163 clear_fixmap(FIX_APEI_GHES_IRQ);
203 void *base = ghes_ioremap_area->addr;
204
205 BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base));
206 unmap_kernel_range_noflush(vaddr, PAGE_SIZE);
207 arch_apei_flush_tlb_one(vaddr);
208} 164}
209 165
210static int ghes_estatus_pool_init(void) 166static int ghes_estatus_pool_init(void)
@@ -360,10 +316,10 @@ static void ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len,
360 paddr += trunk; 316 paddr += trunk;
361 buffer += trunk; 317 buffer += trunk;
362 if (in_nmi) { 318 if (in_nmi) {
363 ghes_iounmap_nmi(vaddr); 319 ghes_iounmap_nmi();
364 raw_spin_unlock(&ghes_ioremap_lock_nmi); 320 raw_spin_unlock(&ghes_ioremap_lock_nmi);
365 } else { 321 } else {
366 ghes_iounmap_irq(vaddr); 322 ghes_iounmap_irq();
367 spin_unlock_irqrestore(&ghes_ioremap_lock_irq, flags); 323 spin_unlock_irqrestore(&ghes_ioremap_lock_irq, flags);
368 } 324 }
369 } 325 }
@@ -851,17 +807,8 @@ static void ghes_sea_remove(struct ghes *ghes)
851 synchronize_rcu(); 807 synchronize_rcu();
852} 808}
853#else /* CONFIG_ACPI_APEI_SEA */ 809#else /* CONFIG_ACPI_APEI_SEA */
854static inline void ghes_sea_add(struct ghes *ghes) 810static inline void ghes_sea_add(struct ghes *ghes) { }
855{ 811static inline void ghes_sea_remove(struct ghes *ghes) { }
856 pr_err(GHES_PFX "ID: %d, trying to add SEA notification which is not supported\n",
857 ghes->generic->header.source_id);
858}
859
860static inline void ghes_sea_remove(struct ghes *ghes)
861{
862 pr_err(GHES_PFX "ID: %d, trying to remove SEA notification which is not supported\n",
863 ghes->generic->header.source_id);
864}
865#endif /* CONFIG_ACPI_APEI_SEA */ 812#endif /* CONFIG_ACPI_APEI_SEA */
866 813
867#ifdef CONFIG_HAVE_ACPI_APEI_NMI 814#ifdef CONFIG_HAVE_ACPI_APEI_NMI
@@ -1063,23 +1010,9 @@ static void ghes_nmi_init_cxt(void)
1063 init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq); 1010 init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq);
1064} 1011}
1065#else /* CONFIG_HAVE_ACPI_APEI_NMI */ 1012#else /* CONFIG_HAVE_ACPI_APEI_NMI */
1066static inline void ghes_nmi_add(struct ghes *ghes) 1013static inline void ghes_nmi_add(struct ghes *ghes) { }
1067{ 1014static inline void ghes_nmi_remove(struct ghes *ghes) { }
1068 pr_err(GHES_PFX "ID: %d, trying to add NMI notification which is not supported!\n", 1015static inline void ghes_nmi_init_cxt(void) { }
1069 ghes->generic->header.source_id);
1070 BUG();
1071}
1072
1073static inline void ghes_nmi_remove(struct ghes *ghes)
1074{
1075 pr_err(GHES_PFX "ID: %d, trying to remove NMI notification which is not supported!\n",
1076 ghes->generic->header.source_id);
1077 BUG();
1078}
1079
1080static inline void ghes_nmi_init_cxt(void)
1081{
1082}
1083#endif /* CONFIG_HAVE_ACPI_APEI_NMI */ 1016#endif /* CONFIG_HAVE_ACPI_APEI_NMI */
1084 1017
1085static int ghes_probe(struct platform_device *ghes_dev) 1018static int ghes_probe(struct platform_device *ghes_dev)
@@ -1285,13 +1218,9 @@ static int __init ghes_init(void)
1285 1218
1286 ghes_nmi_init_cxt(); 1219 ghes_nmi_init_cxt();
1287 1220
1288 rc = ghes_ioremap_init();
1289 if (rc)
1290 goto err;
1291
1292 rc = ghes_estatus_pool_init(); 1221 rc = ghes_estatus_pool_init();
1293 if (rc) 1222 if (rc)
1294 goto err_ioremap_exit; 1223 goto err;
1295 1224
1296 rc = ghes_estatus_pool_expand(GHES_ESTATUS_CACHE_AVG_SIZE * 1225 rc = ghes_estatus_pool_expand(GHES_ESTATUS_CACHE_AVG_SIZE *
1297 GHES_ESTATUS_CACHE_ALLOCED_MAX); 1226 GHES_ESTATUS_CACHE_ALLOCED_MAX);
@@ -1315,8 +1244,6 @@ static int __init ghes_init(void)
1315 return 0; 1244 return 0;
1316err_pool_exit: 1245err_pool_exit:
1317 ghes_estatus_pool_exit(); 1246 ghes_estatus_pool_exit();
1318err_ioremap_exit:
1319 ghes_ioremap_exit();
1320err: 1247err:
1321 return rc; 1248 return rc;
1322} 1249}
diff --git a/drivers/acpi/pmic/tps68470_pmic.c b/drivers/acpi/pmic/tps68470_pmic.c
new file mode 100644
index 000000000000..7f3c567e8168
--- /dev/null
+++ b/drivers/acpi/pmic/tps68470_pmic.c
@@ -0,0 +1,455 @@
1/*
2 * TI TPS68470 PMIC operation region driver
3 *
4 * Copyright (C) 2017 Intel Corporation. All rights reserved.
5 *
6 * Author: Rajmohan Mani <rajmohan.mani@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * Based on drivers/acpi/pmic/intel_pmic* drivers
18 */
19
20#include <linux/acpi.h>
21#include <linux/mfd/tps68470.h>
22#include <linux/init.h>
23#include <linux/platform_device.h>
24#include <linux/regmap.h>
25
26struct tps68470_pmic_table {
27 u32 address; /* operation region address */
28 u32 reg; /* corresponding register */
29 u32 bitmask; /* bit mask for power, clock */
30};
31
32#define TI_PMIC_POWER_OPREGION_ID 0xB0
33#define TI_PMIC_VR_VAL_OPREGION_ID 0xB1
34#define TI_PMIC_CLOCK_OPREGION_ID 0xB2
35#define TI_PMIC_CLKFREQ_OPREGION_ID 0xB3
36
37struct tps68470_pmic_opregion {
38 struct mutex lock;
39 struct regmap *regmap;
40};
41
42#define S_IO_I2C_EN (BIT(0) | BIT(1))
43
44static const struct tps68470_pmic_table power_table[] = {
45 {
46 .address = 0x00,
47 .reg = TPS68470_REG_S_I2C_CTL,
48 .bitmask = S_IO_I2C_EN,
49 /* S_I2C_CTL */
50 },
51 {
52 .address = 0x04,
53 .reg = TPS68470_REG_VCMCTL,
54 .bitmask = BIT(0),
55 /* VCMCTL */
56 },
57 {
58 .address = 0x08,
59 .reg = TPS68470_REG_VAUX1CTL,
60 .bitmask = BIT(0),
61 /* VAUX1_CTL */
62 },
63 {
64 .address = 0x0C,
65 .reg = TPS68470_REG_VAUX2CTL,
66 .bitmask = BIT(0),
67 /* VAUX2CTL */
68 },
69 {
70 .address = 0x10,
71 .reg = TPS68470_REG_VACTL,
72 .bitmask = BIT(0),
73 /* VACTL */
74 },
75 {
76 .address = 0x14,
77 .reg = TPS68470_REG_VDCTL,
78 .bitmask = BIT(0),
79 /* VDCTL */
80 },
81};
82
83/* Table to set voltage regulator value */
84static const struct tps68470_pmic_table vr_val_table[] = {
85 {
86 .address = 0x00,
87 .reg = TPS68470_REG_VSIOVAL,
88 .bitmask = TPS68470_VSIOVAL_IOVOLT_MASK,
89 /* TPS68470_REG_VSIOVAL */
90 },
91 {
92 .address = 0x04,
93 .reg = TPS68470_REG_VIOVAL,
94 .bitmask = TPS68470_VIOVAL_IOVOLT_MASK,
95 /* TPS68470_REG_VIOVAL */
96 },
97 {
98 .address = 0x08,
99 .reg = TPS68470_REG_VCMVAL,
100 .bitmask = TPS68470_VCMVAL_VCVOLT_MASK,
101 /* TPS68470_REG_VCMVAL */
102 },
103 {
104 .address = 0x0C,
105 .reg = TPS68470_REG_VAUX1VAL,
106 .bitmask = TPS68470_VAUX1VAL_AUX1VOLT_MASK,
107 /* TPS68470_REG_VAUX1VAL */
108 },
109 {
110 .address = 0x10,
111 .reg = TPS68470_REG_VAUX2VAL,
112 .bitmask = TPS68470_VAUX2VAL_AUX2VOLT_MASK,
113 /* TPS68470_REG_VAUX2VAL */
114 },
115 {
116 .address = 0x14,
117 .reg = TPS68470_REG_VAVAL,
118 .bitmask = TPS68470_VAVAL_AVOLT_MASK,
119 /* TPS68470_REG_VAVAL */
120 },
121 {
122 .address = 0x18,
123 .reg = TPS68470_REG_VDVAL,
124 .bitmask = TPS68470_VDVAL_DVOLT_MASK,
125 /* TPS68470_REG_VDVAL */
126 },
127};
128
129/* Table to configure clock frequency */
130static const struct tps68470_pmic_table clk_freq_table[] = {
131 {
132 .address = 0x00,
133 .reg = TPS68470_REG_POSTDIV2,
134 .bitmask = BIT(0) | BIT(1),
135 /* TPS68470_REG_POSTDIV2 */
136 },
137 {
138 .address = 0x04,
139 .reg = TPS68470_REG_BOOSTDIV,
140 .bitmask = 0x1F,
141 /* TPS68470_REG_BOOSTDIV */
142 },
143 {
144 .address = 0x08,
145 .reg = TPS68470_REG_BUCKDIV,
146 .bitmask = 0x0F,
147 /* TPS68470_REG_BUCKDIV */
148 },
149 {
150 .address = 0x0C,
151 .reg = TPS68470_REG_PLLSWR,
152 .bitmask = 0x13,
153 /* TPS68470_REG_PLLSWR */
154 },
155 {
156 .address = 0x10,
157 .reg = TPS68470_REG_XTALDIV,
158 .bitmask = 0xFF,
159 /* TPS68470_REG_XTALDIV */
160 },
161 {
162 .address = 0x14,
163 .reg = TPS68470_REG_PLLDIV,
164 .bitmask = 0xFF,
165 /* TPS68470_REG_PLLDIV */
166 },
167 {
168 .address = 0x18,
169 .reg = TPS68470_REG_POSTDIV,
170 .bitmask = 0x83,
171 /* TPS68470_REG_POSTDIV */
172 },
173};
174
175/* Table to configure and enable clocks */
176static const struct tps68470_pmic_table clk_table[] = {
177 {
178 .address = 0x00,
179 .reg = TPS68470_REG_PLLCTL,
180 .bitmask = 0xF5,
181 /* TPS68470_REG_PLLCTL */
182 },
183 {
184 .address = 0x04,
185 .reg = TPS68470_REG_PLLCTL2,
186 .bitmask = BIT(0),
187 /* TPS68470_REG_PLLCTL2 */
188 },
189 {
190 .address = 0x08,
191 .reg = TPS68470_REG_CLKCFG1,
192 .bitmask = TPS68470_CLKCFG1_MODE_A_MASK |
193 TPS68470_CLKCFG1_MODE_B_MASK,
194 /* TPS68470_REG_CLKCFG1 */
195 },
196 {
197 .address = 0x0C,
198 .reg = TPS68470_REG_CLKCFG2,
199 .bitmask = TPS68470_CLKCFG1_MODE_A_MASK |
200 TPS68470_CLKCFG1_MODE_B_MASK,
201 /* TPS68470_REG_CLKCFG2 */
202 },
203};
204
205static int pmic_get_reg_bit(u64 address,
206 const struct tps68470_pmic_table *table,
207 const unsigned int table_size, int *reg,
208 int *bitmask)
209{
210 u64 i;
211
212 i = address / 4;
213 if (i >= table_size)
214 return -ENOENT;
215
216 if (!reg || !bitmask)
217 return -EINVAL;
218
219 *reg = table[i].reg;
220 *bitmask = table[i].bitmask;
221
222 return 0;
223}
224
225static int tps68470_pmic_get_power(struct regmap *regmap, int reg,
226 int bitmask, u64 *value)
227{
228 unsigned int data;
229
230 if (regmap_read(regmap, reg, &data))
231 return -EIO;
232
233 *value = (data & bitmask) ? 1 : 0;
234 return 0;
235}
236
237static int tps68470_pmic_get_vr_val(struct regmap *regmap, int reg,
238 int bitmask, u64 *value)
239{
240 unsigned int data;
241
242 if (regmap_read(regmap, reg, &data))
243 return -EIO;
244
245 *value = data & bitmask;
246 return 0;
247}
248
249static int tps68470_pmic_get_clk(struct regmap *regmap, int reg,
250 int bitmask, u64 *value)
251{
252 unsigned int data;
253
254 if (regmap_read(regmap, reg, &data))
255 return -EIO;
256
257 *value = (data & bitmask) ? 1 : 0;
258 return 0;
259}
260
261static int tps68470_pmic_get_clk_freq(struct regmap *regmap, int reg,
262 int bitmask, u64 *value)
263{
264 unsigned int data;
265
266 if (regmap_read(regmap, reg, &data))
267 return -EIO;
268
269 *value = data & bitmask;
270 return 0;
271}
272
273static int ti_tps68470_regmap_update_bits(struct regmap *regmap, int reg,
274 int bitmask, u64 value)
275{
276 return regmap_update_bits(regmap, reg, bitmask, value);
277}
278
279static acpi_status tps68470_pmic_common_handler(u32 function,
280 acpi_physical_address address,
281 u32 bits, u64 *value,
282 void *region_context,
283 int (*get)(struct regmap *,
284 int, int, u64 *),
285 int (*update)(struct regmap *,
286 int, int, u64),
287 const struct tps68470_pmic_table *tbl,
288 unsigned int tbl_size)
289{
290 struct tps68470_pmic_opregion *opregion = region_context;
291 struct regmap *regmap = opregion->regmap;
292 int reg, ret, bitmask;
293
294 if (bits != 32)
295 return AE_BAD_PARAMETER;
296
297 ret = pmic_get_reg_bit(address, tbl, tbl_size, &reg, &bitmask);
298 if (ret < 0)
299 return AE_BAD_PARAMETER;
300
301 if (function == ACPI_WRITE && *value > bitmask)
302 return AE_BAD_PARAMETER;
303
304 mutex_lock(&opregion->lock);
305
306 ret = (function == ACPI_READ) ?
307 get(regmap, reg, bitmask, value) :
308 update(regmap, reg, bitmask, *value);
309
310 mutex_unlock(&opregion->lock);
311
312 return ret ? AE_ERROR : AE_OK;
313}
314
315static acpi_status tps68470_pmic_cfreq_handler(u32 function,
316 acpi_physical_address address,
317 u32 bits, u64 *value,
318 void *handler_context,
319 void *region_context)
320{
321 return tps68470_pmic_common_handler(function, address, bits, value,
322 region_context,
323 tps68470_pmic_get_clk_freq,
324 ti_tps68470_regmap_update_bits,
325 clk_freq_table,
326 ARRAY_SIZE(clk_freq_table));
327}
328
329static acpi_status tps68470_pmic_clk_handler(u32 function,
330 acpi_physical_address address, u32 bits,
331 u64 *value, void *handler_context,
332 void *region_context)
333{
334 return tps68470_pmic_common_handler(function, address, bits, value,
335 region_context,
336 tps68470_pmic_get_clk,
337 ti_tps68470_regmap_update_bits,
338 clk_table,
339 ARRAY_SIZE(clk_table));
340}
341
342static acpi_status tps68470_pmic_vrval_handler(u32 function,
343 acpi_physical_address address,
344 u32 bits, u64 *value,
345 void *handler_context,
346 void *region_context)
347{
348 return tps68470_pmic_common_handler(function, address, bits, value,
349 region_context,
350 tps68470_pmic_get_vr_val,
351 ti_tps68470_regmap_update_bits,
352 vr_val_table,
353 ARRAY_SIZE(vr_val_table));
354}
355
356static acpi_status tps68470_pmic_pwr_handler(u32 function,
357 acpi_physical_address address,
358 u32 bits, u64 *value,
359 void *handler_context,
360 void *region_context)
361{
362 if (bits != 32)
363 return AE_BAD_PARAMETER;
364
365 /* set/clear for bit 0, bits 0 and 1 together */
366 if (function == ACPI_WRITE &&
367 !(*value == 0 || *value == 1 || *value == 3)) {
368 return AE_BAD_PARAMETER;
369 }
370
371 return tps68470_pmic_common_handler(function, address, bits, value,
372 region_context,
373 tps68470_pmic_get_power,
374 ti_tps68470_regmap_update_bits,
375 power_table,
376 ARRAY_SIZE(power_table));
377}
378
379static int tps68470_pmic_opregion_probe(struct platform_device *pdev)
380{
381 struct regmap *tps68470_regmap = dev_get_drvdata(pdev->dev.parent);
382 acpi_handle handle = ACPI_HANDLE(pdev->dev.parent);
383 struct device *dev = &pdev->dev;
384 struct tps68470_pmic_opregion *opregion;
385 acpi_status status;
386
387 if (!dev || !tps68470_regmap) {
388 dev_warn(dev, "dev or regmap is NULL\n");
389 return -EINVAL;
390 }
391
392 if (!handle) {
393 dev_warn(dev, "acpi handle is NULL\n");
394 return -ENODEV;
395 }
396
397 opregion = devm_kzalloc(dev, sizeof(*opregion), GFP_KERNEL);
398 if (!opregion)
399 return -ENOMEM;
400
401 mutex_init(&opregion->lock);
402 opregion->regmap = tps68470_regmap;
403
404 status = acpi_install_address_space_handler(handle,
405 TI_PMIC_POWER_OPREGION_ID,
406 tps68470_pmic_pwr_handler,
407 NULL, opregion);
408 if (ACPI_FAILURE(status))
409 goto out_mutex_destroy;
410
411 status = acpi_install_address_space_handler(handle,
412 TI_PMIC_VR_VAL_OPREGION_ID,
413 tps68470_pmic_vrval_handler,
414 NULL, opregion);
415 if (ACPI_FAILURE(status))
416 goto out_remove_power_handler;
417
418 status = acpi_install_address_space_handler(handle,
419 TI_PMIC_CLOCK_OPREGION_ID,
420 tps68470_pmic_clk_handler,
421 NULL, opregion);
422 if (ACPI_FAILURE(status))
423 goto out_remove_vr_val_handler;
424
425 status = acpi_install_address_space_handler(handle,
426 TI_PMIC_CLKFREQ_OPREGION_ID,
427 tps68470_pmic_cfreq_handler,
428 NULL, opregion);
429 if (ACPI_FAILURE(status))
430 goto out_remove_clk_handler;
431
432 return 0;
433
434out_remove_clk_handler:
435 acpi_remove_address_space_handler(handle, TI_PMIC_CLOCK_OPREGION_ID,
436 tps68470_pmic_clk_handler);
437out_remove_vr_val_handler:
438 acpi_remove_address_space_handler(handle, TI_PMIC_VR_VAL_OPREGION_ID,
439 tps68470_pmic_vrval_handler);
440out_remove_power_handler:
441 acpi_remove_address_space_handler(handle, TI_PMIC_POWER_OPREGION_ID,
442 tps68470_pmic_pwr_handler);
443out_mutex_destroy:
444 mutex_destroy(&opregion->lock);
445 return -ENODEV;
446}
447
448static struct platform_driver tps68470_pmic_opregion_driver = {
449 .probe = tps68470_pmic_opregion_probe,
450 .driver = {
451 .name = "tps68470_pmic_opregion",
452 },
453};
454
455builtin_platform_driver(tps68470_pmic_opregion_driver)
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index b4fbb9929482..ec5b0f190231 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -71,18 +71,34 @@ static const struct always_present_id always_present_ids[] = {
71 DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"), 71 DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
72 }), 72 }),
73 /* 73 /*
74 * The GPD win BIOS dated 20170320 has disabled the accelerometer, the 74 * The GPD win BIOS dated 20170221 has disabled the accelerometer, the
75 * drivers sometimes cause crashes under Windows and this is how the 75 * drivers sometimes cause crashes under Windows and this is how the
76 * manufacturer has solved this :| Note that the the DMI data is less 76 * manufacturer has solved this :| Note that the the DMI data is less
77 * generic then it seems, a board_vendor of "AMI Corporation" is quite 77 * generic then it seems, a board_vendor of "AMI Corporation" is quite
78 * rare and a board_name of "Default String" also is rare. 78 * rare and a board_name of "Default String" also is rare.
79 *
80 * Unfortunately the GPD pocket also uses these strings and its BIOS
81 * was copy-pasted from the GPD win, so it has a disabled KIOX000A
82 * node which we should not enable, thus we also check the BIOS date.
79 */ 83 */
80 ENTRY("KIOX000A", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), { 84 ENTRY("KIOX000A", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {
81 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 85 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
82 DMI_MATCH(DMI_BOARD_NAME, "Default string"), 86 DMI_MATCH(DMI_BOARD_NAME, "Default string"),
83 DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), 87 DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
88 DMI_MATCH(DMI_BIOS_DATE, "02/21/2017")
89 }),
90 ENTRY("KIOX000A", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {
91 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
92 DMI_MATCH(DMI_BOARD_NAME, "Default string"),
93 DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
84 DMI_MATCH(DMI_BIOS_DATE, "03/20/2017") 94 DMI_MATCH(DMI_BIOS_DATE, "03/20/2017")
85 }), 95 }),
96 ENTRY("KIOX000A", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {
97 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
98 DMI_MATCH(DMI_BOARD_NAME, "Default string"),
99 DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
100 DMI_MATCH(DMI_BIOS_DATE, "05/25/2017")
101 }),
86}; 102};
87 103
88bool acpi_device_always_present(struct acpi_device *adev) 104bool acpi_device_always_present(struct acpi_device *adev)
diff --git a/include/acpi/apei.h b/include/acpi/apei.h
index 1797e81a3204..680f80960c3d 100644
--- a/include/acpi/apei.h
+++ b/include/acpi/apei.h
@@ -51,7 +51,6 @@ int erst_clear(u64 record_id);
51 51
52int arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data); 52int arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, void *data);
53void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err); 53void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err);
54void arch_apei_flush_tlb_one(unsigned long addr);
55 54
56#endif 55#endif
57#endif 56#endif