Commit 47edaea4943c99f560f3d055b2468333e9192628
Committed by
Tom Rini
1 parent
deff9b1d2a
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
driver: timer: Add the Atmel PIT timer driver
Add the new Atmel PIT timer driver, which supports the driver model and device tree. Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com>
Showing 5 changed files with 103 additions and 0 deletions Side-by-side Diff
arch/arm/mach-at91/arm926ejs/Makefile
arch/arm/mach-at91/armv7/Makefile
drivers/timer/Kconfig
... | ... | @@ -44,6 +44,14 @@ |
44 | 44 | Select this to enable a timer for Altera devices. Please find |
45 | 45 | details on the "Embedded Peripherals IP User Guide" of Altera. |
46 | 46 | |
47 | +config ATMEL_PIT_TIMER | |
48 | + bool "Atmel periodic interval timer support" | |
49 | + depends on TIMER | |
50 | + help | |
51 | + Select this to enable a periodic interval timer for Atmel devices, | |
52 | + it is designed to offer maximum accuracy and efficient management, | |
53 | + even for systems with long response time. | |
54 | + | |
47 | 55 | config SANDBOX_TIMER |
48 | 56 | bool "Sandbox timer support" |
49 | 57 | depends on SANDBOX && TIMER |
drivers/timer/Makefile
drivers/timer/atmel_pit_timer.c
1 | +/* | |
2 | + * Copyright (C) 2017 Microchip Corporation | |
3 | + * Wenyou.Yang <wenyou.yang@microchip.com> | |
4 | + * | |
5 | + * SPDX-License-Identifier: GPL-2.0+ | |
6 | + */ | |
7 | + | |
8 | +#include <common.h> | |
9 | +#include <clk.h> | |
10 | +#include <dm.h> | |
11 | +#include <timer.h> | |
12 | +#include <asm/io.h> | |
13 | + | |
14 | +#define AT91_PIT_VALUE 0xfffff | |
15 | +#define AT91_PIT_PITEN BIT(24) /* Timer Enabled */ | |
16 | + | |
17 | +struct atmel_pit_regs { | |
18 | + u32 mode; | |
19 | + u32 status; | |
20 | + u32 value; | |
21 | + u32 value_image; | |
22 | +}; | |
23 | + | |
24 | +struct atmel_pit_platdata { | |
25 | + struct atmel_pit_regs *regs; | |
26 | +}; | |
27 | + | |
28 | +static int atmel_pit_get_count(struct udevice *dev, u64 *count) | |
29 | +{ | |
30 | + struct atmel_pit_platdata *plat = dev_get_platdata(dev); | |
31 | + struct atmel_pit_regs *const regs = plat->regs; | |
32 | + u32 val = readl(®s->value_image); | |
33 | + | |
34 | + *count = timer_conv_64(val); | |
35 | + | |
36 | + return 0; | |
37 | +} | |
38 | + | |
39 | +static int atmel_pit_probe(struct udevice *dev) | |
40 | +{ | |
41 | + struct atmel_pit_platdata *plat = dev_get_platdata(dev); | |
42 | + struct atmel_pit_regs *const regs = plat->regs; | |
43 | + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); | |
44 | + struct clk clk; | |
45 | + ulong clk_rate; | |
46 | + int ret; | |
47 | + | |
48 | + ret = clk_get_by_index(dev, 0, &clk); | |
49 | + if (ret) | |
50 | + return -EINVAL; | |
51 | + | |
52 | + clk_rate = clk_get_rate(&clk); | |
53 | + if (!clk_rate) | |
54 | + return -EINVAL; | |
55 | + | |
56 | + uc_priv->clock_rate = clk_rate / 16; | |
57 | + | |
58 | + writel(AT91_PIT_VALUE | AT91_PIT_PITEN, ®s->mode); | |
59 | + | |
60 | + return 0; | |
61 | +} | |
62 | + | |
63 | +static int atmel_pit_ofdata_to_platdata(struct udevice *dev) | |
64 | +{ | |
65 | + struct atmel_pit_platdata *plat = dev_get_platdata(dev); | |
66 | + | |
67 | + plat->regs = (struct atmel_pit_regs *)devfdt_get_addr_ptr(dev); | |
68 | + | |
69 | + return 0; | |
70 | +} | |
71 | + | |
72 | +static const struct timer_ops atmel_pit_ops = { | |
73 | + .get_count = atmel_pit_get_count, | |
74 | +}; | |
75 | + | |
76 | +static const struct udevice_id atmel_pit_ids[] = { | |
77 | + { .compatible = "atmel,at91sam9260-pit" }, | |
78 | + { } | |
79 | +}; | |
80 | + | |
81 | +U_BOOT_DRIVER(atmel_pit) = { | |
82 | + .name = "atmel_pit", | |
83 | + .id = UCLASS_TIMER, | |
84 | + .of_match = atmel_pit_ids, | |
85 | + .ofdata_to_platdata = atmel_pit_ofdata_to_platdata, | |
86 | + .platdata_auto_alloc_size = sizeof(struct atmel_pit_platdata), | |
87 | + .probe = atmel_pit_probe, | |
88 | + .ops = &atmel_pit_ops, | |
89 | + .flags = DM_FLAG_PRE_RELOC, | |
90 | +}; |