1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Microchip LAN966x SoC Clock driver.
5 * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
7 * Author: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
10 #include <linux/bitfield.h>
11 #include <linux/clk-provider.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/slab.h>
19 #include <dt-bindings/clock/microchip,lan966x.h>
21 #define GCK_ENA BIT(0)
22 #define GCK_SRC_SEL GENMASK(9, 8)
23 #define GCK_PRESCALER GENMASK(23, 16)
27 static const char *clk_names
[N_CLOCKS
] = {
28 "qspi0", "qspi1", "qspi2", "sdmmc0",
29 "pi", "mcan0", "mcan1", "flexcom0",
30 "flexcom1", "flexcom2", "flexcom3",
31 "flexcom4", "timer1", "usb_refclk",
38 #define to_lan966x_gck(hw) container_of(hw, struct lan966x_gck, hw)
40 static const struct clk_parent_data lan966x_gck_pdata
[] = {
41 { .fw_name
= "cpu", },
42 { .fw_name
= "ddr", },
43 { .fw_name
= "sys", },
46 static struct clk_init_data init
= {
47 .parent_data
= lan966x_gck_pdata
,
48 .num_parents
= ARRAY_SIZE(lan966x_gck_pdata
),
51 struct clk_gate_soc_desc
{
56 static const struct clk_gate_soc_desc clk_gate_desc
[] = {
64 static DEFINE_SPINLOCK(clk_gate_lock
);
65 static void __iomem
*base
;
67 static int lan966x_gck_enable(struct clk_hw
*hw
)
69 struct lan966x_gck
*gck
= to_lan966x_gck(hw
);
70 u32 val
= readl(gck
->reg
);
73 writel(val
, gck
->reg
);
78 static void lan966x_gck_disable(struct clk_hw
*hw
)
80 struct lan966x_gck
*gck
= to_lan966x_gck(hw
);
81 u32 val
= readl(gck
->reg
);
84 writel(val
, gck
->reg
);
87 static int lan966x_gck_set_rate(struct clk_hw
*hw
,
89 unsigned long parent_rate
)
91 struct lan966x_gck
*gck
= to_lan966x_gck(hw
);
92 u32 div
, val
= readl(gck
->reg
);
94 if (rate
== 0 || parent_rate
== 0)
98 div
= parent_rate
/ rate
;
99 val
&= ~GCK_PRESCALER
;
100 val
|= FIELD_PREP(GCK_PRESCALER
, (div
- 1));
101 writel(val
, gck
->reg
);
106 static unsigned long lan966x_gck_recalc_rate(struct clk_hw
*hw
,
107 unsigned long parent_rate
)
109 struct lan966x_gck
*gck
= to_lan966x_gck(hw
);
110 u32 div
, val
= readl(gck
->reg
);
112 div
= FIELD_GET(GCK_PRESCALER
, val
);
114 return parent_rate
/ (div
+ 1);
117 static int lan966x_gck_determine_rate(struct clk_hw
*hw
,
118 struct clk_rate_request
*req
)
120 struct clk_hw
*parent
;
123 for (i
= 0; i
< clk_hw_get_num_parents(hw
); ++i
) {
124 parent
= clk_hw_get_parent_by_index(hw
, i
);
128 /* Allowed prescaler divider range is 0-255 */
129 if (clk_hw_get_rate(parent
) / req
->rate
<= DIV_MAX
) {
130 req
->best_parent_hw
= parent
;
131 req
->best_parent_rate
= clk_hw_get_rate(parent
);
140 static u8
lan966x_gck_get_parent(struct clk_hw
*hw
)
142 struct lan966x_gck
*gck
= to_lan966x_gck(hw
);
143 u32 val
= readl(gck
->reg
);
145 return FIELD_GET(GCK_SRC_SEL
, val
);
148 static int lan966x_gck_set_parent(struct clk_hw
*hw
, u8 index
)
150 struct lan966x_gck
*gck
= to_lan966x_gck(hw
);
151 u32 val
= readl(gck
->reg
);
154 val
|= FIELD_PREP(GCK_SRC_SEL
, index
);
155 writel(val
, gck
->reg
);
160 static const struct clk_ops lan966x_gck_ops
= {
161 .enable
= lan966x_gck_enable
,
162 .disable
= lan966x_gck_disable
,
163 .set_rate
= lan966x_gck_set_rate
,
164 .recalc_rate
= lan966x_gck_recalc_rate
,
165 .determine_rate
= lan966x_gck_determine_rate
,
166 .set_parent
= lan966x_gck_set_parent
,
167 .get_parent
= lan966x_gck_get_parent
,
170 static struct clk_hw
*lan966x_gck_clk_register(struct device
*dev
, int i
)
172 struct lan966x_gck
*priv
;
175 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
177 return ERR_PTR(-ENOMEM
);
179 priv
->reg
= base
+ (i
* 4);
180 priv
->hw
.init
= &init
;
181 ret
= devm_clk_hw_register(dev
, &priv
->hw
);
188 static int lan966x_gate_clk_register(struct device
*dev
,
189 struct clk_hw_onecell_data
*hw_data
,
190 void __iomem
*gate_base
)
194 for (i
= GCK_GATE_UHPHS
; i
< N_CLOCKS
; ++i
) {
195 int idx
= i
- GCK_GATE_UHPHS
;
198 devm_clk_hw_register_gate(dev
, clk_gate_desc
[idx
].name
,
199 "lan966x", 0, gate_base
,
200 clk_gate_desc
[idx
].bit_idx
,
203 if (IS_ERR(hw_data
->hws
[i
]))
204 return dev_err_probe(dev
, PTR_ERR(hw_data
->hws
[i
]),
205 "failed to register %s clock\n",
206 clk_gate_desc
[idx
].name
);
212 static int lan966x_clk_probe(struct platform_device
*pdev
)
214 struct clk_hw_onecell_data
*hw_data
;
215 struct device
*dev
= &pdev
->dev
;
216 void __iomem
*gate_base
;
217 struct resource
*res
;
220 hw_data
= devm_kzalloc(dev
, struct_size(hw_data
, hws
, N_CLOCKS
),
225 base
= devm_platform_ioremap_resource(pdev
, 0);
227 return PTR_ERR(base
);
229 init
.ops
= &lan966x_gck_ops
;
231 hw_data
->num
= GCK_GATE_UHPHS
;
233 for (i
= 0; i
< GCK_GATE_UHPHS
; i
++) {
234 init
.name
= clk_names
[i
];
235 hw_data
->hws
[i
] = lan966x_gck_clk_register(dev
, i
);
236 if (IS_ERR(hw_data
->hws
[i
])) {
237 dev_err(dev
, "failed to register %s clock\n",
239 return PTR_ERR(hw_data
->hws
[i
]);
243 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
245 gate_base
= devm_ioremap_resource(&pdev
->dev
, res
);
246 if (IS_ERR(gate_base
))
247 return PTR_ERR(gate_base
);
249 hw_data
->num
= N_CLOCKS
;
251 ret
= lan966x_gate_clk_register(dev
, hw_data
, gate_base
);
256 return devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
, hw_data
);
259 static const struct of_device_id lan966x_clk_dt_ids
[] = {
260 { .compatible
= "microchip,lan966x-gck", },
263 MODULE_DEVICE_TABLE(of
, lan966x_clk_dt_ids
);
265 static struct platform_driver lan966x_clk_driver
= {
266 .probe
= lan966x_clk_probe
,
268 .name
= "lan966x-clk",
269 .of_match_table
= lan966x_clk_dt_ids
,
272 module_platform_driver(lan966x_clk_driver
);
274 MODULE_AUTHOR("Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>");
275 MODULE_DESCRIPTION("LAN966X clock driver");
276 MODULE_LICENSE("GPL v2");