video: ivybridge: Use mtrr_set_next_var() for graphics memory
[platform/kernel/u-boot.git] / drivers / timer / mtk_timer.c
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 #include <linux/bitops.h>
15
16 #define MTK_GPT4_OFFSET_V1      0x40
17 #define MTK_GPT4_OFFSET_V2      0x80
18
19 #define MTK_GPT_CON             0x0
20 #define MTK_GPT_V1_CLK          0x4
21 #define MTK_GPT_CNT             0x8
22
23 #define GPT_ENABLE              BIT(0)
24 #define GPT_CLEAR               BIT(1)
25 #define GPT_V1_FREERUN          GENMASK(5, 4)
26 #define GPT_V2_FREERUN          GENMASK(6, 5)
27
28 enum mtk_gpt_ver {
29         MTK_GPT_V1,
30         MTK_GPT_V2
31 };
32
33 struct mtk_timer_priv {
34         void __iomem *base;
35         unsigned int gpt4_offset;
36 };
37
38 static u64 mtk_timer_get_count(struct udevice *dev)
39 {
40         struct mtk_timer_priv *priv = dev_get_priv(dev);
41         u32 val = readl(priv->base + priv->gpt4_offset + MTK_GPT_CNT);
42
43         return timer_conv_64(val);
44 }
45
46 static int mtk_timer_probe(struct udevice *dev)
47 {
48         struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
49         struct mtk_timer_priv *priv = dev_get_priv(dev);
50         struct clk clk, parent;
51         int ret, gpt_ver;
52
53         priv->base = dev_read_addr_ptr(dev);
54         gpt_ver = dev_get_driver_data(dev);
55
56         if (!priv->base)
57                 return -ENOENT;
58
59         if (gpt_ver == MTK_GPT_V2) {
60                 priv->gpt4_offset = MTK_GPT4_OFFSET_V2;
61
62                 writel(GPT_V2_FREERUN | GPT_CLEAR | GPT_ENABLE,
63                        priv->base + priv->gpt4_offset + MTK_GPT_CON);
64         } else {
65                 priv->gpt4_offset = MTK_GPT4_OFFSET_V1;
66
67                 writel(GPT_V1_FREERUN | GPT_CLEAR | GPT_ENABLE,
68                        priv->base + priv->gpt4_offset + MTK_GPT_CON);
69                 writel(0, priv->base + priv->gpt4_offset + MTK_GPT_V1_CLK);
70         }
71
72         ret = clk_get_by_index(dev, 0, &clk);
73         if (ret)
74                 return ret;
75
76         ret = clk_get_by_index(dev, 1, &parent);
77         if (!ret) {
78                 ret = clk_set_parent(&clk, &parent);
79                 if (ret)
80                         return ret;
81         }
82
83         uc_priv->clock_rate = clk_get_rate(&clk);
84         if (!uc_priv->clock_rate)
85                 return -EINVAL;
86
87         return 0;
88 }
89
90 static const struct timer_ops mtk_timer_ops = {
91         .get_count = mtk_timer_get_count,
92 };
93
94 static const struct udevice_id mtk_timer_ids[] = {
95         { .compatible = "mediatek,timer", .data = MTK_GPT_V1 },
96         { .compatible = "mediatek,mt6577-timer", .data = MTK_GPT_V1 },
97         { .compatible = "mediatek,mt7981-timer", .data = MTK_GPT_V2 },
98         { .compatible = "mediatek,mt7986-timer", .data = MTK_GPT_V2 },
99         { }
100 };
101
102 U_BOOT_DRIVER(mtk_timer) = {
103         .name = "mtk_timer",
104         .id = UCLASS_TIMER,
105         .of_match = mtk_timer_ids,
106         .priv_auto      = sizeof(struct mtk_timer_priv),
107         .probe = mtk_timer_probe,
108         .ops = &mtk_timer_ops,
109         .flags = DM_FLAG_PRE_RELOC,
110 };