video: ivybridge: Use mtrr_set_next_var() for graphics memory
[platform/kernel/u-boot.git] / drivers / timer / arc_timer.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Synopsys, Inc. All rights reserved.
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <timer.h>
10 #include <asm/arcregs.h>
11 #include <asm/global_data.h>
12 #include <asm/io.h>
13
14 DECLARE_GLOBAL_DATA_PTR;
15
16 #define NH_MODE (1 << 1)
17
18 /*
19  * ARC timer control registers are mapped to auxiliary address space.
20  * There are special ARC asm command to access that addresses.
21  * Therefore we use built-in functions to read from and write to timer
22  * control register.
23  */
24
25 /* Driver private data. Contains timer id. Could be either 0 or 1. */
26 struct arc_timer_priv {
27                 uint timer_id;
28 };
29
30 static u64 arc_timer_get_count(struct udevice *dev)
31 {
32         u32 val = 0;
33         struct arc_timer_priv *priv = dev_get_priv(dev);
34
35         switch (priv->timer_id) {
36         case 0:
37                 val = read_aux_reg(ARC_AUX_TIMER0_CNT);
38                 break;
39         case 1:
40                 val = read_aux_reg(ARC_AUX_TIMER1_CNT);
41                 break;
42         }
43         return timer_conv_64(val);
44 }
45
46 static int arc_timer_probe(struct udevice *dev)
47 {
48         int id;
49         struct arc_timer_priv *priv = dev_get_priv(dev);
50
51         /* Get registers offset and size */
52         id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", -1);
53         if (id < 0)
54                 return -EINVAL;
55
56         if (id > 1)
57                 return -ENXIO;
58
59         priv->timer_id = (uint)id;
60
61         /*
62          * In ARC core there're special registers (Auxiliary or AUX) in its
63          * separate memory space that are used for accessing some hardware
64          * features of the core. They are not mapped in normal memory space
65          * and also always have the same location regardless core configuration.
66          * Thus to simplify understanding of the programming model we chose to
67          * access AUX regs of Timer0 and Timer1 separately instead of using
68          * offsets from some base address.
69          */
70
71         switch (priv->timer_id) {
72         case 0:
73                 /* Disable timer if CPU is halted */
74                 write_aux_reg(ARC_AUX_TIMER0_CTRL, NH_MODE);
75                 /* Set max value for counter/timer */
76                 write_aux_reg(ARC_AUX_TIMER0_LIMIT, 0xffffffff);
77                 /* Set initial count value and restart counter/timer */
78                 write_aux_reg(ARC_AUX_TIMER0_CNT, 0);
79                 break;
80         case 1:
81                 /* Disable timer if CPU is halted */
82                 write_aux_reg(ARC_AUX_TIMER1_CTRL, NH_MODE);
83                 /* Set max value for counter/timer */
84                 write_aux_reg(ARC_AUX_TIMER1_LIMIT, 0xffffffff);
85                 /* Set initial count value and restart counter/timer */
86                 write_aux_reg(ARC_AUX_TIMER1_CNT, 0);
87                 break;
88         }
89
90         return 0;
91 }
92
93
94 static const struct timer_ops arc_timer_ops = {
95         .get_count = arc_timer_get_count,
96 };
97
98 static const struct udevice_id arc_timer_ids[] = {
99         { .compatible = "snps,arc-timer" },
100         {}
101 };
102
103 U_BOOT_DRIVER(arc_timer) = {
104         .name   = "arc_timer",
105         .id     = UCLASS_TIMER,
106         .of_match = arc_timer_ids,
107         .probe = arc_timer_probe,
108         .ops    = &arc_timer_ops,
109         .priv_auto      = sizeof(struct arc_timer_priv),
110 };