blob: 35ed5c6fd22decdbda32cd25207dbc0d8752ec62 [file] [log] [blame]
Shashank Mittal30262902012-02-21 15:37:24 -08001/*
Channagoud Kadabif32341c2014-04-03 15:34:04 -07002 * Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved.
Shashank Mittal30262902012-02-21 15:37:24 -08003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
Duy Truongf3ac7b32013-02-13 01:07:28 -080011 * * Neither the name of The Linux Foundation nor
Shashank Mittal30262902012-02-21 15:37:24 -080012 * the names of its contributors may be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdint.h>
30#include <debug.h>
31#include <reg.h>
32#include <err.h>
33#include <limits.h>
34#include <bits.h>
35#include <clock.h>
36#include <string.h>
37
38static struct clk_list msm_clk_list;
39
40int clk_set_parent(struct clk *clk, struct clk *parent)
41{
42 if (!clk->ops->set_parent)
43 return 0;
44
45 return clk->ops->set_parent(clk, parent);
46}
47
48struct clk *clk_get_parent(struct clk *clk)
49{
50 if (!clk->ops->get_parent)
51 return NULL;
52
53 return clk->ops->get_parent(clk);
54}
55
Channagoud Kadabif32341c2014-04-03 15:34:04 -070056int clk_reset(struct clk *clk, enum clk_reset_action action)
57{
58 if (!clk)
59 return 0;
60
61 if (!clk->ops->reset)
62 return 0;
63
64 return clk->ops->reset(clk, action);
65}
66
Shashank Mittal30262902012-02-21 15:37:24 -080067/*
68 * Standard clock functions defined in include/clk.h
69 */
70int clk_enable(struct clk *clk)
71{
72 int ret = 0;
73 struct clk *parent;
74
75 if (!clk)
76 return 0;
77
78 if (clk->count == 0) {
79 parent = clk_get_parent(clk);
80 ret = clk_enable(parent);
81 if (ret)
82 goto out;
83
84 if (clk->ops->enable)
85 ret = clk->ops->enable(clk);
86 if (ret) {
87 clk_disable(parent);
88 goto out;
89 }
90 }
91 clk->count++;
92out:
93 return ret;
94}
95
96void clk_disable(struct clk *clk)
97{
98 struct clk *parent;
99
100 if (!clk)
101 return;
102
103 if (clk->count == 0)
104 goto out;
105 if (clk->count == 1) {
106 if (clk->ops->disable)
107 clk->ops->disable(clk);
108 parent = clk_get_parent(clk);
109 clk_disable(parent);
110 }
111 clk->count--;
112out:
113 return;
114}
115
116unsigned long clk_get_rate(struct clk *clk)
117{
118 if (!clk->ops->get_rate)
119 return 0;
120
121 return clk->ops->get_rate(clk);
122}
123
124int clk_set_rate(struct clk *clk, unsigned long rate)
125{
126 if (!clk->ops->set_rate)
127 return ERR_NOT_VALID;
128
129 return clk->ops->set_rate(clk, rate);
130}
131
132void clk_init(struct clk_lookup *clist, unsigned num)
133{
134 if(clist && num)
135 {
136 msm_clk_list.clist = (struct clk_lookup *)clist;
137 msm_clk_list.num = num;
138 }
139}
140
141struct clk *clk_get (const char * cid)
142{
143 unsigned i;
144 struct clk_lookup *cl= msm_clk_list.clist;
145 unsigned num = msm_clk_list.num;
146
147 if(!cl || !num)
148 {
149 dprintf (CRITICAL, "Alert!! clock list not defined!\n");
150 return NULL;
151 }
152 for(i=0; i < num; i++, cl++)
153 {
154 if(!strcmp(cl->con_id, cid))
155 {
156 return cl->clk;
157 }
158 }
159
160 dprintf(CRITICAL, "Alert!! Requested clock \"%s\" is not supported!", cid);
161 return NULL;
162}
163
164int clk_get_set_enable(char *id, unsigned long rate, bool enable)
165{
166 int ret = NO_ERROR;
167 struct clk *cp;
168
169 /* Get clk */
170 cp = clk_get(id);
171 if(!cp)
172 {
173 dprintf(CRITICAL, "Can't find clock with id: %s\n", id);
174 ret = ERR_NOT_VALID;
175 goto get_set_enable_error;
176 }
177
178 /* Set rate */
179 if(rate)
180 {
181 ret = clk_set_rate(cp, rate);
182 if(ret)
183 {
184 dprintf(CRITICAL, "Clock set rate failed.\n");
185 goto get_set_enable_error;
186 }
187 }
188
189 /* Enable clock */
190 if(enable)
191 {
192 ret = clk_enable(cp);
193 if(ret)
194 {
195 dprintf(CRITICAL, "Clock enable failed.\n");
196 }
197 }
198
199get_set_enable_error:
200 return ret;
201}
202
203#ifdef DEBUG_CLOCK
204struct clk_list *clk_get_list()
205{
206 return &msm_clk_list;
207}
208#endif