diff options
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 34 |
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 | ||
193 | struct 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 | |||
381 | static | ||
382 | bool 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 | |||
374 | static const struct arch_timer_erratum_workaround * | 402 | static const struct arch_timer_erratum_workaround * |
375 | arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, | 403 | arch_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 | } |