From d3c3606c5cc65f85274320b6fade00ea8dc6c77f Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Thu, 15 Nov 2018 10:07:56 +0800 Subject: [PATCH] timer: MediaTek: add timer driver for MediaTek SoCs This patch adds clock source and clock event for the timer found on the Mediatek SoCs. Signed-off-by: Ryder Lee Tested-by: Matthias Brugger Reviewed-by: Simon Glass --- drivers/timer/Kconfig | 7 ++++ drivers/timer/Makefile | 1 + drivers/timer/mtk_timer.c | 85 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 drivers/timer/mtk_timer.c diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index d0cfc35306..b0e6f32f0b 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -160,4 +160,11 @@ config X86_TSC_TIMER help Select this to enable Time-Stamp Counter (TSC) timer for x86. +config MTK_TIMER + bool "MediaTek timer support" + depends on TIMER + help + Select this to enable support for the timer found on + MediaTek devices. + endmenu diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index 7f19c4970a..c4fbab2aac 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o obj-$(CONFIG_STI_TIMER) += sti-timer.o obj-$(CONFIG_STM32_TIMER) += stm32_timer.o obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o +obj-$(CONFIG_MTK_TIMER) += mtk_timer.o diff --git a/drivers/timer/mtk_timer.c b/drivers/timer/mtk_timer.c new file mode 100644 index 0000000000..b5e76bd358 --- /dev/null +++ b/drivers/timer/mtk_timer.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek timer driver + * + * Copyright (C) 2018 MediaTek Inc. + * Author: Ryder Lee + */ + +#include +#include +#include +#include +#include + +#define MTK_GPT4_CTRL 0x40 +#define MTK_GPT4_CLK 0x44 +#define MTK_GPT4_CNT 0x48 + +#define GPT4_ENABLE BIT(0) +#define GPT4_CLEAR BIT(1) +#define GPT4_FREERUN GENMASK(5, 4) +#define GPT4_CLK_SYS 0x0 +#define GPT4_CLK_DIV1 0x0 + +struct mtk_timer_priv { + void __iomem *base; +}; + +static int mtk_timer_get_count(struct udevice *dev, u64 *count) +{ + struct mtk_timer_priv *priv = dev_get_priv(dev); + u32 val = readl(priv->base + MTK_GPT4_CNT); + + *count = timer_conv_64(val); + + return 0; +} + +static int mtk_timer_probe(struct udevice *dev) +{ + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct mtk_timer_priv *priv = dev_get_priv(dev); + struct clk clk, parent; + int ret; + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -ENOENT; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; + + ret = clk_get_by_index(dev, 1, &parent); + if (!ret) { + ret = clk_set_parent(&clk, &parent); + if (ret) + return ret; + } + + uc_priv->clock_rate = clk_get_rate(&clk); + if (!uc_priv->clock_rate) + return -EINVAL; + + return 0; +} + +static const struct timer_ops mtk_timer_ops = { + .get_count = mtk_timer_get_count, +}; + +static const struct udevice_id mtk_timer_ids[] = { + { .compatible = "mediatek,timer" }, + { } +}; + +U_BOOT_DRIVER(mtk_timer) = { + .name = "mtk_timer", + .id = UCLASS_TIMER, + .of_match = mtk_timer_ids, + .priv_auto_alloc_size = sizeof(struct mtk_timer_priv), + .probe = mtk_timer_probe, + .ops = &mtk_timer_ops, + .flags = DM_FLAG_PRE_RELOC, +}; -- 2.39.5