blob: a3207895f4068151c7c46b08d88824a2ae3be325 [file] [log] [blame]
Cheick Traorea2d20272025-03-11 15:30:34 +01001// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
4 * Author: Cheick Traore <cheick.traore@foss.st.com>
5 *
6 * Originally based on the Linux kernel v6.1 drivers/mfd/stm32-timers.c.
7 */
8
9#include <dm.h>
10#include <asm/io.h>
11#include <asm/arch/timers.h>
12#include <dm/device_compat.h>
13
14static void stm32_timers_get_arr_size(struct udevice *dev)
15{
16 struct stm32_timers_plat *plat = dev_get_plat(dev);
17 struct stm32_timers_priv *priv = dev_get_priv(dev);
18 u32 arr;
19
20 /* Backup ARR to restore it after getting the maximum value */
21 arr = readl(plat->base + TIM_ARR);
22
23 /*
24 * Only the available bits will be written so when readback
25 * we get the maximum value of auto reload register
26 */
27 writel(~0L, plat->base + TIM_ARR);
28 priv->max_arr = readl(plat->base + TIM_ARR);
29 writel(arr, plat->base + TIM_ARR);
30}
31
32static int stm32_timers_of_to_plat(struct udevice *dev)
33{
34 struct stm32_timers_plat *plat = dev_get_plat(dev);
35
36 plat->base = dev_read_addr_ptr(dev);
37 if (!plat->base) {
38 dev_err(dev, "can't get address\n");
39 return -ENOENT;
40 }
41
42 return 0;
43}
44
45static int stm32_timers_probe(struct udevice *dev)
46{
47 struct stm32_timers_priv *priv = dev_get_priv(dev);
48 struct clk clk;
49 int ret = 0;
50
51 ret = clk_get_by_index(dev, 0, &clk);
52 if (ret < 0)
53 return ret;
54
55 ret = clk_enable(&clk);
56 if (ret) {
57 dev_err(dev, "failed to enable clock: ret=%d\n", ret);
58 return ret;
59 }
60
61 priv->rate = clk_get_rate(&clk);
62
63 stm32_timers_get_arr_size(dev);
64
65 return ret;
66}
67
68static const struct udevice_id stm32_timers_ids[] = {
69 { .compatible = "st,stm32-timers" },
70 {}
71};
72
73U_BOOT_DRIVER(stm32_timers) = {
74 .name = "stm32_timers",
75 .id = UCLASS_NOP,
76 .of_match = stm32_timers_ids,
77 .of_to_plat = stm32_timers_of_to_plat,
78 .plat_auto = sizeof(struct stm32_timers_plat),
79 .probe = stm32_timers_probe,
80 .priv_auto = sizeof(struct stm32_timers_priv),
81 .bind = dm_scan_fdt_dev,
82};