diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-11-04 10:15:29 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-11-04 10:15:29 -0400 |
commit | d63638440cfad75fb339fd1261bea0485c7c3ecc (patch) | |
tree | d1705ceeef82eb0b7b58f9503a472be810f418f2 /arch/arm/mach-shmobile | |
parent | f1e0477a7b7a541f51eea279910eed4ddd010033 (diff) | |
parent | 1a67a573b8d9f02211f36fbab50f6265dc49384a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into rmobile-latest
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r-- | arch/arm/mach-shmobile/Makefile.boot | 2 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/board-ag5evm.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/board-ap4evb.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/board-g3evm.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/board-g4evm.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/board-mackerel.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/entry-intc.S | 3 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/common.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/entry-macro.S | 3 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/gpio.h | 24 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/memory.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/sh7372.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/intc-sh7372.c | 52 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/platsmp.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/pm-sh7372.c | 342 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/pm_runtime.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/setup-sh7372.c | 25 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/sleep-sh7372.S | 221 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/smp-sh73a0.c | 6 |
19 files changed, 455 insertions, 296 deletions
diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot index 1c08ee9de86a..498efd99338d 100644 --- a/arch/arm/mach-shmobile/Makefile.boot +++ b/arch/arm/mach-shmobile/Makefile.boot | |||
@@ -1,7 +1,7 @@ | |||
1 | __ZRELADDR := $(shell /bin/bash -c 'printf "0x%08x" \ | 1 | __ZRELADDR := $(shell /bin/bash -c 'printf "0x%08x" \ |
2 | $$[$(CONFIG_MEMORY_START) + 0x8000]') | 2 | $$[$(CONFIG_MEMORY_START) + 0x8000]') |
3 | 3 | ||
4 | zreladdr-y := $(__ZRELADDR) | 4 | zreladdr-y += $(__ZRELADDR) |
5 | 5 | ||
6 | # Unsupported legacy stuff | 6 | # Unsupported legacy stuff |
7 | # | 7 | # |
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index cdfdd624d21d..475342bcc95c 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/mmc/sh_mobile_sdhi.h> | 37 | #include <linux/mmc/sh_mobile_sdhi.h> |
38 | #include <linux/mfd/tmio.h> | 38 | #include <linux/mfd/tmio.h> |
39 | #include <linux/sh_clk.h> | 39 | #include <linux/sh_clk.h> |
40 | #include <linux/dma-mapping.h> | ||
40 | #include <video/sh_mobile_lcdc.h> | 41 | #include <video/sh_mobile_lcdc.h> |
41 | #include <video/sh_mipi_dsi.h> | 42 | #include <video/sh_mipi_dsi.h> |
42 | #include <sound/sh_fsi.h> | 43 | #include <sound/sh_fsi.h> |
@@ -354,14 +355,17 @@ static struct resource sdhi0_resources[] = { | |||
354 | .flags = IORESOURCE_MEM, | 355 | .flags = IORESOURCE_MEM, |
355 | }, | 356 | }, |
356 | [1] = { | 357 | [1] = { |
358 | .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, | ||
357 | .start = gic_spi(83), | 359 | .start = gic_spi(83), |
358 | .flags = IORESOURCE_IRQ, | 360 | .flags = IORESOURCE_IRQ, |
359 | }, | 361 | }, |
360 | [2] = { | 362 | [2] = { |
363 | .name = SH_MOBILE_SDHI_IRQ_SDCARD, | ||
361 | .start = gic_spi(84), | 364 | .start = gic_spi(84), |
362 | .flags = IORESOURCE_IRQ, | 365 | .flags = IORESOURCE_IRQ, |
363 | }, | 366 | }, |
364 | [3] = { | 367 | [3] = { |
368 | .name = SH_MOBILE_SDHI_IRQ_SDIO, | ||
365 | .start = gic_spi(85), | 369 | .start = gic_spi(85), |
366 | .flags = IORESOURCE_IRQ, | 370 | .flags = IORESOURCE_IRQ, |
367 | }, | 371 | }, |
@@ -397,14 +401,17 @@ static struct resource sdhi1_resources[] = { | |||
397 | .flags = IORESOURCE_MEM, | 401 | .flags = IORESOURCE_MEM, |
398 | }, | 402 | }, |
399 | [1] = { | 403 | [1] = { |
404 | .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, | ||
400 | .start = gic_spi(87), | 405 | .start = gic_spi(87), |
401 | .flags = IORESOURCE_IRQ, | 406 | .flags = IORESOURCE_IRQ, |
402 | }, | 407 | }, |
403 | [2] = { | 408 | [2] = { |
409 | .name = SH_MOBILE_SDHI_IRQ_SDCARD, | ||
404 | .start = gic_spi(88), | 410 | .start = gic_spi(88), |
405 | .flags = IORESOURCE_IRQ, | 411 | .flags = IORESOURCE_IRQ, |
406 | }, | 412 | }, |
407 | [3] = { | 413 | [3] = { |
414 | .name = SH_MOBILE_SDHI_IRQ_SDIO, | ||
408 | .start = gic_spi(89), | 415 | .start = gic_spi(89), |
409 | .flags = IORESOURCE_IRQ, | 416 | .flags = IORESOURCE_IRQ, |
410 | }, | 417 | }, |
@@ -447,6 +454,8 @@ static struct map_desc ag5evm_io_desc[] __initdata = { | |||
447 | static void __init ag5evm_map_io(void) | 454 | static void __init ag5evm_map_io(void) |
448 | { | 455 | { |
449 | iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc)); | 456 | iotable_init(ag5evm_io_desc, ARRAY_SIZE(ag5evm_io_desc)); |
457 | /* DMA memory at 0xf6000000 - 0xffdfffff */ | ||
458 | init_consistent_dma_size(158 << 20); | ||
450 | 459 | ||
451 | /* setup early devices and console here as well */ | 460 | /* setup early devices and console here as well */ |
452 | sh73a0_add_early_devices(); | 461 | sh73a0_add_early_devices(); |
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 523f608eb8cf..5b7edadf4647 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -42,6 +42,8 @@ | |||
42 | #include <linux/leds.h> | 42 | #include <linux/leds.h> |
43 | #include <linux/input/sh_keysc.h> | 43 | #include <linux/input/sh_keysc.h> |
44 | #include <linux/usb/r8a66597.h> | 44 | #include <linux/usb/r8a66597.h> |
45 | #include <linux/pm_clock.h> | ||
46 | #include <linux/dma-mapping.h> | ||
45 | 47 | ||
46 | #include <media/sh_mobile_ceu.h> | 48 | #include <media/sh_mobile_ceu.h> |
47 | #include <media/sh_mobile_csi2.h> | 49 | #include <media/sh_mobile_csi2.h> |
@@ -1170,6 +1172,8 @@ static struct map_desc ap4evb_io_desc[] __initdata = { | |||
1170 | static void __init ap4evb_map_io(void) | 1172 | static void __init ap4evb_map_io(void) |
1171 | { | 1173 | { |
1172 | iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc)); | 1174 | iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc)); |
1175 | /* DMA memory at 0xf6000000 - 0xffdfffff */ | ||
1176 | init_consistent_dma_size(158 << 20); | ||
1173 | 1177 | ||
1174 | /* setup early devices and console here as well */ | 1178 | /* setup early devices and console here as well */ |
1175 | sh7372_add_early_devices(); | 1179 | sh7372_add_early_devices(); |
@@ -1408,6 +1412,11 @@ static void __init ap4evb_init(void) | |||
1408 | sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); | 1412 | sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); |
1409 | sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); | 1413 | sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); |
1410 | 1414 | ||
1415 | sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device); | ||
1416 | sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device); | ||
1417 | sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device); | ||
1418 | sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device); | ||
1419 | |||
1411 | hdmi_init_pm_clock(); | 1420 | hdmi_init_pm_clock(); |
1412 | fsi_init_pm_clock(); | 1421 | fsi_init_pm_clock(); |
1413 | sh7372_pm_init(); | 1422 | sh7372_pm_init(); |
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c index ef4613b993a2..8b620bf06221 100644 --- a/arch/arm/mach-shmobile/board-g3evm.c +++ b/arch/arm/mach-shmobile/board-g3evm.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/input.h> | 33 | #include <linux/input.h> |
34 | #include <linux/input/sh_keysc.h> | 34 | #include <linux/input/sh_keysc.h> |
35 | #include <linux/dma-mapping.h> | ||
35 | #include <mach/sh7367.h> | 36 | #include <mach/sh7367.h> |
36 | #include <mach/common.h> | 37 | #include <mach/common.h> |
37 | #include <asm/mach-types.h> | 38 | #include <asm/mach-types.h> |
@@ -260,6 +261,8 @@ static struct map_desc g3evm_io_desc[] __initdata = { | |||
260 | static void __init g3evm_map_io(void) | 261 | static void __init g3evm_map_io(void) |
261 | { | 262 | { |
262 | iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc)); | 263 | iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc)); |
264 | /* DMA memory at 0xf6000000 - 0xffdfffff */ | ||
265 | init_consistent_dma_size(158 << 20); | ||
263 | 266 | ||
264 | /* setup early devices and console here as well */ | 267 | /* setup early devices and console here as well */ |
265 | sh7367_add_early_devices(); | 268 | sh7367_add_early_devices(); |
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c index 8e3c5559f27f..7719ddc5f591 100644 --- a/arch/arm/mach-shmobile/board-g4evm.c +++ b/arch/arm/mach-shmobile/board-g4evm.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/mmc/host.h> | 33 | #include <linux/mmc/host.h> |
34 | #include <linux/mmc/sh_mobile_sdhi.h> | 34 | #include <linux/mmc/sh_mobile_sdhi.h> |
35 | #include <linux/gpio.h> | 35 | #include <linux/gpio.h> |
36 | #include <linux/dma-mapping.h> | ||
36 | #include <mach/sh7377.h> | 37 | #include <mach/sh7377.h> |
37 | #include <mach/common.h> | 38 | #include <mach/common.h> |
38 | #include <asm/mach-types.h> | 39 | #include <asm/mach-types.h> |
@@ -274,6 +275,8 @@ static struct map_desc g4evm_io_desc[] __initdata = { | |||
274 | static void __init g4evm_map_io(void) | 275 | static void __init g4evm_map_io(void) |
275 | { | 276 | { |
276 | iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc)); | 277 | iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc)); |
278 | /* DMA memory at 0xf6000000 - 0xffdfffff */ | ||
279 | init_consistent_dma_size(158 << 20); | ||
277 | 280 | ||
278 | /* setup early devices and console here as well */ | 281 | /* setup early devices and console here as well */ |
279 | sh7377_add_early_devices(); | 282 | sh7377_add_early_devices(); |
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 17c19dc25604..3689ad2e9156 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c | |||
@@ -39,12 +39,13 @@ | |||
39 | #include <linux/mtd/mtd.h> | 39 | #include <linux/mtd/mtd.h> |
40 | #include <linux/mtd/partitions.h> | 40 | #include <linux/mtd/partitions.h> |
41 | #include <linux/mtd/physmap.h> | 41 | #include <linux/mtd/physmap.h> |
42 | #include <linux/pm_runtime.h> | 42 | #include <linux/pm_clock.h> |
43 | #include <linux/smsc911x.h> | 43 | #include <linux/smsc911x.h> |
44 | #include <linux/sh_intc.h> | 44 | #include <linux/sh_intc.h> |
45 | #include <linux/tca6416_keypad.h> | 45 | #include <linux/tca6416_keypad.h> |
46 | #include <linux/usb/r8a66597.h> | 46 | #include <linux/usb/r8a66597.h> |
47 | #include <linux/usb/renesas_usbhs.h> | 47 | #include <linux/usb/renesas_usbhs.h> |
48 | #include <linux/dma-mapping.h> | ||
48 | 49 | ||
49 | #include <video/sh_mobile_hdmi.h> | 50 | #include <video/sh_mobile_hdmi.h> |
50 | #include <video/sh_mobile_lcdc.h> | 51 | #include <video/sh_mobile_lcdc.h> |
@@ -810,6 +811,7 @@ static struct usbhs_private usbhs1_private = { | |||
810 | }, | 811 | }, |
811 | .driver_param = { | 812 | .driver_param = { |
812 | .buswait_bwait = 4, | 813 | .buswait_bwait = 4, |
814 | .has_otg = 1, | ||
813 | .pipe_type = usbhs1_pipe_cfg, | 815 | .pipe_type = usbhs1_pipe_cfg, |
814 | .pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg), | 816 | .pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg), |
815 | .d0_tx_id = SHDMA_SLAVE_USB1_TX, | 817 | .d0_tx_id = SHDMA_SLAVE_USB1_TX, |
@@ -1070,14 +1072,17 @@ static struct resource sdhi1_resources[] = { | |||
1070 | .flags = IORESOURCE_MEM, | 1072 | .flags = IORESOURCE_MEM, |
1071 | }, | 1073 | }, |
1072 | [1] = { | 1074 | [1] = { |
1075 | .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, | ||
1073 | .start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */ | 1076 | .start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */ |
1074 | .flags = IORESOURCE_IRQ, | 1077 | .flags = IORESOURCE_IRQ, |
1075 | }, | 1078 | }, |
1076 | [2] = { | 1079 | [2] = { |
1080 | .name = SH_MOBILE_SDHI_IRQ_SDCARD, | ||
1077 | .start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */ | 1081 | .start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */ |
1078 | .flags = IORESOURCE_IRQ, | 1082 | .flags = IORESOURCE_IRQ, |
1079 | }, | 1083 | }, |
1080 | [3] = { | 1084 | [3] = { |
1085 | .name = SH_MOBILE_SDHI_IRQ_SDIO, | ||
1081 | .start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */ | 1086 | .start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */ |
1082 | .flags = IORESOURCE_IRQ, | 1087 | .flags = IORESOURCE_IRQ, |
1083 | }, | 1088 | }, |
@@ -1121,14 +1126,17 @@ static struct resource sdhi2_resources[] = { | |||
1121 | .flags = IORESOURCE_MEM, | 1126 | .flags = IORESOURCE_MEM, |
1122 | }, | 1127 | }, |
1123 | [1] = { | 1128 | [1] = { |
1129 | .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, | ||
1124 | .start = evt2irq(0x1200), /* SDHI2_SDHI2I0 */ | 1130 | .start = evt2irq(0x1200), /* SDHI2_SDHI2I0 */ |
1125 | .flags = IORESOURCE_IRQ, | 1131 | .flags = IORESOURCE_IRQ, |
1126 | }, | 1132 | }, |
1127 | [2] = { | 1133 | [2] = { |
1134 | .name = SH_MOBILE_SDHI_IRQ_SDCARD, | ||
1128 | .start = evt2irq(0x1220), /* SDHI2_SDHI2I1 */ | 1135 | .start = evt2irq(0x1220), /* SDHI2_SDHI2I1 */ |
1129 | .flags = IORESOURCE_IRQ, | 1136 | .flags = IORESOURCE_IRQ, |
1130 | }, | 1137 | }, |
1131 | [3] = { | 1138 | [3] = { |
1139 | .name = SH_MOBILE_SDHI_IRQ_SDIO, | ||
1132 | .start = evt2irq(0x1240), /* SDHI2_SDHI2I2 */ | 1140 | .start = evt2irq(0x1240), /* SDHI2_SDHI2I2 */ |
1133 | .flags = IORESOURCE_IRQ, | 1141 | .flags = IORESOURCE_IRQ, |
1134 | }, | 1142 | }, |
@@ -1381,6 +1389,8 @@ static struct map_desc mackerel_io_desc[] __initdata = { | |||
1381 | static void __init mackerel_map_io(void) | 1389 | static void __init mackerel_map_io(void) |
1382 | { | 1390 | { |
1383 | iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc)); | 1391 | iotable_init(mackerel_io_desc, ARRAY_SIZE(mackerel_io_desc)); |
1392 | /* DMA memory at 0xf6000000 - 0xffdfffff */ | ||
1393 | init_consistent_dma_size(158 << 20); | ||
1384 | 1394 | ||
1385 | /* setup early devices and console here as well */ | 1395 | /* setup early devices and console here as well */ |
1386 | sh7372_add_early_devices(); | 1396 | sh7372_add_early_devices(); |
@@ -1587,7 +1597,17 @@ static void __init mackerel_init(void) | |||
1587 | 1597 | ||
1588 | sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); | 1598 | sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); |
1589 | sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device); | 1599 | sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device); |
1600 | sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device); | ||
1590 | sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); | 1601 | sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); |
1602 | sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device); | ||
1603 | sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device); | ||
1604 | sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device); | ||
1605 | sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device); | ||
1606 | #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) | ||
1607 | sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device); | ||
1608 | #endif | ||
1609 | sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device); | ||
1610 | sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device); | ||
1591 | 1611 | ||
1592 | hdmi_init_pm_clock(); | 1612 | hdmi_init_pm_clock(); |
1593 | sh7372_pm_init(); | 1613 | sh7372_pm_init(); |
diff --git a/arch/arm/mach-shmobile/entry-intc.S b/arch/arm/mach-shmobile/entry-intc.S index cac0a7ae2084..1a1c00ca39a2 100644 --- a/arch/arm/mach-shmobile/entry-intc.S +++ b/arch/arm/mach-shmobile/entry-intc.S | |||
@@ -51,7 +51,4 @@ | |||
51 | .macro test_for_ipi, irqnr, irqstat, base, tmp | 51 | .macro test_for_ipi, irqnr, irqstat, base, tmp |
52 | .endm | 52 | .endm |
53 | 53 | ||
54 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
55 | .endm | ||
56 | |||
57 | arch_irq_handler shmobile_handle_irq_intc | 54 | arch_irq_handler shmobile_handle_irq_intc |
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 06aecb31d9c7..c0cdbf997c91 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h | |||
@@ -35,8 +35,8 @@ extern void sh7372_add_standard_devices(void); | |||
35 | extern void sh7372_clock_init(void); | 35 | extern void sh7372_clock_init(void); |
36 | extern void sh7372_pinmux_init(void); | 36 | extern void sh7372_pinmux_init(void); |
37 | extern void sh7372_pm_init(void); | 37 | extern void sh7372_pm_init(void); |
38 | extern void sh7372_cpu_suspend(void); | 38 | extern void sh7372_resume_core_standby_a3sm(void); |
39 | extern void sh7372_cpu_resume(void); | 39 | extern int sh7372_do_idle_a3sm(unsigned long unused); |
40 | extern struct clk sh7372_extal1_clk; | 40 | extern struct clk sh7372_extal1_clk; |
41 | extern struct clk sh7372_extal2_clk; | 41 | extern struct clk sh7372_extal2_clk; |
42 | 42 | ||
diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S index d791f10eeac7..8d4a416d4285 100644 --- a/arch/arm/mach-shmobile/include/mach/entry-macro.S +++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S | |||
@@ -27,8 +27,5 @@ | |||
27 | .macro test_for_ipi, irqnr, irqstat, base, tmp | 27 | .macro test_for_ipi, irqnr, irqstat, base, tmp |
28 | .endm | 28 | .endm |
29 | 29 | ||
30 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
31 | .endm | ||
32 | |||
33 | .macro arch_ret_to_user, tmp1, tmp2 | 30 | .macro arch_ret_to_user, tmp1, tmp2 |
34 | .endm | 31 | .endm |
diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h index 2b1bb9e43dda..7bf0890e16ba 100644 --- a/arch/arm/mach-shmobile/include/mach/gpio.h +++ b/arch/arm/mach-shmobile/include/mach/gpio.h | |||
@@ -18,31 +18,15 @@ | |||
18 | 18 | ||
19 | #ifdef CONFIG_GPIOLIB | 19 | #ifdef CONFIG_GPIOLIB |
20 | 20 | ||
21 | static inline int gpio_get_value(unsigned gpio) | ||
22 | { | ||
23 | return __gpio_get_value(gpio); | ||
24 | } | ||
25 | |||
26 | static inline void gpio_set_value(unsigned gpio, int value) | ||
27 | { | ||
28 | __gpio_set_value(gpio, value); | ||
29 | } | ||
30 | |||
31 | static inline int gpio_cansleep(unsigned gpio) | ||
32 | { | ||
33 | return __gpio_cansleep(gpio); | ||
34 | } | ||
35 | |||
36 | static inline int gpio_to_irq(unsigned gpio) | ||
37 | { | ||
38 | return __gpio_to_irq(gpio); | ||
39 | } | ||
40 | |||
41 | static inline int irq_to_gpio(unsigned int irq) | 21 | static inline int irq_to_gpio(unsigned int irq) |
42 | { | 22 | { |
43 | return -ENOSYS; | 23 | return -ENOSYS; |
44 | } | 24 | } |
45 | 25 | ||
26 | #else | ||
27 | |||
28 | #define __ARM_GPIOLIB_COMPLEX | ||
29 | |||
46 | #endif /* CONFIG_GPIOLIB */ | 30 | #endif /* CONFIG_GPIOLIB */ |
47 | 31 | ||
48 | #endif /* __ASM_ARCH_GPIO_H */ | 32 | #endif /* __ASM_ARCH_GPIO_H */ |
diff --git a/arch/arm/mach-shmobile/include/mach/memory.h b/arch/arm/mach-shmobile/include/mach/memory.h index ad00c3c258f4..0ffbe8155c76 100644 --- a/arch/arm/mach-shmobile/include/mach/memory.h +++ b/arch/arm/mach-shmobile/include/mach/memory.h | |||
@@ -4,7 +4,4 @@ | |||
4 | #define PLAT_PHYS_OFFSET UL(CONFIG_MEMORY_START) | 4 | #define PLAT_PHYS_OFFSET UL(CONFIG_MEMORY_START) |
5 | #define MEM_SIZE UL(CONFIG_MEMORY_SIZE) | 5 | #define MEM_SIZE UL(CONFIG_MEMORY_SIZE) |
6 | 6 | ||
7 | /* DMA memory at 0xf6000000 - 0xffdfffff */ | ||
8 | #define CONSISTENT_DMA_SIZE (158 << 20) | ||
9 | |||
10 | #endif /* __ASM_MACH_MEMORY_H */ | 7 | #endif /* __ASM_MACH_MEMORY_H */ |
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 24e63a85e669..84532f9629b2 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h | |||
@@ -479,7 +479,12 @@ struct platform_device; | |||
479 | 479 | ||
480 | struct sh7372_pm_domain { | 480 | struct sh7372_pm_domain { |
481 | struct generic_pm_domain genpd; | 481 | struct generic_pm_domain genpd; |
482 | struct dev_power_governor *gov; | ||
483 | void (*suspend)(void); | ||
484 | void (*resume)(void); | ||
482 | unsigned int bit_shift; | 485 | unsigned int bit_shift; |
486 | bool no_debug; | ||
487 | bool stay_on; | ||
483 | }; | 488 | }; |
484 | 489 | ||
485 | static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) | 490 | static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) |
@@ -491,16 +496,24 @@ static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) | |||
491 | extern struct sh7372_pm_domain sh7372_a4lc; | 496 | extern struct sh7372_pm_domain sh7372_a4lc; |
492 | extern struct sh7372_pm_domain sh7372_a4mp; | 497 | extern struct sh7372_pm_domain sh7372_a4mp; |
493 | extern struct sh7372_pm_domain sh7372_d4; | 498 | extern struct sh7372_pm_domain sh7372_d4; |
499 | extern struct sh7372_pm_domain sh7372_a4r; | ||
494 | extern struct sh7372_pm_domain sh7372_a3rv; | 500 | extern struct sh7372_pm_domain sh7372_a3rv; |
495 | extern struct sh7372_pm_domain sh7372_a3ri; | 501 | extern struct sh7372_pm_domain sh7372_a3ri; |
502 | extern struct sh7372_pm_domain sh7372_a3sp; | ||
496 | extern struct sh7372_pm_domain sh7372_a3sg; | 503 | extern struct sh7372_pm_domain sh7372_a3sg; |
497 | 504 | ||
498 | extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd); | 505 | extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd); |
499 | extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, | 506 | extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, |
500 | struct platform_device *pdev); | 507 | struct platform_device *pdev); |
508 | extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, | ||
509 | struct sh7372_pm_domain *sh7372_sd); | ||
501 | #else | 510 | #else |
502 | #define sh7372_init_pm_domain(pd) do { } while(0) | 511 | #define sh7372_init_pm_domain(pd) do { } while(0) |
503 | #define sh7372_add_device_to_domain(pd, pdev) do { } while(0) | 512 | #define sh7372_add_device_to_domain(pd, pdev) do { } while(0) |
513 | #define sh7372_pm_add_subdomain(pd, sd) do { } while(0) | ||
504 | #endif /* CONFIG_PM */ | 514 | #endif /* CONFIG_PM */ |
505 | 515 | ||
516 | extern void sh7372_intcs_suspend(void); | ||
517 | extern void sh7372_intcs_resume(void); | ||
518 | |||
506 | #endif /* __ASM_SH7372_H__ */ | 519 | #endif /* __ASM_SH7372_H__ */ |
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c index 739315e30eb9..29cdc0522d9c 100644 --- a/arch/arm/mach-shmobile/intc-sh7372.c +++ b/arch/arm/mach-shmobile/intc-sh7372.c | |||
@@ -606,9 +606,16 @@ static void intcs_demux(unsigned int irq, struct irq_desc *desc) | |||
606 | generic_handle_irq(intcs_evt2irq(evtcodeas)); | 606 | generic_handle_irq(intcs_evt2irq(evtcodeas)); |
607 | } | 607 | } |
608 | 608 | ||
609 | static void __iomem *intcs_ffd2; | ||
610 | static void __iomem *intcs_ffd5; | ||
611 | |||
609 | void __init sh7372_init_irq(void) | 612 | void __init sh7372_init_irq(void) |
610 | { | 613 | { |
611 | void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); | 614 | void __iomem *intevtsa; |
615 | |||
616 | intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE); | ||
617 | intevtsa = intcs_ffd2 + 0x100; | ||
618 | intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE); | ||
612 | 619 | ||
613 | register_intc_controller(&intca_desc); | 620 | register_intc_controller(&intca_desc); |
614 | register_intc_controller(&intcs_desc); | 621 | register_intc_controller(&intcs_desc); |
@@ -617,3 +624,46 @@ void __init sh7372_init_irq(void) | |||
617 | irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa); | 624 | irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa); |
618 | irq_set_chained_handler(evt2irq(0xf80), intcs_demux); | 625 | irq_set_chained_handler(evt2irq(0xf80), intcs_demux); |
619 | } | 626 | } |
627 | |||
628 | static unsigned short ffd2[0x200]; | ||
629 | static unsigned short ffd5[0x100]; | ||
630 | |||
631 | void sh7372_intcs_suspend(void) | ||
632 | { | ||
633 | int k; | ||
634 | |||
635 | for (k = 0x00; k <= 0x30; k += 4) | ||
636 | ffd2[k] = __raw_readw(intcs_ffd2 + k); | ||
637 | |||
638 | for (k = 0x80; k <= 0xb0; k += 4) | ||
639 | ffd2[k] = __raw_readb(intcs_ffd2 + k); | ||
640 | |||
641 | for (k = 0x180; k <= 0x188; k += 4) | ||
642 | ffd2[k] = __raw_readb(intcs_ffd2 + k); | ||
643 | |||
644 | for (k = 0x00; k <= 0x3c; k += 4) | ||
645 | ffd5[k] = __raw_readw(intcs_ffd5 + k); | ||
646 | |||
647 | for (k = 0x80; k <= 0x9c; k += 4) | ||
648 | ffd5[k] = __raw_readb(intcs_ffd5 + k); | ||
649 | } | ||
650 | |||
651 | void sh7372_intcs_resume(void) | ||
652 | { | ||
653 | int k; | ||
654 | |||
655 | for (k = 0x00; k <= 0x30; k += 4) | ||
656 | __raw_writew(ffd2[k], intcs_ffd2 + k); | ||
657 | |||
658 | for (k = 0x80; k <= 0xb0; k += 4) | ||
659 | __raw_writeb(ffd2[k], intcs_ffd2 + k); | ||
660 | |||
661 | for (k = 0x180; k <= 0x188; k += 4) | ||
662 | __raw_writeb(ffd2[k], intcs_ffd2 + k); | ||
663 | |||
664 | for (k = 0x00; k <= 0x3c; k += 4) | ||
665 | __raw_writew(ffd5[k], intcs_ffd5 + k); | ||
666 | |||
667 | for (k = 0x80; k <= 0x9c; k += 4) | ||
668 | __raw_writeb(ffd5[k], intcs_ffd5 + k); | ||
669 | } | ||
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index 66f980625a33..e4e485fa2532 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c | |||
@@ -56,6 +56,12 @@ void __init smp_init_cpus(void) | |||
56 | unsigned int ncores = shmobile_smp_get_core_count(); | 56 | unsigned int ncores = shmobile_smp_get_core_count(); |
57 | unsigned int i; | 57 | unsigned int i; |
58 | 58 | ||
59 | if (ncores > nr_cpu_ids) { | ||
60 | pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", | ||
61 | ncores, nr_cpu_ids); | ||
62 | ncores = nr_cpu_ids; | ||
63 | } | ||
64 | |||
59 | for (i = 0; i < ncores; i++) | 65 | for (i = 0; i < ncores; i++) |
60 | set_cpu_possible(i, true); | 66 | set_cpu_possible(i, true); |
61 | 67 | ||
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 933fb411be0f..79612737c5b2 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c | |||
@@ -15,23 +15,61 @@ | |||
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/pm_runtime.h> | 18 | #include <linux/pm_clock.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/irq.h> | ||
22 | #include <linux/bitrev.h> | ||
21 | #include <asm/system.h> | 23 | #include <asm/system.h> |
22 | #include <asm/io.h> | 24 | #include <asm/io.h> |
23 | #include <asm/tlbflush.h> | 25 | #include <asm/tlbflush.h> |
26 | #include <asm/suspend.h> | ||
24 | #include <mach/common.h> | 27 | #include <mach/common.h> |
25 | #include <mach/sh7372.h> | 28 | #include <mach/sh7372.h> |
26 | 29 | ||
27 | #define SMFRAM 0xe6a70000 | 30 | /* DBG */ |
28 | #define SYSTBCR 0xe6150024 | 31 | #define DBGREG1 0xe6100020 |
29 | #define SBAR 0xe6180020 | 32 | #define DBGREG9 0xe6100040 |
30 | #define APARMBAREA 0xe6f10020 | ||
31 | 33 | ||
34 | /* CPGA */ | ||
35 | #define SYSTBCR 0xe6150024 | ||
36 | #define MSTPSR0 0xe6150030 | ||
37 | #define MSTPSR1 0xe6150038 | ||
38 | #define MSTPSR2 0xe6150040 | ||
39 | #define MSTPSR3 0xe6150048 | ||
40 | #define MSTPSR4 0xe615004c | ||
41 | #define PLLC01STPCR 0xe61500c8 | ||
42 | |||
43 | /* SYSC */ | ||
32 | #define SPDCR 0xe6180008 | 44 | #define SPDCR 0xe6180008 |
33 | #define SWUCR 0xe6180014 | 45 | #define SWUCR 0xe6180014 |
46 | #define SBAR 0xe6180020 | ||
47 | #define WUPRMSK 0xe6180028 | ||
48 | #define WUPSMSK 0xe618002c | ||
49 | #define WUPSMSK2 0xe6180048 | ||
34 | #define PSTR 0xe6180080 | 50 | #define PSTR 0xe6180080 |
51 | #define WUPSFAC 0xe6180098 | ||
52 | #define IRQCR 0xe618022c | ||
53 | #define IRQCR2 0xe6180238 | ||
54 | #define IRQCR3 0xe6180244 | ||
55 | #define IRQCR4 0xe6180248 | ||
56 | #define PDNSEL 0xe6180254 | ||
57 | |||
58 | /* INTC */ | ||
59 | #define ICR1A 0xe6900000 | ||
60 | #define ICR2A 0xe6900004 | ||
61 | #define ICR3A 0xe6900008 | ||
62 | #define ICR4A 0xe690000c | ||
63 | #define INTMSK00A 0xe6900040 | ||
64 | #define INTMSK10A 0xe6900044 | ||
65 | #define INTMSK20A 0xe6900048 | ||
66 | #define INTMSK30A 0xe690004c | ||
67 | |||
68 | /* MFIS */ | ||
69 | #define SMFRAM 0xe6a70000 | ||
70 | |||
71 | /* AP-System Core */ | ||
72 | #define APARMBAREA 0xe6f10020 | ||
35 | 73 | ||
36 | #define PSTR_RETRIES 100 | 74 | #define PSTR_RETRIES 100 |
37 | #define PSTR_DELAY_US 10 | 75 | #define PSTR_DELAY_US 10 |
@@ -43,6 +81,12 @@ static int pd_power_down(struct generic_pm_domain *genpd) | |||
43 | struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); | 81 | struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); |
44 | unsigned int mask = 1 << sh7372_pd->bit_shift; | 82 | unsigned int mask = 1 << sh7372_pd->bit_shift; |
45 | 83 | ||
84 | if (sh7372_pd->suspend) | ||
85 | sh7372_pd->suspend(); | ||
86 | |||
87 | if (sh7372_pd->stay_on) | ||
88 | return 0; | ||
89 | |||
46 | if (__raw_readl(PSTR) & mask) { | 90 | if (__raw_readl(PSTR) & mask) { |
47 | unsigned int retry_count; | 91 | unsigned int retry_count; |
48 | 92 | ||
@@ -55,8 +99,9 @@ static int pd_power_down(struct generic_pm_domain *genpd) | |||
55 | } | 99 | } |
56 | } | 100 | } |
57 | 101 | ||
58 | pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n", | 102 | if (!sh7372_pd->no_debug) |
59 | mask, __raw_readl(PSTR)); | 103 | pr_debug("sh7372 power domain down 0x%08x -> PSTR = 0x%08x\n", |
104 | mask, __raw_readl(PSTR)); | ||
60 | 105 | ||
61 | return 0; | 106 | return 0; |
62 | } | 107 | } |
@@ -68,6 +113,9 @@ static int pd_power_up(struct generic_pm_domain *genpd) | |||
68 | unsigned int retry_count; | 113 | unsigned int retry_count; |
69 | int ret = 0; | 114 | int ret = 0; |
70 | 115 | ||
116 | if (sh7372_pd->stay_on) | ||
117 | goto out; | ||
118 | |||
71 | if (__raw_readl(PSTR) & mask) | 119 | if (__raw_readl(PSTR) & mask) |
72 | goto out; | 120 | goto out; |
73 | 121 | ||
@@ -84,66 +132,48 @@ static int pd_power_up(struct generic_pm_domain *genpd) | |||
84 | if (__raw_readl(SWUCR) & mask) | 132 | if (__raw_readl(SWUCR) & mask) |
85 | ret = -EIO; | 133 | ret = -EIO; |
86 | 134 | ||
135 | if (!sh7372_pd->no_debug) | ||
136 | pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n", | ||
137 | mask, __raw_readl(PSTR)); | ||
138 | |||
87 | out: | 139 | out: |
88 | pr_debug("sh7372 power domain up 0x%08x -> PSTR = 0x%08x\n", | 140 | if (ret == 0 && sh7372_pd->resume) |
89 | mask, __raw_readl(PSTR)); | 141 | sh7372_pd->resume(); |
90 | 142 | ||
91 | return ret; | 143 | return ret; |
92 | } | 144 | } |
93 | 145 | ||
94 | static int pd_power_up_a3rv(struct generic_pm_domain *genpd) | 146 | static void sh7372_a4r_suspend(void) |
95 | { | 147 | { |
96 | int ret = pd_power_up(genpd); | 148 | sh7372_intcs_suspend(); |
97 | 149 | __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ | |
98 | /* force A4LC on after A3RV has been requested on */ | ||
99 | pm_genpd_poweron(&sh7372_a4lc.genpd); | ||
100 | |||
101 | return ret; | ||
102 | } | 150 | } |
103 | 151 | ||
104 | static int pd_power_down_a3rv(struct generic_pm_domain *genpd) | 152 | static bool pd_active_wakeup(struct device *dev) |
105 | { | 153 | { |
106 | int ret = pd_power_down(genpd); | 154 | return true; |
107 | |||
108 | /* try to power down A4LC after A3RV is requested off */ | ||
109 | genpd_queue_power_off_work(&sh7372_a4lc.genpd); | ||
110 | |||
111 | return ret; | ||
112 | } | 155 | } |
113 | 156 | ||
114 | static int pd_power_down_a4lc(struct generic_pm_domain *genpd) | 157 | static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain) |
115 | { | 158 | { |
116 | /* only power down A4LC if A3RV is off */ | 159 | return false; |
117 | if (!(__raw_readl(PSTR) & (1 << sh7372_a3rv.bit_shift))) | ||
118 | return pd_power_down(genpd); | ||
119 | |||
120 | return -EBUSY; | ||
121 | } | 160 | } |
122 | 161 | ||
123 | static bool pd_active_wakeup(struct device *dev) | 162 | struct dev_power_governor sh7372_always_on_gov = { |
124 | { | 163 | .power_down_ok = sh7372_power_down_forbidden, |
125 | return true; | 164 | }; |
126 | } | ||
127 | 165 | ||
128 | void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) | 166 | void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) |
129 | { | 167 | { |
130 | struct generic_pm_domain *genpd = &sh7372_pd->genpd; | 168 | struct generic_pm_domain *genpd = &sh7372_pd->genpd; |
131 | 169 | ||
132 | pm_genpd_init(genpd, NULL, false); | 170 | pm_genpd_init(genpd, sh7372_pd->gov, false); |
133 | genpd->stop_device = pm_clk_suspend; | 171 | genpd->stop_device = pm_clk_suspend; |
134 | genpd->start_device = pm_clk_resume; | 172 | genpd->start_device = pm_clk_resume; |
173 | genpd->dev_irq_safe = true; | ||
135 | genpd->active_wakeup = pd_active_wakeup; | 174 | genpd->active_wakeup = pd_active_wakeup; |
136 | 175 | genpd->power_off = pd_power_down; | |
137 | if (sh7372_pd == &sh7372_a4lc) { | 176 | genpd->power_on = pd_power_up; |
138 | genpd->power_off = pd_power_down_a4lc; | ||
139 | genpd->power_on = pd_power_up; | ||
140 | } else if (sh7372_pd == &sh7372_a3rv) { | ||
141 | genpd->power_off = pd_power_down_a3rv; | ||
142 | genpd->power_on = pd_power_up_a3rv; | ||
143 | } else { | ||
144 | genpd->power_off = pd_power_down; | ||
145 | genpd->power_on = pd_power_up; | ||
146 | } | ||
147 | genpd->power_on(&sh7372_pd->genpd); | 177 | genpd->power_on(&sh7372_pd->genpd); |
148 | } | 178 | } |
149 | 179 | ||
@@ -152,11 +182,15 @@ void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, | |||
152 | { | 182 | { |
153 | struct device *dev = &pdev->dev; | 183 | struct device *dev = &pdev->dev; |
154 | 184 | ||
155 | if (!dev->power.subsys_data) { | ||
156 | pm_clk_init(dev); | ||
157 | pm_clk_add(dev, NULL); | ||
158 | } | ||
159 | pm_genpd_add_device(&sh7372_pd->genpd, dev); | 185 | pm_genpd_add_device(&sh7372_pd->genpd, dev); |
186 | if (pm_clk_no_clocks(dev)) | ||
187 | pm_clk_add(dev, NULL); | ||
188 | } | ||
189 | |||
190 | void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, | ||
191 | struct sh7372_pm_domain *sh7372_sd) | ||
192 | { | ||
193 | pm_genpd_add_subdomain(&sh7372_pd->genpd, &sh7372_sd->genpd); | ||
160 | } | 194 | } |
161 | 195 | ||
162 | struct sh7372_pm_domain sh7372_a4lc = { | 196 | struct sh7372_pm_domain sh7372_a4lc = { |
@@ -171,6 +205,14 @@ struct sh7372_pm_domain sh7372_d4 = { | |||
171 | .bit_shift = 3, | 205 | .bit_shift = 3, |
172 | }; | 206 | }; |
173 | 207 | ||
208 | struct sh7372_pm_domain sh7372_a4r = { | ||
209 | .bit_shift = 5, | ||
210 | .gov = &sh7372_always_on_gov, | ||
211 | .suspend = sh7372_a4r_suspend, | ||
212 | .resume = sh7372_intcs_resume, | ||
213 | .stay_on = true, | ||
214 | }; | ||
215 | |||
174 | struct sh7372_pm_domain sh7372_a3rv = { | 216 | struct sh7372_pm_domain sh7372_a3rv = { |
175 | .bit_shift = 6, | 217 | .bit_shift = 6, |
176 | }; | 218 | }; |
@@ -179,39 +221,187 @@ struct sh7372_pm_domain sh7372_a3ri = { | |||
179 | .bit_shift = 8, | 221 | .bit_shift = 8, |
180 | }; | 222 | }; |
181 | 223 | ||
224 | struct sh7372_pm_domain sh7372_a3sp = { | ||
225 | .bit_shift = 11, | ||
226 | .gov = &sh7372_always_on_gov, | ||
227 | .no_debug = true, | ||
228 | }; | ||
229 | |||
182 | struct sh7372_pm_domain sh7372_a3sg = { | 230 | struct sh7372_pm_domain sh7372_a3sg = { |
183 | .bit_shift = 13, | 231 | .bit_shift = 13, |
184 | }; | 232 | }; |
185 | 233 | ||
186 | #endif /* CONFIG_PM */ | 234 | #endif /* CONFIG_PM */ |
187 | 235 | ||
236 | #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) | ||
237 | static int sh7372_do_idle_core_standby(unsigned long unused) | ||
238 | { | ||
239 | cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */ | ||
240 | return 0; | ||
241 | } | ||
242 | |||
188 | static void sh7372_enter_core_standby(void) | 243 | static void sh7372_enter_core_standby(void) |
189 | { | 244 | { |
190 | void __iomem *smfram = (void __iomem *)SMFRAM; | 245 | /* set reset vector, translate 4k */ |
246 | __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); | ||
247 | __raw_writel(0, APARMBAREA); | ||
191 | 248 | ||
192 | __raw_writel(0, APARMBAREA); /* translate 4k */ | 249 | /* enter sleep mode with SYSTBCR to 0x10 */ |
193 | __raw_writel(__pa(sh7372_cpu_resume), SBAR); /* set reset vector */ | 250 | __raw_writel(0x10, SYSTBCR); |
194 | __raw_writel(0x10, SYSTBCR); /* enable core standby */ | 251 | cpu_suspend(0, sh7372_do_idle_core_standby); |
252 | __raw_writel(0, SYSTBCR); | ||
195 | 253 | ||
196 | __raw_writel(0, smfram + 0x3c); /* clear page table address */ | 254 | /* disable reset vector translation */ |
255 | __raw_writel(0, SBAR); | ||
256 | } | ||
257 | #endif | ||
258 | |||
259 | #ifdef CONFIG_SUSPEND | ||
260 | static void sh7372_enter_a3sm_common(int pllc0_on) | ||
261 | { | ||
262 | /* set reset vector, translate 4k */ | ||
263 | __raw_writel(__pa(sh7372_resume_core_standby_a3sm), SBAR); | ||
264 | __raw_writel(0, APARMBAREA); | ||
265 | |||
266 | if (pllc0_on) | ||
267 | __raw_writel(0, PLLC01STPCR); | ||
268 | else | ||
269 | __raw_writel(1 << 28, PLLC01STPCR); | ||
270 | |||
271 | __raw_writel(0, PDNSEL); /* power-down A3SM only, not A4S */ | ||
272 | __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */ | ||
273 | cpu_suspend(0, sh7372_do_idle_a3sm); | ||
274 | __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */ | ||
275 | |||
276 | /* disable reset vector translation */ | ||
277 | __raw_writel(0, SBAR); | ||
278 | } | ||
279 | |||
280 | static int sh7372_a3sm_valid(unsigned long *mskp, unsigned long *msk2p) | ||
281 | { | ||
282 | unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4; | ||
283 | unsigned long msk, msk2; | ||
284 | |||
285 | /* check active clocks to determine potential wakeup sources */ | ||
286 | |||
287 | mstpsr0 = __raw_readl(MSTPSR0); | ||
288 | if ((mstpsr0 & 0x00000003) != 0x00000003) { | ||
289 | pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0); | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | mstpsr1 = __raw_readl(MSTPSR1); | ||
294 | if ((mstpsr1 & 0xff079b7f) != 0xff079b7f) { | ||
295 | pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1); | ||
296 | return 0; | ||
297 | } | ||
197 | 298 | ||
198 | sh7372_cpu_suspend(); | 299 | mstpsr2 = __raw_readl(MSTPSR2); |
199 | cpu_init(); | 300 | if ((mstpsr2 & 0x000741ff) != 0x000741ff) { |
301 | pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2); | ||
302 | return 0; | ||
303 | } | ||
200 | 304 | ||
201 | /* if page table address is non-NULL then we have been powered down */ | 305 | mstpsr3 = __raw_readl(MSTPSR3); |
202 | if (__raw_readl(smfram + 0x3c)) { | 306 | if ((mstpsr3 & 0x1a60f010) != 0x1a60f010) { |
203 | __raw_writel(__raw_readl(smfram + 0x40), | 307 | pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3); |
204 | __va(__raw_readl(smfram + 0x3c))); | 308 | return 0; |
309 | } | ||
205 | 310 | ||
206 | flush_tlb_all(); | 311 | mstpsr4 = __raw_readl(MSTPSR4); |
207 | set_cr(__raw_readl(smfram + 0x38)); | 312 | if ((mstpsr4 & 0x00008cf0) != 0x00008cf0) { |
313 | pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4); | ||
314 | return 0; | ||
208 | } | 315 | } |
209 | 316 | ||
210 | __raw_writel(0, SYSTBCR); /* disable core standby */ | 317 | msk = 0; |
211 | __raw_writel(0, SBAR); /* disable reset vector translation */ | 318 | msk2 = 0; |
319 | |||
320 | /* make bitmaps of limited number of wakeup sources */ | ||
321 | |||
322 | if ((mstpsr2 & (1 << 23)) == 0) /* SPU2 */ | ||
323 | msk |= 1 << 31; | ||
324 | |||
325 | if ((mstpsr2 & (1 << 12)) == 0) /* MFI_MFIM */ | ||
326 | msk |= 1 << 21; | ||
327 | |||
328 | if ((mstpsr4 & (1 << 3)) == 0) /* KEYSC */ | ||
329 | msk |= 1 << 2; | ||
330 | |||
331 | if ((mstpsr1 & (1 << 24)) == 0) /* CMT0 */ | ||
332 | msk |= 1 << 1; | ||
333 | |||
334 | if ((mstpsr3 & (1 << 29)) == 0) /* CMT1 */ | ||
335 | msk |= 1 << 1; | ||
336 | |||
337 | if ((mstpsr4 & (1 << 0)) == 0) /* CMT2 */ | ||
338 | msk |= 1 << 1; | ||
339 | |||
340 | if ((mstpsr2 & (1 << 13)) == 0) /* MFI_MFIS */ | ||
341 | msk2 |= 1 << 17; | ||
342 | |||
343 | *mskp = msk; | ||
344 | *msk2p = msk2; | ||
345 | |||
346 | return 1; | ||
347 | } | ||
348 | |||
349 | static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p) | ||
350 | { | ||
351 | u16 tmp, irqcr1, irqcr2; | ||
352 | int k; | ||
353 | |||
354 | irqcr1 = 0; | ||
355 | irqcr2 = 0; | ||
356 | |||
357 | /* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */ | ||
358 | for (k = 0; k <= 7; k++) { | ||
359 | tmp = (icr >> ((7 - k) * 4)) & 0xf; | ||
360 | irqcr1 |= (tmp & 0x03) << (k * 2); | ||
361 | irqcr2 |= (tmp >> 2) << (k * 2); | ||
362 | } | ||
363 | |||
364 | *irqcr1p = irqcr1; | ||
365 | *irqcr2p = irqcr2; | ||
366 | } | ||
367 | |||
368 | static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2) | ||
369 | { | ||
370 | u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high; | ||
371 | unsigned long tmp; | ||
372 | |||
373 | /* read IRQ0A -> IRQ15A mask */ | ||
374 | tmp = bitrev8(__raw_readb(INTMSK00A)); | ||
375 | tmp |= bitrev8(__raw_readb(INTMSK10A)) << 8; | ||
376 | |||
377 | /* setup WUPSMSK from clocks and external IRQ mask */ | ||
378 | msk = (~msk & 0xc030000f) | (tmp << 4); | ||
379 | __raw_writel(msk, WUPSMSK); | ||
380 | |||
381 | /* propage level/edge trigger for external IRQ 0->15 */ | ||
382 | sh7372_icr_to_irqcr(__raw_readl(ICR1A), &irqcrx_low, &irqcry_low); | ||
383 | sh7372_icr_to_irqcr(__raw_readl(ICR2A), &irqcrx_high, &irqcry_high); | ||
384 | __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR); | ||
385 | __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR2); | ||
386 | |||
387 | /* read IRQ16A -> IRQ31A mask */ | ||
388 | tmp = bitrev8(__raw_readb(INTMSK20A)); | ||
389 | tmp |= bitrev8(__raw_readb(INTMSK30A)) << 8; | ||
390 | |||
391 | /* setup WUPSMSK2 from clocks and external IRQ mask */ | ||
392 | msk2 = (~msk2 & 0x00030000) | tmp; | ||
393 | __raw_writel(msk2, WUPSMSK2); | ||
394 | |||
395 | /* propage level/edge trigger for external IRQ 16->31 */ | ||
396 | sh7372_icr_to_irqcr(__raw_readl(ICR3A), &irqcrx_low, &irqcry_low); | ||
397 | sh7372_icr_to_irqcr(__raw_readl(ICR4A), &irqcrx_high, &irqcry_high); | ||
398 | __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3); | ||
399 | __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4); | ||
212 | } | 400 | } |
401 | #endif | ||
213 | 402 | ||
214 | #ifdef CONFIG_CPU_IDLE | 403 | #ifdef CONFIG_CPU_IDLE |
404 | |||
215 | static void sh7372_cpuidle_setup(struct cpuidle_device *dev) | 405 | static void sh7372_cpuidle_setup(struct cpuidle_device *dev) |
216 | { | 406 | { |
217 | struct cpuidle_state *state; | 407 | struct cpuidle_state *state; |
@@ -239,9 +429,25 @@ static void sh7372_cpuidle_init(void) {} | |||
239 | #endif | 429 | #endif |
240 | 430 | ||
241 | #ifdef CONFIG_SUSPEND | 431 | #ifdef CONFIG_SUSPEND |
432 | |||
242 | static int sh7372_enter_suspend(suspend_state_t suspend_state) | 433 | static int sh7372_enter_suspend(suspend_state_t suspend_state) |
243 | { | 434 | { |
244 | sh7372_enter_core_standby(); | 435 | unsigned long msk, msk2; |
436 | |||
437 | /* check active clocks to determine potential wakeup sources */ | ||
438 | if (sh7372_a3sm_valid(&msk, &msk2)) { | ||
439 | |||
440 | /* convert INTC mask and sense to SYSC mask and sense */ | ||
441 | sh7372_setup_a3sm(msk, msk2); | ||
442 | |||
443 | /* enter A3SM sleep with PLLC0 off */ | ||
444 | pr_debug("entering A3SM\n"); | ||
445 | sh7372_enter_a3sm_common(0); | ||
446 | } else { | ||
447 | /* default to Core Standby that supports all wakeup sources */ | ||
448 | pr_debug("entering Core Standby\n"); | ||
449 | sh7372_enter_core_standby(); | ||
450 | } | ||
245 | return 0; | 451 | return 0; |
246 | } | 452 | } |
247 | 453 | ||
@@ -253,9 +459,6 @@ static void sh7372_suspend_init(void) | |||
253 | static void sh7372_suspend_init(void) {} | 459 | static void sh7372_suspend_init(void) {} |
254 | #endif | 460 | #endif |
255 | 461 | ||
256 | #define DBGREG1 0xe6100020 | ||
257 | #define DBGREG9 0xe6100040 | ||
258 | |||
259 | void __init sh7372_pm_init(void) | 462 | void __init sh7372_pm_init(void) |
260 | { | 463 | { |
261 | /* enable DBG hardware block to kick SYSC */ | 464 | /* enable DBG hardware block to kick SYSC */ |
@@ -263,6 +466,9 @@ void __init sh7372_pm_init(void) | |||
263 | __raw_writel(0x0000a501, DBGREG9); | 466 | __raw_writel(0x0000a501, DBGREG9); |
264 | __raw_writel(0x00000000, DBGREG1); | 467 | __raw_writel(0x00000000, DBGREG1); |
265 | 468 | ||
469 | /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */ | ||
470 | __raw_writel(0, PDNSEL); | ||
471 | |||
266 | sh7372_suspend_init(); | 472 | sh7372_suspend_init(); |
267 | sh7372_cpuidle_init(); | 473 | sh7372_cpuidle_init(); |
268 | } | 474 | } |
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c index 6ec454e1e063..bd5c6a3b8c55 100644 --- a/arch/arm/mach-shmobile/pm_runtime.c +++ b/arch/arm/mach-shmobile/pm_runtime.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/pm_runtime.h> | 16 | #include <linux/pm_runtime.h> |
17 | #include <linux/pm_domain.h> | 17 | #include <linux/pm_domain.h> |
18 | #include <linux/pm_clock.h> | ||
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
20 | #include <linux/sh_clk.h> | 21 | #include <linux/sh_clk.h> |
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 2d9b1b1a2538..2380389e6ac5 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/sh_dma.h> | 30 | #include <linux/sh_dma.h> |
31 | #include <linux/sh_intc.h> | 31 | #include <linux/sh_intc.h> |
32 | #include <linux/sh_timer.h> | 32 | #include <linux/sh_timer.h> |
33 | #include <linux/pm_domain.h> | ||
33 | #include <mach/hardware.h> | 34 | #include <mach/hardware.h> |
34 | #include <mach/sh7372.h> | 35 | #include <mach/sh7372.h> |
35 | #include <asm/mach-types.h> | 36 | #include <asm/mach-types.h> |
@@ -990,9 +991,14 @@ void __init sh7372_add_standard_devices(void) | |||
990 | sh7372_init_pm_domain(&sh7372_a4lc); | 991 | sh7372_init_pm_domain(&sh7372_a4lc); |
991 | sh7372_init_pm_domain(&sh7372_a4mp); | 992 | sh7372_init_pm_domain(&sh7372_a4mp); |
992 | sh7372_init_pm_domain(&sh7372_d4); | 993 | sh7372_init_pm_domain(&sh7372_d4); |
994 | sh7372_init_pm_domain(&sh7372_a4r); | ||
993 | sh7372_init_pm_domain(&sh7372_a3rv); | 995 | sh7372_init_pm_domain(&sh7372_a3rv); |
994 | sh7372_init_pm_domain(&sh7372_a3ri); | 996 | sh7372_init_pm_domain(&sh7372_a3ri); |
995 | sh7372_init_pm_domain(&sh7372_a3sg); | 997 | sh7372_init_pm_domain(&sh7372_a3sg); |
998 | sh7372_init_pm_domain(&sh7372_a3sp); | ||
999 | |||
1000 | sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv); | ||
1001 | sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc); | ||
996 | 1002 | ||
997 | platform_add_devices(sh7372_early_devices, | 1003 | platform_add_devices(sh7372_early_devices, |
998 | ARRAY_SIZE(sh7372_early_devices)); | 1004 | ARRAY_SIZE(sh7372_early_devices)); |
@@ -1003,6 +1009,25 @@ void __init sh7372_add_standard_devices(void) | |||
1003 | sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device); | 1009 | sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device); |
1004 | sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device); | 1010 | sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device); |
1005 | sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device); | 1011 | sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device); |
1012 | sh7372_add_device_to_domain(&sh7372_a3sp, &scif0_device); | ||
1013 | sh7372_add_device_to_domain(&sh7372_a3sp, &scif1_device); | ||
1014 | sh7372_add_device_to_domain(&sh7372_a3sp, &scif2_device); | ||
1015 | sh7372_add_device_to_domain(&sh7372_a3sp, &scif3_device); | ||
1016 | sh7372_add_device_to_domain(&sh7372_a3sp, &scif4_device); | ||
1017 | sh7372_add_device_to_domain(&sh7372_a3sp, &scif5_device); | ||
1018 | sh7372_add_device_to_domain(&sh7372_a3sp, &scif6_device); | ||
1019 | sh7372_add_device_to_domain(&sh7372_a3sp, &iic1_device); | ||
1020 | sh7372_add_device_to_domain(&sh7372_a3sp, &dma0_device); | ||
1021 | sh7372_add_device_to_domain(&sh7372_a3sp, &dma1_device); | ||
1022 | sh7372_add_device_to_domain(&sh7372_a3sp, &dma2_device); | ||
1023 | sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma0_device); | ||
1024 | sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma1_device); | ||
1025 | sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device); | ||
1026 | sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device); | ||
1027 | sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device); | ||
1028 | sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device); | ||
1029 | sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device); | ||
1030 | sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device); | ||
1006 | } | 1031 | } |
1007 | 1032 | ||
1008 | void __init sh7372_add_early_devices(void) | 1033 | void __init sh7372_add_early_devices(void) |
diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S index d37d3ca4d18f..f3ab3c5810ea 100644 --- a/arch/arm/mach-shmobile/sleep-sh7372.S +++ b/arch/arm/mach-shmobile/sleep-sh7372.S | |||
@@ -30,58 +30,20 @@ | |||
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/linkage.h> | 32 | #include <linux/linkage.h> |
33 | #include <linux/init.h> | ||
34 | #include <asm/memory.h> | ||
33 | #include <asm/assembler.h> | 35 | #include <asm/assembler.h> |
34 | 36 | ||
35 | #define SMFRAM 0xe6a70000 | 37 | #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) |
36 | 38 | .align 12 | |
37 | .align | 39 | .text |
38 | kernel_flush: | 40 | .global sh7372_resume_core_standby_a3sm |
39 | .word v7_flush_dcache_all | 41 | sh7372_resume_core_standby_a3sm: |
40 | 42 | ldr pc, 1f | |
41 | .align 3 | 43 | 1: .long cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET |
42 | ENTRY(sh7372_cpu_suspend) | ||
43 | stmfd sp!, {r0-r12, lr} @ save registers on stack | ||
44 | |||
45 | ldr r8, =SMFRAM | ||
46 | |||
47 | mov r4, sp @ Store sp | ||
48 | mrs r5, spsr @ Store spsr | ||
49 | mov r6, lr @ Store lr | ||
50 | stmia r8!, {r4-r6} | ||
51 | |||
52 | mrc p15, 0, r4, c1, c0, 2 @ Coprocessor access control register | ||
53 | mrc p15, 0, r5, c2, c0, 0 @ TTBR0 | ||
54 | mrc p15, 0, r6, c2, c0, 1 @ TTBR1 | ||
55 | mrc p15, 0, r7, c2, c0, 2 @ TTBCR | ||
56 | stmia r8!, {r4-r7} | ||
57 | |||
58 | mrc p15, 0, r4, c3, c0, 0 @ Domain access Control Register | ||
59 | mrc p15, 0, r5, c10, c2, 0 @ PRRR | ||
60 | mrc p15, 0, r6, c10, c2, 1 @ NMRR | ||
61 | stmia r8!,{r4-r6} | ||
62 | |||
63 | mrc p15, 0, r4, c13, c0, 1 @ Context ID | ||
64 | mrc p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID | ||
65 | mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address | ||
66 | mrs r7, cpsr @ Store current cpsr | ||
67 | stmia r8!, {r4-r7} | ||
68 | |||
69 | mrc p15, 0, r4, c1, c0, 0 @ save control register | ||
70 | stmia r8!, {r4} | ||
71 | |||
72 | /* | ||
73 | * jump out to kernel flush routine | ||
74 | * - reuse that code is better | ||
75 | * - it executes in a cached space so is faster than refetch per-block | ||
76 | * - should be faster and will change with kernel | ||
77 | * - 'might' have to copy address, load and jump to it | ||
78 | * Flush all data from the L1 data cache before disabling | ||
79 | * SCTLR.C bit. | ||
80 | */ | ||
81 | ldr r1, kernel_flush | ||
82 | mov lr, pc | ||
83 | bx r1 | ||
84 | 44 | ||
45 | .global sh7372_do_idle_a3sm | ||
46 | sh7372_do_idle_a3sm: | ||
85 | /* | 47 | /* |
86 | * Clear the SCTLR.C bit to prevent further data cache | 48 | * Clear the SCTLR.C bit to prevent further data cache |
87 | * allocation. Clearing SCTLR.C would make all the data accesses | 49 | * allocation. Clearing SCTLR.C would make all the data accesses |
@@ -92,10 +54,13 @@ ENTRY(sh7372_cpu_suspend) | |||
92 | mcr p15, 0, r0, c1, c0, 0 | 54 | mcr p15, 0, r0, c1, c0, 0 |
93 | isb | 55 | isb |
94 | 56 | ||
57 | /* disable L2 cache in the aux control register */ | ||
58 | mrc p15, 0, r10, c1, c0, 1 | ||
59 | bic r10, r10, #2 | ||
60 | mcr p15, 0, r10, c1, c0, 1 | ||
61 | |||
95 | /* | 62 | /* |
96 | * Invalidate L1 data cache. Even though only invalidate is | 63 | * Invalidate data cache again. |
97 | * necessary exported flush API is used here. Doing clean | ||
98 | * on already clean cache would be almost NOP. | ||
99 | */ | 64 | */ |
100 | ldr r1, kernel_flush | 65 | ldr r1, kernel_flush |
101 | blx r1 | 66 | blx r1 |
@@ -115,146 +80,16 @@ ENTRY(sh7372_cpu_suspend) | |||
115 | dsb | 80 | dsb |
116 | dmb | 81 | dmb |
117 | 82 | ||
118 | /* | 83 | #define SPDCR 0xe6180008 |
119 | * =================================== | 84 | #define A3SM (1 << 12) |
120 | * == WFI instruction => Enter idle == | ||
121 | * =================================== | ||
122 | */ | ||
123 | wfi @ wait for interrupt | ||
124 | |||
125 | /* | ||
126 | * =================================== | ||
127 | * == Resume path for non-OFF modes == | ||
128 | * =================================== | ||
129 | */ | ||
130 | mrc p15, 0, r0, c1, c0, 0 | ||
131 | tst r0, #(1 << 2) @ Check C bit enabled? | ||
132 | orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared | ||
133 | mcreq p15, 0, r0, c1, c0, 0 | ||
134 | isb | ||
135 | |||
136 | /* | ||
137 | * =================================== | ||
138 | * == Exit point from non-OFF modes == | ||
139 | * =================================== | ||
140 | */ | ||
141 | ldmfd sp!, {r0-r12, pc} @ restore regs and return | ||
142 | 85 | ||
143 | .pool | 86 | /* A3SM power down */ |
87 | ldr r0, =SPDCR | ||
88 | ldr r1, =A3SM | ||
89 | str r1, [r0] | ||
90 | 1: | ||
91 | b 1b | ||
144 | 92 | ||
145 | .align 12 | 93 | kernel_flush: |
146 | .text | 94 | .word v7_flush_dcache_all |
147 | .global sh7372_cpu_resume | 95 | #endif |
148 | sh7372_cpu_resume: | ||
149 | |||
150 | mov r1, #0 | ||
151 | /* | ||
152 | * Invalidate all instruction caches to PoU | ||
153 | * and flush branch target cache | ||
154 | */ | ||
155 | mcr p15, 0, r1, c7, c5, 0 | ||
156 | |||
157 | ldr r3, =SMFRAM | ||
158 | |||
159 | ldmia r3!, {r4-r6} | ||
160 | mov sp, r4 @ Restore sp | ||
161 | msr spsr_cxsf, r5 @ Restore spsr | ||
162 | mov lr, r6 @ Restore lr | ||
163 | |||
164 | ldmia r3!, {r4-r7} | ||
165 | mcr p15, 0, r4, c1, c0, 2 @ Coprocessor access Control Register | ||
166 | mcr p15, 0, r5, c2, c0, 0 @ TTBR0 | ||
167 | mcr p15, 0, r6, c2, c0, 1 @ TTBR1 | ||
168 | mcr p15, 0, r7, c2, c0, 2 @ TTBCR | ||
169 | |||
170 | ldmia r3!,{r4-r6} | ||
171 | mcr p15, 0, r4, c3, c0, 0 @ Domain access Control Register | ||
172 | mcr p15, 0, r5, c10, c2, 0 @ PRRR | ||
173 | mcr p15, 0, r6, c10, c2, 1 @ NMRR | ||
174 | |||
175 | ldmia r3!,{r4-r7} | ||
176 | mcr p15, 0, r4, c13, c0, 1 @ Context ID | ||
177 | mcr p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID | ||
178 | mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address | ||
179 | msr cpsr, r7 @ store cpsr | ||
180 | |||
181 | /* Starting to enable MMU here */ | ||
182 | mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl | ||
183 | /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */ | ||
184 | and r7, #0x7 | ||
185 | cmp r7, #0x0 | ||
186 | beq usettbr0 | ||
187 | ttbr_error: | ||
188 | /* | ||
189 | * More work needs to be done to support N[0:2] value other than 0 | ||
190 | * So looping here so that the error can be detected | ||
191 | */ | ||
192 | b ttbr_error | ||
193 | |||
194 | .align | ||
195 | cache_pred_disable_mask: | ||
196 | .word 0xFFFFE7FB | ||
197 | ttbrbit_mask: | ||
198 | .word 0xFFFFC000 | ||
199 | table_index_mask: | ||
200 | .word 0xFFF00000 | ||
201 | table_entry: | ||
202 | .word 0x00000C02 | ||
203 | usettbr0: | ||
204 | |||
205 | mrc p15, 0, r2, c2, c0, 0 | ||
206 | ldr r5, ttbrbit_mask | ||
207 | and r2, r5 | ||
208 | mov r4, pc | ||
209 | ldr r5, table_index_mask | ||
210 | and r4, r5 @ r4 = 31 to 20 bits of pc | ||
211 | /* Extract the value to be written to table entry */ | ||
212 | ldr r6, table_entry | ||
213 | /* r6 has the value to be written to table entry */ | ||
214 | add r6, r6, r4 | ||
215 | /* Getting the address of table entry to modify */ | ||
216 | lsr r4, #18 | ||
217 | /* r2 has the location which needs to be modified */ | ||
218 | add r2, r4 | ||
219 | ldr r4, [r2] | ||
220 | str r6, [r2] /* modify the table entry */ | ||
221 | |||
222 | mov r7, r6 | ||
223 | mov r5, r2 | ||
224 | mov r6, r4 | ||
225 | /* r5 = original page table address */ | ||
226 | /* r6 = original page table data */ | ||
227 | |||
228 | mov r0, #0 | ||
229 | mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer | ||
230 | mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array | ||
231 | mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB | ||
232 | mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB | ||
233 | |||
234 | /* | ||
235 | * Restore control register. This enables the MMU. | ||
236 | * The caches and prediction are not enabled here, they | ||
237 | * will be enabled after restoring the MMU table entry. | ||
238 | */ | ||
239 | ldmia r3!, {r4} | ||
240 | stmia r3!, {r5} /* save original page table address */ | ||
241 | stmia r3!, {r6} /* save original page table data */ | ||
242 | stmia r3!, {r7} /* save modified page table data */ | ||
243 | |||
244 | ldr r2, cache_pred_disable_mask | ||
245 | and r4, r2 | ||
246 | mcr p15, 0, r4, c1, c0, 0 | ||
247 | dsb | ||
248 | isb | ||
249 | |||
250 | ldr r0, =restoremmu_on | ||
251 | bx r0 | ||
252 | |||
253 | /* | ||
254 | * ============================== | ||
255 | * == Exit point from OFF mode == | ||
256 | * ============================== | ||
257 | */ | ||
258 | restoremmu_on: | ||
259 | |||
260 | ldmfd sp!, {r0-r12, pc} @ restore regs and return | ||
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 3ffdbc92ba82..be1ade76ccc8 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c | |||
@@ -74,6 +74,8 @@ void __cpuinit sh73a0_secondary_init(unsigned int cpu) | |||
74 | 74 | ||
75 | int __cpuinit sh73a0_boot_secondary(unsigned int cpu) | 75 | int __cpuinit sh73a0_boot_secondary(unsigned int cpu) |
76 | { | 76 | { |
77 | cpu = cpu_logical_map(cpu); | ||
78 | |||
77 | /* enable cache coherency */ | 79 | /* enable cache coherency */ |
78 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); | 80 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); |
79 | 81 | ||
@@ -87,6 +89,8 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu) | |||
87 | 89 | ||
88 | void __init sh73a0_smp_prepare_cpus(void) | 90 | void __init sh73a0_smp_prepare_cpus(void) |
89 | { | 91 | { |
92 | int cpu = cpu_logical_map(0); | ||
93 | |||
90 | scu_enable(scu_base_addr()); | 94 | scu_enable(scu_base_addr()); |
91 | 95 | ||
92 | /* Map the reset vector (in headsmp.S) */ | 96 | /* Map the reset vector (in headsmp.S) */ |
@@ -94,5 +98,5 @@ void __init sh73a0_smp_prepare_cpus(void) | |||
94 | __raw_writel(__pa(shmobile_secondary_vector), __io(SBAR)); | 98 | __raw_writel(__pa(shmobile_secondary_vector), __io(SBAR)); |
95 | 99 | ||
96 | /* enable cache coherency on CPU0 */ | 100 | /* enable cache coherency on CPU0 */ |
97 | modify_scu_cpu_psr(0, 3 << (0 * 8)); | 101 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); |
98 | } | 102 | } |