1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2015 Altera Corporation. All rights reserved
5 #include <linux/slab.h>
6 #include <linux/clk-provider.h>
8 #include <linux/mfd/syscon.h>
10 #include <linux/regmap.h>
14 #define streq(a, b) (strcmp((a), (b)) == 0)
16 #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
18 /* SDMMC Group for System Manager defines */
19 #define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x28
21 static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw
*hwclk
,
22 unsigned long parent_rate
)
24 struct socfpga_gate_clk
*socfpgaclk
= to_socfpga_gate_clk(hwclk
);
27 if (socfpgaclk
->fixed_div
)
28 div
= socfpgaclk
->fixed_div
;
29 else if (socfpgaclk
->div_reg
) {
30 val
= readl(socfpgaclk
->div_reg
) >> socfpgaclk
->shift
;
31 val
&= GENMASK(socfpgaclk
->width
- 1, 0);
35 return parent_rate
/ div
;
38 static struct clk_ops gateclk_ops
= {
39 .recalc_rate
= socfpga_gate_clk_recalc_rate
,
42 static void __init
__socfpga_gate_init(struct device_node
*node
,
43 const struct clk_ops
*ops
)
48 struct clk_hw
*hw_clk
;
49 struct socfpga_gate_clk
*socfpga_clk
;
50 const char *clk_name
= node
->name
;
51 const char *parent_name
[SOCFPGA_MAX_PARENTS
];
52 struct clk_init_data init
;
55 socfpga_clk
= kzalloc(sizeof(*socfpga_clk
), GFP_KERNEL
);
56 if (WARN_ON(!socfpga_clk
))
59 rc
= of_property_read_u32_array(node
, "clk-gate", clk_gate
, 2);
64 socfpga_clk
->hw
.reg
= clk_mgr_a10_base_addr
+ clk_gate
[0];
65 socfpga_clk
->hw
.bit_idx
= clk_gate
[1];
67 gateclk_ops
.enable
= clk_gate_ops
.enable
;
68 gateclk_ops
.disable
= clk_gate_ops
.disable
;
71 rc
= of_property_read_u32(node
, "fixed-divider", &fixed_div
);
73 socfpga_clk
->fixed_div
= 0;
75 socfpga_clk
->fixed_div
= fixed_div
;
77 rc
= of_property_read_u32_array(node
, "div-reg", div_reg
, 3);
79 socfpga_clk
->div_reg
= clk_mgr_a10_base_addr
+ div_reg
[0];
80 socfpga_clk
->shift
= div_reg
[1];
81 socfpga_clk
->width
= div_reg
[2];
83 socfpga_clk
->div_reg
= NULL
;
86 of_property_read_string(node
, "clock-output-names", &clk_name
);
92 init
.num_parents
= of_clk_parent_fill(node
, parent_name
, SOCFPGA_MAX_PARENTS
);
93 init
.parent_names
= parent_name
;
94 socfpga_clk
->hw
.hw
.init
= &init
;
95 hw_clk
= &socfpga_clk
->hw
.hw
;
97 rc
= clk_hw_register(NULL
, hw_clk
);
99 pr_err("Could not register clock:%s\n", clk_name
);
100 goto err_clk_hw_register
;
103 rc
= of_clk_add_hw_provider(node
, of_clk_hw_simple_get
, hw_clk
);
105 pr_err("Could not register clock provider for node:%s\n",
107 goto err_of_clk_add_hw_provider
;
112 err_of_clk_add_hw_provider
:
113 clk_hw_unregister(hw_clk
);
118 void __init
socfpga_a10_gate_init(struct device_node
*node
)
120 __socfpga_gate_init(node
, &gateclk_ops
);