blob: 5cf46f224ab00206283c9b55d65c15ade2172c5f [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +08002/*
3 * Copyright (C) 2017 Microchip Corporation
Wolfgang Denk0cf207e2021-09-27 17:42:39 +02004 * Wenyou.Yang <wenyou.yang@microchip.com>
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +08005 */
6
7#include <common.h>
8#include <clk.h>
9#include <dm.h>
10#include <timer.h>
11#include <asm/io.h>
Simon Glasscd93d622020-05-10 11:40:13 -060012#include <linux/bitops.h>
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080013
14#define AT91_PIT_VALUE 0xfffff
15#define AT91_PIT_PITEN BIT(24) /* Timer Enabled */
16
17struct atmel_pit_regs {
18 u32 mode;
19 u32 status;
20 u32 value;
21 u32 value_image;
22};
23
Simon Glass8a8d24b2020-12-03 16:55:23 -070024struct atmel_pit_plat {
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080025 struct atmel_pit_regs *regs;
26};
27
Sean Anderson8af7bb92020-10-07 14:37:44 -040028static u64 atmel_pit_get_count(struct udevice *dev)
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080029{
Simon Glass8a8d24b2020-12-03 16:55:23 -070030 struct atmel_pit_plat *plat = dev_get_plat(dev);
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080031 struct atmel_pit_regs *const regs = plat->regs;
32 u32 val = readl(&regs->value_image);
33
Sean Anderson8af7bb92020-10-07 14:37:44 -040034 return timer_conv_64(val);
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080035}
36
37static int atmel_pit_probe(struct udevice *dev)
38{
Simon Glass8a8d24b2020-12-03 16:55:23 -070039 struct atmel_pit_plat *plat = dev_get_plat(dev);
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080040 struct atmel_pit_regs *const regs = plat->regs;
41 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
42 struct clk clk;
43 ulong clk_rate;
44 int ret;
45
46 ret = clk_get_by_index(dev, 0, &clk);
47 if (ret)
48 return -EINVAL;
49
50 clk_rate = clk_get_rate(&clk);
51 if (!clk_rate)
52 return -EINVAL;
53
54 uc_priv->clock_rate = clk_rate / 16;
55
56 writel(AT91_PIT_VALUE | AT91_PIT_PITEN, &regs->mode);
57
58 return 0;
59}
60
Simon Glassd1998a92020-12-03 16:55:21 -070061static int atmel_pit_of_to_plat(struct udevice *dev)
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080062{
Simon Glass8a8d24b2020-12-03 16:55:23 -070063 struct atmel_pit_plat *plat = dev_get_plat(dev);
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080064
Masahiro Yamada702e57e2020-08-04 14:14:43 +090065 plat->regs = dev_read_addr_ptr(dev);
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080066
67 return 0;
68}
69
70static const struct timer_ops atmel_pit_ops = {
71 .get_count = atmel_pit_get_count,
72};
73
74static const struct udevice_id atmel_pit_ids[] = {
75 { .compatible = "atmel,at91sam9260-pit" },
76 { }
77};
78
79U_BOOT_DRIVER(atmel_pit) = {
80 .name = "atmel_pit",
81 .id = UCLASS_TIMER,
82 .of_match = atmel_pit_ids,
Simon Glassd1998a92020-12-03 16:55:21 -070083 .of_to_plat = atmel_pit_of_to_plat,
Simon Glass8a8d24b2020-12-03 16:55:23 -070084 .plat_auto = sizeof(struct atmel_pit_plat),
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080085 .probe = atmel_pit_probe,
86 .ops = &atmel_pit_ops,
Wenyou.Yang@microchip.com47edaea2017-08-15 17:40:26 +080087};