1// SPDX-License-Identifier: GPL-2.0-only
2
3#include <linux/delay.h>
4#include <linux/clk-provider.h>
5#include <linux/io.h>
6#include <linux/of.h>
7#include <linux/platform_device.h>
8#include <dt-bindings/clock/en7523-clk.h>
9
10#define REG_PCI_CONTROL 0x88
11#define REG_PCI_CONTROL_PERSTOUT BIT(29)
12#define REG_PCI_CONTROL_PERSTOUT1 BIT(26)
13#define REG_PCI_CONTROL_REFCLK_EN1 BIT(22)
14#define REG_GSW_CLK_DIV_SEL 0x1b4
15#define REG_EMI_CLK_DIV_SEL 0x1b8
16#define REG_BUS_CLK_DIV_SEL 0x1bc
17#define REG_SPI_CLK_DIV_SEL 0x1c4
18#define REG_SPI_CLK_FREQ_SEL 0x1c8
19#define REG_NPU_CLK_DIV_SEL 0x1fc
20#define REG_CRYPTO_CLKSRC 0x200
21#define REG_RESET_CONTROL 0x834
22#define REG_RESET_CONTROL_PCIEHB BIT(29)
23#define REG_RESET_CONTROL_PCIE1 BIT(27)
24#define REG_RESET_CONTROL_PCIE2 BIT(26)
25
26struct en_clk_desc {
27 int id;
28 const char *name;
29 u32 base_reg;
30 u8 base_bits;
31 u8 base_shift;
32 union {
33 const unsigned int *base_values;
34 unsigned int base_value;
35 };
36 size_t n_base_values;
37
38 u16 div_reg;
39 u8 div_bits;
40 u8 div_shift;
41 u16 div_val0;
42 u8 div_step;
43};
44
45struct en_clk_gate {
46 void __iomem *base;
47 struct clk_hw hw;
48};
49
50static const u32 gsw_base[] = { 400000000, 500000000 };
51static const u32 emi_base[] = { 333000000, 400000000 };
52static const u32 bus_base[] = { 500000000, 540000000 };
53static const u32 slic_base[] = { 100000000, 3125000 };
54static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
55
56static const struct en_clk_desc en7523_base_clks[] = {
57 {
58 .id = EN7523_CLK_GSW,
59 .name = "gsw",
60
61 .base_reg = REG_GSW_CLK_DIV_SEL,
62 .base_bits = 1,
63 .base_shift = 8,
64 .base_values = gsw_base,
65 .n_base_values = ARRAY_SIZE(gsw_base),
66
67 .div_bits = 3,
68 .div_shift = 0,
69 .div_step = 1,
70 }, {
71 .id = EN7523_CLK_EMI,
72 .name = "emi",
73
74 .base_reg = REG_EMI_CLK_DIV_SEL,
75 .base_bits = 1,
76 .base_shift = 8,
77 .base_values = emi_base,
78 .n_base_values = ARRAY_SIZE(emi_base),
79
80 .div_bits = 3,
81 .div_shift = 0,
82 .div_step = 1,
83 }, {
84 .id = EN7523_CLK_BUS,
85 .name = "bus",
86
87 .base_reg = REG_BUS_CLK_DIV_SEL,
88 .base_bits = 1,
89 .base_shift = 8,
90 .base_values = bus_base,
91 .n_base_values = ARRAY_SIZE(bus_base),
92
93 .div_bits = 3,
94 .div_shift = 0,
95 .div_step = 1,
96 }, {
97 .id = EN7523_CLK_SLIC,
98 .name = "slic",
99
100 .base_reg = REG_SPI_CLK_FREQ_SEL,
101 .base_bits = 1,
102 .base_shift = 0,
103 .base_values = slic_base,
104 .n_base_values = ARRAY_SIZE(slic_base),
105
106 .div_reg = REG_SPI_CLK_DIV_SEL,
107 .div_bits = 5,
108 .div_shift = 24,
109 .div_val0 = 20,
110 .div_step = 2,
111 }, {
112 .id = EN7523_CLK_SPI,
113 .name = "spi",
114
115 .base_reg = REG_SPI_CLK_DIV_SEL,
116
117 .base_value = 400000000,
118
119 .div_bits = 5,
120 .div_shift = 8,
121 .div_val0 = 40,
122 .div_step = 2,
123 }, {
124 .id = EN7523_CLK_NPU,
125 .name = "npu",
126
127 .base_reg = REG_NPU_CLK_DIV_SEL,
128 .base_bits = 2,
129 .base_shift = 8,
130 .base_values = npu_base,
131 .n_base_values = ARRAY_SIZE(npu_base),
132
133 .div_bits = 3,
134 .div_shift = 0,
135 .div_step = 1,
136 }, {
137 .id = EN7523_CLK_CRYPTO,
138 .name = "crypto",
139
140 .base_reg = REG_CRYPTO_CLKSRC,
141 .base_bits = 1,
142 .base_shift = 8,
143 .base_values = emi_base,
144 .n_base_values = ARRAY_SIZE(emi_base),
145 }
146};
147
148static const struct of_device_id of_match_clk_en7523[] = {
149 { .compatible = "airoha,en7523-scu", },
150 { /* sentinel */ }
151};
152
153static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
154{
155 const struct en_clk_desc *desc = &en7523_base_clks[i];
156 u32 val;
157
158 if (!desc->base_bits)
159 return desc->base_value;
160
161 val = readl(addr: base + desc->base_reg);
162 val >>= desc->base_shift;
163 val &= (1 << desc->base_bits) - 1;
164
165 if (val >= desc->n_base_values)
166 return 0;
167
168 return desc->base_values[val];
169}
170
171static u32 en7523_get_div(void __iomem *base, int i)
172{
173 const struct en_clk_desc *desc = &en7523_base_clks[i];
174 u32 reg, val;
175
176 if (!desc->div_bits)
177 return 1;
178
179 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
180 val = readl(addr: base + reg);
181 val >>= desc->div_shift;
182 val &= (1 << desc->div_bits) - 1;
183
184 if (!val && desc->div_val0)
185 return desc->div_val0;
186
187 return (val + 1) * desc->div_step;
188}
189
190static int en7523_pci_is_enabled(struct clk_hw *hw)
191{
192 struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
193
194 return !!(readl(addr: cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1);
195}
196
197static int en7523_pci_prepare(struct clk_hw *hw)
198{
199 struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
200 void __iomem *np_base = cg->base;
201 u32 val, mask;
202
203 /* Need to pull device low before reset */
204 val = readl(addr: np_base + REG_PCI_CONTROL);
205 val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT);
206 writel(val, addr: np_base + REG_PCI_CONTROL);
207 usleep_range(min: 1000, max: 2000);
208
209 /* Enable PCIe port 1 */
210 val |= REG_PCI_CONTROL_REFCLK_EN1;
211 writel(val, addr: np_base + REG_PCI_CONTROL);
212 usleep_range(min: 1000, max: 2000);
213
214 /* Reset to default */
215 val = readl(addr: np_base + REG_RESET_CONTROL);
216 mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
217 REG_RESET_CONTROL_PCIEHB;
218 writel(val: val & ~mask, addr: np_base + REG_RESET_CONTROL);
219 usleep_range(min: 1000, max: 2000);
220 writel(val: val | mask, addr: np_base + REG_RESET_CONTROL);
221 msleep(msecs: 100);
222 writel(val: val & ~mask, addr: np_base + REG_RESET_CONTROL);
223 usleep_range(min: 5000, max: 10000);
224
225 /* Release device */
226 mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT;
227 val = readl(addr: np_base + REG_PCI_CONTROL);
228 writel(val: val & ~mask, addr: np_base + REG_PCI_CONTROL);
229 usleep_range(min: 1000, max: 2000);
230 writel(val: val | mask, addr: np_base + REG_PCI_CONTROL);
231 msleep(msecs: 250);
232
233 return 0;
234}
235
236static void en7523_pci_unprepare(struct clk_hw *hw)
237{
238 struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
239 void __iomem *np_base = cg->base;
240 u32 val;
241
242 val = readl(addr: np_base + REG_PCI_CONTROL);
243 val &= ~REG_PCI_CONTROL_REFCLK_EN1;
244 writel(val, addr: np_base + REG_PCI_CONTROL);
245}
246
247static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
248 void __iomem *np_base)
249{
250 static const struct clk_ops pcie_gate_ops = {
251 .is_enabled = en7523_pci_is_enabled,
252 .prepare = en7523_pci_prepare,
253 .unprepare = en7523_pci_unprepare,
254 };
255 struct clk_init_data init = {
256 .name = "pcie",
257 .ops = &pcie_gate_ops,
258 };
259 struct en_clk_gate *cg;
260
261 cg = devm_kzalloc(dev, size: sizeof(*cg), GFP_KERNEL);
262 if (!cg)
263 return NULL;
264
265 cg->base = np_base;
266 cg->hw.init = &init;
267 en7523_pci_unprepare(hw: &cg->hw);
268
269 if (clk_hw_register(dev, hw: &cg->hw))
270 return NULL;
271
272 return &cg->hw;
273}
274
275static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
276 void __iomem *base, void __iomem *np_base)
277{
278 struct clk_hw *hw;
279 u32 rate;
280 int i;
281
282 for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
283 const struct en_clk_desc *desc = &en7523_base_clks[i];
284
285 rate = en7523_get_base_rate(base, i);
286 rate /= en7523_get_div(base, i);
287
288 hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
289 if (IS_ERR(ptr: hw)) {
290 pr_err("Failed to register clk %s: %ld\n",
291 desc->name, PTR_ERR(hw));
292 continue;
293 }
294
295 clk_data->hws[desc->id] = hw;
296 }
297
298 hw = en7523_register_pcie_clk(dev, np_base);
299 clk_data->hws[EN7523_CLK_PCIE] = hw;
300
301 clk_data->num = EN7523_NUM_CLOCKS;
302}
303
304static int en7523_clk_probe(struct platform_device *pdev)
305{
306 struct device_node *node = pdev->dev.of_node;
307 struct clk_hw_onecell_data *clk_data;
308 void __iomem *base, *np_base;
309 int r;
310
311 base = devm_platform_ioremap_resource(pdev, index: 0);
312 if (IS_ERR(ptr: base))
313 return PTR_ERR(ptr: base);
314
315 np_base = devm_platform_ioremap_resource(pdev, index: 1);
316 if (IS_ERR(ptr: np_base))
317 return PTR_ERR(ptr: np_base);
318
319 clk_data = devm_kzalloc(dev: &pdev->dev,
320 struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
321 GFP_KERNEL);
322 if (!clk_data)
323 return -ENOMEM;
324
325 en7523_register_clocks(dev: &pdev->dev, clk_data, base, np_base);
326
327 r = of_clk_add_hw_provider(np: node, get: of_clk_hw_onecell_get, data: clk_data);
328 if (r)
329 dev_err(&pdev->dev,
330 "could not register clock provider: %s: %d\n",
331 pdev->name, r);
332
333 return r;
334}
335
336static struct platform_driver clk_en7523_drv = {
337 .probe = en7523_clk_probe,
338 .driver = {
339 .name = "clk-en7523",
340 .of_match_table = of_match_clk_en7523,
341 .suppress_bind_attrs = true,
342 },
343};
344
345static int __init clk_en7523_init(void)
346{
347 return platform_driver_register(&clk_en7523_drv);
348}
349
350arch_initcall(clk_en7523_init);
351

source code of linux/drivers/clk/clk-en7523.c