soc/ipq806x: Replace GPT with fine grained DGT timer.
Support 1MHz libpayload restriction on timer implementation by using DGT (debug) timer instead of GPT (general purpose) timer. BUG=chrome-os-partner:28880 TEST=manual verified DGT timer functions in coreboot and depthcharge. Original-Change-Id: Iab322d7e863e3959c027e9ce876223a64eb7e257 Original-Signed-off-by: Deepa Dinamani <deepad@codeaurora.org> Original-Reviewed-on: https://chromium-review.googlesource.com/201574 Original-Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Original-Commit-Queue: Vadim Bendebury <vbendeb@chromium.org> Original-Tested-by: Vadim Bendebury <vbendeb@chromium.org> (cherry picked from commit ddf11eee5ec2d86a62095e932dbec9313b8fb9e1) Signed-off-by: Marc Jones <marc.jones@se-eng.com> Change-Id: Id73e805801fd8d135b607df9f4f8caf567ec5b83 Reviewed-on: http://review.coreboot.org/8596 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
f69a99dbf8
commit
74aa7770f6
|
@ -1,8 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2011 - 2014 The Linux Foundation. All rights reserved.
|
||||||
* Source : APQ8064 LK boot
|
|
||||||
*
|
|
||||||
* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
|
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -36,103 +33,67 @@
|
||||||
#include <ipq_timer.h>
|
#include <ipq_timer.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
|
|
||||||
#define GPT_FREQ_KHZ 32
|
/*
|
||||||
#define GPT_FREQ (GPT_FREQ_KHZ * 1000) /* 32 KHz */
|
* DGT runs at 25 MHz / 4, or 6.25 ticks per microsecond
|
||||||
|
*/
|
||||||
|
#define DGT_MHZ_NUM 25
|
||||||
|
#define DGT_MHZ_DEN 4
|
||||||
|
|
||||||
|
#define TIMER_TICKS(us) ((DGT_MHZ_NUM*(us) + (DGT_MHZ_DEN - 1)) / DGT_MHZ_DEN)
|
||||||
|
#define TIMER_USECS(ticks) (DGT_MHZ_DEN*(ticks) / DGT_MHZ_NUM)
|
||||||
|
|
||||||
|
/* Clock divider values for the timer. */
|
||||||
|
#define DGT_CLK_DIV_1 0
|
||||||
|
#define DGT_CLK_DIV_2 1
|
||||||
|
#define DGT_CLK_DIV_3 2
|
||||||
|
#define DGT_CLK_DIV_4 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init_timer - initialize timer
|
* init_timer - initialize timer
|
||||||
*/
|
*/
|
||||||
void init_timer(void)
|
void init_timer(void)
|
||||||
{
|
{
|
||||||
writel(0, GPT_ENABLE);
|
/* disable timer */
|
||||||
writel(GPT_ENABLE_EN, GPT_ENABLE);
|
writel_i(0, DGT_ENABLE);
|
||||||
|
|
||||||
|
/* DGT uses TCXO source which is 25MHz.
|
||||||
|
* The timer should run at 1/4th the frequency of TCXO
|
||||||
|
* according to clock plan.
|
||||||
|
* Set clock divider to 4.
|
||||||
|
*/
|
||||||
|
writel_i(DGT_CLK_DIV_4, DGT_CLK_CTL);
|
||||||
|
|
||||||
|
/* Enable timer */
|
||||||
|
writel_i(0, DGT_CLEAR);
|
||||||
|
writel_i(DGT_ENABLE_EN, DGT_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* udelay - generates micro second delay.
|
* udelay - generates micro second delay.
|
||||||
* @param usec: delay duration in microseconds
|
* @param usec: delay duration in microseconds
|
||||||
*
|
|
||||||
* With 32KHz clock, minimum possible delay is 31.25 Micro seconds and
|
|
||||||
* its multiples. In Rumi GPT clock is 32 KHz
|
|
||||||
*/
|
*/
|
||||||
void udelay(unsigned usec)
|
void udelay(unsigned usec)
|
||||||
{
|
{
|
||||||
unsigned val;
|
uint32_t now;
|
||||||
unsigned now, last;
|
uint32_t last;
|
||||||
unsigned runcount;
|
uint32_t ticks;
|
||||||
|
uint32_t curr_ticks = 0;
|
||||||
|
|
||||||
usec = (usec + GPT_FREQ_KHZ - 1) / GPT_FREQ_KHZ;
|
/* Calculate number of ticks required. */
|
||||||
last = readl(GPT_COUNT_VAL);
|
ticks = TIMER_TICKS(usec);
|
||||||
runcount = last;
|
|
||||||
val = usec + last;
|
|
||||||
|
|
||||||
do {
|
/* Obtain the current timer value. */
|
||||||
now = readl(GPT_COUNT_VAL);
|
last = readl_i(DGT_COUNT_VAL);
|
||||||
if (last > now)
|
|
||||||
runcount += ((GPT_FREQ - last) + now);
|
/* Loop until the right number of ticks. */
|
||||||
else
|
while (curr_ticks < ticks) {
|
||||||
runcount += (now - last);
|
now = readl_i(DGT_COUNT_VAL);
|
||||||
|
curr_ticks += now - last;
|
||||||
last = now;
|
last = now;
|
||||||
} while (runcount < val);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer_monotonic_get(struct mono_time *mt)
|
void timer_monotonic_get(struct mono_time *mt)
|
||||||
{
|
{
|
||||||
mono_time_set_usecs(mt, (readl(GPT_COUNT_VAL) * 1000) / GPT_FREQ_KHZ);
|
mono_time_set_usecs(mt, TIMER_USECS(readl_i(DGT_COUNT_VAL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO(vbendeb) clean it up later.
|
|
||||||
* Compile out the below code but leave it for now in case it will become
|
|
||||||
* necessary later in order to make the platform fully functional.
|
|
||||||
*/
|
|
||||||
static unsigned long timestamp;
|
|
||||||
static unsigned long lastinc;
|
|
||||||
|
|
||||||
inline ulong gpt_to_sys_freq(unsigned int gpt)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* get_timer() expects the timer increments to be in terms
|
|
||||||
* of CONFIG_SYS_HZ. Convert GPT timer values to CONFIG_SYS_HZ
|
|
||||||
* units.
|
|
||||||
*/
|
|
||||||
return (((ulong)gpt) / (GPT_FREQ / CONFIG_SYS_HZ));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get_timer_masked - returns current ticks
|
|
||||||
*
|
|
||||||
* Returns the current timer ticks, since boot.
|
|
||||||
*/
|
|
||||||
ulong get_timer_masked(void)
|
|
||||||
{
|
|
||||||
ulong now = gpt_to_sys_freq(readl(GPT_COUNT_VAL));
|
|
||||||
|
|
||||||
if (lastinc <= now) { /* normal mode (non roll) */
|
|
||||||
/* normal mode */
|
|
||||||
timestamp += now - lastinc;
|
|
||||||
/* move stamp forward with absolute diff ticks */
|
|
||||||
} else { /* we have overflow of the count down timer */
|
|
||||||
timestamp += now + (TIMER_LOAD_VAL - lastinc);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastinc = now;
|
|
||||||
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long long get_ticks(void)
|
|
||||||
{
|
|
||||||
return readl(GPT_COUNT_VAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the number of timer ticks per second.
|
|
||||||
*/
|
|
||||||
ulong get_tbclk(void)
|
|
||||||
{
|
|
||||||
return GPT_FREQ;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in New Issue