![Bryan O'Donoghue](/assets/img/avatar_default.png)
A system configured without CONFIG_CPUFREQ will return 0 for cpufreq_get(). greybus-timesync can subsequently then do a divide-by-zero as result. This patch fixes by checking for a zero return value from cpufreq_get() and setting to a default value of 19.2MHz. Reported-by: Rui Miguel Silva <rmfrfs@gmail.com> Signed-off-by: Bryan O'Donoghue <pure.logic@nexus-software.ie> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
83 lines
2.1 KiB
C
83 lines
2.1 KiB
C
/*
|
|
* TimeSync API driver.
|
|
*
|
|
* Copyright 2016 Google Inc.
|
|
* Copyright 2016 Linaro Ltd.
|
|
*
|
|
* Released under the GPLv2 only.
|
|
*
|
|
* This code reads directly from an ARMv7 memory-mapped timer that lives in
|
|
* MMIO space. Since this counter lives inside of MMIO space its shared between
|
|
* cores and that means we don't have to worry about issues like TSC on x86
|
|
* where each time-stamp-counter (TSC) is local to a particular core.
|
|
*
|
|
* Register-level access code is based on
|
|
* drivers/clocksource/arm_arch_timer.c
|
|
*/
|
|
#include <linux/cpufreq.h>
|
|
#include <linux/of_platform.h>
|
|
|
|
#include "greybus.h"
|
|
#include "arche_platform.h"
|
|
|
|
#define DEFAULT_FRAMETIME_CLOCK_HZ 19200000
|
|
|
|
static u32 gb_timesync_clock_frequency;
|
|
int (*arche_platform_change_state_cb)(enum arche_platform_state state,
|
|
struct gb_timesync_svc *pdata);
|
|
EXPORT_SYMBOL_GPL(arche_platform_change_state_cb);
|
|
|
|
u64 gb_timesync_platform_get_counter(void)
|
|
{
|
|
return (u64)get_cycles();
|
|
}
|
|
|
|
u32 gb_timesync_platform_get_clock_rate(void)
|
|
{
|
|
if (unlikely(!gb_timesync_clock_frequency)) {
|
|
gb_timesync_clock_frequency = cpufreq_get(0);
|
|
if (!gb_timesync_clock_frequency)
|
|
gb_timesync_clock_frequency = DEFAULT_FRAMETIME_CLOCK_HZ;
|
|
}
|
|
|
|
return gb_timesync_clock_frequency;
|
|
}
|
|
|
|
int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata)
|
|
{
|
|
return arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_TIME_SYNC,
|
|
pdata);
|
|
}
|
|
|
|
void gb_timesync_platform_unlock_bus(void)
|
|
{
|
|
arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_ACTIVE, NULL);
|
|
}
|
|
|
|
static const struct of_device_id arch_timer_of_match[] = {
|
|
{ .compatible = "google,greybus-frame-time-counter", },
|
|
{},
|
|
};
|
|
|
|
int __init gb_timesync_platform_init(void)
|
|
{
|
|
struct device_node *np;
|
|
|
|
np = of_find_matching_node(NULL, arch_timer_of_match);
|
|
if (!np) {
|
|
/* Tolerate not finding to allow BBB etc to continue */
|
|
pr_warn("Unable to find a compatible ARMv7 timer\n");
|
|
return 0;
|
|
}
|
|
|
|
if (of_property_read_u32(np, "clock-frequency",
|
|
&gb_timesync_clock_frequency)) {
|
|
pr_err("Unable to find timer clock-frequency\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void gb_timesync_platform_exit(void) {}
|