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