2 #include <linux/compiler.h>
3 #include <linux/slab.h>
5 #include <linux/spinlock.h>
6 #include <asm/suspend.h>
10 static DEFINE_SPINLOCK(hwblk_lock);
12 static void hwblk_area_inc(struct hwblk_info *info, int area)
14 struct hwblk_area *hap = info->areas + area;
18 if (hap->flags & HWBLK_AREA_FLAG_PARENT)
19 hwblk_area_inc(info, hap->parent);
22 static void hwblk_area_dec(struct hwblk_info *info, int area)
24 struct hwblk_area *hap = info->areas + area;
27 if (hap->flags & HWBLK_AREA_FLAG_PARENT)
28 hwblk_area_dec(info, hap->parent);
32 static void hwblk_enable(struct hwblk_info *info, int hwblk)
34 struct hwblk *hp = info->hwblks + hwblk;
38 spin_lock_irqsave(&hwblk_lock, flags);
42 hwblk_area_inc(info, hp->area);
44 tmp = __raw_readl(hp->mstp);
45 tmp &= ~(1 << hp->bit);
46 __raw_writel(tmp, hp->mstp);
49 spin_unlock_irqrestore(&hwblk_lock, flags);
52 static void hwblk_disable(struct hwblk_info *info, int hwblk)
54 struct hwblk *hp = info->hwblks + hwblk;
58 spin_lock_irqsave(&hwblk_lock, flags);
61 hwblk_area_dec(info, hp->area);
63 tmp = __raw_readl(hp->mstp);
65 __raw_writel(tmp, hp->mstp);
69 spin_unlock_irqrestore(&hwblk_lock, flags);
72 static struct hwblk_info *hwblk_info;
74 int __init hwblk_register(struct hwblk_info *info)
80 int __init __weak arch_hwblk_init(void)
85 int __weak arch_hwblk_sleep_mode(void)
90 int __init hwblk_init(void)
92 return arch_hwblk_init();
95 /* allow clocks to enable and disable hardware blocks */
96 static int sh_hwblk_clk_enable(struct clk *clk)
101 hwblk_enable(hwblk_info, clk->arch_flags);
105 static void sh_hwblk_clk_disable(struct clk *clk)
108 hwblk_disable(hwblk_info, clk->arch_flags);
111 static struct clk_ops sh_hwblk_clk_ops = {
112 .enable = sh_hwblk_clk_enable,
113 .disable = sh_hwblk_clk_disable,
114 .recalc = followparent_recalc,
117 int __init sh_hwblk_clk_register(struct clk *clks, int nr)
123 for (k = 0; !ret && (k < nr); k++) {
125 clkp->ops = &sh_hwblk_clk_ops;
126 ret |= clk_register(clkp);