aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c38
-rw-r--r--arch/sh/include/asm/hwblk.h61
-rw-r--r--arch/sh/include/asm/suspend.h9
-rw-r--r--arch/sh/include/cpu-sh4/cpu/sh7722.h14
-rw-r--r--arch/sh/kernel/cpu/Makefile2
-rw-r--r--arch/sh/kernel/cpu/hwblk.c130
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile2
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7722.c60
-rw-r--r--arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c106
-rw-r--r--arch/sh/kernel/cpu/shmobile/Makefile1
-rw-r--r--arch/sh/kernel/cpu/shmobile/cpuidle.c102
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm.c26
-rw-r--r--arch/sh/kernel/time.c2
13 files changed, 510 insertions, 43 deletions
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index c050a8d76dfd..8fed45a2fb85 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -19,6 +19,7 @@
19#include <linux/smc91x.h> 19#include <linux/smc91x.h>
20#include <linux/gpio.h> 20#include <linux/gpio.h>
21#include <linux/input.h> 21#include <linux/input.h>
22#include <linux/usb/r8a66597.h>
22#include <video/sh_mobile_lcdc.h> 23#include <video/sh_mobile_lcdc.h>
23#include <media/sh_mobile_ceu.h> 24#include <media/sh_mobile_ceu.h>
24#include <asm/io.h> 25#include <asm/io.h>
@@ -302,6 +303,34 @@ static struct platform_device sh_eth_device = {
302 .resource = sh_eth_resources, 303 .resource = sh_eth_resources,
303}; 304};
304 305
306static struct r8a66597_platdata sh7724_usb0_host_data = {
307};
308
309static struct resource sh7724_usb0_host_resources[] = {
310 [0] = {
311 .start = 0xa4d80000,
312 .end = 0xa4d800ff,
313 .flags = IORESOURCE_MEM,
314 },
315 [1] = {
316 .start = 65,
317 .end = 65,
318 .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
319 },
320};
321
322static struct platform_device sh7724_usb0_host_device = {
323 .name = "r8a66597_hcd",
324 .id = 0,
325 .dev = {
326 .dma_mask = NULL, /* not use dma */
327 .coherent_dma_mask = 0xffffffff,
328 .platform_data = &sh7724_usb0_host_data,
329 },
330 .num_resources = ARRAY_SIZE(sh7724_usb0_host_resources),
331 .resource = sh7724_usb0_host_resources,
332};
333
305static struct platform_device *ms7724se_devices[] __initdata = { 334static struct platform_device *ms7724se_devices[] __initdata = {
306 &heartbeat_device, 335 &heartbeat_device,
307 &smc91x_eth_device, 336 &smc91x_eth_device,
@@ -311,6 +340,7 @@ static struct platform_device *ms7724se_devices[] __initdata = {
311 &ceu1_device, 340 &ceu1_device,
312 &keysc_device, 341 &keysc_device,
313 &sh_eth_device, 342 &sh_eth_device,
343 &sh7724_usb0_host_device,
314}; 344};
315 345
316#define EEPROM_OP 0xBA206000 346#define EEPROM_OP 0xBA206000
@@ -364,6 +394,7 @@ static void __init sh_eth_init(void)
364#define SW4140 0xBA201000 394#define SW4140 0xBA201000
365#define FPGA_OUT 0xBA200400 395#define FPGA_OUT 0xBA200400
366#define PORT_HIZA 0xA4050158 396#define PORT_HIZA 0xA4050158
397#define PORT_MSELCRB 0xA4050182
367 398
368#define SW41_A 0x0100 399#define SW41_A 0x0100
369#define SW41_B 0x0200 400#define SW41_B 0x0200
@@ -373,6 +404,7 @@ static void __init sh_eth_init(void)
373#define SW41_F 0x2000 404#define SW41_F 0x2000
374#define SW41_G 0x4000 405#define SW41_G 0x4000
375#define SW41_H 0x8000 406#define SW41_H 0x8000
407
376static int __init devices_setup(void) 408static int __init devices_setup(void)
377{ 409{
378 u16 sw = ctrl_inw(SW4140); /* select camera, monitor */ 410 u16 sw = ctrl_inw(SW4140); /* select camera, monitor */
@@ -385,6 +417,12 @@ static int __init devices_setup(void)
385 (1 << 14)), /* RMII */ 417 (1 << 14)), /* RMII */
386 FPGA_OUT); 418 FPGA_OUT);
387 419
420 /* turn on USB clocks, use external clock */
421 ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
422
423 /* enable USB0 port */
424 ctrl_outw(0x0600, 0xa40501d4);
425
388 /* enable IRQ 0,1,2 */ 426 /* enable IRQ 0,1,2 */
389 gpio_request(GPIO_FN_INTC_IRQ0, NULL); 427 gpio_request(GPIO_FN_INTC_IRQ0, NULL);
390 gpio_request(GPIO_FN_INTC_IRQ1, NULL); 428 gpio_request(GPIO_FN_INTC_IRQ1, NULL);
diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h
new file mode 100644
index 000000000000..51a46f496639
--- /dev/null
+++ b/arch/sh/include/asm/hwblk.h
@@ -0,0 +1,61 @@
1#ifndef __ASM_SH_HWBLK_H
2#define __ASM_SH_HWBLK_H
3
4#include <asm/clock.h>
5#include <asm/io.h>
6
7#define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */
8
9#define HWBLK_AREA(_flags, _parent) \
10{ \
11 .flags = _flags, \
12 .parent = _parent, \
13}
14
15struct hwblk_area {
16 unsigned long cnt;
17 unsigned char parent;
18 unsigned char flags;
19};
20
21#define HWBLK(_mstp, _bit, _area) \
22{ \
23 .mstp = (void __iomem *)_mstp, \
24 .bit = _bit, \
25 .area = _area, \
26}
27
28struct hwblk {
29 void __iomem *mstp;
30 unsigned char bit;
31 unsigned char area;
32 unsigned long cnt;
33};
34
35struct hwblk_info {
36 struct hwblk_area *areas;
37 int nr_areas;
38 struct hwblk *hwblks;
39 int nr_hwblks;
40};
41
42/* Should be defined by processor-specific code */
43int arch_hwblk_init(void);
44int arch_hwblk_sleep_mode(void);
45
46int hwblk_register(struct hwblk_info *info);
47int hwblk_init(void);
48
49/* allow clocks to enable and disable hardware blocks */
50#define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \
51{ \
52 .name = _name, \
53 .id = _id, \
54 .parent = _parent, \
55 .arch_flags = _hwblk, \
56 .flags = _flags, \
57}
58
59int sh_hwblk_clk_register(struct clk *clks, int nr);
60
61#endif /* __ASM_SH_HWBLK_H */
diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h
index b1b995370e79..5c8ea28ff7a4 100644
--- a/arch/sh/include/asm/suspend.h
+++ b/arch/sh/include/asm/suspend.h
@@ -10,6 +10,15 @@ struct swsusp_arch_regs {
10 struct pt_regs user_regs; 10 struct pt_regs user_regs;
11 unsigned long bank1_regs[8]; 11 unsigned long bank1_regs[8];
12}; 12};
13
14void sh_mobile_call_standby(unsigned long mode);
15
16#ifdef CONFIG_CPU_IDLE
17void sh_mobile_setup_cpuidle(void);
18#else
19static inline void sh_mobile_setup_cpuidle(void) {}
20#endif
21
13#endif 22#endif
14 23
15/* flags passed to assembly suspend code */ 24/* flags passed to assembly suspend code */
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7722.h b/arch/sh/include/cpu-sh4/cpu/sh7722.h
index 738ea43c5038..48560407cbe1 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7722.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7722.h
@@ -221,4 +221,18 @@ enum {
221 GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5, 221 GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5,
222}; 222};
223 223
224enum {
225 HWBLK_UNKNOWN = 0,
226 HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_URAM, HWBLK_XYMEM,
227 HWBLK_INTC, HWBLK_DMAC, HWBLK_SHYWAY, HWBLK_HUDI,
228 HWBLK_UBC, HWBLK_TMU, HWBLK_CMT, HWBLK_RWDT, HWBLK_FLCTL,
229 HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SIO,
230 HWBLK_SIOF0, HWBLK_SIOF1, HWBLK_IIC, HWBLK_RTC,
231 HWBLK_TPU, HWBLK_IRDA, HWBLK_SDHI, HWBLK_SIM, HWBLK_KEYSC,
232 HWBLK_TSIF, HWBLK_USBF, HWBLK_2DG, HWBLK_SIU, HWBLK_VOU,
233 HWBLK_JPU, HWBLK_BEU, HWBLK_CEU, HWBLK_VEU, HWBLK_VPU,
234 HWBLK_LCDC,
235 HWBLK_NR,
236};
237
224#endif /* __ASM_SH7722_H__ */ 238#endif /* __ASM_SH7722_H__ */
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index eecad7cbd61e..3d6b9312dc47 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -19,4 +19,4 @@ obj-$(CONFIG_UBC_WAKEUP) += ubc.o
19obj-$(CONFIG_SH_ADC) += adc.o 19obj-$(CONFIG_SH_ADC) += adc.o
20obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o 20obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o
21 21
22obj-y += irq/ init.o clock.o 22obj-y += irq/ init.o clock.o hwblk.o
diff --git a/arch/sh/kernel/cpu/hwblk.c b/arch/sh/kernel/cpu/hwblk.c
new file mode 100644
index 000000000000..7c3a73deff24
--- /dev/null
+++ b/arch/sh/kernel/cpu/hwblk.c
@@ -0,0 +1,130 @@
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>
9
10static DEFINE_SPINLOCK(hwblk_lock);
11
12static void hwblk_area_inc(struct hwblk_info *info, int area)
13{
14 struct hwblk_area *hap = info->areas + area;
15
16 hap->cnt++;
17 if (hap->cnt == 1)
18 if (hap->flags & HWBLK_AREA_FLAG_PARENT)
19 hwblk_area_inc(info, hap->parent);
20}
21
22static void hwblk_area_dec(struct hwblk_info *info, int area)
23{
24 struct hwblk_area *hap = info->areas + area;
25
26 if (hap->cnt == 1)
27 if (hap->flags & HWBLK_AREA_FLAG_PARENT)
28 hwblk_area_dec(info, hap->parent);
29 hap->cnt--;
30}
31
32static void hwblk_enable(struct hwblk_info *info, int hwblk)
33{
34 struct hwblk *hp = info->hwblks + hwblk;
35 unsigned long tmp;
36 unsigned long flags;
37
38 spin_lock_irqsave(&hwblk_lock, flags);
39
40 hp->cnt++;
41 if (hp->cnt == 1) {
42 hwblk_area_inc(info, hp->area);
43
44 tmp = __raw_readl(hp->mstp);
45 tmp &= ~(1 << hp->bit);
46 __raw_writel(tmp, hp->mstp);
47 }
48
49 spin_unlock_irqrestore(&hwblk_lock, flags);
50}
51
52static void hwblk_disable(struct hwblk_info *info, int hwblk)
53{
54 struct hwblk *hp = info->hwblks + hwblk;
55 unsigned long tmp;
56 unsigned long flags;
57
58 spin_lock_irqsave(&hwblk_lock, flags);
59
60 if (hp->cnt == 1) {
61 hwblk_area_dec(info, hp->area);
62
63 tmp = __raw_readl(hp->mstp);
64 tmp |= 1 << hp->bit;
65 __raw_writel(tmp, hp->mstp);
66 }
67 hp->cnt--;
68
69 spin_unlock_irqrestore(&hwblk_lock, flags);
70}
71
72static struct hwblk_info *hwblk_info;
73
74int __init hwblk_register(struct hwblk_info *info)
75{
76 hwblk_info = info;
77 return 0;
78}
79
80int __init __weak arch_hwblk_init(void)
81{
82 return 0;
83}
84
85int __weak arch_hwblk_sleep_mode(void)
86{
87 return SUSP_SH_SLEEP;
88}
89
90int __init hwblk_init(void)
91{
92 return arch_hwblk_init();
93}
94
95/* allow clocks to enable and disable hardware blocks */
96static int sh_hwblk_clk_enable(struct clk *clk)
97{
98 if (!hwblk_info)
99 return -ENOENT;
100
101 hwblk_enable(hwblk_info, clk->arch_flags);
102 return 0;
103}
104
105static void sh_hwblk_clk_disable(struct clk *clk)
106{
107 if (hwblk_info)
108 hwblk_disable(hwblk_info, clk->arch_flags);
109}
110
111static struct clk_ops sh_hwblk_clk_ops = {
112 .enable = sh_hwblk_clk_enable,
113 .disable = sh_hwblk_clk_disable,
114 .recalc = followparent_recalc,
115};
116
117int __init sh_hwblk_clk_register(struct clk *clks, int nr)
118{
119 struct clk *clkp;
120 int ret = 0;
121 int k;
122
123 for (k = 0; !ret && (k < nr); k++) {
124 clkp = clks + k;
125 clkp->ops = &sh_hwblk_clk_ops;
126 ret |= clk_register(clkp);
127 }
128
129 return ret;
130}
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index ebdd391d5f42..3cafda696378 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -25,7 +25,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
25clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o 25clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
26clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o 26clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
27clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o 27clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
28clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o 28clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o hwblk-sh7722.o
29clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o 29clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o
30clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o 30clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o
31clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o 31clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index 40f859354f79..1fa9e1dd1cc8 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -22,6 +22,8 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/io.h> 23#include <linux/io.h>
24#include <asm/clock.h> 24#include <asm/clock.h>
25#include <asm/hwblk.h>
26#include <cpu/sh7722.h>
25 27
26/* SH7722 registers */ 28/* SH7722 registers */
27#define FRQCR 0xa4150000 29#define FRQCR 0xa4150000
@@ -140,35 +142,37 @@ struct clk div6_clks[] = {
140 SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), 142 SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
141}; 143};
142 144
143#define MSTP(_str, _parent, _reg, _bit, _flags) \ 145#define R_CLK &r_clk
144 SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags) 146#define P_CLK &div4_clks[DIV4_P]
147#define B_CLK &div4_clks[DIV4_B]
148#define U_CLK &div4_clks[DIV4_U]
145 149
146static struct clk mstp_clks[] = { 150static struct clk mstp_clks[] = {
147 MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), 151 SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT),
148 MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), 152 SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT),
149 MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0), 153 SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0),
150 MSTP("cmt0", &r_clk, MSTPCR0, 14, 0), 154 SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
151 MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), 155 SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
152 MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), 156 SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
153 MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0), 157 SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
154 MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0), 158 SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
155 MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0), 159 SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
156 160
157 MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), 161 SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
158 MSTP("rtc0", &r_clk, MSTPCR1, 8, 0), 162 SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
159 163
160 MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), 164 SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0),
161 MSTP("keysc0", &r_clk, MSTPCR2, 14, 0), 165 SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
162 MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), 166 SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0),
163 MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0), 167 SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
164 MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0), 168 SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
165 MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), 169 SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
166 MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT), 170 SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT),
167 MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), 171 SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
168 MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), 172 SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
169 MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), 173 SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, CLK_ENABLE_ON_INIT),
170 MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), 174 SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
171 MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), 175 SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0),
172}; 176};
173 177
174int __init arch_clk_init(void) 178int __init arch_clk_init(void)
@@ -191,7 +195,7 @@ int __init arch_clk_init(void)
191 ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); 195 ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
192 196
193 if (!ret) 197 if (!ret)
194 ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); 198 ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
195 199
196 return ret; 200 return ret;
197} 201}
diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
new file mode 100644
index 000000000000..00a1c02d82b1
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
@@ -0,0 +1,106 @@
1/*
2 * arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c
3 *
4 * SH7722 hardware block support
5 *
6 * Copyright (C) 2009 Magnus Damm
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/io.h>
24#include <asm/suspend.h>
25#include <asm/hwblk.h>
26#include <cpu/sh7722.h>
27
28/* SH7722 registers */
29#define MSTPCR0 0xa4150030
30#define MSTPCR1 0xa4150034
31#define MSTPCR2 0xa4150038
32
33/* SH7722 Power Domains */
34enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
35static struct hwblk_area sh7722_hwblk_area[] = {
36 [CORE_AREA] = HWBLK_AREA(0, 0),
37 [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
38 [SUB_AREA] = HWBLK_AREA(0, 0),
39};
40
41/* Table mapping HWBLK to Module Stop Bit and Power Domain */
42static struct hwblk sh7722_hwblk[HWBLK_NR] = {
43 [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
44 [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
45 [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
46 [HWBLK_URAM] = HWBLK(MSTPCR0, 28, CORE_AREA),
47 [HWBLK_XYMEM] = HWBLK(MSTPCR0, 26, CORE_AREA),
48 [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
49 [HWBLK_DMAC] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
50 [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
51 [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
52 [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
53 [HWBLK_TMU] = HWBLK(MSTPCR0, 15, CORE_AREA),
54 [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
55 [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
56 [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
57 [HWBLK_SCIF0] = HWBLK(MSTPCR0, 7, CORE_AREA),
58 [HWBLK_SCIF1] = HWBLK(MSTPCR0, 6, CORE_AREA),
59 [HWBLK_SCIF2] = HWBLK(MSTPCR0, 5, CORE_AREA),
60 [HWBLK_SIO] = HWBLK(MSTPCR0, 3, CORE_AREA),
61 [HWBLK_SIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
62 [HWBLK_SIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
63
64 [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
65 [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
66
67 [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
68 [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
69 [HWBLK_SDHI] = HWBLK(MSTPCR2, 18, CORE_AREA),
70 [HWBLK_SIM] = HWBLK(MSTPCR2, 16, CORE_AREA),
71 [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
72 [HWBLK_TSIF] = HWBLK(MSTPCR2, 13, SUB_AREA),
73 [HWBLK_USBF] = HWBLK(MSTPCR2, 11, CORE_AREA),
74 [HWBLK_2DG] = HWBLK(MSTPCR2, 9, CORE_AREA_BM),
75 [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
76 [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
77 [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
78 [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
79 [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
80 [HWBLK_VEU] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
81 [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
82 [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
83};
84
85static struct hwblk_info sh7722_hwblk_info = {
86 .areas = sh7722_hwblk_area,
87 .nr_areas = ARRAY_SIZE(sh7722_hwblk_area),
88 .hwblks = sh7722_hwblk,
89 .nr_hwblks = ARRAY_SIZE(sh7722_hwblk),
90};
91
92int arch_hwblk_sleep_mode(void)
93{
94 if (!sh7722_hwblk_area[CORE_AREA].cnt)
95 return SUSP_SH_STANDBY | SUSP_SH_SF;
96
97 if (!sh7722_hwblk_area[CORE_AREA_BM].cnt)
98 return SUSP_SH_SLEEP | SUSP_SH_SF;
99
100 return SUSP_SH_SLEEP;
101}
102
103int __init arch_hwblk_init(void)
104{
105 return hwblk_register(&sh7722_hwblk_info);
106}
diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile
index 08bfa7c7db29..e8a5111e848a 100644
--- a/arch/sh/kernel/cpu/shmobile/Makefile
+++ b/arch/sh/kernel/cpu/shmobile/Makefile
@@ -4,3 +4,4 @@
4 4
5# Power Management & Sleep mode 5# Power Management & Sleep mode
6obj-$(CONFIG_PM) += pm.o sleep.o 6obj-$(CONFIG_PM) += pm.o sleep.o
7obj-$(CONFIG_CPU_IDLE) += cpuidle.o
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
new file mode 100644
index 000000000000..4afdd975cc66
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -0,0 +1,102 @@
1/*
2 * arch/sh/kernel/cpu/shmobile/cpuidle.c
3 *
4 * Cpuidle support code for SuperH Mobile
5 *
6 * Copyright (C) 2009 Magnus Damm
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/io.h>
15#include <linux/suspend.h>
16#include <linux/cpuidle.h>
17#include <asm/suspend.h>
18#include <asm/uaccess.h>
19#include <asm/hwblk.h>
20
21static unsigned long cpuidle_mode[] = {
22 SUSP_SH_SLEEP, /* regular sleep mode */
23 SUSP_SH_SLEEP | SUSP_SH_SF, /* sleep mode + self refresh */
24};
25
26static int cpuidle_sleep_enter(struct cpuidle_device *dev,
27 struct cpuidle_state *state)
28{
29 unsigned long allowed_mode = arch_hwblk_sleep_mode();
30 ktime_t before, after;
31 int requested_state = state - &dev->states[0];
32 int allowed_state;
33 int k;
34
35 /* convert allowed mode to allowed state */
36 for (k = ARRAY_SIZE(cpuidle_mode) - 1; k > 0; k--)
37 if (cpuidle_mode[k] == allowed_mode)
38 break;
39
40 allowed_state = k;
41
42 /* take the following into account for sleep mode selection:
43 * - allowed_state: best mode allowed by hardware (clock deps)
44 * - requested_state: best mode allowed by software (latencies)
45 */
46 k = min_t(int, allowed_state, requested_state);
47
48 dev->last_state = &dev->states[k];
49 before = ktime_get();
50 sh_mobile_call_standby(cpuidle_mode[k]);
51 after = ktime_get();
52 return ktime_to_ns(ktime_sub(after, before)) >> 10;
53}
54
55static struct cpuidle_device cpuidle_dev;
56static struct cpuidle_driver cpuidle_driver = {
57 .name = "sh_idle",
58 .owner = THIS_MODULE,
59};
60
61void sh_mobile_setup_cpuidle(void)
62{
63 struct cpuidle_device *dev = &cpuidle_dev;
64 struct cpuidle_state *state;
65 int i;
66
67 cpuidle_register_driver(&cpuidle_driver);
68
69 for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
70 dev->states[i].name[0] = '\0';
71 dev->states[i].desc[0] = '\0';
72 }
73
74 i = CPUIDLE_DRIVER_STATE_START;
75
76 state = &dev->states[i++];
77 snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
78 strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
79 state->exit_latency = 1;
80 state->target_residency = 1 * 2;
81 state->power_usage = 3;
82 state->flags = 0;
83 state->flags |= CPUIDLE_FLAG_SHALLOW;
84 state->flags |= CPUIDLE_FLAG_TIME_VALID;
85 state->enter = cpuidle_sleep_enter;
86
87 dev->safe_state = state;
88
89 state = &dev->states[i++];
90 snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
91 strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN);
92 state->exit_latency = 100;
93 state->target_residency = 1 * 2;
94 state->power_usage = 1;
95 state->flags = 0;
96 state->flags |= CPUIDLE_FLAG_TIME_VALID;
97 state->enter = cpuidle_sleep_enter;
98
99 dev->state_count = i;
100
101 cpuidle_register_device(dev);
102}
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index 8c067adf6830..de078d24ce56 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c 2 * arch/sh/kernel/cpu/shmobile/pm.c
3 * 3 *
4 * Power management support code for SuperH Mobile 4 * Power management support code for SuperH Mobile
5 * 5 *
@@ -32,20 +32,17 @@
32 * 32 *
33 * R-standby mode is unsupported, but will be added in the future 33 * R-standby mode is unsupported, but will be added in the future
34 * U-standby mode is low priority since it needs bootloader hacks 34 * U-standby mode is low priority since it needs bootloader hacks
35 *
36 * All modes should be tied in with cpuidle. But before that can
37 * happen we need to keep track of enabled hardware blocks so we
38 * can avoid entering sleep modes that stop clocks to hardware
39 * blocks that are in use even though the cpu core is idle.
40 */ 35 */
41 36
37#define ILRAM_BASE 0xe5200000
38
42extern const unsigned char sh_mobile_standby[]; 39extern const unsigned char sh_mobile_standby[];
43extern const unsigned int sh_mobile_standby_size; 40extern const unsigned int sh_mobile_standby_size;
44 41
45static void sh_mobile_call_standby(unsigned long mode) 42void sh_mobile_call_standby(unsigned long mode)
46{ 43{
47 extern void *vbr_base; 44 extern void *vbr_base;
48 void *onchip_mem = (void *)0xe5200000; /* ILRAM */ 45 void *onchip_mem = (void *)ILRAM_BASE;
49 void (*standby_onchip_mem)(unsigned long) = onchip_mem; 46 void (*standby_onchip_mem)(unsigned long) = onchip_mem;
50 47
51 /* Note: Wake up from sleep may generate exceptions! 48 /* Note: Wake up from sleep may generate exceptions!
@@ -55,11 +52,6 @@ static void sh_mobile_call_standby(unsigned long mode)
55 if (mode & SUSP_SH_SF) 52 if (mode & SUSP_SH_SF)
56 asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory"); 53 asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory");
57 54
58 /* Copy the assembly snippet to the otherwise ununsed ILRAM */
59 memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
60 wmb();
61 ctrl_barrier();
62
63 /* Let assembly snippet in on-chip memory handle the rest */ 55 /* Let assembly snippet in on-chip memory handle the rest */
64 standby_onchip_mem(mode); 56 standby_onchip_mem(mode);
65 57
@@ -85,7 +77,15 @@ static struct platform_suspend_ops sh_pm_ops = {
85 77
86static int __init sh_pm_init(void) 78static int __init sh_pm_init(void)
87{ 79{
80 void *onchip_mem = (void *)ILRAM_BASE;
81
82 /* Copy the assembly snippet to the otherwise ununsed ILRAM */
83 memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
84 wmb();
85 ctrl_barrier();
86
88 suspend_set_ops(&sh_pm_ops); 87 suspend_set_ops(&sh_pm_ops);
88 sh_mobile_setup_cpuidle();
89 return 0; 89 return 0;
90} 90}
91 91
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 9b352a1e3fb4..d2424b068b7b 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -21,6 +21,7 @@
21#include <linux/smp.h> 21#include <linux/smp.h>
22#include <linux/rtc.h> 22#include <linux/rtc.h>
23#include <asm/clock.h> 23#include <asm/clock.h>
24#include <asm/hwblk.h>
24#include <asm/rtc.h> 25#include <asm/rtc.h>
25 26
26/* Dummy RTC ops */ 27/* Dummy RTC ops */
@@ -96,6 +97,7 @@ void __init time_init(void)
96 if (board_time_init) 97 if (board_time_init)
97 board_time_init(); 98 board_time_init();
98 99
100 hwblk_init();
99 clk_init(); 101 clk_init();
100 102
101 rtc_sh_get_time(&xtime); 103 rtc_sh_get_time(&xtime);