blob: 5978ce426ec54dd869d29422224caee2e88ae2bb [file] [log] [blame]
Paul Walmsley71348bc2009-09-03 20:14:02 +03001/*
2 * OMAP2/3 CM module functions
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Paul Walmsley
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
Paul Walmsley71348bc2009-09-03 20:14:02 +030013#include <linux/types.h>
14#include <linux/delay.h>
15#include <linux/spinlock.h>
16#include <linux/list.h>
17#include <linux/errno.h>
18#include <linux/err.h>
19#include <linux/io.h>
20
Paul Walmsley6f8b7ff2009-12-08 16:33:16 -070021#include <plat/common.h>
22
Paul Walmsley71348bc2009-09-03 20:14:02 +030023#include "cm.h"
Paul Walmsley59fb6592010-12-21 15:30:55 -070024#include "cm2xxx_3xxx.h"
Paul Walmsley71348bc2009-09-03 20:14:02 +030025#include "cm-regbits-24xx.h"
26#include "cm-regbits-34xx.h"
27
Paul Walmsley71348bc2009-09-03 20:14:02 +030028static const u8 cm_idlest_offs[] = {
29 CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
30};
31
Paul Walmsley59fb6592010-12-21 15:30:55 -070032
33u32 cm_read_mod_reg(s16 module, u16 idx)
34{
35 return __raw_readl(cm_base + module + idx);
36}
37
38void cm_write_mod_reg(u32 val, s16 module, u16 idx)
39{
40 __raw_writel(val, cm_base + module + idx);
41}
42
43/* Read-modify-write a register in a CM module. Caller must lock */
44u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
45{
46 u32 v;
47
48 v = cm_read_mod_reg(module, idx);
49 v &= ~mask;
50 v |= bits;
51 cm_write_mod_reg(v, module, idx);
52
53 return v;
54}
55
56u32 cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
57{
58 return cm_rmw_mod_reg_bits(bits, bits, module, idx);
59}
60
61u32 cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
62{
63 return cm_rmw_mod_reg_bits(bits, 0x0, module, idx);
64}
65
Paul Walmsley71348bc2009-09-03 20:14:02 +030066/**
67 * omap2_cm_wait_idlest_ready - wait for a module to leave idle or standby
68 * @prcm_mod: PRCM module offset
69 * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
70 * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
71 *
72 * XXX document
73 */
74int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
75{
76 int ena = 0, i = 0;
77 u8 cm_idlest_reg;
78 u32 mask;
79
80 if (!idlest_id || (idlest_id > ARRAY_SIZE(cm_idlest_offs)))
81 return -EINVAL;
82
83 cm_idlest_reg = cm_idlest_offs[idlest_id - 1];
84
Kevin Hilman64056162010-07-26 16:34:28 -060085 mask = 1 << idlest_shift;
86
Paul Walmsley71348bc2009-09-03 20:14:02 +030087 if (cpu_is_omap24xx())
Kevin Hilman64056162010-07-26 16:34:28 -060088 ena = mask;
Paul Walmsley71348bc2009-09-03 20:14:02 +030089 else if (cpu_is_omap34xx())
90 ena = 0;
91 else
92 BUG();
93
Paul Walmsley6f8b7ff2009-12-08 16:33:16 -070094 omap_test_timeout(((cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena),
95 MAX_MODULE_READY_TIME, i);
Paul Walmsley71348bc2009-09-03 20:14:02 +030096
97 return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
98}
99