xref: /OK3568_Linux_fs/kernel/drivers/clk/pistachio/clk.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2014 Google, Inc.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/clk.h>
7*4882a593Smuzhiyun #include <linux/clk-provider.h>
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/of.h>
10*4882a593Smuzhiyun #include <linux/of_address.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "clk.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun struct pistachio_clk_provider *
pistachio_clk_alloc_provider(struct device_node * node,unsigned int num_clks)16*4882a593Smuzhiyun pistachio_clk_alloc_provider(struct device_node *node, unsigned int num_clks)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun 	struct pistachio_clk_provider *p;
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 	p = kzalloc(sizeof(*p), GFP_KERNEL);
21*4882a593Smuzhiyun 	if (!p)
22*4882a593Smuzhiyun 		return p;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	p->clk_data.clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL);
25*4882a593Smuzhiyun 	if (!p->clk_data.clks)
26*4882a593Smuzhiyun 		goto free_provider;
27*4882a593Smuzhiyun 	p->clk_data.clk_num = num_clks;
28*4882a593Smuzhiyun 	p->node = node;
29*4882a593Smuzhiyun 	p->base = of_iomap(node, 0);
30*4882a593Smuzhiyun 	if (!p->base) {
31*4882a593Smuzhiyun 		pr_err("Failed to map clock provider registers\n");
32*4882a593Smuzhiyun 		goto free_clks;
33*4882a593Smuzhiyun 	}
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	return p;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun free_clks:
38*4882a593Smuzhiyun 	kfree(p->clk_data.clks);
39*4882a593Smuzhiyun free_provider:
40*4882a593Smuzhiyun 	kfree(p);
41*4882a593Smuzhiyun 	return NULL;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun 
pistachio_clk_register_provider(struct pistachio_clk_provider * p)44*4882a593Smuzhiyun void pistachio_clk_register_provider(struct pistachio_clk_provider *p)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	unsigned int i;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	for (i = 0; i < p->clk_data.clk_num; i++) {
49*4882a593Smuzhiyun 		if (IS_ERR(p->clk_data.clks[i]))
50*4882a593Smuzhiyun 			pr_warn("Failed to register clock %d: %ld\n", i,
51*4882a593Smuzhiyun 				PTR_ERR(p->clk_data.clks[i]));
52*4882a593Smuzhiyun 	}
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	of_clk_add_provider(p->node, of_clk_src_onecell_get, &p->clk_data);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
pistachio_clk_register_gate(struct pistachio_clk_provider * p,struct pistachio_gate * gate,unsigned int num)57*4882a593Smuzhiyun void pistachio_clk_register_gate(struct pistachio_clk_provider *p,
58*4882a593Smuzhiyun 				 struct pistachio_gate *gate,
59*4882a593Smuzhiyun 				 unsigned int num)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct clk *clk;
62*4882a593Smuzhiyun 	unsigned int i;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
65*4882a593Smuzhiyun 		clk = clk_register_gate(NULL, gate[i].name, gate[i].parent,
66*4882a593Smuzhiyun 					CLK_SET_RATE_PARENT,
67*4882a593Smuzhiyun 					p->base + gate[i].reg, gate[i].shift,
68*4882a593Smuzhiyun 					0, NULL);
69*4882a593Smuzhiyun 		p->clk_data.clks[gate[i].id] = clk;
70*4882a593Smuzhiyun 	}
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
pistachio_clk_register_mux(struct pistachio_clk_provider * p,struct pistachio_mux * mux,unsigned int num)73*4882a593Smuzhiyun void pistachio_clk_register_mux(struct pistachio_clk_provider *p,
74*4882a593Smuzhiyun 				struct pistachio_mux *mux,
75*4882a593Smuzhiyun 				unsigned int num)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	struct clk *clk;
78*4882a593Smuzhiyun 	unsigned int i;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
81*4882a593Smuzhiyun 		clk = clk_register_mux(NULL, mux[i].name, mux[i].parents,
82*4882a593Smuzhiyun 				       mux[i].num_parents,
83*4882a593Smuzhiyun 				       CLK_SET_RATE_NO_REPARENT,
84*4882a593Smuzhiyun 				       p->base + mux[i].reg, mux[i].shift,
85*4882a593Smuzhiyun 				       get_count_order(mux[i].num_parents),
86*4882a593Smuzhiyun 				       0, NULL);
87*4882a593Smuzhiyun 		p->clk_data.clks[mux[i].id] = clk;
88*4882a593Smuzhiyun 	}
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
pistachio_clk_register_div(struct pistachio_clk_provider * p,struct pistachio_div * div,unsigned int num)91*4882a593Smuzhiyun void pistachio_clk_register_div(struct pistachio_clk_provider *p,
92*4882a593Smuzhiyun 				struct pistachio_div *div,
93*4882a593Smuzhiyun 				unsigned int num)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	struct clk *clk;
96*4882a593Smuzhiyun 	unsigned int i;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
99*4882a593Smuzhiyun 		clk = clk_register_divider(NULL, div[i].name, div[i].parent,
100*4882a593Smuzhiyun 					   0, p->base + div[i].reg, 0,
101*4882a593Smuzhiyun 					   div[i].width, div[i].div_flags,
102*4882a593Smuzhiyun 					   NULL);
103*4882a593Smuzhiyun 		p->clk_data.clks[div[i].id] = clk;
104*4882a593Smuzhiyun 	}
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
pistachio_clk_register_fixed_factor(struct pistachio_clk_provider * p,struct pistachio_fixed_factor * ff,unsigned int num)107*4882a593Smuzhiyun void pistachio_clk_register_fixed_factor(struct pistachio_clk_provider *p,
108*4882a593Smuzhiyun 					 struct pistachio_fixed_factor *ff,
109*4882a593Smuzhiyun 					 unsigned int num)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	struct clk *clk;
112*4882a593Smuzhiyun 	unsigned int i;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
115*4882a593Smuzhiyun 		clk = clk_register_fixed_factor(NULL, ff[i].name, ff[i].parent,
116*4882a593Smuzhiyun 						0, 1, ff[i].div);
117*4882a593Smuzhiyun 		p->clk_data.clks[ff[i].id] = clk;
118*4882a593Smuzhiyun 	}
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
pistachio_clk_force_enable(struct pistachio_clk_provider * p,unsigned int * clk_ids,unsigned int num)121*4882a593Smuzhiyun void pistachio_clk_force_enable(struct pistachio_clk_provider *p,
122*4882a593Smuzhiyun 				unsigned int *clk_ids, unsigned int num)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	unsigned int i;
125*4882a593Smuzhiyun 	int err;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
128*4882a593Smuzhiyun 		struct clk *clk = p->clk_data.clks[clk_ids[i]];
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 		if (IS_ERR(clk))
131*4882a593Smuzhiyun 			continue;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 		err = clk_prepare_enable(clk);
134*4882a593Smuzhiyun 		if (err)
135*4882a593Smuzhiyun 			pr_err("Failed to enable clock %s: %d\n",
136*4882a593Smuzhiyun 			       __clk_get_name(clk), err);
137*4882a593Smuzhiyun 	}
138*4882a593Smuzhiyun }
139