GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / clk / bcm / clk-bcm63268-timer.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * BCM63268 Timer Clock and Reset Controller Driver
4  *
5  * Copyright (C) 2023 Álvaro Fernández Rojas <noltari@gmail.com>
6  */
7
8 #include <linux/clk-provider.h>
9 #include <linux/container_of.h>
10 #include <linux/delay.h>
11 #include <linux/device.h>
12 #include <linux/io.h>
13 #include <linux/platform_device.h>
14 #include <linux/reset-controller.h>
15 #include <linux/spinlock.h>
16
17 #include <dt-bindings/clock/bcm63268-clock.h>
18
19 #define BCM63268_TIMER_RESET_SLEEP_MIN_US       10000
20 #define BCM63268_TIMER_RESET_SLEEP_MAX_US       20000
21
22 struct bcm63268_tclkrst_hw {
23         void __iomem *regs;
24         spinlock_t lock;
25
26         struct reset_controller_dev rcdev;
27         struct clk_hw_onecell_data data;
28 };
29
30 struct bcm63268_tclk_table_entry {
31         const char * const name;
32         u8 bit;
33 };
34
35 static const struct bcm63268_tclk_table_entry bcm63268_timer_clocks[] = {
36         {
37                 .name = "ephy1",
38                 .bit = BCM63268_TCLK_EPHY1,
39         }, {
40                 .name = "ephy2",
41                 .bit = BCM63268_TCLK_EPHY2,
42         }, {
43                 .name = "ephy3",
44                 .bit = BCM63268_TCLK_EPHY3,
45         }, {
46                 .name = "gphy1",
47                 .bit = BCM63268_TCLK_GPHY1,
48         }, {
49                 .name = "dsl",
50                 .bit = BCM63268_TCLK_DSL,
51         }, {
52                 .name = "wakeon_ephy",
53                 .bit = BCM63268_TCLK_WAKEON_EPHY,
54         }, {
55                 .name = "wakeon_dsl",
56                 .bit = BCM63268_TCLK_WAKEON_DSL,
57         }, {
58                 .name = "fap1_pll",
59                 .bit = BCM63268_TCLK_FAP1,
60         }, {
61                 .name = "fap2_pll",
62                 .bit = BCM63268_TCLK_FAP2,
63         }, {
64                 .name = "uto_50",
65                 .bit = BCM63268_TCLK_UTO_50,
66         }, {
67                 .name = "uto_extin",
68                 .bit = BCM63268_TCLK_UTO_EXTIN,
69         }, {
70                 .name = "usb_ref",
71                 .bit = BCM63268_TCLK_USB_REF,
72         }, {
73                 /* sentinel */
74         }
75 };
76
77 static inline struct bcm63268_tclkrst_hw *
78 to_bcm63268_timer_reset(struct reset_controller_dev *rcdev)
79 {
80         return container_of(rcdev, struct bcm63268_tclkrst_hw, rcdev);
81 }
82
83 static int bcm63268_timer_reset_update(struct reset_controller_dev *rcdev,
84                                 unsigned long id, bool assert)
85 {
86         struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev);
87         unsigned long flags;
88         uint32_t val;
89
90         spin_lock_irqsave(&reset->lock, flags);
91         val = __raw_readl(reset->regs);
92         if (assert)
93                 val &= ~BIT(id);
94         else
95                 val |= BIT(id);
96         __raw_writel(val, reset->regs);
97         spin_unlock_irqrestore(&reset->lock, flags);
98
99         return 0;
100 }
101
102 static int bcm63268_timer_reset_assert(struct reset_controller_dev *rcdev,
103                                 unsigned long id)
104 {
105         return bcm63268_timer_reset_update(rcdev, id, true);
106 }
107
108 static int bcm63268_timer_reset_deassert(struct reset_controller_dev *rcdev,
109                                   unsigned long id)
110 {
111         return bcm63268_timer_reset_update(rcdev, id, false);
112 }
113
114 static int bcm63268_timer_reset_reset(struct reset_controller_dev *rcdev,
115                                unsigned long id)
116 {
117         bcm63268_timer_reset_update(rcdev, id, true);
118         usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US,
119                      BCM63268_TIMER_RESET_SLEEP_MAX_US);
120
121         bcm63268_timer_reset_update(rcdev, id, false);
122         /*
123          * Ensure component is taken out reset state by sleeping also after
124          * deasserting the reset. Otherwise, the component may not be ready
125          * for operation.
126          */
127         usleep_range(BCM63268_TIMER_RESET_SLEEP_MIN_US,
128                      BCM63268_TIMER_RESET_SLEEP_MAX_US);
129
130         return 0;
131 }
132
133 static int bcm63268_timer_reset_status(struct reset_controller_dev *rcdev,
134                                 unsigned long id)
135 {
136         struct bcm63268_tclkrst_hw *reset = to_bcm63268_timer_reset(rcdev);
137
138         return !(__raw_readl(reset->regs) & BIT(id));
139 }
140
141 static const struct reset_control_ops bcm63268_timer_reset_ops = {
142         .assert = bcm63268_timer_reset_assert,
143         .deassert = bcm63268_timer_reset_deassert,
144         .reset = bcm63268_timer_reset_reset,
145         .status = bcm63268_timer_reset_status,
146 };
147
148 static int bcm63268_tclk_probe(struct platform_device *pdev)
149 {
150         struct device *dev = &pdev->dev;
151         const struct bcm63268_tclk_table_entry *entry;
152         struct bcm63268_tclkrst_hw *hw;
153         struct clk_hw *clk;
154         u8 maxbit = 0;
155         int i, ret;
156
157         for (entry = bcm63268_timer_clocks; entry->name; entry++)
158                 maxbit = max(maxbit, entry->bit);
159         maxbit++;
160
161         hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
162                           GFP_KERNEL);
163         if (!hw)
164                 return -ENOMEM;
165
166         platform_set_drvdata(pdev, hw);
167
168         spin_lock_init(&hw->lock);
169
170         hw->data.num = maxbit;
171         for (i = 0; i < maxbit; i++)
172                 hw->data.hws[i] = ERR_PTR(-ENODEV);
173
174         hw->regs = devm_platform_ioremap_resource(pdev, 0);
175         if (IS_ERR(hw->regs))
176                 return PTR_ERR(hw->regs);
177
178         for (entry = bcm63268_timer_clocks; entry->name; entry++) {
179                 clk = devm_clk_hw_register_gate(dev, entry->name, NULL, 0,
180                                                 hw->regs, entry->bit,
181                                                 CLK_GATE_BIG_ENDIAN,
182                                                 &hw->lock);
183                 if (IS_ERR(clk))
184                         return PTR_ERR(clk);
185
186                 hw->data.hws[entry->bit] = clk;
187         }
188
189         ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
190                                           &hw->data);
191         if (ret)
192                 return ret;
193
194         hw->rcdev.of_node = dev->of_node;
195         hw->rcdev.ops = &bcm63268_timer_reset_ops;
196
197         ret = devm_reset_controller_register(dev, &hw->rcdev);
198         if (ret)
199                 dev_err(dev, "Failed to register reset controller\n");
200
201         return 0;
202 }
203
204 static const struct of_device_id bcm63268_tclk_dt_ids[] = {
205         { .compatible = "brcm,bcm63268-timer-clocks" },
206         { /* sentinel */ }
207 };
208
209 static struct platform_driver bcm63268_tclk = {
210         .probe = bcm63268_tclk_probe,
211         .driver = {
212                 .name = "bcm63268-timer-clock",
213                 .of_match_table = bcm63268_tclk_dt_ids,
214         },
215 };
216 builtin_platform_driver(bcm63268_tclk);