blob: d69f2c7dd3e46ed118d9fab3fd059354bb50c4f7 [file] [log] [blame]
Shashank Mittal30262902012-02-21 15:37:24 -08001/*
Duy Truongf3ac7b32013-02-13 01:07:28 -08002 * Copyright (c) 2012, 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
56/*
57 * Standard clock functions defined in include/clk.h
58 */
59int clk_enable(struct clk *clk)
60{
61 int ret = 0;
62 struct clk *parent;
63
64 if (!clk)
65 return 0;
66
67 if (clk->count == 0) {
68 parent = clk_get_parent(clk);
69 ret = clk_enable(parent);
70 if (ret)
71 goto out;
72
73 if (clk->ops->enable)
74 ret = clk->ops->enable(clk);
75 if (ret) {
76 clk_disable(parent);
77 goto out;
78 }
79 }
80 clk->count++;
81out:
82 return ret;
83}
84
85void clk_disable(struct clk *clk)
86{
87 struct clk *parent;
88
89 if (!clk)
90 return;
91
92 if (clk->count == 0)
93 goto out;
94 if (clk->count == 1) {
95 if (clk->ops->disable)
96 clk->ops->disable(clk);
97 parent = clk_get_parent(clk);
98 clk_disable(parent);
99 }
100 clk->count--;
101out:
102 return;
103}
104
105unsigned long clk_get_rate(struct clk *clk)
106{
107 if (!clk->ops->get_rate)
108 return 0;
109
110 return clk->ops->get_rate(clk);
111}
112
113int clk_set_rate(struct clk *clk, unsigned long rate)
114{
115 if (!clk->ops->set_rate)
116 return ERR_NOT_VALID;
117
118 return clk->ops->set_rate(clk, rate);
119}
120
121void clk_init(struct clk_lookup *clist, unsigned num)
122{
123 if(clist && num)
124 {
125 msm_clk_list.clist = (struct clk_lookup *)clist;
126 msm_clk_list.num = num;
127 }
128}
129
130struct clk *clk_get (const char * cid)
131{
132 unsigned i;
133 struct clk_lookup *cl= msm_clk_list.clist;
134 unsigned num = msm_clk_list.num;
135
136 if(!cl || !num)
137 {
138 dprintf (CRITICAL, "Alert!! clock list not defined!\n");
139 return NULL;
140 }
141 for(i=0; i < num; i++, cl++)
142 {
143 if(!strcmp(cl->con_id, cid))
144 {
145 return cl->clk;
146 }
147 }
148
149 dprintf(CRITICAL, "Alert!! Requested clock \"%s\" is not supported!", cid);
150 return NULL;
151}
152
153int clk_get_set_enable(char *id, unsigned long rate, bool enable)
154{
155 int ret = NO_ERROR;
156 struct clk *cp;
157
158 /* Get clk */
159 cp = clk_get(id);
160 if(!cp)
161 {
162 dprintf(CRITICAL, "Can't find clock with id: %s\n", id);
163 ret = ERR_NOT_VALID;
164 goto get_set_enable_error;
165 }
166
167 /* Set rate */
168 if(rate)
169 {
170 ret = clk_set_rate(cp, rate);
171 if(ret)
172 {
173 dprintf(CRITICAL, "Clock set rate failed.\n");
174 goto get_set_enable_error;
175 }
176 }
177
178 /* Enable clock */
179 if(enable)
180 {
181 ret = clk_enable(cp);
182 if(ret)
183 {
184 dprintf(CRITICAL, "Clock enable failed.\n");
185 }
186 }
187
188get_set_enable_error:
189 return ret;
190}
191
192#ifdef DEBUG_CLOCK
193struct clk_list *clk_get_list()
194{
195 return &msm_clk_list;
196}
197#endif