--- zzzz-none-000/linux-3.10.107/arch/arm/mach-shmobile/timer.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/arm/mach-shmobile/timer.c 2021-02-04 17:41:59.000000000 +0000 @@ -12,54 +12,68 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * */ #include #include #include +#include -void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz, - unsigned int mult, unsigned int div) +static void __init shmobile_setup_delay_hz(unsigned int max_cpu_core_hz, + unsigned int mult, unsigned int div) { /* calculate a worst-case loops-per-jiffy value - * based on maximum cpu core mhz setting and the + * based on maximum cpu core hz setting and the * __delay() implementation in arch/arm/lib/delay.S * * this will result in a longer delay than expected * when the cpu core runs on lower frequencies. */ - unsigned int value = (1000000 * mult) / (HZ * div); + unsigned int value = HZ * div / mult; if (!preset_lpj) - preset_lpj = max_cpu_core_mhz * value; + preset_lpj = max_cpu_core_hz / value; } -static void __init shmobile_late_time_init(void) +void __init shmobile_init_delay(void) { - /* - * Make sure all compiled-in early timers register themselves. - * - * Run probe() for two "earlytimer" devices, these will be the - * clockevents and clocksource devices respectively. In the event - * that only a clockevents device is available, we -ENODEV on the - * clocksource and the jiffies clocksource is used transparently - * instead. No error handling is necessary here. - */ - early_platform_driver_register_all("earlytimer"); - early_platform_driver_probe("earlytimer", 2, 0); -} - -void __init shmobile_earlytimer_init(void) -{ - late_time_init = shmobile_late_time_init; -} - -void __init shmobile_timer_init(void) -{ - clocksource_of_init(); + struct device_node *np, *cpus; + bool is_a7_a8_a9 = false; + bool is_a15 = false; + bool has_arch_timer = false; + u32 max_freq = 0; + + cpus = of_find_node_by_path("/cpus"); + if (!cpus) + return; + + for_each_child_of_node(cpus, np) { + u32 freq; + + if (!of_property_read_u32(np, "clock-frequency", &freq)) + max_freq = max(max_freq, freq); + + if (of_device_is_compatible(np, "arm,cortex-a8") || + of_device_is_compatible(np, "arm,cortex-a9")) { + is_a7_a8_a9 = true; + } else if (of_device_is_compatible(np, "arm,cortex-a7")) { + is_a7_a8_a9 = true; + has_arch_timer = true; + } else if (of_device_is_compatible(np, "arm,cortex-a15")) { + is_a15 = true; + has_arch_timer = true; + } + } + + of_node_put(cpus); + + if (!max_freq) + return; + + if (!has_arch_timer || !IS_ENABLED(CONFIG_ARM_ARCH_TIMER)) { + if (is_a7_a8_a9) + shmobile_setup_delay_hz(max_freq, 1, 3); + else if (is_a15) + shmobile_setup_delay_hz(max_freq, 2, 4); + } }