Tristan Hsieh has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/32245
Change subject: mediatek: Using a 64 bits timer ......................................................................
mediatek: Using a 64 bits timer
GPT4 is a 32 bits timer and the counter of GPT4 will be overflow about 330 seconds (0xffffffff / 13MHz). With the GPT4 version, timer and delay functions will not work when the counter is overflow. Now we use a 64 bits timer, GPT6, to fix the overflow issue.
BUG=b:80501386 BRANCH=none Test=emerge-elm coreboot; emerge-kukui coreboot
Change-Id: I9f080e47253a1b1bab4636a45cb86c8666a25302 Signed-off-by: Tristan Shieh tristan.shieh@mediatek.com --- M src/soc/mediatek/common/include/soc/timer.h M src/soc/mediatek/common/timer.c M src/soc/mediatek/mt8173/timer.c 3 files changed, 31 insertions(+), 16 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/45/32245/1
diff --git a/src/soc/mediatek/common/include/soc/timer.h b/src/soc/mediatek/common/include/soc/timer.h index babcbba..b58d4d3 100644 --- a/src/soc/mediatek/common/include/soc/timer.h +++ b/src/soc/mediatek/common/include/soc/timer.h @@ -19,18 +19,21 @@ #include <soc/addressmap.h> #include <types.h>
-#define GPT4_MHZ 13 +#define GPT_MHZ 13
struct mtk_gpt_regs { - u32 reserved[16]; - u32 gpt4_con; - u32 gpt4_clk; - u32 gpt4_cnt; + u32 reserved1[24]; + u32 gpt6_con; + u32 gpt6_clk; + u32 gpt6_cnt_l; + u32 reserved2[3]; + u32 gpt6_cnt_h; };
-check_member(mtk_gpt_regs, gpt4_con, 0x0040); -check_member(mtk_gpt_regs, gpt4_clk, 0x0044); -check_member(mtk_gpt_regs, gpt4_cnt, 0x0048); +check_member(mtk_gpt_regs, gpt6_con, 0x0060); +check_member(mtk_gpt_regs, gpt6_clk, 0x0064); +check_member(mtk_gpt_regs, gpt6_cnt_l, 0x0068); +check_member(mtk_gpt_regs, gpt6_cnt_h, 0x0078);
enum { GPT_CON_EN = 0x01, diff --git a/src/soc/mediatek/common/timer.c b/src/soc/mediatek/common/timer.c index 0762c2b..bc0577c 100644 --- a/src/soc/mediatek/common/timer.c +++ b/src/soc/mediatek/common/timer.c @@ -25,21 +25,33 @@
__weak void timer_prepare(void) { /* do nothing */ }
+static uint64_t timer_raw_value(void) +{ + uint32_t low, high; + + do { + high = read32(&mtk_gpt->gpt6_cnt_h); + low = read32(&mtk_gpt->gpt6_cnt_l); + } while (high != read32(&mtk_gpt->gpt6_cnt_h)); + + return (uint64_t)low | ((uint64_t)high) << 32; +} + void timer_monotonic_get(struct mono_time *mt) { - mono_time_set_usecs(mt, read32(&mtk_gpt->gpt4_cnt) / GPT4_MHZ); + mono_time_set_usecs(mt, timer_raw_value() / GPT_MHZ); }
void init_timer(void) { timer_prepare();
- /* Disable GPT4 and clear the counter */ - clrbits_le32(&mtk_gpt->gpt4_con, GPT_CON_EN); - setbits_le32(&mtk_gpt->gpt4_con, GPT_CON_CLR); + /* Disable timer and clear the counter */ + clrbits_le32(&mtk_gpt->gpt6_con, GPT_CON_EN); + setbits_le32(&mtk_gpt->gpt6_con, GPT_CON_CLR);
/* Set clock source to system clock and set clock divider to 1 */ - write32(&mtk_gpt->gpt4_clk, GPT_SYS_CLK | GPT_CLK_DIV1); - /* Set operation mode to FREERUN mode and enable GTP4 */ - write32(&mtk_gpt->gpt4_con, GPT_CON_EN | GPT_MODE_FREERUN); + write32(&mtk_gpt->gpt6_clk, GPT_SYS_CLK | GPT_CLK_DIV1); + /* Set operation mode to FREERUN mode and enable timer */ + write32(&mtk_gpt->gpt6_con, GPT_CON_EN | GPT_MODE_FREERUN); } diff --git a/src/soc/mediatek/mt8173/timer.c b/src/soc/mediatek/mt8173/timer.c index 2c9995a..eb2a142 100644 --- a/src/soc/mediatek/mt8173/timer.c +++ b/src/soc/mediatek/mt8173/timer.c @@ -31,5 +31,5 @@ */ write32(&mt8173_mcucfg->xgpt_idx, 0); /* Set clock mode to 13Mhz and enable XGPT */ - write32(&mt8173_mcucfg->xgpt_ctl, (0x1 | ((26 / GPT4_MHZ) << 8))); + write32(&mt8173_mcucfg->xgpt_ctl, (0x1 | ((26 / GPT_MHZ) << 8))); }