1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * MediaTek timer driver 4 * 5 * Copyright (C) 2018 MediaTek Inc. 6 * Author: Ryder Lee <ryder.lee@mediatek.com> 7 */ 8 9 #include <clk.h> 10 #include <common.h> 11 #include <dm.h> 12 #include <timer.h> 13 #include <asm/io.h> 14 15 #define MTK_GPT4_CTRL 0x40 16 #define MTK_GPT4_CLK 0x44 17 #define MTK_GPT4_CNT 0x48 18 19 #define GPT4_ENABLE BIT(0) 20 #define GPT4_CLEAR BIT(1) 21 #define GPT4_FREERUN GENMASK(5, 4) 22 #define GPT4_CLK_SYS 0x0 23 #define GPT4_CLK_DIV1 0x0 24 25 struct mtk_timer_priv { 26 void __iomem *base; 27 }; 28 29 static int mtk_timer_get_count(struct udevice *dev, u64 *count) 30 { 31 struct mtk_timer_priv *priv = dev_get_priv(dev); 32 u32 val = readl(priv->base + MTK_GPT4_CNT); 33 34 *count = timer_conv_64(val); 35 36 return 0; 37 } 38 39 static int mtk_timer_probe(struct udevice *dev) 40 { 41 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); 42 struct mtk_timer_priv *priv = dev_get_priv(dev); 43 struct clk clk, parent; 44 int ret; 45 46 priv->base = dev_read_addr_ptr(dev); 47 if (!priv->base) 48 return -ENOENT; 49 50 ret = clk_get_by_index(dev, 0, &clk); 51 if (ret) 52 return ret; 53 54 ret = clk_get_by_index(dev, 1, &parent); 55 if (!ret) { 56 ret = clk_set_parent(&clk, &parent); 57 if (ret) 58 return ret; 59 } 60 61 uc_priv->clock_rate = clk_get_rate(&clk); 62 if (!uc_priv->clock_rate) 63 return -EINVAL; 64 65 return 0; 66 } 67 68 static const struct timer_ops mtk_timer_ops = { 69 .get_count = mtk_timer_get_count, 70 }; 71 72 static const struct udevice_id mtk_timer_ids[] = { 73 { .compatible = "mediatek,timer" }, 74 { } 75 }; 76 77 U_BOOT_DRIVER(mtk_timer) = { 78 .name = "mtk_timer", 79 .id = UCLASS_TIMER, 80 .of_match = mtk_timer_ids, 81 .priv_auto_alloc_size = sizeof(struct mtk_timer_priv), 82 .probe = mtk_timer_probe, 83 .ops = &mtk_timer_ops, 84 .flags = DM_FLAG_PRE_RELOC, 85 }; 86