Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clocksource / arch_timer: Parse GTDT to initialize arch timer

Using the information presented by GTDT (Generic Timer Description Table)
to initialize the arch timer (not memory-mapped).

CC: Daniel Lezcano <daniel.lezcano@linaro.org>
CC: Thomas Gleixner <tglx@linutronix.de>
Originally-by: Amit Daniel Kachhap <amit.daniel@samsung.com>
Tested-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Tested-by: Yijing Wang <wangyijing@huawei.com>
Tested-by: Mark Langsdorf <mlangsdo@redhat.com>
Tested-by: Jon Masters <jcm@redhat.com>
Tested-by: Timur Tabi <timur@codeaurora.org>
Tested-by: Robert Richter <rrichter@cavium.com>
Acked-by: Robert Richter <rrichter@cavium.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>

authored by

Hanjun Guo and committed by
Will Deacon
b09ca1ec d60fc389

+118 -27
+7
arch/arm64/kernel/time.c
··· 35 35 #include <linux/delay.h> 36 36 #include <linux/clocksource.h> 37 37 #include <linux/clk-provider.h> 38 + #include <linux/acpi.h> 38 39 39 40 #include <clocksource/arm_arch_timer.h> 40 41 ··· 72 71 clocksource_of_init(); 73 72 74 73 tick_setup_hrtimer_broadcast(); 74 + 75 + /* 76 + * Since ACPI or FDT will only one be available in the system, 77 + * we can use acpi_generic_timer_init() here safely 78 + */ 79 + acpi_generic_timer_init(); 75 80 76 81 arch_timer_rate = arch_timer_get_rate(); 77 82 if (!arch_timer_rate)
+105 -27
drivers/clocksource/arm_arch_timer.c
··· 22 22 #include <linux/io.h> 23 23 #include <linux/slab.h> 24 24 #include <linux/sched_clock.h> 25 + #include <linux/acpi.h> 25 26 26 27 #include <asm/arch_timer.h> 27 28 #include <asm/virt.h> ··· 372 371 if (arch_timer_rate) 373 372 return; 374 373 375 - /* Try to determine the frequency from the device tree or CNTFRQ */ 376 - if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { 374 + /* 375 + * Try to determine the frequency from the device tree or CNTFRQ, 376 + * if ACPI is enabled, get the frequency from CNTFRQ ONLY. 377 + */ 378 + if (!acpi_disabled || 379 + of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { 377 380 if (cntbase) 378 381 arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); 379 382 else ··· 696 691 arch_timer_arch_init(); 697 692 } 698 693 699 - static void __init arch_timer_init(struct device_node *np) 694 + static void __init arch_timer_init(void) 700 695 { 701 - int i; 702 - 703 - if (arch_timers_present & ARCH_CP15_TIMER) { 704 - pr_warn("arch_timer: multiple nodes in dt, skipping\n"); 705 - return; 706 - } 707 - 708 - arch_timers_present |= ARCH_CP15_TIMER; 709 - for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) 710 - arch_timer_ppi[i] = irq_of_parse_and_map(np, i); 711 - arch_timer_detect_rate(NULL, np); 712 - 713 - /* 714 - * If we cannot rely on firmware initializing the timer registers then 715 - * we should use the physical timers instead. 716 - */ 717 - if (IS_ENABLED(CONFIG_ARM) && 718 - of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) 719 - arch_timer_use_virtual = false; 720 - 721 696 /* 722 697 * If HYP mode is available, we know that the physical timer 723 698 * has been configured to be accessible from PL1. Use it, so ··· 716 731 } 717 732 } 718 733 719 - arch_timer_c3stop = !of_property_read_bool(np, "always-on"); 720 - 721 734 arch_timer_register(); 722 735 arch_timer_common_init(); 723 736 } 724 - CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init); 725 - CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init); 737 + 738 + static void __init arch_timer_of_init(struct device_node *np) 739 + { 740 + int i; 741 + 742 + if (arch_timers_present & ARCH_CP15_TIMER) { 743 + pr_warn("arch_timer: multiple nodes in dt, skipping\n"); 744 + return; 745 + } 746 + 747 + arch_timers_present |= ARCH_CP15_TIMER; 748 + for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) 749 + arch_timer_ppi[i] = irq_of_parse_and_map(np, i); 750 + 751 + arch_timer_detect_rate(NULL, np); 752 + 753 + arch_timer_c3stop = !of_property_read_bool(np, "always-on"); 754 + 755 + /* 756 + * If we cannot rely on firmware initializing the timer registers then 757 + * we should use the physical timers instead. 758 + */ 759 + if (IS_ENABLED(CONFIG_ARM) && 760 + of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) 761 + arch_timer_use_virtual = false; 762 + 763 + arch_timer_init(); 764 + } 765 + CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); 766 + CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); 726 767 727 768 static void __init arch_timer_mem_init(struct device_node *np) 728 769 { ··· 815 804 } 816 805 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", 817 806 arch_timer_mem_init); 807 + 808 + #ifdef CONFIG_ACPI 809 + static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags) 810 + { 811 + int trigger, polarity; 812 + 813 + if (!interrupt) 814 + return 0; 815 + 816 + trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE 817 + : ACPI_LEVEL_SENSITIVE; 818 + 819 + polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW 820 + : ACPI_ACTIVE_HIGH; 821 + 822 + return acpi_register_gsi(NULL, interrupt, trigger, polarity); 823 + } 824 + 825 + /* Initialize per-processor generic timer */ 826 + static int __init arch_timer_acpi_init(struct acpi_table_header *table) 827 + { 828 + struct acpi_table_gtdt *gtdt; 829 + 830 + if (arch_timers_present & ARCH_CP15_TIMER) { 831 + pr_warn("arch_timer: already initialized, skipping\n"); 832 + return -EINVAL; 833 + } 834 + 835 + gtdt = container_of(table, struct acpi_table_gtdt, header); 836 + 837 + arch_timers_present |= ARCH_CP15_TIMER; 838 + 839 + arch_timer_ppi[PHYS_SECURE_PPI] = 840 + map_generic_timer_interrupt(gtdt->secure_el1_interrupt, 841 + gtdt->secure_el1_flags); 842 + 843 + arch_timer_ppi[PHYS_NONSECURE_PPI] = 844 + map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt, 845 + gtdt->non_secure_el1_flags); 846 + 847 + arch_timer_ppi[VIRT_PPI] = 848 + map_generic_timer_interrupt(gtdt->virtual_timer_interrupt, 849 + gtdt->virtual_timer_flags); 850 + 851 + arch_timer_ppi[HYP_PPI] = 852 + map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt, 853 + gtdt->non_secure_el2_flags); 854 + 855 + /* Get the frequency from CNTFRQ */ 856 + arch_timer_detect_rate(NULL, NULL); 857 + 858 + /* Always-on capability */ 859 + arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); 860 + 861 + arch_timer_init(); 862 + return 0; 863 + } 864 + 865 + /* Initialize all the generic timers presented in GTDT */ 866 + void __init acpi_generic_timer_init(void) 867 + { 868 + if (acpi_disabled) 869 + return; 870 + 871 + acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init); 872 + } 873 + #endif
+6
include/linux/clocksource.h
··· 244 244 static inline void clocksource_of_init(void) {} 245 245 #endif 246 246 247 + #ifdef CONFIG_ACPI 248 + void acpi_generic_timer_init(void); 249 + #else 250 + static inline void acpi_generic_timer_init(void) { } 251 + #endif 252 + 247 253 #endif /* _LINUX_CLOCKSOURCE_H */