OMAP: DSS2: fix irq-stats compilation
[linux/fpc-iii.git] / arch / sh / kernel / cpu / hwblk.c
blobc0ad7d46e7848687b5103ad826bb1a92b1a284de
1 #include <linux/clk.h>
2 #include <linux/compiler.h>
3 #include <linux/slab.h>
4 #include <linux/io.h>
5 #include <linux/spinlock.h>
6 #include <asm/suspend.h>
7 #include <asm/hwblk.h>
8 #include <asm/clock.h>
10 static DEFINE_SPINLOCK(hwblk_lock);
12 static void hwblk_area_mod_cnt(struct hwblk_info *info,
13 int area, int counter, int value, int goal)
15 struct hwblk_area *hap = info->areas + area;
17 hap->cnt[counter] += value;
19 if (hap->cnt[counter] != goal)
20 return;
22 if (hap->flags & HWBLK_AREA_FLAG_PARENT)
23 hwblk_area_mod_cnt(info, hap->parent, counter, value, goal);
27 static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
28 int counter, int value, int goal)
30 struct hwblk *hp = info->hwblks + hwblk;
32 hp->cnt[counter] += value;
33 if (hp->cnt[counter] == goal)
34 hwblk_area_mod_cnt(info, hp->area, counter, value, goal);
36 return hp->cnt[counter];
39 static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
40 int counter, int value, int goal)
42 unsigned long flags;
44 spin_lock_irqsave(&hwblk_lock, flags);
45 __hwblk_mod_cnt(info, hwblk, counter, value, goal);
46 spin_unlock_irqrestore(&hwblk_lock, flags);
49 void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter)
51 hwblk_mod_cnt(info, hwblk, counter, 1, 1);
54 void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter)
56 hwblk_mod_cnt(info, hwblk, counter, -1, 0);
59 void hwblk_enable(struct hwblk_info *info, int hwblk)
61 struct hwblk *hp = info->hwblks + hwblk;
62 unsigned long tmp;
63 unsigned long flags;
64 int ret;
66 spin_lock_irqsave(&hwblk_lock, flags);
68 ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1);
69 if (ret == 1) {
70 tmp = __raw_readl(hp->mstp);
71 tmp &= ~(1 << hp->bit);
72 __raw_writel(tmp, hp->mstp);
75 spin_unlock_irqrestore(&hwblk_lock, flags);
78 void hwblk_disable(struct hwblk_info *info, int hwblk)
80 struct hwblk *hp = info->hwblks + hwblk;
81 unsigned long tmp;
82 unsigned long flags;
83 int ret;
85 spin_lock_irqsave(&hwblk_lock, flags);
87 ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0);
88 if (ret == 0) {
89 tmp = __raw_readl(hp->mstp);
90 tmp |= 1 << hp->bit;
91 __raw_writel(tmp, hp->mstp);
94 spin_unlock_irqrestore(&hwblk_lock, flags);
97 struct hwblk_info *hwblk_info;
99 int __init hwblk_register(struct hwblk_info *info)
101 hwblk_info = info;
102 return 0;
105 int __init __weak arch_hwblk_init(void)
107 return 0;
110 int __weak arch_hwblk_sleep_mode(void)
112 return SUSP_SH_SLEEP;
115 int __init hwblk_init(void)
117 return arch_hwblk_init();
120 /* allow clocks to enable and disable hardware blocks */
121 static int sh_hwblk_clk_enable(struct clk *clk)
123 if (!hwblk_info)
124 return -ENOENT;
126 hwblk_enable(hwblk_info, clk->arch_flags);
127 return 0;
130 static void sh_hwblk_clk_disable(struct clk *clk)
132 if (hwblk_info)
133 hwblk_disable(hwblk_info, clk->arch_flags);
136 static struct clk_ops sh_hwblk_clk_ops = {
137 .enable = sh_hwblk_clk_enable,
138 .disable = sh_hwblk_clk_disable,
139 .recalc = followparent_recalc,
142 int __init sh_hwblk_clk_register(struct clk *clks, int nr)
144 struct clk *clkp;
145 int ret = 0;
146 int k;
148 for (k = 0; !ret && (k < nr); k++) {
149 clkp = clks + k;
150 clkp->ops = &sh_hwblk_clk_ops;
151 ret |= clk_register(clkp);
154 return ret;