mirror of
https://github.com/physwizz/a155-U-u1.git
synced 2025-07-14 08:44:45 +00:00
127 lines
2.9 KiB
C
127 lines
2.9 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
//
|
|
// adsp_timesync.c-- Mediatek ADSP timesync
|
|
//
|
|
// Copyright (c) 2020 MediaTek Inc.
|
|
// Author: Celine Liu <Celine.liu@mediatek.com>
|
|
|
|
#include <linux/clocksource.h>
|
|
#include <linux/sched/clock.h>
|
|
#include <linux/suspend.h>
|
|
#include <linux/timex.h>
|
|
#include <linux/types.h>
|
|
#include <linux/io.h>
|
|
#include <asm/arch_timer.h>
|
|
#include <asm/timex.h>
|
|
#include "adsp_core.h"
|
|
#include "adsp_platform.h"
|
|
#include "adsp_timesync.h"
|
|
|
|
struct timesync_info_s {
|
|
u32 tick_h;
|
|
u32 tick_l;
|
|
u32 ts_h;
|
|
u32 ts_l;
|
|
u32 freeze;
|
|
u32 version;
|
|
};
|
|
|
|
struct timesync_control_s {
|
|
struct timecounter tc;
|
|
struct cyclecounter cc;
|
|
struct hrtimer timer;
|
|
u32 period_ms;
|
|
struct timesync_info_s infos;
|
|
};
|
|
|
|
static struct timesync_control_s timesync_ctrl;
|
|
|
|
static u64 adsp_ts_tick_read(const struct cyclecounter *cc)
|
|
{
|
|
return arch_timer_read_counter();
|
|
}
|
|
|
|
static void adsp_timesync_update(u32 fz)
|
|
{
|
|
u64 tick, ts;
|
|
struct timesync_info_s *infos = ×ync_ctrl.infos;
|
|
int ret = 0;
|
|
|
|
ts = timecounter_read(×ync_ctrl.tc);
|
|
tick = timesync_ctrl.tc.cycle_last;
|
|
|
|
infos->tick_h = (tick >> 32) & 0xFFFFFFFF;
|
|
infos->tick_l = tick & 0xFFFFFFFF;
|
|
infos->ts_h = (ts >> 32) & 0xFFFFFFFF;
|
|
infos->ts_l = ts & 0xFFFFFFFF;
|
|
infos->freeze = fz;
|
|
infos->version++;
|
|
|
|
if (is_adsp_system_running()) {
|
|
ret = adsp_copy_to_sharedmem(get_adsp_core_by_id(ADSP_A_ID),
|
|
ADSP_SHAREDMEM_TIMESYNC,
|
|
infos, sizeof(*infos));
|
|
}
|
|
}
|
|
|
|
static enum hrtimer_restart adsp_timesync_refresh(struct hrtimer *hrt)
|
|
{
|
|
adsp_timesync_update(APTIME_UNFREEZE);
|
|
|
|
hrtimer_forward_now(hrt, ms_to_ktime(timesync_ctrl.period_ms));
|
|
return HRTIMER_RESTART;
|
|
}
|
|
|
|
int adsp_timesync_init(void)
|
|
{
|
|
u32 multiplier, shifter;
|
|
|
|
/* init cyclecounter mult and shift as sched_clock */
|
|
clocks_calc_mult_shift(&multiplier,
|
|
&shifter,
|
|
arch_timer_get_cntfrq(),
|
|
NSEC_PER_SEC, 3600);
|
|
|
|
timesync_ctrl.cc.read = adsp_ts_tick_read;
|
|
timesync_ctrl.cc.mask = CLOCKSOURCE_MASK(56);
|
|
timesync_ctrl.cc.mult = multiplier;
|
|
timesync_ctrl.cc.shift = shifter;
|
|
|
|
/* init time counter */
|
|
timecounter_init(×ync_ctrl.tc,
|
|
×ync_ctrl.cc,
|
|
sched_clock());
|
|
|
|
/* init refresh hr_timer */
|
|
hrtimer_init(×ync_ctrl.timer,
|
|
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
|
timesync_ctrl.timer.function = adsp_timesync_refresh;
|
|
timesync_ctrl.period_ms = TIMESYNC_WRAP_TIME_MS;
|
|
|
|
pr_info("%s(), done", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void adsp_timesync_suspend(u32 fz)
|
|
{
|
|
hrtimer_cancel(×ync_ctrl.timer);
|
|
|
|
/* update after suspend timer */
|
|
adsp_timesync_update(fz);
|
|
}
|
|
void adsp_timesync_resume(void)
|
|
{
|
|
/* re-init timecounter because sched_clock will be stopped during
|
|
* suspend but arch timer counter is not, so we need to update
|
|
* start time after resume
|
|
*/
|
|
timecounter_init(×ync_ctrl.tc,
|
|
×ync_ctrl.cc,
|
|
sched_clock());
|
|
|
|
/* kick start the timer immediately */
|
|
hrtimer_start(×ync_ctrl.timer, 0, HRTIMER_MODE_REL);
|
|
}
|
|
|