]>
Commit | Line | Data |
---|---|---|
4697abea | 1 | /* |
2 | * Copyright 2016 Google Inc. | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <dm.h> | |
9 | #include <errno.h> | |
10 | #include <timer.h> | |
11 | #include <asm/io.h> | |
12 | #include <asm/arch/timer.h> | |
13 | ||
14 | DECLARE_GLOBAL_DATA_PTR; | |
15 | ||
16 | #define AST_TICK_TIMER 1 | |
17 | #define AST_TMC_RELOAD_VAL 0xffffffff | |
18 | ||
19 | struct ast_timer_priv { | |
20 | struct ast_timer *regs; | |
21 | struct ast_timer_counter *tmc; | |
22 | }; | |
23 | ||
24 | static struct ast_timer_counter *ast_get_timer_counter(struct ast_timer *timer, | |
25 | int n) | |
26 | { | |
27 | if (n > 3) | |
28 | return &timer->timers2[n - 4]; | |
29 | else | |
30 | return &timer->timers1[n - 1]; | |
31 | } | |
32 | ||
33 | static int ast_timer_probe(struct udevice *dev) | |
34 | { | |
35 | struct ast_timer_priv *priv = dev_get_priv(dev); | |
36 | struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); | |
37 | ||
38 | writel(AST_TMC_RELOAD_VAL, &priv->tmc->reload_val); | |
39 | ||
40 | /* | |
41 | * Stop the timer. This will also load reload_val into | |
42 | * the status register. | |
43 | */ | |
44 | clrbits_le32(&priv->regs->ctrl1, | |
45 | AST_TMC_EN << AST_TMC_CTRL1_SHIFT(AST_TICK_TIMER)); | |
46 | /* Start the timer from the fixed 1MHz clock. */ | |
47 | setbits_le32(&priv->regs->ctrl1, | |
48 | (AST_TMC_EN | AST_TMC_1MHZ) << | |
49 | AST_TMC_CTRL1_SHIFT(AST_TICK_TIMER)); | |
50 | ||
51 | uc_priv->clock_rate = AST_TMC_RATE; | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | static int ast_timer_get_count(struct udevice *dev, u64 *count) | |
57 | { | |
58 | struct ast_timer_priv *priv = dev_get_priv(dev); | |
59 | ||
60 | *count = AST_TMC_RELOAD_VAL - readl(&priv->tmc->status); | |
61 | ||
62 | return 0; | |
63 | } | |
64 | ||
65 | static int ast_timer_ofdata_to_platdata(struct udevice *dev) | |
66 | { | |
67 | struct ast_timer_priv *priv = dev_get_priv(dev); | |
68 | ||
a821c4af | 69 | priv->regs = devfdt_get_addr_ptr(dev); |
4697abea | 70 | if (IS_ERR(priv->regs)) |
71 | return PTR_ERR(priv->regs); | |
72 | ||
73 | priv->tmc = ast_get_timer_counter(priv->regs, AST_TICK_TIMER); | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
78 | static const struct timer_ops ast_timer_ops = { | |
79 | .get_count = ast_timer_get_count, | |
80 | }; | |
81 | ||
82 | static const struct udevice_id ast_timer_ids[] = { | |
83 | { .compatible = "aspeed,ast2500-timer" }, | |
84 | { .compatible = "aspeed,ast2400-timer" }, | |
85 | { } | |
86 | }; | |
87 | ||
88 | U_BOOT_DRIVER(ast_timer) = { | |
89 | .name = "ast_timer", | |
90 | .id = UCLASS_TIMER, | |
91 | .of_match = ast_timer_ids, | |
92 | .probe = ast_timer_probe, | |
93 | .priv_auto_alloc_size = sizeof(struct ast_timer_priv), | |
94 | .ofdata_to_platdata = ast_timer_ofdata_to_platdata, | |
95 | .ops = &ast_timer_ops, | |
96 | .flags = DM_FLAG_PRE_RELOC, | |
97 | }; |