aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 8459d19a84f5..887f6d00a71d 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -190,6 +190,12 @@ static struct cyclecounter cyclecounter __ro_after_init = {
190 .mask = CLOCKSOURCE_MASK(56), 190 .mask = CLOCKSOURCE_MASK(56),
191}; 191};
192 192
193struct ate_acpi_oem_info {
194 char oem_id[ACPI_OEM_ID_SIZE + 1];
195 char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
196 u32 oem_revision;
197};
198
193#ifdef CONFIG_FSL_ERRATUM_A008585 199#ifdef CONFIG_FSL_ERRATUM_A008585
194/* 200/*
195 * The number of retries is an arbitrary value well beyond the highest number 201 * The number of retries is an arbitrary value well beyond the highest number
@@ -371,6 +377,28 @@ bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workarou
371 return this_cpu_has_cap((uintptr_t)wa->id); 377 return this_cpu_has_cap((uintptr_t)wa->id);
372} 378}
373 379
380
381static
382bool arch_timer_check_acpi_oem_erratum(const struct arch_timer_erratum_workaround *wa,
383 const void *arg)
384{
385 static const struct ate_acpi_oem_info empty_oem_info = {};
386 const struct ate_acpi_oem_info *info = wa->id;
387 const struct acpi_table_header *table = arg;
388
389 /* Iterate over the ACPI OEM info array, looking for a match */
390 while (memcmp(info, &empty_oem_info, sizeof(*info))) {
391 if (!memcmp(info->oem_id, table->oem_id, ACPI_OEM_ID_SIZE) &&
392 !memcmp(info->oem_table_id, table->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
393 info->oem_revision == table->oem_revision)
394 return true;
395
396 info++;
397 }
398
399 return false;
400}
401
374static const struct arch_timer_erratum_workaround * 402static const struct arch_timer_erratum_workaround *
375arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, 403arch_timer_iterate_errata(enum arch_timer_erratum_match_type type,
376 ate_match_fn_t match_fn, 404 ate_match_fn_t match_fn,
@@ -431,6 +459,9 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t
431 match_fn = arch_timer_check_local_cap_erratum; 459 match_fn = arch_timer_check_local_cap_erratum;
432 local = true; 460 local = true;
433 break; 461 break;
462 case ate_match_acpi_oem_info:
463 match_fn = arch_timer_check_acpi_oem_erratum;
464 break;
434 default: 465 default:
435 WARN_ON(1); 466 WARN_ON(1);
436 return; 467 return;
@@ -1277,6 +1308,9 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
1277 /* Always-on capability */ 1308 /* Always-on capability */
1278 arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); 1309 arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
1279 1310
1311 /* Check for globally applicable workarounds */
1312 arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table);
1313
1280 arch_timer_init(); 1314 arch_timer_init();
1281 return 0; 1315 return 0;
1282} 1316}