Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * OMAP2 and OMAP3 clockdomain control
  3 *
  4 * Copyright (C) 2008-2010 Texas Instruments, Inc.
  5 * Copyright (C) 2008-2010 Nokia Corporation
  6 *
  7 * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
  8 * Rajendra Nayak <rnayak@ti.com>
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License version 2 as
 12 * published by the Free Software Foundation.
 13 */
 14
 15#include <linux/types.h>
 16#include <plat/prcm.h>
 17#include "prm.h"
 18#include "prm2xxx_3xxx.h"
 19#include "cm.h"
 20#include "cm2xxx_3xxx.h"
 21#include "cm-regbits-24xx.h"
 22#include "cm-regbits-34xx.h"
 23#include "prm-regbits-24xx.h"
 24#include "clockdomain.h"
 25
 26static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
 27						struct clockdomain *clkdm2)
 28{
 29	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
 30				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
 31	return 0;
 32}
 33
 34static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
 35						 struct clockdomain *clkdm2)
 36{
 37	omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
 38				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
 39	return 0;
 40}
 41
 42static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
 43						 struct clockdomain *clkdm2)
 44{
 45	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
 46				PM_WKDEP, (1 << clkdm2->dep_bit));
 47}
 48
 49static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 50{
 51	struct clkdm_dep *cd;
 52	u32 mask = 0;
 53
 54	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
 
 
 55		if (!cd->clkdm)
 56			continue; /* only happens if data is erroneous */
 57
 58		/* PRM accesses are slow, so minimize them */
 59		mask |= 1 << cd->clkdm->dep_bit;
 60		atomic_set(&cd->wkdep_usecount, 0);
 61	}
 62
 63	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
 64				 PM_WKDEP);
 65	return 0;
 66}
 67
 68static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
 69						 struct clockdomain *clkdm2)
 70{
 71	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
 72				clkdm1->pwrdm.ptr->prcm_offs,
 73				OMAP3430_CM_SLEEPDEP);
 74	return 0;
 75}
 76
 77static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
 78						 struct clockdomain *clkdm2)
 79{
 80	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
 81				clkdm1->pwrdm.ptr->prcm_offs,
 82				OMAP3430_CM_SLEEPDEP);
 83	return 0;
 84}
 85
 86static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
 87						 struct clockdomain *clkdm2)
 88{
 89	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
 90				OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
 91}
 92
 93static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 94{
 95	struct clkdm_dep *cd;
 96	u32 mask = 0;
 97
 98	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
 
 
 99		if (!cd->clkdm)
100			continue; /* only happens if data is erroneous */
101
102		/* PRM accesses are slow, so minimize them */
103		mask |= 1 << cd->clkdm->dep_bit;
104		atomic_set(&cd->sleepdep_usecount, 0);
105	}
106	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
107				OMAP3430_CM_SLEEPDEP);
108	return 0;
109}
110
111static int omap2_clkdm_sleep(struct clockdomain *clkdm)
112{
113	omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
114				clkdm->pwrdm.ptr->prcm_offs,
115				OMAP2_PM_PWSTCTRL);
116	return 0;
117}
118
119static int omap2_clkdm_wakeup(struct clockdomain *clkdm)
120{
121	omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
122				clkdm->pwrdm.ptr->prcm_offs,
123				OMAP2_PM_PWSTCTRL);
124	return 0;
125}
126
127static void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
128{
129	if (atomic_read(&clkdm->usecount) > 0)
130		_clkdm_add_autodeps(clkdm);
131
132	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
133				clkdm->clktrctrl_mask);
134}
135
136static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
137{
138	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
139				clkdm->clktrctrl_mask);
140
141	if (atomic_read(&clkdm->usecount) > 0)
142		_clkdm_del_autodeps(clkdm);
143}
144
145static void _enable_hwsup(struct clockdomain *clkdm)
146{
147	if (cpu_is_omap24xx())
148		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
149					       clkdm->clktrctrl_mask);
150	else if (cpu_is_omap34xx())
151		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
152					       clkdm->clktrctrl_mask);
153}
154
155static void _disable_hwsup(struct clockdomain *clkdm)
156{
157	if (cpu_is_omap24xx())
158		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
159						clkdm->clktrctrl_mask);
160	else if (cpu_is_omap34xx())
161		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
162						clkdm->clktrctrl_mask);
163}
164
165
166static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
167{
168	bool hwsup = false;
169
170	if (!clkdm->clktrctrl_mask)
171		return 0;
172
173	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
174				clkdm->clktrctrl_mask);
175
176	if (hwsup) {
177		/* Disable HW transitions when we are changing deps */
178		_disable_hwsup(clkdm);
179		_clkdm_add_autodeps(clkdm);
180		_enable_hwsup(clkdm);
181	} else {
182		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
183			omap2_clkdm_wakeup(clkdm);
184	}
185
186	return 0;
187}
188
189static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
190{
191	bool hwsup = false;
192
193	if (!clkdm->clktrctrl_mask)
194		return 0;
195
196	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
197				clkdm->clktrctrl_mask);
198
199	if (hwsup) {
200		/* Disable HW transitions when we are changing deps */
201		_disable_hwsup(clkdm);
202		_clkdm_del_autodeps(clkdm);
203		_enable_hwsup(clkdm);
204	} else {
205		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
206			omap2_clkdm_sleep(clkdm);
207	}
208
209	return 0;
210}
211
212static int omap3_clkdm_sleep(struct clockdomain *clkdm)
213{
214	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
215				clkdm->clktrctrl_mask);
216	return 0;
217}
218
219static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
220{
221	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
222				clkdm->clktrctrl_mask);
223	return 0;
224}
225
226static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
227{
228	if (atomic_read(&clkdm->usecount) > 0)
229		_clkdm_add_autodeps(clkdm);
230
231	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
232				clkdm->clktrctrl_mask);
233}
234
235static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
236{
237	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
238				clkdm->clktrctrl_mask);
239
240	if (atomic_read(&clkdm->usecount) > 0)
241		_clkdm_del_autodeps(clkdm);
242}
243
244struct clkdm_ops omap2_clkdm_operations = {
245	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
246	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
247	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
248	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
249	.clkdm_sleep		= omap2_clkdm_sleep,
250	.clkdm_wakeup		= omap2_clkdm_wakeup,
251	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
252	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
253	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
254	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
255};
256
257struct clkdm_ops omap3_clkdm_operations = {
258	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
259	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
260	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
261	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
262	.clkdm_add_sleepdep	= omap3_clkdm_add_sleepdep,
263	.clkdm_del_sleepdep	= omap3_clkdm_del_sleepdep,
264	.clkdm_read_sleepdep	= omap3_clkdm_read_sleepdep,
265	.clkdm_clear_all_sleepdeps	= omap3_clkdm_clear_all_sleepdeps,
266	.clkdm_sleep		= omap3_clkdm_sleep,
267	.clkdm_wakeup		= omap3_clkdm_wakeup,
268	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
269	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
270	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
271	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
272};
v3.1
  1/*
  2 * OMAP2 and OMAP3 clockdomain control
  3 *
  4 * Copyright (C) 2008-2010 Texas Instruments, Inc.
  5 * Copyright (C) 2008-2010 Nokia Corporation
  6 *
  7 * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
  8 * Rajendra Nayak <rnayak@ti.com>
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License version 2 as
 12 * published by the Free Software Foundation.
 13 */
 14
 15#include <linux/types.h>
 16#include <plat/prcm.h>
 17#include "prm.h"
 18#include "prm2xxx_3xxx.h"
 19#include "cm.h"
 20#include "cm2xxx_3xxx.h"
 21#include "cm-regbits-24xx.h"
 22#include "cm-regbits-34xx.h"
 23#include "prm-regbits-24xx.h"
 24#include "clockdomain.h"
 25
 26static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
 27						struct clockdomain *clkdm2)
 28{
 29	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
 30				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
 31	return 0;
 32}
 33
 34static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
 35						 struct clockdomain *clkdm2)
 36{
 37	omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
 38				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
 39	return 0;
 40}
 41
 42static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
 43						 struct clockdomain *clkdm2)
 44{
 45	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
 46				PM_WKDEP, (1 << clkdm2->dep_bit));
 47}
 48
 49static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 50{
 51	struct clkdm_dep *cd;
 52	u32 mask = 0;
 53
 54	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
 55		if (!omap_chip_is(cd->omap_chip))
 56			continue;
 57		if (!cd->clkdm)
 58			continue; /* only happens if data is erroneous */
 59
 60		/* PRM accesses are slow, so minimize them */
 61		mask |= 1 << cd->clkdm->dep_bit;
 62		atomic_set(&cd->wkdep_usecount, 0);
 63	}
 64
 65	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
 66				 PM_WKDEP);
 67	return 0;
 68}
 69
 70static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
 71						 struct clockdomain *clkdm2)
 72{
 73	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
 74				clkdm1->pwrdm.ptr->prcm_offs,
 75				OMAP3430_CM_SLEEPDEP);
 76	return 0;
 77}
 78
 79static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
 80						 struct clockdomain *clkdm2)
 81{
 82	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
 83				clkdm1->pwrdm.ptr->prcm_offs,
 84				OMAP3430_CM_SLEEPDEP);
 85	return 0;
 86}
 87
 88static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
 89						 struct clockdomain *clkdm2)
 90{
 91	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
 92				OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
 93}
 94
 95static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 96{
 97	struct clkdm_dep *cd;
 98	u32 mask = 0;
 99
100	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
101		if (!omap_chip_is(cd->omap_chip))
102			continue;
103		if (!cd->clkdm)
104			continue; /* only happens if data is erroneous */
105
106		/* PRM accesses are slow, so minimize them */
107		mask |= 1 << cd->clkdm->dep_bit;
108		atomic_set(&cd->sleepdep_usecount, 0);
109	}
110	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
111				OMAP3430_CM_SLEEPDEP);
112	return 0;
113}
114
115static int omap2_clkdm_sleep(struct clockdomain *clkdm)
116{
117	omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
118				clkdm->pwrdm.ptr->prcm_offs,
119				OMAP2_PM_PWSTCTRL);
120	return 0;
121}
122
123static int omap2_clkdm_wakeup(struct clockdomain *clkdm)
124{
125	omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
126				clkdm->pwrdm.ptr->prcm_offs,
127				OMAP2_PM_PWSTCTRL);
128	return 0;
129}
130
131static void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
132{
133	if (atomic_read(&clkdm->usecount) > 0)
134		_clkdm_add_autodeps(clkdm);
135
136	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
137				clkdm->clktrctrl_mask);
138}
139
140static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
141{
142	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
143				clkdm->clktrctrl_mask);
144
145	if (atomic_read(&clkdm->usecount) > 0)
146		_clkdm_del_autodeps(clkdm);
147}
148
149static void _enable_hwsup(struct clockdomain *clkdm)
150{
151	if (cpu_is_omap24xx())
152		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
153					       clkdm->clktrctrl_mask);
154	else if (cpu_is_omap34xx())
155		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
156					       clkdm->clktrctrl_mask);
157}
158
159static void _disable_hwsup(struct clockdomain *clkdm)
160{
161	if (cpu_is_omap24xx())
162		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
163						clkdm->clktrctrl_mask);
164	else if (cpu_is_omap34xx())
165		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
166						clkdm->clktrctrl_mask);
167}
168
169
170static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
171{
172	bool hwsup = false;
173
174	if (!clkdm->clktrctrl_mask)
175		return 0;
176
177	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
178				clkdm->clktrctrl_mask);
179
180	if (hwsup) {
181		/* Disable HW transitions when we are changing deps */
182		_disable_hwsup(clkdm);
183		_clkdm_add_autodeps(clkdm);
184		_enable_hwsup(clkdm);
185	} else {
186		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
187			omap2_clkdm_wakeup(clkdm);
188	}
189
190	return 0;
191}
192
193static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
194{
195	bool hwsup = false;
196
197	if (!clkdm->clktrctrl_mask)
198		return 0;
199
200	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
201				clkdm->clktrctrl_mask);
202
203	if (hwsup) {
204		/* Disable HW transitions when we are changing deps */
205		_disable_hwsup(clkdm);
206		_clkdm_del_autodeps(clkdm);
207		_enable_hwsup(clkdm);
208	} else {
209		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
210			omap2_clkdm_sleep(clkdm);
211	}
212
213	return 0;
214}
215
216static int omap3_clkdm_sleep(struct clockdomain *clkdm)
217{
218	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
219				clkdm->clktrctrl_mask);
220	return 0;
221}
222
223static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
224{
225	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
226				clkdm->clktrctrl_mask);
227	return 0;
228}
229
230static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
231{
232	if (atomic_read(&clkdm->usecount) > 0)
233		_clkdm_add_autodeps(clkdm);
234
235	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
236				clkdm->clktrctrl_mask);
237}
238
239static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
240{
241	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
242				clkdm->clktrctrl_mask);
243
244	if (atomic_read(&clkdm->usecount) > 0)
245		_clkdm_del_autodeps(clkdm);
246}
247
248struct clkdm_ops omap2_clkdm_operations = {
249	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
250	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
251	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
252	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
253	.clkdm_sleep		= omap2_clkdm_sleep,
254	.clkdm_wakeup		= omap2_clkdm_wakeup,
255	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
256	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
257	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
258	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
259};
260
261struct clkdm_ops omap3_clkdm_operations = {
262	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
263	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
264	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
265	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
266	.clkdm_add_sleepdep	= omap3_clkdm_add_sleepdep,
267	.clkdm_del_sleepdep	= omap3_clkdm_del_sleepdep,
268	.clkdm_read_sleepdep	= omap3_clkdm_read_sleepdep,
269	.clkdm_clear_all_sleepdeps	= omap3_clkdm_clear_all_sleepdeps,
270	.clkdm_sleep		= omap3_clkdm_sleep,
271	.clkdm_wakeup		= omap3_clkdm_wakeup,
272	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
273	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
274	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
275	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
276};