diff options
Diffstat (limited to 'arch')
327 files changed, 4330 insertions, 3377 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fac58916ade..a3fb23be87f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -2,6 +2,7 @@ config ARM | |||
2 | bool | 2 | bool |
3 | default y | 3 | default y |
4 | select HAVE_AOUT | 4 | select HAVE_AOUT |
5 | select HAVE_DMA_API_DEBUG | ||
5 | select HAVE_IDE | 6 | select HAVE_IDE |
6 | select HAVE_MEMBLOCK | 7 | select HAVE_MEMBLOCK |
7 | select RTC_LIB | 8 | select RTC_LIB |
@@ -24,6 +25,7 @@ config ARM | |||
24 | select PERF_USE_VMALLOC | 25 | select PERF_USE_VMALLOC |
25 | select HAVE_REGS_AND_STACK_ACCESS_API | 26 | select HAVE_REGS_AND_STACK_ACCESS_API |
26 | select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7)) | 27 | select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7)) |
28 | select HAVE_C_RECORDMCOUNT | ||
27 | help | 29 | help |
28 | The ARM series is a line of low-power-consumption RISC chip designs | 30 | The ARM series is a line of low-power-consumption RISC chip designs |
29 | licensed by ARM Ltd and targeted at embedded applications and | 31 | licensed by ARM Ltd and targeted at embedded applications and |
@@ -35,9 +37,15 @@ config ARM | |||
35 | config HAVE_PWM | 37 | config HAVE_PWM |
36 | bool | 38 | bool |
37 | 39 | ||
40 | config MIGHT_HAVE_PCI | ||
41 | bool | ||
42 | |||
38 | config SYS_SUPPORTS_APM_EMULATION | 43 | config SYS_SUPPORTS_APM_EMULATION |
39 | bool | 44 | bool |
40 | 45 | ||
46 | config HAVE_SCHED_CLOCK | ||
47 | bool | ||
48 | |||
41 | config GENERIC_GPIO | 49 | config GENERIC_GPIO |
42 | bool | 50 | bool |
43 | 51 | ||
@@ -222,7 +230,7 @@ config ARCH_INTEGRATOR | |||
222 | bool "ARM Ltd. Integrator family" | 230 | bool "ARM Ltd. Integrator family" |
223 | select ARM_AMBA | 231 | select ARM_AMBA |
224 | select ARCH_HAS_CPUFREQ | 232 | select ARCH_HAS_CPUFREQ |
225 | select COMMON_CLKDEV | 233 | select CLKDEV_LOOKUP |
226 | select ICST | 234 | select ICST |
227 | select GENERIC_CLOCKEVENTS | 235 | select GENERIC_CLOCKEVENTS |
228 | select PLAT_VERSATILE | 236 | select PLAT_VERSATILE |
@@ -232,7 +240,8 @@ config ARCH_INTEGRATOR | |||
232 | config ARCH_REALVIEW | 240 | config ARCH_REALVIEW |
233 | bool "ARM Ltd. RealView family" | 241 | bool "ARM Ltd. RealView family" |
234 | select ARM_AMBA | 242 | select ARM_AMBA |
235 | select COMMON_CLKDEV | 243 | select CLKDEV_LOOKUP |
244 | select HAVE_SCHED_CLOCK | ||
236 | select ICST | 245 | select ICST |
237 | select GENERIC_CLOCKEVENTS | 246 | select GENERIC_CLOCKEVENTS |
238 | select ARCH_WANT_OPTIONAL_GPIOLIB | 247 | select ARCH_WANT_OPTIONAL_GPIOLIB |
@@ -246,7 +255,8 @@ config ARCH_VERSATILE | |||
246 | bool "ARM Ltd. Versatile family" | 255 | bool "ARM Ltd. Versatile family" |
247 | select ARM_AMBA | 256 | select ARM_AMBA |
248 | select ARM_VIC | 257 | select ARM_VIC |
249 | select COMMON_CLKDEV | 258 | select CLKDEV_LOOKUP |
259 | select HAVE_SCHED_CLOCK | ||
250 | select ICST | 260 | select ICST |
251 | select GENERIC_CLOCKEVENTS | 261 | select GENERIC_CLOCKEVENTS |
252 | select ARCH_WANT_OPTIONAL_GPIOLIB | 262 | select ARCH_WANT_OPTIONAL_GPIOLIB |
@@ -260,9 +270,10 @@ config ARCH_VEXPRESS | |||
260 | select ARCH_WANT_OPTIONAL_GPIOLIB | 270 | select ARCH_WANT_OPTIONAL_GPIOLIB |
261 | select ARM_AMBA | 271 | select ARM_AMBA |
262 | select ARM_TIMER_SP804 | 272 | select ARM_TIMER_SP804 |
263 | select COMMON_CLKDEV | 273 | select CLKDEV_LOOKUP |
264 | select GENERIC_CLOCKEVENTS | 274 | select GENERIC_CLOCKEVENTS |
265 | select HAVE_CLK | 275 | select HAVE_CLK |
276 | select HAVE_SCHED_CLOCK | ||
266 | select ICST | 277 | select ICST |
267 | select PLAT_VERSATILE | 278 | select PLAT_VERSATILE |
268 | help | 279 | help |
@@ -281,7 +292,7 @@ config ARCH_BCMRING | |||
281 | depends on MMU | 292 | depends on MMU |
282 | select CPU_V6 | 293 | select CPU_V6 |
283 | select ARM_AMBA | 294 | select ARM_AMBA |
284 | select COMMON_CLKDEV | 295 | select CLKDEV_LOOKUP |
285 | select GENERIC_CLOCKEVENTS | 296 | select GENERIC_CLOCKEVENTS |
286 | select ARCH_WANT_OPTIONAL_GPIOLIB | 297 | select ARCH_WANT_OPTIONAL_GPIOLIB |
287 | help | 298 | help |
@@ -299,6 +310,7 @@ config ARCH_CNS3XXX | |||
299 | select CPU_V6 | 310 | select CPU_V6 |
300 | select GENERIC_CLOCKEVENTS | 311 | select GENERIC_CLOCKEVENTS |
301 | select ARM_GIC | 312 | select ARM_GIC |
313 | select MIGHT_HAVE_PCI | ||
302 | select PCI_DOMAINS if PCI | 314 | select PCI_DOMAINS if PCI |
303 | help | 315 | help |
304 | Support for Cavium Networks CNS3XXX platform. | 316 | Support for Cavium Networks CNS3XXX platform. |
@@ -328,7 +340,7 @@ config ARCH_EP93XX | |||
328 | select CPU_ARM920T | 340 | select CPU_ARM920T |
329 | select ARM_AMBA | 341 | select ARM_AMBA |
330 | select ARM_VIC | 342 | select ARM_VIC |
331 | select COMMON_CLKDEV | 343 | select CLKDEV_LOOKUP |
332 | select ARCH_REQUIRE_GPIOLIB | 344 | select ARCH_REQUIRE_GPIOLIB |
333 | select ARCH_HAS_HOLES_MEMORYMODEL | 345 | select ARCH_HAS_HOLES_MEMORYMODEL |
334 | select ARCH_USES_GETTIMEOFFSET | 346 | select ARCH_USES_GETTIMEOFFSET |
@@ -348,7 +360,7 @@ config ARCH_MXC | |||
348 | bool "Freescale MXC/iMX-based" | 360 | bool "Freescale MXC/iMX-based" |
349 | select GENERIC_CLOCKEVENTS | 361 | select GENERIC_CLOCKEVENTS |
350 | select ARCH_REQUIRE_GPIOLIB | 362 | select ARCH_REQUIRE_GPIOLIB |
351 | select COMMON_CLKDEV | 363 | select CLKDEV_LOOKUP |
352 | help | 364 | help |
353 | Support for Freescale MXC/iMX-based family of processors | 365 | Support for Freescale MXC/iMX-based family of processors |
354 | 366 | ||
@@ -363,7 +375,7 @@ config ARCH_MXS | |||
363 | config ARCH_STMP3XXX | 375 | config ARCH_STMP3XXX |
364 | bool "Freescale STMP3xxx" | 376 | bool "Freescale STMP3xxx" |
365 | select CPU_ARM926T | 377 | select CPU_ARM926T |
366 | select COMMON_CLKDEV | 378 | select CLKDEV_LOOKUP |
367 | select ARCH_REQUIRE_GPIOLIB | 379 | select ARCH_REQUIRE_GPIOLIB |
368 | select GENERIC_CLOCKEVENTS | 380 | select GENERIC_CLOCKEVENTS |
369 | select USB_ARCH_HAS_EHCI | 381 | select USB_ARCH_HAS_EHCI |
@@ -442,6 +454,8 @@ config ARCH_IXP4XX | |||
442 | select CPU_XSCALE | 454 | select CPU_XSCALE |
443 | select GENERIC_GPIO | 455 | select GENERIC_GPIO |
444 | select GENERIC_CLOCKEVENTS | 456 | select GENERIC_CLOCKEVENTS |
457 | select HAVE_SCHED_CLOCK | ||
458 | select MIGHT_HAVE_PCI | ||
445 | select DMABOUNCE if PCI | 459 | select DMABOUNCE if PCI |
446 | help | 460 | help |
447 | Support for Intel's IXP4XX (XScale) family of processors. | 461 | Support for Intel's IXP4XX (XScale) family of processors. |
@@ -481,7 +495,7 @@ config ARCH_LPC32XX | |||
481 | select HAVE_IDE | 495 | select HAVE_IDE |
482 | select ARM_AMBA | 496 | select ARM_AMBA |
483 | select USB_ARCH_HAS_OHCI | 497 | select USB_ARCH_HAS_OHCI |
484 | select COMMON_CLKDEV | 498 | select CLKDEV_LOOKUP |
485 | select GENERIC_TIME | 499 | select GENERIC_TIME |
486 | select GENERIC_CLOCKEVENTS | 500 | select GENERIC_CLOCKEVENTS |
487 | help | 501 | help |
@@ -515,8 +529,9 @@ config ARCH_MMP | |||
515 | bool "Marvell PXA168/910/MMP2" | 529 | bool "Marvell PXA168/910/MMP2" |
516 | depends on MMU | 530 | depends on MMU |
517 | select ARCH_REQUIRE_GPIOLIB | 531 | select ARCH_REQUIRE_GPIOLIB |
518 | select COMMON_CLKDEV | 532 | select CLKDEV_LOOKUP |
519 | select GENERIC_CLOCKEVENTS | 533 | select GENERIC_CLOCKEVENTS |
534 | select HAVE_SCHED_CLOCK | ||
520 | select TICK_ONESHOT | 535 | select TICK_ONESHOT |
521 | select PLAT_PXA | 536 | select PLAT_PXA |
522 | select SPARSE_IRQ | 537 | select SPARSE_IRQ |
@@ -548,7 +563,7 @@ config ARCH_W90X900 | |||
548 | bool "Nuvoton W90X900 CPU" | 563 | bool "Nuvoton W90X900 CPU" |
549 | select CPU_ARM926T | 564 | select CPU_ARM926T |
550 | select ARCH_REQUIRE_GPIOLIB | 565 | select ARCH_REQUIRE_GPIOLIB |
551 | select COMMON_CLKDEV | 566 | select CLKDEV_LOOKUP |
552 | select GENERIC_CLOCKEVENTS | 567 | select GENERIC_CLOCKEVENTS |
553 | help | 568 | help |
554 | Support for Nuvoton (Winbond logic dept.) ARM9 processor, | 569 | Support for Nuvoton (Winbond logic dept.) ARM9 processor, |
@@ -562,18 +577,19 @@ config ARCH_W90X900 | |||
562 | config ARCH_NUC93X | 577 | config ARCH_NUC93X |
563 | bool "Nuvoton NUC93X CPU" | 578 | bool "Nuvoton NUC93X CPU" |
564 | select CPU_ARM926T | 579 | select CPU_ARM926T |
565 | select COMMON_CLKDEV | 580 | select CLKDEV_LOOKUP |
566 | help | 581 | help |
567 | Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a | 582 | Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a |
568 | low-power and high performance MPEG-4/JPEG multimedia controller chip. | 583 | low-power and high performance MPEG-4/JPEG multimedia controller chip. |
569 | 584 | ||
570 | config ARCH_TEGRA | 585 | config ARCH_TEGRA |
571 | bool "NVIDIA Tegra" | 586 | bool "NVIDIA Tegra" |
587 | select CLKDEV_LOOKUP | ||
572 | select GENERIC_TIME | 588 | select GENERIC_TIME |
573 | select GENERIC_CLOCKEVENTS | 589 | select GENERIC_CLOCKEVENTS |
574 | select GENERIC_GPIO | 590 | select GENERIC_GPIO |
575 | select HAVE_CLK | 591 | select HAVE_CLK |
576 | select COMMON_CLKDEV | 592 | select HAVE_SCHED_CLOCK |
577 | select ARCH_HAS_BARRIERS if CACHE_L2X0 | 593 | select ARCH_HAS_BARRIERS if CACHE_L2X0 |
578 | select ARCH_HAS_CPUFREQ | 594 | select ARCH_HAS_CPUFREQ |
579 | help | 595 | help |
@@ -583,7 +599,7 @@ config ARCH_TEGRA | |||
583 | config ARCH_PNX4008 | 599 | config ARCH_PNX4008 |
584 | bool "Philips Nexperia PNX4008 Mobile" | 600 | bool "Philips Nexperia PNX4008 Mobile" |
585 | select CPU_ARM926T | 601 | select CPU_ARM926T |
586 | select COMMON_CLKDEV | 602 | select CLKDEV_LOOKUP |
587 | select ARCH_USES_GETTIMEOFFSET | 603 | select ARCH_USES_GETTIMEOFFSET |
588 | help | 604 | help |
589 | This enables support for Philips PNX4008 mobile platform. | 605 | This enables support for Philips PNX4008 mobile platform. |
@@ -593,9 +609,10 @@ config ARCH_PXA | |||
593 | depends on MMU | 609 | depends on MMU |
594 | select ARCH_MTD_XIP | 610 | select ARCH_MTD_XIP |
595 | select ARCH_HAS_CPUFREQ | 611 | select ARCH_HAS_CPUFREQ |
596 | select COMMON_CLKDEV | 612 | select CLKDEV_LOOKUP |
597 | select ARCH_REQUIRE_GPIOLIB | 613 | select ARCH_REQUIRE_GPIOLIB |
598 | select GENERIC_CLOCKEVENTS | 614 | select GENERIC_CLOCKEVENTS |
615 | select HAVE_SCHED_CLOCK | ||
599 | select TICK_ONESHOT | 616 | select TICK_ONESHOT |
600 | select PLAT_PXA | 617 | select PLAT_PXA |
601 | select SPARSE_IRQ | 618 | select SPARSE_IRQ |
@@ -644,6 +661,7 @@ config ARCH_SA1100 | |||
644 | select CPU_FREQ | 661 | select CPU_FREQ |
645 | select GENERIC_CLOCKEVENTS | 662 | select GENERIC_CLOCKEVENTS |
646 | select HAVE_CLK | 663 | select HAVE_CLK |
664 | select HAVE_SCHED_CLOCK | ||
647 | select TICK_ONESHOT | 665 | select TICK_ONESHOT |
648 | select ARCH_REQUIRE_GPIOLIB | 666 | select ARCH_REQUIRE_GPIOLIB |
649 | help | 667 | help |
@@ -770,7 +788,7 @@ config ARCH_TCC_926 | |||
770 | bool "Telechips TCC ARM926-based systems" | 788 | bool "Telechips TCC ARM926-based systems" |
771 | select CPU_ARM926T | 789 | select CPU_ARM926T |
772 | select HAVE_CLK | 790 | select HAVE_CLK |
773 | select COMMON_CLKDEV | 791 | select CLKDEV_LOOKUP |
774 | select GENERIC_CLOCKEVENTS | 792 | select GENERIC_CLOCKEVENTS |
775 | help | 793 | help |
776 | Support for Telechips TCC ARM926-based systems. | 794 | Support for Telechips TCC ARM926-based systems. |
@@ -790,11 +808,12 @@ config ARCH_U300 | |||
790 | bool "ST-Ericsson U300 Series" | 808 | bool "ST-Ericsson U300 Series" |
791 | depends on MMU | 809 | depends on MMU |
792 | select CPU_ARM926T | 810 | select CPU_ARM926T |
811 | select HAVE_SCHED_CLOCK | ||
793 | select HAVE_TCM | 812 | select HAVE_TCM |
794 | select ARM_AMBA | 813 | select ARM_AMBA |
795 | select ARM_VIC | 814 | select ARM_VIC |
796 | select GENERIC_CLOCKEVENTS | 815 | select GENERIC_CLOCKEVENTS |
797 | select COMMON_CLKDEV | 816 | select CLKDEV_LOOKUP |
798 | select GENERIC_GPIO | 817 | select GENERIC_GPIO |
799 | help | 818 | help |
800 | Support for ST-Ericsson U300 series mobile platforms. | 819 | Support for ST-Ericsson U300 series mobile platforms. |
@@ -804,7 +823,7 @@ config ARCH_U8500 | |||
804 | select CPU_V7 | 823 | select CPU_V7 |
805 | select ARM_AMBA | 824 | select ARM_AMBA |
806 | select GENERIC_CLOCKEVENTS | 825 | select GENERIC_CLOCKEVENTS |
807 | select COMMON_CLKDEV | 826 | select CLKDEV_LOOKUP |
808 | select ARCH_REQUIRE_GPIOLIB | 827 | select ARCH_REQUIRE_GPIOLIB |
809 | select ARCH_HAS_CPUFREQ | 828 | select ARCH_HAS_CPUFREQ |
810 | help | 829 | help |
@@ -815,7 +834,7 @@ config ARCH_NOMADIK | |||
815 | select ARM_AMBA | 834 | select ARM_AMBA |
816 | select ARM_VIC | 835 | select ARM_VIC |
817 | select CPU_ARM926T | 836 | select CPU_ARM926T |
818 | select COMMON_CLKDEV | 837 | select CLKDEV_LOOKUP |
819 | select GENERIC_CLOCKEVENTS | 838 | select GENERIC_CLOCKEVENTS |
820 | select ARCH_REQUIRE_GPIOLIB | 839 | select ARCH_REQUIRE_GPIOLIB |
821 | help | 840 | help |
@@ -827,7 +846,7 @@ config ARCH_DAVINCI | |||
827 | select ARCH_REQUIRE_GPIOLIB | 846 | select ARCH_REQUIRE_GPIOLIB |
828 | select ZONE_DMA | 847 | select ZONE_DMA |
829 | select HAVE_IDE | 848 | select HAVE_IDE |
830 | select COMMON_CLKDEV | 849 | select CLKDEV_LOOKUP |
831 | select GENERIC_ALLOCATOR | 850 | select GENERIC_ALLOCATOR |
832 | select ARCH_HAS_HOLES_MEMORYMODEL | 851 | select ARCH_HAS_HOLES_MEMORYMODEL |
833 | help | 852 | help |
@@ -839,6 +858,7 @@ config ARCH_OMAP | |||
839 | select ARCH_REQUIRE_GPIOLIB | 858 | select ARCH_REQUIRE_GPIOLIB |
840 | select ARCH_HAS_CPUFREQ | 859 | select ARCH_HAS_CPUFREQ |
841 | select GENERIC_CLOCKEVENTS | 860 | select GENERIC_CLOCKEVENTS |
861 | select HAVE_SCHED_CLOCK | ||
842 | select ARCH_HAS_HOLES_MEMORYMODEL | 862 | select ARCH_HAS_HOLES_MEMORYMODEL |
843 | help | 863 | help |
844 | Support for TI's OMAP platform (OMAP1/2/3/4). | 864 | Support for TI's OMAP platform (OMAP1/2/3/4). |
@@ -847,7 +867,7 @@ config PLAT_SPEAR | |||
847 | bool "ST SPEAr" | 867 | bool "ST SPEAr" |
848 | select ARM_AMBA | 868 | select ARM_AMBA |
849 | select ARCH_REQUIRE_GPIOLIB | 869 | select ARCH_REQUIRE_GPIOLIB |
850 | select COMMON_CLKDEV | 870 | select CLKDEV_LOOKUP |
851 | select GENERIC_CLOCKEVENTS | 871 | select GENERIC_CLOCKEVENTS |
852 | select HAVE_CLK | 872 | select HAVE_CLK |
853 | help | 873 | help |
@@ -994,9 +1014,11 @@ config ARCH_ACORN | |||
994 | config PLAT_IOP | 1014 | config PLAT_IOP |
995 | bool | 1015 | bool |
996 | select GENERIC_CLOCKEVENTS | 1016 | select GENERIC_CLOCKEVENTS |
1017 | select HAVE_SCHED_CLOCK | ||
997 | 1018 | ||
998 | config PLAT_ORION | 1019 | config PLAT_ORION |
999 | bool | 1020 | bool |
1021 | select HAVE_SCHED_CLOCK | ||
1000 | 1022 | ||
1001 | config PLAT_PXA | 1023 | config PLAT_PXA |
1002 | bool | 1024 | bool |
@@ -1029,6 +1051,11 @@ config CPU_HAS_PMU | |||
1029 | default y | 1051 | default y |
1030 | bool | 1052 | bool |
1031 | 1053 | ||
1054 | config MULTI_IRQ_HANDLER | ||
1055 | bool | ||
1056 | help | ||
1057 | Allow each machine to specify it's own IRQ handler at run time. | ||
1058 | |||
1032 | if !MMU | 1059 | if !MMU |
1033 | source "arch/arm/Kconfig-nommu" | 1060 | source "arch/arm/Kconfig-nommu" |
1034 | endif | 1061 | endif |
@@ -1176,7 +1203,7 @@ config ISA_DMA_API | |||
1176 | bool | 1203 | bool |
1177 | 1204 | ||
1178 | config PCI | 1205 | config PCI |
1179 | bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX | 1206 | bool "PCI support" if MIGHT_HAVE_PCI |
1180 | help | 1207 | help |
1181 | Find out whether you have a PCI motherboard. PCI is the name of a | 1208 | Find out whether you have a PCI motherboard. PCI is the name of a |
1182 | bus system, i.e. the way the CPU talks to the other stuff inside | 1209 | bus system, i.e. the way the CPU talks to the other stuff inside |
@@ -1187,6 +1214,12 @@ config PCI_DOMAINS | |||
1187 | bool | 1214 | bool |
1188 | depends on PCI | 1215 | depends on PCI |
1189 | 1216 | ||
1217 | config PCI_NANOENGINE | ||
1218 | bool "BSE nanoEngine PCI support" | ||
1219 | depends on SA1100_NANOENGINE | ||
1220 | help | ||
1221 | Enable PCI on the BSE nanoEngine board. | ||
1222 | |||
1190 | config PCI_SYSCALL | 1223 | config PCI_SYSCALL |
1191 | def_bool PCI | 1224 | def_bool PCI |
1192 | 1225 | ||
@@ -1242,7 +1275,7 @@ config SMP | |||
1242 | config SMP_ON_UP | 1275 | config SMP_ON_UP |
1243 | bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" | 1276 | bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" |
1244 | depends on EXPERIMENTAL | 1277 | depends on EXPERIMENTAL |
1245 | depends on SMP && !XIP && !THUMB2_KERNEL | 1278 | depends on SMP && !XIP |
1246 | default y | 1279 | default y |
1247 | help | 1280 | help |
1248 | SMP kernels contain instructions which fail on non-SMP processors. | 1281 | SMP kernels contain instructions which fail on non-SMP processors. |
@@ -1261,6 +1294,7 @@ config HAVE_ARM_SCU | |||
1261 | config HAVE_ARM_TWD | 1294 | config HAVE_ARM_TWD |
1262 | bool | 1295 | bool |
1263 | depends on SMP | 1296 | depends on SMP |
1297 | select TICK_ONESHOT | ||
1264 | help | 1298 | help |
1265 | This options enables support for the ARM timer and watchdog unit | 1299 | This options enables support for the ARM timer and watchdog unit |
1266 | 1300 | ||
@@ -1324,7 +1358,7 @@ config HZ | |||
1324 | default 100 | 1358 | default 100 |
1325 | 1359 | ||
1326 | config THUMB2_KERNEL | 1360 | config THUMB2_KERNEL |
1327 | bool "Compile the kernel in Thumb-2 mode" | 1361 | bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)" |
1328 | depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL | 1362 | depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL |
1329 | select AEABI | 1363 | select AEABI |
1330 | select ARM_ASM_UNIFIED | 1364 | select ARM_ASM_UNIFIED |
@@ -1538,6 +1572,7 @@ config SECCOMP | |||
1538 | 1572 | ||
1539 | config CC_STACKPROTECTOR | 1573 | config CC_STACKPROTECTOR |
1540 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" | 1574 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" |
1575 | depends on EXPERIMENTAL | ||
1541 | help | 1576 | help |
1542 | This option turns on the -fstack-protector GCC feature. This | 1577 | This option turns on the -fstack-protector GCC feature. This |
1543 | feature puts, at the beginning of functions, a canary value on | 1578 | feature puts, at the beginning of functions, a canary value on |
@@ -1664,6 +1699,19 @@ config ATAGS_PROC | |||
1664 | Should the atags used to boot the kernel be exported in an "atags" | 1699 | Should the atags used to boot the kernel be exported in an "atags" |
1665 | file in procfs. Useful with kexec. | 1700 | file in procfs. Useful with kexec. |
1666 | 1701 | ||
1702 | config CRASH_DUMP | ||
1703 | bool "Build kdump crash kernel (EXPERIMENTAL)" | ||
1704 | depends on EXPERIMENTAL | ||
1705 | help | ||
1706 | Generate crash dump after being started by kexec. This should | ||
1707 | be normally only set in special crash dump kernels which are | ||
1708 | loaded in the main kernel with kexec-tools into a specially | ||
1709 | reserved region and then later executed after a crash by | ||
1710 | kdump/kexec. The crash dump kernel must be compiled to a | ||
1711 | memory address not used by the main kernel | ||
1712 | |||
1713 | For more details see Documentation/kdump/kdump.txt | ||
1714 | |||
1667 | config AUTO_ZRELADDR | 1715 | config AUTO_ZRELADDR |
1668 | bool "Auto calculation of the decompressed kernel image address" | 1716 | bool "Auto calculation of the decompressed kernel image address" |
1669 | depends on !ZBOOT_ROM && !ARCH_U300 | 1717 | depends on !ZBOOT_ROM && !ARCH_U300 |
@@ -1721,7 +1769,7 @@ config CPU_FREQ_S3C | |||
1721 | Internal configuration node for common cpufreq on Samsung SoC | 1769 | Internal configuration node for common cpufreq on Samsung SoC |
1722 | 1770 | ||
1723 | config CPU_FREQ_S3C24XX | 1771 | config CPU_FREQ_S3C24XX |
1724 | bool "CPUfreq driver for Samsung S3C24XX series CPUs" | 1772 | bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)" |
1725 | depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL | 1773 | depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL |
1726 | select CPU_FREQ_S3C | 1774 | select CPU_FREQ_S3C |
1727 | help | 1775 | help |
@@ -1733,7 +1781,7 @@ config CPU_FREQ_S3C24XX | |||
1733 | If in doubt, say N. | 1781 | If in doubt, say N. |
1734 | 1782 | ||
1735 | config CPU_FREQ_S3C24XX_PLL | 1783 | config CPU_FREQ_S3C24XX_PLL |
1736 | bool "Support CPUfreq changing of PLL frequency" | 1784 | bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)" |
1737 | depends on CPU_FREQ_S3C24XX && EXPERIMENTAL | 1785 | depends on CPU_FREQ_S3C24XX && EXPERIMENTAL |
1738 | help | 1786 | help |
1739 | Compile in support for changing the PLL frequency from the | 1787 | Compile in support for changing the PLL frequency from the |
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index eac62085f5b..494224a9b45 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
@@ -31,7 +31,7 @@ config FRAME_POINTER | |||
31 | reported is severely limited. | 31 | reported is severely limited. |
32 | 32 | ||
33 | config ARM_UNWIND | 33 | config ARM_UNWIND |
34 | bool "Enable stack unwinding support" | 34 | bool "Enable stack unwinding support (EXPERIMENTAL)" |
35 | depends on AEABI && EXPERIMENTAL | 35 | depends on AEABI && EXPERIMENTAL |
36 | default y | 36 | default y |
37 | help | 37 | help |
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 65a7c1c588a..0a8f748e506 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile | |||
@@ -45,6 +45,10 @@ else | |||
45 | endif | 45 | endif |
46 | endif | 46 | endif |
47 | 47 | ||
48 | ifeq ($(CONFIG_ARCH_SHMOBILE),y) | ||
49 | OBJS += head-shmobile.o | ||
50 | endif | ||
51 | |||
48 | # | 52 | # |
49 | # We now have a PIC decompressor implementation. Decompressors running | 53 | # We now have a PIC decompressor implementation. Decompressors running |
50 | # from RAM should not define ZTEXTADDR. Decompressors running directly | 54 | # from RAM should not define ZTEXTADDR. Decompressors running directly |
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S new file mode 100644 index 00000000000..30973b76e6a --- /dev/null +++ b/arch/arm/boot/compressed/head-shmobile.S | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * The head-file for SH-Mobile ARM platforms | ||
3 | * | ||
4 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
5 | * Simon Horman <horms@verge.net.au> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #ifdef CONFIG_ZBOOT_ROM | ||
22 | |||
23 | .section ".start", "ax" | ||
24 | |||
25 | /* load board-specific initialization code */ | ||
26 | #include <mach/zboot.h> | ||
27 | |||
28 | b 1f | ||
29 | __atags:@ tag #1 | ||
30 | .long 12 @ tag->hdr.size = tag_size(tag_core); | ||
31 | .long 0x54410001 @ tag->hdr.tag = ATAG_CORE; | ||
32 | .long 0 @ tag->u.core.flags = 0; | ||
33 | .long 0 @ tag->u.core.pagesize = 0; | ||
34 | .long 0 @ tag->u.core.rootdev = 0; | ||
35 | @ tag #2 | ||
36 | .long 8 @ tag->hdr.size = tag_size(tag_mem32); | ||
37 | .long 0x54410002 @ tag->hdr.tag = ATAG_MEM; | ||
38 | .long CONFIG_MEMORY_SIZE @ tag->u.mem.size = CONFIG_MEMORY_SIZE; | ||
39 | .long CONFIG_MEMORY_START @ @ tag->u.mem.start = CONFIG_MEMORY_START; | ||
40 | @ tag #3 | ||
41 | .long 0 @ tag->hdr.size = 0 | ||
42 | .long 0 @ tag->hdr.tag = ATAG_NONE; | ||
43 | 1: | ||
44 | |||
45 | /* Set board ID necessary for boot */ | ||
46 | ldr r7, 1f @ Set machine type register | ||
47 | adr r8, __atags @ Set atag register | ||
48 | b 2f | ||
49 | |||
50 | 1 : .long MACH_TYPE | ||
51 | 2 : | ||
52 | |||
53 | #endif /* CONFIG_ZBOOT_ROM */ | ||
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 0a34c818692..778655f0257 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig | |||
@@ -37,7 +37,3 @@ config SHARP_PARAM | |||
37 | 37 | ||
38 | config SHARP_SCOOP | 38 | config SHARP_SCOOP |
39 | bool | 39 | bool |
40 | |||
41 | config COMMON_CLKDEV | ||
42 | bool | ||
43 | select HAVE_CLK | ||
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index e6e8664a941..e7521bca2c3 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile | |||
@@ -17,3 +17,4 @@ obj-$(CONFIG_ARCH_IXP2000) += uengine.o | |||
17 | obj-$(CONFIG_ARCH_IXP23XX) += uengine.o | 17 | obj-$(CONFIG_ARCH_IXP23XX) += uengine.o |
18 | obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o | 18 | obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o |
19 | obj-$(CONFIG_COMMON_CLKDEV) += clkdev.o | 19 | obj-$(CONFIG_COMMON_CLKDEV) += clkdev.o |
20 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o | ||
diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c deleted file mode 100644 index e2b2bb66e09..00000000000 --- a/arch/arm/common/clkdev.c +++ /dev/null | |||
@@ -1,179 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/common/clkdev.c | ||
3 | * | ||
4 | * Copyright (C) 2008 Russell King. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * Helper for the clk API to assist looking up a struct clk. | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <asm/clkdev.h> | ||
24 | #include <mach/clkdev.h> | ||
25 | |||
26 | static LIST_HEAD(clocks); | ||
27 | static DEFINE_MUTEX(clocks_mutex); | ||
28 | |||
29 | /* | ||
30 | * Find the correct struct clk for the device and connection ID. | ||
31 | * We do slightly fuzzy matching here: | ||
32 | * An entry with a NULL ID is assumed to be a wildcard. | ||
33 | * If an entry has a device ID, it must match | ||
34 | * If an entry has a connection ID, it must match | ||
35 | * Then we take the most specific entry - with the following | ||
36 | * order of precedence: dev+con > dev only > con only. | ||
37 | */ | ||
38 | static struct clk *clk_find(const char *dev_id, const char *con_id) | ||
39 | { | ||
40 | struct clk_lookup *p; | ||
41 | struct clk *clk = NULL; | ||
42 | int match, best = 0; | ||
43 | |||
44 | list_for_each_entry(p, &clocks, node) { | ||
45 | match = 0; | ||
46 | if (p->dev_id) { | ||
47 | if (!dev_id || strcmp(p->dev_id, dev_id)) | ||
48 | continue; | ||
49 | match += 2; | ||
50 | } | ||
51 | if (p->con_id) { | ||
52 | if (!con_id || strcmp(p->con_id, con_id)) | ||
53 | continue; | ||
54 | match += 1; | ||
55 | } | ||
56 | |||
57 | if (match > best) { | ||
58 | clk = p->clk; | ||
59 | if (match != 3) | ||
60 | best = match; | ||
61 | else | ||
62 | break; | ||
63 | } | ||
64 | } | ||
65 | return clk; | ||
66 | } | ||
67 | |||
68 | struct clk *clk_get_sys(const char *dev_id, const char *con_id) | ||
69 | { | ||
70 | struct clk *clk; | ||
71 | |||
72 | mutex_lock(&clocks_mutex); | ||
73 | clk = clk_find(dev_id, con_id); | ||
74 | if (clk && !__clk_get(clk)) | ||
75 | clk = NULL; | ||
76 | mutex_unlock(&clocks_mutex); | ||
77 | |||
78 | return clk ? clk : ERR_PTR(-ENOENT); | ||
79 | } | ||
80 | EXPORT_SYMBOL(clk_get_sys); | ||
81 | |||
82 | struct clk *clk_get(struct device *dev, const char *con_id) | ||
83 | { | ||
84 | const char *dev_id = dev ? dev_name(dev) : NULL; | ||
85 | |||
86 | return clk_get_sys(dev_id, con_id); | ||
87 | } | ||
88 | EXPORT_SYMBOL(clk_get); | ||
89 | |||
90 | void clk_put(struct clk *clk) | ||
91 | { | ||
92 | __clk_put(clk); | ||
93 | } | ||
94 | EXPORT_SYMBOL(clk_put); | ||
95 | |||
96 | void clkdev_add(struct clk_lookup *cl) | ||
97 | { | ||
98 | mutex_lock(&clocks_mutex); | ||
99 | list_add_tail(&cl->node, &clocks); | ||
100 | mutex_unlock(&clocks_mutex); | ||
101 | } | ||
102 | EXPORT_SYMBOL(clkdev_add); | ||
103 | |||
104 | void __init clkdev_add_table(struct clk_lookup *cl, size_t num) | ||
105 | { | ||
106 | mutex_lock(&clocks_mutex); | ||
107 | while (num--) { | ||
108 | list_add_tail(&cl->node, &clocks); | ||
109 | cl++; | ||
110 | } | ||
111 | mutex_unlock(&clocks_mutex); | ||
112 | } | ||
113 | |||
114 | #define MAX_DEV_ID 20 | ||
115 | #define MAX_CON_ID 16 | ||
116 | |||
117 | struct clk_lookup_alloc { | ||
118 | struct clk_lookup cl; | ||
119 | char dev_id[MAX_DEV_ID]; | ||
120 | char con_id[MAX_CON_ID]; | ||
121 | }; | ||
122 | |||
123 | struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, | ||
124 | const char *dev_fmt, ...) | ||
125 | { | ||
126 | struct clk_lookup_alloc *cla; | ||
127 | |||
128 | cla = kzalloc(sizeof(*cla), GFP_KERNEL); | ||
129 | if (!cla) | ||
130 | return NULL; | ||
131 | |||
132 | cla->cl.clk = clk; | ||
133 | if (con_id) { | ||
134 | strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); | ||
135 | cla->cl.con_id = cla->con_id; | ||
136 | } | ||
137 | |||
138 | if (dev_fmt) { | ||
139 | va_list ap; | ||
140 | |||
141 | va_start(ap, dev_fmt); | ||
142 | vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); | ||
143 | cla->cl.dev_id = cla->dev_id; | ||
144 | va_end(ap); | ||
145 | } | ||
146 | |||
147 | return &cla->cl; | ||
148 | } | ||
149 | EXPORT_SYMBOL(clkdev_alloc); | ||
150 | |||
151 | int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, | ||
152 | struct device *dev) | ||
153 | { | ||
154 | struct clk *r = clk_get(dev, id); | ||
155 | struct clk_lookup *l; | ||
156 | |||
157 | if (IS_ERR(r)) | ||
158 | return PTR_ERR(r); | ||
159 | |||
160 | l = clkdev_alloc(r, alias, alias_dev_name); | ||
161 | clk_put(r); | ||
162 | if (!l) | ||
163 | return -ENODEV; | ||
164 | clkdev_add(l); | ||
165 | return 0; | ||
166 | } | ||
167 | EXPORT_SYMBOL(clk_add_alias); | ||
168 | |||
169 | /* | ||
170 | * clkdev_drop - remove a clock dynamically allocated | ||
171 | */ | ||
172 | void clkdev_drop(struct clk_lookup *cl) | ||
173 | { | ||
174 | mutex_lock(&clocks_mutex); | ||
175 | list_del(&cl->node); | ||
176 | mutex_unlock(&clocks_mutex); | ||
177 | kfree(cl); | ||
178 | } | ||
179 | EXPORT_SYMBOL(clkdev_drop); | ||
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index cc0a932bbea..e5681636626 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c | |||
@@ -328,7 +328,7 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr, | |||
328 | * substitute the safe buffer for the unsafe one. | 328 | * substitute the safe buffer for the unsafe one. |
329 | * (basically move the buffer from an unsafe area to a safe one) | 329 | * (basically move the buffer from an unsafe area to a safe one) |
330 | */ | 330 | */ |
331 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 331 | dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size, |
332 | enum dma_data_direction dir) | 332 | enum dma_data_direction dir) |
333 | { | 333 | { |
334 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", | 334 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", |
@@ -338,7 +338,7 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | |||
338 | 338 | ||
339 | return map_single(dev, ptr, size, dir); | 339 | return map_single(dev, ptr, size, dir); |
340 | } | 340 | } |
341 | EXPORT_SYMBOL(dma_map_single); | 341 | EXPORT_SYMBOL(__dma_map_single); |
342 | 342 | ||
343 | /* | 343 | /* |
344 | * see if a mapped address was really a "safe" buffer and if so, copy | 344 | * see if a mapped address was really a "safe" buffer and if so, copy |
@@ -346,7 +346,7 @@ EXPORT_SYMBOL(dma_map_single); | |||
346 | * the safe buffer. (basically return things back to the way they | 346 | * the safe buffer. (basically return things back to the way they |
347 | * should be) | 347 | * should be) |
348 | */ | 348 | */ |
349 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 349 | void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, |
350 | enum dma_data_direction dir) | 350 | enum dma_data_direction dir) |
351 | { | 351 | { |
352 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", | 352 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", |
@@ -354,9 +354,9 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
354 | 354 | ||
355 | unmap_single(dev, dma_addr, size, dir); | 355 | unmap_single(dev, dma_addr, size, dir); |
356 | } | 356 | } |
357 | EXPORT_SYMBOL(dma_unmap_single); | 357 | EXPORT_SYMBOL(__dma_unmap_single); |
358 | 358 | ||
359 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | 359 | dma_addr_t __dma_map_page(struct device *dev, struct page *page, |
360 | unsigned long offset, size_t size, enum dma_data_direction dir) | 360 | unsigned long offset, size_t size, enum dma_data_direction dir) |
361 | { | 361 | { |
362 | dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n", | 362 | dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n", |
@@ -372,7 +372,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, | |||
372 | 372 | ||
373 | return map_single(dev, page_address(page) + offset, size, dir); | 373 | return map_single(dev, page_address(page) + offset, size, dir); |
374 | } | 374 | } |
375 | EXPORT_SYMBOL(dma_map_page); | 375 | EXPORT_SYMBOL(__dma_map_page); |
376 | 376 | ||
377 | /* | 377 | /* |
378 | * see if a mapped address was really a "safe" buffer and if so, copy | 378 | * see if a mapped address was really a "safe" buffer and if so, copy |
@@ -380,7 +380,7 @@ EXPORT_SYMBOL(dma_map_page); | |||
380 | * the safe buffer. (basically return things back to the way they | 380 | * the safe buffer. (basically return things back to the way they |
381 | * should be) | 381 | * should be) |
382 | */ | 382 | */ |
383 | void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, | 383 | void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, |
384 | enum dma_data_direction dir) | 384 | enum dma_data_direction dir) |
385 | { | 385 | { |
386 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", | 386 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", |
@@ -388,7 +388,7 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
388 | 388 | ||
389 | unmap_single(dev, dma_addr, size, dir); | 389 | unmap_single(dev, dma_addr, size, dir); |
390 | } | 390 | } |
391 | EXPORT_SYMBOL(dma_unmap_page); | 391 | EXPORT_SYMBOL(__dma_unmap_page); |
392 | 392 | ||
393 | int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, | 393 | int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, |
394 | unsigned long off, size_t sz, enum dma_data_direction dir) | 394 | unsigned long off, size_t sz, enum dma_data_direction dir) |
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index e6388dcd8cf..0b89ef00133 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c | |||
@@ -35,6 +35,9 @@ | |||
35 | 35 | ||
36 | static DEFINE_SPINLOCK(irq_controller_lock); | 36 | static DEFINE_SPINLOCK(irq_controller_lock); |
37 | 37 | ||
38 | /* Address of GIC 0 CPU interface */ | ||
39 | void __iomem *gic_cpu_base_addr __read_mostly; | ||
40 | |||
38 | struct gic_chip_data { | 41 | struct gic_chip_data { |
39 | unsigned int irq_offset; | 42 | unsigned int irq_offset; |
40 | void __iomem *dist_base; | 43 | void __iomem *dist_base; |
@@ -45,7 +48,7 @@ struct gic_chip_data { | |||
45 | #define MAX_GIC_NR 1 | 48 | #define MAX_GIC_NR 1 |
46 | #endif | 49 | #endif |
47 | 50 | ||
48 | static struct gic_chip_data gic_data[MAX_GIC_NR]; | 51 | static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly; |
49 | 52 | ||
50 | static inline void __iomem *gic_dist_base(unsigned int irq) | 53 | static inline void __iomem *gic_dist_base(unsigned int irq) |
51 | { | 54 | { |
@@ -213,21 +216,16 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) | |||
213 | set_irq_chained_handler(irq, gic_handle_cascade_irq); | 216 | set_irq_chained_handler(irq, gic_handle_cascade_irq); |
214 | } | 217 | } |
215 | 218 | ||
216 | void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, | 219 | static void __init gic_dist_init(struct gic_chip_data *gic, |
217 | unsigned int irq_start) | 220 | unsigned int irq_start) |
218 | { | 221 | { |
219 | unsigned int gic_irqs, irq_limit, i; | 222 | unsigned int gic_irqs, irq_limit, i; |
223 | void __iomem *base = gic->dist_base; | ||
220 | u32 cpumask = 1 << smp_processor_id(); | 224 | u32 cpumask = 1 << smp_processor_id(); |
221 | 225 | ||
222 | if (gic_nr >= MAX_GIC_NR) | ||
223 | BUG(); | ||
224 | |||
225 | cpumask |= cpumask << 8; | 226 | cpumask |= cpumask << 8; |
226 | cpumask |= cpumask << 16; | 227 | cpumask |= cpumask << 16; |
227 | 228 | ||
228 | gic_data[gic_nr].dist_base = base; | ||
229 | gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31; | ||
230 | |||
231 | writel(0, base + GIC_DIST_CTRL); | 229 | writel(0, base + GIC_DIST_CTRL); |
232 | 230 | ||
233 | /* | 231 | /* |
@@ -267,7 +265,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, | |||
267 | /* | 265 | /* |
268 | * Limit number of interrupts registered to the platform maximum | 266 | * Limit number of interrupts registered to the platform maximum |
269 | */ | 267 | */ |
270 | irq_limit = gic_data[gic_nr].irq_offset + gic_irqs; | 268 | irq_limit = gic->irq_offset + gic_irqs; |
271 | if (WARN_ON(irq_limit > NR_IRQS)) | 269 | if (WARN_ON(irq_limit > NR_IRQS)) |
272 | irq_limit = NR_IRQS; | 270 | irq_limit = NR_IRQS; |
273 | 271 | ||
@@ -276,7 +274,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, | |||
276 | */ | 274 | */ |
277 | for (i = irq_start; i < irq_limit; i++) { | 275 | for (i = irq_start; i < irq_limit; i++) { |
278 | set_irq_chip(i, &gic_chip); | 276 | set_irq_chip(i, &gic_chip); |
279 | set_irq_chip_data(i, &gic_data[gic_nr]); | 277 | set_irq_chip_data(i, gic); |
280 | set_irq_handler(i, handle_level_irq); | 278 | set_irq_handler(i, handle_level_irq); |
281 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); | 279 | set_irq_flags(i, IRQF_VALID | IRQF_PROBE); |
282 | } | 280 | } |
@@ -284,19 +282,12 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, | |||
284 | writel(1, base + GIC_DIST_CTRL); | 282 | writel(1, base + GIC_DIST_CTRL); |
285 | } | 283 | } |
286 | 284 | ||
287 | void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) | 285 | static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) |
288 | { | 286 | { |
289 | void __iomem *dist_base; | 287 | void __iomem *dist_base = gic->dist_base; |
288 | void __iomem *base = gic->cpu_base; | ||
290 | int i; | 289 | int i; |
291 | 290 | ||
292 | if (gic_nr >= MAX_GIC_NR) | ||
293 | BUG(); | ||
294 | |||
295 | dist_base = gic_data[gic_nr].dist_base; | ||
296 | BUG_ON(!dist_base); | ||
297 | |||
298 | gic_data[gic_nr].cpu_base = base; | ||
299 | |||
300 | /* | 291 | /* |
301 | * Deal with the banked PPI and SGI interrupts - disable all | 292 | * Deal with the banked PPI and SGI interrupts - disable all |
302 | * PPI interrupts, ensure all SGI interrupts are enabled. | 293 | * PPI interrupts, ensure all SGI interrupts are enabled. |
@@ -314,6 +305,42 @@ void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) | |||
314 | writel(1, base + GIC_CPU_CTRL); | 305 | writel(1, base + GIC_CPU_CTRL); |
315 | } | 306 | } |
316 | 307 | ||
308 | void __init gic_init(unsigned int gic_nr, unsigned int irq_start, | ||
309 | void __iomem *dist_base, void __iomem *cpu_base) | ||
310 | { | ||
311 | struct gic_chip_data *gic; | ||
312 | |||
313 | BUG_ON(gic_nr >= MAX_GIC_NR); | ||
314 | |||
315 | gic = &gic_data[gic_nr]; | ||
316 | gic->dist_base = dist_base; | ||
317 | gic->cpu_base = cpu_base; | ||
318 | gic->irq_offset = (irq_start - 1) & ~31; | ||
319 | |||
320 | if (gic_nr == 0) | ||
321 | gic_cpu_base_addr = cpu_base; | ||
322 | |||
323 | gic_dist_init(gic, irq_start); | ||
324 | gic_cpu_init(gic); | ||
325 | } | ||
326 | |||
327 | void __cpuinit gic_secondary_init(unsigned int gic_nr) | ||
328 | { | ||
329 | BUG_ON(gic_nr >= MAX_GIC_NR); | ||
330 | |||
331 | gic_cpu_init(&gic_data[gic_nr]); | ||
332 | } | ||
333 | |||
334 | void __cpuinit gic_enable_ppi(unsigned int irq) | ||
335 | { | ||
336 | unsigned long flags; | ||
337 | |||
338 | local_irq_save(flags); | ||
339 | irq_to_desc(irq)->status |= IRQ_NOPROBE; | ||
340 | gic_unmask_irq(irq); | ||
341 | local_irq_restore(flags); | ||
342 | } | ||
343 | |||
317 | #ifdef CONFIG_SMP | 344 | #ifdef CONFIG_SMP |
318 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) | 345 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) |
319 | { | 346 | { |
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 1bec96e8519..42ff90b46df 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c | |||
@@ -352,3 +352,4 @@ struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys) | |||
352 | return pci_scan_bus(nr, &it8152_ops, sys); | 352 | return pci_scan_bus(nr, &it8152_ops, sys); |
353 | } | 353 | } |
354 | 354 | ||
355 | EXPORT_SYMBOL(dma_set_coherent_mask); | ||
diff --git a/arch/arm/plat-versatile/timer-sp.c b/arch/arm/common/timer-sp.c index fb0d1c29971..6ef3342153b 100644 --- a/arch/arm/plat-versatile/timer-sp.c +++ b/arch/arm/common/timer-sp.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/plat-versatile/timer-sp.c | 2 | * linux/arch/arm/common/timer-sp.c |
3 | * | 3 | * |
4 | * Copyright (C) 1999 - 2003 ARM Limited | 4 | * Copyright (C) 1999 - 2003 ARM Limited |
5 | * Copyright (C) 2000 Deep Blue Solutions Ltd | 5 | * Copyright (C) 2000 Deep Blue Solutions Ltd |
@@ -26,8 +26,6 @@ | |||
26 | 26 | ||
27 | #include <asm/hardware/arm_timer.h> | 27 | #include <asm/hardware/arm_timer.h> |
28 | 28 | ||
29 | #include <plat/timer-sp.h> | ||
30 | |||
31 | /* | 29 | /* |
32 | * These timers are currently always setup to be clocked at 1MHz. | 30 | * These timers are currently always setup to be clocked at 1MHz. |
33 | */ | 31 | */ |
@@ -46,7 +44,6 @@ static struct clocksource clocksource_sp804 = { | |||
46 | .rating = 200, | 44 | .rating = 200, |
47 | .read = sp804_read, | 45 | .read = sp804_read, |
48 | .mask = CLOCKSOURCE_MASK(32), | 46 | .mask = CLOCKSOURCE_MASK(32), |
49 | .shift = 20, | ||
50 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 47 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
51 | }; | 48 | }; |
52 | 49 | ||
@@ -63,8 +60,7 @@ void __init sp804_clocksource_init(void __iomem *base) | |||
63 | writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, | 60 | writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, |
64 | clksrc_base + TIMER_CTRL); | 61 | clksrc_base + TIMER_CTRL); |
65 | 62 | ||
66 | cs->mult = clocksource_khz2mult(TIMER_FREQ_KHZ, cs->shift); | 63 | clocksource_register_khz(cs, TIMER_FREQ_KHZ); |
67 | clocksource_register(cs); | ||
68 | } | 64 | } |
69 | 65 | ||
70 | 66 | ||
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 749bb662240..bc2d2d75f70 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
21 | #include <asm/domain.h> | ||
21 | 22 | ||
22 | /* | 23 | /* |
23 | * Endian independent macros for shifting bytes within registers. | 24 | * Endian independent macros for shifting bytes within registers. |
@@ -157,16 +158,24 @@ | |||
157 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
158 | #define ALT_SMP(instr...) \ | 159 | #define ALT_SMP(instr...) \ |
159 | 9998: instr | 160 | 9998: instr |
161 | /* | ||
162 | * Note: if you get assembler errors from ALT_UP() when building with | ||
163 | * CONFIG_THUMB2_KERNEL, you almost certainly need to use | ||
164 | * ALT_SMP( W(instr) ... ) | ||
165 | */ | ||
160 | #define ALT_UP(instr...) \ | 166 | #define ALT_UP(instr...) \ |
161 | .pushsection ".alt.smp.init", "a" ;\ | 167 | .pushsection ".alt.smp.init", "a" ;\ |
162 | .long 9998b ;\ | 168 | .long 9998b ;\ |
163 | instr ;\ | 169 | 9997: instr ;\ |
170 | .if . - 9997b != 4 ;\ | ||
171 | .error "ALT_UP() content must assemble to exactly 4 bytes";\ | ||
172 | .endif ;\ | ||
164 | .popsection | 173 | .popsection |
165 | #define ALT_UP_B(label) \ | 174 | #define ALT_UP_B(label) \ |
166 | .equ up_b_offset, label - 9998b ;\ | 175 | .equ up_b_offset, label - 9998b ;\ |
167 | .pushsection ".alt.smp.init", "a" ;\ | 176 | .pushsection ".alt.smp.init", "a" ;\ |
168 | .long 9998b ;\ | 177 | .long 9998b ;\ |
169 | b . + up_b_offset ;\ | 178 | W(b) . + up_b_offset ;\ |
170 | .popsection | 179 | .popsection |
171 | #else | 180 | #else |
172 | #define ALT_SMP(instr...) | 181 | #define ALT_SMP(instr...) |
@@ -177,16 +186,24 @@ | |||
177 | /* | 186 | /* |
178 | * SMP data memory barrier | 187 | * SMP data memory barrier |
179 | */ | 188 | */ |
180 | .macro smp_dmb | 189 | .macro smp_dmb mode |
181 | #ifdef CONFIG_SMP | 190 | #ifdef CONFIG_SMP |
182 | #if __LINUX_ARM_ARCH__ >= 7 | 191 | #if __LINUX_ARM_ARCH__ >= 7 |
192 | .ifeqs "\mode","arm" | ||
183 | ALT_SMP(dmb) | 193 | ALT_SMP(dmb) |
194 | .else | ||
195 | ALT_SMP(W(dmb)) | ||
196 | .endif | ||
184 | #elif __LINUX_ARM_ARCH__ == 6 | 197 | #elif __LINUX_ARM_ARCH__ == 6 |
185 | ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb | 198 | ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb |
186 | #else | 199 | #else |
187 | #error Incompatible SMP platform | 200 | #error Incompatible SMP platform |
188 | #endif | 201 | #endif |
202 | .ifeqs "\mode","arm" | ||
189 | ALT_UP(nop) | 203 | ALT_UP(nop) |
204 | .else | ||
205 | ALT_UP(W(nop)) | ||
206 | .endif | ||
190 | #endif | 207 | #endif |
191 | .endm | 208 | .endm |
192 | 209 | ||
@@ -206,12 +223,12 @@ | |||
206 | */ | 223 | */ |
207 | #ifdef CONFIG_THUMB2_KERNEL | 224 | #ifdef CONFIG_THUMB2_KERNEL |
208 | 225 | ||
209 | .macro usraccoff, instr, reg, ptr, inc, off, cond, abort | 226 | .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T() |
210 | 9999: | 227 | 9999: |
211 | .if \inc == 1 | 228 | .if \inc == 1 |
212 | \instr\cond\()bt \reg, [\ptr, #\off] | 229 | \instr\cond\()b\()\t\().w \reg, [\ptr, #\off] |
213 | .elseif \inc == 4 | 230 | .elseif \inc == 4 |
214 | \instr\cond\()t \reg, [\ptr, #\off] | 231 | \instr\cond\()\t\().w \reg, [\ptr, #\off] |
215 | .else | 232 | .else |
216 | .error "Unsupported inc macro argument" | 233 | .error "Unsupported inc macro argument" |
217 | .endif | 234 | .endif |
@@ -246,13 +263,13 @@ | |||
246 | 263 | ||
247 | #else /* !CONFIG_THUMB2_KERNEL */ | 264 | #else /* !CONFIG_THUMB2_KERNEL */ |
248 | 265 | ||
249 | .macro usracc, instr, reg, ptr, inc, cond, rept, abort | 266 | .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=T() |
250 | .rept \rept | 267 | .rept \rept |
251 | 9999: | 268 | 9999: |
252 | .if \inc == 1 | 269 | .if \inc == 1 |
253 | \instr\cond\()bt \reg, [\ptr], #\inc | 270 | \instr\cond\()b\()\t \reg, [\ptr], #\inc |
254 | .elseif \inc == 4 | 271 | .elseif \inc == 4 |
255 | \instr\cond\()t \reg, [\ptr], #\inc | 272 | \instr\cond\()\t \reg, [\ptr], #\inc |
256 | .else | 273 | .else |
257 | .error "Unsupported inc macro argument" | 274 | .error "Unsupported inc macro argument" |
258 | .endif | 275 | .endif |
diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h index 9d6122096fb..75fe66bc02b 100644 --- a/arch/arm/include/asm/cache.h +++ b/arch/arm/include/asm/cache.h | |||
@@ -23,4 +23,6 @@ | |||
23 | #define ARCH_SLAB_MINALIGN 8 | 23 | #define ARCH_SLAB_MINALIGN 8 |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | #define __read_mostly __attribute__((__section__(".data..read_mostly"))) | ||
27 | |||
26 | #endif | 28 | #endif |
diff --git a/arch/arm/include/asm/clkdev.h b/arch/arm/include/asm/clkdev.h index b56c1389b6f..765d3322236 100644 --- a/arch/arm/include/asm/clkdev.h +++ b/arch/arm/include/asm/clkdev.h | |||
@@ -12,23 +12,13 @@ | |||
12 | #ifndef __ASM_CLKDEV_H | 12 | #ifndef __ASM_CLKDEV_H |
13 | #define __ASM_CLKDEV_H | 13 | #define __ASM_CLKDEV_H |
14 | 14 | ||
15 | struct clk; | 15 | #include <linux/slab.h> |
16 | struct device; | ||
17 | 16 | ||
18 | struct clk_lookup { | 17 | #include <mach/clkdev.h> |
19 | struct list_head node; | ||
20 | const char *dev_id; | ||
21 | const char *con_id; | ||
22 | struct clk *clk; | ||
23 | }; | ||
24 | 18 | ||
25 | struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, | 19 | static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) |
26 | const char *dev_fmt, ...); | 20 | { |
27 | 21 | return kzalloc(size, GFP_KERNEL); | |
28 | void clkdev_add(struct clk_lookup *cl); | 22 | } |
29 | void clkdev_drop(struct clk_lookup *cl); | ||
30 | |||
31 | void clkdev_add_table(struct clk_lookup *, size_t); | ||
32 | int clk_add_alias(const char *, const char *, char *, struct device *); | ||
33 | 23 | ||
34 | #endif | 24 | #endif |
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index c568da7dcae..4fff837363e 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
@@ -5,24 +5,29 @@ | |||
5 | 5 | ||
6 | #include <linux/mm_types.h> | 6 | #include <linux/mm_types.h> |
7 | #include <linux/scatterlist.h> | 7 | #include <linux/scatterlist.h> |
8 | #include <linux/dma-debug.h> | ||
8 | 9 | ||
9 | #include <asm-generic/dma-coherent.h> | 10 | #include <asm-generic/dma-coherent.h> |
10 | #include <asm/memory.h> | 11 | #include <asm/memory.h> |
11 | 12 | ||
13 | #ifdef __arch_page_to_dma | ||
14 | #error Please update to __arch_pfn_to_dma | ||
15 | #endif | ||
16 | |||
12 | /* | 17 | /* |
13 | * page_to_dma/dma_to_virt/virt_to_dma are architecture private functions | 18 | * dma_to_pfn/pfn_to_dma/dma_to_virt/virt_to_dma are architecture private |
14 | * used internally by the DMA-mapping API to provide DMA addresses. They | 19 | * functions used internally by the DMA-mapping API to provide DMA |
15 | * must not be used by drivers. | 20 | * addresses. They must not be used by drivers. |
16 | */ | 21 | */ |
17 | #ifndef __arch_page_to_dma | 22 | #ifndef __arch_pfn_to_dma |
18 | static inline dma_addr_t page_to_dma(struct device *dev, struct page *page) | 23 | static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) |
19 | { | 24 | { |
20 | return (dma_addr_t)__pfn_to_bus(page_to_pfn(page)); | 25 | return (dma_addr_t)__pfn_to_bus(pfn); |
21 | } | 26 | } |
22 | 27 | ||
23 | static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr) | 28 | static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) |
24 | { | 29 | { |
25 | return pfn_to_page(__bus_to_pfn(addr)); | 30 | return __bus_to_pfn(addr); |
26 | } | 31 | } |
27 | 32 | ||
28 | static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) | 33 | static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) |
@@ -35,14 +40,14 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) | |||
35 | return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); | 40 | return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); |
36 | } | 41 | } |
37 | #else | 42 | #else |
38 | static inline dma_addr_t page_to_dma(struct device *dev, struct page *page) | 43 | static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) |
39 | { | 44 | { |
40 | return __arch_page_to_dma(dev, page); | 45 | return __arch_pfn_to_dma(dev, pfn); |
41 | } | 46 | } |
42 | 47 | ||
43 | static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr) | 48 | static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) |
44 | { | 49 | { |
45 | return __arch_dma_to_page(dev, addr); | 50 | return __arch_dma_to_pfn(dev, addr); |
46 | } | 51 | } |
47 | 52 | ||
48 | static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) | 53 | static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) |
@@ -293,13 +298,13 @@ extern int dma_needs_bounce(struct device*, dma_addr_t, size_t); | |||
293 | /* | 298 | /* |
294 | * The DMA API, implemented by dmabounce.c. See below for descriptions. | 299 | * The DMA API, implemented by dmabounce.c. See below for descriptions. |
295 | */ | 300 | */ |
296 | extern dma_addr_t dma_map_single(struct device *, void *, size_t, | 301 | extern dma_addr_t __dma_map_single(struct device *, void *, size_t, |
297 | enum dma_data_direction); | 302 | enum dma_data_direction); |
298 | extern void dma_unmap_single(struct device *, dma_addr_t, size_t, | 303 | extern void __dma_unmap_single(struct device *, dma_addr_t, size_t, |
299 | enum dma_data_direction); | 304 | enum dma_data_direction); |
300 | extern dma_addr_t dma_map_page(struct device *, struct page *, | 305 | extern dma_addr_t __dma_map_page(struct device *, struct page *, |
301 | unsigned long, size_t, enum dma_data_direction); | 306 | unsigned long, size_t, enum dma_data_direction); |
302 | extern void dma_unmap_page(struct device *, dma_addr_t, size_t, | 307 | extern void __dma_unmap_page(struct device *, dma_addr_t, size_t, |
303 | enum dma_data_direction); | 308 | enum dma_data_direction); |
304 | 309 | ||
305 | /* | 310 | /* |
@@ -323,6 +328,34 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr, | |||
323 | } | 328 | } |
324 | 329 | ||
325 | 330 | ||
331 | static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr, | ||
332 | size_t size, enum dma_data_direction dir) | ||
333 | { | ||
334 | __dma_single_cpu_to_dev(cpu_addr, size, dir); | ||
335 | return virt_to_dma(dev, cpu_addr); | ||
336 | } | ||
337 | |||
338 | static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page, | ||
339 | unsigned long offset, size_t size, enum dma_data_direction dir) | ||
340 | { | ||
341 | __dma_page_cpu_to_dev(page, offset, size, dir); | ||
342 | return pfn_to_dma(dev, page_to_pfn(page)) + offset; | ||
343 | } | ||
344 | |||
345 | static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle, | ||
346 | size_t size, enum dma_data_direction dir) | ||
347 | { | ||
348 | __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir); | ||
349 | } | ||
350 | |||
351 | static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle, | ||
352 | size_t size, enum dma_data_direction dir) | ||
353 | { | ||
354 | __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)), | ||
355 | handle & ~PAGE_MASK, size, dir); | ||
356 | } | ||
357 | #endif /* CONFIG_DMABOUNCE */ | ||
358 | |||
326 | /** | 359 | /** |
327 | * dma_map_single - map a single buffer for streaming DMA | 360 | * dma_map_single - map a single buffer for streaming DMA |
328 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices | 361 | * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices |
@@ -340,11 +373,16 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr, | |||
340 | static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | 373 | static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, |
341 | size_t size, enum dma_data_direction dir) | 374 | size_t size, enum dma_data_direction dir) |
342 | { | 375 | { |
376 | dma_addr_t addr; | ||
377 | |||
343 | BUG_ON(!valid_dma_direction(dir)); | 378 | BUG_ON(!valid_dma_direction(dir)); |
344 | 379 | ||
345 | __dma_single_cpu_to_dev(cpu_addr, size, dir); | 380 | addr = __dma_map_single(dev, cpu_addr, size, dir); |
381 | debug_dma_map_page(dev, virt_to_page(cpu_addr), | ||
382 | (unsigned long)cpu_addr & ~PAGE_MASK, size, | ||
383 | dir, addr, true); | ||
346 | 384 | ||
347 | return virt_to_dma(dev, cpu_addr); | 385 | return addr; |
348 | } | 386 | } |
349 | 387 | ||
350 | /** | 388 | /** |
@@ -364,11 +402,14 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | |||
364 | static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | 402 | static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, |
365 | unsigned long offset, size_t size, enum dma_data_direction dir) | 403 | unsigned long offset, size_t size, enum dma_data_direction dir) |
366 | { | 404 | { |
405 | dma_addr_t addr; | ||
406 | |||
367 | BUG_ON(!valid_dma_direction(dir)); | 407 | BUG_ON(!valid_dma_direction(dir)); |
368 | 408 | ||
369 | __dma_page_cpu_to_dev(page, offset, size, dir); | 409 | addr = __dma_map_page(dev, page, offset, size, dir); |
410 | debug_dma_map_page(dev, page, offset, size, dir, addr, false); | ||
370 | 411 | ||
371 | return page_to_dma(dev, page) + offset; | 412 | return addr; |
372 | } | 413 | } |
373 | 414 | ||
374 | /** | 415 | /** |
@@ -388,7 +429,8 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | |||
388 | static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, | 429 | static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, |
389 | size_t size, enum dma_data_direction dir) | 430 | size_t size, enum dma_data_direction dir) |
390 | { | 431 | { |
391 | __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir); | 432 | debug_dma_unmap_page(dev, handle, size, dir, true); |
433 | __dma_unmap_single(dev, handle, size, dir); | ||
392 | } | 434 | } |
393 | 435 | ||
394 | /** | 436 | /** |
@@ -408,10 +450,9 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle, | |||
408 | static inline void dma_unmap_page(struct device *dev, dma_addr_t handle, | 450 | static inline void dma_unmap_page(struct device *dev, dma_addr_t handle, |
409 | size_t size, enum dma_data_direction dir) | 451 | size_t size, enum dma_data_direction dir) |
410 | { | 452 | { |
411 | __dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK, | 453 | debug_dma_unmap_page(dev, handle, size, dir, false); |
412 | size, dir); | 454 | __dma_unmap_page(dev, handle, size, dir); |
413 | } | 455 | } |
414 | #endif /* CONFIG_DMABOUNCE */ | ||
415 | 456 | ||
416 | /** | 457 | /** |
417 | * dma_sync_single_range_for_cpu | 458 | * dma_sync_single_range_for_cpu |
@@ -437,6 +478,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev, | |||
437 | { | 478 | { |
438 | BUG_ON(!valid_dma_direction(dir)); | 479 | BUG_ON(!valid_dma_direction(dir)); |
439 | 480 | ||
481 | debug_dma_sync_single_for_cpu(dev, handle + offset, size, dir); | ||
482 | |||
440 | if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir)) | 483 | if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir)) |
441 | return; | 484 | return; |
442 | 485 | ||
@@ -449,6 +492,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev, | |||
449 | { | 492 | { |
450 | BUG_ON(!valid_dma_direction(dir)); | 493 | BUG_ON(!valid_dma_direction(dir)); |
451 | 494 | ||
495 | debug_dma_sync_single_for_device(dev, handle + offset, size, dir); | ||
496 | |||
452 | if (!dmabounce_sync_for_device(dev, handle, offset, size, dir)) | 497 | if (!dmabounce_sync_for_device(dev, handle, offset, size, dir)) |
453 | return; | 498 | return; |
454 | 499 | ||
diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h index cc7ef408071..af18ceaacf5 100644 --- a/arch/arm/include/asm/domain.h +++ b/arch/arm/include/asm/domain.h | |||
@@ -45,13 +45,17 @@ | |||
45 | */ | 45 | */ |
46 | #define DOMAIN_NOACCESS 0 | 46 | #define DOMAIN_NOACCESS 0 |
47 | #define DOMAIN_CLIENT 1 | 47 | #define DOMAIN_CLIENT 1 |
48 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
48 | #define DOMAIN_MANAGER 3 | 49 | #define DOMAIN_MANAGER 3 |
50 | #else | ||
51 | #define DOMAIN_MANAGER 1 | ||
52 | #endif | ||
49 | 53 | ||
50 | #define domain_val(dom,type) ((type) << (2*(dom))) | 54 | #define domain_val(dom,type) ((type) << (2*(dom))) |
51 | 55 | ||
52 | #ifndef __ASSEMBLY__ | 56 | #ifndef __ASSEMBLY__ |
53 | 57 | ||
54 | #ifdef CONFIG_MMU | 58 | #ifdef CONFIG_CPU_USE_DOMAINS |
55 | #define set_domain(x) \ | 59 | #define set_domain(x) \ |
56 | do { \ | 60 | do { \ |
57 | __asm__ __volatile__( \ | 61 | __asm__ __volatile__( \ |
@@ -74,5 +78,28 @@ | |||
74 | #define modify_domain(dom,type) do { } while (0) | 78 | #define modify_domain(dom,type) do { } while (0) |
75 | #endif | 79 | #endif |
76 | 80 | ||
81 | /* | ||
82 | * Generate the T (user) versions of the LDR/STR and related | ||
83 | * instructions (inline assembly) | ||
84 | */ | ||
85 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
86 | #define T(instr) #instr "t" | ||
87 | #else | ||
88 | #define T(instr) #instr | ||
77 | #endif | 89 | #endif |
78 | #endif /* !__ASSEMBLY__ */ | 90 | |
91 | #else /* __ASSEMBLY__ */ | ||
92 | |||
93 | /* | ||
94 | * Generate the T (user) versions of the LDR/STR and related | ||
95 | * instructions | ||
96 | */ | ||
97 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
98 | #define T(instr) instr ## t | ||
99 | #else | ||
100 | #define T(instr) instr | ||
101 | #endif | ||
102 | |||
103 | #endif /* __ASSEMBLY__ */ | ||
104 | |||
105 | #endif /* !__ASM_PROC_DOMAIN_H */ | ||
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index 8bb66bca2e3..c3cd8755e64 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h | |||
@@ -99,6 +99,8 @@ struct elf32_hdr; | |||
99 | extern int elf_check_arch(const struct elf32_hdr *); | 99 | extern int elf_check_arch(const struct elf32_hdr *); |
100 | #define elf_check_arch elf_check_arch | 100 | #define elf_check_arch elf_check_arch |
101 | 101 | ||
102 | #define vmcore_elf64_check_arch(x) (0) | ||
103 | |||
102 | extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int); | 104 | extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int); |
103 | #define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk) | 105 | #define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk) |
104 | 106 | ||
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S new file mode 100644 index 00000000000..ec0bbf79c71 --- /dev/null +++ b/arch/arm/include/asm/entry-macro-multi.S | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Interrupt handling. Preserves r7, r8, r9 | ||
3 | */ | ||
4 | .macro arch_irq_handler_default | ||
5 | get_irqnr_preamble r5, lr | ||
6 | 1: get_irqnr_and_base r0, r6, r5, lr | ||
7 | movne r1, sp | ||
8 | @ | ||
9 | @ routine called with r0 = irq number, r1 = struct pt_regs * | ||
10 | @ | ||
11 | adrne lr, BSYM(1b) | ||
12 | bne asm_do_IRQ | ||
13 | |||
14 | #ifdef CONFIG_SMP | ||
15 | /* | ||
16 | * XXX | ||
17 | * | ||
18 | * this macro assumes that irqstat (r6) and base (r5) are | ||
19 | * preserved from get_irqnr_and_base above | ||
20 | */ | ||
21 | ALT_SMP(test_for_ipi r0, r6, r5, lr) | ||
22 | ALT_UP_B(9997f) | ||
23 | movne r1, sp | ||
24 | adrne lr, BSYM(1b) | ||
25 | bne do_IPI | ||
26 | |||
27 | #ifdef CONFIG_LOCAL_TIMERS | ||
28 | test_for_ltirq r0, r6, r5, lr | ||
29 | movne r0, sp | ||
30 | adrne lr, BSYM(1b) | ||
31 | bne do_local_timer | ||
32 | #endif | ||
33 | #endif | ||
34 | 9997: | ||
35 | .endm | ||
36 | |||
37 | .macro arch_irq_handler, symbol_name | ||
38 | .align 5 | ||
39 | .global \symbol_name | ||
40 | \symbol_name: | ||
41 | mov r4, lr | ||
42 | arch_irq_handler_default | ||
43 | mov pc, r4 | ||
44 | .endm | ||
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index 540a044153a..b33fe7065b3 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h | |||
@@ -13,12 +13,13 @@ | |||
13 | #include <linux/preempt.h> | 13 | #include <linux/preempt.h> |
14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
15 | #include <asm/errno.h> | 15 | #include <asm/errno.h> |
16 | #include <asm/domain.h> | ||
16 | 17 | ||
17 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | 18 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ |
18 | __asm__ __volatile__( \ | 19 | __asm__ __volatile__( \ |
19 | "1: ldrt %1, [%2]\n" \ | 20 | "1: " T(ldr) " %1, [%2]\n" \ |
20 | " " insn "\n" \ | 21 | " " insn "\n" \ |
21 | "2: strt %0, [%2]\n" \ | 22 | "2: " T(str) " %0, [%2]\n" \ |
22 | " mov %0, #0\n" \ | 23 | " mov %0, #0\n" \ |
23 | "3:\n" \ | 24 | "3:\n" \ |
24 | " .pushsection __ex_table,\"a\"\n" \ | 25 | " .pushsection __ex_table,\"a\"\n" \ |
@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | |||
97 | pagefault_disable(); /* implies preempt_disable() */ | 98 | pagefault_disable(); /* implies preempt_disable() */ |
98 | 99 | ||
99 | __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" | 100 | __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" |
100 | "1: ldrt %0, [%3]\n" | 101 | "1: " T(ldr) " %0, [%3]\n" |
101 | " teq %0, %1\n" | 102 | " teq %0, %1\n" |
102 | " it eq @ explicit IT needed for the 2b label\n" | 103 | " it eq @ explicit IT needed for the 2b label\n" |
103 | "2: streqt %2, [%3]\n" | 104 | "2: " T(streq) " %2, [%3]\n" |
104 | "3:\n" | 105 | "3:\n" |
105 | " .pushsection __ex_table,\"a\"\n" | 106 | " .pushsection __ex_table,\"a\"\n" |
106 | " .align 3\n" | 107 | " .align 3\n" |
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h index 6d7485aff95..89ad1805e57 100644 --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h | |||
@@ -5,13 +5,31 @@ | |||
5 | #include <linux/threads.h> | 5 | #include <linux/threads.h> |
6 | #include <asm/irq.h> | 6 | #include <asm/irq.h> |
7 | 7 | ||
8 | #define NR_IPI 5 | ||
9 | |||
8 | typedef struct { | 10 | typedef struct { |
9 | unsigned int __softirq_pending; | 11 | unsigned int __softirq_pending; |
12 | #ifdef CONFIG_LOCAL_TIMERS | ||
10 | unsigned int local_timer_irqs; | 13 | unsigned int local_timer_irqs; |
14 | #endif | ||
15 | #ifdef CONFIG_SMP | ||
16 | unsigned int ipi_irqs[NR_IPI]; | ||
17 | #endif | ||
11 | } ____cacheline_aligned irq_cpustat_t; | 18 | } ____cacheline_aligned irq_cpustat_t; |
12 | 19 | ||
13 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ | 20 | #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ |
14 | 21 | ||
22 | #define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++ | ||
23 | #define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member) | ||
24 | |||
25 | #ifdef CONFIG_SMP | ||
26 | u64 smp_irq_stat_cpu(unsigned int cpu); | ||
27 | #else | ||
28 | #define smp_irq_stat_cpu(cpu) 0 | ||
29 | #endif | ||
30 | |||
31 | #define arch_irq_stat_cpu smp_irq_stat_cpu | ||
32 | |||
15 | #if NR_IRQS > 512 | 33 | #if NR_IRQS > 512 |
16 | #define HARDIRQ_BITS 10 | 34 | #define HARDIRQ_BITS 10 |
17 | #elif NR_IRQS > 256 | 35 | #elif NR_IRQS > 256 |
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S new file mode 100644 index 00000000000..c115b82fe80 --- /dev/null +++ b/arch/arm/include/asm/hardware/entry-macro-gic.S | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/hardware/entry-macro-gic.S | ||
3 | * | ||
4 | * Low-level IRQ helper macros for GIC | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <asm/hardware/gic.h> | ||
12 | |||
13 | #ifndef HAVE_GET_IRQNR_PREAMBLE | ||
14 | .macro get_irqnr_preamble, base, tmp | ||
15 | ldr \base, =gic_cpu_base_addr | ||
16 | ldr \base, [\base] | ||
17 | .endm | ||
18 | #endif | ||
19 | |||
20 | /* | ||
21 | * The interrupt numbering scheme is defined in the | ||
22 | * interrupt controller spec. To wit: | ||
23 | * | ||
24 | * Interrupts 0-15 are IPI | ||
25 | * 16-28 are reserved | ||
26 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
27 | * 32-1020 are global | ||
28 | * 1021-1022 are reserved | ||
29 | * 1023 is "spurious" (no interrupt) | ||
30 | * | ||
31 | * For now, we ignore all local interrupts so only return an interrupt if it's | ||
32 | * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. | ||
33 | * | ||
34 | * A simple read from the controller will tell us the number of the highest | ||
35 | * priority enabled interrupt. We then just need to check whether it is in the | ||
36 | * valid range for an IRQ (30-1020 inclusive). | ||
37 | */ | ||
38 | |||
39 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
40 | |||
41 | ldr \irqstat, [\base, #GIC_CPU_INTACK] | ||
42 | /* bits 12-10 = src CPU, 9-0 = int # */ | ||
43 | |||
44 | ldr \tmp, =1021 | ||
45 | bic \irqnr, \irqstat, #0x1c00 | ||
46 | cmp \irqnr, #29 | ||
47 | cmpcc \irqnr, \irqnr | ||
48 | cmpne \irqnr, \tmp | ||
49 | cmpcs \irqnr, \irqnr | ||
50 | .endm | ||
51 | |||
52 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
53 | * register) is preserved from the macro above. | ||
54 | * If there is an IPI, we immediately signal end of interrupt on the | ||
55 | * controller, since this requires the original irqstat value which | ||
56 | * we won't easily be able to recreate later. | ||
57 | */ | ||
58 | |||
59 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
60 | bic \irqnr, \irqstat, #0x1c00 | ||
61 | cmp \irqnr, #16 | ||
62 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
63 | cmpcs \irqnr, \irqnr | ||
64 | .endm | ||
65 | |||
66 | /* As above, this assumes that irqstat and base are preserved.. */ | ||
67 | |||
68 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
69 | bic \irqnr, \irqstat, #0x1c00 | ||
70 | mov \tmp, #0 | ||
71 | cmp \irqnr, #29 | ||
72 | moveq \tmp, #1 | ||
73 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
74 | cmp \tmp, #0 | ||
75 | .endm | ||
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 7f34333bb54..84557d32100 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h | |||
@@ -33,10 +33,13 @@ | |||
33 | #define GIC_DIST_SOFTINT 0xf00 | 33 | #define GIC_DIST_SOFTINT 0xf00 |
34 | 34 | ||
35 | #ifndef __ASSEMBLY__ | 35 | #ifndef __ASSEMBLY__ |
36 | void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start); | 36 | extern void __iomem *gic_cpu_base_addr; |
37 | void gic_cpu_init(unsigned int gic_nr, void __iomem *base); | 37 | |
38 | void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *); | ||
39 | void gic_secondary_init(unsigned int); | ||
38 | void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); | 40 | void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); |
39 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); | 41 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); |
42 | void gic_enable_ppi(unsigned int); | ||
40 | #endif | 43 | #endif |
41 | 44 | ||
42 | #endif | 45 | #endif |
diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h index 21fa272301f..b2f95c72287 100644 --- a/arch/arm/include/asm/hardware/it8152.h +++ b/arch/arm/include/asm/hardware/it8152.h | |||
@@ -76,6 +76,7 @@ extern unsigned long it8152_base_address; | |||
76 | IT8152_PD_IRQ(0) Audio controller (ACR) | 76 | IT8152_PD_IRQ(0) Audio controller (ACR) |
77 | */ | 77 | */ |
78 | #define IT8152_IRQ(x) (IRQ_BOARD_START + (x)) | 78 | #define IT8152_IRQ(x) (IRQ_BOARD_START + (x)) |
79 | #define IT8152_LAST_IRQ (IRQ_BOARD_START + 40) | ||
79 | 80 | ||
80 | /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */ | 81 | /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */ |
81 | #define IT8152_LD_IRQ_COUNT 9 | 82 | #define IT8152_LD_IRQ_COUNT 9 |
diff --git a/arch/arm/plat-versatile/include/plat/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h index 21e75e30d49..21e75e30d49 100644 --- a/arch/arm/plat-versatile/include/plat/timer-sp.h +++ b/arch/arm/include/asm/hardware/timer-sp.h | |||
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 1fc684e70ab..7080e2c8fa6 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h | |||
@@ -25,9 +25,6 @@ extern void *kmap_high(struct page *page); | |||
25 | extern void *kmap_high_get(struct page *page); | 25 | extern void *kmap_high_get(struct page *page); |
26 | extern void kunmap_high(struct page *page); | 26 | extern void kunmap_high(struct page *page); |
27 | 27 | ||
28 | extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte); | ||
29 | extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte); | ||
30 | |||
31 | /* | 28 | /* |
32 | * The following functions are already defined by <linux/highmem.h> | 29 | * The following functions are already defined by <linux/highmem.h> |
33 | * when CONFIG_HIGHMEM is not set. | 30 | * when CONFIG_HIGHMEM is not set. |
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 815efa2d4e0..20e0f7c9e03 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h | |||
@@ -241,18 +241,15 @@ extern void _memset_io(volatile void __iomem *, int, size_t); | |||
241 | * | 241 | * |
242 | */ | 242 | */ |
243 | #ifndef __arch_ioremap | 243 | #ifndef __arch_ioremap |
244 | #define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE) | 244 | #define __arch_ioremap __arm_ioremap |
245 | #define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE) | 245 | #define __arch_iounmap __iounmap |
246 | #define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED) | 246 | #endif |
247 | #define ioremap_wc(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_WC) | 247 | |
248 | #define iounmap(cookie) __iounmap(cookie) | ||
249 | #else | ||
250 | #define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) | 248 | #define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) |
251 | #define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) | 249 | #define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) |
252 | #define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED) | 250 | #define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED) |
253 | #define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC) | 251 | #define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC) |
254 | #define iounmap(cookie) __arch_iounmap(cookie) | 252 | #define iounmap __arch_iounmap |
255 | #endif | ||
256 | 253 | ||
257 | /* | 254 | /* |
258 | * io{read,write}{8,16,32} macros | 255 | * io{read,write}{8,16,32} macros |
diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h index 8ec9ef5c3c7..c0094d8edae 100644 --- a/arch/arm/include/asm/kexec.h +++ b/arch/arm/include/asm/kexec.h | |||
@@ -33,10 +33,20 @@ static inline void crash_setup_regs(struct pt_regs *newregs, | |||
33 | if (oldregs) { | 33 | if (oldregs) { |
34 | memcpy(newregs, oldregs, sizeof(*newregs)); | 34 | memcpy(newregs, oldregs, sizeof(*newregs)); |
35 | } else { | 35 | } else { |
36 | __asm__ __volatile__ ("stmia %0, {r0 - r15}" | 36 | __asm__ __volatile__ ( |
37 | : : "r" (&newregs->ARM_r0)); | 37 | "stmia %[regs_base], {r0-r12}\n\t" |
38 | __asm__ __volatile__ ("mrs %0, cpsr" | 38 | "mov %[_ARM_sp], sp\n\t" |
39 | : "=r" (newregs->ARM_cpsr)); | 39 | "str lr, %[_ARM_lr]\n\t" |
40 | "adr %[_ARM_pc], 1f\n\t" | ||
41 | "mrs %[_ARM_cpsr], cpsr\n\t" | ||
42 | "1:" | ||
43 | : [_ARM_pc] "=r" (newregs->ARM_pc), | ||
44 | [_ARM_cpsr] "=r" (newregs->ARM_cpsr), | ||
45 | [_ARM_sp] "=r" (newregs->ARM_sp), | ||
46 | [_ARM_lr] "=o" (newregs->ARM_lr) | ||
47 | : [regs_base] "r" (&newregs->ARM_r0) | ||
48 | : "memory" | ||
49 | ); | ||
40 | } | 50 | } |
41 | } | 51 | } |
42 | 52 | ||
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h index 50c7e7cfd67..6bc63ab498c 100644 --- a/arch/arm/include/asm/localtimer.h +++ b/arch/arm/include/asm/localtimer.h | |||
@@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt_regs *); | |||
30 | #include "smp_twd.h" | 30 | #include "smp_twd.h" |
31 | 31 | ||
32 | #define local_timer_ack() twd_timer_ack() | 32 | #define local_timer_ack() twd_timer_ack() |
33 | #define local_timer_stop() twd_timer_stop() | ||
34 | 33 | ||
35 | #else | 34 | #else |
36 | 35 | ||
@@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt_regs *); | |||
40 | */ | 39 | */ |
41 | int local_timer_ack(void); | 40 | int local_timer_ack(void); |
42 | 41 | ||
43 | /* | ||
44 | * Stop a local timer interrupt. | ||
45 | */ | ||
46 | void local_timer_stop(void); | ||
47 | |||
48 | #endif | 42 | #endif |
49 | 43 | ||
50 | /* | 44 | /* |
@@ -52,12 +46,6 @@ void local_timer_stop(void); | |||
52 | */ | 46 | */ |
53 | void local_timer_setup(struct clock_event_device *); | 47 | void local_timer_setup(struct clock_event_device *); |
54 | 48 | ||
55 | #else | ||
56 | |||
57 | static inline void local_timer_stop(void) | ||
58 | { | ||
59 | } | ||
60 | |||
61 | #endif | 49 | #endif |
62 | 50 | ||
63 | #endif | 51 | #endif |
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index d97a964207f..3a0893a76a3 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h | |||
@@ -37,12 +37,21 @@ struct machine_desc { | |||
37 | struct meminfo *); | 37 | struct meminfo *); |
38 | void (*reserve)(void);/* reserve mem blocks */ | 38 | void (*reserve)(void);/* reserve mem blocks */ |
39 | void (*map_io)(void);/* IO mapping function */ | 39 | void (*map_io)(void);/* IO mapping function */ |
40 | void (*init_early)(void); | ||
40 | void (*init_irq)(void); | 41 | void (*init_irq)(void); |
41 | struct sys_timer *timer; /* system tick timer */ | 42 | struct sys_timer *timer; /* system tick timer */ |
42 | void (*init_machine)(void); | 43 | void (*init_machine)(void); |
44 | #ifdef CONFIG_MULTI_IRQ_HANDLER | ||
45 | void (*handle_irq)(struct pt_regs *); | ||
46 | #endif | ||
43 | }; | 47 | }; |
44 | 48 | ||
45 | /* | 49 | /* |
50 | * Current machine - only accessible during boot. | ||
51 | */ | ||
52 | extern struct machine_desc *machine_desc; | ||
53 | |||
54 | /* | ||
46 | * Set of macros to define architecture features. This is built into | 55 | * Set of macros to define architecture features. This is built into |
47 | * a table by the linker. | 56 | * a table by the linker. |
48 | */ | 57 | */ |
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h index ce3eee9fe26..22ac140edd9 100644 --- a/arch/arm/include/asm/mach/irq.h +++ b/arch/arm/include/asm/mach/irq.h | |||
@@ -17,10 +17,12 @@ struct seq_file; | |||
17 | /* | 17 | /* |
18 | * This is internal. Do not use it. | 18 | * This is internal. Do not use it. |
19 | */ | 19 | */ |
20 | extern unsigned int arch_nr_irqs; | ||
21 | extern void (*init_arch_irq)(void); | ||
22 | extern void init_FIQ(void); | 20 | extern void init_FIQ(void); |
23 | extern int show_fiq_list(struct seq_file *, void *); | 21 | extern int show_fiq_list(struct seq_file *, int); |
22 | |||
23 | #ifdef CONFIG_MULTI_IRQ_HANDLER | ||
24 | extern void (*handle_arch_irq)(struct pt_regs *); | ||
25 | #endif | ||
24 | 26 | ||
25 | /* | 27 | /* |
26 | * This is for easy migration, but should be changed in the source | 28 | * This is for easy migration, but should be changed in the source |
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h index 35d408f6dcc..883f6be5117 100644 --- a/arch/arm/include/asm/mach/time.h +++ b/arch/arm/include/asm/mach/time.h | |||
@@ -43,7 +43,6 @@ struct sys_timer { | |||
43 | #endif | 43 | #endif |
44 | }; | 44 | }; |
45 | 45 | ||
46 | extern struct sys_timer *system_timer; | ||
47 | extern void timer_tick(void); | 46 | extern void timer_tick(void); |
48 | 47 | ||
49 | #endif | 48 | #endif |
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index cbb0bc295d2..12c8e680cbf 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h | |||
@@ -8,11 +8,6 @@ | |||
8 | struct unwind_table; | 8 | struct unwind_table; |
9 | 9 | ||
10 | #ifdef CONFIG_ARM_UNWIND | 10 | #ifdef CONFIG_ARM_UNWIND |
11 | struct arm_unwind_mapping { | ||
12 | Elf_Shdr *unw_sec; | ||
13 | Elf_Shdr *sec_text; | ||
14 | struct unwind_table *unwind; | ||
15 | }; | ||
16 | enum { | 11 | enum { |
17 | ARM_SEC_INIT, | 12 | ARM_SEC_INIT, |
18 | ARM_SEC_DEVINIT, | 13 | ARM_SEC_DEVINIT, |
@@ -21,13 +16,13 @@ enum { | |||
21 | ARM_SEC_DEVEXIT, | 16 | ARM_SEC_DEVEXIT, |
22 | ARM_SEC_MAX, | 17 | ARM_SEC_MAX, |
23 | }; | 18 | }; |
19 | #endif | ||
20 | |||
24 | struct mod_arch_specific { | 21 | struct mod_arch_specific { |
25 | struct arm_unwind_mapping map[ARM_SEC_MAX]; | 22 | #ifdef CONFIG_ARM_UNWIND |
26 | }; | 23 | struct unwind_table *unwind[ARM_SEC_MAX]; |
27 | #else | ||
28 | struct mod_arch_specific { | ||
29 | }; | ||
30 | #endif | 24 | #endif |
25 | }; | ||
31 | 26 | ||
32 | /* | 27 | /* |
33 | * Include the ARM architecture version. | 28 | * Include the ARM architecture version. |
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index a485ac3c869..f51a69595f6 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h | |||
@@ -151,13 +151,15 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from, | |||
151 | #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) | 151 | #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) |
152 | extern void copy_page(void *to, const void *from); | 152 | extern void copy_page(void *to, const void *from); |
153 | 153 | ||
154 | typedef unsigned long pteval_t; | ||
155 | |||
154 | #undef STRICT_MM_TYPECHECKS | 156 | #undef STRICT_MM_TYPECHECKS |
155 | 157 | ||
156 | #ifdef STRICT_MM_TYPECHECKS | 158 | #ifdef STRICT_MM_TYPECHECKS |
157 | /* | 159 | /* |
158 | * These are used to make use of C type-checking.. | 160 | * These are used to make use of C type-checking.. |
159 | */ | 161 | */ |
160 | typedef struct { unsigned long pte; } pte_t; | 162 | typedef struct { pteval_t pte; } pte_t; |
161 | typedef struct { unsigned long pmd; } pmd_t; | 163 | typedef struct { unsigned long pmd; } pmd_t; |
162 | typedef struct { unsigned long pgd[2]; } pgd_t; | 164 | typedef struct { unsigned long pgd[2]; } pgd_t; |
163 | typedef struct { unsigned long pgprot; } pgprot_t; | 165 | typedef struct { unsigned long pgprot; } pgprot_t; |
@@ -175,7 +177,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
175 | /* | 177 | /* |
176 | * .. while these make it easier on the compiler | 178 | * .. while these make it easier on the compiler |
177 | */ | 179 | */ |
178 | typedef unsigned long pte_t; | 180 | typedef pteval_t pte_t; |
179 | typedef unsigned long pmd_t; | 181 | typedef unsigned long pmd_t; |
180 | typedef unsigned long pgd_t[2]; | 182 | typedef unsigned long pgd_t[2]; |
181 | typedef unsigned long pgprot_t; | 183 | typedef unsigned long pgprot_t; |
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index b12cc98bbe0..9763be04f77 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h | |||
@@ -30,14 +30,16 @@ | |||
30 | #define pmd_free(mm, pmd) do { } while (0) | 30 | #define pmd_free(mm, pmd) do { } while (0) |
31 | #define pgd_populate(mm,pmd,pte) BUG() | 31 | #define pgd_populate(mm,pmd,pte) BUG() |
32 | 32 | ||
33 | extern pgd_t *get_pgd_slow(struct mm_struct *mm); | 33 | extern pgd_t *pgd_alloc(struct mm_struct *mm); |
34 | extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd); | 34 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); |
35 | |||
36 | #define pgd_alloc(mm) get_pgd_slow(mm) | ||
37 | #define pgd_free(mm, pgd) free_pgd_slow(mm, pgd) | ||
38 | 35 | ||
39 | #define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) | 36 | #define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO) |
40 | 37 | ||
38 | static inline void clean_pte_table(pte_t *pte) | ||
39 | { | ||
40 | clean_dcache_area(pte + PTE_HWTABLE_PTRS, PTE_HWTABLE_SIZE); | ||
41 | } | ||
42 | |||
41 | /* | 43 | /* |
42 | * Allocate one PTE table. | 44 | * Allocate one PTE table. |
43 | * | 45 | * |
@@ -45,14 +47,14 @@ extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd); | |||
45 | * into one table thus: | 47 | * into one table thus: |
46 | * | 48 | * |
47 | * +------------+ | 49 | * +------------+ |
48 | * | h/w pt 0 | | ||
49 | * +------------+ | ||
50 | * | h/w pt 1 | | ||
51 | * +------------+ | ||
52 | * | Linux pt 0 | | 50 | * | Linux pt 0 | |
53 | * +------------+ | 51 | * +------------+ |
54 | * | Linux pt 1 | | 52 | * | Linux pt 1 | |
55 | * +------------+ | 53 | * +------------+ |
54 | * | h/w pt 0 | | ||
55 | * +------------+ | ||
56 | * | h/w pt 1 | | ||
57 | * +------------+ | ||
56 | */ | 58 | */ |
57 | static inline pte_t * | 59 | static inline pte_t * |
58 | pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) | 60 | pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) |
@@ -60,10 +62,8 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr) | |||
60 | pte_t *pte; | 62 | pte_t *pte; |
61 | 63 | ||
62 | pte = (pte_t *)__get_free_page(PGALLOC_GFP); | 64 | pte = (pte_t *)__get_free_page(PGALLOC_GFP); |
63 | if (pte) { | 65 | if (pte) |
64 | clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE); | 66 | clean_pte_table(pte); |
65 | pte += PTRS_PER_PTE; | ||
66 | } | ||
67 | 67 | ||
68 | return pte; | 68 | return pte; |
69 | } | 69 | } |
@@ -79,10 +79,8 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr) | |||
79 | pte = alloc_pages(PGALLOC_GFP, 0); | 79 | pte = alloc_pages(PGALLOC_GFP, 0); |
80 | #endif | 80 | #endif |
81 | if (pte) { | 81 | if (pte) { |
82 | if (!PageHighMem(pte)) { | 82 | if (!PageHighMem(pte)) |
83 | void *page = page_address(pte); | 83 | clean_pte_table(page_address(pte)); |
84 | clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE); | ||
85 | } | ||
86 | pgtable_page_ctor(pte); | 84 | pgtable_page_ctor(pte); |
87 | } | 85 | } |
88 | 86 | ||
@@ -94,10 +92,8 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr) | |||
94 | */ | 92 | */ |
95 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 93 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) |
96 | { | 94 | { |
97 | if (pte) { | 95 | if (pte) |
98 | pte -= PTRS_PER_PTE; | ||
99 | free_page((unsigned long)pte); | 96 | free_page((unsigned long)pte); |
100 | } | ||
101 | } | 97 | } |
102 | 98 | ||
103 | static inline void pte_free(struct mm_struct *mm, pgtable_t pte) | 99 | static inline void pte_free(struct mm_struct *mm, pgtable_t pte) |
@@ -106,8 +102,10 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte) | |||
106 | __free_page(pte); | 102 | __free_page(pte); |
107 | } | 103 | } |
108 | 104 | ||
109 | static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval) | 105 | static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, |
106 | unsigned long prot) | ||
110 | { | 107 | { |
108 | unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot; | ||
111 | pmdp[0] = __pmd(pmdval); | 109 | pmdp[0] = __pmd(pmdval); |
112 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); | 110 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); |
113 | flush_pmd_entry(pmdp); | 111 | flush_pmd_entry(pmdp); |
@@ -122,20 +120,16 @@ static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval) | |||
122 | static inline void | 120 | static inline void |
123 | pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | 121 | pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) |
124 | { | 122 | { |
125 | unsigned long pte_ptr = (unsigned long)ptep; | ||
126 | |||
127 | /* | 123 | /* |
128 | * The pmd must be loaded with the physical | 124 | * The pmd must be loaded with the physical address of the PTE table |
129 | * address of the PTE table | ||
130 | */ | 125 | */ |
131 | pte_ptr -= PTRS_PER_PTE * sizeof(void *); | 126 | __pmd_populate(pmdp, __pa(ptep), _PAGE_KERNEL_TABLE); |
132 | __pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE); | ||
133 | } | 127 | } |
134 | 128 | ||
135 | static inline void | 129 | static inline void |
136 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) | 130 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) |
137 | { | 131 | { |
138 | __pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE); | 132 | __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE); |
139 | } | 133 | } |
140 | #define pmd_pgtable(pmd) pmd_page(pmd) | 134 | #define pmd_pgtable(pmd) pmd_page(pmd) |
141 | 135 | ||
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 53d1d5deb11..ebcb6432f45 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #ifndef _ASMARM_PGTABLE_H | 10 | #ifndef _ASMARM_PGTABLE_H |
11 | #define _ASMARM_PGTABLE_H | 11 | #define _ASMARM_PGTABLE_H |
12 | 12 | ||
13 | #include <linux/const.h> | ||
13 | #include <asm-generic/4level-fixup.h> | 14 | #include <asm-generic/4level-fixup.h> |
14 | #include <asm/proc-fns.h> | 15 | #include <asm/proc-fns.h> |
15 | 16 | ||
@@ -54,7 +55,7 @@ | |||
54 | * Therefore, we tweak the implementation slightly - we tell Linux that we | 55 | * Therefore, we tweak the implementation slightly - we tell Linux that we |
55 | * have 2048 entries in the first level, each of which is 8 bytes (iow, two | 56 | * have 2048 entries in the first level, each of which is 8 bytes (iow, two |
56 | * hardware pointers to the second level.) The second level contains two | 57 | * hardware pointers to the second level.) The second level contains two |
57 | * hardware PTE tables arranged contiguously, followed by Linux versions | 58 | * hardware PTE tables arranged contiguously, preceded by Linux versions |
58 | * which contain the state information Linux needs. We, therefore, end up | 59 | * which contain the state information Linux needs. We, therefore, end up |
59 | * with 512 entries in the "PTE" level. | 60 | * with 512 entries in the "PTE" level. |
60 | * | 61 | * |
@@ -62,15 +63,15 @@ | |||
62 | * | 63 | * |
63 | * pgd pte | 64 | * pgd pte |
64 | * | | | 65 | * | | |
65 | * +--------+ +0 | 66 | * +--------+ |
66 | * | |-----> +------------+ +0 | 67 | * | | +------------+ +0 |
68 | * +- - - - + | Linux pt 0 | | ||
69 | * | | +------------+ +1024 | ||
70 | * +--------+ +0 | Linux pt 1 | | ||
71 | * | |-----> +------------+ +2048 | ||
67 | * +- - - - + +4 | h/w pt 0 | | 72 | * +- - - - + +4 | h/w pt 0 | |
68 | * | |-----> +------------+ +1024 | 73 | * | |-----> +------------+ +3072 |
69 | * +--------+ +8 | h/w pt 1 | | 74 | * +--------+ +8 | h/w pt 1 | |
70 | * | | +------------+ +2048 | ||
71 | * +- - - - + | Linux pt 0 | | ||
72 | * | | +------------+ +3072 | ||
73 | * +--------+ | Linux pt 1 | | ||
74 | * | | +------------+ +4096 | 75 | * | | +------------+ +4096 |
75 | * | 76 | * |
76 | * See L_PTE_xxx below for definitions of bits in the "Linux pt", and | 77 | * See L_PTE_xxx below for definitions of bits in the "Linux pt", and |
@@ -102,6 +103,10 @@ | |||
102 | #define PTRS_PER_PMD 1 | 103 | #define PTRS_PER_PMD 1 |
103 | #define PTRS_PER_PGD 2048 | 104 | #define PTRS_PER_PGD 2048 |
104 | 105 | ||
106 | #define PTE_HWTABLE_PTRS (PTRS_PER_PTE) | ||
107 | #define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) | ||
108 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32)) | ||
109 | |||
105 | /* | 110 | /* |
106 | * PMD_SHIFT determines the size of the area a second-level page table can map | 111 | * PMD_SHIFT determines the size of the area a second-level page table can map |
107 | * PGDIR_SHIFT determines what a third-level page table entry can map | 112 | * PGDIR_SHIFT determines what a third-level page table entry can map |
@@ -112,13 +117,13 @@ | |||
112 | #define LIBRARY_TEXT_START 0x0c000000 | 117 | #define LIBRARY_TEXT_START 0x0c000000 |
113 | 118 | ||
114 | #ifndef __ASSEMBLY__ | 119 | #ifndef __ASSEMBLY__ |
115 | extern void __pte_error(const char *file, int line, unsigned long val); | 120 | extern void __pte_error(const char *file, int line, pte_t); |
116 | extern void __pmd_error(const char *file, int line, unsigned long val); | 121 | extern void __pmd_error(const char *file, int line, pmd_t); |
117 | extern void __pgd_error(const char *file, int line, unsigned long val); | 122 | extern void __pgd_error(const char *file, int line, pgd_t); |
118 | 123 | ||
119 | #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte)) | 124 | #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte) |
120 | #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd)) | 125 | #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd) |
121 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) | 126 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd) |
122 | #endif /* !__ASSEMBLY__ */ | 127 | #endif /* !__ASSEMBLY__ */ |
123 | 128 | ||
124 | #define PMD_SIZE (1UL << PMD_SHIFT) | 129 | #define PMD_SIZE (1UL << PMD_SHIFT) |
@@ -133,8 +138,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); | |||
133 | */ | 138 | */ |
134 | #define FIRST_USER_ADDRESS PAGE_SIZE | 139 | #define FIRST_USER_ADDRESS PAGE_SIZE |
135 | 140 | ||
136 | #define FIRST_USER_PGD_NR 1 | 141 | #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) |
137 | #define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR) | ||
138 | 142 | ||
139 | /* | 143 | /* |
140 | * section address mask and size definitions. | 144 | * section address mask and size definitions. |
@@ -161,30 +165,30 @@ extern void __pgd_error(const char *file, int line, unsigned long val); | |||
161 | * The PTE table pointer refers to the hardware entries; the "Linux" | 165 | * The PTE table pointer refers to the hardware entries; the "Linux" |
162 | * entries are stored 1024 bytes below. | 166 | * entries are stored 1024 bytes below. |
163 | */ | 167 | */ |
164 | #define L_PTE_PRESENT (1 << 0) | 168 | #define L_PTE_PRESENT (_AT(pteval_t, 1) << 0) |
165 | #define L_PTE_YOUNG (1 << 1) | 169 | #define L_PTE_YOUNG (_AT(pteval_t, 1) << 1) |
166 | #define L_PTE_FILE (1 << 2) /* only when !PRESENT */ | 170 | #define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ |
167 | #define L_PTE_DIRTY (1 << 6) | 171 | #define L_PTE_DIRTY (_AT(pteval_t, 1) << 6) |
168 | #define L_PTE_WRITE (1 << 7) | 172 | #define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) |
169 | #define L_PTE_USER (1 << 8) | 173 | #define L_PTE_USER (_AT(pteval_t, 1) << 8) |
170 | #define L_PTE_EXEC (1 << 9) | 174 | #define L_PTE_XN (_AT(pteval_t, 1) << 9) |
171 | #define L_PTE_SHARED (1 << 10) /* shared(v6), coherent(xsc3) */ | 175 | #define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ |
172 | 176 | ||
173 | /* | 177 | /* |
174 | * These are the memory types, defined to be compatible with | 178 | * These are the memory types, defined to be compatible with |
175 | * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB | 179 | * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB |
176 | */ | 180 | */ |
177 | #define L_PTE_MT_UNCACHED (0x00 << 2) /* 0000 */ | 181 | #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ |
178 | #define L_PTE_MT_BUFFERABLE (0x01 << 2) /* 0001 */ | 182 | #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ |
179 | #define L_PTE_MT_WRITETHROUGH (0x02 << 2) /* 0010 */ | 183 | #define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */ |
180 | #define L_PTE_MT_WRITEBACK (0x03 << 2) /* 0011 */ | 184 | #define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */ |
181 | #define L_PTE_MT_MINICACHE (0x06 << 2) /* 0110 (sa1100, xscale) */ | 185 | #define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */ |
182 | #define L_PTE_MT_WRITEALLOC (0x07 << 2) /* 0111 */ | 186 | #define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */ |
183 | #define L_PTE_MT_DEV_SHARED (0x04 << 2) /* 0100 */ | 187 | #define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */ |
184 | #define L_PTE_MT_DEV_NONSHARED (0x0c << 2) /* 1100 */ | 188 | #define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ |
185 | #define L_PTE_MT_DEV_WC (0x09 << 2) /* 1001 */ | 189 | #define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ |
186 | #define L_PTE_MT_DEV_CACHED (0x0b << 2) /* 1011 */ | 190 | #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ |
187 | #define L_PTE_MT_MASK (0x0f << 2) | 191 | #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) |
188 | 192 | ||
189 | #ifndef __ASSEMBLY__ | 193 | #ifndef __ASSEMBLY__ |
190 | 194 | ||
@@ -201,23 +205,44 @@ extern pgprot_t pgprot_kernel; | |||
201 | 205 | ||
202 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) | 206 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) |
203 | 207 | ||
204 | #define PAGE_NONE pgprot_user | 208 | #define PAGE_NONE _MOD_PROT(pgprot_user, L_PTE_XN | L_PTE_RDONLY) |
205 | #define PAGE_SHARED _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE) | 209 | #define PAGE_SHARED _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_XN) |
206 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC) | 210 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_user, L_PTE_USER) |
207 | #define PAGE_COPY _MOD_PROT(pgprot_user, L_PTE_USER) | 211 | #define PAGE_COPY _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN) |
208 | #define PAGE_COPY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_EXEC) | 212 | #define PAGE_COPY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY) |
209 | #define PAGE_READONLY _MOD_PROT(pgprot_user, L_PTE_USER) | 213 | #define PAGE_READONLY _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN) |
210 | #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_EXEC) | 214 | #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY) |
211 | #define PAGE_KERNEL pgprot_kernel | 215 | #define PAGE_KERNEL _MOD_PROT(pgprot_kernel, L_PTE_XN) |
212 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_kernel, L_PTE_EXEC) | 216 | #define PAGE_KERNEL_EXEC pgprot_kernel |
213 | 217 | ||
214 | #define __PAGE_NONE __pgprot(_L_PTE_DEFAULT) | 218 | #define __PAGE_NONE __pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN) |
215 | #define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE) | 219 | #define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN) |
216 | #define __PAGE_SHARED_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC) | 220 | #define __PAGE_SHARED_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER) |
217 | #define __PAGE_COPY __pgprot(_L_PTE_DEFAULT | L_PTE_USER) | 221 | #define __PAGE_COPY __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN) |
218 | #define __PAGE_COPY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_EXEC) | 222 | #define __PAGE_COPY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY) |
219 | #define __PAGE_READONLY __pgprot(_L_PTE_DEFAULT | L_PTE_USER) | 223 | #define __PAGE_READONLY __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN) |
220 | #define __PAGE_READONLY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_EXEC) | 224 | #define __PAGE_READONLY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY) |
225 | |||
226 | #define __pgprot_modify(prot,mask,bits) \ | ||
227 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
228 | |||
229 | #define pgprot_noncached(prot) \ | ||
230 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) | ||
231 | |||
232 | #define pgprot_writecombine(prot) \ | ||
233 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) | ||
234 | |||
235 | #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE | ||
236 | #define pgprot_dmacoherent(prot) \ | ||
237 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN) | ||
238 | #define __HAVE_PHYS_MEM_ACCESS_PROT | ||
239 | struct file; | ||
240 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
241 | unsigned long size, pgprot_t vma_prot); | ||
242 | #else | ||
243 | #define pgprot_dmacoherent(prot) \ | ||
244 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN) | ||
245 | #endif | ||
221 | 246 | ||
222 | #endif /* __ASSEMBLY__ */ | 247 | #endif /* __ASSEMBLY__ */ |
223 | 248 | ||
@@ -255,26 +280,84 @@ extern pgprot_t pgprot_kernel; | |||
255 | extern struct page *empty_zero_page; | 280 | extern struct page *empty_zero_page; |
256 | #define ZERO_PAGE(vaddr) (empty_zero_page) | 281 | #define ZERO_PAGE(vaddr) (empty_zero_page) |
257 | 282 | ||
258 | #define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) | ||
259 | #define pfn_pte(pfn,prot) (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))) | ||
260 | 283 | ||
261 | #define pte_none(pte) (!pte_val(pte)) | 284 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
262 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) | 285 | |
263 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) | 286 | /* to find an entry in a page-table-directory */ |
264 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) | 287 | #define pgd_index(addr) ((addr) >> PGDIR_SHIFT) |
288 | |||
289 | #define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr)) | ||
290 | |||
291 | /* to find an entry in a kernel page-table-directory */ | ||
292 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) | ||
293 | |||
294 | /* | ||
295 | * The "pgd_xxx()" functions here are trivial for a folded two-level | ||
296 | * setup: the pgd is never bad, and a pmd always exists (as it's folded | ||
297 | * into the pgd entry) | ||
298 | */ | ||
299 | #define pgd_none(pgd) (0) | ||
300 | #define pgd_bad(pgd) (0) | ||
301 | #define pgd_present(pgd) (1) | ||
302 | #define pgd_clear(pgdp) do { } while (0) | ||
303 | #define set_pgd(pgd,pgdp) do { } while (0) | ||
304 | |||
305 | |||
306 | /* Find an entry in the second-level page table.. */ | ||
307 | #define pmd_offset(dir, addr) ((pmd_t *)(dir)) | ||
308 | |||
309 | #define pmd_none(pmd) (!pmd_val(pmd)) | ||
310 | #define pmd_present(pmd) (pmd_val(pmd)) | ||
311 | #define pmd_bad(pmd) (pmd_val(pmd) & 2) | ||
312 | |||
313 | #define copy_pmd(pmdpd,pmdps) \ | ||
314 | do { \ | ||
315 | pmdpd[0] = pmdps[0]; \ | ||
316 | pmdpd[1] = pmdps[1]; \ | ||
317 | flush_pmd_entry(pmdpd); \ | ||
318 | } while (0) | ||
319 | |||
320 | #define pmd_clear(pmdp) \ | ||
321 | do { \ | ||
322 | pmdp[0] = __pmd(0); \ | ||
323 | pmdp[1] = __pmd(0); \ | ||
324 | clean_pmd_entry(pmdp); \ | ||
325 | } while (0) | ||
326 | |||
327 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) | ||
328 | { | ||
329 | return __va(pmd_val(pmd) & PAGE_MASK); | ||
330 | } | ||
331 | |||
332 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) | ||
333 | |||
334 | /* we don't need complex calculations here as the pmd is folded into the pgd */ | ||
335 | #define pmd_addr_end(addr,end) (end) | ||
265 | 336 | ||
266 | #define pte_offset_map(dir,addr) (__pte_map(dir) + __pte_index(addr)) | ||
267 | #define pte_unmap(pte) __pte_unmap(pte) | ||
268 | 337 | ||
269 | #ifndef CONFIG_HIGHPTE | 338 | #ifndef CONFIG_HIGHPTE |
270 | #define __pte_map(dir) pmd_page_vaddr(*(dir)) | 339 | #define __pte_map(pmd) pmd_page_vaddr(*(pmd)) |
271 | #define __pte_unmap(pte) do { } while (0) | 340 | #define __pte_unmap(pte) do { } while (0) |
272 | #else | 341 | #else |
273 | #define __pte_map(dir) ((pte_t *)kmap_atomic(pmd_page(*(dir))) + PTRS_PER_PTE) | 342 | #define __pte_map(pmd) (pte_t *)kmap_atomic(pmd_page(*(pmd))) |
274 | #define __pte_unmap(pte) kunmap_atomic((pte - PTRS_PER_PTE)) | 343 | #define __pte_unmap(pte) kunmap_atomic(pte) |
275 | #endif | 344 | #endif |
276 | 345 | ||
346 | #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | ||
347 | |||
348 | #define pte_offset_kernel(pmd,addr) (pmd_page_vaddr(*(pmd)) + pte_index(addr)) | ||
349 | |||
350 | #define pte_offset_map(pmd,addr) (__pte_map(pmd) + pte_index(addr)) | ||
351 | #define pte_unmap(pte) __pte_unmap(pte) | ||
352 | |||
353 | #define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) | ||
354 | #define pfn_pte(pfn,prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) | ||
355 | |||
356 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) | ||
357 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot) | ||
358 | |||
277 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | 359 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) |
360 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) | ||
278 | 361 | ||
279 | #if __LINUX_ARM_ARCH__ < 6 | 362 | #if __LINUX_ARM_ARCH__ < 6 |
280 | static inline void __sync_icache_dcache(pte_t pteval) | 363 | static inline void __sync_icache_dcache(pte_t pteval) |
@@ -295,15 +378,12 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
295 | } | 378 | } |
296 | } | 379 | } |
297 | 380 | ||
298 | /* | 381 | #define pte_none(pte) (!pte_val(pte)) |
299 | * The following only work if pte_present() is true. | ||
300 | * Undefined behaviour if not.. | ||
301 | */ | ||
302 | #define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) | 382 | #define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) |
303 | #define pte_write(pte) (pte_val(pte) & L_PTE_WRITE) | 383 | #define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) |
304 | #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) | 384 | #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) |
305 | #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) | 385 | #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) |
306 | #define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC) | 386 | #define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) |
307 | #define pte_special(pte) (0) | 387 | #define pte_special(pte) (0) |
308 | 388 | ||
309 | #define pte_present_user(pte) \ | 389 | #define pte_present_user(pte) \ |
@@ -313,8 +393,8 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
313 | #define PTE_BIT_FUNC(fn,op) \ | 393 | #define PTE_BIT_FUNC(fn,op) \ |
314 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | 394 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } |
315 | 395 | ||
316 | PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE); | 396 | PTE_BIT_FUNC(wrprotect, |= L_PTE_RDONLY); |
317 | PTE_BIT_FUNC(mkwrite, |= L_PTE_WRITE); | 397 | PTE_BIT_FUNC(mkwrite, &= ~L_PTE_RDONLY); |
318 | PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); | 398 | PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); |
319 | PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); | 399 | PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); |
320 | PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); | 400 | PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); |
@@ -322,101 +402,13 @@ PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); | |||
322 | 402 | ||
323 | static inline pte_t pte_mkspecial(pte_t pte) { return pte; } | 403 | static inline pte_t pte_mkspecial(pte_t pte) { return pte; } |
324 | 404 | ||
325 | #define __pgprot_modify(prot,mask,bits) \ | ||
326 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
327 | |||
328 | /* | ||
329 | * Mark the prot value as uncacheable and unbufferable. | ||
330 | */ | ||
331 | #define pgprot_noncached(prot) \ | ||
332 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) | ||
333 | #define pgprot_writecombine(prot) \ | ||
334 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) | ||
335 | #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE | ||
336 | #define pgprot_dmacoherent(prot) \ | ||
337 | __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE) | ||
338 | #define __HAVE_PHYS_MEM_ACCESS_PROT | ||
339 | struct file; | ||
340 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
341 | unsigned long size, pgprot_t vma_prot); | ||
342 | #else | ||
343 | #define pgprot_dmacoherent(prot) \ | ||
344 | __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED) | ||
345 | #endif | ||
346 | |||
347 | #define pmd_none(pmd) (!pmd_val(pmd)) | ||
348 | #define pmd_present(pmd) (pmd_val(pmd)) | ||
349 | #define pmd_bad(pmd) (pmd_val(pmd) & 2) | ||
350 | |||
351 | #define copy_pmd(pmdpd,pmdps) \ | ||
352 | do { \ | ||
353 | pmdpd[0] = pmdps[0]; \ | ||
354 | pmdpd[1] = pmdps[1]; \ | ||
355 | flush_pmd_entry(pmdpd); \ | ||
356 | } while (0) | ||
357 | |||
358 | #define pmd_clear(pmdp) \ | ||
359 | do { \ | ||
360 | pmdp[0] = __pmd(0); \ | ||
361 | pmdp[1] = __pmd(0); \ | ||
362 | clean_pmd_entry(pmdp); \ | ||
363 | } while (0) | ||
364 | |||
365 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) | ||
366 | { | ||
367 | unsigned long ptr; | ||
368 | |||
369 | ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1); | ||
370 | ptr += PTRS_PER_PTE * sizeof(void *); | ||
371 | |||
372 | return __va(ptr); | ||
373 | } | ||
374 | |||
375 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) | ||
376 | |||
377 | /* we don't need complex calculations here as the pmd is folded into the pgd */ | ||
378 | #define pmd_addr_end(addr,end) (end) | ||
379 | |||
380 | /* | ||
381 | * Conversion functions: convert a page and protection to a page entry, | ||
382 | * and a page entry and page directory to the page they refer to. | ||
383 | */ | ||
384 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot) | ||
385 | |||
386 | /* | ||
387 | * The "pgd_xxx()" functions here are trivial for a folded two-level | ||
388 | * setup: the pgd is never bad, and a pmd always exists (as it's folded | ||
389 | * into the pgd entry) | ||
390 | */ | ||
391 | #define pgd_none(pgd) (0) | ||
392 | #define pgd_bad(pgd) (0) | ||
393 | #define pgd_present(pgd) (1) | ||
394 | #define pgd_clear(pgdp) do { } while (0) | ||
395 | #define set_pgd(pgd,pgdp) do { } while (0) | ||
396 | |||
397 | /* to find an entry in a page-table-directory */ | ||
398 | #define pgd_index(addr) ((addr) >> PGDIR_SHIFT) | ||
399 | |||
400 | #define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr)) | ||
401 | |||
402 | /* to find an entry in a kernel page-table-directory */ | ||
403 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) | ||
404 | |||
405 | /* Find an entry in the second-level page table.. */ | ||
406 | #define pmd_offset(dir, addr) ((pmd_t *)(dir)) | ||
407 | |||
408 | /* Find an entry in the third-level page table.. */ | ||
409 | #define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | ||
410 | |||
411 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 405 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
412 | { | 406 | { |
413 | const unsigned long mask = L_PTE_EXEC | L_PTE_WRITE | L_PTE_USER; | 407 | const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER; |
414 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); | 408 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); |
415 | return pte; | 409 | return pte; |
416 | } | 410 | } |
417 | 411 | ||
418 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||
419 | |||
420 | /* | 412 | /* |
421 | * Encode and decode a swap entry. Swap entries are stored in the Linux | 413 | * Encode and decode a swap entry. Swap entries are stored in the Linux |
422 | * page tables as follows: | 414 | * page tables as follows: |
@@ -481,6 +473,9 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | |||
481 | 473 | ||
482 | #define pgtable_cache_init() do { } while (0) | 474 | #define pgtable_cache_init() do { } while (0) |
483 | 475 | ||
476 | void identity_mapping_add(pgd_t *, unsigned long, unsigned long); | ||
477 | void identity_mapping_del(pgd_t *, unsigned long, unsigned long); | ||
478 | |||
484 | #endif /* !__ASSEMBLY__ */ | 479 | #endif /* !__ASSEMBLY__ */ |
485 | 480 | ||
486 | #endif /* CONFIG_MMU */ | 481 | #endif /* CONFIG_MMU */ |
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h new file mode 100644 index 00000000000..a84628be1a7 --- /dev/null +++ b/arch/arm/include/asm/sched_clock.h | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * sched_clock.h: support for extending counters to full 64-bit ns counter | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #ifndef ASM_SCHED_CLOCK | ||
9 | #define ASM_SCHED_CLOCK | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/types.h> | ||
13 | |||
14 | struct clock_data { | ||
15 | u64 epoch_ns; | ||
16 | u32 epoch_cyc; | ||
17 | u32 epoch_cyc_copy; | ||
18 | u32 mult; | ||
19 | u32 shift; | ||
20 | }; | ||
21 | |||
22 | #define DEFINE_CLOCK_DATA(name) struct clock_data name | ||
23 | |||
24 | static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift) | ||
25 | { | ||
26 | return (cyc * mult) >> shift; | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * Atomically update the sched_clock epoch. Your update callback will | ||
31 | * be called from a timer before the counter wraps - read the current | ||
32 | * counter value, and call this function to safely move the epochs | ||
33 | * forward. Only use this from the update callback. | ||
34 | */ | ||
35 | static inline void update_sched_clock(struct clock_data *cd, u32 cyc, u32 mask) | ||
36 | { | ||
37 | unsigned long flags; | ||
38 | u64 ns = cd->epoch_ns + | ||
39 | cyc_to_ns((cyc - cd->epoch_cyc) & mask, cd->mult, cd->shift); | ||
40 | |||
41 | /* | ||
42 | * Write epoch_cyc and epoch_ns in a way that the update is | ||
43 | * detectable in cyc_to_fixed_sched_clock(). | ||
44 | */ | ||
45 | raw_local_irq_save(flags); | ||
46 | cd->epoch_cyc = cyc; | ||
47 | smp_wmb(); | ||
48 | cd->epoch_ns = ns; | ||
49 | smp_wmb(); | ||
50 | cd->epoch_cyc_copy = cyc; | ||
51 | raw_local_irq_restore(flags); | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * If your clock rate is known at compile time, using this will allow | ||
56 | * you to optimize the mult/shift loads away. This is paired with | ||
57 | * init_fixed_sched_clock() to ensure that your mult/shift are correct. | ||
58 | */ | ||
59 | static inline unsigned long long cyc_to_fixed_sched_clock(struct clock_data *cd, | ||
60 | u32 cyc, u32 mask, u32 mult, u32 shift) | ||
61 | { | ||
62 | u64 epoch_ns; | ||
63 | u32 epoch_cyc; | ||
64 | |||
65 | /* | ||
66 | * Load the epoch_cyc and epoch_ns atomically. We do this by | ||
67 | * ensuring that we always write epoch_cyc, epoch_ns and | ||
68 | * epoch_cyc_copy in strict order, and read them in strict order. | ||
69 | * If epoch_cyc and epoch_cyc_copy are not equal, then we're in | ||
70 | * the middle of an update, and we should repeat the load. | ||
71 | */ | ||
72 | do { | ||
73 | epoch_cyc = cd->epoch_cyc; | ||
74 | smp_rmb(); | ||
75 | epoch_ns = cd->epoch_ns; | ||
76 | smp_rmb(); | ||
77 | } while (epoch_cyc != cd->epoch_cyc_copy); | ||
78 | |||
79 | return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, mult, shift); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Otherwise, you need to use this, which will obtain the mult/shift | ||
84 | * from the clock_data structure. Use init_sched_clock() with this. | ||
85 | */ | ||
86 | static inline unsigned long long cyc_to_sched_clock(struct clock_data *cd, | ||
87 | u32 cyc, u32 mask) | ||
88 | { | ||
89 | return cyc_to_fixed_sched_clock(cd, cyc, mask, cd->mult, cd->shift); | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Initialize the clock data - calculate the appropriate multiplier | ||
94 | * and shift. Also setup a timer to ensure that the epoch is refreshed | ||
95 | * at the appropriate time interval, which will call your update | ||
96 | * handler. | ||
97 | */ | ||
98 | void init_sched_clock(struct clock_data *, void (*)(void), | ||
99 | unsigned int, unsigned long); | ||
100 | |||
101 | /* | ||
102 | * Use this initialization function rather than init_sched_clock() if | ||
103 | * you're using cyc_to_fixed_sched_clock, which will warn if your | ||
104 | * constants are incorrect. | ||
105 | */ | ||
106 | static inline void init_fixed_sched_clock(struct clock_data *cd, | ||
107 | void (*update)(void), unsigned int bits, unsigned long rate, | ||
108 | u32 mult, u32 shift) | ||
109 | { | ||
110 | init_sched_clock(cd, update, bits, rate); | ||
111 | if (cd->mult != mult || cd->shift != shift) { | ||
112 | pr_crit("sched_clock: wrong multiply/shift: %u>>%u vs calculated %u>>%u\n" | ||
113 | "sched_clock: fix multiply/shift to avoid scheduler hiccups\n", | ||
114 | mult, shift, cd->mult, cd->shift); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | #endif | ||
diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h index 4fc1565e4f9..316bb2b2be3 100644 --- a/arch/arm/include/asm/sizes.h +++ b/arch/arm/include/asm/sizes.h | |||
@@ -13,9 +13,6 @@ | |||
13 | * along with this program; if not, write to the Free Software | 13 | * along with this program; if not, write to the Free Software |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
15 | */ | 15 | */ |
16 | /* DO NOT EDIT!! - this file automatically generated | ||
17 | * from .s file by awk -f s2h.awk | ||
18 | */ | ||
19 | /* Size definitions | 16 | /* Size definitions |
20 | * Copyright (C) ARM Limited 1998. All rights reserved. | 17 | * Copyright (C) ARM Limited 1998. All rights reserved. |
21 | */ | 18 | */ |
@@ -25,6 +22,9 @@ | |||
25 | 22 | ||
26 | /* handy sizes */ | 23 | /* handy sizes */ |
27 | #define SZ_16 0x00000010 | 24 | #define SZ_16 0x00000010 |
25 | #define SZ_32 0x00000020 | ||
26 | #define SZ_64 0x00000040 | ||
27 | #define SZ_128 0x00000080 | ||
28 | #define SZ_256 0x00000100 | 28 | #define SZ_256 0x00000100 |
29 | #define SZ_512 0x00000200 | 29 | #define SZ_512 0x00000200 |
30 | 30 | ||
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 3d05190797c..96ed521f240 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h | |||
@@ -33,27 +33,23 @@ struct seq_file; | |||
33 | /* | 33 | /* |
34 | * generate IPI list text | 34 | * generate IPI list text |
35 | */ | 35 | */ |
36 | extern void show_ipi_list(struct seq_file *p); | 36 | extern void show_ipi_list(struct seq_file *, int); |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Called from assembly code, this handles an IPI. | 39 | * Called from assembly code, this handles an IPI. |
40 | */ | 40 | */ |
41 | asmlinkage void do_IPI(struct pt_regs *regs); | 41 | asmlinkage void do_IPI(int ipinr, struct pt_regs *regs); |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Setup the set of possible CPUs (via set_cpu_possible) | 44 | * Setup the set of possible CPUs (via set_cpu_possible) |
45 | */ | 45 | */ |
46 | extern void smp_init_cpus(void); | 46 | extern void smp_init_cpus(void); |
47 | 47 | ||
48 | /* | ||
49 | * Move global data into per-processor storage. | ||
50 | */ | ||
51 | extern void smp_store_cpu_info(unsigned int cpuid); | ||
52 | 48 | ||
53 | /* | 49 | /* |
54 | * Raise an IPI cross call on CPUs in callmap. | 50 | * Raise an IPI cross call on CPUs in callmap. |
55 | */ | 51 | */ |
56 | extern void smp_cross_call(const struct cpumask *mask); | 52 | extern void smp_cross_call(const struct cpumask *mask, int ipi); |
57 | 53 | ||
58 | /* | 54 | /* |
59 | * Boot a secondary CPU, and assign it the specified idle task. | 55 | * Boot a secondary CPU, and assign it the specified idle task. |
@@ -73,6 +69,11 @@ asmlinkage void secondary_start_kernel(void); | |||
73 | extern void platform_secondary_init(unsigned int cpu); | 69 | extern void platform_secondary_init(unsigned int cpu); |
74 | 70 | ||
75 | /* | 71 | /* |
72 | * Initialize cpu_possible map, and enable coherency | ||
73 | */ | ||
74 | extern void platform_smp_prepare_cpus(unsigned int); | ||
75 | |||
76 | /* | ||
76 | * Initial data for bringing up a secondary CPU. | 77 | * Initial data for bringing up a secondary CPU. |
77 | */ | 78 | */ |
78 | struct secondary_data { | 79 | struct secondary_data { |
@@ -97,6 +98,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | |||
97 | /* | 98 | /* |
98 | * show local interrupt info | 99 | * show local interrupt info |
99 | */ | 100 | */ |
100 | extern void show_local_irqs(struct seq_file *); | 101 | extern void show_local_irqs(struct seq_file *, int); |
101 | 102 | ||
102 | #endif /* ifndef __ASM_ARM_SMP_H */ | 103 | #endif /* ifndef __ASM_ARM_SMP_H */ |
diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h deleted file mode 100644 index 6a9307d6490..00000000000 --- a/arch/arm/include/asm/smp_mpidr.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | #ifndef ASMARM_SMP_MIDR_H | ||
2 | #define ASMARM_SMP_MIDR_H | ||
3 | |||
4 | #define hard_smp_processor_id() \ | ||
5 | ({ \ | ||
6 | unsigned int cpunum; \ | ||
7 | __asm__("\n" \ | ||
8 | "1: mrc p15, 0, %0, c0, c0, 5\n" \ | ||
9 | " .pushsection \".alt.smp.init\", \"a\"\n"\ | ||
10 | " .long 1b\n" \ | ||
11 | " mov %0, #0\n" \ | ||
12 | " .popsection" \ | ||
13 | : "=r" (cpunum)); \ | ||
14 | cpunum &= 0x0F; \ | ||
15 | }) | ||
16 | |||
17 | #endif | ||
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h index 634f357be6b..fed9981fba0 100644 --- a/arch/arm/include/asm/smp_twd.h +++ b/arch/arm/include/asm/smp_twd.h | |||
@@ -22,7 +22,6 @@ struct clock_event_device; | |||
22 | 22 | ||
23 | extern void __iomem *twd_base; | 23 | extern void __iomem *twd_base; |
24 | 24 | ||
25 | void twd_timer_stop(void); | ||
26 | int twd_timer_ack(void); | 25 | int twd_timer_ack(void); |
27 | void twd_timer_setup(struct clock_event_device *); | 26 | void twd_timer_setup(struct clock_event_device *); |
28 | 27 | ||
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index ec4327a4653..97f6d60297d 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
@@ -124,6 +124,13 @@ extern unsigned int user_debug; | |||
124 | #define vectors_high() (0) | 124 | #define vectors_high() (0) |
125 | #endif | 125 | #endif |
126 | 126 | ||
127 | #if __LINUX_ARM_ARCH__ >= 7 || \ | ||
128 | (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K)) | ||
129 | #define sev() __asm__ __volatile__ ("sev" : : : "memory") | ||
130 | #define wfe() __asm__ __volatile__ ("wfe" : : : "memory") | ||
131 | #define wfi() __asm__ __volatile__ ("wfi" : : : "memory") | ||
132 | #endif | ||
133 | |||
127 | #if __LINUX_ARM_ARCH__ >= 7 | 134 | #if __LINUX_ARM_ARCH__ >= 7 |
128 | #define isb() __asm__ __volatile__ ("isb" : : : "memory") | 135 | #define isb() __asm__ __volatile__ ("isb" : : : "memory") |
129 | #define dsb() __asm__ __volatile__ ("dsb" : : : "memory") | 136 | #define dsb() __asm__ __volatile__ ("dsb" : : : "memory") |
@@ -155,6 +162,7 @@ extern unsigned int user_debug; | |||
155 | #define rmb() dmb() | 162 | #define rmb() dmb() |
156 | #define wmb() mb() | 163 | #define wmb() mb() |
157 | #else | 164 | #else |
165 | #include <asm/memory.h> | ||
158 | #define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) | 166 | #define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) |
159 | #define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) | 167 | #define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) |
160 | #define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) | 168 | #define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0) |
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index 124475afb00..1b960d5ef6a 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h | |||
@@ -46,4 +46,6 @@ static inline int in_exception_text(unsigned long ptr) | |||
46 | extern void __init early_trap_init(void); | 46 | extern void __init early_trap_init(void); |
47 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); | 47 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); |
48 | 48 | ||
49 | extern void *vectors_page; | ||
50 | |||
49 | #endif | 51 | #endif |
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 33e4a48fe10..b293616a1a1 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h | |||
@@ -227,7 +227,7 @@ do { \ | |||
227 | 227 | ||
228 | #define __get_user_asm_byte(x,addr,err) \ | 228 | #define __get_user_asm_byte(x,addr,err) \ |
229 | __asm__ __volatile__( \ | 229 | __asm__ __volatile__( \ |
230 | "1: ldrbt %1,[%2]\n" \ | 230 | "1: " T(ldrb) " %1,[%2],#0\n" \ |
231 | "2:\n" \ | 231 | "2:\n" \ |
232 | " .pushsection .fixup,\"ax\"\n" \ | 232 | " .pushsection .fixup,\"ax\"\n" \ |
233 | " .align 2\n" \ | 233 | " .align 2\n" \ |
@@ -263,7 +263,7 @@ do { \ | |||
263 | 263 | ||
264 | #define __get_user_asm_word(x,addr,err) \ | 264 | #define __get_user_asm_word(x,addr,err) \ |
265 | __asm__ __volatile__( \ | 265 | __asm__ __volatile__( \ |
266 | "1: ldrt %1,[%2]\n" \ | 266 | "1: " T(ldr) " %1,[%2],#0\n" \ |
267 | "2:\n" \ | 267 | "2:\n" \ |
268 | " .pushsection .fixup,\"ax\"\n" \ | 268 | " .pushsection .fixup,\"ax\"\n" \ |
269 | " .align 2\n" \ | 269 | " .align 2\n" \ |
@@ -308,7 +308,7 @@ do { \ | |||
308 | 308 | ||
309 | #define __put_user_asm_byte(x,__pu_addr,err) \ | 309 | #define __put_user_asm_byte(x,__pu_addr,err) \ |
310 | __asm__ __volatile__( \ | 310 | __asm__ __volatile__( \ |
311 | "1: strbt %1,[%2]\n" \ | 311 | "1: " T(strb) " %1,[%2],#0\n" \ |
312 | "2:\n" \ | 312 | "2:\n" \ |
313 | " .pushsection .fixup,\"ax\"\n" \ | 313 | " .pushsection .fixup,\"ax\"\n" \ |
314 | " .align 2\n" \ | 314 | " .align 2\n" \ |
@@ -341,7 +341,7 @@ do { \ | |||
341 | 341 | ||
342 | #define __put_user_asm_word(x,__pu_addr,err) \ | 342 | #define __put_user_asm_word(x,__pu_addr,err) \ |
343 | __asm__ __volatile__( \ | 343 | __asm__ __volatile__( \ |
344 | "1: strt %1,[%2]\n" \ | 344 | "1: " T(str) " %1,[%2],#0\n" \ |
345 | "2:\n" \ | 345 | "2:\n" \ |
346 | " .pushsection .fixup,\"ax\"\n" \ | 346 | " .pushsection .fixup,\"ax\"\n" \ |
347 | " .align 2\n" \ | 347 | " .align 2\n" \ |
@@ -366,10 +366,10 @@ do { \ | |||
366 | 366 | ||
367 | #define __put_user_asm_dword(x,__pu_addr,err) \ | 367 | #define __put_user_asm_dword(x,__pu_addr,err) \ |
368 | __asm__ __volatile__( \ | 368 | __asm__ __volatile__( \ |
369 | ARM( "1: strt " __reg_oper1 ", [%1], #4\n" ) \ | 369 | ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \ |
370 | ARM( "2: strt " __reg_oper0 ", [%1]\n" ) \ | 370 | ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \ |
371 | THUMB( "1: strt " __reg_oper1 ", [%1]\n" ) \ | 371 | THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \ |
372 | THUMB( "2: strt " __reg_oper0 ", [%1, #4]\n" ) \ | 372 | THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \ |
373 | "3:\n" \ | 373 | "3:\n" \ |
374 | " .pushsection .fixup,\"ax\"\n" \ | 374 | " .pushsection .fixup,\"ax\"\n" \ |
375 | " .align 2\n" \ | 375 | " .align 2\n" \ |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index c73abe4b7e7..185ee822c93 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -29,7 +29,8 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o | |||
29 | obj-$(CONFIG_ARTHUR) += arthur.o | 29 | obj-$(CONFIG_ARTHUR) += arthur.o |
30 | obj-$(CONFIG_ISA_DMA) += dma-isa.o | 30 | obj-$(CONFIG_ISA_DMA) += dma-isa.o |
31 | obj-$(CONFIG_PCI) += bios32.o isa.o | 31 | obj-$(CONFIG_PCI) += bios32.o isa.o |
32 | obj-$(CONFIG_SMP) += smp.o | 32 | obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o |
33 | obj-$(CONFIG_SMP) += smp.o smp_tlb.o | ||
33 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o | 34 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o |
34 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o | 35 | obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o |
35 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 36 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
@@ -43,6 +44,8 @@ obj-$(CONFIG_KGDB) += kgdb.o | |||
43 | obj-$(CONFIG_ARM_UNWIND) += unwind.o | 44 | obj-$(CONFIG_ARM_UNWIND) += unwind.o |
44 | obj-$(CONFIG_HAVE_TCM) += tcm.o | 45 | obj-$(CONFIG_HAVE_TCM) += tcm.o |
45 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 46 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
47 | obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o | ||
48 | CFLAGS_swp_emulate.o := -Wa,-march=armv7-a | ||
46 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o | 49 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o |
47 | 50 | ||
48 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o | 51 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 36199ffc4cc..2b46fea36c9 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -25,42 +25,22 @@ | |||
25 | #include <asm/tls.h> | 25 | #include <asm/tls.h> |
26 | 26 | ||
27 | #include "entry-header.S" | 27 | #include "entry-header.S" |
28 | #include <asm/entry-macro-multi.S> | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * Interrupt handling. Preserves r7, r8, r9 | 31 | * Interrupt handling. Preserves r7, r8, r9 |
31 | */ | 32 | */ |
32 | .macro irq_handler | 33 | .macro irq_handler |
33 | get_irqnr_preamble r5, lr | 34 | #ifdef CONFIG_MULTI_IRQ_HANDLER |
34 | 1: get_irqnr_and_base r0, r6, r5, lr | 35 | ldr r5, =handle_arch_irq |
35 | movne r1, sp | 36 | mov r0, sp |
36 | @ | 37 | ldr r5, [r5] |
37 | @ routine called with r0 = irq number, r1 = struct pt_regs * | 38 | adr lr, BSYM(9997f) |
38 | @ | 39 | teq r5, #0 |
39 | adrne lr, BSYM(1b) | 40 | movne pc, r5 |
40 | bne asm_do_IRQ | ||
41 | |||
42 | #ifdef CONFIG_SMP | ||
43 | /* | ||
44 | * XXX | ||
45 | * | ||
46 | * this macro assumes that irqstat (r6) and base (r5) are | ||
47 | * preserved from get_irqnr_and_base above | ||
48 | */ | ||
49 | ALT_SMP(test_for_ipi r0, r6, r5, lr) | ||
50 | ALT_UP_B(9997f) | ||
51 | movne r0, sp | ||
52 | adrne lr, BSYM(1b) | ||
53 | bne do_IPI | ||
54 | |||
55 | #ifdef CONFIG_LOCAL_TIMERS | ||
56 | test_for_ltirq r0, r6, r5, lr | ||
57 | movne r0, sp | ||
58 | adrne lr, BSYM(1b) | ||
59 | bne do_local_timer | ||
60 | #endif | 41 | #endif |
42 | arch_irq_handler_default | ||
61 | 9997: | 43 | 9997: |
62 | #endif | ||
63 | |||
64 | .endm | 44 | .endm |
65 | 45 | ||
66 | #ifdef CONFIG_KPROBES | 46 | #ifdef CONFIG_KPROBES |
@@ -739,7 +719,7 @@ ENTRY(__switch_to) | |||
739 | THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack | 719 | THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack |
740 | THUMB( str sp, [ip], #4 ) | 720 | THUMB( str sp, [ip], #4 ) |
741 | THUMB( str lr, [ip], #4 ) | 721 | THUMB( str lr, [ip], #4 ) |
742 | #ifdef CONFIG_MMU | 722 | #ifdef CONFIG_CPU_USE_DOMAINS |
743 | ldr r6, [r2, #TI_CPU_DOMAIN] | 723 | ldr r6, [r2, #TI_CPU_DOMAIN] |
744 | #endif | 724 | #endif |
745 | set_tls r3, r4, r5 | 725 | set_tls r3, r4, r5 |
@@ -748,7 +728,7 @@ ENTRY(__switch_to) | |||
748 | ldr r8, =__stack_chk_guard | 728 | ldr r8, =__stack_chk_guard |
749 | ldr r7, [r7, #TSK_STACK_CANARY] | 729 | ldr r7, [r7, #TSK_STACK_CANARY] |
750 | #endif | 730 | #endif |
751 | #ifdef CONFIG_MMU | 731 | #ifdef CONFIG_CPU_USE_DOMAINS |
752 | mcr p15, 0, r6, c3, c0, 0 @ Set domain register | 732 | mcr p15, 0, r6, c3, c0, 0 @ Set domain register |
753 | #endif | 733 | #endif |
754 | mov r5, r0 | 734 | mov r5, r0 |
@@ -846,7 +826,7 @@ __kuser_helper_start: | |||
846 | */ | 826 | */ |
847 | 827 | ||
848 | __kuser_memory_barrier: @ 0xffff0fa0 | 828 | __kuser_memory_barrier: @ 0xffff0fa0 |
849 | smp_dmb | 829 | smp_dmb arm |
850 | usr_ret lr | 830 | usr_ret lr |
851 | 831 | ||
852 | .align 5 | 832 | .align 5 |
@@ -963,7 +943,7 @@ kuser_cmpxchg_fixup: | |||
963 | 943 | ||
964 | #else | 944 | #else |
965 | 945 | ||
966 | smp_dmb | 946 | smp_dmb arm |
967 | 1: ldrex r3, [r2] | 947 | 1: ldrex r3, [r2] |
968 | subs r3, r3, r0 | 948 | subs r3, r3, r0 |
969 | strexeq r3, r1, [r2] | 949 | strexeq r3, r1, [r2] |
@@ -1249,3 +1229,9 @@ cr_alignment: | |||
1249 | .space 4 | 1229 | .space 4 |
1250 | cr_no_alignment: | 1230 | cr_no_alignment: |
1251 | .space 4 | 1231 | .space 4 |
1232 | |||
1233 | #ifdef CONFIG_MULTI_IRQ_HANDLER | ||
1234 | .globl handle_arch_irq | ||
1235 | handle_arch_irq: | ||
1236 | .space 4 | ||
1237 | #endif | ||
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index aae802ee12f..1e7b04a40a3 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -29,6 +29,9 @@ ret_fast_syscall: | |||
29 | ldr r1, [tsk, #TI_FLAGS] | 29 | ldr r1, [tsk, #TI_FLAGS] |
30 | tst r1, #_TIF_WORK_MASK | 30 | tst r1, #_TIF_WORK_MASK |
31 | bne fast_work_pending | 31 | bne fast_work_pending |
32 | #if defined(CONFIG_IRQSOFF_TRACER) | ||
33 | asm_trace_hardirqs_on | ||
34 | #endif | ||
32 | 35 | ||
33 | /* perform architecture specific actions before user return */ | 36 | /* perform architecture specific actions before user return */ |
34 | arch_ret_to_user r1, lr | 37 | arch_ret_to_user r1, lr |
@@ -65,6 +68,9 @@ ret_slow_syscall: | |||
65 | tst r1, #_TIF_WORK_MASK | 68 | tst r1, #_TIF_WORK_MASK |
66 | bne work_pending | 69 | bne work_pending |
67 | no_work_pending: | 70 | no_work_pending: |
71 | #if defined(CONFIG_IRQSOFF_TRACER) | ||
72 | asm_trace_hardirqs_on | ||
73 | #endif | ||
68 | /* perform architecture specific actions before user return */ | 74 | /* perform architecture specific actions before user return */ |
69 | arch_ret_to_user r1, lr | 75 | arch_ret_to_user r1, lr |
70 | 76 | ||
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 6ff7919613d..e72dc34eea1 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/fiq.h> | 45 | #include <asm/fiq.h> |
46 | #include <asm/irq.h> | 46 | #include <asm/irq.h> |
47 | #include <asm/system.h> | 47 | #include <asm/system.h> |
48 | #include <asm/traps.h> | ||
48 | 49 | ||
49 | static unsigned long no_fiq_insn; | 50 | static unsigned long no_fiq_insn; |
50 | 51 | ||
@@ -67,17 +68,22 @@ static struct fiq_handler default_owner = { | |||
67 | 68 | ||
68 | static struct fiq_handler *current_fiq = &default_owner; | 69 | static struct fiq_handler *current_fiq = &default_owner; |
69 | 70 | ||
70 | int show_fiq_list(struct seq_file *p, void *v) | 71 | int show_fiq_list(struct seq_file *p, int prec) |
71 | { | 72 | { |
72 | if (current_fiq != &default_owner) | 73 | if (current_fiq != &default_owner) |
73 | seq_printf(p, "FIQ: %s\n", current_fiq->name); | 74 | seq_printf(p, "%*s: %s\n", prec, "FIQ", |
75 | current_fiq->name); | ||
74 | 76 | ||
75 | return 0; | 77 | return 0; |
76 | } | 78 | } |
77 | 79 | ||
78 | void set_fiq_handler(void *start, unsigned int length) | 80 | void set_fiq_handler(void *start, unsigned int length) |
79 | { | 81 | { |
82 | #if defined(CONFIG_CPU_USE_DOMAINS) | ||
80 | memcpy((void *)0xffff001c, start, length); | 83 | memcpy((void *)0xffff001c, start, length); |
84 | #else | ||
85 | memcpy(vectors_page + 0x1c, start, length); | ||
86 | #endif | ||
81 | flush_icache_range(0xffff001c, 0xffff001c + length); | 87 | flush_icache_range(0xffff001c, 0xffff001c + length); |
82 | if (!vectors_high()) | 88 | if (!vectors_high()) |
83 | flush_icache_range(0x1c, 0x1c + length); | 89 | flush_icache_range(0x1c, 0x1c + length); |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 6bd82d25683..f17d9a09e8f 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -91,6 +91,11 @@ ENTRY(stext) | |||
91 | movs r8, r5 @ invalid machine (r5=0)? | 91 | movs r8, r5 @ invalid machine (r5=0)? |
92 | THUMB( it eq ) @ force fixup-able long branch encoding | 92 | THUMB( it eq ) @ force fixup-able long branch encoding |
93 | beq __error_a @ yes, error 'a' | 93 | beq __error_a @ yes, error 'a' |
94 | |||
95 | /* | ||
96 | * r1 = machine no, r2 = atags, | ||
97 | * r8 = machinfo, r9 = cpuid, r10 = procinfo | ||
98 | */ | ||
94 | bl __vet_atags | 99 | bl __vet_atags |
95 | #ifdef CONFIG_SMP_ON_UP | 100 | #ifdef CONFIG_SMP_ON_UP |
96 | bl __fixup_smp | 101 | bl __fixup_smp |
@@ -387,19 +392,19 @@ ENDPROC(__turn_mmu_on) | |||
387 | 392 | ||
388 | #ifdef CONFIG_SMP_ON_UP | 393 | #ifdef CONFIG_SMP_ON_UP |
389 | __fixup_smp: | 394 | __fixup_smp: |
390 | mov r7, #0x00070000 | 395 | mov r4, #0x00070000 |
391 | orr r6, r7, #0xff000000 @ mask 0xff070000 | 396 | orr r3, r4, #0xff000000 @ mask 0xff070000 |
392 | orr r7, r7, #0x41000000 @ val 0x41070000 | 397 | orr r4, r4, #0x41000000 @ val 0x41070000 |
393 | and r0, r9, r6 | 398 | and r0, r9, r3 |
394 | teq r0, r7 @ ARM CPU and ARMv6/v7? | 399 | teq r0, r4 @ ARM CPU and ARMv6/v7? |
395 | bne __fixup_smp_on_up @ no, assume UP | 400 | bne __fixup_smp_on_up @ no, assume UP |
396 | 401 | ||
397 | orr r6, r6, #0x0000ff00 | 402 | orr r3, r3, #0x0000ff00 |
398 | orr r6, r6, #0x000000f0 @ mask 0xff07fff0 | 403 | orr r3, r3, #0x000000f0 @ mask 0xff07fff0 |
399 | orr r7, r7, #0x0000b000 | 404 | orr r4, r4, #0x0000b000 |
400 | orr r7, r7, #0x00000020 @ val 0x4107b020 | 405 | orr r4, r4, #0x00000020 @ val 0x4107b020 |
401 | and r0, r9, r6 | 406 | and r0, r9, r3 |
402 | teq r0, r7 @ ARM 11MPCore? | 407 | teq r0, r4 @ ARM 11MPCore? |
403 | moveq pc, lr @ yes, assume SMP | 408 | moveq pc, lr @ yes, assume SMP |
404 | 409 | ||
405 | mrc p15, 0, r0, c0, c0, 5 @ read MPIDR | 410 | mrc p15, 0, r0, c0, c0, 5 @ read MPIDR |
@@ -408,15 +413,22 @@ __fixup_smp: | |||
408 | 413 | ||
409 | __fixup_smp_on_up: | 414 | __fixup_smp_on_up: |
410 | adr r0, 1f | 415 | adr r0, 1f |
411 | ldmia r0, {r3, r6, r7} | 416 | ldmia r0, {r3 - r5} |
412 | sub r3, r0, r3 | 417 | sub r3, r0, r3 |
413 | add r6, r6, r3 | 418 | add r4, r4, r3 |
414 | add r7, r7, r3 | 419 | add r5, r5, r3 |
415 | 2: cmp r6, r7 | 420 | 2: cmp r4, r5 |
416 | ldmia r6!, {r0, r4} | 421 | movhs pc, lr |
417 | strlo r4, [r0, r3] | 422 | ldmia r4!, {r0, r6} |
418 | blo 2b | 423 | ARM( str r6, [r0, r3] ) |
419 | mov pc, lr | 424 | THUMB( add r0, r0, r3 ) |
425 | #ifdef __ARMEB__ | ||
426 | THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. | ||
427 | #endif | ||
428 | THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords | ||
429 | THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. | ||
430 | THUMB( strh r6, [r0] ) | ||
431 | b 2b | ||
420 | ENDPROC(__fixup_smp) | 432 | ENDPROC(__fixup_smp) |
421 | 433 | ||
422 | .align | 434 | .align |
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 6d616333340..8135438b881 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/ftrace.h> | 38 | #include <linux/ftrace.h> |
39 | 39 | ||
40 | #include <asm/system.h> | 40 | #include <asm/system.h> |
41 | #include <asm/mach/arch.h> | ||
41 | #include <asm/mach/irq.h> | 42 | #include <asm/mach/irq.h> |
42 | #include <asm/mach/time.h> | 43 | #include <asm/mach/time.h> |
43 | 44 | ||
@@ -48,8 +49,6 @@ | |||
48 | #define irq_finish(irq) do { } while (0) | 49 | #define irq_finish(irq) do { } while (0) |
49 | #endif | 50 | #endif |
50 | 51 | ||
51 | unsigned int arch_nr_irqs; | ||
52 | void (*init_arch_irq)(void) __initdata = NULL; | ||
53 | unsigned long irq_err_count; | 52 | unsigned long irq_err_count; |
54 | 53 | ||
55 | int show_interrupts(struct seq_file *p, void *v) | 54 | int show_interrupts(struct seq_file *p, void *v) |
@@ -58,11 +57,20 @@ int show_interrupts(struct seq_file *p, void *v) | |||
58 | struct irq_desc *desc; | 57 | struct irq_desc *desc; |
59 | struct irqaction * action; | 58 | struct irqaction * action; |
60 | unsigned long flags; | 59 | unsigned long flags; |
60 | int prec, n; | ||
61 | |||
62 | for (prec = 3, n = 1000; prec < 10 && n <= nr_irqs; prec++) | ||
63 | n *= 10; | ||
64 | |||
65 | #ifdef CONFIG_SMP | ||
66 | if (prec < 4) | ||
67 | prec = 4; | ||
68 | #endif | ||
61 | 69 | ||
62 | if (i == 0) { | 70 | if (i == 0) { |
63 | char cpuname[12]; | 71 | char cpuname[12]; |
64 | 72 | ||
65 | seq_printf(p, " "); | 73 | seq_printf(p, "%*s ", prec, ""); |
66 | for_each_present_cpu(cpu) { | 74 | for_each_present_cpu(cpu) { |
67 | sprintf(cpuname, "CPU%d", cpu); | 75 | sprintf(cpuname, "CPU%d", cpu); |
68 | seq_printf(p, " %10s", cpuname); | 76 | seq_printf(p, " %10s", cpuname); |
@@ -77,7 +85,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
77 | if (!action) | 85 | if (!action) |
78 | goto unlock; | 86 | goto unlock; |
79 | 87 | ||
80 | seq_printf(p, "%3d: ", i); | 88 | seq_printf(p, "%*d: ", prec, i); |
81 | for_each_present_cpu(cpu) | 89 | for_each_present_cpu(cpu) |
82 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); | 90 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); |
83 | seq_printf(p, " %10s", desc->chip->name ? : "-"); | 91 | seq_printf(p, " %10s", desc->chip->name ? : "-"); |
@@ -90,13 +98,15 @@ unlock: | |||
90 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 98 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
91 | } else if (i == nr_irqs) { | 99 | } else if (i == nr_irqs) { |
92 | #ifdef CONFIG_FIQ | 100 | #ifdef CONFIG_FIQ |
93 | show_fiq_list(p, v); | 101 | show_fiq_list(p, prec); |
94 | #endif | 102 | #endif |
95 | #ifdef CONFIG_SMP | 103 | #ifdef CONFIG_SMP |
96 | show_ipi_list(p); | 104 | show_ipi_list(p, prec); |
97 | show_local_irqs(p); | 105 | #endif |
106 | #ifdef CONFIG_LOCAL_TIMERS | ||
107 | show_local_irqs(p, prec); | ||
98 | #endif | 108 | #endif |
99 | seq_printf(p, "Err: %10lu\n", irq_err_count); | 109 | seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); |
100 | } | 110 | } |
101 | return 0; | 111 | return 0; |
102 | } | 112 | } |
@@ -156,13 +166,13 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) | |||
156 | 166 | ||
157 | void __init init_IRQ(void) | 167 | void __init init_IRQ(void) |
158 | { | 168 | { |
159 | init_arch_irq(); | 169 | machine_desc->init_irq(); |
160 | } | 170 | } |
161 | 171 | ||
162 | #ifdef CONFIG_SPARSE_IRQ | 172 | #ifdef CONFIG_SPARSE_IRQ |
163 | int __init arch_probe_nr_irqs(void) | 173 | int __init arch_probe_nr_irqs(void) |
164 | { | 174 | { |
165 | nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS; | 175 | nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS; |
166 | return nr_irqs; | 176 | return nr_irqs; |
167 | } | 177 | } |
168 | #endif | 178 | #endif |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 3a8fd5140d7..30ead135ff5 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -23,6 +23,8 @@ extern unsigned long kexec_indirection_page; | |||
23 | extern unsigned long kexec_mach_type; | 23 | extern unsigned long kexec_mach_type; |
24 | extern unsigned long kexec_boot_atags; | 24 | extern unsigned long kexec_boot_atags; |
25 | 25 | ||
26 | static atomic_t waiting_for_crash_ipi; | ||
27 | |||
26 | /* | 28 | /* |
27 | * Provide a dummy crash_notes definition while crash dump arrives to arm. | 29 | * Provide a dummy crash_notes definition while crash dump arrives to arm. |
28 | * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. | 30 | * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. |
@@ -37,9 +39,37 @@ void machine_kexec_cleanup(struct kimage *image) | |||
37 | { | 39 | { |
38 | } | 40 | } |
39 | 41 | ||
42 | void machine_crash_nonpanic_core(void *unused) | ||
43 | { | ||
44 | struct pt_regs regs; | ||
45 | |||
46 | crash_setup_regs(®s, NULL); | ||
47 | printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n", | ||
48 | smp_processor_id()); | ||
49 | crash_save_cpu(®s, smp_processor_id()); | ||
50 | flush_cache_all(); | ||
51 | |||
52 | atomic_dec(&waiting_for_crash_ipi); | ||
53 | while (1) | ||
54 | cpu_relax(); | ||
55 | } | ||
56 | |||
40 | void machine_crash_shutdown(struct pt_regs *regs) | 57 | void machine_crash_shutdown(struct pt_regs *regs) |
41 | { | 58 | { |
59 | unsigned long msecs; | ||
60 | |||
42 | local_irq_disable(); | 61 | local_irq_disable(); |
62 | |||
63 | atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); | ||
64 | smp_call_function(machine_crash_nonpanic_core, NULL, false); | ||
65 | msecs = 1000; /* Wait at most a second for the other cpus to stop */ | ||
66 | while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { | ||
67 | mdelay(1); | ||
68 | msecs--; | ||
69 | } | ||
70 | if (atomic_read(&waiting_for_crash_ipi) > 0) | ||
71 | printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n"); | ||
72 | |||
43 | crash_save_cpu(regs, smp_processor_id()); | 73 | crash_save_cpu(regs, smp_processor_id()); |
44 | 74 | ||
45 | printk(KERN_INFO "Loading crashdump kernel...\n"); | 75 | printk(KERN_INFO "Loading crashdump kernel...\n"); |
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index d9bd786ce23..0c1bb68ff4a 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c | |||
@@ -67,35 +67,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, | |||
67 | char *secstrings, | 67 | char *secstrings, |
68 | struct module *mod) | 68 | struct module *mod) |
69 | { | 69 | { |
70 | #ifdef CONFIG_ARM_UNWIND | ||
71 | Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; | ||
72 | struct arm_unwind_mapping *maps = mod->arch.map; | ||
73 | |||
74 | for (s = sechdrs; s < sechdrs_end; s++) { | ||
75 | char const *secname = secstrings + s->sh_name; | ||
76 | |||
77 | if (strcmp(".ARM.exidx.init.text", secname) == 0) | ||
78 | maps[ARM_SEC_INIT].unw_sec = s; | ||
79 | else if (strcmp(".ARM.exidx.devinit.text", secname) == 0) | ||
80 | maps[ARM_SEC_DEVINIT].unw_sec = s; | ||
81 | else if (strcmp(".ARM.exidx", secname) == 0) | ||
82 | maps[ARM_SEC_CORE].unw_sec = s; | ||
83 | else if (strcmp(".ARM.exidx.exit.text", secname) == 0) | ||
84 | maps[ARM_SEC_EXIT].unw_sec = s; | ||
85 | else if (strcmp(".ARM.exidx.devexit.text", secname) == 0) | ||
86 | maps[ARM_SEC_DEVEXIT].unw_sec = s; | ||
87 | else if (strcmp(".init.text", secname) == 0) | ||
88 | maps[ARM_SEC_INIT].sec_text = s; | ||
89 | else if (strcmp(".devinit.text", secname) == 0) | ||
90 | maps[ARM_SEC_DEVINIT].sec_text = s; | ||
91 | else if (strcmp(".text", secname) == 0) | ||
92 | maps[ARM_SEC_CORE].sec_text = s; | ||
93 | else if (strcmp(".exit.text", secname) == 0) | ||
94 | maps[ARM_SEC_EXIT].sec_text = s; | ||
95 | else if (strcmp(".devexit.text", secname) == 0) | ||
96 | maps[ARM_SEC_DEVEXIT].sec_text = s; | ||
97 | } | ||
98 | #endif | ||
99 | return 0; | 70 | return 0; |
100 | } | 71 | } |
101 | 72 | ||
@@ -300,41 +271,69 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, | |||
300 | return -ENOEXEC; | 271 | return -ENOEXEC; |
301 | } | 272 | } |
302 | 273 | ||
303 | #ifdef CONFIG_ARM_UNWIND | 274 | struct mod_unwind_map { |
304 | static void register_unwind_tables(struct module *mod) | 275 | const Elf_Shdr *unw_sec; |
276 | const Elf_Shdr *txt_sec; | ||
277 | }; | ||
278 | |||
279 | int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, | ||
280 | struct module *mod) | ||
305 | { | 281 | { |
282 | #ifdef CONFIG_ARM_UNWIND | ||
283 | const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
284 | const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; | ||
285 | struct mod_unwind_map maps[ARM_SEC_MAX]; | ||
306 | int i; | 286 | int i; |
307 | for (i = 0; i < ARM_SEC_MAX; ++i) { | 287 | |
308 | struct arm_unwind_mapping *map = &mod->arch.map[i]; | 288 | memset(maps, 0, sizeof(maps)); |
309 | if (map->unw_sec && map->sec_text) | 289 | |
310 | map->unwind = unwind_table_add(map->unw_sec->sh_addr, | 290 | for (s = sechdrs; s < sechdrs_end; s++) { |
311 | map->unw_sec->sh_size, | 291 | const char *secname = secstrs + s->sh_name; |
312 | map->sec_text->sh_addr, | 292 | |
313 | map->sec_text->sh_size); | 293 | if (!(s->sh_flags & SHF_ALLOC)) |
294 | continue; | ||
295 | |||
296 | if (strcmp(".ARM.exidx.init.text", secname) == 0) | ||
297 | maps[ARM_SEC_INIT].unw_sec = s; | ||
298 | else if (strcmp(".ARM.exidx.devinit.text", secname) == 0) | ||
299 | maps[ARM_SEC_DEVINIT].unw_sec = s; | ||
300 | else if (strcmp(".ARM.exidx", secname) == 0) | ||
301 | maps[ARM_SEC_CORE].unw_sec = s; | ||
302 | else if (strcmp(".ARM.exidx.exit.text", secname) == 0) | ||
303 | maps[ARM_SEC_EXIT].unw_sec = s; | ||
304 | else if (strcmp(".ARM.exidx.devexit.text", secname) == 0) | ||
305 | maps[ARM_SEC_DEVEXIT].unw_sec = s; | ||
306 | else if (strcmp(".init.text", secname) == 0) | ||
307 | maps[ARM_SEC_INIT].txt_sec = s; | ||
308 | else if (strcmp(".devinit.text", secname) == 0) | ||
309 | maps[ARM_SEC_DEVINIT].txt_sec = s; | ||
310 | else if (strcmp(".text", secname) == 0) | ||
311 | maps[ARM_SEC_CORE].txt_sec = s; | ||
312 | else if (strcmp(".exit.text", secname) == 0) | ||
313 | maps[ARM_SEC_EXIT].txt_sec = s; | ||
314 | else if (strcmp(".devexit.text", secname) == 0) | ||
315 | maps[ARM_SEC_DEVEXIT].txt_sec = s; | ||
314 | } | 316 | } |
315 | } | ||
316 | 317 | ||
317 | static void unregister_unwind_tables(struct module *mod) | 318 | for (i = 0; i < ARM_SEC_MAX; i++) |
318 | { | 319 | if (maps[i].unw_sec && maps[i].txt_sec) |
319 | int i = ARM_SEC_MAX; | 320 | mod->arch.unwind[i] = |
320 | while (--i >= 0) | 321 | unwind_table_add(maps[i].unw_sec->sh_addr, |
321 | unwind_table_del(mod->arch.map[i].unwind); | 322 | maps[i].unw_sec->sh_size, |
322 | } | 323 | maps[i].txt_sec->sh_addr, |
323 | #else | 324 | maps[i].txt_sec->sh_size); |
324 | static inline void register_unwind_tables(struct module *mod) { } | ||
325 | static inline void unregister_unwind_tables(struct module *mod) { } | ||
326 | #endif | 325 | #endif |
327 | |||
328 | int | ||
329 | module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, | ||
330 | struct module *module) | ||
331 | { | ||
332 | register_unwind_tables(module); | ||
333 | return 0; | 326 | return 0; |
334 | } | 327 | } |
335 | 328 | ||
336 | void | 329 | void |
337 | module_arch_cleanup(struct module *mod) | 330 | module_arch_cleanup(struct module *mod) |
338 | { | 331 | { |
339 | unregister_unwind_tables(mod); | 332 | #ifdef CONFIG_ARM_UNWIND |
333 | int i; | ||
334 | |||
335 | for (i = 0; i < ARM_SEC_MAX; i++) | ||
336 | if (mod->arch.unwind[i]) | ||
337 | unwind_table_del(mod->arch.unwind[i]); | ||
338 | #endif | ||
340 | } | 339 | } |
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c new file mode 100644 index 00000000000..2cdcc9287c7 --- /dev/null +++ b/arch/arm/kernel/sched_clock.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * sched_clock.c: support for extending counters to full 64-bit ns counter | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #include <linux/clocksource.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/jiffies.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/timer.h> | ||
14 | |||
15 | #include <asm/sched_clock.h> | ||
16 | |||
17 | static void sched_clock_poll(unsigned long wrap_ticks); | ||
18 | static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); | ||
19 | static void (*sched_clock_update_fn)(void); | ||
20 | |||
21 | static void sched_clock_poll(unsigned long wrap_ticks) | ||
22 | { | ||
23 | mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks)); | ||
24 | sched_clock_update_fn(); | ||
25 | } | ||
26 | |||
27 | void __init init_sched_clock(struct clock_data *cd, void (*update)(void), | ||
28 | unsigned int clock_bits, unsigned long rate) | ||
29 | { | ||
30 | unsigned long r, w; | ||
31 | u64 res, wrap; | ||
32 | char r_unit; | ||
33 | |||
34 | sched_clock_update_fn = update; | ||
35 | |||
36 | /* calculate the mult/shift to convert counter ticks to ns. */ | ||
37 | clocks_calc_mult_shift(&cd->mult, &cd->shift, rate, NSEC_PER_SEC, 60); | ||
38 | |||
39 | r = rate; | ||
40 | if (r >= 4000000) { | ||
41 | r /= 1000000; | ||
42 | r_unit = 'M'; | ||
43 | } else { | ||
44 | r /= 1000; | ||
45 | r_unit = 'k'; | ||
46 | } | ||
47 | |||
48 | /* calculate how many ns until we wrap */ | ||
49 | wrap = cyc_to_ns((1ULL << clock_bits) - 1, cd->mult, cd->shift); | ||
50 | do_div(wrap, NSEC_PER_MSEC); | ||
51 | w = wrap; | ||
52 | |||
53 | /* calculate the ns resolution of this counter */ | ||
54 | res = cyc_to_ns(1ULL, cd->mult, cd->shift); | ||
55 | pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n", | ||
56 | clock_bits, r, r_unit, res, w); | ||
57 | |||
58 | /* | ||
59 | * Start the timer to keep sched_clock() properly updated and | ||
60 | * sets the initial epoch. | ||
61 | */ | ||
62 | sched_clock_timer.data = msecs_to_jiffies(w - (w / 10)); | ||
63 | sched_clock_poll(sched_clock_timer.data); | ||
64 | |||
65 | /* | ||
66 | * Ensure that sched_clock() starts off at 0ns | ||
67 | */ | ||
68 | cd->epoch_ns = 0; | ||
69 | } | ||
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 336f14e0e5c..3455ad33de4 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -75,9 +75,9 @@ extern void reboot_setup(char *str); | |||
75 | 75 | ||
76 | unsigned int processor_id; | 76 | unsigned int processor_id; |
77 | EXPORT_SYMBOL(processor_id); | 77 | EXPORT_SYMBOL(processor_id); |
78 | unsigned int __machine_arch_type; | 78 | unsigned int __machine_arch_type __read_mostly; |
79 | EXPORT_SYMBOL(__machine_arch_type); | 79 | EXPORT_SYMBOL(__machine_arch_type); |
80 | unsigned int cacheid; | 80 | unsigned int cacheid __read_mostly; |
81 | EXPORT_SYMBOL(cacheid); | 81 | EXPORT_SYMBOL(cacheid); |
82 | 82 | ||
83 | unsigned int __atags_pointer __initdata; | 83 | unsigned int __atags_pointer __initdata; |
@@ -91,24 +91,24 @@ EXPORT_SYMBOL(system_serial_low); | |||
91 | unsigned int system_serial_high; | 91 | unsigned int system_serial_high; |
92 | EXPORT_SYMBOL(system_serial_high); | 92 | EXPORT_SYMBOL(system_serial_high); |
93 | 93 | ||
94 | unsigned int elf_hwcap; | 94 | unsigned int elf_hwcap __read_mostly; |
95 | EXPORT_SYMBOL(elf_hwcap); | 95 | EXPORT_SYMBOL(elf_hwcap); |
96 | 96 | ||
97 | 97 | ||
98 | #ifdef MULTI_CPU | 98 | #ifdef MULTI_CPU |
99 | struct processor processor; | 99 | struct processor processor __read_mostly; |
100 | #endif | 100 | #endif |
101 | #ifdef MULTI_TLB | 101 | #ifdef MULTI_TLB |
102 | struct cpu_tlb_fns cpu_tlb; | 102 | struct cpu_tlb_fns cpu_tlb __read_mostly; |
103 | #endif | 103 | #endif |
104 | #ifdef MULTI_USER | 104 | #ifdef MULTI_USER |
105 | struct cpu_user_fns cpu_user; | 105 | struct cpu_user_fns cpu_user __read_mostly; |
106 | #endif | 106 | #endif |
107 | #ifdef MULTI_CACHE | 107 | #ifdef MULTI_CACHE |
108 | struct cpu_cache_fns cpu_cache; | 108 | struct cpu_cache_fns cpu_cache __read_mostly; |
109 | #endif | 109 | #endif |
110 | #ifdef CONFIG_OUTER_CACHE | 110 | #ifdef CONFIG_OUTER_CACHE |
111 | struct outer_cache_fns outer_cache; | 111 | struct outer_cache_fns outer_cache __read_mostly; |
112 | EXPORT_SYMBOL(outer_cache); | 112 | EXPORT_SYMBOL(outer_cache); |
113 | #endif | 113 | #endif |
114 | 114 | ||
@@ -126,6 +126,7 @@ EXPORT_SYMBOL(elf_platform); | |||
126 | static const char *cpu_name; | 126 | static const char *cpu_name; |
127 | static const char *machine_name; | 127 | static const char *machine_name; |
128 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; | 128 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; |
129 | struct machine_desc *machine_desc __initdata; | ||
129 | 130 | ||
130 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | 131 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; |
131 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; | 132 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; |
@@ -708,13 +709,11 @@ static struct init_tags { | |||
708 | { 0, ATAG_NONE } | 709 | { 0, ATAG_NONE } |
709 | }; | 710 | }; |
710 | 711 | ||
711 | static void (*init_machine)(void) __initdata; | ||
712 | |||
713 | static int __init customize_machine(void) | 712 | static int __init customize_machine(void) |
714 | { | 713 | { |
715 | /* customizes platform devices, or adds new ones */ | 714 | /* customizes platform devices, or adds new ones */ |
716 | if (init_machine) | 715 | if (machine_desc->init_machine) |
717 | init_machine(); | 716 | machine_desc->init_machine(); |
718 | return 0; | 717 | return 0; |
719 | } | 718 | } |
720 | arch_initcall(customize_machine); | 719 | arch_initcall(customize_machine); |
@@ -809,6 +808,7 @@ void __init setup_arch(char **cmdline_p) | |||
809 | 808 | ||
810 | setup_processor(); | 809 | setup_processor(); |
811 | mdesc = setup_machine(machine_arch_type); | 810 | mdesc = setup_machine(machine_arch_type); |
811 | machine_desc = mdesc; | ||
812 | machine_name = mdesc->name; | 812 | machine_name = mdesc->name; |
813 | 813 | ||
814 | if (mdesc->soft_reboot) | 814 | if (mdesc->soft_reboot) |
@@ -868,13 +868,9 @@ void __init setup_arch(char **cmdline_p) | |||
868 | cpu_init(); | 868 | cpu_init(); |
869 | tcm_init(); | 869 | tcm_init(); |
870 | 870 | ||
871 | /* | 871 | #ifdef CONFIG_MULTI_IRQ_HANDLER |
872 | * Set up various architecture-specific pointers | 872 | handle_arch_irq = mdesc->handle_irq; |
873 | */ | 873 | #endif |
874 | arch_nr_irqs = mdesc->nr_irqs; | ||
875 | init_arch_irq = mdesc->init_irq; | ||
876 | system_timer = mdesc->timer; | ||
877 | init_machine = mdesc->init_machine; | ||
878 | 874 | ||
879 | #ifdef CONFIG_VT | 875 | #ifdef CONFIG_VT |
880 | #if defined(CONFIG_VGA_CONSOLE) | 876 | #if defined(CONFIG_VGA_CONSOLE) |
@@ -884,6 +880,9 @@ void __init setup_arch(char **cmdline_p) | |||
884 | #endif | 880 | #endif |
885 | #endif | 881 | #endif |
886 | early_trap_init(); | 882 | early_trap_init(); |
883 | |||
884 | if (mdesc->init_early) | ||
885 | mdesc->init_early(); | ||
887 | } | 886 | } |
888 | 887 | ||
889 | 888 | ||
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index bbca89872c1..4539ebcb089 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
26 | #include <linux/percpu.h> | 26 | #include <linux/percpu.h> |
27 | #include <linux/clockchips.h> | 27 | #include <linux/clockchips.h> |
28 | #include <linux/completion.h> | ||
28 | 29 | ||
29 | #include <asm/atomic.h> | 30 | #include <asm/atomic.h> |
30 | #include <asm/cacheflush.h> | 31 | #include <asm/cacheflush.h> |
@@ -38,7 +39,6 @@ | |||
38 | #include <asm/tlbflush.h> | 39 | #include <asm/tlbflush.h> |
39 | #include <asm/ptrace.h> | 40 | #include <asm/ptrace.h> |
40 | #include <asm/localtimer.h> | 41 | #include <asm/localtimer.h> |
41 | #include <asm/smp_plat.h> | ||
42 | 42 | ||
43 | /* | 43 | /* |
44 | * as from 2.5, kernels no longer have an init_tasks structure | 44 | * as from 2.5, kernels no longer have an init_tasks structure |
@@ -47,64 +47,14 @@ | |||
47 | */ | 47 | */ |
48 | struct secondary_data secondary_data; | 48 | struct secondary_data secondary_data; |
49 | 49 | ||
50 | /* | ||
51 | * structures for inter-processor calls | ||
52 | * - A collection of single bit ipi messages. | ||
53 | */ | ||
54 | struct ipi_data { | ||
55 | spinlock_t lock; | ||
56 | unsigned long ipi_count; | ||
57 | unsigned long bits; | ||
58 | }; | ||
59 | |||
60 | static DEFINE_PER_CPU(struct ipi_data, ipi_data) = { | ||
61 | .lock = SPIN_LOCK_UNLOCKED, | ||
62 | }; | ||
63 | |||
64 | enum ipi_msg_type { | 50 | enum ipi_msg_type { |
65 | IPI_TIMER, | 51 | IPI_TIMER = 2, |
66 | IPI_RESCHEDULE, | 52 | IPI_RESCHEDULE, |
67 | IPI_CALL_FUNC, | 53 | IPI_CALL_FUNC, |
68 | IPI_CALL_FUNC_SINGLE, | 54 | IPI_CALL_FUNC_SINGLE, |
69 | IPI_CPU_STOP, | 55 | IPI_CPU_STOP, |
70 | }; | 56 | }; |
71 | 57 | ||
72 | static inline void identity_mapping_add(pgd_t *pgd, unsigned long start, | ||
73 | unsigned long end) | ||
74 | { | ||
75 | unsigned long addr, prot; | ||
76 | pmd_t *pmd; | ||
77 | |||
78 | prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; | ||
79 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) | ||
80 | prot |= PMD_BIT4; | ||
81 | |||
82 | for (addr = start & PGDIR_MASK; addr < end;) { | ||
83 | pmd = pmd_offset(pgd + pgd_index(addr), addr); | ||
84 | pmd[0] = __pmd(addr | prot); | ||
85 | addr += SECTION_SIZE; | ||
86 | pmd[1] = __pmd(addr | prot); | ||
87 | addr += SECTION_SIZE; | ||
88 | flush_pmd_entry(pmd); | ||
89 | outer_clean_range(__pa(pmd), __pa(pmd + 1)); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | static inline void identity_mapping_del(pgd_t *pgd, unsigned long start, | ||
94 | unsigned long end) | ||
95 | { | ||
96 | unsigned long addr; | ||
97 | pmd_t *pmd; | ||
98 | |||
99 | for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) { | ||
100 | pmd = pmd_offset(pgd + pgd_index(addr), addr); | ||
101 | pmd[0] = __pmd(0); | ||
102 | pmd[1] = __pmd(0); | ||
103 | clean_pmd_entry(pmd); | ||
104 | outer_clean_range(__pa(pmd), __pa(pmd + 1)); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | int __cpuinit __cpu_up(unsigned int cpu) | 58 | int __cpuinit __cpu_up(unsigned int cpu) |
109 | { | 59 | { |
110 | struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); | 60 | struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); |
@@ -178,8 +128,12 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
178 | barrier(); | 128 | barrier(); |
179 | } | 129 | } |
180 | 130 | ||
181 | if (!cpu_online(cpu)) | 131 | if (!cpu_online(cpu)) { |
132 | pr_crit("CPU%u: failed to come online\n", cpu); | ||
182 | ret = -EIO; | 133 | ret = -EIO; |
134 | } | ||
135 | } else { | ||
136 | pr_err("CPU%u: failed to boot: %d\n", cpu, ret); | ||
183 | } | 137 | } |
184 | 138 | ||
185 | secondary_data.stack = NULL; | 139 | secondary_data.stack = NULL; |
@@ -195,18 +149,12 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
195 | 149 | ||
196 | pgd_free(&init_mm, pgd); | 150 | pgd_free(&init_mm, pgd); |
197 | 151 | ||
198 | if (ret) { | ||
199 | printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu); | ||
200 | |||
201 | /* | ||
202 | * FIXME: We need to clean up the new idle thread. --rmk | ||
203 | */ | ||
204 | } | ||
205 | |||
206 | return ret; | 152 | return ret; |
207 | } | 153 | } |
208 | 154 | ||
209 | #ifdef CONFIG_HOTPLUG_CPU | 155 | #ifdef CONFIG_HOTPLUG_CPU |
156 | static void percpu_timer_stop(void); | ||
157 | |||
210 | /* | 158 | /* |
211 | * __cpu_disable runs on the processor to be shutdown. | 159 | * __cpu_disable runs on the processor to be shutdown. |
212 | */ | 160 | */ |
@@ -234,7 +182,7 @@ int __cpu_disable(void) | |||
234 | /* | 182 | /* |
235 | * Stop the local timer for this CPU. | 183 | * Stop the local timer for this CPU. |
236 | */ | 184 | */ |
237 | local_timer_stop(); | 185 | percpu_timer_stop(); |
238 | 186 | ||
239 | /* | 187 | /* |
240 | * Flush user cache and TLB mappings, and then remove this CPU | 188 | * Flush user cache and TLB mappings, and then remove this CPU |
@@ -253,12 +201,20 @@ int __cpu_disable(void) | |||
253 | return 0; | 201 | return 0; |
254 | } | 202 | } |
255 | 203 | ||
204 | static DECLARE_COMPLETION(cpu_died); | ||
205 | |||
256 | /* | 206 | /* |
257 | * called on the thread which is asking for a CPU to be shutdown - | 207 | * called on the thread which is asking for a CPU to be shutdown - |
258 | * waits until shutdown has completed, or it is timed out. | 208 | * waits until shutdown has completed, or it is timed out. |
259 | */ | 209 | */ |
260 | void __cpu_die(unsigned int cpu) | 210 | void __cpu_die(unsigned int cpu) |
261 | { | 211 | { |
212 | if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) { | ||
213 | pr_err("CPU%u: cpu didn't die\n", cpu); | ||
214 | return; | ||
215 | } | ||
216 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
217 | |||
262 | if (!platform_cpu_kill(cpu)) | 218 | if (!platform_cpu_kill(cpu)) |
263 | printk("CPU%u: unable to kill\n", cpu); | 219 | printk("CPU%u: unable to kill\n", cpu); |
264 | } | 220 | } |
@@ -275,12 +231,17 @@ void __ref cpu_die(void) | |||
275 | { | 231 | { |
276 | unsigned int cpu = smp_processor_id(); | 232 | unsigned int cpu = smp_processor_id(); |
277 | 233 | ||
278 | local_irq_disable(); | ||
279 | idle_task_exit(); | 234 | idle_task_exit(); |
280 | 235 | ||
236 | local_irq_disable(); | ||
237 | mb(); | ||
238 | |||
239 | /* Tell __cpu_die() that this CPU is now safe to dispose of */ | ||
240 | complete(&cpu_died); | ||
241 | |||
281 | /* | 242 | /* |
282 | * actual CPU shutdown procedure is at least platform (if not | 243 | * actual CPU shutdown procedure is at least platform (if not |
283 | * CPU) specific | 244 | * CPU) specific. |
284 | */ | 245 | */ |
285 | platform_cpu_die(cpu); | 246 | platform_cpu_die(cpu); |
286 | 247 | ||
@@ -290,6 +251,7 @@ void __ref cpu_die(void) | |||
290 | * to be repeated to undo the effects of taking the CPU offline. | 251 | * to be repeated to undo the effects of taking the CPU offline. |
291 | */ | 252 | */ |
292 | __asm__("mov sp, %0\n" | 253 | __asm__("mov sp, %0\n" |
254 | " mov fp, #0\n" | ||
293 | " b secondary_start_kernel" | 255 | " b secondary_start_kernel" |
294 | : | 256 | : |
295 | : "r" (task_stack_page(current) + THREAD_SIZE - 8)); | 257 | : "r" (task_stack_page(current) + THREAD_SIZE - 8)); |
@@ -297,6 +259,17 @@ void __ref cpu_die(void) | |||
297 | #endif /* CONFIG_HOTPLUG_CPU */ | 259 | #endif /* CONFIG_HOTPLUG_CPU */ |
298 | 260 | ||
299 | /* | 261 | /* |
262 | * Called by both boot and secondaries to move global data into | ||
263 | * per-processor storage. | ||
264 | */ | ||
265 | static void __cpuinit smp_store_cpu_info(unsigned int cpuid) | ||
266 | { | ||
267 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); | ||
268 | |||
269 | cpu_info->loops_per_jiffy = loops_per_jiffy; | ||
270 | } | ||
271 | |||
272 | /* | ||
300 | * This is the secondary CPU boot entry. We're using this CPUs | 273 | * This is the secondary CPU boot entry. We're using this CPUs |
301 | * idle thread stack, but a set of temporary page tables. | 274 | * idle thread stack, but a set of temporary page tables. |
302 | */ | 275 | */ |
@@ -311,7 +284,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
311 | * All kernel threads share the same mm context; grab a | 284 | * All kernel threads share the same mm context; grab a |
312 | * reference and switch to it. | 285 | * reference and switch to it. |
313 | */ | 286 | */ |
314 | atomic_inc(&mm->mm_users); | ||
315 | atomic_inc(&mm->mm_count); | 287 | atomic_inc(&mm->mm_count); |
316 | current->active_mm = mm; | 288 | current->active_mm = mm; |
317 | cpumask_set_cpu(cpu, mm_cpumask(mm)); | 289 | cpumask_set_cpu(cpu, mm_cpumask(mm)); |
@@ -321,6 +293,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
321 | 293 | ||
322 | cpu_init(); | 294 | cpu_init(); |
323 | preempt_disable(); | 295 | preempt_disable(); |
296 | trace_hardirqs_off(); | ||
324 | 297 | ||
325 | /* | 298 | /* |
326 | * Give the platform a chance to do its own initialisation. | 299 | * Give the platform a chance to do its own initialisation. |
@@ -354,17 +327,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
354 | cpu_idle(); | 327 | cpu_idle(); |
355 | } | 328 | } |
356 | 329 | ||
357 | /* | ||
358 | * Called by both boot and secondaries to move global data into | ||
359 | * per-processor storage. | ||
360 | */ | ||
361 | void __cpuinit smp_store_cpu_info(unsigned int cpuid) | ||
362 | { | ||
363 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); | ||
364 | |||
365 | cpu_info->loops_per_jiffy = loops_per_jiffy; | ||
366 | } | ||
367 | |||
368 | void __init smp_cpus_done(unsigned int max_cpus) | 330 | void __init smp_cpus_done(unsigned int max_cpus) |
369 | { | 331 | { |
370 | int cpu; | 332 | int cpu; |
@@ -387,61 +349,80 @@ void __init smp_prepare_boot_cpu(void) | |||
387 | per_cpu(cpu_data, cpu).idle = current; | 349 | per_cpu(cpu_data, cpu).idle = current; |
388 | } | 350 | } |
389 | 351 | ||
390 | static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg) | 352 | void __init smp_prepare_cpus(unsigned int max_cpus) |
391 | { | 353 | { |
392 | unsigned long flags; | 354 | unsigned int ncores = num_possible_cpus(); |
393 | unsigned int cpu; | ||
394 | 355 | ||
395 | local_irq_save(flags); | 356 | smp_store_cpu_info(smp_processor_id()); |
396 | |||
397 | for_each_cpu(cpu, mask) { | ||
398 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | ||
399 | |||
400 | spin_lock(&ipi->lock); | ||
401 | ipi->bits |= 1 << msg; | ||
402 | spin_unlock(&ipi->lock); | ||
403 | } | ||
404 | 357 | ||
405 | /* | 358 | /* |
406 | * Call the platform specific cross-CPU call function. | 359 | * are we trying to boot more cores than exist? |
407 | */ | 360 | */ |
408 | smp_cross_call(mask); | 361 | if (max_cpus > ncores) |
362 | max_cpus = ncores; | ||
363 | |||
364 | if (max_cpus > 1) { | ||
365 | /* | ||
366 | * Enable the local timer or broadcast device for the | ||
367 | * boot CPU, but only if we have more than one CPU. | ||
368 | */ | ||
369 | percpu_timer_setup(); | ||
409 | 370 | ||
410 | local_irq_restore(flags); | 371 | /* |
372 | * Initialise the SCU if there are more than one CPU | ||
373 | * and let them know where to start. | ||
374 | */ | ||
375 | platform_smp_prepare_cpus(max_cpus); | ||
376 | } | ||
411 | } | 377 | } |
412 | 378 | ||
413 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) | 379 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) |
414 | { | 380 | { |
415 | send_ipi_message(mask, IPI_CALL_FUNC); | 381 | smp_cross_call(mask, IPI_CALL_FUNC); |
416 | } | 382 | } |
417 | 383 | ||
418 | void arch_send_call_function_single_ipi(int cpu) | 384 | void arch_send_call_function_single_ipi(int cpu) |
419 | { | 385 | { |
420 | send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); | 386 | smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); |
421 | } | 387 | } |
422 | 388 | ||
423 | void show_ipi_list(struct seq_file *p) | 389 | static const char *ipi_types[NR_IPI] = { |
390 | #define S(x,s) [x - IPI_TIMER] = s | ||
391 | S(IPI_TIMER, "Timer broadcast interrupts"), | ||
392 | S(IPI_RESCHEDULE, "Rescheduling interrupts"), | ||
393 | S(IPI_CALL_FUNC, "Function call interrupts"), | ||
394 | S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"), | ||
395 | S(IPI_CPU_STOP, "CPU stop interrupts"), | ||
396 | }; | ||
397 | |||
398 | void show_ipi_list(struct seq_file *p, int prec) | ||
424 | { | 399 | { |
425 | unsigned int cpu; | 400 | unsigned int cpu, i; |
426 | 401 | ||
427 | seq_puts(p, "IPI:"); | 402 | for (i = 0; i < NR_IPI; i++) { |
403 | seq_printf(p, "%*s%u: ", prec - 1, "IPI", i); | ||
428 | 404 | ||
429 | for_each_present_cpu(cpu) | 405 | for_each_present_cpu(cpu) |
430 | seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count); | 406 | seq_printf(p, "%10u ", |
407 | __get_irq_stat(cpu, ipi_irqs[i])); | ||
431 | 408 | ||
432 | seq_putc(p, '\n'); | 409 | seq_printf(p, " %s\n", ipi_types[i]); |
410 | } | ||
433 | } | 411 | } |
434 | 412 | ||
435 | void show_local_irqs(struct seq_file *p) | 413 | u64 smp_irq_stat_cpu(unsigned int cpu) |
436 | { | 414 | { |
437 | unsigned int cpu; | 415 | u64 sum = 0; |
416 | int i; | ||
438 | 417 | ||
439 | seq_printf(p, "LOC: "); | 418 | for (i = 0; i < NR_IPI; i++) |
419 | sum += __get_irq_stat(cpu, ipi_irqs[i]); | ||
440 | 420 | ||
441 | for_each_present_cpu(cpu) | 421 | #ifdef CONFIG_LOCAL_TIMERS |
442 | seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs); | 422 | sum += __get_irq_stat(cpu, local_timer_irqs); |
423 | #endif | ||
443 | 424 | ||
444 | seq_putc(p, '\n'); | 425 | return sum; |
445 | } | 426 | } |
446 | 427 | ||
447 | /* | 428 | /* |
@@ -464,18 +445,30 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) | |||
464 | int cpu = smp_processor_id(); | 445 | int cpu = smp_processor_id(); |
465 | 446 | ||
466 | if (local_timer_ack()) { | 447 | if (local_timer_ack()) { |
467 | irq_stat[cpu].local_timer_irqs++; | 448 | __inc_irq_stat(cpu, local_timer_irqs); |
468 | ipi_timer(); | 449 | ipi_timer(); |
469 | } | 450 | } |
470 | 451 | ||
471 | set_irq_regs(old_regs); | 452 | set_irq_regs(old_regs); |
472 | } | 453 | } |
454 | |||
455 | void show_local_irqs(struct seq_file *p, int prec) | ||
456 | { | ||
457 | unsigned int cpu; | ||
458 | |||
459 | seq_printf(p, "%*s: ", prec, "LOC"); | ||
460 | |||
461 | for_each_present_cpu(cpu) | ||
462 | seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs)); | ||
463 | |||
464 | seq_printf(p, " Local timer interrupts\n"); | ||
465 | } | ||
473 | #endif | 466 | #endif |
474 | 467 | ||
475 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | 468 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST |
476 | static void smp_timer_broadcast(const struct cpumask *mask) | 469 | static void smp_timer_broadcast(const struct cpumask *mask) |
477 | { | 470 | { |
478 | send_ipi_message(mask, IPI_TIMER); | 471 | smp_cross_call(mask, IPI_TIMER); |
479 | } | 472 | } |
480 | #else | 473 | #else |
481 | #define smp_timer_broadcast NULL | 474 | #define smp_timer_broadcast NULL |
@@ -512,6 +505,21 @@ void __cpuinit percpu_timer_setup(void) | |||
512 | local_timer_setup(evt); | 505 | local_timer_setup(evt); |
513 | } | 506 | } |
514 | 507 | ||
508 | #ifdef CONFIG_HOTPLUG_CPU | ||
509 | /* | ||
510 | * The generic clock events code purposely does not stop the local timer | ||
511 | * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it | ||
512 | * manually here. | ||
513 | */ | ||
514 | static void percpu_timer_stop(void) | ||
515 | { | ||
516 | unsigned int cpu = smp_processor_id(); | ||
517 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); | ||
518 | |||
519 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | ||
520 | } | ||
521 | #endif | ||
522 | |||
515 | static DEFINE_SPINLOCK(stop_lock); | 523 | static DEFINE_SPINLOCK(stop_lock); |
516 | 524 | ||
517 | /* | 525 | /* |
@@ -538,216 +546,76 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
538 | 546 | ||
539 | /* | 547 | /* |
540 | * Main handler for inter-processor interrupts | 548 | * Main handler for inter-processor interrupts |
541 | * | ||
542 | * For ARM, the ipimask now only identifies a single | ||
543 | * category of IPI (Bit 1 IPIs have been replaced by a | ||
544 | * different mechanism): | ||
545 | * | ||
546 | * Bit 0 - Inter-processor function call | ||
547 | */ | 549 | */ |
548 | asmlinkage void __exception_irq_entry do_IPI(struct pt_regs *regs) | 550 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) |
549 | { | 551 | { |
550 | unsigned int cpu = smp_processor_id(); | 552 | unsigned int cpu = smp_processor_id(); |
551 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | ||
552 | struct pt_regs *old_regs = set_irq_regs(regs); | 553 | struct pt_regs *old_regs = set_irq_regs(regs); |
553 | 554 | ||
554 | ipi->ipi_count++; | 555 | if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI) |
555 | 556 | __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]); | |
556 | for (;;) { | ||
557 | unsigned long msgs; | ||
558 | |||
559 | spin_lock(&ipi->lock); | ||
560 | msgs = ipi->bits; | ||
561 | ipi->bits = 0; | ||
562 | spin_unlock(&ipi->lock); | ||
563 | 557 | ||
564 | if (!msgs) | 558 | switch (ipinr) { |
565 | break; | 559 | case IPI_TIMER: |
566 | 560 | ipi_timer(); | |
567 | do { | 561 | break; |
568 | unsigned nextmsg; | ||
569 | |||
570 | nextmsg = msgs & -msgs; | ||
571 | msgs &= ~nextmsg; | ||
572 | nextmsg = ffz(~nextmsg); | ||
573 | |||
574 | switch (nextmsg) { | ||
575 | case IPI_TIMER: | ||
576 | ipi_timer(); | ||
577 | break; | ||
578 | 562 | ||
579 | case IPI_RESCHEDULE: | 563 | case IPI_RESCHEDULE: |
580 | /* | 564 | /* |
581 | * nothing more to do - eveything is | 565 | * nothing more to do - eveything is |
582 | * done on the interrupt return path | 566 | * done on the interrupt return path |
583 | */ | 567 | */ |
584 | break; | 568 | break; |
585 | 569 | ||
586 | case IPI_CALL_FUNC: | 570 | case IPI_CALL_FUNC: |
587 | generic_smp_call_function_interrupt(); | 571 | generic_smp_call_function_interrupt(); |
588 | break; | 572 | break; |
589 | 573 | ||
590 | case IPI_CALL_FUNC_SINGLE: | 574 | case IPI_CALL_FUNC_SINGLE: |
591 | generic_smp_call_function_single_interrupt(); | 575 | generic_smp_call_function_single_interrupt(); |
592 | break; | 576 | break; |
593 | 577 | ||
594 | case IPI_CPU_STOP: | 578 | case IPI_CPU_STOP: |
595 | ipi_cpu_stop(cpu); | 579 | ipi_cpu_stop(cpu); |
596 | break; | 580 | break; |
597 | 581 | ||
598 | default: | 582 | default: |
599 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", | 583 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", |
600 | cpu, nextmsg); | 584 | cpu, ipinr); |
601 | break; | 585 | break; |
602 | } | ||
603 | } while (msgs); | ||
604 | } | 586 | } |
605 | |||
606 | set_irq_regs(old_regs); | 587 | set_irq_regs(old_regs); |
607 | } | 588 | } |
608 | 589 | ||
609 | void smp_send_reschedule(int cpu) | 590 | void smp_send_reschedule(int cpu) |
610 | { | 591 | { |
611 | send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); | 592 | smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); |
612 | } | 593 | } |
613 | 594 | ||
614 | void smp_send_stop(void) | 595 | void smp_send_stop(void) |
615 | { | 596 | { |
616 | cpumask_t mask = cpu_online_map; | 597 | unsigned long timeout; |
617 | cpu_clear(smp_processor_id(), mask); | ||
618 | if (!cpus_empty(mask)) | ||
619 | send_ipi_message(&mask, IPI_CPU_STOP); | ||
620 | } | ||
621 | 598 | ||
622 | /* | 599 | if (num_online_cpus() > 1) { |
623 | * not supported here | 600 | cpumask_t mask = cpu_online_map; |
624 | */ | 601 | cpu_clear(smp_processor_id(), mask); |
625 | int setup_profiling_timer(unsigned int multiplier) | ||
626 | { | ||
627 | return -EINVAL; | ||
628 | } | ||
629 | 602 | ||
630 | static void | 603 | smp_cross_call(&mask, IPI_CPU_STOP); |
631 | on_each_cpu_mask(void (*func)(void *), void *info, int wait, | 604 | } |
632 | const struct cpumask *mask) | ||
633 | { | ||
634 | preempt_disable(); | ||
635 | 605 | ||
636 | smp_call_function_many(mask, func, info, wait); | 606 | /* Wait up to one second for other CPUs to stop */ |
637 | if (cpumask_test_cpu(smp_processor_id(), mask)) | 607 | timeout = USEC_PER_SEC; |
638 | func(info); | 608 | while (num_online_cpus() > 1 && timeout--) |
609 | udelay(1); | ||
639 | 610 | ||
640 | preempt_enable(); | 611 | if (num_online_cpus() > 1) |
612 | pr_warning("SMP: failed to stop secondary CPUs\n"); | ||
641 | } | 613 | } |
642 | 614 | ||
643 | /**********************************************************************/ | ||
644 | |||
645 | /* | 615 | /* |
646 | * TLB operations | 616 | * not supported here |
647 | */ | 617 | */ |
648 | struct tlb_args { | 618 | int setup_profiling_timer(unsigned int multiplier) |
649 | struct vm_area_struct *ta_vma; | ||
650 | unsigned long ta_start; | ||
651 | unsigned long ta_end; | ||
652 | }; | ||
653 | |||
654 | static inline void ipi_flush_tlb_all(void *ignored) | ||
655 | { | ||
656 | local_flush_tlb_all(); | ||
657 | } | ||
658 | |||
659 | static inline void ipi_flush_tlb_mm(void *arg) | ||
660 | { | ||
661 | struct mm_struct *mm = (struct mm_struct *)arg; | ||
662 | |||
663 | local_flush_tlb_mm(mm); | ||
664 | } | ||
665 | |||
666 | static inline void ipi_flush_tlb_page(void *arg) | ||
667 | { | ||
668 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
669 | |||
670 | local_flush_tlb_page(ta->ta_vma, ta->ta_start); | ||
671 | } | ||
672 | |||
673 | static inline void ipi_flush_tlb_kernel_page(void *arg) | ||
674 | { | ||
675 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
676 | |||
677 | local_flush_tlb_kernel_page(ta->ta_start); | ||
678 | } | ||
679 | |||
680 | static inline void ipi_flush_tlb_range(void *arg) | ||
681 | { | ||
682 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
683 | |||
684 | local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); | ||
685 | } | ||
686 | |||
687 | static inline void ipi_flush_tlb_kernel_range(void *arg) | ||
688 | { | ||
689 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
690 | |||
691 | local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); | ||
692 | } | ||
693 | |||
694 | void flush_tlb_all(void) | ||
695 | { | ||
696 | if (tlb_ops_need_broadcast()) | ||
697 | on_each_cpu(ipi_flush_tlb_all, NULL, 1); | ||
698 | else | ||
699 | local_flush_tlb_all(); | ||
700 | } | ||
701 | |||
702 | void flush_tlb_mm(struct mm_struct *mm) | ||
703 | { | ||
704 | if (tlb_ops_need_broadcast()) | ||
705 | on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm)); | ||
706 | else | ||
707 | local_flush_tlb_mm(mm); | ||
708 | } | ||
709 | |||
710 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) | ||
711 | { | ||
712 | if (tlb_ops_need_broadcast()) { | ||
713 | struct tlb_args ta; | ||
714 | ta.ta_vma = vma; | ||
715 | ta.ta_start = uaddr; | ||
716 | on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm)); | ||
717 | } else | ||
718 | local_flush_tlb_page(vma, uaddr); | ||
719 | } | ||
720 | |||
721 | void flush_tlb_kernel_page(unsigned long kaddr) | ||
722 | { | ||
723 | if (tlb_ops_need_broadcast()) { | ||
724 | struct tlb_args ta; | ||
725 | ta.ta_start = kaddr; | ||
726 | on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); | ||
727 | } else | ||
728 | local_flush_tlb_kernel_page(kaddr); | ||
729 | } | ||
730 | |||
731 | void flush_tlb_range(struct vm_area_struct *vma, | ||
732 | unsigned long start, unsigned long end) | ||
733 | { | ||
734 | if (tlb_ops_need_broadcast()) { | ||
735 | struct tlb_args ta; | ||
736 | ta.ta_vma = vma; | ||
737 | ta.ta_start = start; | ||
738 | ta.ta_end = end; | ||
739 | on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm)); | ||
740 | } else | ||
741 | local_flush_tlb_range(vma, start, end); | ||
742 | } | ||
743 | |||
744 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) | ||
745 | { | 619 | { |
746 | if (tlb_ops_need_broadcast()) { | 620 | return -EINVAL; |
747 | struct tlb_args ta; | ||
748 | ta.ta_start = start; | ||
749 | ta.ta_end = end; | ||
750 | on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); | ||
751 | } else | ||
752 | local_flush_tlb_kernel_range(start, end); | ||
753 | } | 621 | } |
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c new file mode 100644 index 00000000000..7dcb35285be --- /dev/null +++ b/arch/arm/kernel/smp_tlb.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/smp_tlb.c | ||
3 | * | ||
4 | * Copyright (C) 2002 ARM Limited, All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/preempt.h> | ||
11 | #include <linux/smp.h> | ||
12 | |||
13 | #include <asm/smp_plat.h> | ||
14 | #include <asm/tlbflush.h> | ||
15 | |||
16 | static void on_each_cpu_mask(void (*func)(void *), void *info, int wait, | ||
17 | const struct cpumask *mask) | ||
18 | { | ||
19 | preempt_disable(); | ||
20 | |||
21 | smp_call_function_many(mask, func, info, wait); | ||
22 | if (cpumask_test_cpu(smp_processor_id(), mask)) | ||
23 | func(info); | ||
24 | |||
25 | preempt_enable(); | ||
26 | } | ||
27 | |||
28 | /**********************************************************************/ | ||
29 | |||
30 | /* | ||
31 | * TLB operations | ||
32 | */ | ||
33 | struct tlb_args { | ||
34 | struct vm_area_struct *ta_vma; | ||
35 | unsigned long ta_start; | ||
36 | unsigned long ta_end; | ||
37 | }; | ||
38 | |||
39 | static inline void ipi_flush_tlb_all(void *ignored) | ||
40 | { | ||
41 | local_flush_tlb_all(); | ||
42 | } | ||
43 | |||
44 | static inline void ipi_flush_tlb_mm(void *arg) | ||
45 | { | ||
46 | struct mm_struct *mm = (struct mm_struct *)arg; | ||
47 | |||
48 | local_flush_tlb_mm(mm); | ||
49 | } | ||
50 | |||
51 | static inline void ipi_flush_tlb_page(void *arg) | ||
52 | { | ||
53 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
54 | |||
55 | local_flush_tlb_page(ta->ta_vma, ta->ta_start); | ||
56 | } | ||
57 | |||
58 | static inline void ipi_flush_tlb_kernel_page(void *arg) | ||
59 | { | ||
60 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
61 | |||
62 | local_flush_tlb_kernel_page(ta->ta_start); | ||
63 | } | ||
64 | |||
65 | static inline void ipi_flush_tlb_range(void *arg) | ||
66 | { | ||
67 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
68 | |||
69 | local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); | ||
70 | } | ||
71 | |||
72 | static inline void ipi_flush_tlb_kernel_range(void *arg) | ||
73 | { | ||
74 | struct tlb_args *ta = (struct tlb_args *)arg; | ||
75 | |||
76 | local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); | ||
77 | } | ||
78 | |||
79 | void flush_tlb_all(void) | ||
80 | { | ||
81 | if (tlb_ops_need_broadcast()) | ||
82 | on_each_cpu(ipi_flush_tlb_all, NULL, 1); | ||
83 | else | ||
84 | local_flush_tlb_all(); | ||
85 | } | ||
86 | |||
87 | void flush_tlb_mm(struct mm_struct *mm) | ||
88 | { | ||
89 | if (tlb_ops_need_broadcast()) | ||
90 | on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm)); | ||
91 | else | ||
92 | local_flush_tlb_mm(mm); | ||
93 | } | ||
94 | |||
95 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) | ||
96 | { | ||
97 | if (tlb_ops_need_broadcast()) { | ||
98 | struct tlb_args ta; | ||
99 | ta.ta_vma = vma; | ||
100 | ta.ta_start = uaddr; | ||
101 | on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm)); | ||
102 | } else | ||
103 | local_flush_tlb_page(vma, uaddr); | ||
104 | } | ||
105 | |||
106 | void flush_tlb_kernel_page(unsigned long kaddr) | ||
107 | { | ||
108 | if (tlb_ops_need_broadcast()) { | ||
109 | struct tlb_args ta; | ||
110 | ta.ta_start = kaddr; | ||
111 | on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); | ||
112 | } else | ||
113 | local_flush_tlb_kernel_page(kaddr); | ||
114 | } | ||
115 | |||
116 | void flush_tlb_range(struct vm_area_struct *vma, | ||
117 | unsigned long start, unsigned long end) | ||
118 | { | ||
119 | if (tlb_ops_need_broadcast()) { | ||
120 | struct tlb_args ta; | ||
121 | ta.ta_vma = vma; | ||
122 | ta.ta_start = start; | ||
123 | ta.ta_end = end; | ||
124 | on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm)); | ||
125 | } else | ||
126 | local_flush_tlb_range(vma, start, end); | ||
127 | } | ||
128 | |||
129 | void flush_tlb_kernel_range(unsigned long start, unsigned long end) | ||
130 | { | ||
131 | if (tlb_ops_need_broadcast()) { | ||
132 | struct tlb_args ta; | ||
133 | ta.ta_start = start; | ||
134 | ta.ta_end = end; | ||
135 | on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); | ||
136 | } else | ||
137 | local_flush_tlb_kernel_range(start, end); | ||
138 | } | ||
139 | |||
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 35882fbf37f..dd790745b3e 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -127,8 +127,6 @@ static void __cpuinit twd_calibrate_rate(void) | |||
127 | */ | 127 | */ |
128 | void __cpuinit twd_timer_setup(struct clock_event_device *clk) | 128 | void __cpuinit twd_timer_setup(struct clock_event_device *clk) |
129 | { | 129 | { |
130 | unsigned long flags; | ||
131 | |||
132 | twd_calibrate_rate(); | 130 | twd_calibrate_rate(); |
133 | 131 | ||
134 | clk->name = "local_timer"; | 132 | clk->name = "local_timer"; |
@@ -143,20 +141,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | |||
143 | clk->min_delta_ns = clockevent_delta2ns(0xf, clk); | 141 | clk->min_delta_ns = clockevent_delta2ns(0xf, clk); |
144 | 142 | ||
145 | /* Make sure our local interrupt controller has this enabled */ | 143 | /* Make sure our local interrupt controller has this enabled */ |
146 | local_irq_save(flags); | 144 | gic_enable_ppi(clk->irq); |
147 | irq_to_desc(clk->irq)->status |= IRQ_NOPROBE; | ||
148 | get_irq_chip(clk->irq)->unmask(clk->irq); | ||
149 | local_irq_restore(flags); | ||
150 | 145 | ||
151 | clockevents_register_device(clk); | 146 | clockevents_register_device(clk); |
152 | } | 147 | } |
153 | |||
154 | #ifdef CONFIG_HOTPLUG_CPU | ||
155 | /* | ||
156 | * take a local timer down | ||
157 | */ | ||
158 | void twd_timer_stop(void) | ||
159 | { | ||
160 | __raw_writel(0, twd_base + TWD_TIMER_CONTROL); | ||
161 | } | ||
162 | #endif | ||
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c new file mode 100644 index 00000000000..7a576092291 --- /dev/null +++ b/arch/arm/kernel/swp_emulate.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/kernel/swp_emulate.c | ||
3 | * | ||
4 | * Copyright (C) 2009 ARM Limited | ||
5 | * __user_* functions adapted from include/asm/uaccess.h | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Implements emulation of the SWP/SWPB instructions using load-exclusive and | ||
12 | * store-exclusive for processors that have them disabled (or future ones that | ||
13 | * might not implement them). | ||
14 | * | ||
15 | * Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>] | ||
16 | * Where: Rt = destination | ||
17 | * Rt2 = source | ||
18 | * Rn = address | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/proc_fs.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/syscalls.h> | ||
26 | #include <linux/perf_event.h> | ||
27 | |||
28 | #include <asm/traps.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | |||
31 | /* | ||
32 | * Error-checking SWP macros implemented using ldrex{b}/strex{b} | ||
33 | */ | ||
34 | #define __user_swpX_asm(data, addr, res, temp, B) \ | ||
35 | __asm__ __volatile__( \ | ||
36 | " mov %2, %1\n" \ | ||
37 | "0: ldrex"B" %1, [%3]\n" \ | ||
38 | "1: strex"B" %0, %2, [%3]\n" \ | ||
39 | " cmp %0, #0\n" \ | ||
40 | " movne %0, %4\n" \ | ||
41 | "2:\n" \ | ||
42 | " .section .fixup,\"ax\"\n" \ | ||
43 | " .align 2\n" \ | ||
44 | "3: mov %0, %5\n" \ | ||
45 | " b 2b\n" \ | ||
46 | " .previous\n" \ | ||
47 | " .section __ex_table,\"a\"\n" \ | ||
48 | " .align 3\n" \ | ||
49 | " .long 0b, 3b\n" \ | ||
50 | " .long 1b, 3b\n" \ | ||
51 | " .previous" \ | ||
52 | : "=&r" (res), "+r" (data), "=&r" (temp) \ | ||
53 | : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ | ||
54 | : "cc", "memory") | ||
55 | |||
56 | #define __user_swp_asm(data, addr, res, temp) \ | ||
57 | __user_swpX_asm(data, addr, res, temp, "") | ||
58 | #define __user_swpb_asm(data, addr, res, temp) \ | ||
59 | __user_swpX_asm(data, addr, res, temp, "b") | ||
60 | |||
61 | /* | ||
62 | * Macros/defines for extracting register numbers from instruction. | ||
63 | */ | ||
64 | #define EXTRACT_REG_NUM(instruction, offset) \ | ||
65 | (((instruction) & (0xf << (offset))) >> (offset)) | ||
66 | #define RN_OFFSET 16 | ||
67 | #define RT_OFFSET 12 | ||
68 | #define RT2_OFFSET 0 | ||
69 | /* | ||
70 | * Bit 22 of the instruction encoding distinguishes between | ||
71 | * the SWP and SWPB variants (bit set means SWPB). | ||
72 | */ | ||
73 | #define TYPE_SWPB (1 << 22) | ||
74 | |||
75 | static unsigned long swpcounter; | ||
76 | static unsigned long swpbcounter; | ||
77 | static unsigned long abtcounter; | ||
78 | static pid_t previous_pid; | ||
79 | |||
80 | #ifdef CONFIG_PROC_FS | ||
81 | static int proc_read_status(char *page, char **start, off_t off, int count, | ||
82 | int *eof, void *data) | ||
83 | { | ||
84 | char *p = page; | ||
85 | int len; | ||
86 | |||
87 | p += sprintf(p, "Emulated SWP:\t\t%lu\n", swpcounter); | ||
88 | p += sprintf(p, "Emulated SWPB:\t\t%lu\n", swpbcounter); | ||
89 | p += sprintf(p, "Aborted SWP{B}:\t\t%lu\n", abtcounter); | ||
90 | if (previous_pid != 0) | ||
91 | p += sprintf(p, "Last process:\t\t%d\n", previous_pid); | ||
92 | |||
93 | len = (p - page) - off; | ||
94 | if (len < 0) | ||
95 | len = 0; | ||
96 | |||
97 | *eof = (len <= count) ? 1 : 0; | ||
98 | *start = page + off; | ||
99 | |||
100 | return len; | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | /* | ||
105 | * Set up process info to signal segmentation fault - called on access error. | ||
106 | */ | ||
107 | static void set_segfault(struct pt_regs *regs, unsigned long addr) | ||
108 | { | ||
109 | siginfo_t info; | ||
110 | |||
111 | if (find_vma(current->mm, addr) == NULL) | ||
112 | info.si_code = SEGV_MAPERR; | ||
113 | else | ||
114 | info.si_code = SEGV_ACCERR; | ||
115 | |||
116 | info.si_signo = SIGSEGV; | ||
117 | info.si_errno = 0; | ||
118 | info.si_addr = (void *) instruction_pointer(regs); | ||
119 | |||
120 | pr_debug("SWP{B} emulation: access caused memory abort!\n"); | ||
121 | arm_notify_die("Illegal memory access", regs, &info, 0, 0); | ||
122 | |||
123 | abtcounter++; | ||
124 | } | ||
125 | |||
126 | static int emulate_swpX(unsigned int address, unsigned int *data, | ||
127 | unsigned int type) | ||
128 | { | ||
129 | unsigned int res = 0; | ||
130 | |||
131 | if ((type != TYPE_SWPB) && (address & 0x3)) { | ||
132 | /* SWP to unaligned address not permitted */ | ||
133 | pr_debug("SWP instruction on unaligned pointer!\n"); | ||
134 | return -EFAULT; | ||
135 | } | ||
136 | |||
137 | while (1) { | ||
138 | unsigned long temp; | ||
139 | |||
140 | /* | ||
141 | * Barrier required between accessing protected resource and | ||
142 | * releasing a lock for it. Legacy code might not have done | ||
143 | * this, and we cannot determine that this is not the case | ||
144 | * being emulated, so insert always. | ||
145 | */ | ||
146 | smp_mb(); | ||
147 | |||
148 | if (type == TYPE_SWPB) | ||
149 | __user_swpb_asm(*data, address, res, temp); | ||
150 | else | ||
151 | __user_swp_asm(*data, address, res, temp); | ||
152 | |||
153 | if (likely(res != -EAGAIN) || signal_pending(current)) | ||
154 | break; | ||
155 | |||
156 | cond_resched(); | ||
157 | } | ||
158 | |||
159 | if (res == 0) { | ||
160 | /* | ||
161 | * Barrier also required between aquiring a lock for a | ||
162 | * protected resource and accessing the resource. Inserted for | ||
163 | * same reason as above. | ||
164 | */ | ||
165 | smp_mb(); | ||
166 | |||
167 | if (type == TYPE_SWPB) | ||
168 | swpbcounter++; | ||
169 | else | ||
170 | swpcounter++; | ||
171 | } | ||
172 | |||
173 | return res; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * swp_handler logs the id of calling process, dissects the instruction, sanity | ||
178 | * checks the memory location, calls emulate_swpX for the actual operation and | ||
179 | * deals with fixup/error handling before returning | ||
180 | */ | ||
181 | static int swp_handler(struct pt_regs *regs, unsigned int instr) | ||
182 | { | ||
183 | unsigned int address, destreg, data, type; | ||
184 | unsigned int res = 0; | ||
185 | |||
186 | perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc); | ||
187 | |||
188 | if (current->pid != previous_pid) { | ||
189 | pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n", | ||
190 | current->comm, (unsigned long)current->pid); | ||
191 | previous_pid = current->pid; | ||
192 | } | ||
193 | |||
194 | address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)]; | ||
195 | data = regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)]; | ||
196 | destreg = EXTRACT_REG_NUM(instr, RT_OFFSET); | ||
197 | |||
198 | type = instr & TYPE_SWPB; | ||
199 | |||
200 | pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n", | ||
201 | EXTRACT_REG_NUM(instr, RN_OFFSET), address, | ||
202 | destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data); | ||
203 | |||
204 | /* Check access in reasonable access range for both SWP and SWPB */ | ||
205 | if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) { | ||
206 | pr_debug("SWP{B} emulation: access to %p not allowed!\n", | ||
207 | (void *)address); | ||
208 | res = -EFAULT; | ||
209 | } else { | ||
210 | res = emulate_swpX(address, &data, type); | ||
211 | } | ||
212 | |||
213 | if (res == 0) { | ||
214 | /* | ||
215 | * On successful emulation, revert the adjustment to the PC | ||
216 | * made in kernel/traps.c in order to resume execution at the | ||
217 | * instruction following the SWP{B}. | ||
218 | */ | ||
219 | regs->ARM_pc += 4; | ||
220 | regs->uregs[destreg] = data; | ||
221 | } else if (res == -EFAULT) { | ||
222 | /* | ||
223 | * Memory errors do not mean emulation failed. | ||
224 | * Set up signal info to return SEGV, then return OK | ||
225 | */ | ||
226 | set_segfault(regs, address); | ||
227 | } | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Only emulate SWP/SWPB executed in ARM state/User mode. | ||
234 | * The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE. | ||
235 | */ | ||
236 | static struct undef_hook swp_hook = { | ||
237 | .instr_mask = 0x0fb00ff0, | ||
238 | .instr_val = 0x01000090, | ||
239 | .cpsr_mask = MODE_MASK | PSR_T_BIT | PSR_J_BIT, | ||
240 | .cpsr_val = USR_MODE, | ||
241 | .fn = swp_handler | ||
242 | }; | ||
243 | |||
244 | /* | ||
245 | * Register handler and create status file in /proc/cpu | ||
246 | * Invoked as late_initcall, since not needed before init spawned. | ||
247 | */ | ||
248 | static int __init swp_emulation_init(void) | ||
249 | { | ||
250 | #ifdef CONFIG_PROC_FS | ||
251 | struct proc_dir_entry *res; | ||
252 | |||
253 | res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL); | ||
254 | |||
255 | if (!res) | ||
256 | return -ENOMEM; | ||
257 | |||
258 | res->read_proc = proc_read_status; | ||
259 | #endif /* CONFIG_PROC_FS */ | ||
260 | |||
261 | printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n"); | ||
262 | register_undef_hook(&swp_hook); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | late_initcall(swp_emulation_init); | ||
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 38c261f9951..f1e2eb19a67 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -30,12 +30,13 @@ | |||
30 | #include <asm/leds.h> | 30 | #include <asm/leds.h> |
31 | #include <asm/thread_info.h> | 31 | #include <asm/thread_info.h> |
32 | #include <asm/stacktrace.h> | 32 | #include <asm/stacktrace.h> |
33 | #include <asm/mach/arch.h> | ||
33 | #include <asm/mach/time.h> | 34 | #include <asm/mach/time.h> |
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Our system timer. | 37 | * Our system timer. |
37 | */ | 38 | */ |
38 | struct sys_timer *system_timer; | 39 | static struct sys_timer *system_timer; |
39 | 40 | ||
40 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) | 41 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) |
41 | /* this needs a better home */ | 42 | /* this needs a better home */ |
@@ -160,6 +161,7 @@ device_initcall(timer_init_sysfs); | |||
160 | 161 | ||
161 | void __init time_init(void) | 162 | void __init time_init(void) |
162 | { | 163 | { |
164 | system_timer = machine_desc->timer; | ||
163 | system_timer->init(); | 165 | system_timer->init(); |
164 | } | 166 | } |
165 | 167 | ||
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 446aee97436..ee57640ba2b 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -37,6 +37,8 @@ | |||
37 | 37 | ||
38 | static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; | 38 | static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; |
39 | 39 | ||
40 | void *vectors_page; | ||
41 | |||
40 | #ifdef CONFIG_DEBUG_USER | 42 | #ifdef CONFIG_DEBUG_USER |
41 | unsigned int user_debug; | 43 | unsigned int user_debug; |
42 | 44 | ||
@@ -708,19 +710,19 @@ void __readwrite_bug(const char *fn) | |||
708 | } | 710 | } |
709 | EXPORT_SYMBOL(__readwrite_bug); | 711 | EXPORT_SYMBOL(__readwrite_bug); |
710 | 712 | ||
711 | void __pte_error(const char *file, int line, unsigned long val) | 713 | void __pte_error(const char *file, int line, pte_t pte) |
712 | { | 714 | { |
713 | printk("%s:%d: bad pte %08lx.\n", file, line, val); | 715 | printk("%s:%d: bad pte %08lx.\n", file, line, pte_val(pte)); |
714 | } | 716 | } |
715 | 717 | ||
716 | void __pmd_error(const char *file, int line, unsigned long val) | 718 | void __pmd_error(const char *file, int line, pmd_t pmd) |
717 | { | 719 | { |
718 | printk("%s:%d: bad pmd %08lx.\n", file, line, val); | 720 | printk("%s:%d: bad pmd %08lx.\n", file, line, pmd_val(pmd)); |
719 | } | 721 | } |
720 | 722 | ||
721 | void __pgd_error(const char *file, int line, unsigned long val) | 723 | void __pgd_error(const char *file, int line, pgd_t pgd) |
722 | { | 724 | { |
723 | printk("%s:%d: bad pgd %08lx.\n", file, line, val); | 725 | printk("%s:%d: bad pgd %08lx.\n", file, line, pgd_val(pgd)); |
724 | } | 726 | } |
725 | 727 | ||
726 | asmlinkage void __div0(void) | 728 | asmlinkage void __div0(void) |
@@ -756,7 +758,11 @@ static void __init kuser_get_tls_init(unsigned long vectors) | |||
756 | 758 | ||
757 | void __init early_trap_init(void) | 759 | void __init early_trap_init(void) |
758 | { | 760 | { |
761 | #if defined(CONFIG_CPU_USE_DOMAINS) | ||
759 | unsigned long vectors = CONFIG_VECTORS_BASE; | 762 | unsigned long vectors = CONFIG_VECTORS_BASE; |
763 | #else | ||
764 | unsigned long vectors = (unsigned long)vectors_page; | ||
765 | #endif | ||
760 | extern char __stubs_start[], __stubs_end[]; | 766 | extern char __stubs_start[], __stubs_end[]; |
761 | extern char __vectors_start[], __vectors_end[]; | 767 | extern char __vectors_start[], __vectors_end[]; |
762 | extern char __kuser_helper_start[], __kuser_helper_end[]; | 768 | extern char __kuser_helper_start[], __kuser_helper_end[]; |
@@ -780,10 +786,10 @@ void __init early_trap_init(void) | |||
780 | * Copy signal return handlers into the vector page, and | 786 | * Copy signal return handlers into the vector page, and |
781 | * set sigreturn to be a pointer to these. | 787 | * set sigreturn to be a pointer to these. |
782 | */ | 788 | */ |
783 | memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, | 789 | memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), |
784 | sizeof(sigreturn_codes)); | 790 | sigreturn_codes, sizeof(sigreturn_codes)); |
785 | memcpy((void *)KERN_RESTART_CODE, syscall_restart_code, | 791 | memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE), |
786 | sizeof(syscall_restart_code)); | 792 | syscall_restart_code, sizeof(syscall_restart_code)); |
787 | 793 | ||
788 | flush_icache_range(vectors, vectors + PAGE_SIZE); | 794 | flush_icache_range(vectors, vectors + PAGE_SIZE); |
789 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); | 795 | modify_domain(DOMAIN_USER, DOMAIN_CLIENT); |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 897c1a8f169..86b66f3f203 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -168,6 +168,7 @@ SECTIONS | |||
168 | 168 | ||
169 | NOSAVE_DATA | 169 | NOSAVE_DATA |
170 | CACHELINE_ALIGNED_DATA(32) | 170 | CACHELINE_ALIGNED_DATA(32) |
171 | READ_MOSTLY_DATA(32) | ||
171 | 172 | ||
172 | /* | 173 | /* |
173 | * The exception fixup table (might need resorting at runtime) | 174 | * The exception fixup table (might need resorting at runtime) |
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index b1631a7dbe7..1b049cd7a49 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S | |||
@@ -28,20 +28,21 @@ | |||
28 | */ | 28 | */ |
29 | #include <linux/linkage.h> | 29 | #include <linux/linkage.h> |
30 | #include <asm/errno.h> | 30 | #include <asm/errno.h> |
31 | #include <asm/domain.h> | ||
31 | 32 | ||
32 | ENTRY(__get_user_1) | 33 | ENTRY(__get_user_1) |
33 | 1: ldrbt r2, [r0] | 34 | 1: T(ldrb) r2, [r0] |
34 | mov r0, #0 | 35 | mov r0, #0 |
35 | mov pc, lr | 36 | mov pc, lr |
36 | ENDPROC(__get_user_1) | 37 | ENDPROC(__get_user_1) |
37 | 38 | ||
38 | ENTRY(__get_user_2) | 39 | ENTRY(__get_user_2) |
39 | #ifdef CONFIG_THUMB2_KERNEL | 40 | #ifdef CONFIG_THUMB2_KERNEL |
40 | 2: ldrbt r2, [r0] | 41 | 2: T(ldrb) r2, [r0] |
41 | 3: ldrbt r3, [r0, #1] | 42 | 3: T(ldrb) r3, [r0, #1] |
42 | #else | 43 | #else |
43 | 2: ldrbt r2, [r0], #1 | 44 | 2: T(ldrb) r2, [r0], #1 |
44 | 3: ldrbt r3, [r0] | 45 | 3: T(ldrb) r3, [r0] |
45 | #endif | 46 | #endif |
46 | #ifndef __ARMEB__ | 47 | #ifndef __ARMEB__ |
47 | orr r2, r2, r3, lsl #8 | 48 | orr r2, r2, r3, lsl #8 |
@@ -53,7 +54,7 @@ ENTRY(__get_user_2) | |||
53 | ENDPROC(__get_user_2) | 54 | ENDPROC(__get_user_2) |
54 | 55 | ||
55 | ENTRY(__get_user_4) | 56 | ENTRY(__get_user_4) |
56 | 4: ldrt r2, [r0] | 57 | 4: T(ldr) r2, [r0] |
57 | mov r0, #0 | 58 | mov r0, #0 |
58 | mov pc, lr | 59 | mov pc, lr |
59 | ENDPROC(__get_user_4) | 60 | ENDPROC(__get_user_4) |
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 5a01a23c6c0..c023fc11e86 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S | |||
@@ -28,9 +28,10 @@ | |||
28 | */ | 28 | */ |
29 | #include <linux/linkage.h> | 29 | #include <linux/linkage.h> |
30 | #include <asm/errno.h> | 30 | #include <asm/errno.h> |
31 | #include <asm/domain.h> | ||
31 | 32 | ||
32 | ENTRY(__put_user_1) | 33 | ENTRY(__put_user_1) |
33 | 1: strbt r2, [r0] | 34 | 1: T(strb) r2, [r0] |
34 | mov r0, #0 | 35 | mov r0, #0 |
35 | mov pc, lr | 36 | mov pc, lr |
36 | ENDPROC(__put_user_1) | 37 | ENDPROC(__put_user_1) |
@@ -39,19 +40,19 @@ ENTRY(__put_user_2) | |||
39 | mov ip, r2, lsr #8 | 40 | mov ip, r2, lsr #8 |
40 | #ifdef CONFIG_THUMB2_KERNEL | 41 | #ifdef CONFIG_THUMB2_KERNEL |
41 | #ifndef __ARMEB__ | 42 | #ifndef __ARMEB__ |
42 | 2: strbt r2, [r0] | 43 | 2: T(strb) r2, [r0] |
43 | 3: strbt ip, [r0, #1] | 44 | 3: T(strb) ip, [r0, #1] |
44 | #else | 45 | #else |
45 | 2: strbt ip, [r0] | 46 | 2: T(strb) ip, [r0] |
46 | 3: strbt r2, [r0, #1] | 47 | 3: T(strb) r2, [r0, #1] |
47 | #endif | 48 | #endif |
48 | #else /* !CONFIG_THUMB2_KERNEL */ | 49 | #else /* !CONFIG_THUMB2_KERNEL */ |
49 | #ifndef __ARMEB__ | 50 | #ifndef __ARMEB__ |
50 | 2: strbt r2, [r0], #1 | 51 | 2: T(strb) r2, [r0], #1 |
51 | 3: strbt ip, [r0] | 52 | 3: T(strb) ip, [r0] |
52 | #else | 53 | #else |
53 | 2: strbt ip, [r0], #1 | 54 | 2: T(strb) ip, [r0], #1 |
54 | 3: strbt r2, [r0] | 55 | 3: T(strb) r2, [r0] |
55 | #endif | 56 | #endif |
56 | #endif /* CONFIG_THUMB2_KERNEL */ | 57 | #endif /* CONFIG_THUMB2_KERNEL */ |
57 | mov r0, #0 | 58 | mov r0, #0 |
@@ -59,18 +60,18 @@ ENTRY(__put_user_2) | |||
59 | ENDPROC(__put_user_2) | 60 | ENDPROC(__put_user_2) |
60 | 61 | ||
61 | ENTRY(__put_user_4) | 62 | ENTRY(__put_user_4) |
62 | 4: strt r2, [r0] | 63 | 4: T(str) r2, [r0] |
63 | mov r0, #0 | 64 | mov r0, #0 |
64 | mov pc, lr | 65 | mov pc, lr |
65 | ENDPROC(__put_user_4) | 66 | ENDPROC(__put_user_4) |
66 | 67 | ||
67 | ENTRY(__put_user_8) | 68 | ENTRY(__put_user_8) |
68 | #ifdef CONFIG_THUMB2_KERNEL | 69 | #ifdef CONFIG_THUMB2_KERNEL |
69 | 5: strt r2, [r0] | 70 | 5: T(str) r2, [r0] |
70 | 6: strt r3, [r0, #4] | 71 | 6: T(str) r3, [r0, #4] |
71 | #else | 72 | #else |
72 | 5: strt r2, [r0], #4 | 73 | 5: T(str) r2, [r0], #4 |
73 | 6: strt r3, [r0] | 74 | 6: T(str) r3, [r0] |
74 | #endif | 75 | #endif |
75 | mov r0, #0 | 76 | mov r0, #0 |
76 | mov pc, lr | 77 | mov pc, lr |
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S index fee9f6f88ad..d0ece2aeb70 100644 --- a/arch/arm/lib/uaccess.S +++ b/arch/arm/lib/uaccess.S | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/linkage.h> | 14 | #include <linux/linkage.h> |
15 | #include <asm/assembler.h> | 15 | #include <asm/assembler.h> |
16 | #include <asm/errno.h> | 16 | #include <asm/errno.h> |
17 | #include <asm/domain.h> | ||
17 | 18 | ||
18 | .text | 19 | .text |
19 | 20 | ||
@@ -31,11 +32,11 @@ | |||
31 | rsb ip, ip, #4 | 32 | rsb ip, ip, #4 |
32 | cmp ip, #2 | 33 | cmp ip, #2 |
33 | ldrb r3, [r1], #1 | 34 | ldrb r3, [r1], #1 |
34 | USER( strbt r3, [r0], #1) @ May fault | 35 | USER( T(strb) r3, [r0], #1) @ May fault |
35 | ldrgeb r3, [r1], #1 | 36 | ldrgeb r3, [r1], #1 |
36 | USER( strgebt r3, [r0], #1) @ May fault | 37 | USER( T(strgeb) r3, [r0], #1) @ May fault |
37 | ldrgtb r3, [r1], #1 | 38 | ldrgtb r3, [r1], #1 |
38 | USER( strgtbt r3, [r0], #1) @ May fault | 39 | USER( T(strgtb) r3, [r0], #1) @ May fault |
39 | sub r2, r2, ip | 40 | sub r2, r2, ip |
40 | b .Lc2u_dest_aligned | 41 | b .Lc2u_dest_aligned |
41 | 42 | ||
@@ -58,7 +59,7 @@ ENTRY(__copy_to_user) | |||
58 | addmi ip, r2, #4 | 59 | addmi ip, r2, #4 |
59 | bmi .Lc2u_0nowords | 60 | bmi .Lc2u_0nowords |
60 | ldr r3, [r1], #4 | 61 | ldr r3, [r1], #4 |
61 | USER( strt r3, [r0], #4) @ May fault | 62 | USER( T(str) r3, [r0], #4) @ May fault |
62 | mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction | 63 | mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction |
63 | rsb ip, ip, #0 | 64 | rsb ip, ip, #0 |
64 | movs ip, ip, lsr #32 - PAGE_SHIFT | 65 | movs ip, ip, lsr #32 - PAGE_SHIFT |
@@ -87,18 +88,18 @@ USER( strt r3, [r0], #4) @ May fault | |||
87 | stmneia r0!, {r3 - r4} @ Shouldnt fault | 88 | stmneia r0!, {r3 - r4} @ Shouldnt fault |
88 | tst ip, #4 | 89 | tst ip, #4 |
89 | ldrne r3, [r1], #4 | 90 | ldrne r3, [r1], #4 |
90 | strnet r3, [r0], #4 @ Shouldnt fault | 91 | T(strne) r3, [r0], #4 @ Shouldnt fault |
91 | ands ip, ip, #3 | 92 | ands ip, ip, #3 |
92 | beq .Lc2u_0fupi | 93 | beq .Lc2u_0fupi |
93 | .Lc2u_0nowords: teq ip, #0 | 94 | .Lc2u_0nowords: teq ip, #0 |
94 | beq .Lc2u_finished | 95 | beq .Lc2u_finished |
95 | .Lc2u_nowords: cmp ip, #2 | 96 | .Lc2u_nowords: cmp ip, #2 |
96 | ldrb r3, [r1], #1 | 97 | ldrb r3, [r1], #1 |
97 | USER( strbt r3, [r0], #1) @ May fault | 98 | USER( T(strb) r3, [r0], #1) @ May fault |
98 | ldrgeb r3, [r1], #1 | 99 | ldrgeb r3, [r1], #1 |
99 | USER( strgebt r3, [r0], #1) @ May fault | 100 | USER( T(strgeb) r3, [r0], #1) @ May fault |
100 | ldrgtb r3, [r1], #1 | 101 | ldrgtb r3, [r1], #1 |
101 | USER( strgtbt r3, [r0], #1) @ May fault | 102 | USER( T(strgtb) r3, [r0], #1) @ May fault |
102 | b .Lc2u_finished | 103 | b .Lc2u_finished |
103 | 104 | ||
104 | .Lc2u_not_enough: | 105 | .Lc2u_not_enough: |
@@ -119,7 +120,7 @@ USER( strgtbt r3, [r0], #1) @ May fault | |||
119 | mov r3, r7, pull #8 | 120 | mov r3, r7, pull #8 |
120 | ldr r7, [r1], #4 | 121 | ldr r7, [r1], #4 |
121 | orr r3, r3, r7, push #24 | 122 | orr r3, r3, r7, push #24 |
122 | USER( strt r3, [r0], #4) @ May fault | 123 | USER( T(str) r3, [r0], #4) @ May fault |
123 | mov ip, r0, lsl #32 - PAGE_SHIFT | 124 | mov ip, r0, lsl #32 - PAGE_SHIFT |
124 | rsb ip, ip, #0 | 125 | rsb ip, ip, #0 |
125 | movs ip, ip, lsr #32 - PAGE_SHIFT | 126 | movs ip, ip, lsr #32 - PAGE_SHIFT |
@@ -154,18 +155,18 @@ USER( strt r3, [r0], #4) @ May fault | |||
154 | movne r3, r7, pull #8 | 155 | movne r3, r7, pull #8 |
155 | ldrne r7, [r1], #4 | 156 | ldrne r7, [r1], #4 |
156 | orrne r3, r3, r7, push #24 | 157 | orrne r3, r3, r7, push #24 |
157 | strnet r3, [r0], #4 @ Shouldnt fault | 158 | T(strne) r3, [r0], #4 @ Shouldnt fault |
158 | ands ip, ip, #3 | 159 | ands ip, ip, #3 |
159 | beq .Lc2u_1fupi | 160 | beq .Lc2u_1fupi |
160 | .Lc2u_1nowords: mov r3, r7, get_byte_1 | 161 | .Lc2u_1nowords: mov r3, r7, get_byte_1 |
161 | teq ip, #0 | 162 | teq ip, #0 |
162 | beq .Lc2u_finished | 163 | beq .Lc2u_finished |
163 | cmp ip, #2 | 164 | cmp ip, #2 |
164 | USER( strbt r3, [r0], #1) @ May fault | 165 | USER( T(strb) r3, [r0], #1) @ May fault |
165 | movge r3, r7, get_byte_2 | 166 | movge r3, r7, get_byte_2 |
166 | USER( strgebt r3, [r0], #1) @ May fault | 167 | USER( T(strgeb) r3, [r0], #1) @ May fault |
167 | movgt r3, r7, get_byte_3 | 168 | movgt r3, r7, get_byte_3 |
168 | USER( strgtbt r3, [r0], #1) @ May fault | 169 | USER( T(strgtb) r3, [r0], #1) @ May fault |
169 | b .Lc2u_finished | 170 | b .Lc2u_finished |
170 | 171 | ||
171 | .Lc2u_2fupi: subs r2, r2, #4 | 172 | .Lc2u_2fupi: subs r2, r2, #4 |
@@ -174,7 +175,7 @@ USER( strgtbt r3, [r0], #1) @ May fault | |||
174 | mov r3, r7, pull #16 | 175 | mov r3, r7, pull #16 |
175 | ldr r7, [r1], #4 | 176 | ldr r7, [r1], #4 |
176 | orr r3, r3, r7, push #16 | 177 | orr r3, r3, r7, push #16 |
177 | USER( strt r3, [r0], #4) @ May fault | 178 | USER( T(str) r3, [r0], #4) @ May fault |
178 | mov ip, r0, lsl #32 - PAGE_SHIFT | 179 | mov ip, r0, lsl #32 - PAGE_SHIFT |
179 | rsb ip, ip, #0 | 180 | rsb ip, ip, #0 |
180 | movs ip, ip, lsr #32 - PAGE_SHIFT | 181 | movs ip, ip, lsr #32 - PAGE_SHIFT |
@@ -209,18 +210,18 @@ USER( strt r3, [r0], #4) @ May fault | |||
209 | movne r3, r7, pull #16 | 210 | movne r3, r7, pull #16 |
210 | ldrne r7, [r1], #4 | 211 | ldrne r7, [r1], #4 |
211 | orrne r3, r3, r7, push #16 | 212 | orrne r3, r3, r7, push #16 |
212 | strnet r3, [r0], #4 @ Shouldnt fault | 213 | T(strne) r3, [r0], #4 @ Shouldnt fault |
213 | ands ip, ip, #3 | 214 | ands ip, ip, #3 |
214 | beq .Lc2u_2fupi | 215 | beq .Lc2u_2fupi |
215 | .Lc2u_2nowords: mov r3, r7, get_byte_2 | 216 | .Lc2u_2nowords: mov r3, r7, get_byte_2 |
216 | teq ip, #0 | 217 | teq ip, #0 |
217 | beq .Lc2u_finished | 218 | beq .Lc2u_finished |
218 | cmp ip, #2 | 219 | cmp ip, #2 |
219 | USER( strbt r3, [r0], #1) @ May fault | 220 | USER( T(strb) r3, [r0], #1) @ May fault |
220 | movge r3, r7, get_byte_3 | 221 | movge r3, r7, get_byte_3 |
221 | USER( strgebt r3, [r0], #1) @ May fault | 222 | USER( T(strgeb) r3, [r0], #1) @ May fault |
222 | ldrgtb r3, [r1], #0 | 223 | ldrgtb r3, [r1], #0 |
223 | USER( strgtbt r3, [r0], #1) @ May fault | 224 | USER( T(strgtb) r3, [r0], #1) @ May fault |
224 | b .Lc2u_finished | 225 | b .Lc2u_finished |
225 | 226 | ||
226 | .Lc2u_3fupi: subs r2, r2, #4 | 227 | .Lc2u_3fupi: subs r2, r2, #4 |
@@ -229,7 +230,7 @@ USER( strgtbt r3, [r0], #1) @ May fault | |||
229 | mov r3, r7, pull #24 | 230 | mov r3, r7, pull #24 |
230 | ldr r7, [r1], #4 | 231 | ldr r7, [r1], #4 |
231 | orr r3, r3, r7, push #8 | 232 | orr r3, r3, r7, push #8 |
232 | USER( strt r3, [r0], #4) @ May fault | 233 | USER( T(str) r3, [r0], #4) @ May fault |
233 | mov ip, r0, lsl #32 - PAGE_SHIFT | 234 | mov ip, r0, lsl #32 - PAGE_SHIFT |
234 | rsb ip, ip, #0 | 235 | rsb ip, ip, #0 |
235 | movs ip, ip, lsr #32 - PAGE_SHIFT | 236 | movs ip, ip, lsr #32 - PAGE_SHIFT |
@@ -264,18 +265,18 @@ USER( strt r3, [r0], #4) @ May fault | |||
264 | movne r3, r7, pull #24 | 265 | movne r3, r7, pull #24 |
265 | ldrne r7, [r1], #4 | 266 | ldrne r7, [r1], #4 |
266 | orrne r3, r3, r7, push #8 | 267 | orrne r3, r3, r7, push #8 |
267 | strnet r3, [r0], #4 @ Shouldnt fault | 268 | T(strne) r3, [r0], #4 @ Shouldnt fault |
268 | ands ip, ip, #3 | 269 | ands ip, ip, #3 |
269 | beq .Lc2u_3fupi | 270 | beq .Lc2u_3fupi |
270 | .Lc2u_3nowords: mov r3, r7, get_byte_3 | 271 | .Lc2u_3nowords: mov r3, r7, get_byte_3 |
271 | teq ip, #0 | 272 | teq ip, #0 |
272 | beq .Lc2u_finished | 273 | beq .Lc2u_finished |
273 | cmp ip, #2 | 274 | cmp ip, #2 |
274 | USER( strbt r3, [r0], #1) @ May fault | 275 | USER( T(strb) r3, [r0], #1) @ May fault |
275 | ldrgeb r3, [r1], #1 | 276 | ldrgeb r3, [r1], #1 |
276 | USER( strgebt r3, [r0], #1) @ May fault | 277 | USER( T(strgeb) r3, [r0], #1) @ May fault |
277 | ldrgtb r3, [r1], #0 | 278 | ldrgtb r3, [r1], #0 |
278 | USER( strgtbt r3, [r0], #1) @ May fault | 279 | USER( T(strgtb) r3, [r0], #1) @ May fault |
279 | b .Lc2u_finished | 280 | b .Lc2u_finished |
280 | ENDPROC(__copy_to_user) | 281 | ENDPROC(__copy_to_user) |
281 | 282 | ||
@@ -294,11 +295,11 @@ ENDPROC(__copy_to_user) | |||
294 | .Lcfu_dest_not_aligned: | 295 | .Lcfu_dest_not_aligned: |
295 | rsb ip, ip, #4 | 296 | rsb ip, ip, #4 |
296 | cmp ip, #2 | 297 | cmp ip, #2 |
297 | USER( ldrbt r3, [r1], #1) @ May fault | 298 | USER( T(ldrb) r3, [r1], #1) @ May fault |
298 | strb r3, [r0], #1 | 299 | strb r3, [r0], #1 |
299 | USER( ldrgebt r3, [r1], #1) @ May fault | 300 | USER( T(ldrgeb) r3, [r1], #1) @ May fault |
300 | strgeb r3, [r0], #1 | 301 | strgeb r3, [r0], #1 |
301 | USER( ldrgtbt r3, [r1], #1) @ May fault | 302 | USER( T(ldrgtb) r3, [r1], #1) @ May fault |
302 | strgtb r3, [r0], #1 | 303 | strgtb r3, [r0], #1 |
303 | sub r2, r2, ip | 304 | sub r2, r2, ip |
304 | b .Lcfu_dest_aligned | 305 | b .Lcfu_dest_aligned |
@@ -321,7 +322,7 @@ ENTRY(__copy_from_user) | |||
321 | .Lcfu_0fupi: subs r2, r2, #4 | 322 | .Lcfu_0fupi: subs r2, r2, #4 |
322 | addmi ip, r2, #4 | 323 | addmi ip, r2, #4 |
323 | bmi .Lcfu_0nowords | 324 | bmi .Lcfu_0nowords |
324 | USER( ldrt r3, [r1], #4) | 325 | USER( T(ldr) r3, [r1], #4) |
325 | str r3, [r0], #4 | 326 | str r3, [r0], #4 |
326 | mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction | 327 | mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction |
327 | rsb ip, ip, #0 | 328 | rsb ip, ip, #0 |
@@ -350,18 +351,18 @@ USER( ldrt r3, [r1], #4) | |||
350 | ldmneia r1!, {r3 - r4} @ Shouldnt fault | 351 | ldmneia r1!, {r3 - r4} @ Shouldnt fault |
351 | stmneia r0!, {r3 - r4} | 352 | stmneia r0!, {r3 - r4} |
352 | tst ip, #4 | 353 | tst ip, #4 |
353 | ldrnet r3, [r1], #4 @ Shouldnt fault | 354 | T(ldrne) r3, [r1], #4 @ Shouldnt fault |
354 | strne r3, [r0], #4 | 355 | strne r3, [r0], #4 |
355 | ands ip, ip, #3 | 356 | ands ip, ip, #3 |
356 | beq .Lcfu_0fupi | 357 | beq .Lcfu_0fupi |
357 | .Lcfu_0nowords: teq ip, #0 | 358 | .Lcfu_0nowords: teq ip, #0 |
358 | beq .Lcfu_finished | 359 | beq .Lcfu_finished |
359 | .Lcfu_nowords: cmp ip, #2 | 360 | .Lcfu_nowords: cmp ip, #2 |
360 | USER( ldrbt r3, [r1], #1) @ May fault | 361 | USER( T(ldrb) r3, [r1], #1) @ May fault |
361 | strb r3, [r0], #1 | 362 | strb r3, [r0], #1 |
362 | USER( ldrgebt r3, [r1], #1) @ May fault | 363 | USER( T(ldrgeb) r3, [r1], #1) @ May fault |
363 | strgeb r3, [r0], #1 | 364 | strgeb r3, [r0], #1 |
364 | USER( ldrgtbt r3, [r1], #1) @ May fault | 365 | USER( T(ldrgtb) r3, [r1], #1) @ May fault |
365 | strgtb r3, [r0], #1 | 366 | strgtb r3, [r0], #1 |
366 | b .Lcfu_finished | 367 | b .Lcfu_finished |
367 | 368 | ||
@@ -374,7 +375,7 @@ USER( ldrgtbt r3, [r1], #1) @ May fault | |||
374 | 375 | ||
375 | .Lcfu_src_not_aligned: | 376 | .Lcfu_src_not_aligned: |
376 | bic r1, r1, #3 | 377 | bic r1, r1, #3 |
377 | USER( ldrt r7, [r1], #4) @ May fault | 378 | USER( T(ldr) r7, [r1], #4) @ May fault |
378 | cmp ip, #2 | 379 | cmp ip, #2 |
379 | bgt .Lcfu_3fupi | 380 | bgt .Lcfu_3fupi |
380 | beq .Lcfu_2fupi | 381 | beq .Lcfu_2fupi |
@@ -382,7 +383,7 @@ USER( ldrt r7, [r1], #4) @ May fault | |||
382 | addmi ip, r2, #4 | 383 | addmi ip, r2, #4 |
383 | bmi .Lcfu_1nowords | 384 | bmi .Lcfu_1nowords |
384 | mov r3, r7, pull #8 | 385 | mov r3, r7, pull #8 |
385 | USER( ldrt r7, [r1], #4) @ May fault | 386 | USER( T(ldr) r7, [r1], #4) @ May fault |
386 | orr r3, r3, r7, push #24 | 387 | orr r3, r3, r7, push #24 |
387 | str r3, [r0], #4 | 388 | str r3, [r0], #4 |
388 | mov ip, r1, lsl #32 - PAGE_SHIFT | 389 | mov ip, r1, lsl #32 - PAGE_SHIFT |
@@ -417,7 +418,7 @@ USER( ldrt r7, [r1], #4) @ May fault | |||
417 | stmneia r0!, {r3 - r4} | 418 | stmneia r0!, {r3 - r4} |
418 | tst ip, #4 | 419 | tst ip, #4 |
419 | movne r3, r7, pull #8 | 420 | movne r3, r7, pull #8 |
420 | USER( ldrnet r7, [r1], #4) @ May fault | 421 | USER( T(ldrne) r7, [r1], #4) @ May fault |
421 | orrne r3, r3, r7, push #24 | 422 | orrne r3, r3, r7, push #24 |
422 | strne r3, [r0], #4 | 423 | strne r3, [r0], #4 |
423 | ands ip, ip, #3 | 424 | ands ip, ip, #3 |
@@ -437,7 +438,7 @@ USER( ldrnet r7, [r1], #4) @ May fault | |||
437 | addmi ip, r2, #4 | 438 | addmi ip, r2, #4 |
438 | bmi .Lcfu_2nowords | 439 | bmi .Lcfu_2nowords |
439 | mov r3, r7, pull #16 | 440 | mov r3, r7, pull #16 |
440 | USER( ldrt r7, [r1], #4) @ May fault | 441 | USER( T(ldr) r7, [r1], #4) @ May fault |
441 | orr r3, r3, r7, push #16 | 442 | orr r3, r3, r7, push #16 |
442 | str r3, [r0], #4 | 443 | str r3, [r0], #4 |
443 | mov ip, r1, lsl #32 - PAGE_SHIFT | 444 | mov ip, r1, lsl #32 - PAGE_SHIFT |
@@ -473,7 +474,7 @@ USER( ldrt r7, [r1], #4) @ May fault | |||
473 | stmneia r0!, {r3 - r4} | 474 | stmneia r0!, {r3 - r4} |
474 | tst ip, #4 | 475 | tst ip, #4 |
475 | movne r3, r7, pull #16 | 476 | movne r3, r7, pull #16 |
476 | USER( ldrnet r7, [r1], #4) @ May fault | 477 | USER( T(ldrne) r7, [r1], #4) @ May fault |
477 | orrne r3, r3, r7, push #16 | 478 | orrne r3, r3, r7, push #16 |
478 | strne r3, [r0], #4 | 479 | strne r3, [r0], #4 |
479 | ands ip, ip, #3 | 480 | ands ip, ip, #3 |
@@ -485,7 +486,7 @@ USER( ldrnet r7, [r1], #4) @ May fault | |||
485 | strb r3, [r0], #1 | 486 | strb r3, [r0], #1 |
486 | movge r3, r7, get_byte_3 | 487 | movge r3, r7, get_byte_3 |
487 | strgeb r3, [r0], #1 | 488 | strgeb r3, [r0], #1 |
488 | USER( ldrgtbt r3, [r1], #0) @ May fault | 489 | USER( T(ldrgtb) r3, [r1], #0) @ May fault |
489 | strgtb r3, [r0], #1 | 490 | strgtb r3, [r0], #1 |
490 | b .Lcfu_finished | 491 | b .Lcfu_finished |
491 | 492 | ||
@@ -493,7 +494,7 @@ USER( ldrgtbt r3, [r1], #0) @ May fault | |||
493 | addmi ip, r2, #4 | 494 | addmi ip, r2, #4 |
494 | bmi .Lcfu_3nowords | 495 | bmi .Lcfu_3nowords |
495 | mov r3, r7, pull #24 | 496 | mov r3, r7, pull #24 |
496 | USER( ldrt r7, [r1], #4) @ May fault | 497 | USER( T(ldr) r7, [r1], #4) @ May fault |
497 | orr r3, r3, r7, push #8 | 498 | orr r3, r3, r7, push #8 |
498 | str r3, [r0], #4 | 499 | str r3, [r0], #4 |
499 | mov ip, r1, lsl #32 - PAGE_SHIFT | 500 | mov ip, r1, lsl #32 - PAGE_SHIFT |
@@ -528,7 +529,7 @@ USER( ldrt r7, [r1], #4) @ May fault | |||
528 | stmneia r0!, {r3 - r4} | 529 | stmneia r0!, {r3 - r4} |
529 | tst ip, #4 | 530 | tst ip, #4 |
530 | movne r3, r7, pull #24 | 531 | movne r3, r7, pull #24 |
531 | USER( ldrnet r7, [r1], #4) @ May fault | 532 | USER( T(ldrne) r7, [r1], #4) @ May fault |
532 | orrne r3, r3, r7, push #8 | 533 | orrne r3, r3, r7, push #8 |
533 | strne r3, [r0], #4 | 534 | strne r3, [r0], #4 |
534 | ands ip, ip, #3 | 535 | ands ip, ip, #3 |
@@ -538,9 +539,9 @@ USER( ldrnet r7, [r1], #4) @ May fault | |||
538 | beq .Lcfu_finished | 539 | beq .Lcfu_finished |
539 | cmp ip, #2 | 540 | cmp ip, #2 |
540 | strb r3, [r0], #1 | 541 | strb r3, [r0], #1 |
541 | USER( ldrgebt r3, [r1], #1) @ May fault | 542 | USER( T(ldrgeb) r3, [r1], #1) @ May fault |
542 | strgeb r3, [r0], #1 | 543 | strgeb r3, [r0], #1 |
543 | USER( ldrgtbt r3, [r1], #1) @ May fault | 544 | USER( T(ldrgtb) r3, [r1], #1) @ May fault |
544 | strgtb r3, [r0], #1 | 545 | strgtb r3, [r0], #1 |
545 | b .Lcfu_finished | 546 | b .Lcfu_finished |
546 | ENDPROC(__copy_from_user) | 547 | ENDPROC(__copy_from_user) |
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 62d686f0b42..d13add71f72 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile | |||
@@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o | |||
65 | obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o | 65 | obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o |
66 | obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o | 66 | obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o |
67 | obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o | 67 | obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o |
68 | obj-$(CONFIG_MACH_PCONTROL_G20) += board-pcontrol-g20.o | 68 | obj-$(CONFIG_MACH_PCONTROL_G20) += board-pcontrol-g20.o board-stamp9g20.o |
69 | 69 | ||
70 | # AT91SAM9260/AT91SAM9G20 board-specific support | 70 | # AT91SAM9260/AT91SAM9G20 board-specific support |
71 | obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o | 71 | obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o |
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index 2500f41d8d2..1dd69c85dfe 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c | |||
@@ -101,7 +101,6 @@ static struct clocksource clk32k = { | |||
101 | .rating = 150, | 101 | .rating = 150, |
102 | .read = read_clk32k, | 102 | .read = read_clk32k, |
103 | .mask = CLOCKSOURCE_MASK(20), | 103 | .mask = CLOCKSOURCE_MASK(20), |
104 | .shift = 10, | ||
105 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 104 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
106 | }; | 105 | }; |
107 | 106 | ||
@@ -201,8 +200,7 @@ void __init at91rm9200_timer_init(void) | |||
201 | clockevents_register_device(&clkevt); | 200 | clockevents_register_device(&clkevt); |
202 | 201 | ||
203 | /* register clocksource */ | 202 | /* register clocksource */ |
204 | clk32k.mult = clocksource_hz2mult(AT91_SLOW_CLOCK, clk32k.shift); | 203 | clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK); |
205 | clocksource_register(&clk32k); | ||
206 | } | 204 | } |
207 | 205 | ||
208 | struct sys_timer at91rm9200_timer = { | 206 | struct sys_timer at91rm9200_timer = { |
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index 608a63240b6..4ba85499fa9 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c | |||
@@ -51,7 +51,6 @@ static struct clocksource pit_clk = { | |||
51 | .name = "pit", | 51 | .name = "pit", |
52 | .rating = 175, | 52 | .rating = 175, |
53 | .read = read_pit_clk, | 53 | .read = read_pit_clk, |
54 | .shift = 20, | ||
55 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 54 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
56 | }; | 55 | }; |
57 | 56 | ||
@@ -163,10 +162,9 @@ static void __init at91sam926x_pit_init(void) | |||
163 | * Register clocksource. The high order bits of PIV are unused, | 162 | * Register clocksource. The high order bits of PIV are unused, |
164 | * so this isn't a 32-bit counter unless we get clockevent irqs. | 163 | * so this isn't a 32-bit counter unless we get clockevent irqs. |
165 | */ | 164 | */ |
166 | pit_clk.mult = clocksource_hz2mult(pit_rate, pit_clk.shift); | ||
167 | bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */; | 165 | bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */; |
168 | pit_clk.mask = CLOCKSOURCE_MASK(bits); | 166 | pit_clk.mask = CLOCKSOURCE_MASK(bits); |
169 | clocksource_register(&pit_clk); | 167 | clocksource_register_hz(&pit_clk, pit_rate); |
170 | 168 | ||
171 | /* Set up irq handler */ | 169 | /* Set up irq handler */ |
172 | setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq); | 170 | setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq); |
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c index bba5a560e02..feb65787c30 100644 --- a/arch/arm/mach-at91/board-pcontrol-g20.c +++ b/arch/arm/mach-at91/board-pcontrol-g20.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include <mach/board.h> | 32 | #include <mach/board.h> |
33 | #include <mach/at91sam9_smc.h> | 33 | #include <mach/at91sam9_smc.h> |
34 | #include <mach/stamp9g20.h> | ||
34 | 35 | ||
35 | #include "sam9_smc.h" | 36 | #include "sam9_smc.h" |
36 | #include "generic.h" | 37 | #include "generic.h" |
@@ -38,11 +39,7 @@ | |||
38 | 39 | ||
39 | static void __init pcontrol_g20_map_io(void) | 40 | static void __init pcontrol_g20_map_io(void) |
40 | { | 41 | { |
41 | /* Initialize processor: 18.432 MHz crystal */ | 42 | stamp9g20_map_io(); |
42 | at91sam9260_initialize(18432000); | ||
43 | |||
44 | /* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */ | ||
45 | at91_register_uart(0, 0, 0); | ||
46 | 43 | ||
47 | /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback A2 */ | 44 | /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback A2 */ |
48 | at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | 45 | at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS |
@@ -54,9 +51,6 @@ static void __init pcontrol_g20_map_io(void) | |||
54 | 51 | ||
55 | /* USART2 on ttyS3. (Rx, Tx) 9bit-Bus Multidrop-mode X4 */ | 52 | /* USART2 on ttyS3. (Rx, Tx) 9bit-Bus Multidrop-mode X4 */ |
56 | at91_register_uart(AT91SAM9260_ID_US4, 3, 0); | 53 | at91_register_uart(AT91SAM9260_ID_US4, 3, 0); |
57 | |||
58 | /* set serial console to ttyS0 (ie, DBGU) */ | ||
59 | at91_set_serial_console(0); | ||
60 | } | 54 | } |
61 | 55 | ||
62 | 56 | ||
@@ -66,38 +60,6 @@ static void __init init_irq(void) | |||
66 | } | 60 | } |
67 | 61 | ||
68 | 62 | ||
69 | /* | ||
70 | * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB | ||
71 | */ | ||
72 | static struct atmel_nand_data __initdata nand_data = { | ||
73 | .ale = 21, | ||
74 | .cle = 22, | ||
75 | .rdy_pin = AT91_PIN_PC13, | ||
76 | .enable_pin = AT91_PIN_PC14, | ||
77 | }; | ||
78 | |||
79 | /* | ||
80 | * Bus timings; unit = 7.57ns | ||
81 | */ | ||
82 | static struct sam9_smc_config __initdata nand_smc_config = { | ||
83 | .ncs_read_setup = 0, | ||
84 | .nrd_setup = 2, | ||
85 | .ncs_write_setup = 0, | ||
86 | .nwe_setup = 2, | ||
87 | |||
88 | .ncs_read_pulse = 4, | ||
89 | .nrd_pulse = 4, | ||
90 | .ncs_write_pulse = 4, | ||
91 | .nwe_pulse = 4, | ||
92 | |||
93 | .read_cycle = 7, | ||
94 | .write_cycle = 7, | ||
95 | |||
96 | .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | ||
97 | | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, | ||
98 | .tdf_cycles = 3, | ||
99 | }; | ||
100 | |||
101 | static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { { | 63 | static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { { |
102 | .ncs_read_setup = 16, | 64 | .ncs_read_setup = 16, |
103 | .nrd_setup = 18, | 65 | .nrd_setup = 18, |
@@ -138,14 +100,6 @@ static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { { | |||
138 | .tdf_cycles = 1, | 100 | .tdf_cycles = 1, |
139 | } }; | 101 | } }; |
140 | 102 | ||
141 | static void __init add_device_nand(void) | ||
142 | { | ||
143 | /* configure chip-select 3 (NAND) */ | ||
144 | sam9_smc_configure(3, &nand_smc_config); | ||
145 | at91_add_device_nand(&nand_data); | ||
146 | } | ||
147 | |||
148 | |||
149 | static void __init add_device_pcontrol(void) | 103 | static void __init add_device_pcontrol(void) |
150 | { | 104 | { |
151 | /* configure chip-select 4 (IO compatible to 8051 X4 ) */ | 105 | /* configure chip-select 4 (IO compatible to 8051 X4 ) */ |
@@ -156,23 +110,6 @@ static void __init add_device_pcontrol(void) | |||
156 | 110 | ||
157 | 111 | ||
158 | /* | 112 | /* |
159 | * MCI (SD/MMC) | ||
160 | * det_pin, wp_pin and vcc_pin are not connected | ||
161 | */ | ||
162 | #if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) | ||
163 | static struct mci_platform_data __initdata mmc_data = { | ||
164 | .slot[0] = { | ||
165 | .bus_width = 4, | ||
166 | }, | ||
167 | }; | ||
168 | #else | ||
169 | static struct at91_mmc_data __initdata mmc_data = { | ||
170 | .wire4 = 1, | ||
171 | }; | ||
172 | #endif | ||
173 | |||
174 | |||
175 | /* | ||
176 | * USB Host port | 113 | * USB Host port |
177 | */ | 114 | */ |
178 | static struct at91_usbh_data __initdata usbh_data = { | 115 | static struct at91_usbh_data __initdata usbh_data = { |
@@ -265,42 +202,13 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = { | |||
265 | }; | 202 | }; |
266 | 203 | ||
267 | 204 | ||
268 | /* | ||
269 | * Dallas 1-Wire DS2431 | ||
270 | */ | ||
271 | static struct w1_gpio_platform_data w1_gpio_pdata = { | ||
272 | .pin = AT91_PIN_PA29, | ||
273 | .is_open_drain = 1, | ||
274 | }; | ||
275 | |||
276 | static struct platform_device w1_device = { | ||
277 | .name = "w1-gpio", | ||
278 | .id = -1, | ||
279 | .dev.platform_data = &w1_gpio_pdata, | ||
280 | }; | ||
281 | |||
282 | static void add_wire1(void) | ||
283 | { | ||
284 | at91_set_GPIO_periph(w1_gpio_pdata.pin, 1); | ||
285 | at91_set_multi_drive(w1_gpio_pdata.pin, 1); | ||
286 | platform_device_register(&w1_device); | ||
287 | } | ||
288 | |||
289 | |||
290 | static void __init pcontrol_g20_board_init(void) | 205 | static void __init pcontrol_g20_board_init(void) |
291 | { | 206 | { |
292 | at91_add_device_serial(); | 207 | stamp9g20_board_init(); |
293 | add_device_nand(); | ||
294 | #if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) | ||
295 | at91_add_device_mci(0, &mmc_data); | ||
296 | #else | ||
297 | at91_add_device_mmc(0, &mmc_data); | ||
298 | #endif | ||
299 | at91_add_device_usbh(&usbh_data); | 208 | at91_add_device_usbh(&usbh_data); |
300 | at91_add_device_eth(&macb_data); | 209 | at91_add_device_eth(&macb_data); |
301 | at91_add_device_i2c(pcontrol_g20_i2c_devices, | 210 | at91_add_device_i2c(pcontrol_g20_i2c_devices, |
302 | ARRAY_SIZE(pcontrol_g20_i2c_devices)); | 211 | ARRAY_SIZE(pcontrol_g20_i2c_devices)); |
303 | add_wire1(); | ||
304 | add_device_pcontrol(); | 212 | add_device_pcontrol(); |
305 | at91_add_device_spi(pcontrol_g20_spi_devices, | 213 | at91_add_device_spi(pcontrol_g20_spi_devices, |
306 | ARRAY_SIZE(pcontrol_g20_spi_devices)); | 214 | ARRAY_SIZE(pcontrol_g20_spi_devices)); |
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c index 5206eef4a67..f8902b11896 100644 --- a/arch/arm/mach-at91/board-stamp9g20.c +++ b/arch/arm/mach-at91/board-stamp9g20.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include "generic.h" | 32 | #include "generic.h" |
33 | 33 | ||
34 | 34 | ||
35 | static void __init portuxg20_map_io(void) | 35 | void __init stamp9g20_map_io(void) |
36 | { | 36 | { |
37 | /* Initialize processor: 18.432 MHz crystal */ | 37 | /* Initialize processor: 18.432 MHz crystal */ |
38 | at91sam9260_initialize(18432000); | 38 | at91sam9260_initialize(18432000); |
@@ -40,6 +40,24 @@ static void __init portuxg20_map_io(void) | |||
40 | /* DGBU on ttyS0. (Rx & Tx only) */ | 40 | /* DGBU on ttyS0. (Rx & Tx only) */ |
41 | at91_register_uart(0, 0, 0); | 41 | at91_register_uart(0, 0, 0); |
42 | 42 | ||
43 | /* set serial console to ttyS0 (ie, DBGU) */ | ||
44 | at91_set_serial_console(0); | ||
45 | } | ||
46 | |||
47 | static void __init stamp9g20evb_map_io(void) | ||
48 | { | ||
49 | stamp9g20_map_io(); | ||
50 | |||
51 | /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ | ||
52 | at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS | ||
53 | | ATMEL_UART_DTR | ATMEL_UART_DSR | ||
54 | | ATMEL_UART_DCD | ATMEL_UART_RI); | ||
55 | } | ||
56 | |||
57 | static void __init portuxg20_map_io(void) | ||
58 | { | ||
59 | stamp9g20_map_io(); | ||
60 | |||
43 | /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ | 61 | /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ |
44 | at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS | 62 | at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS |
45 | | ATMEL_UART_DTR | ATMEL_UART_DSR | 63 | | ATMEL_UART_DTR | ATMEL_UART_DSR |
@@ -56,26 +74,6 @@ static void __init portuxg20_map_io(void) | |||
56 | 74 | ||
57 | /* USART5 on ttyS6. (Rx, Tx only) */ | 75 | /* USART5 on ttyS6. (Rx, Tx only) */ |
58 | at91_register_uart(AT91SAM9260_ID_US5, 6, 0); | 76 | at91_register_uart(AT91SAM9260_ID_US5, 6, 0); |
59 | |||
60 | /* set serial console to ttyS0 (ie, DBGU) */ | ||
61 | at91_set_serial_console(0); | ||
62 | } | ||
63 | |||
64 | static void __init stamp9g20_map_io(void) | ||
65 | { | ||
66 | /* Initialize processor: 18.432 MHz crystal */ | ||
67 | at91sam9260_initialize(18432000); | ||
68 | |||
69 | /* DGBU on ttyS0. (Rx & Tx only) */ | ||
70 | at91_register_uart(0, 0, 0); | ||
71 | |||
72 | /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ | ||
73 | at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS | ||
74 | | ATMEL_UART_DTR | ATMEL_UART_DSR | ||
75 | | ATMEL_UART_DCD | ATMEL_UART_RI); | ||
76 | |||
77 | /* set serial console to ttyS0 (ie, DBGU) */ | ||
78 | at91_set_serial_console(0); | ||
79 | } | 77 | } |
80 | 78 | ||
81 | static void __init init_irq(void) | 79 | static void __init init_irq(void) |
@@ -156,7 +154,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = { | |||
156 | .pullup_pin = 0, /* pull-up driven by UDC */ | 154 | .pullup_pin = 0, /* pull-up driven by UDC */ |
157 | }; | 155 | }; |
158 | 156 | ||
159 | static struct at91_udc_data __initdata stamp9g20_udc_data = { | 157 | static struct at91_udc_data __initdata stamp9g20evb_udc_data = { |
160 | .vbus_pin = AT91_PIN_PA22, | 158 | .vbus_pin = AT91_PIN_PA22, |
161 | .pullup_pin = 0, /* pull-up driven by UDC */ | 159 | .pullup_pin = 0, /* pull-up driven by UDC */ |
162 | }; | 160 | }; |
@@ -190,7 +188,7 @@ static struct gpio_led portuxg20_leds[] = { | |||
190 | } | 188 | } |
191 | }; | 189 | }; |
192 | 190 | ||
193 | static struct gpio_led stamp9g20_leds[] = { | 191 | static struct gpio_led stamp9g20evb_leds[] = { |
194 | { | 192 | { |
195 | .name = "D8", | 193 | .name = "D8", |
196 | .gpio = AT91_PIN_PB18, | 194 | .gpio = AT91_PIN_PB18, |
@@ -250,7 +248,7 @@ void add_w1(void) | |||
250 | } | 248 | } |
251 | 249 | ||
252 | 250 | ||
253 | static void __init generic_board_init(void) | 251 | void __init stamp9g20_board_init(void) |
254 | { | 252 | { |
255 | /* Serial */ | 253 | /* Serial */ |
256 | at91_add_device_serial(); | 254 | at91_add_device_serial(); |
@@ -262,34 +260,40 @@ static void __init generic_board_init(void) | |||
262 | #else | 260 | #else |
263 | at91_add_device_mmc(0, &mmc_data); | 261 | at91_add_device_mmc(0, &mmc_data); |
264 | #endif | 262 | #endif |
265 | /* USB Host */ | ||
266 | at91_add_device_usbh(&usbh_data); | ||
267 | /* Ethernet */ | ||
268 | at91_add_device_eth(&macb_data); | ||
269 | /* I2C */ | ||
270 | at91_add_device_i2c(NULL, 0); | ||
271 | /* W1 */ | 263 | /* W1 */ |
272 | add_w1(); | 264 | add_w1(); |
273 | } | 265 | } |
274 | 266 | ||
275 | static void __init portuxg20_board_init(void) | 267 | static void __init portuxg20_board_init(void) |
276 | { | 268 | { |
277 | generic_board_init(); | 269 | stamp9g20_board_init(); |
278 | /* SPI */ | 270 | /* USB Host */ |
279 | at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices)); | 271 | at91_add_device_usbh(&usbh_data); |
280 | /* USB Device */ | 272 | /* USB Device */ |
281 | at91_add_device_udc(&portuxg20_udc_data); | 273 | at91_add_device_udc(&portuxg20_udc_data); |
274 | /* Ethernet */ | ||
275 | at91_add_device_eth(&macb_data); | ||
276 | /* I2C */ | ||
277 | at91_add_device_i2c(NULL, 0); | ||
278 | /* SPI */ | ||
279 | at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices)); | ||
282 | /* LEDs */ | 280 | /* LEDs */ |
283 | at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds)); | 281 | at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds)); |
284 | } | 282 | } |
285 | 283 | ||
286 | static void __init stamp9g20_board_init(void) | 284 | static void __init stamp9g20evb_board_init(void) |
287 | { | 285 | { |
288 | generic_board_init(); | 286 | stamp9g20_board_init(); |
287 | /* USB Host */ | ||
288 | at91_add_device_usbh(&usbh_data); | ||
289 | /* USB Device */ | 289 | /* USB Device */ |
290 | at91_add_device_udc(&stamp9g20_udc_data); | 290 | at91_add_device_udc(&stamp9g20evb_udc_data); |
291 | /* Ethernet */ | ||
292 | at91_add_device_eth(&macb_data); | ||
293 | /* I2C */ | ||
294 | at91_add_device_i2c(NULL, 0); | ||
291 | /* LEDs */ | 295 | /* LEDs */ |
292 | at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds)); | 296 | at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds)); |
293 | } | 297 | } |
294 | 298 | ||
295 | MACHINE_START(PORTUXG20, "taskit PortuxG20") | 299 | MACHINE_START(PORTUXG20, "taskit PortuxG20") |
@@ -305,7 +309,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20") | |||
305 | /* Maintainer: taskit GmbH */ | 309 | /* Maintainer: taskit GmbH */ |
306 | .boot_params = AT91_SDRAM_BASE + 0x100, | 310 | .boot_params = AT91_SDRAM_BASE + 0x100, |
307 | .timer = &at91sam926x_timer, | 311 | .timer = &at91sam926x_timer, |
308 | .map_io = stamp9g20_map_io, | 312 | .map_io = stamp9g20evb_map_io, |
309 | .init_irq = init_irq, | 313 | .init_irq = init_irq, |
310 | .init_machine = stamp9g20_board_init, | 314 | .init_machine = stamp9g20evb_board_init, |
311 | MACHINE_END | 315 | MACHINE_END |
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 7525cee3983..9113da6845f 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c | |||
@@ -658,7 +658,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock) | |||
658 | /* Now set uhpck values */ | 658 | /* Now set uhpck values */ |
659 | uhpck.parent = &utmi_clk; | 659 | uhpck.parent = &utmi_clk; |
660 | uhpck.pmc_mask = AT91SAM926x_PMC_UHP; | 660 | uhpck.pmc_mask = AT91SAM926x_PMC_UHP; |
661 | uhpck.rate_hz = utmi_clk.parent->rate_hz; | 661 | uhpck.rate_hz = utmi_clk.rate_hz; |
662 | uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8); | 662 | uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8); |
663 | } | 663 | } |
664 | 664 | ||
diff --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/arch/arm/mach-at91/include/mach/at91_mci.h index 57f8ee15494..27ac6f550fe 100644 --- a/arch/arm/mach-at91/include/mach/at91_mci.h +++ b/arch/arm/mach-at91/include/mach/at91_mci.h | |||
@@ -74,6 +74,8 @@ | |||
74 | #define AT91_MCI_TRTYP_BLOCK (0 << 19) | 74 | #define AT91_MCI_TRTYP_BLOCK (0 << 19) |
75 | #define AT91_MCI_TRTYP_MULTIPLE (1 << 19) | 75 | #define AT91_MCI_TRTYP_MULTIPLE (1 << 19) |
76 | #define AT91_MCI_TRTYP_STREAM (2 << 19) | 76 | #define AT91_MCI_TRTYP_STREAM (2 << 19) |
77 | #define AT91_MCI_TRTYP_SDIO_BYTE (4 << 19) | ||
78 | #define AT91_MCI_TRTYP_SDIO_BLOCK (5 << 19) | ||
77 | 79 | ||
78 | #define AT91_MCI_BLKR 0x18 /* Block Register */ | 80 | #define AT91_MCI_BLKR 0x18 /* Block Register */ |
79 | #define AT91_MCI_BLKR_BCNT(n) ((0xffff & (n)) << 0) /* Block count */ | 81 | #define AT91_MCI_BLKR_BCNT(n) ((0xffff & (n)) << 0) /* Block count */ |
diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h new file mode 100644 index 00000000000..6120f9c46d5 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/stamp9g20.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __MACH_STAMP9G20_H | ||
2 | #define __MACH_STAMP9G20_H | ||
3 | |||
4 | void stamp9g20_map_io(void); | ||
5 | void stamp9g20_board_init(void); | ||
6 | |||
7 | #endif | ||
diff --git a/arch/arm/mach-bcmring/clock.c b/arch/arm/mach-bcmring/clock.c index 14bafc38f2d..ad237a42d26 100644 --- a/arch/arm/mach-bcmring/clock.c +++ b/arch/arm/mach-bcmring/clock.c | |||
@@ -21,13 +21,12 @@ | |||
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/clkdev.h> | ||
24 | #include <mach/csp/hw_cfg.h> | 25 | #include <mach/csp/hw_cfg.h> |
25 | #include <mach/csp/chipcHw_def.h> | 26 | #include <mach/csp/chipcHw_def.h> |
26 | #include <mach/csp/chipcHw_reg.h> | 27 | #include <mach/csp/chipcHw_reg.h> |
27 | #include <mach/csp/chipcHw_inline.h> | 28 | #include <mach/csp/chipcHw_inline.h> |
28 | 29 | ||
29 | #include <asm/clkdev.h> | ||
30 | |||
31 | #include "clock.h" | 30 | #include "clock.h" |
32 | 31 | ||
33 | #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) | 32 | #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) |
diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c index d3f959e92b2..8fc2035759f 100644 --- a/arch/arm/mach-bcmring/core.c +++ b/arch/arm/mach-bcmring/core.c | |||
@@ -30,10 +30,10 @@ | |||
30 | #include <linux/amba/bus.h> | 30 | #include <linux/amba/bus.h> |
31 | #include <linux/clocksource.h> | 31 | #include <linux/clocksource.h> |
32 | #include <linux/clockchips.h> | 32 | #include <linux/clockchips.h> |
33 | #include <linux/clkdev.h> | ||
33 | 34 | ||
34 | #include <mach/csp/mm_addr.h> | 35 | #include <mach/csp/mm_addr.h> |
35 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
36 | #include <asm/clkdev.h> | ||
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <asm/irq.h> | 38 | #include <asm/irq.h> |
39 | #include <asm/hardware/arm_timer.h> | 39 | #include <asm/hardware/arm_timer.h> |
@@ -294,7 +294,6 @@ static struct clocksource clocksource_bcmring_timer1 = { | |||
294 | .rating = 200, | 294 | .rating = 200, |
295 | .read = bcmring_get_cycles_timer1, | 295 | .read = bcmring_get_cycles_timer1, |
296 | .mask = CLOCKSOURCE_MASK(32), | 296 | .mask = CLOCKSOURCE_MASK(32), |
297 | .shift = 20, | ||
298 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 297 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
299 | }; | 298 | }; |
300 | 299 | ||
@@ -303,7 +302,6 @@ static struct clocksource clocksource_bcmring_timer3 = { | |||
303 | .rating = 100, | 302 | .rating = 100, |
304 | .read = bcmring_get_cycles_timer3, | 303 | .read = bcmring_get_cycles_timer3, |
305 | .mask = CLOCKSOURCE_MASK(32), | 304 | .mask = CLOCKSOURCE_MASK(32), |
306 | .shift = 20, | ||
307 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 305 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
308 | }; | 306 | }; |
309 | 307 | ||
@@ -316,10 +314,8 @@ static int __init bcmring_clocksource_init(void) | |||
316 | writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, | 314 | writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, |
317 | TIMER1_VA_BASE + TIMER_CTRL); | 315 | TIMER1_VA_BASE + TIMER_CTRL); |
318 | 316 | ||
319 | clocksource_bcmring_timer1.mult = | 317 | clocksource_register_khz(&clocksource_bcmring_timer1, |
320 | clocksource_khz2mult(TIMER1_FREQUENCY_MHZ * 1000, | 318 | TIMER1_FREQUENCY_MHZ * 1000); |
321 | clocksource_bcmring_timer1.shift); | ||
322 | clocksource_register(&clocksource_bcmring_timer1); | ||
323 | 319 | ||
324 | /* setup timer3 as free-running clocksource */ | 320 | /* setup timer3 as free-running clocksource */ |
325 | writel(0, TIMER3_VA_BASE + TIMER_CTRL); | 321 | writel(0, TIMER3_VA_BASE + TIMER_CTRL); |
@@ -328,10 +324,8 @@ static int __init bcmring_clocksource_init(void) | |||
328 | writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, | 324 | writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, |
329 | TIMER3_VA_BASE + TIMER_CTRL); | 325 | TIMER3_VA_BASE + TIMER_CTRL); |
330 | 326 | ||
331 | clocksource_bcmring_timer3.mult = | 327 | clocksource_register_khz(&clocksource_bcmring_timer3, |
332 | clocksource_khz2mult(TIMER3_FREQUENCY_KHZ, | 328 | TIMER3_FREQUENCY_KHZ); |
333 | clocksource_bcmring_timer3.shift); | ||
334 | clocksource_register(&clocksource_bcmring_timer3); | ||
335 | 329 | ||
336 | return 0; | 330 | return 0; |
337 | } | 331 | } |
diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig index 9ebfcc46feb..29b13f249aa 100644 --- a/arch/arm/mach-cns3xxx/Kconfig +++ b/arch/arm/mach-cns3xxx/Kconfig | |||
@@ -3,6 +3,7 @@ menu "CNS3XXX platform type" | |||
3 | 3 | ||
4 | config MACH_CNS3420VB | 4 | config MACH_CNS3420VB |
5 | bool "Support for CNS3420 Validation Board" | 5 | bool "Support for CNS3420 Validation Board" |
6 | select MIGHT_HAVE_PCI | ||
6 | help | 7 | help |
7 | Include support for the Cavium Networks CNS3420 MPCore Platform | 8 | Include support for the Cavium Networks CNS3420 MPCore Platform |
8 | Baseboard. | 9 | Baseboard. |
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 9ca4d581016..da30078a80c 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c | |||
@@ -69,13 +69,10 @@ void __init cns3xxx_map_io(void) | |||
69 | } | 69 | } |
70 | 70 | ||
71 | /* used by entry-macro.S */ | 71 | /* used by entry-macro.S */ |
72 | void __iomem *gic_cpu_base_addr; | ||
73 | |||
74 | void __init cns3xxx_init_irq(void) | 72 | void __init cns3xxx_init_irq(void) |
75 | { | 73 | { |
76 | gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT); | 74 | gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), |
77 | gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29); | 75 | __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT)); |
78 | gic_cpu_init(0, gic_cpu_base_addr); | ||
79 | } | 76 | } |
80 | 77 | ||
81 | void cns3xxx_power_off(void) | 78 | void cns3xxx_power_off(void) |
diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h index 73898a7835d..ffeb3a8b73b 100644 --- a/arch/arm/mach-cns3xxx/core.h +++ b/arch/arm/mach-cns3xxx/core.h | |||
@@ -11,7 +11,6 @@ | |||
11 | #ifndef __CNS3XXX_CORE_H | 11 | #ifndef __CNS3XXX_CORE_H |
12 | #define __CNS3XXX_CORE_H | 12 | #define __CNS3XXX_CORE_H |
13 | 13 | ||
14 | extern void __iomem *gic_cpu_base_addr; | ||
15 | extern struct sys_timer cns3xxx_timer; | 14 | extern struct sys_timer cns3xxx_timer; |
16 | 15 | ||
17 | void __init cns3xxx_map_io(void); | 16 | void __init cns3xxx_map_io(void); |
diff --git a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S index 5e1c5545680..6bd83ed90af 100644 --- a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S +++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S | |||
@@ -9,74 +9,10 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <mach/hardware.h> | 11 | #include <mach/hardware.h> |
12 | #include <asm/hardware/gic.h> | 12 | #include <asm/hardware/entry-macro-gic.S> |
13 | 13 | ||
14 | .macro disable_fiq | 14 | .macro disable_fiq |
15 | .endm | 15 | .endm |
16 | 16 | ||
17 | .macro get_irqnr_preamble, base, tmp | ||
18 | ldr \base, =gic_cpu_base_addr | ||
19 | ldr \base, [\base] | ||
20 | .endm | ||
21 | |||
22 | .macro arch_ret_to_user, tmp1, tmp2 | 17 | .macro arch_ret_to_user, tmp1, tmp2 |
23 | .endm | 18 | .endm |
24 | |||
25 | /* | ||
26 | * The interrupt numbering scheme is defined in the | ||
27 | * interrupt controller spec. To wit: | ||
28 | * | ||
29 | * Interrupts 0-15 are IPI | ||
30 | * 16-28 are reserved | ||
31 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
32 | * 32-1020 are global | ||
33 | * 1021-1022 are reserved | ||
34 | * 1023 is "spurious" (no interrupt) | ||
35 | * | ||
36 | * For now, we ignore all local interrupts so only return an interrupt if it's | ||
37 | * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. | ||
38 | * | ||
39 | * A simple read from the controller will tell us the number of the highest | ||
40 | * priority enabled interrupt. We then just need to check whether it is in the | ||
41 | * valid range for an IRQ (30-1020 inclusive). | ||
42 | */ | ||
43 | |||
44 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
45 | |||
46 | ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ | ||
47 | |||
48 | ldr \tmp, =1021 | ||
49 | |||
50 | bic \irqnr, \irqstat, #0x1c00 | ||
51 | |||
52 | cmp \irqnr, #29 | ||
53 | cmpcc \irqnr, \irqnr | ||
54 | cmpne \irqnr, \tmp | ||
55 | cmpcs \irqnr, \irqnr | ||
56 | |||
57 | .endm | ||
58 | |||
59 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
60 | * register) is preserved from the macro above. | ||
61 | * If there is an IPI, we immediately signal end of interrupt on the | ||
62 | * controller, since this requires the original irqstat value which | ||
63 | * we won't easily be able to recreate later. | ||
64 | */ | ||
65 | |||
66 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
67 | bic \irqnr, \irqstat, #0x1c00 | ||
68 | cmp \irqnr, #16 | ||
69 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
70 | cmpcs \irqnr, \irqnr | ||
71 | .endm | ||
72 | |||
73 | /* As above, this assumes that irqstat and base are preserved.. */ | ||
74 | |||
75 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
76 | bic \irqnr, \irqstat, #0x1c00 | ||
77 | mov \tmp, #0 | ||
78 | cmp \irqnr, #29 | ||
79 | moveq \tmp, #1 | ||
80 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
81 | cmp \tmp, #0 | ||
82 | .endm | ||
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 11099980b58..0dd22031ec6 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h | |||
@@ -68,7 +68,7 @@ | |||
68 | #ifndef __ASSEMBLER__ | 68 | #ifndef __ASSEMBLER__ |
69 | 69 | ||
70 | #include <linux/list.h> | 70 | #include <linux/list.h> |
71 | #include <asm/clkdev.h> | 71 | #include <linux/clkdev.h> |
72 | 72 | ||
73 | #define PLLSTAT_GOSTAT BIT(0) | 73 | #define PLLSTAT_GOSTAT BIT(0) |
74 | #define PLLCMD_GOSET BIT(0) | 74 | #define PLLCMD_GOSET BIT(0) |
diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h index 62b0a90309a..d1b954955c1 100644 --- a/arch/arm/mach-davinci/include/mach/io.h +++ b/arch/arm/mach-davinci/include/mach/io.h | |||
@@ -22,8 +22,8 @@ | |||
22 | #define __mem_isa(a) (a) | 22 | #define __mem_isa(a) (a) |
23 | 23 | ||
24 | #ifndef __ASSEMBLER__ | 24 | #ifndef __ASSEMBLER__ |
25 | #define __arch_ioremap(p, s, t) davinci_ioremap(p, s, t) | 25 | #define __arch_ioremap davinci_ioremap |
26 | #define __arch_iounmap(v) davinci_iounmap(v) | 26 | #define __arch_iounmap davinci_iounmap |
27 | 27 | ||
28 | void __iomem *davinci_ioremap(unsigned long phys, size_t size, | 28 | void __iomem *davinci_ioremap(unsigned long phys, size_t size, |
29 | unsigned int type); | 29 | unsigned int type); |
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 5d1eea02663..e1969ce904d 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c | |||
@@ -286,7 +286,6 @@ static struct clocksource clocksource_davinci = { | |||
286 | .rating = 300, | 286 | .rating = 300, |
287 | .read = read_dummy, | 287 | .read = read_dummy, |
288 | .mask = CLOCKSOURCE_MASK(32), | 288 | .mask = CLOCKSOURCE_MASK(32), |
289 | .shift = 24, | ||
290 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 289 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
291 | }; | 290 | }; |
292 | 291 | ||
@@ -400,10 +399,8 @@ static void __init davinci_timer_init(void) | |||
400 | /* setup clocksource */ | 399 | /* setup clocksource */ |
401 | clocksource_davinci.read = read_cycles; | 400 | clocksource_davinci.read = read_cycles; |
402 | clocksource_davinci.name = id_to_name[clocksource_id]; | 401 | clocksource_davinci.name = id_to_name[clocksource_id]; |
403 | clocksource_davinci.mult = | 402 | if (clocksource_register_hz(&clocksource_davinci, |
404 | clocksource_khz2mult(davinci_clock_tick_rate/1000, | 403 | davinci_clock_tick_rate)) |
405 | clocksource_davinci.shift); | ||
406 | if (clocksource_register(&clocksource_davinci)) | ||
407 | printk(err, clocksource_davinci.name); | 404 | printk(err, clocksource_davinci.name); |
408 | 405 | ||
409 | /* setup clockevent */ | 406 | /* setup clockevent */ |
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index ef06c66a6f1..ca4de710509 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c | |||
@@ -19,10 +19,10 @@ | |||
19 | #include <linux/string.h> | 19 | #include <linux/string.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include <linux/clkdev.h> | ||
22 | 23 | ||
23 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
24 | 25 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <asm/div64.h> | 26 | #include <asm/div64.h> |
27 | 27 | ||
28 | 28 | ||
diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c index daca30b2d5b..3938a563b28 100644 --- a/arch/arm/mach-imx/clock-imx1.c +++ b/arch/arm/mach-imx/clock-imx1.c | |||
@@ -22,8 +22,7 @@ | |||
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | 25 | #include <linux/clkdev.h> | |
26 | #include <asm/clkdev.h> | ||
27 | 26 | ||
28 | #include <mach/clock.h> | 27 | #include <mach/clock.h> |
29 | #include <mach/hardware.h> | 28 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-imx/clock-imx21.c b/arch/arm/mach-imx/clock-imx21.c index c63a4f5ffcb..bf30a8c7ce6 100644 --- a/arch/arm/mach-imx/clock-imx21.c +++ b/arch/arm/mach-imx/clock-imx21.c | |||
@@ -21,11 +21,11 @@ | |||
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/clkdev.h> | ||
24 | 25 | ||
25 | #include <mach/clock.h> | 26 | #include <mach/clock.h> |
26 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
27 | #include <mach/common.h> | 28 | #include <mach/common.h> |
28 | #include <asm/clkdev.h> | ||
29 | #include <asm/div64.h> | 29 | #include <asm/div64.h> |
30 | 30 | ||
31 | #define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off))) | 31 | #define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off))) |
diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c index 21ef34c501e..daa0165b677 100644 --- a/arch/arm/mach-imx/clock-imx25.c +++ b/arch/arm/mach-imx/clock-imx25.c | |||
@@ -21,8 +21,7 @@ | |||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | #include <linux/clkdev.h> | |
25 | #include <asm/clkdev.h> | ||
26 | 25 | ||
27 | #include <mach/clock.h> | 26 | #include <mach/clock.h> |
28 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c index f32f3b8e8ba..583f2515c1d 100644 --- a/arch/arm/mach-imx/clock-imx27.c +++ b/arch/arm/mach-imx/clock-imx27.c | |||
@@ -21,8 +21,8 @@ | |||
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/clkdev.h> | ||
24 | 25 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <asm/div64.h> | 26 | #include <asm/div64.h> |
27 | 27 | ||
28 | #include <mach/clock.h> | 28 | #include <mach/clock.h> |
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig index 27db275b367..769b0f10c83 100644 --- a/arch/arm/mach-integrator/Kconfig +++ b/arch/arm/mach-integrator/Kconfig | |||
@@ -4,6 +4,7 @@ menu "Integrator Options" | |||
4 | 4 | ||
5 | config ARCH_INTEGRATOR_AP | 5 | config ARCH_INTEGRATOR_AP |
6 | bool "Support Integrator/AP and Integrator/PP2 platforms" | 6 | bool "Support Integrator/AP and Integrator/PP2 platforms" |
7 | select MIGHT_HAVE_PCI | ||
7 | help | 8 | help |
8 | Include support for the ARM(R) Integrator/AP and | 9 | Include support for the ARM(R) Integrator/AP and |
9 | Integrator/PP2 platforms. | 10 | Integrator/PP2 platforms. |
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 8f4fb6d638f..b8e884b450d 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c | |||
@@ -21,9 +21,8 @@ | |||
21 | #include <linux/amba/bus.h> | 21 | #include <linux/amba/bus.h> |
22 | #include <linux/amba/serial.h> | 22 | #include <linux/amba/serial.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/clkdev.h> | ||
24 | 25 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <mach/clkdev.h> | ||
27 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
28 | #include <mach/platform.h> | 27 | #include <mach/platform.h> |
29 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index fd684bf205e..5db574f8ae3 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c | |||
@@ -22,9 +22,8 @@ | |||
22 | #include <linux/amba/clcd.h> | 22 | #include <linux/amba/clcd.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/clkdev.h> | ||
25 | 26 | ||
26 | #include <asm/clkdev.h> | ||
27 | #include <mach/clkdev.h> | ||
28 | #include <asm/hardware/icst.h> | 27 | #include <asm/hardware/icst.h> |
29 | #include <mach/lm.h> | 28 | #include <mach/lm.h> |
30 | #include <mach/impd1.h> | 29 | #include <mach/impd1.h> |
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 548208f1117..2774df8021d 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c | |||
@@ -372,7 +372,6 @@ static struct clocksource clocksource_timersp = { | |||
372 | .rating = 200, | 372 | .rating = 200, |
373 | .read = timersp_read, | 373 | .read = timersp_read, |
374 | .mask = CLOCKSOURCE_MASK(16), | 374 | .mask = CLOCKSOURCE_MASK(16), |
375 | .shift = 16, | ||
376 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 375 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
377 | }; | 376 | }; |
378 | 377 | ||
@@ -390,8 +389,7 @@ static void integrator_clocksource_init(u32 khz) | |||
390 | writel(ctrl, base + TIMER_CTRL); | 389 | writel(ctrl, base + TIMER_CTRL); |
391 | writel(0xffff, base + TIMER_LOAD); | 390 | writel(0xffff, base + TIMER_LOAD); |
392 | 391 | ||
393 | cs->mult = clocksource_khz2mult(khz, cs->shift); | 392 | clocksource_register_khz(cs, khz); |
394 | clocksource_register(cs); | ||
395 | } | 393 | } |
396 | 394 | ||
397 | static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; | 395 | static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; |
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 6258c90d020..85e48a5f77b 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c | |||
@@ -21,9 +21,8 @@ | |||
21 | #include <linux/amba/mmci.h> | 21 | #include <linux/amba/mmci.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/gfp.h> | 23 | #include <linux/gfp.h> |
24 | #include <linux/clkdev.h> | ||
24 | 25 | ||
25 | #include <asm/clkdev.h> | ||
26 | #include <mach/clkdev.h> | ||
27 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
28 | #include <mach/platform.h> | 27 | #include <mach/platform.h> |
29 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
@@ -41,7 +40,7 @@ | |||
41 | #include <asm/mach/map.h> | 40 | #include <asm/mach/map.h> |
42 | #include <asm/mach/time.h> | 41 | #include <asm/mach/time.h> |
43 | 42 | ||
44 | #include <plat/timer-sp.h> | 43 | #include <asm/hardware/timer-sp.h> |
45 | 44 | ||
46 | #include "common.h" | 45 | #include "common.h" |
47 | 46 | ||
diff --git a/arch/arm/mach-iop13xx/include/mach/io.h b/arch/arm/mach-iop13xx/include/mach/io.h index a6e0f9e6ddc..dffb234bb96 100644 --- a/arch/arm/mach-iop13xx/include/mach/io.h +++ b/arch/arm/mach-iop13xx/include/mach/io.h | |||
@@ -35,7 +35,7 @@ extern u32 iop13xx_atux_mem_base; | |||
35 | extern size_t iop13xx_atue_mem_size; | 35 | extern size_t iop13xx_atue_mem_size; |
36 | extern size_t iop13xx_atux_mem_size; | 36 | extern size_t iop13xx_atux_mem_size; |
37 | 37 | ||
38 | #define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f) | 38 | #define __arch_ioremap __iop13xx_ioremap |
39 | #define __arch_iounmap(a) __iop13xx_iounmap(a) | 39 | #define __arch_iounmap __iop13xx_iounmap |
40 | 40 | ||
41 | #endif | 41 | #endif |
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h index 7415e433865..3ad45531886 100644 --- a/arch/arm/mach-iop13xx/include/mach/memory.h +++ b/arch/arm/mach-iop13xx/include/mach/memory.h | |||
@@ -58,13 +58,13 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x) | |||
58 | __dma; \ | 58 | __dma; \ |
59 | }) | 59 | }) |
60 | 60 | ||
61 | #define __arch_page_to_dma(dev, page) \ | 61 | #define __arch_pfn_to_dma(dev, pfn) \ |
62 | ({ \ | 62 | ({ \ |
63 | /* __is_lbus_virt() can never be true for RAM pages */ \ | 63 | /* __is_lbus_virt() can never be true for RAM pages */ \ |
64 | (dma_addr_t)page_to_phys(page); \ | 64 | (dma_addr_t)__pfn_to_phys(pfn); \ |
65 | }) | 65 | }) |
66 | 66 | ||
67 | #define __arch_dma_to_page(dev, addr) phys_to_page(addr) | 67 | #define __arch_dma_to_pfn(dev, addr) __phys_to_pfn(addr) |
68 | 68 | ||
69 | #endif /* CONFIG_ARCH_IOP13XX */ | 69 | #endif /* CONFIG_ARCH_IOP13XX */ |
70 | #endif /* !ASSEMBLY */ | 70 | #endif /* !ASSEMBLY */ |
diff --git a/arch/arm/mach-iop32x/include/mach/io.h b/arch/arm/mach-iop32x/include/mach/io.h index 339e5854728..059c783ce0b 100644 --- a/arch/arm/mach-iop32x/include/mach/io.h +++ b/arch/arm/mach-iop32x/include/mach/io.h | |||
@@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr); | |||
21 | #define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p)) | 21 | #define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p)) |
22 | #define __mem_pci(a) (a) | 22 | #define __mem_pci(a) (a) |
23 | 23 | ||
24 | #define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f) | 24 | #define __arch_ioremap __iop3xx_ioremap |
25 | #define __arch_iounmap(a) __iop3xx_iounmap(a) | 25 | #define __arch_iounmap __iop3xx_iounmap |
26 | 26 | ||
27 | #endif | 27 | #endif |
diff --git a/arch/arm/mach-iop33x/include/mach/io.h b/arch/arm/mach-iop33x/include/mach/io.h index e99a7ed6d05..39e893e97c2 100644 --- a/arch/arm/mach-iop33x/include/mach/io.h +++ b/arch/arm/mach-iop33x/include/mach/io.h | |||
@@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr); | |||
21 | #define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p)) | 21 | #define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p)) |
22 | #define __mem_pci(a) (a) | 22 | #define __mem_pci(a) (a) |
23 | 23 | ||
24 | #define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f) | 24 | #define __arch_ioremap __iop3xx_ioremap |
25 | #define __arch_iounmap(a) __iop3xx_iounmap(a) | 25 | #define __arch_iounmap __iop3xx_iounmap |
26 | 26 | ||
27 | #endif | 27 | #endif |
diff --git a/arch/arm/mach-ixp23xx/include/mach/io.h b/arch/arm/mach-ixp23xx/include/mach/io.h index fd9ef8e519f..a1749d0fd89 100644 --- a/arch/arm/mach-ixp23xx/include/mach/io.h +++ b/arch/arm/mach-ixp23xx/include/mach/io.h | |||
@@ -45,8 +45,8 @@ ixp23xx_iounmap(void __iomem *addr) | |||
45 | __iounmap(addr); | 45 | __iounmap(addr); |
46 | } | 46 | } |
47 | 47 | ||
48 | #define __arch_ioremap(a,s,f) ixp23xx_ioremap(a,s,f) | 48 | #define __arch_ioremap ixp23xx_ioremap |
49 | #define __arch_iounmap(a) ixp23xx_iounmap(a) | 49 | #define __arch_iounmap ixp23xx_iounmap |
50 | 50 | ||
51 | 51 | ||
52 | #endif | 52 | #endif |
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index 24498a932ba..a54b3db8036 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c | |||
@@ -513,4 +513,4 @@ int dma_set_coherent_mask(struct device *dev, u64 mask) | |||
513 | 513 | ||
514 | EXPORT_SYMBOL(ixp4xx_pci_read); | 514 | EXPORT_SYMBOL(ixp4xx_pci_read); |
515 | EXPORT_SYMBOL(ixp4xx_pci_write); | 515 | EXPORT_SYMBOL(ixp4xx_pci_write); |
516 | 516 | EXPORT_SYMBOL(dma_set_coherent_mask); | |
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 0bce09799d1..4dbfcbb9163 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
36 | #include <asm/page.h> | 36 | #include <asm/page.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <asm/sched_clock.h> | ||
38 | 39 | ||
39 | #include <asm/mach/map.h> | 40 | #include <asm/mach/map.h> |
40 | #include <asm/mach/irq.h> | 41 | #include <asm/mach/irq.h> |
@@ -399,6 +400,23 @@ void __init ixp4xx_sys_init(void) | |||
399 | } | 400 | } |
400 | 401 | ||
401 | /* | 402 | /* |
403 | * sched_clock() | ||
404 | */ | ||
405 | static DEFINE_CLOCK_DATA(cd); | ||
406 | |||
407 | unsigned long long notrace sched_clock(void) | ||
408 | { | ||
409 | u32 cyc = *IXP4XX_OSTS; | ||
410 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
411 | } | ||
412 | |||
413 | static void notrace ixp4xx_update_sched_clock(void) | ||
414 | { | ||
415 | u32 cyc = *IXP4XX_OSTS; | ||
416 | update_sched_clock(&cd, cyc, (u32)~0); | ||
417 | } | ||
418 | |||
419 | /* | ||
402 | * clocksource | 420 | * clocksource |
403 | */ | 421 | */ |
404 | static cycle_t ixp4xx_get_cycles(struct clocksource *cs) | 422 | static cycle_t ixp4xx_get_cycles(struct clocksource *cs) |
@@ -411,7 +429,6 @@ static struct clocksource clocksource_ixp4xx = { | |||
411 | .rating = 200, | 429 | .rating = 200, |
412 | .read = ixp4xx_get_cycles, | 430 | .read = ixp4xx_get_cycles, |
413 | .mask = CLOCKSOURCE_MASK(32), | 431 | .mask = CLOCKSOURCE_MASK(32), |
414 | .shift = 20, | ||
415 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 432 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
416 | }; | 433 | }; |
417 | 434 | ||
@@ -419,21 +436,9 @@ unsigned long ixp4xx_timer_freq = FREQ; | |||
419 | EXPORT_SYMBOL(ixp4xx_timer_freq); | 436 | EXPORT_SYMBOL(ixp4xx_timer_freq); |
420 | static void __init ixp4xx_clocksource_init(void) | 437 | static void __init ixp4xx_clocksource_init(void) |
421 | { | 438 | { |
422 | clocksource_ixp4xx.mult = | 439 | init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq); |
423 | clocksource_hz2mult(ixp4xx_timer_freq, | ||
424 | clocksource_ixp4xx.shift); | ||
425 | clocksource_register(&clocksource_ixp4xx); | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * sched_clock() | ||
430 | */ | ||
431 | unsigned long long sched_clock(void) | ||
432 | { | ||
433 | cycle_t cyc = ixp4xx_get_cycles(NULL); | ||
434 | struct clocksource *cs = &clocksource_ixp4xx; | ||
435 | 440 | ||
436 | return clocksource_cyc2ns(cyc, cs->mult, cs->shift); | 441 | clocksource_register_hz(&clocksource_ixp4xx, ixp4xx_timer_freq); |
437 | } | 442 | } |
438 | 443 | ||
439 | /* | 444 | /* |
diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h index de274a1f19d..57b5410c31f 100644 --- a/arch/arm/mach-ixp4xx/include/mach/io.h +++ b/arch/arm/mach-ixp4xx/include/mach/io.h | |||
@@ -74,8 +74,8 @@ static inline void __indirect_iounmap(void __iomem *addr) | |||
74 | __iounmap(addr); | 74 | __iounmap(addr); |
75 | } | 75 | } |
76 | 76 | ||
77 | #define __arch_ioremap(a, s, f) __indirect_ioremap(a, s, f) | 77 | #define __arch_ioremap __indirect_ioremap |
78 | #define __arch_iounmap(a) __indirect_iounmap(a) | 78 | #define __arch_iounmap __indirect_iounmap |
79 | 79 | ||
80 | #define writeb(v, p) __indirect_writeb(v, p) | 80 | #define writeb(v, p) __indirect_writeb(v, p) |
81 | #define writew(v, p) __indirect_writew(v, p) | 81 | #define writew(v, p) __indirect_writew(v, p) |
diff --git a/arch/arm/mach-kirkwood/include/mach/io.h b/arch/arm/mach-kirkwood/include/mach/io.h index 44e8be04f25..1aaddc364f2 100644 --- a/arch/arm/mach-kirkwood/include/mach/io.h +++ b/arch/arm/mach-kirkwood/include/mach/io.h | |||
@@ -42,8 +42,8 @@ __arch_iounmap(void __iomem *addr) | |||
42 | __iounmap(addr); | 42 | __iounmap(addr); |
43 | } | 43 | } |
44 | 44 | ||
45 | #define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m) | 45 | #define __arch_ioremap __arch_ioremap |
46 | #define __arch_iounmap(a) __arch_iounmap(a) | 46 | #define __arch_iounmap __arch_iounmap |
47 | #define __io(a) __io(a) | 47 | #define __io(a) __io(a) |
48 | #define __mem_pci(a) (a) | 48 | #define __mem_pci(a) (a) |
49 | 49 | ||
diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig index fe0c82e30b2..f5c39a8c2b0 100644 --- a/arch/arm/mach-ks8695/Kconfig +++ b/arch/arm/mach-ks8695/Kconfig | |||
@@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations" | |||
4 | 4 | ||
5 | config MACH_KS8695 | 5 | config MACH_KS8695 |
6 | bool "KS8695 development board" | 6 | bool "KS8695 development board" |
7 | select MIGHT_HAVE_PCI | ||
7 | help | 8 | help |
8 | Say 'Y' here if you want your kernel to run on the original | 9 | Say 'Y' here if you want your kernel to run on the original |
9 | Kendin-Micrel KS8695 development board. | 10 | Kendin-Micrel KS8695 development board. |
diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h index ffa19aae6e0..bace9a681ad 100644 --- a/arch/arm/mach-ks8695/include/mach/memory.h +++ b/arch/arm/mach-ks8695/include/mach/memory.h | |||
@@ -35,17 +35,17 @@ extern struct bus_type platform_bus_type; | |||
35 | __phys_to_virt(x) : __bus_to_virt(x)); }) | 35 | __phys_to_virt(x) : __bus_to_virt(x)); }) |
36 | #define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \ | 36 | #define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \ |
37 | (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); }) | 37 | (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); }) |
38 | #define __arch_page_to_dma(dev, x) \ | 38 | #define __arch_pfn_to_dma(dev, pfn) \ |
39 | ({ dma_addr_t __dma = page_to_phys(page); \ | 39 | ({ dma_addr_t __dma = __pfn_to_phys(pfn); \ |
40 | if (!is_lbus_device(dev)) \ | 40 | if (!is_lbus_device(dev)) \ |
41 | __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \ | 41 | __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \ |
42 | __dma; }) | 42 | __dma; }) |
43 | 43 | ||
44 | #define __arch_dma_to_page(dev, x) \ | 44 | #define __arch_dma_to_pfn(dev, x) \ |
45 | ({ dma_addr_t __dma = x; \ | 45 | ({ dma_addr_t __dma = x; \ |
46 | if (!is_lbus_device(dev)) \ | 46 | if (!is_lbus_device(dev)) \ |
47 | __dma += PHYS_OFFSET - KS8695_PCIMEM_PA; \ | 47 | __dma += PHYS_OFFSET - KS8695_PCIMEM_PA; \ |
48 | phys_to_page(__dma); \ | 48 | __phys_to_pfn(__dma); \ |
49 | }) | 49 | }) |
50 | 50 | ||
51 | #endif | 51 | #endif |
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 32d63796430..da0e6498110 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c | |||
@@ -90,10 +90,9 @@ | |||
90 | #include <linux/clk.h> | 90 | #include <linux/clk.h> |
91 | #include <linux/amba/bus.h> | 91 | #include <linux/amba/bus.h> |
92 | #include <linux/amba/clcd.h> | 92 | #include <linux/amba/clcd.h> |
93 | #include <linux/clkdev.h> | ||
93 | 94 | ||
94 | #include <mach/hardware.h> | 95 | #include <mach/hardware.h> |
95 | #include <asm/clkdev.h> | ||
96 | #include <mach/clkdev.h> | ||
97 | #include <mach/platform.h> | 96 | #include <mach/platform.h> |
98 | #include "clock.h" | 97 | #include "clock.h" |
99 | #include "common.h" | 98 | #include "common.h" |
diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c index 630dd4a74b2..6162ac308c2 100644 --- a/arch/arm/mach-lpc32xx/timer.c +++ b/arch/arm/mach-lpc32xx/timer.c | |||
@@ -38,7 +38,6 @@ static cycle_t lpc32xx_clksrc_read(struct clocksource *cs) | |||
38 | 38 | ||
39 | static struct clocksource lpc32xx_clksrc = { | 39 | static struct clocksource lpc32xx_clksrc = { |
40 | .name = "lpc32xx_clksrc", | 40 | .name = "lpc32xx_clksrc", |
41 | .shift = 24, | ||
42 | .rating = 300, | 41 | .rating = 300, |
43 | .read = lpc32xx_clksrc_read, | 42 | .read = lpc32xx_clksrc_read, |
44 | .mask = CLOCKSOURCE_MASK(32), | 43 | .mask = CLOCKSOURCE_MASK(32), |
@@ -171,9 +170,7 @@ static void __init lpc32xx_timer_init(void) | |||
171 | __raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE)); | 170 | __raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE)); |
172 | __raw_writel(LCP32XX_TIMER_CNTR_TCR_EN, | 171 | __raw_writel(LCP32XX_TIMER_CNTR_TCR_EN, |
173 | LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE)); | 172 | LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE)); |
174 | lpc32xx_clksrc.mult = clocksource_hz2mult(clkrate, | 173 | clocksource_register_hz(&lpc32xx_clksrc, clkrate); |
175 | lpc32xx_clksrc.shift); | ||
176 | clocksource_register(&lpc32xx_clksrc); | ||
177 | } | 174 | } |
178 | 175 | ||
179 | struct sys_timer lpc32xx_timer = { | 176 | struct sys_timer lpc32xx_timer = { |
diff --git a/arch/arm/mach-mmp/clock.h b/arch/arm/mach-mmp/clock.h index 016ae94691c..9b027d7491f 100644 --- a/arch/arm/mach-mmp/clock.h +++ b/arch/arm/mach-mmp/clock.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <asm/clkdev.h> | 9 | #include <linux/clkdev.h> |
10 | 10 | ||
11 | struct clkops { | 11 | struct clkops { |
12 | void (*enable)(struct clk *); | 12 | void (*enable)(struct clk *); |
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 66528193f93..aeb9ae23e6c 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c | |||
@@ -26,8 +26,8 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/irq.h> | 27 | #include <linux/irq.h> |
28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
29 | #include <linux/cnt32_to_63.h> | ||
30 | 29 | ||
30 | #include <asm/sched_clock.h> | ||
31 | #include <mach/addr-map.h> | 31 | #include <mach/addr-map.h> |
32 | #include <mach/regs-timers.h> | 32 | #include <mach/regs-timers.h> |
33 | #include <mach/regs-apbc.h> | 33 | #include <mach/regs-apbc.h> |
@@ -42,23 +42,7 @@ | |||
42 | #define MAX_DELTA (0xfffffffe) | 42 | #define MAX_DELTA (0xfffffffe) |
43 | #define MIN_DELTA (16) | 43 | #define MIN_DELTA (16) |
44 | 44 | ||
45 | #define TCR2NS_SCALE_FACTOR 10 | 45 | static DEFINE_CLOCK_DATA(cd); |
46 | |||
47 | static unsigned long tcr2ns_scale; | ||
48 | |||
49 | static void __init set_tcr2ns_scale(unsigned long tcr_rate) | ||
50 | { | ||
51 | unsigned long long v = 1000000000ULL << TCR2NS_SCALE_FACTOR; | ||
52 | do_div(v, tcr_rate); | ||
53 | tcr2ns_scale = v; | ||
54 | /* | ||
55 | * We want an even value to automatically clear the top bit | ||
56 | * returned by cnt32_to_63() without an additional run time | ||
57 | * instruction. So if the LSB is 1 then round it up. | ||
58 | */ | ||
59 | if (tcr2ns_scale & 1) | ||
60 | tcr2ns_scale++; | ||
61 | } | ||
62 | 46 | ||
63 | /* | 47 | /* |
64 | * FIXME: the timer needs some delay to stablize the counter capture | 48 | * FIXME: the timer needs some delay to stablize the counter capture |
@@ -75,10 +59,16 @@ static inline uint32_t timer_read(void) | |||
75 | return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(0)); | 59 | return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(0)); |
76 | } | 60 | } |
77 | 61 | ||
78 | unsigned long long sched_clock(void) | 62 | unsigned long long notrace sched_clock(void) |
79 | { | 63 | { |
80 | unsigned long long v = cnt32_to_63(timer_read()); | 64 | u32 cyc = timer_read(); |
81 | return (v * tcr2ns_scale) >> TCR2NS_SCALE_FACTOR; | 65 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
66 | } | ||
67 | |||
68 | static void notrace mmp_update_sched_clock(void) | ||
69 | { | ||
70 | u32 cyc = timer_read(); | ||
71 | update_sched_clock(&cd, cyc, (u32)~0); | ||
82 | } | 72 | } |
83 | 73 | ||
84 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 74 | static irqreturn_t timer_interrupt(int irq, void *dev_id) |
@@ -146,7 +136,6 @@ static cycle_t clksrc_read(struct clocksource *cs) | |||
146 | 136 | ||
147 | static struct clocksource cksrc = { | 137 | static struct clocksource cksrc = { |
148 | .name = "clocksource", | 138 | .name = "clocksource", |
149 | .shift = 20, | ||
150 | .rating = 200, | 139 | .rating = 200, |
151 | .read = clksrc_read, | 140 | .read = clksrc_read, |
152 | .mask = CLOCKSOURCE_MASK(32), | 141 | .mask = CLOCKSOURCE_MASK(32), |
@@ -186,17 +175,15 @@ void __init timer_init(int irq) | |||
186 | { | 175 | { |
187 | timer_config(); | 176 | timer_config(); |
188 | 177 | ||
189 | set_tcr2ns_scale(CLOCK_TICK_RATE); | 178 | init_sched_clock(&cd, mmp_update_sched_clock, 32, CLOCK_TICK_RATE); |
190 | 179 | ||
191 | ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); | 180 | ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); |
192 | ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); | 181 | ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); |
193 | ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt); | 182 | ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt); |
194 | ckevt.cpumask = cpumask_of(0); | 183 | ckevt.cpumask = cpumask_of(0); |
195 | 184 | ||
196 | cksrc.mult = clocksource_hz2mult(CLOCK_TICK_RATE, cksrc.shift); | ||
197 | |||
198 | setup_irq(irq, &timer_irq); | 185 | setup_irq(irq, &timer_irq); |
199 | 186 | ||
200 | clocksource_register(&cksrc); | 187 | clocksource_register_hz(&cksrc, CLOCK_TICK_RATE); |
201 | clockevents_register_device(&ckevt); | 188 | clockevents_register_device(&ckevt); |
202 | } | 189 | } |
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c index 7486a681cc7..9b5eb2b4ae1 100644 --- a/arch/arm/mach-msm/board-msm8x60.c +++ b/arch/arm/mach-msm/board-msm8x60.c | |||
@@ -28,8 +28,6 @@ | |||
28 | #include <mach/board.h> | 28 | #include <mach/board.h> |
29 | #include <mach/msm_iomap.h> | 29 | #include <mach/msm_iomap.h> |
30 | 30 | ||
31 | void __iomem *gic_cpu_base_addr; | ||
32 | |||
33 | unsigned long clk_get_max_axi_khz(void) | 31 | unsigned long clk_get_max_axi_khz(void) |
34 | { | 32 | { |
35 | return 0; | 33 | return 0; |
@@ -44,9 +42,8 @@ static void __init msm8x60_init_irq(void) | |||
44 | { | 42 | { |
45 | unsigned int i; | 43 | unsigned int i; |
46 | 44 | ||
47 | gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START); | 45 | gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, |
48 | gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE; | 46 | (void *)MSM_QGIC_CPU_BASE); |
49 | gic_cpu_init(0, MSM_QGIC_CPU_BASE); | ||
50 | 47 | ||
51 | /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */ | 48 | /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */ |
52 | writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4); | 49 | writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4); |
diff --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h index 3ff7bf5e679..a95f7b9efe3 100644 --- a/arch/arm/mach-msm/include/mach/smp.h +++ b/arch/arm/mach-msm/include/mach/smp.h | |||
@@ -31,9 +31,9 @@ | |||
31 | 31 | ||
32 | #include <asm/hardware/gic.h> | 32 | #include <asm/hardware/gic.h> |
33 | 33 | ||
34 | static inline void smp_cross_call(const struct cpumask *mask) | 34 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
35 | { | 35 | { |
36 | gic_raise_softirq(mask, 1); | 36 | gic_raise_softirq(mask, ipi); |
37 | } | 37 | } |
38 | 38 | ||
39 | #endif | 39 | #endif |
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 950100f19d0..595be7fea31 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c | |||
@@ -137,7 +137,6 @@ static struct msm_clock msm_clocks[] = { | |||
137 | .rating = 200, | 137 | .rating = 200, |
138 | .read = msm_gpt_read, | 138 | .read = msm_gpt_read, |
139 | .mask = CLOCKSOURCE_MASK(32), | 139 | .mask = CLOCKSOURCE_MASK(32), |
140 | .shift = 17, | ||
141 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 140 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
142 | }, | 141 | }, |
143 | .irq = { | 142 | .irq = { |
@@ -164,7 +163,6 @@ static struct msm_clock msm_clocks[] = { | |||
164 | .rating = 300, | 163 | .rating = 300, |
165 | .read = msm_dgt_read, | 164 | .read = msm_dgt_read, |
166 | .mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)), | 165 | .mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)), |
167 | .shift = 24 - MSM_DGT_SHIFT, | ||
168 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 166 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
169 | }, | 167 | }, |
170 | .irq = { | 168 | .irq = { |
@@ -205,8 +203,7 @@ static void __init msm_timer_init(void) | |||
205 | ce->min_delta_ns = clockevent_delta2ns(4, ce); | 203 | ce->min_delta_ns = clockevent_delta2ns(4, ce); |
206 | ce->cpumask = cpumask_of(0); | 204 | ce->cpumask = cpumask_of(0); |
207 | 205 | ||
208 | cs->mult = clocksource_hz2mult(clock->freq, cs->shift); | 206 | res = clocksource_register_hz(cs, clock->freq); |
209 | res = clocksource_register(cs); | ||
210 | if (res) | 207 | if (res) |
211 | printk(KERN_ERR "msm_timer_init: clocksource_register " | 208 | printk(KERN_ERR "msm_timer_init: clocksource_register " |
212 | "failed for %s\n", cs->name); | 209 | "failed for %s\n", cs->name); |
diff --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c index 4193cf5a263..d423cac8cab 100644 --- a/arch/arm/mach-mx3/clock-imx31.c +++ b/arch/arm/mach-mx3/clock-imx31.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/clkdev.h> | ||
26 | 27 | ||
27 | #include <asm/clkdev.h> | ||
28 | #include <asm/div64.h> | 28 | #include <asm/div64.h> |
29 | 29 | ||
30 | #include <mach/clock.h> | 30 | #include <mach/clock.h> |
diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 22259d95583..448a038cd1e 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c | |||
@@ -21,8 +21,7 @@ | |||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | #include <linux/clkdev.h> | |
25 | #include <asm/clkdev.h> | ||
26 | 25 | ||
27 | #include <mach/clock.h> | 26 | #include <mach/clock.h> |
28 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c index b21bc47d482..785e1a33618 100644 --- a/arch/arm/mach-mx5/clock-mx51-mx53.c +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c | |||
@@ -14,8 +14,8 @@ | |||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/clkdev.h> | ||
17 | 18 | ||
18 | #include <asm/clkdev.h> | ||
19 | #include <asm/div64.h> | 19 | #include <asm/div64.h> |
20 | 20 | ||
21 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-mxc91231/clock.c b/arch/arm/mach-mxc91231/clock.c index 5c85075d8a5..9fab505f1eb 100644 --- a/arch/arm/mach-mxc91231/clock.c +++ b/arch/arm/mach-mxc91231/clock.c | |||
@@ -2,12 +2,12 @@ | |||
2 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
4 | #include <linux/io.h> | 4 | #include <linux/io.h> |
5 | #include <linux/clkdev.h> | ||
5 | 6 | ||
6 | #include <mach/clock.h> | 7 | #include <mach/clock.h> |
7 | #include <mach/hardware.h> | 8 | #include <mach/hardware.h> |
8 | #include <mach/common.h> | 9 | #include <mach/common.h> |
9 | 10 | ||
10 | #include <asm/clkdev.h> | ||
11 | #include <asm/bug.h> | 11 | #include <asm/bug.h> |
12 | #include <asm/div64.h> | 12 | #include <asm/div64.h> |
13 | 13 | ||
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index 82801dbf057..f12f22d09b6 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c | |||
@@ -114,7 +114,6 @@ static struct clocksource clocksource_netx = { | |||
114 | .rating = 200, | 114 | .rating = 200, |
115 | .read = netx_get_cycles, | 115 | .read = netx_get_cycles, |
116 | .mask = CLOCKSOURCE_MASK(32), | 116 | .mask = CLOCKSOURCE_MASK(32), |
117 | .shift = 20, | ||
118 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 117 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
119 | }; | 118 | }; |
120 | 119 | ||
@@ -151,9 +150,7 @@ static void __init netx_timer_init(void) | |||
151 | writel(NETX_GPIO_COUNTER_CTRL_RUN, | 150 | writel(NETX_GPIO_COUNTER_CTRL_RUN, |
152 | NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); | 151 | NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); |
153 | 152 | ||
154 | clocksource_netx.mult = | 153 | clocksource_register_hz(&clocksource_netx, CLOCK_TICK_RATE); |
155 | clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_netx.shift); | ||
156 | clocksource_register(&clocksource_netx); | ||
157 | 154 | ||
158 | netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, | 155 | netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, |
159 | netx_clockevent.shift); | 156 | netx_clockevent.shift); |
diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c index 89f793adf77..48a59f24e10 100644 --- a/arch/arm/mach-nomadik/clock.c +++ b/arch/arm/mach-nomadik/clock.c | |||
@@ -7,7 +7,7 @@ | |||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
9 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
10 | #include <asm/clkdev.h> | 10 | #include <linux/clkdev.h> |
11 | #include "clock.h" | 11 | #include "clock.h" |
12 | 12 | ||
13 | /* | 13 | /* |
diff --git a/arch/arm/mach-ns9xxx/time-ns9360.c b/arch/arm/mach-ns9xxx/time-ns9360.c index 77281260358..9ca32f55728 100644 --- a/arch/arm/mach-ns9xxx/time-ns9360.c +++ b/arch/arm/mach-ns9xxx/time-ns9360.c | |||
@@ -35,7 +35,6 @@ static struct clocksource ns9360_clocksource = { | |||
35 | .rating = 300, | 35 | .rating = 300, |
36 | .read = ns9360_clocksource_read, | 36 | .read = ns9360_clocksource_read, |
37 | .mask = CLOCKSOURCE_MASK(32), | 37 | .mask = CLOCKSOURCE_MASK(32), |
38 | .shift = 20, | ||
39 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 38 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
40 | }; | 39 | }; |
41 | 40 | ||
@@ -148,10 +147,7 @@ static void __init ns9360_timer_init(void) | |||
148 | 147 | ||
149 | __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE)); | 148 | __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE)); |
150 | 149 | ||
151 | ns9360_clocksource.mult = clocksource_hz2mult(ns9360_cpuclock(), | 150 | clocksource_register_hz(&ns9360_clocksource, ns9360_cpuclock()); |
152 | ns9360_clocksource.shift); | ||
153 | |||
154 | clocksource_register(&ns9360_clocksource); | ||
155 | 151 | ||
156 | latch = SH_DIV(ns9360_cpuclock(), HZ, 0); | 152 | latch = SH_DIV(ns9360_cpuclock(), HZ, 0); |
157 | 153 | ||
diff --git a/arch/arm/mach-nuc93x/clock.h b/arch/arm/mach-nuc93x/clock.h index 18e51be4816..4de1f1da9dc 100644 --- a/arch/arm/mach-nuc93x/clock.h +++ b/arch/arm/mach-nuc93x/clock.h | |||
@@ -10,7 +10,7 @@ | |||
10 | * the Free Software Foundation; either version 2 of the License. | 10 | * the Free Software Foundation; either version 2 of the License. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <asm/clkdev.h> | 13 | #include <linux/clkdev.h> |
14 | 14 | ||
15 | void nuc93x_clk_enable(struct clk *clk, int enable); | 15 | void nuc93x_clk_enable(struct clk *clk, int enable); |
16 | void clks_register(struct clk_lookup *clks, size_t num); | 16 | void clks_register(struct clk_lookup *clks, size_t num); |
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index b8c7fb9d792..84ef70476b5 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c | |||
@@ -17,9 +17,9 @@ | |||
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/clkdev.h> | ||
20 | 21 | ||
21 | #include <asm/mach-types.h> | 22 | #include <asm/mach-types.h> |
22 | #include <asm/clkdev.h> | ||
23 | 23 | ||
24 | #include <plat/cpu.h> | 24 | #include <plat/cpu.h> |
25 | #include <plat/usb.h> | 25 | #include <plat/usb.h> |
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 1be6a214d88..abb34ff2041 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c | |||
@@ -208,7 +208,6 @@ static struct clocksource clocksource_mpu = { | |||
208 | .rating = 300, | 208 | .rating = 300, |
209 | .read = mpu_read, | 209 | .read = mpu_read, |
210 | .mask = CLOCKSOURCE_MASK(32), | 210 | .mask = CLOCKSOURCE_MASK(32), |
211 | .shift = 24, | ||
212 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 211 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
213 | }; | 212 | }; |
214 | 213 | ||
@@ -217,13 +216,10 @@ static void __init omap_init_clocksource(unsigned long rate) | |||
217 | static char err[] __initdata = KERN_ERR | 216 | static char err[] __initdata = KERN_ERR |
218 | "%s: can't register clocksource!\n"; | 217 | "%s: can't register clocksource!\n"; |
219 | 218 | ||
220 | clocksource_mpu.mult | ||
221 | = clocksource_khz2mult(rate/1000, clocksource_mpu.shift); | ||
222 | |||
223 | setup_irq(INT_TIMER2, &omap_mpu_timer2_irq); | 219 | setup_irq(INT_TIMER2, &omap_mpu_timer2_irq); |
224 | omap_mpu_timer_start(1, ~0, 1); | 220 | omap_mpu_timer_start(1, ~0, 1); |
225 | 221 | ||
226 | if (clocksource_register(&clocksource_mpu)) | 222 | if (clocksource_register_hz(&clocksource_mpu, rate)) |
227 | printk(err, clocksource_mpu.name); | 223 | printk(err, clocksource_mpu.name); |
228 | } | 224 | } |
229 | 225 | ||
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index ed8d330522f..ebb888f5936 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c | |||
@@ -26,10 +26,10 @@ | |||
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include <linux/clkdev.h> | ||
29 | 30 | ||
30 | #include <plat/cpu.h> | 31 | #include <plat/cpu.h> |
31 | #include <plat/clock.h> | 32 | #include <plat/clock.h> |
32 | #include <asm/clkdev.h> | ||
33 | 33 | ||
34 | #include "clock.h" | 34 | #include "clock.h" |
35 | #include "prm.h" | 35 | #include "prm.h" |
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S index 06e64e1fc28..d54c4f89a8b 100644 --- a/arch/arm/mach-omap2/include/mach/entry-macro.S +++ b/arch/arm/mach-omap2/include/mach/entry-macro.S | |||
@@ -105,6 +105,35 @@ omap_irq_base: .word 0 | |||
105 | 9999: | 105 | 9999: |
106 | .endm | 106 | .endm |
107 | 107 | ||
108 | #ifdef CONFIG_SMP | ||
109 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
110 | * register) is preserved from the macro above. | ||
111 | * If there is an IPI, we immediately signal end of interrupt | ||
112 | * on the controller, since this requires the original irqstat | ||
113 | * value which we won't easily be able to recreate later. | ||
114 | */ | ||
115 | |||
116 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
117 | bic \irqnr, \irqstat, #0x1c00 | ||
118 | cmp \irqnr, #16 | ||
119 | it cc | ||
120 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
121 | it cs | ||
122 | cmpcs \irqnr, \irqnr | ||
123 | .endm | ||
124 | |||
125 | /* As above, this assumes that irqstat and base are preserved */ | ||
126 | |||
127 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
128 | bic \irqnr, \irqstat, #0x1c00 | ||
129 | mov \tmp, #0 | ||
130 | cmp \irqnr, #29 | ||
131 | itt eq | ||
132 | moveq \tmp, #1 | ||
133 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
134 | cmp \tmp, #0 | ||
135 | .endm | ||
136 | #endif /* CONFIG_SMP */ | ||
108 | 137 | ||
109 | #else /* MULTI_OMAP2 */ | 138 | #else /* MULTI_OMAP2 */ |
110 | 139 | ||
@@ -141,74 +170,16 @@ omap_irq_base: .word 0 | |||
141 | 170 | ||
142 | 171 | ||
143 | #ifdef CONFIG_ARCH_OMAP4 | 172 | #ifdef CONFIG_ARCH_OMAP4 |
173 | #define HAVE_GET_IRQNR_PREAMBLE | ||
174 | #include <asm/hardware/entry-macro-gic.S> | ||
144 | 175 | ||
145 | .macro get_irqnr_preamble, base, tmp | 176 | .macro get_irqnr_preamble, base, tmp |
146 | ldr \base, =OMAP4_IRQ_BASE | 177 | ldr \base, =OMAP4_IRQ_BASE |
147 | .endm | 178 | .endm |
148 | 179 | ||
149 | /* | ||
150 | * The interrupt numbering scheme is defined in the | ||
151 | * interrupt controller spec. To wit: | ||
152 | * | ||
153 | * Interrupts 0-15 are IPI | ||
154 | * 16-28 are reserved | ||
155 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
156 | * 32-1020 are global | ||
157 | * 1021-1022 are reserved | ||
158 | * 1023 is "spurious" (no interrupt) | ||
159 | * | ||
160 | * For now, we ignore all local interrupts so only return an | ||
161 | * interrupt if it's between 30 and 1020. The test_for_ipi | ||
162 | * routine below will pick up on IPIs. | ||
163 | * A simple read from the controller will tell us the number | ||
164 | * of the highest priority enabled interrupt. | ||
165 | * We then just need to check whether it is in the | ||
166 | * valid range for an IRQ (30-1020 inclusive). | ||
167 | */ | ||
168 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
169 | ldr \irqstat, [\base, #GIC_CPU_INTACK] | ||
170 | |||
171 | ldr \tmp, =1021 | ||
172 | |||
173 | bic \irqnr, \irqstat, #0x1c00 | ||
174 | |||
175 | cmp \irqnr, #29 | ||
176 | cmpcc \irqnr, \irqnr | ||
177 | cmpne \irqnr, \tmp | ||
178 | cmpcs \irqnr, \irqnr | ||
179 | .endm | ||
180 | #endif | 180 | #endif |
181 | #endif /* MULTI_OMAP2 */ | ||
182 | |||
183 | #ifdef CONFIG_SMP | ||
184 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
185 | * register) is preserved from the macro above. | ||
186 | * If there is an IPI, we immediately signal end of interrupt | ||
187 | * on the controller, since this requires the original irqstat | ||
188 | * value which we won't easily be able to recreate later. | ||
189 | */ | ||
190 | 181 | ||
191 | .macro test_for_ipi, irqnr, irqstat, base, tmp | 182 | #endif /* MULTI_OMAP2 */ |
192 | bic \irqnr, \irqstat, #0x1c00 | ||
193 | cmp \irqnr, #16 | ||
194 | it cc | ||
195 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
196 | it cs | ||
197 | cmpcs \irqnr, \irqnr | ||
198 | .endm | ||
199 | |||
200 | /* As above, this assumes that irqstat and base are preserved */ | ||
201 | |||
202 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
203 | bic \irqnr, \irqstat, #0x1c00 | ||
204 | mov \tmp, #0 | ||
205 | cmp \irqnr, #29 | ||
206 | itt eq | ||
207 | moveq \tmp, #1 | ||
208 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
209 | cmp \tmp, #0 | ||
210 | .endm | ||
211 | #endif /* CONFIG_SMP */ | ||
212 | 183 | ||
213 | .macro irq_prio_table | 184 | .macro irq_prio_table |
214 | .endm | 185 | .endm |
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h index 2744dfee1ff..5b0270b2893 100644 --- a/arch/arm/mach-omap2/include/mach/omap4-common.h +++ b/arch/arm/mach-omap2/include/mach/omap4-common.h | |||
@@ -24,7 +24,6 @@ | |||
24 | extern void __iomem *l2cache_base; | 24 | extern void __iomem *l2cache_base; |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | extern void __iomem *gic_cpu_base_addr; | ||
28 | extern void __iomem *gic_dist_base_addr; | 27 | extern void __iomem *gic_dist_base_addr; |
29 | 28 | ||
30 | extern void __init gic_init_irq(void); | 29 | extern void __init gic_init_irq(void); |
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c index 6cee456ca54..4976b9393e4 100644 --- a/arch/arm/mach-omap2/omap-hotplug.c +++ b/arch/arm/mach-omap2/omap-hotplug.c | |||
@@ -17,16 +17,13 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <linux/completion.h> | ||
21 | 20 | ||
22 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
23 | #include <mach/omap4-common.h> | 22 | #include <mach/omap4-common.h> |
24 | 23 | ||
25 | static DECLARE_COMPLETION(cpu_killed); | ||
26 | |||
27 | int platform_cpu_kill(unsigned int cpu) | 24 | int platform_cpu_kill(unsigned int cpu) |
28 | { | 25 | { |
29 | return wait_for_completion_timeout(&cpu_killed, 5000); | 26 | return 1; |
30 | } | 27 | } |
31 | 28 | ||
32 | /* | 29 | /* |
@@ -35,15 +32,6 @@ int platform_cpu_kill(unsigned int cpu) | |||
35 | */ | 32 | */ |
36 | void platform_cpu_die(unsigned int cpu) | 33 | void platform_cpu_die(unsigned int cpu) |
37 | { | 34 | { |
38 | unsigned int this_cpu = hard_smp_processor_id(); | ||
39 | |||
40 | if (cpu != this_cpu) { | ||
41 | pr_crit("platform_cpu_die running on %u, should be %u\n", | ||
42 | this_cpu, cpu); | ||
43 | BUG(); | ||
44 | } | ||
45 | pr_notice("CPU%u: shutdown\n", cpu); | ||
46 | complete(&cpu_killed); | ||
47 | flush_cache_all(); | 35 | flush_cache_all(); |
48 | dsb(); | 36 | dsb(); |
49 | 37 | ||
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 9e9f70e18e3..b66cfe8bc46 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | 22 | ||
23 | #include <asm/cacheflush.h> | 23 | #include <asm/cacheflush.h> |
24 | #include <asm/localtimer.h> | ||
25 | #include <asm/smp_scu.h> | 24 | #include <asm/smp_scu.h> |
26 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
27 | #include <mach/omap4-common.h> | 26 | #include <mach/omap4-common.h> |
@@ -29,28 +28,16 @@ | |||
29 | /* SCU base address */ | 28 | /* SCU base address */ |
30 | static void __iomem *scu_base; | 29 | static void __iomem *scu_base; |
31 | 30 | ||
32 | /* | ||
33 | * Use SCU config register to count number of cores | ||
34 | */ | ||
35 | static inline unsigned int get_core_count(void) | ||
36 | { | ||
37 | if (scu_base) | ||
38 | return scu_get_core_count(scu_base); | ||
39 | return 1; | ||
40 | } | ||
41 | |||
42 | static DEFINE_SPINLOCK(boot_lock); | 31 | static DEFINE_SPINLOCK(boot_lock); |
43 | 32 | ||
44 | void __cpuinit platform_secondary_init(unsigned int cpu) | 33 | void __cpuinit platform_secondary_init(unsigned int cpu) |
45 | { | 34 | { |
46 | trace_hardirqs_off(); | ||
47 | |||
48 | /* | 35 | /* |
49 | * If any interrupts are already enabled for the primary | 36 | * If any interrupts are already enabled for the primary |
50 | * core (e.g. timer irq), then they will not have been enabled | 37 | * core (e.g. timer irq), then they will not have been enabled |
51 | * for us: do so | 38 | * for us: do so |
52 | */ | 39 | */ |
53 | gic_cpu_init(0, gic_cpu_base_addr); | 40 | gic_secondary_init(0); |
54 | 41 | ||
55 | /* | 42 | /* |
56 | * Synchronise with the boot thread. | 43 | * Synchronise with the boot thread. |
@@ -76,7 +63,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
76 | omap_modify_auxcoreboot0(0x200, 0xfffffdff); | 63 | omap_modify_auxcoreboot0(0x200, 0xfffffdff); |
77 | flush_cache_all(); | 64 | flush_cache_all(); |
78 | smp_wmb(); | 65 | smp_wmb(); |
79 | smp_cross_call(cpumask_of(cpu)); | 66 | smp_cross_call(cpumask_of(cpu), 1); |
80 | 67 | ||
81 | /* | 68 | /* |
82 | * Now the secondary core is starting up let it run its | 69 | * Now the secondary core is starting up let it run its |
@@ -118,25 +105,9 @@ void __init smp_init_cpus(void) | |||
118 | scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256); | 105 | scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256); |
119 | BUG_ON(!scu_base); | 106 | BUG_ON(!scu_base); |
120 | 107 | ||
121 | ncores = get_core_count(); | 108 | ncores = scu_get_core_count(scu_base); |
122 | |||
123 | for (i = 0; i < ncores; i++) | ||
124 | set_cpu_possible(i, true); | ||
125 | } | ||
126 | |||
127 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
128 | { | ||
129 | unsigned int ncores = get_core_count(); | ||
130 | unsigned int cpu = smp_processor_id(); | ||
131 | int i; | ||
132 | 109 | ||
133 | /* sanity check */ | 110 | /* sanity check */ |
134 | if (ncores == 0) { | ||
135 | printk(KERN_ERR | ||
136 | "OMAP4: strange core count of 0? Default to 1\n"); | ||
137 | ncores = 1; | ||
138 | } | ||
139 | |||
140 | if (ncores > NR_CPUS) { | 111 | if (ncores > NR_CPUS) { |
141 | printk(KERN_WARNING | 112 | printk(KERN_WARNING |
142 | "OMAP4: no. of cores (%d) greater than configured " | 113 | "OMAP4: no. of cores (%d) greater than configured " |
@@ -144,13 +115,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
144 | ncores, NR_CPUS); | 115 | ncores, NR_CPUS); |
145 | ncores = NR_CPUS; | 116 | ncores = NR_CPUS; |
146 | } | 117 | } |
147 | smp_store_cpu_info(cpu); | ||
148 | 118 | ||
149 | /* | 119 | for (i = 0; i < ncores; i++) |
150 | * are we trying to boot more cores than exist? | 120 | set_cpu_possible(i, true); |
151 | */ | 121 | } |
152 | if (max_cpus > ncores) | 122 | |
153 | max_cpus = ncores; | 123 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
124 | { | ||
125 | int i; | ||
154 | 126 | ||
155 | /* | 127 | /* |
156 | * Initialise the present map, which describes the set of CPUs | 128 | * Initialise the present map, which describes the set of CPUs |
@@ -159,18 +131,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
159 | for (i = 0; i < max_cpus; i++) | 131 | for (i = 0; i < max_cpus; i++) |
160 | set_cpu_present(i, true); | 132 | set_cpu_present(i, true); |
161 | 133 | ||
162 | if (max_cpus > 1) { | 134 | /* |
163 | /* | 135 | * Initialise the SCU and wake up the secondary core using |
164 | * Enable the local timer or broadcast device for the | 136 | * wakeup_secondary(). |
165 | * boot CPU, but only if we have more than one CPU. | 137 | */ |
166 | */ | 138 | scu_enable(scu_base); |
167 | percpu_timer_setup(); | 139 | wakeup_secondary(); |
168 | |||
169 | /* | ||
170 | * Initialise the SCU and wake up the secondary core using | ||
171 | * wakeup_secondary(). | ||
172 | */ | ||
173 | scu_enable(scu_base); | ||
174 | wakeup_secondary(); | ||
175 | } | ||
176 | } | 140 | } |
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 2f895553e6a..666e852988d 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c | |||
@@ -26,21 +26,22 @@ | |||
26 | void __iomem *l2cache_base; | 26 | void __iomem *l2cache_base; |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | void __iomem *gic_cpu_base_addr; | ||
30 | void __iomem *gic_dist_base_addr; | 29 | void __iomem *gic_dist_base_addr; |
31 | 30 | ||
32 | 31 | ||
33 | void __init gic_init_irq(void) | 32 | void __init gic_init_irq(void) |
34 | { | 33 | { |
34 | void __iomem *gic_cpu_base; | ||
35 | |||
35 | /* Static mapping, never released */ | 36 | /* Static mapping, never released */ |
36 | gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K); | 37 | gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K); |
37 | BUG_ON(!gic_dist_base_addr); | 38 | BUG_ON(!gic_dist_base_addr); |
38 | gic_dist_init(0, gic_dist_base_addr, 29); | ||
39 | 39 | ||
40 | /* Static mapping, never released */ | 40 | /* Static mapping, never released */ |
41 | gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512); | 41 | gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512); |
42 | BUG_ON(!gic_cpu_base_addr); | 42 | BUG_ON(!gic_cpu_base); |
43 | gic_cpu_init(0, gic_cpu_base_addr); | 43 | |
44 | gic_init(0, 29, gic_dist_base_addr, gic_cpu_base); | ||
44 | } | 45 | } |
45 | 46 | ||
46 | #ifdef CONFIG_CACHE_L2X0 | 47 | #ifdef CONFIG_CACHE_L2X0 |
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index e13c29eecf2..a7816dbdc6b 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c | |||
@@ -195,7 +195,6 @@ static struct clocksource clocksource_gpt = { | |||
195 | .rating = 300, | 195 | .rating = 300, |
196 | .read = clocksource_read_cycles, | 196 | .read = clocksource_read_cycles, |
197 | .mask = CLOCKSOURCE_MASK(32), | 197 | .mask = CLOCKSOURCE_MASK(32), |
198 | .shift = 24, | ||
199 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 198 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
200 | }; | 199 | }; |
201 | 200 | ||
@@ -220,9 +219,7 @@ static void __init omap2_gp_clocksource_init(void) | |||
220 | 219 | ||
221 | omap_dm_timer_set_load_start(gpt, 1, 0); | 220 | omap_dm_timer_set_load_start(gpt, 1, 0); |
222 | 221 | ||
223 | clocksource_gpt.mult = | 222 | if (clocksource_register_hz(&clocksource_gpt, tick_rate)) |
224 | clocksource_khz2mult(tick_rate/1000, clocksource_gpt.shift); | ||
225 | if (clocksource_register(&clocksource_gpt)) | ||
226 | printk(err2, clocksource_gpt.name); | 223 | printk(err2, clocksource_gpt.name); |
227 | } | 224 | } |
228 | #endif | 225 | #endif |
diff --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h index c47b033bd99..c5196101a23 100644 --- a/arch/arm/mach-orion5x/include/mach/io.h +++ b/arch/arm/mach-orion5x/include/mach/io.h | |||
@@ -38,8 +38,8 @@ __arch_iounmap(void __iomem *addr) | |||
38 | __iounmap(addr); | 38 | __iounmap(addr); |
39 | } | 39 | } |
40 | 40 | ||
41 | #define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m) | 41 | #define __arch_ioremap __arch_ioremap |
42 | #define __arch_iounmap(a) __arch_iounmap(a) | 42 | #define __arch_iounmap __arch_iounmap |
43 | #define __io(a) __typesafe_io(a) | 43 | #define __io(a) __typesafe_io(a) |
44 | #define __mem_pci(a) (a) | 44 | #define __mem_pci(a) (a) |
45 | 45 | ||
diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c index 9d1975fa4d9..a4a3819c96c 100644 --- a/arch/arm/mach-pnx4008/clock.c +++ b/arch/arm/mach-pnx4008/clock.c | |||
@@ -21,8 +21,7 @@ | |||
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | #include <linux/clkdev.h> | |
25 | #include <asm/clkdev.h> | ||
26 | 25 | ||
27 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
28 | #include <mach/clock.h> | 27 | #include <mach/clock.h> |
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 1df6db6a136..2fc9f94cdd2 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
@@ -98,6 +98,7 @@ config MACH_ARMCORE | |||
98 | select PXA27x | 98 | select PXA27x |
99 | select IWMMXT | 99 | select IWMMXT |
100 | select PXA25x | 100 | select PXA25x |
101 | select MIGHT_HAVE_PCI | ||
101 | 102 | ||
102 | config MACH_EM_X270 | 103 | config MACH_EM_X270 |
103 | bool "CompuLab EM-x270 platform" | 104 | bool "CompuLab EM-x270 platform" |
@@ -544,6 +545,7 @@ config MACH_ICONTROL | |||
544 | config ARCH_PXA_ESERIES | 545 | config ARCH_PXA_ESERIES |
545 | bool "PXA based Toshiba e-series PDAs" | 546 | bool "PXA based Toshiba e-series PDAs" |
546 | select PXA25x | 547 | select PXA25x |
548 | select FB_W100 | ||
547 | 549 | ||
548 | config MACH_E330 | 550 | config MACH_E330 |
549 | bool "Toshiba e330" | 551 | bool "Toshiba e330" |
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index 8184fe2d71c..d5152220ce9 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c | |||
@@ -6,8 +6,7 @@ | |||
6 | #include <linux/clk.h> | 6 | #include <linux/clk.h> |
7 | #include <linux/spinlock.h> | 7 | #include <linux/spinlock.h> |
8 | #include <linux/delay.h> | 8 | #include <linux/delay.h> |
9 | 9 | #include <linux/clkdev.h> | |
10 | #include <asm/clkdev.h> | ||
11 | 10 | ||
12 | #include "clock.h" | 11 | #include "clock.h" |
13 | 12 | ||
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h index 6e949944f2e..f9f349a21b5 100644 --- a/arch/arm/mach-pxa/clock.h +++ b/arch/arm/mach-pxa/clock.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #include <linux/clkdev.h> | ||
1 | #include <linux/sysdev.h> | 2 | #include <linux/sysdev.h> |
2 | #include <asm/clkdev.h> | ||
3 | 3 | ||
4 | struct clkops { | 4 | struct clkops { |
5 | void (*enable)(struct clk *); | 5 | void (*enable)(struct clk *); |
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index 2f5b08aeb52..c551da86baf 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S | |||
@@ -353,8 +353,8 @@ resume_turn_on_mmu: | |||
353 | 353 | ||
354 | @ Let us ensure we jump to resume_after_mmu only when the mcr above | 354 | @ Let us ensure we jump to resume_after_mmu only when the mcr above |
355 | @ actually took effect. They call it the "cpwait" operation. | 355 | @ actually took effect. They call it the "cpwait" operation. |
356 | mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15 | 356 | mrc p15, 0, r0, c2, c0, 0 @ queue a dependency on CP15 |
357 | sub pc, r2, r1, lsr #32 @ jump to virtual addr | 357 | sub pc, r2, r0, lsr #32 @ jump to virtual addr |
358 | nop | 358 | nop |
359 | nop | 359 | nop |
360 | nop | 360 | nop |
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 293e40aeaf2..e7f64d9b4f2 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c | |||
@@ -17,11 +17,11 @@ | |||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/clockchips.h> | 18 | #include <linux/clockchips.h> |
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/cnt32_to_63.h> | ||
21 | 20 | ||
22 | #include <asm/div64.h> | 21 | #include <asm/div64.h> |
23 | #include <asm/mach/irq.h> | 22 | #include <asm/mach/irq.h> |
24 | #include <asm/mach/time.h> | 23 | #include <asm/mach/time.h> |
24 | #include <asm/sched_clock.h> | ||
25 | #include <mach/regs-ost.h> | 25 | #include <mach/regs-ost.h> |
26 | 26 | ||
27 | /* | 27 | /* |
@@ -32,29 +32,18 @@ | |||
32 | * long as there is always less than 582 seconds between successive | 32 | * long as there is always less than 582 seconds between successive |
33 | * calls to sched_clock() which should always be the case in practice. | 33 | * calls to sched_clock() which should always be the case in practice. |
34 | */ | 34 | */ |
35 | static DEFINE_CLOCK_DATA(cd); | ||
35 | 36 | ||
36 | #define OSCR2NS_SCALE_FACTOR 10 | 37 | unsigned long long notrace sched_clock(void) |
37 | |||
38 | static unsigned long oscr2ns_scale; | ||
39 | |||
40 | static void __init set_oscr2ns_scale(unsigned long oscr_rate) | ||
41 | { | 38 | { |
42 | unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR; | 39 | u32 cyc = OSCR; |
43 | do_div(v, oscr_rate); | 40 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
44 | oscr2ns_scale = v; | ||
45 | /* | ||
46 | * We want an even value to automatically clear the top bit | ||
47 | * returned by cnt32_to_63() without an additional run time | ||
48 | * instruction. So if the LSB is 1 then round it up. | ||
49 | */ | ||
50 | if (oscr2ns_scale & 1) | ||
51 | oscr2ns_scale++; | ||
52 | } | 41 | } |
53 | 42 | ||
54 | unsigned long long sched_clock(void) | 43 | static void notrace pxa_update_sched_clock(void) |
55 | { | 44 | { |
56 | unsigned long long v = cnt32_to_63(OSCR); | 45 | u32 cyc = OSCR; |
57 | return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR; | 46 | update_sched_clock(&cd, cyc, (u32)~0); |
58 | } | 47 | } |
59 | 48 | ||
60 | 49 | ||
@@ -127,7 +116,6 @@ static struct clocksource cksrc_pxa_oscr0 = { | |||
127 | .rating = 200, | 116 | .rating = 200, |
128 | .read = pxa_read_oscr, | 117 | .read = pxa_read_oscr, |
129 | .mask = CLOCKSOURCE_MASK(32), | 118 | .mask = CLOCKSOURCE_MASK(32), |
130 | .shift = 20, | ||
131 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 119 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
132 | }; | 120 | }; |
133 | 121 | ||
@@ -145,7 +133,7 @@ static void __init pxa_timer_init(void) | |||
145 | OIER = 0; | 133 | OIER = 0; |
146 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; | 134 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; |
147 | 135 | ||
148 | set_oscr2ns_scale(clock_tick_rate); | 136 | init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate); |
149 | 137 | ||
150 | ckevt_pxa_osmr0.mult = | 138 | ckevt_pxa_osmr0.mult = |
151 | div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); | 139 | div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); |
@@ -155,12 +143,9 @@ static void __init pxa_timer_init(void) | |||
155 | clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1; | 143 | clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1; |
156 | ckevt_pxa_osmr0.cpumask = cpumask_of(0); | 144 | ckevt_pxa_osmr0.cpumask = cpumask_of(0); |
157 | 145 | ||
158 | cksrc_pxa_oscr0.mult = | ||
159 | clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift); | ||
160 | |||
161 | setup_irq(IRQ_OST0, &pxa_ost0_irq); | 146 | setup_irq(IRQ_OST0, &pxa_ost0_irq); |
162 | 147 | ||
163 | clocksource_register(&cksrc_pxa_oscr0); | 148 | clocksource_register_hz(&cksrc_pxa_oscr0, clock_tick_rate); |
164 | clockevents_register_device(&ckevt_pxa_osmr0); | 149 | clockevents_register_device(&ckevt_pxa_osmr0); |
165 | } | 150 | } |
166 | 151 | ||
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 07c08151dfe..1c6602cf50e 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c | |||
@@ -30,8 +30,8 @@ | |||
30 | #include <linux/ata_platform.h> | 30 | #include <linux/ata_platform.h> |
31 | #include <linux/amba/mmci.h> | 31 | #include <linux/amba/mmci.h> |
32 | #include <linux/gfp.h> | 32 | #include <linux/gfp.h> |
33 | #include <linux/clkdev.h> | ||
33 | 34 | ||
34 | #include <asm/clkdev.h> | ||
35 | #include <asm/system.h> | 35 | #include <asm/system.h> |
36 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
@@ -47,15 +47,13 @@ | |||
47 | 47 | ||
48 | #include <asm/hardware/gic.h> | 48 | #include <asm/hardware/gic.h> |
49 | 49 | ||
50 | #include <mach/clkdev.h> | ||
51 | #include <mach/platform.h> | 50 | #include <mach/platform.h> |
52 | #include <mach/irqs.h> | 51 | #include <mach/irqs.h> |
53 | #include <plat/timer-sp.h> | 52 | #include <asm/hardware/timer-sp.h> |
54 | 53 | ||
55 | #include "core.h" | 54 | #include <plat/sched_clock.h> |
56 | 55 | ||
57 | /* used by entry-macro.S and platsmp.c */ | 56 | #include "core.h" |
58 | void __iomem *gic_cpu_base_addr; | ||
59 | 57 | ||
60 | #ifdef CONFIG_ZONE_DMA | 58 | #ifdef CONFIG_ZONE_DMA |
61 | /* | 59 | /* |
@@ -658,6 +656,12 @@ void realview_leds_event(led_event_t ledevt) | |||
658 | #endif /* CONFIG_LEDS */ | 656 | #endif /* CONFIG_LEDS */ |
659 | 657 | ||
660 | /* | 658 | /* |
659 | * The sched_clock counter | ||
660 | */ | ||
661 | #define REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + \ | ||
662 | REALVIEW_SYS_24MHz_OFFSET) | ||
663 | |||
664 | /* | ||
661 | * Where is the timer (VA)? | 665 | * Where is the timer (VA)? |
662 | */ | 666 | */ |
663 | void __iomem *timer0_va_base; | 667 | void __iomem *timer0_va_base; |
@@ -672,6 +676,8 @@ void __init realview_timer_init(unsigned int timer_irq) | |||
672 | { | 676 | { |
673 | u32 val; | 677 | u32 val; |
674 | 678 | ||
679 | versatile_sched_clock_init(REFCOUNTER, 24000000); | ||
680 | |||
675 | /* | 681 | /* |
676 | * set clock frequency: | 682 | * set clock frequency: |
677 | * REALVIEW_REFCLK is 32KHz | 683 | * REALVIEW_REFCLK is 32KHz |
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 781bca68a9f..693239ddc39 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h | |||
@@ -53,7 +53,6 @@ extern struct platform_device realview_i2c_device; | |||
53 | extern struct mmci_platform_data realview_mmc0_plat_data; | 53 | extern struct mmci_platform_data realview_mmc0_plat_data; |
54 | extern struct mmci_platform_data realview_mmc1_plat_data; | 54 | extern struct mmci_platform_data realview_mmc1_plat_data; |
55 | extern struct clcd_board clcd_plat_data; | 55 | extern struct clcd_board clcd_plat_data; |
56 | extern void __iomem *gic_cpu_base_addr; | ||
57 | extern void __iomem *timer0_va_base; | 56 | extern void __iomem *timer0_va_base; |
58 | extern void __iomem *timer1_va_base; | 57 | extern void __iomem *timer1_va_base; |
59 | extern void __iomem *timer2_va_base; | 58 | extern void __iomem *timer2_va_base; |
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c index f95521a5e5c..a87523d095e 100644 --- a/arch/arm/mach-realview/hotplug.c +++ b/arch/arm/mach-realview/hotplug.c | |||
@@ -11,14 +11,11 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/completion.h> | ||
15 | 14 | ||
16 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
17 | 16 | ||
18 | extern volatile int pen_release; | 17 | extern volatile int pen_release; |
19 | 18 | ||
20 | static DECLARE_COMPLETION(cpu_killed); | ||
21 | |||
22 | static inline void cpu_enter_lowpower(void) | 19 | static inline void cpu_enter_lowpower(void) |
23 | { | 20 | { |
24 | unsigned int v; | 21 | unsigned int v; |
@@ -34,10 +31,10 @@ static inline void cpu_enter_lowpower(void) | |||
34 | " bic %0, %0, #0x20\n" | 31 | " bic %0, %0, #0x20\n" |
35 | " mcr p15, 0, %0, c1, c0, 1\n" | 32 | " mcr p15, 0, %0, c1, c0, 1\n" |
36 | " mrc p15, 0, %0, c1, c0, 0\n" | 33 | " mrc p15, 0, %0, c1, c0, 0\n" |
37 | " bic %0, %0, #0x04\n" | 34 | " bic %0, %0, %2\n" |
38 | " mcr p15, 0, %0, c1, c0, 0\n" | 35 | " mcr p15, 0, %0, c1, c0, 0\n" |
39 | : "=&r" (v) | 36 | : "=&r" (v) |
40 | : "r" (0) | 37 | : "r" (0), "Ir" (CR_C) |
41 | : "cc"); | 38 | : "cc"); |
42 | } | 39 | } |
43 | 40 | ||
@@ -46,17 +43,17 @@ static inline void cpu_leave_lowpower(void) | |||
46 | unsigned int v; | 43 | unsigned int v; |
47 | 44 | ||
48 | asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" | 45 | asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" |
49 | " orr %0, %0, #0x04\n" | 46 | " orr %0, %0, %1\n" |
50 | " mcr p15, 0, %0, c1, c0, 0\n" | 47 | " mcr p15, 0, %0, c1, c0, 0\n" |
51 | " mrc p15, 0, %0, c1, c0, 1\n" | 48 | " mrc p15, 0, %0, c1, c0, 1\n" |
52 | " orr %0, %0, #0x20\n" | 49 | " orr %0, %0, #0x20\n" |
53 | " mcr p15, 0, %0, c1, c0, 1\n" | 50 | " mcr p15, 0, %0, c1, c0, 1\n" |
54 | : "=&r" (v) | 51 | : "=&r" (v) |
55 | : | 52 | : "Ir" (CR_C) |
56 | : "cc"); | 53 | : "cc"); |
57 | } | 54 | } |
58 | 55 | ||
59 | static inline void platform_do_lowpower(unsigned int cpu) | 56 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) |
60 | { | 57 | { |
61 | /* | 58 | /* |
62 | * there is no power-control hardware on this platform, so all | 59 | * there is no power-control hardware on this platform, so all |
@@ -80,22 +77,19 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
80 | } | 77 | } |
81 | 78 | ||
82 | /* | 79 | /* |
83 | * getting here, means that we have come out of WFI without | 80 | * Getting here, means that we have come out of WFI without |
84 | * having been woken up - this shouldn't happen | 81 | * having been woken up - this shouldn't happen |
85 | * | 82 | * |
86 | * The trouble is, letting people know about this is not really | 83 | * Just note it happening - when we're woken, we can report |
87 | * possible, since we are currently running incoherently, and | 84 | * its occurrence. |
88 | * therefore cannot safely call printk() or anything else | ||
89 | */ | 85 | */ |
90 | #ifdef DEBUG | 86 | (*spurious)++; |
91 | printk("CPU%u: spurious wakeup call\n", cpu); | ||
92 | #endif | ||
93 | } | 87 | } |
94 | } | 88 | } |
95 | 89 | ||
96 | int platform_cpu_kill(unsigned int cpu) | 90 | int platform_cpu_kill(unsigned int cpu) |
97 | { | 91 | { |
98 | return wait_for_completion_timeout(&cpu_killed, 5000); | 92 | return 1; |
99 | } | 93 | } |
100 | 94 | ||
101 | /* | 95 | /* |
@@ -105,30 +99,22 @@ int platform_cpu_kill(unsigned int cpu) | |||
105 | */ | 99 | */ |
106 | void platform_cpu_die(unsigned int cpu) | 100 | void platform_cpu_die(unsigned int cpu) |
107 | { | 101 | { |
108 | #ifdef DEBUG | 102 | int spurious = 0; |
109 | unsigned int this_cpu = hard_smp_processor_id(); | ||
110 | |||
111 | if (cpu != this_cpu) { | ||
112 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
113 | this_cpu, cpu); | ||
114 | BUG(); | ||
115 | } | ||
116 | #endif | ||
117 | |||
118 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
119 | complete(&cpu_killed); | ||
120 | 103 | ||
121 | /* | 104 | /* |
122 | * we're ready for shutdown now, so do it | 105 | * we're ready for shutdown now, so do it |
123 | */ | 106 | */ |
124 | cpu_enter_lowpower(); | 107 | cpu_enter_lowpower(); |
125 | platform_do_lowpower(cpu); | 108 | platform_do_lowpower(cpu, &spurious); |
126 | 109 | ||
127 | /* | 110 | /* |
128 | * bring this CPU back into the world of cache | 111 | * bring this CPU back into the world of cache |
129 | * coherency, and then restore interrupts | 112 | * coherency, and then restore interrupts |
130 | */ | 113 | */ |
131 | cpu_leave_lowpower(); | 114 | cpu_leave_lowpower(); |
115 | |||
116 | if (spurious) | ||
117 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
132 | } | 118 | } |
133 | 119 | ||
134 | int platform_cpu_disable(unsigned int cpu) | 120 | int platform_cpu_disable(unsigned int cpu) |
diff --git a/arch/arm/mach-realview/include/mach/entry-macro.S b/arch/arm/mach-realview/include/mach/entry-macro.S index 340a5c27694..4071164aeba 100644 --- a/arch/arm/mach-realview/include/mach/entry-macro.S +++ b/arch/arm/mach-realview/include/mach/entry-macro.S | |||
@@ -8,74 +8,11 @@ | |||
8 | * warranty of any kind, whether express or implied. | 8 | * warranty of any kind, whether express or implied. |
9 | */ | 9 | */ |
10 | #include <mach/hardware.h> | 10 | #include <mach/hardware.h> |
11 | #include <asm/hardware/gic.h> | 11 | #include <asm/hardware/entry-macro-gic.S> |
12 | 12 | ||
13 | .macro disable_fiq | 13 | .macro disable_fiq |
14 | .endm | 14 | .endm |
15 | 15 | ||
16 | .macro get_irqnr_preamble, base, tmp | ||
17 | ldr \base, =gic_cpu_base_addr | ||
18 | ldr \base, [\base] | ||
19 | .endm | ||
20 | |||
21 | .macro arch_ret_to_user, tmp1, tmp2 | 16 | .macro arch_ret_to_user, tmp1, tmp2 |
22 | .endm | 17 | .endm |
23 | 18 | ||
24 | /* | ||
25 | * The interrupt numbering scheme is defined in the | ||
26 | * interrupt controller spec. To wit: | ||
27 | * | ||
28 | * Interrupts 0-15 are IPI | ||
29 | * 16-28 are reserved | ||
30 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
31 | * 32-1020 are global | ||
32 | * 1021-1022 are reserved | ||
33 | * 1023 is "spurious" (no interrupt) | ||
34 | * | ||
35 | * For now, we ignore all local interrupts so only return an interrupt if it's | ||
36 | * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. | ||
37 | * | ||
38 | * A simple read from the controller will tell us the number of the highest | ||
39 | * priority enabled interrupt. We then just need to check whether it is in the | ||
40 | * valid range for an IRQ (30-1020 inclusive). | ||
41 | */ | ||
42 | |||
43 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
44 | |||
45 | ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ | ||
46 | |||
47 | ldr \tmp, =1021 | ||
48 | |||
49 | bic \irqnr, \irqstat, #0x1c00 | ||
50 | |||
51 | cmp \irqnr, #29 | ||
52 | cmpcc \irqnr, \irqnr | ||
53 | cmpne \irqnr, \tmp | ||
54 | cmpcs \irqnr, \irqnr | ||
55 | |||
56 | .endm | ||
57 | |||
58 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
59 | * register) is preserved from the macro above. | ||
60 | * If there is an IPI, we immediately signal end of interrupt on the | ||
61 | * controller, since this requires the original irqstat value which | ||
62 | * we won't easily be able to recreate later. | ||
63 | */ | ||
64 | |||
65 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
66 | bic \irqnr, \irqstat, #0x1c00 | ||
67 | cmp \irqnr, #16 | ||
68 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
69 | cmpcs \irqnr, \irqnr | ||
70 | .endm | ||
71 | |||
72 | /* As above, this assumes that irqstat and base are preserved.. */ | ||
73 | |||
74 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
75 | bic \irqnr, \irqstat, #0x1c00 | ||
76 | mov \tmp, #0 | ||
77 | cmp \irqnr, #29 | ||
78 | moveq \tmp, #1 | ||
79 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
80 | cmp \tmp, #0 | ||
81 | .endm | ||
diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h index d3cd265cb05..c8221b38ee7 100644 --- a/arch/arm/mach-realview/include/mach/smp.h +++ b/arch/arm/mach-realview/include/mach/smp.h | |||
@@ -2,14 +2,13 @@ | |||
2 | #define ASMARM_ARCH_SMP_H | 2 | #define ASMARM_ARCH_SMP_H |
3 | 3 | ||
4 | #include <asm/hardware/gic.h> | 4 | #include <asm/hardware/gic.h> |
5 | #include <asm/smp_mpidr.h> | ||
6 | 5 | ||
7 | /* | 6 | /* |
8 | * We use IRQ1 as the IPI | 7 | * We use IRQ1 as the IPI |
9 | */ | 8 | */ |
10 | static inline void smp_cross_call(const struct cpumask *mask) | 9 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
11 | { | 10 | { |
12 | gic_raise_softirq(mask, 1); | 11 | gic_raise_softirq(mask, ipi); |
13 | } | 12 | } |
14 | 13 | ||
15 | #endif | 14 | #endif |
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 009265818d5..a22bf67f2f7 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
20 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
21 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
22 | #include <asm/localtimer.h> | ||
23 | #include <asm/unified.h> | 22 | #include <asm/unified.h> |
24 | 23 | ||
25 | #include <mach/board-eb.h> | 24 | #include <mach/board-eb.h> |
@@ -37,6 +36,19 @@ extern void realview_secondary_startup(void); | |||
37 | */ | 36 | */ |
38 | volatile int __cpuinitdata pen_release = -1; | 37 | volatile int __cpuinitdata pen_release = -1; |
39 | 38 | ||
39 | /* | ||
40 | * Write pen_release in a way that is guaranteed to be visible to all | ||
41 | * observers, irrespective of whether they're taking part in coherency | ||
42 | * or not. This is necessary for the hotplug code to work reliably. | ||
43 | */ | ||
44 | static void write_pen_release(int val) | ||
45 | { | ||
46 | pen_release = val; | ||
47 | smp_wmb(); | ||
48 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
49 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
50 | } | ||
51 | |||
40 | static void __iomem *scu_base_addr(void) | 52 | static void __iomem *scu_base_addr(void) |
41 | { | 53 | { |
42 | if (machine_is_realview_eb_mp()) | 54 | if (machine_is_realview_eb_mp()) |
@@ -50,33 +62,22 @@ static void __iomem *scu_base_addr(void) | |||
50 | return (void __iomem *)0; | 62 | return (void __iomem *)0; |
51 | } | 63 | } |
52 | 64 | ||
53 | static inline unsigned int get_core_count(void) | ||
54 | { | ||
55 | void __iomem *scu_base = scu_base_addr(); | ||
56 | if (scu_base) | ||
57 | return scu_get_core_count(scu_base); | ||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | static DEFINE_SPINLOCK(boot_lock); | 65 | static DEFINE_SPINLOCK(boot_lock); |
62 | 66 | ||
63 | void __cpuinit platform_secondary_init(unsigned int cpu) | 67 | void __cpuinit platform_secondary_init(unsigned int cpu) |
64 | { | 68 | { |
65 | trace_hardirqs_off(); | ||
66 | |||
67 | /* | 69 | /* |
68 | * if any interrupts are already enabled for the primary | 70 | * if any interrupts are already enabled for the primary |
69 | * core (e.g. timer irq), then they will not have been enabled | 71 | * core (e.g. timer irq), then they will not have been enabled |
70 | * for us: do so | 72 | * for us: do so |
71 | */ | 73 | */ |
72 | gic_cpu_init(0, gic_cpu_base_addr); | 74 | gic_secondary_init(0); |
73 | 75 | ||
74 | /* | 76 | /* |
75 | * let the primary processor know we're out of the | 77 | * let the primary processor know we're out of the |
76 | * pen, then head off into the C entry point | 78 | * pen, then head off into the C entry point |
77 | */ | 79 | */ |
78 | pen_release = -1; | 80 | write_pen_release(-1); |
79 | smp_wmb(); | ||
80 | 81 | ||
81 | /* | 82 | /* |
82 | * Synchronise with the boot thread. | 83 | * Synchronise with the boot thread. |
@@ -103,20 +104,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
103 | * Note that "pen_release" is the hardware CPU ID, whereas | 104 | * Note that "pen_release" is the hardware CPU ID, whereas |
104 | * "cpu" is Linux's internal ID. | 105 | * "cpu" is Linux's internal ID. |
105 | */ | 106 | */ |
106 | pen_release = cpu; | 107 | write_pen_release(cpu); |
107 | flush_cache_all(); | ||
108 | 108 | ||
109 | /* | 109 | /* |
110 | * XXX | 110 | * Send the secondary CPU a soft interrupt, thereby causing |
111 | * | 111 | * the boot monitor to read the system wide flags register, |
112 | * This is a later addition to the booting protocol: the | 112 | * and branch to the address found there. |
113 | * bootMonitor now puts secondary cores into WFI, so | ||
114 | * poke_milo() no longer gets the cores moving; we need | ||
115 | * to send a soft interrupt to wake the secondary core. | ||
116 | * Use smp_cross_call() for this, since there's little | ||
117 | * point duplicating the code here | ||
118 | */ | 113 | */ |
119 | smp_cross_call(cpumask_of(cpu)); | 114 | smp_cross_call(cpumask_of(cpu), 1); |
120 | 115 | ||
121 | timeout = jiffies + (1 * HZ); | 116 | timeout = jiffies + (1 * HZ); |
122 | while (time_before(jiffies, timeout)) { | 117 | while (time_before(jiffies, timeout)) { |
@@ -136,48 +131,18 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
136 | return pen_release != -1 ? -ENOSYS : 0; | 131 | return pen_release != -1 ? -ENOSYS : 0; |
137 | } | 132 | } |
138 | 133 | ||
139 | static void __init poke_milo(void) | ||
140 | { | ||
141 | /* nobody is to be released from the pen yet */ | ||
142 | pen_release = -1; | ||
143 | |||
144 | /* | ||
145 | * Write the address of secondary startup into the system-wide flags | ||
146 | * register. The BootMonitor waits for this register to become | ||
147 | * non-zero. | ||
148 | */ | ||
149 | __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)), | ||
150 | __io_address(REALVIEW_SYS_FLAGSSET)); | ||
151 | |||
152 | mb(); | ||
153 | } | ||
154 | |||
155 | /* | 134 | /* |
156 | * Initialise the CPU possible map early - this describes the CPUs | 135 | * Initialise the CPU possible map early - this describes the CPUs |
157 | * which may be present or become present in the system. | 136 | * which may be present or become present in the system. |
158 | */ | 137 | */ |
159 | void __init smp_init_cpus(void) | 138 | void __init smp_init_cpus(void) |
160 | { | 139 | { |
161 | unsigned int i, ncores = get_core_count(); | 140 | void __iomem *scu_base = scu_base_addr(); |
141 | unsigned int i, ncores; | ||
162 | 142 | ||
163 | for (i = 0; i < ncores; i++) | 143 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; |
164 | set_cpu_possible(i, true); | ||
165 | } | ||
166 | |||
167 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
168 | { | ||
169 | unsigned int ncores = get_core_count(); | ||
170 | unsigned int cpu = smp_processor_id(); | ||
171 | int i; | ||
172 | 144 | ||
173 | /* sanity check */ | 145 | /* sanity check */ |
174 | if (ncores == 0) { | ||
175 | printk(KERN_ERR | ||
176 | "Realview: strange CM count of 0? Default to 1\n"); | ||
177 | |||
178 | ncores = 1; | ||
179 | } | ||
180 | |||
181 | if (ncores > NR_CPUS) { | 146 | if (ncores > NR_CPUS) { |
182 | printk(KERN_WARNING | 147 | printk(KERN_WARNING |
183 | "Realview: no. of cores (%d) greater than configured " | 148 | "Realview: no. of cores (%d) greater than configured " |
@@ -186,13 +151,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
186 | ncores = NR_CPUS; | 151 | ncores = NR_CPUS; |
187 | } | 152 | } |
188 | 153 | ||
189 | smp_store_cpu_info(cpu); | 154 | for (i = 0; i < ncores; i++) |
155 | set_cpu_possible(i, true); | ||
156 | } | ||
190 | 157 | ||
191 | /* | 158 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
192 | * are we trying to boot more cores than exist? | 159 | { |
193 | */ | 160 | int i; |
194 | if (max_cpus > ncores) | ||
195 | max_cpus = ncores; | ||
196 | 161 | ||
197 | /* | 162 | /* |
198 | * Initialise the present map, which describes the set of CPUs | 163 | * Initialise the present map, which describes the set of CPUs |
@@ -201,21 +166,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
201 | for (i = 0; i < max_cpus; i++) | 166 | for (i = 0; i < max_cpus; i++) |
202 | set_cpu_present(i, true); | 167 | set_cpu_present(i, true); |
203 | 168 | ||
169 | scu_enable(scu_base_addr()); | ||
170 | |||
204 | /* | 171 | /* |
205 | * Initialise the SCU if there are more than one CPU and let | 172 | * Write the address of secondary startup into the |
206 | * them know where to start. Note that, on modern versions of | 173 | * system-wide flags register. The BootMonitor waits |
207 | * MILO, the "poke" doesn't actually do anything until each | 174 | * until it receives a soft interrupt, and then the |
208 | * individual core is sent a soft interrupt to get it out of | 175 | * secondary CPU branches to this address. |
209 | * WFI | ||
210 | */ | 176 | */ |
211 | if (max_cpus > 1) { | 177 | __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)), |
212 | /* | 178 | __io_address(REALVIEW_SYS_FLAGSSET)); |
213 | * Enable the local timer or broadcast device for the | ||
214 | * boot CPU, but only if we have more than one CPU. | ||
215 | */ | ||
216 | percpu_timer_setup(); | ||
217 | |||
218 | scu_enable(scu_base_addr()); | ||
219 | poke_milo(); | ||
220 | } | ||
221 | } | 179 | } |
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index f2697106f80..6ef5c5e528b 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c | |||
@@ -364,21 +364,19 @@ static void __init gic_init_irq(void) | |||
364 | writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); | 364 | writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); |
365 | 365 | ||
366 | /* core tile GIC, primary */ | 366 | /* core tile GIC, primary */ |
367 | gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE); | 367 | gic_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), |
368 | gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29); | 368 | __io_address(REALVIEW_EB11MP_GIC_CPU_BASE)); |
369 | gic_cpu_init(0, gic_cpu_base_addr); | ||
370 | 369 | ||
371 | #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB | 370 | #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB |
372 | /* board GIC, secondary */ | 371 | /* board GIC, secondary */ |
373 | gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64); | 372 | gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE), |
374 | gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE)); | 373 | __io_address(REALVIEW_EB_GIC_CPU_BASE)); |
375 | gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1); | 374 | gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1); |
376 | #endif | 375 | #endif |
377 | } else { | 376 | } else { |
378 | /* board GIC, primary */ | 377 | /* board GIC, primary */ |
379 | gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE); | 378 | gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE), |
380 | gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29); | 379 | __io_address(REALVIEW_EB_GIC_CPU_BASE)); |
381 | gic_cpu_init(0, gic_cpu_base_addr); | ||
382 | } | 380 | } |
383 | } | 381 | } |
384 | 382 | ||
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index a4125619d71..cbdc97a5685 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c | |||
@@ -304,13 +304,14 @@ static struct platform_device char_lcd_device = { | |||
304 | static void __init gic_init_irq(void) | 304 | static void __init gic_init_irq(void) |
305 | { | 305 | { |
306 | /* ARM1176 DevChip GIC, primary */ | 306 | /* ARM1176 DevChip GIC, primary */ |
307 | gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE); | 307 | gic_init(0, IRQ_DC1176_GIC_START, |
308 | gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START); | 308 | __io_address(REALVIEW_DC1176_GIC_DIST_BASE), |
309 | gic_cpu_init(0, gic_cpu_base_addr); | 309 | __io_address(REALVIEW_DC1176_GIC_CPU_BASE)); |
310 | 310 | ||
311 | /* board GIC, secondary */ | 311 | /* board GIC, secondary */ |
312 | gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START); | 312 | gic_init(1, IRQ_PB1176_GIC_START, |
313 | gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE)); | 313 | __io_address(REALVIEW_PB1176_GIC_DIST_BASE), |
314 | __io_address(REALVIEW_PB1176_GIC_CPU_BASE)); | ||
314 | gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1); | 315 | gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1); |
315 | } | 316 | } |
316 | 317 | ||
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 117b95b2ca1..8e8ab7d29a6 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c | |||
@@ -309,13 +309,13 @@ static void __init gic_init_irq(void) | |||
309 | writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); | 309 | writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); |
310 | 310 | ||
311 | /* ARM11MPCore test chip GIC, primary */ | 311 | /* ARM11MPCore test chip GIC, primary */ |
312 | gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE); | 312 | gic_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), |
313 | gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29); | 313 | __io_address(REALVIEW_TC11MP_GIC_CPU_BASE)); |
314 | gic_cpu_init(0, gic_cpu_base_addr); | ||
315 | 314 | ||
316 | /* board GIC, secondary */ | 315 | /* board GIC, secondary */ |
317 | gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START); | 316 | gic_init(1, IRQ_PB11MP_GIC_START, |
318 | gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE)); | 317 | __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), |
318 | __io_address(REALVIEW_PB11MP_GIC_CPU_BASE)); | ||
319 | gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1); | 319 | gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1); |
320 | } | 320 | } |
321 | 321 | ||
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 929b8dc12e8..841118e3e11 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c | |||
@@ -273,9 +273,9 @@ static struct platform_device pmu_device = { | |||
273 | static void __init gic_init_irq(void) | 273 | static void __init gic_init_irq(void) |
274 | { | 274 | { |
275 | /* ARM PB-A8 on-board GIC */ | 275 | /* ARM PB-A8 on-board GIC */ |
276 | gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE); | 276 | gic_init(0, IRQ_PBA8_GIC_START, |
277 | gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START); | 277 | __io_address(REALVIEW_PBA8_GIC_DIST_BASE), |
278 | gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE)); | 278 | __io_address(REALVIEW_PBA8_GIC_CPU_BASE)); |
279 | } | 279 | } |
280 | 280 | ||
281 | static void __init realview_pba8_timer_init(void) | 281 | static void __init realview_pba8_timer_init(void) |
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index b9f9e20031a..02b755b009d 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c | |||
@@ -313,15 +313,12 @@ static void __init gic_init_irq(void) | |||
313 | { | 313 | { |
314 | /* ARM PBX on-board GIC */ | 314 | /* ARM PBX on-board GIC */ |
315 | if (core_tile_pbx11mp() || core_tile_pbxa9mp()) { | 315 | if (core_tile_pbx11mp() || core_tile_pbxa9mp()) { |
316 | gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE); | 316 | gic_init(0, 29, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE), |
317 | gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE), | 317 | __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE)); |
318 | 29); | ||
319 | gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE)); | ||
320 | } else { | 318 | } else { |
321 | gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE); | 319 | gic_init(0, IRQ_PBX_GIC_START, |
322 | gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE), | 320 | __io_address(REALVIEW_PBX_GIC_DIST_BASE), |
323 | IRQ_PBX_GIC_START); | 321 | __io_address(REALVIEW_PBX_GIC_CPU_BASE)); |
324 | gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE)); | ||
325 | } | 322 | } |
326 | } | 323 | } |
327 | 324 | ||
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig index fa2e5bffbb8..e82ab4aa7ab 100644 --- a/arch/arm/mach-s3c2412/Kconfig +++ b/arch/arm/mach-s3c2412/Kconfig | |||
@@ -28,9 +28,16 @@ config S3C2412_DMA | |||
28 | 28 | ||
29 | config S3C2412_PM | 29 | config S3C2412_PM |
30 | bool | 30 | bool |
31 | select S3C2412_PM_SLEEP | ||
31 | help | 32 | help |
32 | Internal config node to apply S3C2412 power management | 33 | Internal config node to apply S3C2412 power management |
33 | 34 | ||
35 | config S3C2412_PM_SLEEP | ||
36 | bool | ||
37 | help | ||
38 | Internal config node to apply sleep for S3C2412 power management. | ||
39 | Can be selected by another SoCs with similar sleep procedure. | ||
40 | |||
34 | # Note, the S3C2412 IOtiming support is in plat-s3c24xx | 41 | # Note, the S3C2412 IOtiming support is in plat-s3c24xx |
35 | 42 | ||
36 | config S3C2412_CPUFREQ | 43 | config S3C2412_CPUFREQ |
@@ -52,7 +59,7 @@ config MACH_JIVE | |||
52 | Say Y here if you are using the Logitech Jive. | 59 | Say Y here if you are using the Logitech Jive. |
53 | 60 | ||
54 | config MACH_JIVE_SHOW_BOOTLOADER | 61 | config MACH_JIVE_SHOW_BOOTLOADER |
55 | bool "Allow access to bootloader partitions in MTD" | 62 | bool "Allow access to bootloader partitions in MTD (EXPERIMENTAL)" |
56 | depends on MACH_JIVE && EXPERIMENTAL | 63 | depends on MACH_JIVE && EXPERIMENTAL |
57 | 64 | ||
58 | config MACH_SMDK2413 | 65 | config MACH_SMDK2413 |
diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile index 530ec46cbae..6c48a91ea39 100644 --- a/arch/arm/mach-s3c2412/Makefile +++ b/arch/arm/mach-s3c2412/Makefile | |||
@@ -14,7 +14,8 @@ obj-$(CONFIG_CPU_S3C2412) += irq.o | |||
14 | obj-$(CONFIG_CPU_S3C2412) += clock.o | 14 | obj-$(CONFIG_CPU_S3C2412) += clock.o |
15 | obj-$(CONFIG_CPU_S3C2412) += gpio.o | 15 | obj-$(CONFIG_CPU_S3C2412) += gpio.o |
16 | obj-$(CONFIG_S3C2412_DMA) += dma.o | 16 | obj-$(CONFIG_S3C2412_DMA) += dma.o |
17 | obj-$(CONFIG_S3C2412_PM) += pm.o sleep.o | 17 | obj-$(CONFIG_S3C2412_PM) += pm.o |
18 | obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep.o | ||
18 | obj-$(CONFIG_S3C2412_CPUFREQ) += cpu-freq.o | 19 | obj-$(CONFIG_S3C2412_CPUFREQ) += cpu-freq.o |
19 | 20 | ||
20 | # Machine support | 21 | # Machine support |
diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 27b3e7c9d61..df8d14974c9 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig | |||
@@ -27,6 +27,7 @@ config S3C2416_DMA | |||
27 | 27 | ||
28 | config S3C2416_PM | 28 | config S3C2416_PM |
29 | bool | 29 | bool |
30 | select S3C2412_PM_SLEEP | ||
30 | help | 31 | help |
31 | Internal config node to apply S3C2416 power management | 32 | Internal config node to apply S3C2416 power management |
32 | 33 | ||
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 28677caf361..461aa035afc 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c | |||
@@ -378,6 +378,12 @@ static struct max8998_regulator_data aquila_regulators[] = { | |||
378 | static struct max8998_platform_data aquila_max8998_pdata = { | 378 | static struct max8998_platform_data aquila_max8998_pdata = { |
379 | .num_regulators = ARRAY_SIZE(aquila_regulators), | 379 | .num_regulators = ARRAY_SIZE(aquila_regulators), |
380 | .regulators = aquila_regulators, | 380 | .regulators = aquila_regulators, |
381 | .buck1_set1 = S5PV210_GPH0(3), | ||
382 | .buck1_set2 = S5PV210_GPH0(4), | ||
383 | .buck2_set3 = S5PV210_GPH0(5), | ||
384 | .buck1_max_voltage1 = 1200000, | ||
385 | .buck1_max_voltage2 = 1200000, | ||
386 | .buck2_max_voltage = 1200000, | ||
381 | }; | 387 | }; |
382 | #endif | 388 | #endif |
383 | 389 | ||
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index b1dcf964a76..e22d5112fd4 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c | |||
@@ -518,6 +518,12 @@ static struct max8998_regulator_data goni_regulators[] = { | |||
518 | static struct max8998_platform_data goni_max8998_pdata = { | 518 | static struct max8998_platform_data goni_max8998_pdata = { |
519 | .num_regulators = ARRAY_SIZE(goni_regulators), | 519 | .num_regulators = ARRAY_SIZE(goni_regulators), |
520 | .regulators = goni_regulators, | 520 | .regulators = goni_regulators, |
521 | .buck1_set1 = S5PV210_GPH0(3), | ||
522 | .buck1_set2 = S5PV210_GPH0(4), | ||
523 | .buck2_set3 = S5PV210_GPH0(5), | ||
524 | .buck1_max_voltage1 = 1200000, | ||
525 | .buck1_max_voltage2 = 1200000, | ||
526 | .buck2_max_voltage = 1200000, | ||
521 | }; | 527 | }; |
522 | #endif | 528 | #endif |
523 | 529 | ||
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c index 82ce4aa6d61..72ab289e781 100644 --- a/arch/arm/mach-s5pv310/cpu.c +++ b/arch/arm/mach-s5pv310/cpu.c | |||
@@ -24,8 +24,6 @@ | |||
24 | 24 | ||
25 | #include <mach/regs-irq.h> | 25 | #include <mach/regs-irq.h> |
26 | 26 | ||
27 | void __iomem *gic_cpu_base_addr; | ||
28 | |||
29 | extern int combiner_init(unsigned int combiner_nr, void __iomem *base, | 27 | extern int combiner_init(unsigned int combiner_nr, void __iomem *base, |
30 | unsigned int irq_start); | 28 | unsigned int irq_start); |
31 | extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq); | 29 | extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq); |
@@ -122,9 +120,7 @@ void __init s5pv310_init_irq(void) | |||
122 | { | 120 | { |
123 | int irq; | 121 | int irq; |
124 | 122 | ||
125 | gic_cpu_base_addr = S5P_VA_GIC_CPU; | 123 | gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU); |
126 | gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER); | ||
127 | gic_cpu_init(0, S5P_VA_GIC_CPU); | ||
128 | 124 | ||
129 | for (irq = 0; irq < MAX_COMBINER_NR; irq++) { | 125 | for (irq = 0; irq < MAX_COMBINER_NR; irq++) { |
130 | combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), | 126 | combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), |
diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c index 03652c3605f..afa5392d9fc 100644 --- a/arch/arm/mach-s5pv310/hotplug.c +++ b/arch/arm/mach-s5pv310/hotplug.c | |||
@@ -13,14 +13,11 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
16 | #include <linux/completion.h> | ||
17 | 16 | ||
18 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
19 | 18 | ||
20 | extern volatile int pen_release; | 19 | extern volatile int pen_release; |
21 | 20 | ||
22 | static DECLARE_COMPLETION(cpu_killed); | ||
23 | |||
24 | static inline void cpu_enter_lowpower(void) | 21 | static inline void cpu_enter_lowpower(void) |
25 | { | 22 | { |
26 | unsigned int v; | 23 | unsigned int v; |
@@ -33,13 +30,13 @@ static inline void cpu_enter_lowpower(void) | |||
33 | * Turn off coherency | 30 | * Turn off coherency |
34 | */ | 31 | */ |
35 | " mrc p15, 0, %0, c1, c0, 1\n" | 32 | " mrc p15, 0, %0, c1, c0, 1\n" |
36 | " bic %0, %0, #0x20\n" | 33 | " bic %0, %0, %2\n" |
37 | " mcr p15, 0, %0, c1, c0, 1\n" | 34 | " mcr p15, 0, %0, c1, c0, 1\n" |
38 | " mrc p15, 0, %0, c1, c0, 0\n" | 35 | " mrc p15, 0, %0, c1, c0, 0\n" |
39 | " bic %0, %0, #0x04\n" | 36 | " bic %0, %0, #0x04\n" |
40 | " mcr p15, 0, %0, c1, c0, 0\n" | 37 | " mcr p15, 0, %0, c1, c0, 0\n" |
41 | : "=&r" (v) | 38 | : "=&r" (v) |
42 | : "r" (0) | 39 | : "r" (0), "Ir" (CR_C) |
43 | : "cc"); | 40 | : "cc"); |
44 | } | 41 | } |
45 | 42 | ||
@@ -49,17 +46,17 @@ static inline void cpu_leave_lowpower(void) | |||
49 | 46 | ||
50 | asm volatile( | 47 | asm volatile( |
51 | "mrc p15, 0, %0, c1, c0, 0\n" | 48 | "mrc p15, 0, %0, c1, c0, 0\n" |
52 | " orr %0, %0, #0x04\n" | 49 | " orr %0, %0, %1\n" |
53 | " mcr p15, 0, %0, c1, c0, 0\n" | 50 | " mcr p15, 0, %0, c1, c0, 0\n" |
54 | " mrc p15, 0, %0, c1, c0, 1\n" | 51 | " mrc p15, 0, %0, c1, c0, 1\n" |
55 | " orr %0, %0, #0x20\n" | 52 | " orr %0, %0, #0x20\n" |
56 | " mcr p15, 0, %0, c1, c0, 1\n" | 53 | " mcr p15, 0, %0, c1, c0, 1\n" |
57 | : "=&r" (v) | 54 | : "=&r" (v) |
58 | : | 55 | : "Ir" (CR_C) |
59 | : "cc"); | 56 | : "cc"); |
60 | } | 57 | } |
61 | 58 | ||
62 | static inline void platform_do_lowpower(unsigned int cpu) | 59 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) |
63 | { | 60 | { |
64 | /* | 61 | /* |
65 | * there is no power-control hardware on this platform, so all | 62 | * there is no power-control hardware on this platform, so all |
@@ -83,22 +80,19 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
83 | } | 80 | } |
84 | 81 | ||
85 | /* | 82 | /* |
86 | * getting here, means that we have come out of WFI without | 83 | * Getting here, means that we have come out of WFI without |
87 | * having been woken up - this shouldn't happen | 84 | * having been woken up - this shouldn't happen |
88 | * | 85 | * |
89 | * The trouble is, letting people know about this is not really | 86 | * Just note it happening - when we're woken, we can report |
90 | * possible, since we are currently running incoherently, and | 87 | * its occurrence. |
91 | * therefore cannot safely call printk() or anything else | ||
92 | */ | 88 | */ |
93 | #ifdef DEBUG | 89 | (*spurious)++; |
94 | printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu); | ||
95 | #endif | ||
96 | } | 90 | } |
97 | } | 91 | } |
98 | 92 | ||
99 | int platform_cpu_kill(unsigned int cpu) | 93 | int platform_cpu_kill(unsigned int cpu) |
100 | { | 94 | { |
101 | return wait_for_completion_timeout(&cpu_killed, 5000); | 95 | return 1; |
102 | } | 96 | } |
103 | 97 | ||
104 | /* | 98 | /* |
@@ -108,30 +102,22 @@ int platform_cpu_kill(unsigned int cpu) | |||
108 | */ | 102 | */ |
109 | void platform_cpu_die(unsigned int cpu) | 103 | void platform_cpu_die(unsigned int cpu) |
110 | { | 104 | { |
111 | #ifdef DEBUG | 105 | int spurious = 0; |
112 | unsigned int this_cpu = hard_smp_processor_id(); | ||
113 | |||
114 | if (cpu != this_cpu) { | ||
115 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
116 | this_cpu, cpu); | ||
117 | BUG(); | ||
118 | } | ||
119 | #endif | ||
120 | |||
121 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
122 | complete(&cpu_killed); | ||
123 | 106 | ||
124 | /* | 107 | /* |
125 | * we're ready for shutdown now, so do it | 108 | * we're ready for shutdown now, so do it |
126 | */ | 109 | */ |
127 | cpu_enter_lowpower(); | 110 | cpu_enter_lowpower(); |
128 | platform_do_lowpower(cpu); | 111 | platform_do_lowpower(cpu, &spurious); |
129 | 112 | ||
130 | /* | 113 | /* |
131 | * bring this CPU back into the world of cache | 114 | * bring this CPU back into the world of cache |
132 | * coherency, and then restore interrupts | 115 | * coherency, and then restore interrupts |
133 | */ | 116 | */ |
134 | cpu_leave_lowpower(); | 117 | cpu_leave_lowpower(); |
118 | |||
119 | if (spurious) | ||
120 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
135 | } | 121 | } |
136 | 122 | ||
137 | int platform_cpu_disable(unsigned int cpu) | 123 | int platform_cpu_disable(unsigned int cpu) |
diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h index b7ec252384f..393ccbd52c4 100644 --- a/arch/arm/mach-s5pv310/include/mach/smp.h +++ b/arch/arm/mach-s5pv310/include/mach/smp.h | |||
@@ -7,16 +7,13 @@ | |||
7 | #define ASM_ARCH_SMP_H __FILE__ | 7 | #define ASM_ARCH_SMP_H __FILE__ |
8 | 8 | ||
9 | #include <asm/hardware/gic.h> | 9 | #include <asm/hardware/gic.h> |
10 | #include <asm/smp_mpidr.h> | ||
11 | |||
12 | extern void __iomem *gic_cpu_base_addr; | ||
13 | 10 | ||
14 | /* | 11 | /* |
15 | * We use IRQ1 as the IPI | 12 | * We use IRQ1 as the IPI |
16 | */ | 13 | */ |
17 | static inline void smp_cross_call(const struct cpumask *mask) | 14 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
18 | { | 15 | { |
19 | gic_raise_softirq(mask, 1); | 16 | gic_raise_softirq(mask, ipi); |
20 | } | 17 | } |
21 | 18 | ||
22 | #endif | 19 | #endif |
diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c index d357c198ede..34093b069f6 100644 --- a/arch/arm/mach-s5pv310/platsmp.c +++ b/arch/arm/mach-s5pv310/platsmp.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | 23 | ||
24 | #include <asm/cacheflush.h> | 24 | #include <asm/cacheflush.h> |
25 | #include <asm/localtimer.h> | ||
26 | #include <asm/smp_scu.h> | 25 | #include <asm/smp_scu.h> |
27 | #include <asm/unified.h> | 26 | #include <asm/unified.h> |
28 | 27 | ||
@@ -38,6 +37,19 @@ extern void s5pv310_secondary_startup(void); | |||
38 | 37 | ||
39 | volatile int __cpuinitdata pen_release = -1; | 38 | volatile int __cpuinitdata pen_release = -1; |
40 | 39 | ||
40 | /* | ||
41 | * Write pen_release in a way that is guaranteed to be visible to all | ||
42 | * observers, irrespective of whether they're taking part in coherency | ||
43 | * or not. This is necessary for the hotplug code to work reliably. | ||
44 | */ | ||
45 | static void write_pen_release(int val) | ||
46 | { | ||
47 | pen_release = val; | ||
48 | smp_wmb(); | ||
49 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
50 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
51 | } | ||
52 | |||
41 | static void __iomem *scu_base_addr(void) | 53 | static void __iomem *scu_base_addr(void) |
42 | { | 54 | { |
43 | return (void __iomem *)(S5P_VA_SCU); | 55 | return (void __iomem *)(S5P_VA_SCU); |
@@ -47,21 +59,18 @@ static DEFINE_SPINLOCK(boot_lock); | |||
47 | 59 | ||
48 | void __cpuinit platform_secondary_init(unsigned int cpu) | 60 | void __cpuinit platform_secondary_init(unsigned int cpu) |
49 | { | 61 | { |
50 | trace_hardirqs_off(); | ||
51 | |||
52 | /* | 62 | /* |
53 | * if any interrupts are already enabled for the primary | 63 | * if any interrupts are already enabled for the primary |
54 | * core (e.g. timer irq), then they will not have been enabled | 64 | * core (e.g. timer irq), then they will not have been enabled |
55 | * for us: do so | 65 | * for us: do so |
56 | */ | 66 | */ |
57 | gic_cpu_init(0, gic_cpu_base_addr); | 67 | gic_secondary_init(0); |
58 | 68 | ||
59 | /* | 69 | /* |
60 | * let the primary processor know we're out of the | 70 | * let the primary processor know we're out of the |
61 | * pen, then head off into the C entry point | 71 | * pen, then head off into the C entry point |
62 | */ | 72 | */ |
63 | pen_release = -1; | 73 | write_pen_release(-1); |
64 | smp_wmb(); | ||
65 | 74 | ||
66 | /* | 75 | /* |
67 | * Synchronise with the boot thread. | 76 | * Synchronise with the boot thread. |
@@ -88,16 +97,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
88 | * Note that "pen_release" is the hardware CPU ID, whereas | 97 | * Note that "pen_release" is the hardware CPU ID, whereas |
89 | * "cpu" is Linux's internal ID. | 98 | * "cpu" is Linux's internal ID. |
90 | */ | 99 | */ |
91 | pen_release = cpu; | 100 | write_pen_release(cpu); |
92 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
93 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
94 | 101 | ||
95 | /* | 102 | /* |
96 | * Send the secondary CPU a soft interrupt, thereby causing | 103 | * Send the secondary CPU a soft interrupt, thereby causing |
97 | * the boot monitor to read the system wide flags register, | 104 | * the boot monitor to read the system wide flags register, |
98 | * and branch to the address found there. | 105 | * and branch to the address found there. |
99 | */ | 106 | */ |
100 | smp_cross_call(cpumask_of(cpu)); | 107 | smp_cross_call(cpumask_of(cpu), 1); |
101 | 108 | ||
102 | timeout = jiffies + (1 * HZ); | 109 | timeout = jiffies + (1 * HZ); |
103 | while (time_before(jiffies, timeout)) { | 110 | while (time_before(jiffies, timeout)) { |
@@ -130,13 +137,6 @@ void __init smp_init_cpus(void) | |||
130 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; | 137 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; |
131 | 138 | ||
132 | /* sanity check */ | 139 | /* sanity check */ |
133 | if (ncores == 0) { | ||
134 | printk(KERN_ERR | ||
135 | "S5PV310: strange CM count of 0? Default to 1\n"); | ||
136 | |||
137 | ncores = 1; | ||
138 | } | ||
139 | |||
140 | if (ncores > NR_CPUS) { | 140 | if (ncores > NR_CPUS) { |
141 | printk(KERN_WARNING | 141 | printk(KERN_WARNING |
142 | "S5PV310: no. of cores (%d) greater than configured " | 142 | "S5PV310: no. of cores (%d) greater than configured " |
@@ -149,18 +149,10 @@ void __init smp_init_cpus(void) | |||
149 | set_cpu_possible(i, true); | 149 | set_cpu_possible(i, true); |
150 | } | 150 | } |
151 | 151 | ||
152 | void __init smp_prepare_cpus(unsigned int max_cpus) | 152 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
153 | { | 153 | { |
154 | unsigned int ncores = num_possible_cpus(); | ||
155 | unsigned int cpu = smp_processor_id(); | ||
156 | int i; | 154 | int i; |
157 | 155 | ||
158 | smp_store_cpu_info(cpu); | ||
159 | |||
160 | /* are we trying to boot more cores than exist? */ | ||
161 | if (max_cpus > ncores) | ||
162 | max_cpus = ncores; | ||
163 | |||
164 | /* | 156 | /* |
165 | * Initialise the present map, which describes the set of CPUs | 157 | * Initialise the present map, which describes the set of CPUs |
166 | * actually populated at the present time. | 158 | * actually populated at the present time. |
@@ -168,25 +160,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
168 | for (i = 0; i < max_cpus; i++) | 160 | for (i = 0; i < max_cpus; i++) |
169 | set_cpu_present(i, true); | 161 | set_cpu_present(i, true); |
170 | 162 | ||
163 | scu_enable(scu_base_addr()); | ||
164 | |||
171 | /* | 165 | /* |
172 | * Initialise the SCU if there are more than one CPU and let | 166 | * Write the address of secondary startup into the |
173 | * them know where to start. | 167 | * system-wide flags register. The boot monitor waits |
168 | * until it receives a soft interrupt, and then the | ||
169 | * secondary CPU branches to this address. | ||
174 | */ | 170 | */ |
175 | if (max_cpus > 1) { | ||
176 | /* | ||
177 | * Enable the local timer or broadcast device for the | ||
178 | * boot CPU, but only if we have more than one CPU. | ||
179 | */ | ||
180 | percpu_timer_setup(); | ||
181 | |||
182 | scu_enable(scu_base_addr()); | ||
183 | |||
184 | /* | ||
185 | * Write the address of secondary startup into the | ||
186 | * system-wide flags register. The boot monitor waits | ||
187 | * until it receives a soft interrupt, and then the | ||
188 | * secondary CPU branches to this address. | ||
189 | */ | ||
190 | __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM); | 171 | __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM); |
191 | } | ||
192 | } | 172 | } |
diff --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c index 01b012ad1bf..b262d461533 100644 --- a/arch/arm/mach-s5pv310/time.c +++ b/arch/arm/mach-s5pv310/time.c | |||
@@ -211,7 +211,6 @@ struct clocksource pwm_clocksource = { | |||
211 | .rating = 250, | 211 | .rating = 250, |
212 | .read = s5pv310_pwm4_read, | 212 | .read = s5pv310_pwm4_read, |
213 | .mask = CLOCKSOURCE_MASK(32), | 213 | .mask = CLOCKSOURCE_MASK(32), |
214 | .shift = 20, | ||
215 | .flags = CLOCK_SOURCE_IS_CONTINUOUS , | 214 | .flags = CLOCK_SOURCE_IS_CONTINUOUS , |
216 | }; | 215 | }; |
217 | 216 | ||
@@ -230,10 +229,7 @@ static void __init s5pv310_clocksource_init(void) | |||
230 | s5pv310_pwm_init(4, ~0); | 229 | s5pv310_pwm_init(4, ~0); |
231 | s5pv310_pwm_start(4, 1); | 230 | s5pv310_pwm_start(4, 1); |
232 | 231 | ||
233 | pwm_clocksource.mult = | 232 | if (clocksource_register_hz(&pwm_clocksource, clock_rate)) |
234 | clocksource_khz2mult(clock_rate/1000, pwm_clocksource.shift); | ||
235 | |||
236 | if (clocksource_register(&pwm_clocksource)) | ||
237 | panic("%s: can't register clocksource\n", pwm_clocksource.name); | 233 | panic("%s: can't register clocksource\n", pwm_clocksource.name); |
238 | } | 234 | } |
239 | 235 | ||
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index 5da8c35aa0d..42625e4d949 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig | |||
@@ -118,6 +118,16 @@ config SA1100_LART | |||
118 | (also known as the LART). See <http://www.lartmaker.nl/> for | 118 | (also known as the LART). See <http://www.lartmaker.nl/> for |
119 | information on the LART. | 119 | information on the LART. |
120 | 120 | ||
121 | config SA1100_NANOENGINE | ||
122 | bool "nanoEngine" | ||
123 | select CPU_FREQ_SA1110 | ||
124 | select PCI | ||
125 | select PCI_NANOENGINE | ||
126 | help | ||
127 | Say Y here if you are using the Bright Star Engineering nanoEngine. | ||
128 | See <http://www.brightstareng.com/arm/nanoeng.htm> for information | ||
129 | on the BSE nanoEngine. | ||
130 | |||
121 | config SA1100_PLEB | 131 | config SA1100_PLEB |
122 | bool "PLEB" | 132 | bool "PLEB" |
123 | select CPU_FREQ_SA1100 | 133 | select CPU_FREQ_SA1100 |
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 89349c1dd7a..e697691eed2 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile | |||
@@ -37,6 +37,9 @@ obj-$(CONFIG_SA1100_JORNADA720_SSP) += jornada720_ssp.o | |||
37 | obj-$(CONFIG_SA1100_LART) += lart.o | 37 | obj-$(CONFIG_SA1100_LART) += lart.o |
38 | led-$(CONFIG_SA1100_LART) += leds-lart.o | 38 | led-$(CONFIG_SA1100_LART) += leds-lart.o |
39 | 39 | ||
40 | obj-$(CONFIG_SA1100_NANOENGINE) += nanoengine.o | ||
41 | obj-$(CONFIG_PCI_NANOENGINE) += pci-nanoengine.o | ||
42 | |||
40 | obj-$(CONFIG_SA1100_PLEB) += pleb.o | 43 | obj-$(CONFIG_SA1100_PLEB) += pleb.o |
41 | 44 | ||
42 | obj-$(CONFIG_SA1100_SHANNON) += shannon.o | 45 | obj-$(CONFIG_SA1100_SHANNON) += shannon.o |
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index 96f7dc103b5..07d4e8ba371 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c | |||
@@ -94,48 +94,47 @@ | |||
94 | 94 | ||
95 | #include "generic.h" | 95 | #include "generic.h" |
96 | 96 | ||
97 | typedef struct { | 97 | struct sa1100_dram_regs { |
98 | int speed; | 98 | int speed; |
99 | u32 mdcnfg; | 99 | u32 mdcnfg; |
100 | u32 mdcas0; | 100 | u32 mdcas0; |
101 | u32 mdcas1; | 101 | u32 mdcas1; |
102 | u32 mdcas2; | 102 | u32 mdcas2; |
103 | } sa1100_dram_regs_t; | 103 | }; |
104 | 104 | ||
105 | 105 | ||
106 | static struct cpufreq_driver sa1100_driver; | 106 | static struct cpufreq_driver sa1100_driver; |
107 | 107 | ||
108 | static sa1100_dram_regs_t sa1100_dram_settings[] = | 108 | static struct sa1100_dram_regs sa1100_dram_settings[] = { |
109 | { | 109 | /*speed, mdcnfg, mdcas0, mdcas1, mdcas2, clock freq */ |
110 | /* speed, mdcnfg, mdcas0, mdcas1, mdcas2 clock frequency */ | 110 | { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 59.0 MHz */ |
111 | { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 59.0 MHz */ | 111 | { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 73.7 MHz */ |
112 | { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 73.7 MHz */ | 112 | { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 88.5 MHz */ |
113 | { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 88.5 MHz */ | 113 | {103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */ |
114 | { 103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 103.2 MHz */ | 114 | {118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */ |
115 | { 118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 118.0 MHz */ | 115 | {132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */ |
116 | { 132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 132.7 MHz */ | 116 | {147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */ |
117 | { 147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff }, /* 147.5 MHz */ | 117 | {162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */ |
118 | { 162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff }, /* 162.2 MHz */ | 118 | {176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */ |
119 | { 176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff }, /* 176.9 MHz */ | 119 | {191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */ |
120 | { 191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff }, /* 191.7 MHz */ | 120 | {206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */ |
121 | { 206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 206.4 MHz */ | 121 | {221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */ |
122 | { 221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 221.2 MHz */ | 122 | {235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */ |
123 | { 235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1 }, /* 235.9 MHz */ | 123 | {250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */ |
124 | { 250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 250.7 MHz */ | 124 | {265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */ |
125 | { 265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 265.4 MHz */ | 125 | {280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */ |
126 | { 280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87 }, /* 280.2 MHz */ | ||
127 | { 0, 0, 0, 0, 0 } /* last entry */ | 126 | { 0, 0, 0, 0, 0 } /* last entry */ |
128 | }; | 127 | }; |
129 | 128 | ||
130 | static void sa1100_update_dram_timings(int current_speed, int new_speed) | 129 | static void sa1100_update_dram_timings(int current_speed, int new_speed) |
131 | { | 130 | { |
132 | sa1100_dram_regs_t *settings = sa1100_dram_settings; | 131 | struct sa1100_dram_regs *settings = sa1100_dram_settings; |
133 | 132 | ||
134 | /* find speed */ | 133 | /* find speed */ |
135 | while (settings->speed != 0) { | 134 | while (settings->speed != 0) { |
136 | if(new_speed == settings->speed) | 135 | if (new_speed == settings->speed) |
137 | break; | 136 | break; |
138 | 137 | ||
139 | settings++; | 138 | settings++; |
140 | } | 139 | } |
141 | 140 | ||
@@ -149,7 +148,7 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed) | |||
149 | /* We're going FASTER, so first relax the memory | 148 | /* We're going FASTER, so first relax the memory |
150 | * timings before changing the core frequency | 149 | * timings before changing the core frequency |
151 | */ | 150 | */ |
152 | 151 | ||
153 | /* Half the memory access clock */ | 152 | /* Half the memory access clock */ |
154 | MDCNFG |= MDCNFG_CDB2; | 153 | MDCNFG |= MDCNFG_CDB2; |
155 | 154 | ||
@@ -187,7 +186,7 @@ static int sa1100_target(struct cpufreq_policy *policy, | |||
187 | struct cpufreq_freqs freqs; | 186 | struct cpufreq_freqs freqs; |
188 | 187 | ||
189 | new_ppcr = sa11x0_freq_to_ppcr(target_freq); | 188 | new_ppcr = sa11x0_freq_to_ppcr(target_freq); |
190 | switch(relation){ | 189 | switch (relation) { |
191 | case CPUFREQ_RELATION_L: | 190 | case CPUFREQ_RELATION_L: |
192 | if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) | 191 | if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) |
193 | new_ppcr--; | 192 | new_ppcr--; |
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 7252874d328..675bf8ef97e 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c | |||
@@ -16,28 +16,24 @@ | |||
16 | * | 16 | * |
17 | * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type | 17 | * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type |
18 | */ | 18 | */ |
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/cpufreq.h> | 19 | #include <linux/cpufreq.h> |
24 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
25 | #include <linux/init.h> | 21 | #include <linux/init.h> |
26 | #include <linux/io.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/types.h> | ||
27 | 25 | ||
28 | #include <mach/hardware.h> | ||
29 | #include <asm/cputype.h> | 26 | #include <asm/cputype.h> |
30 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
31 | #include <asm/system.h> | 28 | |
29 | #include <mach/hardware.h> | ||
32 | 30 | ||
33 | #include "generic.h" | 31 | #include "generic.h" |
34 | 32 | ||
35 | #undef DEBUG | 33 | #undef DEBUG |
36 | 34 | ||
37 | static struct cpufreq_driver sa1110_driver; | ||
38 | |||
39 | struct sdram_params { | 35 | struct sdram_params { |
40 | const char name[16]; | 36 | const char name[20]; |
41 | u_char rows; /* bits */ | 37 | u_char rows; /* bits */ |
42 | u_char cas_latency; /* cycles */ | 38 | u_char cas_latency; /* cycles */ |
43 | u_char tck; /* clock cycle time (ns) */ | 39 | u_char tck; /* clock cycle time (ns) */ |
@@ -107,6 +103,15 @@ static struct sdram_params sdram_tbl[] __initdata = { | |||
107 | .twr = 8, | 103 | .twr = 8, |
108 | .refresh = 64000, | 104 | .refresh = 64000, |
109 | .cas_latency = 3, | 105 | .cas_latency = 3, |
106 | }, { /* Micron MT48LC8M16A2TG-75 */ | ||
107 | .name = "MT48LC8M16A2TG-75", | ||
108 | .rows = 12, | ||
109 | .tck = 8, | ||
110 | .trcd = 20, | ||
111 | .trp = 20, | ||
112 | .twr = 8, | ||
113 | .refresh = 64000, | ||
114 | .cas_latency = 3, | ||
110 | }, | 115 | }, |
111 | }; | 116 | }; |
112 | 117 | ||
@@ -180,11 +185,13 @@ sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz, | |||
180 | sd->mdrefr |= MDREFR_K1DB2; | 185 | sd->mdrefr |= MDREFR_K1DB2; |
181 | 186 | ||
182 | /* initial number of '1's in MDCAS + 1 */ | 187 | /* initial number of '1's in MDCAS + 1 */ |
183 | set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz)); | 188 | set_mdcas(sd->mdcas, sd_khz >= 62000, |
189 | ns_to_cycles(sdram->trcd, mem_khz)); | ||
184 | 190 | ||
185 | #ifdef DEBUG | 191 | #ifdef DEBUG |
186 | printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n", | 192 | printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n", |
187 | sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]); | 193 | sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], |
194 | sd->mdcas[2]); | ||
188 | #endif | 195 | #endif |
189 | } | 196 | } |
190 | 197 | ||
@@ -213,7 +220,7 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram) | |||
213 | 220 | ||
214 | #ifdef DEBUG | 221 | #ifdef DEBUG |
215 | mdelay(250); | 222 | mdelay(250); |
216 | printk("new dri value = %d\n", dri); | 223 | printk(KERN_DEBUG "new dri value = %d\n", dri); |
217 | #endif | 224 | #endif |
218 | 225 | ||
219 | sdram_set_refresh(dri); | 226 | sdram_set_refresh(dri); |
@@ -232,7 +239,7 @@ static int sa1110_target(struct cpufreq_policy *policy, | |||
232 | unsigned long flags; | 239 | unsigned long flags; |
233 | unsigned int ppcr, unused; | 240 | unsigned int ppcr, unused; |
234 | 241 | ||
235 | switch(relation){ | 242 | switch (relation) { |
236 | case CPUFREQ_RELATION_L: | 243 | case CPUFREQ_RELATION_L: |
237 | ppcr = sa11x0_freq_to_ppcr(target_freq); | 244 | ppcr = sa11x0_freq_to_ppcr(target_freq); |
238 | if (sa11x0_ppcr_to_freq(ppcr) > policy->max) | 245 | if (sa11x0_ppcr_to_freq(ppcr) > policy->max) |
@@ -280,11 +287,10 @@ static int sa1110_target(struct cpufreq_policy *policy, | |||
280 | * We wait 20ms to be safe. | 287 | * We wait 20ms to be safe. |
281 | */ | 288 | */ |
282 | sdram_set_refresh(2); | 289 | sdram_set_refresh(2); |
283 | if (!irqs_disabled()) { | 290 | if (!irqs_disabled()) |
284 | msleep(20); | 291 | msleep(20); |
285 | } else { | 292 | else |
286 | mdelay(20); | 293 | mdelay(20); |
287 | } | ||
288 | 294 | ||
289 | /* | 295 | /* |
290 | * Reprogram the DRAM timings with interrupts disabled, and | 296 | * Reprogram the DRAM timings with interrupts disabled, and |
@@ -295,7 +301,7 @@ static int sa1110_target(struct cpufreq_policy *policy, | |||
295 | local_irq_save(flags); | 301 | local_irq_save(flags); |
296 | asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); | 302 | asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); |
297 | udelay(10); | 303 | udelay(10); |
298 | __asm__ __volatile__(" \n\ | 304 | __asm__ __volatile__("\n\ |
299 | b 2f \n\ | 305 | b 2f \n\ |
300 | .align 5 \n\ | 306 | .align 5 \n\ |
301 | 1: str %3, [%1, #0] @ MDCNFG \n\ | 307 | 1: str %3, [%1, #0] @ MDCNFG \n\ |
@@ -336,7 +342,9 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy) | |||
336 | return 0; | 342 | return 0; |
337 | } | 343 | } |
338 | 344 | ||
339 | static struct cpufreq_driver sa1110_driver = { | 345 | /* sa1110_driver needs __refdata because it must remain after init registers |
346 | * it with cpufreq_register_driver() */ | ||
347 | static struct cpufreq_driver sa1110_driver __refdata = { | ||
340 | .flags = CPUFREQ_STICKY, | 348 | .flags = CPUFREQ_STICKY, |
341 | .verify = sa11x0_verify_speed, | 349 | .verify = sa11x0_verify_speed, |
342 | .target = sa1110_target, | 350 | .target = sa1110_target, |
@@ -349,7 +357,8 @@ static struct sdram_params *sa1110_find_sdram(const char *name) | |||
349 | { | 357 | { |
350 | struct sdram_params *sdram; | 358 | struct sdram_params *sdram; |
351 | 359 | ||
352 | for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); sdram++) | 360 | for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); |
361 | sdram++) | ||
353 | if (strcmp(name, sdram->name) == 0) | 362 | if (strcmp(name, sdram->name) == 0) |
354 | return sdram; | 363 | return sdram; |
355 | 364 | ||
@@ -369,14 +378,14 @@ static int __init sa1110_clk_init(void) | |||
369 | if (!name[0]) { | 378 | if (!name[0]) { |
370 | if (machine_is_assabet()) | 379 | if (machine_is_assabet()) |
371 | name = "TC59SM716-CL3"; | 380 | name = "TC59SM716-CL3"; |
372 | |||
373 | if (machine_is_pt_system3()) | 381 | if (machine_is_pt_system3()) |
374 | name = "K4S641632D"; | 382 | name = "K4S641632D"; |
375 | |||
376 | if (machine_is_h3100()) | 383 | if (machine_is_h3100()) |
377 | name = "KM416S4030CT"; | 384 | name = "KM416S4030CT"; |
378 | if (machine_is_jornada720()) | 385 | if (machine_is_jornada720()) |
379 | name = "K4S281632B-1H"; | 386 | name = "K4S281632B-1H"; |
387 | if (machine_is_nanoengine()) | ||
388 | name = "MT48LC8M16A2TG-75"; | ||
380 | } | 389 | } |
381 | 390 | ||
382 | sdram = sa1110_find_sdram(name); | 391 | sdram = sa1110_find_sdram(name); |
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 3c1fcd69671..59d14f0fdcf 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c | |||
@@ -16,9 +16,7 @@ | |||
16 | #include <linux/pm.h> | 16 | #include <linux/pm.h> |
17 | #include <linux/cpufreq.h> | 17 | #include <linux/cpufreq.h> |
18 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
19 | #include <linux/sched.h> /* just for sched_clock() - funny that */ | ||
20 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
21 | #include <linux/cnt32_to_63.h> | ||
22 | 20 | ||
23 | #include <asm/div64.h> | 21 | #include <asm/div64.h> |
24 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
@@ -110,27 +108,6 @@ unsigned int sa11x0_getspeed(unsigned int cpu) | |||
110 | } | 108 | } |
111 | 109 | ||
112 | /* | 110 | /* |
113 | * This is the SA11x0 sched_clock implementation. This has | ||
114 | * a resolution of 271ns, and a maximum value of 32025597s (370 days). | ||
115 | * | ||
116 | * The return value is guaranteed to be monotonic in that range as | ||
117 | * long as there is always less than 582 seconds between successive | ||
118 | * calls to this function. | ||
119 | * | ||
120 | * ( * 1E9 / 3686400 => * 78125 / 288) | ||
121 | */ | ||
122 | unsigned long long sched_clock(void) | ||
123 | { | ||
124 | unsigned long long v = cnt32_to_63(OSCR); | ||
125 | |||
126 | /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */ | ||
127 | v *= 78125<<1; | ||
128 | do_div(v, 288<<1); | ||
129 | |||
130 | return v; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Default power-off for SA1100 | 111 | * Default power-off for SA1100 |
135 | */ | 112 | */ |
136 | static void sa1100_power_off(void) | 113 | static void sa1100_power_off(void) |
@@ -163,10 +140,15 @@ static void sa11x0_register_device(struct platform_device *dev, void *data) | |||
163 | 140 | ||
164 | static struct resource sa11x0udc_resources[] = { | 141 | static struct resource sa11x0udc_resources[] = { |
165 | [0] = { | 142 | [0] = { |
166 | .start = 0x80000000, | 143 | .start = __PREG(Ser0UDCCR), |
167 | .end = 0x8000ffff, | 144 | .end = __PREG(Ser0UDCCR) + 0xffff, |
168 | .flags = IORESOURCE_MEM, | 145 | .flags = IORESOURCE_MEM, |
169 | }, | 146 | }, |
147 | [1] = { | ||
148 | .start = IRQ_Ser0UDC, | ||
149 | .end = IRQ_Ser0UDC, | ||
150 | .flags = IORESOURCE_IRQ, | ||
151 | }, | ||
170 | }; | 152 | }; |
171 | 153 | ||
172 | static u64 sa11x0udc_dma_mask = 0xffffffffUL; | 154 | static u64 sa11x0udc_dma_mask = 0xffffffffUL; |
@@ -184,10 +166,15 @@ static struct platform_device sa11x0udc_device = { | |||
184 | 166 | ||
185 | static struct resource sa11x0uart1_resources[] = { | 167 | static struct resource sa11x0uart1_resources[] = { |
186 | [0] = { | 168 | [0] = { |
187 | .start = 0x80010000, | 169 | .start = __PREG(Ser1UTCR0), |
188 | .end = 0x8001ffff, | 170 | .end = __PREG(Ser1UTCR0) + 0xffff, |
189 | .flags = IORESOURCE_MEM, | 171 | .flags = IORESOURCE_MEM, |
190 | }, | 172 | }, |
173 | [1] = { | ||
174 | .start = IRQ_Ser1UART, | ||
175 | .end = IRQ_Ser1UART, | ||
176 | .flags = IORESOURCE_IRQ, | ||
177 | }, | ||
191 | }; | 178 | }; |
192 | 179 | ||
193 | static struct platform_device sa11x0uart1_device = { | 180 | static struct platform_device sa11x0uart1_device = { |
@@ -199,10 +186,15 @@ static struct platform_device sa11x0uart1_device = { | |||
199 | 186 | ||
200 | static struct resource sa11x0uart3_resources[] = { | 187 | static struct resource sa11x0uart3_resources[] = { |
201 | [0] = { | 188 | [0] = { |
202 | .start = 0x80050000, | 189 | .start = __PREG(Ser3UTCR0), |
203 | .end = 0x8005ffff, | 190 | .end = __PREG(Ser3UTCR0) + 0xffff, |
204 | .flags = IORESOURCE_MEM, | 191 | .flags = IORESOURCE_MEM, |
205 | }, | 192 | }, |
193 | [1] = { | ||
194 | .start = IRQ_Ser3UART, | ||
195 | .end = IRQ_Ser3UART, | ||
196 | .flags = IORESOURCE_IRQ, | ||
197 | }, | ||
206 | }; | 198 | }; |
207 | 199 | ||
208 | static struct platform_device sa11x0uart3_device = { | 200 | static struct platform_device sa11x0uart3_device = { |
@@ -214,10 +206,15 @@ static struct platform_device sa11x0uart3_device = { | |||
214 | 206 | ||
215 | static struct resource sa11x0mcp_resources[] = { | 207 | static struct resource sa11x0mcp_resources[] = { |
216 | [0] = { | 208 | [0] = { |
217 | .start = 0x80060000, | 209 | .start = __PREG(Ser4MCCR0), |
218 | .end = 0x8006ffff, | 210 | .end = __PREG(Ser4MCCR0) + 0xffff, |
219 | .flags = IORESOURCE_MEM, | 211 | .flags = IORESOURCE_MEM, |
220 | }, | 212 | }, |
213 | [1] = { | ||
214 | .start = IRQ_Ser4MCP, | ||
215 | .end = IRQ_Ser4MCP, | ||
216 | .flags = IORESOURCE_IRQ, | ||
217 | }, | ||
221 | }; | 218 | }; |
222 | 219 | ||
223 | static u64 sa11x0mcp_dma_mask = 0xffffffffUL; | 220 | static u64 sa11x0mcp_dma_mask = 0xffffffffUL; |
@@ -244,6 +241,11 @@ static struct resource sa11x0ssp_resources[] = { | |||
244 | .end = 0x8007ffff, | 241 | .end = 0x8007ffff, |
245 | .flags = IORESOURCE_MEM, | 242 | .flags = IORESOURCE_MEM, |
246 | }, | 243 | }, |
244 | [1] = { | ||
245 | .start = IRQ_Ser4SSP, | ||
246 | .end = IRQ_Ser4SSP, | ||
247 | .flags = IORESOURCE_IRQ, | ||
248 | }, | ||
247 | }; | 249 | }; |
248 | 250 | ||
249 | static u64 sa11x0ssp_dma_mask = 0xffffffffUL; | 251 | static u64 sa11x0ssp_dma_mask = 0xffffffffUL; |
diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h index 99f5856d8de..967ae768439 100644 --- a/arch/arm/mach-sa1100/include/mach/hardware.h +++ b/arch/arm/mach-sa1100/include/mach/hardware.h | |||
@@ -76,4 +76,12 @@ static inline unsigned long get_clock_tick_rate(void) | |||
76 | #include "SA-1101.h" | 76 | #include "SA-1101.h" |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | #if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI) | ||
80 | #define PCIBIOS_MIN_IO 0 | ||
81 | #define PCIBIOS_MIN_MEM 0 | ||
82 | #define pcibios_assign_all_busses() 1 | ||
83 | #define HAVE_ARCH_PCI_SET_DMA_MASK 1 | ||
84 | #endif | ||
85 | |||
86 | |||
79 | #endif /* _ASM_ARCH_HARDWARE_H */ | 87 | #endif /* _ASM_ARCH_HARDWARE_H */ |
diff --git a/arch/arm/mach-sa1100/include/mach/nanoengine.h b/arch/arm/mach-sa1100/include/mach/nanoengine.h new file mode 100644 index 00000000000..14f8382d066 --- /dev/null +++ b/arch/arm/mach-sa1100/include/mach/nanoengine.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-sa1100/include/mach/nanoengine.h | ||
3 | * | ||
4 | * This file contains the hardware specific definitions for nanoEngine. | ||
5 | * Only include this file from SA1100-specific files. | ||
6 | * | ||
7 | * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | #ifndef __ASM_ARCH_NANOENGINE_H | ||
15 | #define __ASM_ARCH_NANOENGINE_H | ||
16 | |||
17 | #include <mach/irqs.h> | ||
18 | |||
19 | #define GPIO_PC_READY0 GPIO_GPIO(11) /* ready for socket 0 (active high)*/ | ||
20 | #define GPIO_PC_READY1 GPIO_GPIO(12) /* ready for socket 1 (active high) */ | ||
21 | #define GPIO_PC_CD0 GPIO_GPIO(13) /* detect for socket 0 (active low) */ | ||
22 | #define GPIO_PC_CD1 GPIO_GPIO(14) /* detect for socket 1 (active low) */ | ||
23 | #define GPIO_PC_RESET0 GPIO_GPIO(15) /* reset socket 0 */ | ||
24 | #define GPIO_PC_RESET1 GPIO_GPIO(16) /* reset socket 1 */ | ||
25 | |||
26 | #define NANOENGINE_IRQ_GPIO_PCI IRQ_GPIO0 | ||
27 | #define NANOENGINE_IRQ_GPIO_PC_READY0 IRQ_GPIO11 | ||
28 | #define NANOENGINE_IRQ_GPIO_PC_READY1 IRQ_GPIO12 | ||
29 | #define NANOENGINE_IRQ_GPIO_PC_CD0 IRQ_GPIO13 | ||
30 | #define NANOENGINE_IRQ_GPIO_PC_CD1 IRQ_GPIO14 | ||
31 | |||
32 | /* | ||
33 | * nanoEngine Memory Map: | ||
34 | * | ||
35 | * 0000.0000 - 003F.0000 - 4 MB Flash | ||
36 | * C000.0000 - C1FF.FFFF - 32 MB SDRAM | ||
37 | * 1860.0000 - 186F.FFFF - 1 MB Internal PCI Memory Read/Write | ||
38 | * 18A1.0000 - 18A1.FFFF - 64 KB Internal PCI Config Space | ||
39 | * 4000.0000 - 47FF.FFFF - 128 MB External Bus I/O - Multiplexed Mode | ||
40 | * 4800.0000 - 4FFF.FFFF - 128 MB External Bus I/O - Non-Multiplexed Mode | ||
41 | * | ||
42 | */ | ||
43 | |||
44 | #define NANO_PCI_MEM_RW_PHYS 0x18600000 | ||
45 | #define NANO_PCI_MEM_RW_VIRT 0xf1000000 | ||
46 | #define NANO_PCI_MEM_RW_SIZE SZ_1M | ||
47 | #define NANO_PCI_CONFIG_SPACE_PHYS 0x18A10000 | ||
48 | #define NANO_PCI_CONFIG_SPACE_VIRT 0xf2000000 | ||
49 | #define NANO_PCI_CONFIG_SPACE_SIZE SZ_64K | ||
50 | |||
51 | #endif | ||
52 | |||
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c new file mode 100644 index 00000000000..72087f0658b --- /dev/null +++ b/arch/arm/mach-sa1100/nanoengine.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-sa1100/nanoengine.c | ||
3 | * | ||
4 | * Bright Star Engineering's nanoEngine board init code. | ||
5 | * | ||
6 | * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br> | ||
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 version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/mtd/mtd.h> | ||
17 | #include <linux/mtd/partitions.h> | ||
18 | #include <linux/root_dev.h> | ||
19 | |||
20 | #include <asm/mach-types.h> | ||
21 | #include <asm/setup.h> | ||
22 | |||
23 | #include <asm/mach/arch.h> | ||
24 | #include <asm/mach/flash.h> | ||
25 | #include <asm/mach/map.h> | ||
26 | #include <asm/mach/serial_sa1100.h> | ||
27 | |||
28 | #include <mach/hardware.h> | ||
29 | #include <mach/nanoengine.h> | ||
30 | |||
31 | #include "generic.h" | ||
32 | |||
33 | /* Flash bank 0 */ | ||
34 | static struct mtd_partition nanoengine_partitions[] = { | ||
35 | { | ||
36 | .name = "nanoEngine boot firmware and parameter table", | ||
37 | .size = 0x00010000, /* 32K */ | ||
38 | .offset = 0, | ||
39 | .mask_flags = MTD_WRITEABLE, | ||
40 | }, { | ||
41 | .name = "kernel/initrd reserved", | ||
42 | .size = 0x002f0000, | ||
43 | .offset = 0x00010000, | ||
44 | .mask_flags = MTD_WRITEABLE, | ||
45 | }, { | ||
46 | .name = "experimental filesystem allocation", | ||
47 | .size = 0x00100000, | ||
48 | .offset = 0x00300000, | ||
49 | .mask_flags = MTD_WRITEABLE, | ||
50 | } | ||
51 | }; | ||
52 | |||
53 | static struct flash_platform_data nanoengine_flash_data = { | ||
54 | .map_name = "jedec_probe", | ||
55 | .parts = nanoengine_partitions, | ||
56 | .nr_parts = ARRAY_SIZE(nanoengine_partitions), | ||
57 | }; | ||
58 | |||
59 | static struct resource nanoengine_flash_resources[] = { | ||
60 | { | ||
61 | .start = SA1100_CS0_PHYS, | ||
62 | .end = SA1100_CS0_PHYS + SZ_32M - 1, | ||
63 | .flags = IORESOURCE_MEM, | ||
64 | }, { | ||
65 | .start = SA1100_CS1_PHYS, | ||
66 | .end = SA1100_CS1_PHYS + SZ_32M - 1, | ||
67 | .flags = IORESOURCE_MEM, | ||
68 | } | ||
69 | }; | ||
70 | |||
71 | static struct map_desc nanoengine_io_desc[] __initdata = { | ||
72 | { | ||
73 | /* System Registers */ | ||
74 | .virtual = 0xf0000000, | ||
75 | .pfn = __phys_to_pfn(0x10000000), | ||
76 | .length = 0x00100000, | ||
77 | .type = MT_DEVICE | ||
78 | }, { | ||
79 | /* Internal PCI Memory Read/Write */ | ||
80 | .virtual = NANO_PCI_MEM_RW_VIRT, | ||
81 | .pfn = __phys_to_pfn(NANO_PCI_MEM_RW_PHYS), | ||
82 | .length = NANO_PCI_MEM_RW_SIZE, | ||
83 | .type = MT_DEVICE | ||
84 | }, { | ||
85 | /* Internal PCI Config Space */ | ||
86 | .virtual = NANO_PCI_CONFIG_SPACE_VIRT, | ||
87 | .pfn = __phys_to_pfn(NANO_PCI_CONFIG_SPACE_PHYS), | ||
88 | .length = NANO_PCI_CONFIG_SPACE_SIZE, | ||
89 | .type = MT_DEVICE | ||
90 | } | ||
91 | }; | ||
92 | |||
93 | static void __init nanoengine_map_io(void) | ||
94 | { | ||
95 | sa1100_map_io(); | ||
96 | iotable_init(nanoengine_io_desc, ARRAY_SIZE(nanoengine_io_desc)); | ||
97 | |||
98 | sa1100_register_uart(0, 1); | ||
99 | sa1100_register_uart(1, 2); | ||
100 | sa1100_register_uart(2, 3); | ||
101 | Ser1SDCR0 |= SDCR0_UART; | ||
102 | /* disable IRDA -- UART2 is used as a normal serial port */ | ||
103 | Ser2UTCR4 = 0; | ||
104 | Ser2HSCR0 = 0; | ||
105 | } | ||
106 | |||
107 | static void __init nanoengine_init(void) | ||
108 | { | ||
109 | sa11x0_register_mtd(&nanoengine_flash_data, nanoengine_flash_resources, | ||
110 | ARRAY_SIZE(nanoengine_flash_resources)); | ||
111 | } | ||
112 | |||
113 | MACHINE_START(NANOENGINE, "BSE nanoEngine") | ||
114 | .boot_params = 0xc0000000, | ||
115 | .map_io = nanoengine_map_io, | ||
116 | .init_irq = sa1100_init_irq, | ||
117 | .timer = &sa1100_timer, | ||
118 | .init_machine = nanoengine_init, | ||
119 | MACHINE_END | ||
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c new file mode 100644 index 00000000000..fba7a913f12 --- /dev/null +++ b/arch/arm/mach-sa1100/pci-nanoengine.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-sa1100/pci-nanoengine.c | ||
3 | * | ||
4 | * PCI functions for BSE nanoEngine PCI | ||
5 | * | ||
6 | * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br> | ||
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, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/irq.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | |||
27 | #include <asm/mach/pci.h> | ||
28 | #include <asm/mach-types.h> | ||
29 | |||
30 | #include <mach/nanoengine.h> | ||
31 | |||
32 | static DEFINE_SPINLOCK(nano_lock); | ||
33 | |||
34 | static int nanoengine_get_pci_address(struct pci_bus *bus, | ||
35 | unsigned int devfn, int where, unsigned long *address) | ||
36 | { | ||
37 | int ret = PCIBIOS_DEVICE_NOT_FOUND; | ||
38 | unsigned int busnr = bus->number; | ||
39 | |||
40 | *address = NANO_PCI_CONFIG_SPACE_VIRT + | ||
41 | ((bus->number << 16) | (devfn << 8) | (where & ~3)); | ||
42 | |||
43 | ret = (busnr > 255 || devfn > 255 || where > 255) ? | ||
44 | PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
45 | |||
46 | return ret; | ||
47 | } | ||
48 | |||
49 | static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
50 | int size, u32 *val) | ||
51 | { | ||
52 | int ret; | ||
53 | unsigned long address; | ||
54 | unsigned long flags; | ||
55 | u32 v; | ||
56 | |||
57 | /* nanoEngine PCI bridge does not return -1 for a non-existing | ||
58 | * device. We must fake the answer. We know that the only valid | ||
59 | * device is device zero at bus 0, which is the network chip. */ | ||
60 | if (bus->number != 0 || (devfn >> 3) != 0) { | ||
61 | v = -1; | ||
62 | nanoengine_get_pci_address(bus, devfn, where, &address); | ||
63 | goto exit_function; | ||
64 | } | ||
65 | |||
66 | spin_lock_irqsave(&nano_lock, flags); | ||
67 | |||
68 | ret = nanoengine_get_pci_address(bus, devfn, where, &address); | ||
69 | if (ret != PCIBIOS_SUCCESSFUL) | ||
70 | return ret; | ||
71 | v = __raw_readl(address); | ||
72 | |||
73 | spin_unlock_irqrestore(&nano_lock, flags); | ||
74 | |||
75 | v >>= ((where & 3) * 8); | ||
76 | v &= (unsigned long)(-1) >> ((4 - size) * 8); | ||
77 | |||
78 | exit_function: | ||
79 | *val = v; | ||
80 | return PCIBIOS_SUCCESSFUL; | ||
81 | } | ||
82 | |||
83 | static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
84 | int size, u32 val) | ||
85 | { | ||
86 | int ret; | ||
87 | unsigned long address; | ||
88 | unsigned long flags; | ||
89 | unsigned shift; | ||
90 | u32 v; | ||
91 | |||
92 | shift = (where & 3) * 8; | ||
93 | |||
94 | spin_lock_irqsave(&nano_lock, flags); | ||
95 | |||
96 | ret = nanoengine_get_pci_address(bus, devfn, where, &address); | ||
97 | if (ret != PCIBIOS_SUCCESSFUL) | ||
98 | return ret; | ||
99 | v = __raw_readl(address); | ||
100 | switch (size) { | ||
101 | case 1: | ||
102 | v &= ~(0xFF << shift); | ||
103 | v |= val << shift; | ||
104 | break; | ||
105 | case 2: | ||
106 | v &= ~(0xFFFF << shift); | ||
107 | v |= val << shift; | ||
108 | break; | ||
109 | case 4: | ||
110 | v = val; | ||
111 | break; | ||
112 | } | ||
113 | __raw_writel(v, address); | ||
114 | |||
115 | spin_unlock_irqrestore(&nano_lock, flags); | ||
116 | |||
117 | return PCIBIOS_SUCCESSFUL; | ||
118 | } | ||
119 | |||
120 | static struct pci_ops pci_nano_ops = { | ||
121 | .read = nanoengine_read_config, | ||
122 | .write = nanoengine_write_config, | ||
123 | }; | ||
124 | |||
125 | static int __init pci_nanoengine_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
126 | { | ||
127 | return NANOENGINE_IRQ_GPIO_PCI; | ||
128 | } | ||
129 | |||
130 | struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys) | ||
131 | { | ||
132 | return pci_scan_bus(sys->busnr, &pci_nano_ops, sys); | ||
133 | } | ||
134 | |||
135 | static struct resource pci_io_ports = { | ||
136 | .name = "PCI IO", | ||
137 | .start = 0x400, | ||
138 | .end = 0x7FF, | ||
139 | .flags = IORESOURCE_IO, | ||
140 | }; | ||
141 | |||
142 | static struct resource pci_non_prefetchable_memory = { | ||
143 | .name = "PCI non-prefetchable", | ||
144 | .start = NANO_PCI_MEM_RW_PHYS, | ||
145 | /* nanoEngine documentation says there is a 1 Megabyte window here, | ||
146 | * but PCI reports just 128 + 8 kbytes. */ | ||
147 | .end = NANO_PCI_MEM_RW_PHYS + NANO_PCI_MEM_RW_SIZE - 1, | ||
148 | /* .end = NANO_PCI_MEM_RW_PHYS + SZ_128K + SZ_8K - 1,*/ | ||
149 | .flags = IORESOURCE_MEM, | ||
150 | }; | ||
151 | |||
152 | /* | ||
153 | * nanoEngine PCI reports 1 Megabyte of prefetchable memory, but it | ||
154 | * overlaps with previously defined memory. | ||
155 | * | ||
156 | * Here is what happens: | ||
157 | * | ||
158 | # dmesg | ||
159 | ... | ||
160 | pci 0000:00:00.0: [8086:1209] type 0 class 0x000200 | ||
161 | pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff] | ||
162 | pci 0000:00:00.0: reg 14: [io 0x0000-0x003f] | ||
163 | pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff] | ||
164 | pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref] | ||
165 | pci 0000:00:00.0: supports D1 D2 | ||
166 | pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot | ||
167 | pci 0000:00:00.0: PME# disabled | ||
168 | PCI: bus0: Fast back to back transfers enabled | ||
169 | pci 0000:00:00.0: BAR 6: can't assign mem pref (size 0x100000) | ||
170 | pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff] | ||
171 | pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff]) | ||
172 | pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff] | ||
173 | pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff]) | ||
174 | pci 0000:00:00.0: BAR 1: assigned [io 0x0400-0x043f] | ||
175 | pci 0000:00:00.0: BAR 1: set to [io 0x0400-0x043f] (PCI address [0x0-0x3f]) | ||
176 | * | ||
177 | * On the other hand, if we do not request the prefetchable memory resource, | ||
178 | * linux will alloc it first and the two non-prefetchable memory areas that | ||
179 | * are our real interest will not be mapped. So we choose to map it to an | ||
180 | * unused area. It gets recognized as expansion ROM, but becomes disabled. | ||
181 | * | ||
182 | * Here is what happens then: | ||
183 | * | ||
184 | # dmesg | ||
185 | ... | ||
186 | pci 0000:00:00.0: [8086:1209] type 0 class 0x000200 | ||
187 | pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff] | ||
188 | pci 0000:00:00.0: reg 14: [io 0x0000-0x003f] | ||
189 | pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff] | ||
190 | pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref] | ||
191 | pci 0000:00:00.0: supports D1 D2 | ||
192 | pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot | ||
193 | pci 0000:00:00.0: PME# disabled | ||
194 | PCI: bus0: Fast back to back transfers enabled | ||
195 | pci 0000:00:00.0: BAR 6: assigned [mem 0x78000000-0x780fffff pref] | ||
196 | pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff] | ||
197 | pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff]) | ||
198 | pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff] | ||
199 | pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff]) | ||
200 | pci 0000:00:00.0: BAR 1: assigned [io 0x0400-0x043f] | ||
201 | pci 0000:00:00.0: BAR 1: set to [io 0x0400-0x043f] (PCI address [0x0-0x3f]) | ||
202 | |||
203 | # lspci -vv -s 0000:00:00.0 | ||
204 | 00:00.0 Class 0200: Device 8086:1209 (rev 09) | ||
205 | Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx- | ||
206 | Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR+ <PERR+ INTx- | ||
207 | Latency: 0 (2000ns min, 14000ns max), Cache Line Size: 32 bytes | ||
208 | Interrupt: pin A routed to IRQ 0 | ||
209 | Region 0: Memory at 18620000 (32-bit, non-prefetchable) [size=4K] | ||
210 | Region 1: I/O ports at 0400 [size=64] | ||
211 | Region 2: [virtual] Memory at 18600000 (32-bit, non-prefetchable) [size=128K] | ||
212 | [virtual] Expansion ROM at 78000000 [disabled] [size=1M] | ||
213 | Capabilities: [dc] Power Management version 2 | ||
214 | Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-) | ||
215 | Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME- | ||
216 | Kernel driver in use: e100 | ||
217 | Kernel modules: e100 | ||
218 | * | ||
219 | */ | ||
220 | static struct resource pci_prefetchable_memory = { | ||
221 | .name = "PCI prefetchable", | ||
222 | .start = 0x78000000, | ||
223 | .end = 0x78000000 + NANO_PCI_MEM_RW_SIZE - 1, | ||
224 | .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH, | ||
225 | }; | ||
226 | |||
227 | static int __init pci_nanoengine_setup_resources(struct resource **resource) | ||
228 | { | ||
229 | if (request_resource(&ioport_resource, &pci_io_ports)) { | ||
230 | printk(KERN_ERR "PCI: unable to allocate io port region\n"); | ||
231 | return -EBUSY; | ||
232 | } | ||
233 | if (request_resource(&iomem_resource, &pci_non_prefetchable_memory)) { | ||
234 | release_resource(&pci_io_ports); | ||
235 | printk(KERN_ERR "PCI: unable to allocate non prefetchable\n"); | ||
236 | return -EBUSY; | ||
237 | } | ||
238 | if (request_resource(&iomem_resource, &pci_prefetchable_memory)) { | ||
239 | release_resource(&pci_io_ports); | ||
240 | release_resource(&pci_non_prefetchable_memory); | ||
241 | printk(KERN_ERR "PCI: unable to allocate prefetchable\n"); | ||
242 | return -EBUSY; | ||
243 | } | ||
244 | resource[0] = &pci_io_ports; | ||
245 | resource[1] = &pci_non_prefetchable_memory; | ||
246 | resource[2] = &pci_prefetchable_memory; | ||
247 | |||
248 | return 1; | ||
249 | } | ||
250 | |||
251 | int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys) | ||
252 | { | ||
253 | int ret = 0; | ||
254 | |||
255 | if (nr == 0) { | ||
256 | sys->mem_offset = NANO_PCI_MEM_RW_PHYS; | ||
257 | sys->io_offset = 0x400; | ||
258 | ret = pci_nanoengine_setup_resources(sys->resource); | ||
259 | /* Enable alternate memory bus master mode, see | ||
260 | * "Intel StrongARM SA1110 Developer's Manual", | ||
261 | * section 10.8, "Alternate Memory Bus Master Mode". */ | ||
262 | GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT; | ||
263 | GAFR |= GPIO_MBGNT | GPIO_MBREQ; | ||
264 | TUCR |= TUCR_MBGPIO; | ||
265 | } | ||
266 | |||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | static struct hw_pci nanoengine_pci __initdata = { | ||
271 | .map_irq = pci_nanoengine_map_irq, | ||
272 | .nr_controllers = 1, | ||
273 | .scan = pci_nanoengine_scan_bus, | ||
274 | .setup = pci_nanoengine_setup, | ||
275 | }; | ||
276 | |||
277 | static int __init nanoengine_pci_init(void) | ||
278 | { | ||
279 | if (machine_is_nanoengine()) | ||
280 | pci_common_init(&nanoengine_pci); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | subsys_initcall(nanoengine_pci_init); | ||
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 27692d0ffbe..cfb76077bd2 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c | |||
@@ -166,9 +166,6 @@ static void __init simpad_map_io(void) | |||
166 | PCFR = 0; | 166 | PCFR = 0; |
167 | PSDR = 0; | 167 | PSDR = 0; |
168 | 168 | ||
169 | sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, | ||
170 | ARRAY_SIZE(simpad_flash_resources)); | ||
171 | sa11x0_register_mcp(&simpad_mcp_data); | ||
172 | } | 169 | } |
173 | 170 | ||
174 | static void simpad_power_off(void) | 171 | static void simpad_power_off(void) |
@@ -216,6 +213,10 @@ static int __init simpad_init(void) | |||
216 | 213 | ||
217 | pm_power_off = simpad_power_off; | 214 | pm_power_off = simpad_power_off; |
218 | 215 | ||
216 | sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, | ||
217 | ARRAY_SIZE(simpad_flash_resources)); | ||
218 | sa11x0_register_mcp(&simpad_mcp_data); | ||
219 | |||
219 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); | 220 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); |
220 | if(ret) | 221 | if(ret) |
221 | printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device"); | 222 | printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device"); |
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 74b6e0e570b..ae4f3d80416 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c | |||
@@ -12,12 +12,39 @@ | |||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
15 | #include <linux/sched.h> /* just for sched_clock() - funny that */ | ||
15 | #include <linux/timex.h> | 16 | #include <linux/timex.h> |
16 | #include <linux/clockchips.h> | 17 | #include <linux/clockchips.h> |
17 | 18 | ||
18 | #include <asm/mach/time.h> | 19 | #include <asm/mach/time.h> |
20 | #include <asm/sched_clock.h> | ||
19 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
20 | 22 | ||
23 | /* | ||
24 | * This is the SA11x0 sched_clock implementation. | ||
25 | */ | ||
26 | static DEFINE_CLOCK_DATA(cd); | ||
27 | |||
28 | /* | ||
29 | * Constants generated by clocks_calc_mult_shift(m, s, 3.6864MHz, | ||
30 | * NSEC_PER_SEC, 60). | ||
31 | * This gives a resolution of about 271ns and a wrap period of about 19min. | ||
32 | */ | ||
33 | #define SC_MULT 2275555556u | ||
34 | #define SC_SHIFT 23 | ||
35 | |||
36 | unsigned long long notrace sched_clock(void) | ||
37 | { | ||
38 | u32 cyc = OSCR; | ||
39 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | ||
40 | } | ||
41 | |||
42 | static void notrace sa1100_update_sched_clock(void) | ||
43 | { | ||
44 | u32 cyc = OSCR; | ||
45 | update_sched_clock(&cd, cyc, (u32)~0); | ||
46 | } | ||
47 | |||
21 | #define MIN_OSCR_DELTA 2 | 48 | #define MIN_OSCR_DELTA 2 |
22 | 49 | ||
23 | static irqreturn_t sa1100_ost0_interrupt(int irq, void *dev_id) | 50 | static irqreturn_t sa1100_ost0_interrupt(int irq, void *dev_id) |
@@ -81,7 +108,6 @@ static struct clocksource cksrc_sa1100_oscr = { | |||
81 | .rating = 200, | 108 | .rating = 200, |
82 | .read = sa1100_read_oscr, | 109 | .read = sa1100_read_oscr, |
83 | .mask = CLOCKSOURCE_MASK(32), | 110 | .mask = CLOCKSOURCE_MASK(32), |
84 | .shift = 20, | ||
85 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 111 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
86 | }; | 112 | }; |
87 | 113 | ||
@@ -97,6 +123,9 @@ static void __init sa1100_timer_init(void) | |||
97 | OIER = 0; /* disable any timer interrupts */ | 123 | OIER = 0; /* disable any timer interrupts */ |
98 | OSSR = 0xf; /* clear status on all timers */ | 124 | OSSR = 0xf; /* clear status on all timers */ |
99 | 125 | ||
126 | init_fixed_sched_clock(&cd, sa1100_update_sched_clock, 32, | ||
127 | 3686400, SC_MULT, SC_SHIFT); | ||
128 | |||
100 | ckevt_sa1100_osmr0.mult = | 129 | ckevt_sa1100_osmr0.mult = |
101 | div_sc(3686400, NSEC_PER_SEC, ckevt_sa1100_osmr0.shift); | 130 | div_sc(3686400, NSEC_PER_SEC, ckevt_sa1100_osmr0.shift); |
102 | ckevt_sa1100_osmr0.max_delta_ns = | 131 | ckevt_sa1100_osmr0.max_delta_ns = |
@@ -105,12 +134,9 @@ static void __init sa1100_timer_init(void) | |||
105 | clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1; | 134 | clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1; |
106 | ckevt_sa1100_osmr0.cpumask = cpumask_of(0); | 135 | ckevt_sa1100_osmr0.cpumask = cpumask_of(0); |
107 | 136 | ||
108 | cksrc_sa1100_oscr.mult = | ||
109 | clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_sa1100_oscr.shift); | ||
110 | |||
111 | setup_irq(IRQ_OST0, &sa1100_timer_irq); | 137 | setup_irq(IRQ_OST0, &sa1100_timer_irq); |
112 | 138 | ||
113 | clocksource_register(&cksrc_sa1100_oscr); | 139 | clocksource_register_hz(&cksrc_sa1100_oscr, CLOCK_TICK_RATE); |
114 | clockevents_register_device(&ckevt_sa1100_osmr0); | 140 | clockevents_register_device(&ckevt_sa1100_osmr0); |
115 | } | 141 | } |
116 | 142 | ||
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 51dcd59eda6..63293335724 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig | |||
@@ -6,7 +6,7 @@ config ARCH_SH7367 | |||
6 | bool "SH-Mobile G3 (SH7367)" | 6 | bool "SH-Mobile G3 (SH7367)" |
7 | select CPU_V6 | 7 | select CPU_V6 |
8 | select HAVE_CLK | 8 | select HAVE_CLK |
9 | select COMMON_CLKDEV | 9 | select CLKDEV_LOOKUP |
10 | select SH_CLK_CPG | 10 | select SH_CLK_CPG |
11 | select GENERIC_CLOCKEVENTS | 11 | select GENERIC_CLOCKEVENTS |
12 | 12 | ||
@@ -14,7 +14,7 @@ config ARCH_SH7377 | |||
14 | bool "SH-Mobile G4 (SH7377)" | 14 | bool "SH-Mobile G4 (SH7377)" |
15 | select CPU_V7 | 15 | select CPU_V7 |
16 | select HAVE_CLK | 16 | select HAVE_CLK |
17 | select COMMON_CLKDEV | 17 | select CLKDEV_LOOKUP |
18 | select SH_CLK_CPG | 18 | select SH_CLK_CPG |
19 | select GENERIC_CLOCKEVENTS | 19 | select GENERIC_CLOCKEVENTS |
20 | 20 | ||
@@ -22,7 +22,7 @@ config ARCH_SH7372 | |||
22 | bool "SH-Mobile AP4 (SH7372)" | 22 | bool "SH-Mobile AP4 (SH7372)" |
23 | select CPU_V7 | 23 | select CPU_V7 |
24 | select HAVE_CLK | 24 | select HAVE_CLK |
25 | select COMMON_CLKDEV | 25 | select CLKDEV_LOOKUP |
26 | select SH_CLK_CPG | 26 | select SH_CLK_CPG |
27 | select GENERIC_CLOCKEVENTS | 27 | select GENERIC_CLOCKEVENTS |
28 | 28 | ||
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index d440e5f456a..ac429ff2c20 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <asm/mach/arch.h> | 61 | #include <asm/mach/arch.h> |
62 | #include <asm/mach/map.h> | 62 | #include <asm/mach/map.h> |
63 | #include <asm/mach/time.h> | 63 | #include <asm/mach/time.h> |
64 | #include <asm/setup.h> | ||
64 | 65 | ||
65 | /* | 66 | /* |
66 | * Address Interface BusWidth note | 67 | * Address Interface BusWidth note |
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c index 9f78729098f..6b186aefcbd 100644 --- a/arch/arm/mach-shmobile/clock-sh7367.c +++ b/arch/arm/mach-shmobile/clock-sh7367.c | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/sh_clk.h> | 22 | #include <linux/sh_clk.h> |
23 | #include <linux/clkdev.h> | ||
23 | #include <mach/common.h> | 24 | #include <mach/common.h> |
24 | #include <asm/clkdev.h> | ||
25 | 25 | ||
26 | /* SH7367 registers */ | 26 | /* SH7367 registers */ |
27 | #define RTFRQCR 0xe6150000 | 27 | #define RTFRQCR 0xe6150000 |
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 3aa02606943..d98deb497c2 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/sh_clk.h> | 22 | #include <linux/sh_clk.h> |
23 | #include <linux/clkdev.h> | ||
23 | #include <mach/common.h> | 24 | #include <mach/common.h> |
24 | #include <asm/clkdev.h> | ||
25 | 25 | ||
26 | /* SH7372 registers */ | 26 | /* SH7372 registers */ |
27 | #define FRQCRA 0xe6150000 | 27 | #define FRQCRA 0xe6150000 |
diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c index f91395aeb9a..95942466e63 100644 --- a/arch/arm/mach-shmobile/clock-sh7377.c +++ b/arch/arm/mach-shmobile/clock-sh7377.c | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/sh_clk.h> | 22 | #include <linux/sh_clk.h> |
23 | #include <linux/clkdev.h> | ||
23 | #include <mach/common.h> | 24 | #include <mach/common.h> |
24 | #include <asm/clkdev.h> | ||
25 | 25 | ||
26 | /* SH7377 registers */ | 26 | /* SH7377 registers */ |
27 | #define RTFRQCR 0xe6150000 | 27 | #define RTFRQCR 0xe6150000 |
diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S index a285d13c741..f428c4db2b6 100644 --- a/arch/arm/mach-shmobile/include/mach/entry-macro.S +++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2010 Magnus Damm | ||
2 | * Copyright (C) 2008 Renesas Solutions Corp. | 3 | * Copyright (C) 2008 Renesas Solutions Corp. |
3 | * | 4 | * |
4 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
@@ -14,24 +15,45 @@ | |||
14 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
15 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
16 | */ | 17 | */ |
17 | #include <mach/hardware.h> | ||
18 | #include <mach/irqs.h> | 18 | #include <mach/irqs.h> |
19 | 19 | ||
20 | #define INTCA_BASE 0xe6980000 | ||
21 | #define INTFLGA_OFFS 0x00000018 /* accept pending interrupt */ | ||
22 | #define INTEVTA_OFFS 0x00000020 /* vector number of accepted interrupt */ | ||
23 | #define INTLVLA_OFFS 0x00000030 /* priority level of accepted interrupt */ | ||
24 | #define INTLVLB_OFFS 0x00000034 /* previous priority level */ | ||
25 | |||
20 | .macro disable_fiq | 26 | .macro disable_fiq |
21 | .endm | 27 | .endm |
22 | 28 | ||
23 | .macro get_irqnr_preamble, base, tmp | 29 | .macro get_irqnr_preamble, base, tmp |
24 | ldr \base, =INTFLGA | 30 | ldr \base, =INTCA_BASE |
25 | .endm | 31 | .endm |
26 | 32 | ||
27 | .macro arch_ret_to_user, tmp1, tmp2 | 33 | .macro arch_ret_to_user, tmp1, tmp2 |
28 | .endm | 34 | .endm |
29 | 35 | ||
30 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | 36 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp |
31 | ldr \irqnr, [\base] | 37 | /* The single INTFLGA read access below results in the following: |
38 | * | ||
39 | * 1. INTLVLB is updated with old priority value from INTLVLA | ||
40 | * 2. Highest priority interrupt is accepted | ||
41 | * 3. INTLVLA is updated to contain priority of accepted interrupt | ||
42 | * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA | ||
43 | */ | ||
44 | ldr \irqnr, [\base, #INTFLGA_OFFS] | ||
45 | |||
46 | /* Restore INTLVLA with the value saved in INTLVLB. | ||
47 | * This is required to support interrupt priorities properly. | ||
48 | */ | ||
49 | ldrb \tmp, [\base, #INTLVLB_OFFS] | ||
50 | strb \tmp, [\base, #INTLVLA_OFFS] | ||
51 | |||
52 | /* Handle invalid vector number case */ | ||
32 | cmp \irqnr, #0 | 53 | cmp \irqnr, #0 |
33 | beq 1000f | 54 | beq 1000f |
34 | /* intevt to irq number */ | 55 | |
56 | /* Convert vector to irq number, same as the evt2irq() macro */ | ||
35 | lsr \irqnr, \irqnr, #0x5 | 57 | lsr \irqnr, \irqnr, #0x5 |
36 | subs \irqnr, \irqnr, #16 | 58 | subs \irqnr, \irqnr, #16 |
37 | 59 | ||
diff --git a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt new file mode 100644 index 00000000000..e3ebfa73956 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt | |||
@@ -0,0 +1,87 @@ | |||
1 | LIST "partner-jet-setup.txt" | ||
2 | LIST "(C) Copyright 2010 Renesas Solutions Corp" | ||
3 | LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>" | ||
4 | |||
5 | LIST "RWT Setting" | ||
6 | EW 0xE6020004, 0xA500 | ||
7 | EW 0xE6030004, 0xA500 | ||
8 | |||
9 | DD 0x01001000, 0x01001000 | ||
10 | |||
11 | LIST "GPIO Setting" | ||
12 | EB 0xE6051013, 0xA2 | ||
13 | |||
14 | LIST "CPG" | ||
15 | ED 0xE6150080, 0x00000180 | ||
16 | ED 0xE61500C0, 0x00000002 | ||
17 | |||
18 | WAIT 1, 0xFE40009C | ||
19 | |||
20 | LIST "FRQCR" | ||
21 | ED 0xE6150000, 0x2D1305C3 | ||
22 | ED 0xE61500E0, 0x9E40358E | ||
23 | ED 0xE6150004, 0x80331050 | ||
24 | |||
25 | WAIT 1, 0xFE40009C | ||
26 | |||
27 | ED 0xE61500E4, 0x00002000 | ||
28 | |||
29 | WAIT 1, 0xFE40009C | ||
30 | |||
31 | LIST "PLL" | ||
32 | ED 0xE6150028, 0x00004000 | ||
33 | |||
34 | WAIT 1, 0xFE40009C | ||
35 | |||
36 | ED 0xE615002C, 0x93000040 | ||
37 | |||
38 | WAIT 1, 0xFE40009C | ||
39 | |||
40 | LIST "BSC" | ||
41 | ED 0xFEC10000, 0x00E0001B | ||
42 | |||
43 | LIST "SBSC1" | ||
44 | ED 0xFE400354, 0x01AD8000 | ||
45 | ED 0xFE400354, 0x01AD8001 | ||
46 | |||
47 | WAIT 5, 0xFE40009C | ||
48 | |||
49 | ED 0xFE400008, 0xBCC90151 | ||
50 | ED 0xFE400040, 0x41774113 | ||
51 | ED 0xFE400044, 0x2712E229 | ||
52 | ED 0xFE400048, 0x20C18505 | ||
53 | ED 0xFE40004C, 0x00110209 | ||
54 | ED 0xFE400010, 0x00000087 | ||
55 | |||
56 | WAIT 10, 0xFE40009C | ||
57 | |||
58 | ED 0xFE400084, 0x0000003F | ||
59 | EB 0xFE500000, 0x00 | ||
60 | |||
61 | WAIT 5, 0xFE40009C | ||
62 | |||
63 | ED 0xFE400084, 0x0000FF0A | ||
64 | EB 0xFE500000, 0x00 | ||
65 | |||
66 | WAIT 1, 0xFE40009C | ||
67 | |||
68 | ED 0xFE400084, 0x00002201 | ||
69 | EB 0xFE500000, 0x00 | ||
70 | ED 0xFE400084, 0x00000302 | ||
71 | EB 0xFE500000, 0x00 | ||
72 | EB 0xFE5C0000, 0x00 | ||
73 | ED 0xFE400008, 0xBCC90159 | ||
74 | ED 0xFE40008C, 0x88800004 | ||
75 | ED 0xFE400094, 0x00000004 | ||
76 | ED 0xFE400028, 0xA55A0032 | ||
77 | ED 0xFE40002C, 0xA55A000C | ||
78 | ED 0xFE400020, 0xA55A2048 | ||
79 | ED 0xFE400008, 0xBCC90959 | ||
80 | |||
81 | LIST "Change CPGA setting" | ||
82 | ED 0xE61500E0, 0x9E40352E | ||
83 | ED 0xE6150004, 0x80331050 | ||
84 | |||
85 | WAIT 1, 0xFE40009C | ||
86 | |||
87 | ED 0xE6150354, 0x00000002 | ||
diff --git a/arch/arm/mach-shmobile/include/mach/vmalloc.h b/arch/arm/mach-shmobile/include/mach/vmalloc.h index 4aecf6e3a85..2b8fd8b942f 100644 --- a/arch/arm/mach-shmobile/include/mach/vmalloc.h +++ b/arch/arm/mach-shmobile/include/mach/vmalloc.h | |||
@@ -2,6 +2,6 @@ | |||
2 | #define __ASM_MACH_VMALLOC_H | 2 | #define __ASM_MACH_VMALLOC_H |
3 | 3 | ||
4 | /* Vmalloc at ... - 0xe5ffffff */ | 4 | /* Vmalloc at ... - 0xe5ffffff */ |
5 | #define VMALLOC_END 0xe6000000 | 5 | #define VMALLOC_END 0xe6000000UL |
6 | 6 | ||
7 | #endif /* __ASM_MACH_VMALLOC_H */ | 7 | #endif /* __ASM_MACH_VMALLOC_H */ |
diff --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h new file mode 100644 index 00000000000..3ad86b7708e --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/zboot.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #ifndef ZBOOT_H | ||
2 | #define ZBOOT_H | ||
3 | |||
4 | #include <asm/mach-types.h> | ||
5 | #include <mach/zboot_macros.h> | ||
6 | |||
7 | /************************************************** | ||
8 | * | ||
9 | * board specific settings | ||
10 | * | ||
11 | **************************************************/ | ||
12 | |||
13 | #ifdef CONFIG_MACH_AP4EVB | ||
14 | #define MACH_TYPE MACH_TYPE_AP4EVB | ||
15 | #include "mach/head-ap4evb.txt" | ||
16 | #else | ||
17 | #error "unsupported board." | ||
18 | #endif | ||
19 | |||
20 | #endif /* ZBOOT_H */ | ||
diff --git a/arch/arm/mach-shmobile/include/mach/zboot_macros.h b/arch/arm/mach-shmobile/include/mach/zboot_macros.h new file mode 100644 index 00000000000..aa6111fbc98 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/zboot_macros.h | |||
@@ -0,0 +1,65 @@ | |||
1 | #ifndef __ZBOOT_MACRO_H | ||
2 | #define __ZBOOT_MACRO_H | ||
3 | |||
4 | /* The LIST command is used to include comments in the script */ | ||
5 | .macro LIST comment | ||
6 | .endm | ||
7 | |||
8 | /* The ED command is used to write a 32-bit word */ | ||
9 | .macro ED, addr, data | ||
10 | LDR r0, 1f | ||
11 | LDR r1, 2f | ||
12 | STR r1, [r0] | ||
13 | B 3f | ||
14 | 1 : .long \addr | ||
15 | 2 : .long \data | ||
16 | 3 : | ||
17 | .endm | ||
18 | |||
19 | /* The EW command is used to write a 16-bit word */ | ||
20 | .macro EW, addr, data | ||
21 | LDR r0, 1f | ||
22 | LDR r1, 2f | ||
23 | STRH r1, [r0] | ||
24 | B 3f | ||
25 | 1 : .long \addr | ||
26 | 2 : .long \data | ||
27 | 3 : | ||
28 | .endm | ||
29 | |||
30 | /* The EB command is used to write an 8-bit word */ | ||
31 | .macro EB, addr, data | ||
32 | LDR r0, 1f | ||
33 | LDR r1, 2f | ||
34 | STRB r1, [r0] | ||
35 | B 3f | ||
36 | 1 : .long \addr | ||
37 | 2 : .long \data | ||
38 | 3 : | ||
39 | .endm | ||
40 | |||
41 | /* The WAIT command is used to delay the execution */ | ||
42 | .macro WAIT, time, reg | ||
43 | LDR r1, 1f | ||
44 | LDR r0, 2f | ||
45 | STR r0, [r1] | ||
46 | 10 : | ||
47 | LDR r0, [r1] | ||
48 | CMP r0, #0x00000000 | ||
49 | BNE 10b | ||
50 | NOP | ||
51 | B 3f | ||
52 | 1 : .long \reg | ||
53 | 2 : .long \time * 100 | ||
54 | 3 : | ||
55 | .endm | ||
56 | |||
57 | /* The DD command is used to read a 32-bit word */ | ||
58 | .macro DD, start, end | ||
59 | LDR r1, 1f | ||
60 | B 2f | ||
61 | 1 : .long \start | ||
62 | 2 : | ||
63 | .endm | ||
64 | |||
65 | #endif /* __ZBOOT_MACRO_H */ | ||
diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c index ba32a15127a..3970a9cdce2 100644 --- a/arch/arm/mach-tcc8k/clock.c +++ b/arch/arm/mach-tcc8k/clock.c | |||
@@ -12,8 +12,7 @@ | |||
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | 15 | #include <linux/clkdev.h> | |
16 | #include <asm/clkdev.h> | ||
17 | 16 | ||
18 | #include <mach/clock.h> | 17 | #include <mach/clock.h> |
19 | #include <mach/irqs.h> | 18 | #include <mach/irqs.h> |
diff --git a/arch/arm/mach-tcc8k/time.c b/arch/arm/mach-tcc8k/time.c index 78d06008841..e0a8d609afe 100644 --- a/arch/arm/mach-tcc8k/time.c +++ b/arch/arm/mach-tcc8k/time.c | |||
@@ -35,7 +35,6 @@ static struct clocksource clocksource_tcc = { | |||
35 | .rating = 200, | 35 | .rating = 200, |
36 | .read = tcc_get_cycles, | 36 | .read = tcc_get_cycles, |
37 | .mask = CLOCKSOURCE_MASK(32), | 37 | .mask = CLOCKSOURCE_MASK(32), |
38 | .shift = 28, | ||
39 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 38 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
40 | }; | 39 | }; |
41 | 40 | ||
@@ -103,9 +102,7 @@ static int __init tcc_clockevent_init(struct clk *clock) | |||
103 | { | 102 | { |
104 | unsigned int c = clk_get_rate(clock); | 103 | unsigned int c = clk_get_rate(clock); |
105 | 104 | ||
106 | clocksource_tcc.mult = clocksource_hz2mult(c, | 105 | clocksource_register_hz(&clocksource_tcc, c); |
107 | clocksource_tcc.shift); | ||
108 | clocksource_register(&clocksource_tcc); | ||
109 | 106 | ||
110 | clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC, | 107 | clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC, |
111 | clockevent_tcc.shift); | 108 | clockevent_tcc.shift); |
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index ae19f95585b..77948e0f490 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
28 | #include <asm/clkdev.h> | 28 | #include <linux/clkdev.h> |
29 | 29 | ||
30 | #include "clock.h" | 30 | #include "clock.h" |
31 | #include "board.h" | 31 | #include "board.h" |
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 94fd859770f..083a4cfc6cf 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h | |||
@@ -21,7 +21,7 @@ | |||
21 | #define __MACH_TEGRA_CLOCK_H | 21 | #define __MACH_TEGRA_CLOCK_H |
22 | 22 | ||
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <asm/clkdev.h> | 24 | #include <linux/clkdev.h> |
25 | 25 | ||
26 | #define DIV_BUS (1 << 0) | 26 | #define DIV_BUS (1 << 0) |
27 | #define DIV_U71 (1 << 1) | 27 | #define DIV_U71 (1 << 1) |
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c index 8e7f115aa21..a5cb1ce76ff 100644 --- a/arch/arm/mach-tegra/hotplug.c +++ b/arch/arm/mach-tegra/hotplug.c | |||
@@ -11,12 +11,9 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/completion.h> | ||
15 | 14 | ||
16 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
17 | 16 | ||
18 | static DECLARE_COMPLETION(cpu_killed); | ||
19 | |||
20 | static inline void cpu_enter_lowpower(void) | 17 | static inline void cpu_enter_lowpower(void) |
21 | { | 18 | { |
22 | unsigned int v; | 19 | unsigned int v; |
@@ -29,13 +26,13 @@ static inline void cpu_enter_lowpower(void) | |||
29 | * Turn off coherency | 26 | * Turn off coherency |
30 | */ | 27 | */ |
31 | " mrc p15, 0, %0, c1, c0, 1\n" | 28 | " mrc p15, 0, %0, c1, c0, 1\n" |
32 | " bic %0, %0, #0x20\n" | 29 | " bic %0, %0, %2\n" |
33 | " mcr p15, 0, %0, c1, c0, 1\n" | 30 | " mcr p15, 0, %0, c1, c0, 1\n" |
34 | " mrc p15, 0, %0, c1, c0, 0\n" | 31 | " mrc p15, 0, %0, c1, c0, 0\n" |
35 | " bic %0, %0, #0x04\n" | 32 | " bic %0, %0, #0x04\n" |
36 | " mcr p15, 0, %0, c1, c0, 0\n" | 33 | " mcr p15, 0, %0, c1, c0, 0\n" |
37 | : "=&r" (v) | 34 | : "=&r" (v) |
38 | : "r" (0) | 35 | : "r" (0), "Ir" (CR_C) |
39 | : "cc"); | 36 | : "cc"); |
40 | } | 37 | } |
41 | 38 | ||
@@ -45,17 +42,17 @@ static inline void cpu_leave_lowpower(void) | |||
45 | 42 | ||
46 | asm volatile( | 43 | asm volatile( |
47 | "mrc p15, 0, %0, c1, c0, 0\n" | 44 | "mrc p15, 0, %0, c1, c0, 0\n" |
48 | " orr %0, %0, #0x04\n" | 45 | " orr %0, %0, %1\n" |
49 | " mcr p15, 0, %0, c1, c0, 0\n" | 46 | " mcr p15, 0, %0, c1, c0, 0\n" |
50 | " mrc p15, 0, %0, c1, c0, 1\n" | 47 | " mrc p15, 0, %0, c1, c0, 1\n" |
51 | " orr %0, %0, #0x20\n" | 48 | " orr %0, %0, #0x20\n" |
52 | " mcr p15, 0, %0, c1, c0, 1\n" | 49 | " mcr p15, 0, %0, c1, c0, 1\n" |
53 | : "=&r" (v) | 50 | : "=&r" (v) |
54 | : | 51 | : "Ir" (CR_C) |
55 | : "cc"); | 52 | : "cc"); |
56 | } | 53 | } |
57 | 54 | ||
58 | static inline void platform_do_lowpower(unsigned int cpu) | 55 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) |
59 | { | 56 | { |
60 | /* | 57 | /* |
61 | * there is no power-control hardware on this platform, so all | 58 | * there is no power-control hardware on this platform, so all |
@@ -79,22 +76,19 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
79 | /*}*/ | 76 | /*}*/ |
80 | 77 | ||
81 | /* | 78 | /* |
82 | * getting here, means that we have come out of WFI without | 79 | * Getting here, means that we have come out of WFI without |
83 | * having been woken up - this shouldn't happen | 80 | * having been woken up - this shouldn't happen |
84 | * | 81 | * |
85 | * The trouble is, letting people know about this is not really | 82 | * Just note it happening - when we're woken, we can report |
86 | * possible, since we are currently running incoherently, and | 83 | * its occurrence. |
87 | * therefore cannot safely call printk() or anything else | ||
88 | */ | 84 | */ |
89 | #ifdef DEBUG | 85 | (*spurious)++; |
90 | printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu); | ||
91 | #endif | ||
92 | } | 86 | } |
93 | } | 87 | } |
94 | 88 | ||
95 | int platform_cpu_kill(unsigned int cpu) | 89 | int platform_cpu_kill(unsigned int cpu) |
96 | { | 90 | { |
97 | return wait_for_completion_timeout(&cpu_killed, 5000); | 91 | return 1; |
98 | } | 92 | } |
99 | 93 | ||
100 | /* | 94 | /* |
@@ -104,30 +98,22 @@ int platform_cpu_kill(unsigned int cpu) | |||
104 | */ | 98 | */ |
105 | void platform_cpu_die(unsigned int cpu) | 99 | void platform_cpu_die(unsigned int cpu) |
106 | { | 100 | { |
107 | #ifdef DEBUG | 101 | int spurious = 0; |
108 | unsigned int this_cpu = hard_smp_processor_id(); | ||
109 | |||
110 | if (cpu != this_cpu) { | ||
111 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
112 | this_cpu, cpu); | ||
113 | BUG(); | ||
114 | } | ||
115 | #endif | ||
116 | |||
117 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
118 | complete(&cpu_killed); | ||
119 | 102 | ||
120 | /* | 103 | /* |
121 | * we're ready for shutdown now, so do it | 104 | * we're ready for shutdown now, so do it |
122 | */ | 105 | */ |
123 | cpu_enter_lowpower(); | 106 | cpu_enter_lowpower(); |
124 | platform_do_lowpower(cpu); | 107 | platform_do_lowpower(cpu, &spurious); |
125 | 108 | ||
126 | /* | 109 | /* |
127 | * bring this CPU back into the world of cache | 110 | * bring this CPU back into the world of cache |
128 | * coherency, and then restore interrupts | 111 | * coherency, and then restore interrupts |
129 | */ | 112 | */ |
130 | cpu_leave_lowpower(); | 113 | cpu_leave_lowpower(); |
114 | |||
115 | if (spurious) | ||
116 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
131 | } | 117 | } |
132 | 118 | ||
133 | int platform_cpu_disable(unsigned int cpu) | 119 | int platform_cpu_disable(unsigned int cpu) |
diff --git a/arch/arm/mach-tegra/include/mach/entry-macro.S b/arch/arm/mach-tegra/include/mach/entry-macro.S index 2ba9e5c9d2f..dd165c53889 100644 --- a/arch/arm/mach-tegra/include/mach/entry-macro.S +++ b/arch/arm/mach-tegra/include/mach/entry-macro.S | |||
@@ -16,8 +16,8 @@ | |||
16 | #include <mach/io.h> | 16 | #include <mach/io.h> |
17 | 17 | ||
18 | #if defined(CONFIG_ARM_GIC) | 18 | #if defined(CONFIG_ARM_GIC) |
19 | 19 | #define HAVE_GET_IRQNR_PREAMBLE | |
20 | #include <asm/hardware/gic.h> | 20 | #include <asm/hardware/entry-macro-gic.S> |
21 | 21 | ||
22 | /* Uses the GIC interrupt controller built into the cpu */ | 22 | /* Uses the GIC interrupt controller built into the cpu */ |
23 | #define ICTRL_BASE (IO_CPU_VIRT + 0x100) | 23 | #define ICTRL_BASE (IO_CPU_VIRT + 0x100) |
@@ -32,68 +32,6 @@ | |||
32 | 32 | ||
33 | .macro arch_ret_to_user, tmp1, tmp2 | 33 | .macro arch_ret_to_user, tmp1, tmp2 |
34 | .endm | 34 | .endm |
35 | |||
36 | /* | ||
37 | * The interrupt numbering scheme is defined in the | ||
38 | * interrupt controller spec. To wit: | ||
39 | * | ||
40 | * Interrupts 0-15 are IPI | ||
41 | * 16-28 are reserved | ||
42 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
43 | * 32-1020 are global | ||
44 | * 1021-1022 are reserved | ||
45 | * 1023 is "spurious" (no interrupt) | ||
46 | * | ||
47 | * For now, we ignore all local interrupts so only return an interrupt | ||
48 | * if it's between 30 and 1020. The test_for_ipi routine below will | ||
49 | * pick up on IPIs. | ||
50 | * | ||
51 | * A simple read from the controller will tell us the number of the | ||
52 | * highest priority enabled interrupt. We then just need to check | ||
53 | * whether it is in the valid range for an IRQ (30-1020 inclusive). | ||
54 | */ | ||
55 | |||
56 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
57 | |||
58 | /* bits 12-10 = src CPU, 9-0 = int # */ | ||
59 | ldr \irqstat, [\base, #GIC_CPU_INTACK] | ||
60 | |||
61 | ldr \tmp, =1021 | ||
62 | |||
63 | bic \irqnr, \irqstat, #0x1c00 | ||
64 | |||
65 | cmp \irqnr, #29 | ||
66 | cmpcc \irqnr, \irqnr | ||
67 | cmpne \irqnr, \tmp | ||
68 | cmpcs \irqnr, \irqnr | ||
69 | |||
70 | .endm | ||
71 | |||
72 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
73 | * register) is preserved from the macro above. | ||
74 | * If there is an IPI, we immediately signal end of interrupt on the | ||
75 | * controller, since this requires the original irqstat value which | ||
76 | * we won't easily be able to recreate later. | ||
77 | */ | ||
78 | |||
79 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
80 | bic \irqnr, \irqstat, #0x1c00 | ||
81 | cmp \irqnr, #16 | ||
82 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
83 | cmpcs \irqnr, \irqnr | ||
84 | .endm | ||
85 | |||
86 | /* As above, this assumes that irqstat and base are preserved.. */ | ||
87 | |||
88 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
89 | bic \irqnr, \irqstat, #0x1c00 | ||
90 | mov \tmp, #0 | ||
91 | cmp \irqnr, #29 | ||
92 | moveq \tmp, #1 | ||
93 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
94 | cmp \tmp, #0 | ||
95 | .endm | ||
96 | |||
97 | #else | 35 | #else |
98 | /* legacy interrupt controller for AP16 */ | 36 | /* legacy interrupt controller for AP16 */ |
99 | .macro disable_fiq | 37 | .macro disable_fiq |
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h index f0981b1ac59..4cea2230c8d 100644 --- a/arch/arm/mach-tegra/include/mach/io.h +++ b/arch/arm/mach-tegra/include/mach/io.h | |||
@@ -65,8 +65,8 @@ | |||
65 | 65 | ||
66 | #ifndef __ASSEMBLER__ | 66 | #ifndef __ASSEMBLER__ |
67 | 67 | ||
68 | #define __arch_ioremap(p, s, t) tegra_ioremap(p, s, t) | 68 | #define __arch_ioremap tegra_ioremap |
69 | #define __arch_iounmap(v) tegra_iounmap(v) | 69 | #define __arch_iounmap tegra_iounmap |
70 | 70 | ||
71 | void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type); | 71 | void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type); |
72 | void tegra_iounmap(volatile void __iomem *addr); | 72 | void tegra_iounmap(volatile void __iomem *addr); |
diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h index e4a34a35a54..c8221b38ee7 100644 --- a/arch/arm/mach-tegra/include/mach/smp.h +++ b/arch/arm/mach-tegra/include/mach/smp.h | |||
@@ -2,21 +2,13 @@ | |||
2 | #define ASMARM_ARCH_SMP_H | 2 | #define ASMARM_ARCH_SMP_H |
3 | 3 | ||
4 | #include <asm/hardware/gic.h> | 4 | #include <asm/hardware/gic.h> |
5 | #include <asm/smp_mpidr.h> | ||
6 | 5 | ||
7 | /* | 6 | /* |
8 | * We use IRQ1 as the IPI | 7 | * We use IRQ1 as the IPI |
9 | */ | 8 | */ |
10 | static inline void smp_cross_call(const struct cpumask *mask) | 9 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
11 | { | ||
12 | gic_raise_softirq(mask, 1); | ||
13 | } | ||
14 | |||
15 | /* | ||
16 | * Do nothing on MPcore. | ||
17 | */ | ||
18 | static inline void smp_cross_call_done(cpumask_t callmap) | ||
19 | { | 10 | { |
11 | gic_raise_softirq(mask, ipi); | ||
20 | } | 12 | } |
21 | 13 | ||
22 | #endif | 14 | #endif |
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index 50a8dfb9a0c..5407de01abf 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c | |||
@@ -94,8 +94,8 @@ void __init tegra_init_irq(void) | |||
94 | writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS); | 94 | writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS); |
95 | } | 95 | } |
96 | 96 | ||
97 | gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29); | 97 | gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), |
98 | gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); | 98 | IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); |
99 | 99 | ||
100 | gic = get_irq_chip(29); | 100 | gic = get_irq_chip(29); |
101 | gic_unmask_irq = gic->unmask; | 101 | gic_unmask_irq = gic->unmask; |
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 1c0fd92cab3..ec1f68924ed 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
24 | #include <asm/mach-types.h> | 24 | #include <asm/mach-types.h> |
25 | #include <asm/localtimer.h> | ||
26 | #include <asm/smp_scu.h> | 25 | #include <asm/smp_scu.h> |
27 | 26 | ||
28 | #include <mach/iomap.h> | 27 | #include <mach/iomap.h> |
@@ -41,14 +40,12 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); | |||
41 | 40 | ||
42 | void __cpuinit platform_secondary_init(unsigned int cpu) | 41 | void __cpuinit platform_secondary_init(unsigned int cpu) |
43 | { | 42 | { |
44 | trace_hardirqs_off(); | ||
45 | |||
46 | /* | 43 | /* |
47 | * if any interrupts are already enabled for the primary | 44 | * if any interrupts are already enabled for the primary |
48 | * core (e.g. timer irq), then they will not have been enabled | 45 | * core (e.g. timer irq), then they will not have been enabled |
49 | * for us: do so | 46 | * for us: do so |
50 | */ | 47 | */ |
51 | gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100); | 48 | gic_secondary_init(0); |
52 | 49 | ||
53 | /* | 50 | /* |
54 | * Synchronise with the boot thread. | 51 | * Synchronise with the boot thread. |
@@ -117,24 +114,20 @@ void __init smp_init_cpus(void) | |||
117 | { | 114 | { |
118 | unsigned int i, ncores = scu_get_core_count(scu_base); | 115 | unsigned int i, ncores = scu_get_core_count(scu_base); |
119 | 116 | ||
117 | if (ncores > NR_CPUS) { | ||
118 | printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n", | ||
119 | ncores, NR_CPUS); | ||
120 | ncores = NR_CPUS; | ||
121 | } | ||
122 | |||
120 | for (i = 0; i < ncores; i++) | 123 | for (i = 0; i < ncores; i++) |
121 | cpu_set(i, cpu_possible_map); | 124 | cpu_set(i, cpu_possible_map); |
122 | } | 125 | } |
123 | 126 | ||
124 | void __init smp_prepare_cpus(unsigned int max_cpus) | 127 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
125 | { | 128 | { |
126 | unsigned int ncores = scu_get_core_count(scu_base); | ||
127 | unsigned int cpu = smp_processor_id(); | ||
128 | int i; | 129 | int i; |
129 | 130 | ||
130 | smp_store_cpu_info(cpu); | ||
131 | |||
132 | /* | ||
133 | * are we trying to boot more cores than exist? | ||
134 | */ | ||
135 | if (max_cpus > ncores) | ||
136 | max_cpus = ncores; | ||
137 | |||
138 | /* | 131 | /* |
139 | * Initialise the present map, which describes the set of CPUs | 132 | * Initialise the present map, which describes the set of CPUs |
140 | * actually populated at the present time. | 133 | * actually populated at the present time. |
@@ -142,15 +135,5 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
142 | for (i = 0; i < max_cpus; i++) | 135 | for (i = 0; i < max_cpus; i++) |
143 | set_cpu_present(i, true); | 136 | set_cpu_present(i, true); |
144 | 137 | ||
145 | /* | 138 | scu_enable(scu_base); |
146 | * Initialise the SCU if there are more than one CPU and let | ||
147 | * them know where to start. Note that, on modern versions of | ||
148 | * MILO, the "poke" doesn't actually do anything until each | ||
149 | * individual core is sent a soft interrupt to get it out of | ||
150 | * WFI | ||
151 | */ | ||
152 | if (max_cpus > 1) { | ||
153 | percpu_timer_setup(); | ||
154 | scu_enable(scu_base); | ||
155 | } | ||
156 | } | 139 | } |
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index ae3b308e22a..f0dae6d8ba5 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c | |||
@@ -24,8 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/hrtimer.h> | 26 | #include <linux/hrtimer.h> |
27 | 27 | #include <linux/clkdev.h> | |
28 | #include <asm/clkdev.h> | ||
29 | 28 | ||
30 | #include <mach/iomap.h> | 29 | #include <mach/iomap.h> |
31 | 30 | ||
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index 9057d6fd1d3..7b8ad1f98f4 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | 22 | #include <linux/time.h> |
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
23 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
@@ -25,10 +26,10 @@ | |||
25 | #include <linux/clocksource.h> | 26 | #include <linux/clocksource.h> |
26 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
27 | #include <linux/io.h> | 28 | #include <linux/io.h> |
28 | #include <linux/cnt32_to_63.h> | ||
29 | 29 | ||
30 | #include <asm/mach/time.h> | 30 | #include <asm/mach/time.h> |
31 | #include <asm/localtimer.h> | 31 | #include <asm/localtimer.h> |
32 | #include <asm/sched_clock.h> | ||
32 | 33 | ||
33 | #include <mach/iomap.h> | 34 | #include <mach/iomap.h> |
34 | #include <mach/irqs.h> | 35 | #include <mach/irqs.h> |
@@ -91,7 +92,7 @@ static void tegra_timer_set_mode(enum clock_event_mode mode, | |||
91 | 92 | ||
92 | static cycle_t tegra_clocksource_read(struct clocksource *cs) | 93 | static cycle_t tegra_clocksource_read(struct clocksource *cs) |
93 | { | 94 | { |
94 | return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)); | 95 | return timer_readl(TIMERUS_CNTR_1US); |
95 | } | 96 | } |
96 | 97 | ||
97 | static struct clock_event_device tegra_clockevent = { | 98 | static struct clock_event_device tegra_clockevent = { |
@@ -106,14 +107,29 @@ static struct clocksource tegra_clocksource = { | |||
106 | .name = "timer_us", | 107 | .name = "timer_us", |
107 | .rating = 300, | 108 | .rating = 300, |
108 | .read = tegra_clocksource_read, | 109 | .read = tegra_clocksource_read, |
109 | .mask = 0x7FFFFFFFFFFFFFFFULL, | 110 | .mask = CLOCKSOURCE_MASK(32), |
110 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 111 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
111 | }; | 112 | }; |
112 | 113 | ||
113 | unsigned long long sched_clock(void) | 114 | static DEFINE_CLOCK_DATA(cd); |
115 | |||
116 | /* | ||
117 | * Constants generated by clocks_calc_mult_shift(m, s, 1MHz, NSEC_PER_SEC, 60). | ||
118 | * This gives a resolution of about 1us and a wrap period of about 1h11min. | ||
119 | */ | ||
120 | #define SC_MULT 4194304000u | ||
121 | #define SC_SHIFT 22 | ||
122 | |||
123 | unsigned long long notrace sched_clock(void) | ||
114 | { | 124 | { |
115 | return clocksource_cyc2ns(tegra_clocksource.read(&tegra_clocksource), | 125 | u32 cyc = timer_readl(TIMERUS_CNTR_1US); |
116 | tegra_clocksource.mult, tegra_clocksource.shift); | 126 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); |
127 | } | ||
128 | |||
129 | static void notrace tegra_update_sched_clock(void) | ||
130 | { | ||
131 | u32 cyc = timer_readl(TIMERUS_CNTR_1US); | ||
132 | update_sched_clock(&cd, cyc, (u32)~0); | ||
117 | } | 133 | } |
118 | 134 | ||
119 | static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) | 135 | static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) |
@@ -158,6 +174,9 @@ static void __init tegra_init_timer(void) | |||
158 | WARN(1, "Unknown clock rate"); | 174 | WARN(1, "Unknown clock rate"); |
159 | } | 175 | } |
160 | 176 | ||
177 | init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32, | ||
178 | 1000000, SC_MULT, SC_SHIFT); | ||
179 | |||
161 | if (clocksource_register_hz(&tegra_clocksource, 1000000)) { | 180 | if (clocksource_register_hz(&tegra_clocksource, 1000000)) { |
162 | printk(KERN_ERR "Failed to register clocksource\n"); | 181 | printk(KERN_ERR "Failed to register clocksource\n"); |
163 | BUG(); | 182 | BUG(); |
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index 7458fc6df5c..fabcc49abe8 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <linux/timer.h> | 25 | #include <linux/timer.h> |
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
28 | #include <linux/clkdev.h> | ||
28 | 29 | ||
29 | #include <asm/clkdev.h> | ||
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/syscon.h> | 31 | #include <mach/syscon.h> |
32 | 32 | ||
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 3fc4472719b..3ec58bd2d6e 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * Author: Linus Walleij <linus.walleij@stericsson.com> | 9 | * Author: Linus Walleij <linus.walleij@stericsson.com> |
10 | */ | 10 | */ |
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/sched.h> | ||
12 | #include <linux/time.h> | 13 | #include <linux/time.h> |
13 | #include <linux/timex.h> | 14 | #include <linux/timex.h> |
14 | #include <linux/clockchips.h> | 15 | #include <linux/clockchips.h> |
@@ -21,6 +22,7 @@ | |||
21 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
22 | 23 | ||
23 | /* Generic stuff */ | 24 | /* Generic stuff */ |
25 | #include <asm/sched_clock.h> | ||
24 | #include <asm/mach/map.h> | 26 | #include <asm/mach/map.h> |
25 | #include <asm/mach/time.h> | 27 | #include <asm/mach/time.h> |
26 | #include <asm/mach/irq.h> | 28 | #include <asm/mach/irq.h> |
@@ -352,12 +354,18 @@ static struct clocksource clocksource_u300_1mhz = { | |||
352 | * this wraps around for now, since it is just a relative time | 354 | * this wraps around for now, since it is just a relative time |
353 | * stamp. (Inspired by OMAP implementation.) | 355 | * stamp. (Inspired by OMAP implementation.) |
354 | */ | 356 | */ |
357 | static DEFINE_CLOCK_DATA(cd); | ||
358 | |||
355 | unsigned long long notrace sched_clock(void) | 359 | unsigned long long notrace sched_clock(void) |
356 | { | 360 | { |
357 | return clocksource_cyc2ns(clocksource_u300_1mhz.read( | 361 | u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); |
358 | &clocksource_u300_1mhz), | 362 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
359 | clocksource_u300_1mhz.mult, | 363 | } |
360 | clocksource_u300_1mhz.shift); | 364 | |
365 | static void notrace u300_update_sched_clock(void) | ||
366 | { | ||
367 | u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); | ||
368 | update_sched_clock(&cd, cyc, (u32)~0); | ||
361 | } | 369 | } |
362 | 370 | ||
363 | 371 | ||
@@ -375,6 +383,8 @@ static void __init u300_timer_init(void) | |||
375 | clk_enable(clk); | 383 | clk_enable(clk); |
376 | rate = clk_get_rate(clk); | 384 | rate = clk_get_rate(clk); |
377 | 385 | ||
386 | init_sched_clock(&cd, u300_update_sched_clock, 32, rate); | ||
387 | |||
378 | /* | 388 | /* |
379 | * Disable the "OS" and "DD" timers - these are designed for Symbian! | 389 | * Disable the "OS" and "DD" timers - these are designed for Symbian! |
380 | * Example usage in cnh1601578 cpu subsystem pd_timer_app.c | 390 | * Example usage in cnh1601578 cpu subsystem pd_timer_app.c |
@@ -412,9 +422,7 @@ static void __init u300_timer_init(void) | |||
412 | writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, | 422 | writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, |
413 | U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2); | 423 | U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2); |
414 | 424 | ||
415 | clocksource_calc_mult_shift(&clocksource_u300_1mhz, | 425 | if (clocksource_register_hz(&clocksource_u300_1mhz, rate)) |
416 | rate, APPTIMER_MIN_RANGE); | ||
417 | if (clocksource_register(&clocksource_u300_1mhz)) | ||
418 | printk(KERN_ERR "timer: failed to initialize clock " | 426 | printk(KERN_ERR "timer: failed to initialize clock " |
419 | "source %s\n", clocksource_u300_1mhz.name); | 427 | "source %s\n", clocksource_u300_1mhz.name); |
420 | 428 | ||
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 912d1cc18c5..ccff2dae167 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c | |||
@@ -13,8 +13,7 @@ | |||
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | 16 | #include <linux/clkdev.h> | |
17 | #include <asm/clkdev.h> | ||
18 | 17 | ||
19 | #include <plat/mtu.h> | 18 | #include <plat/mtu.h> |
20 | #include <mach/hardware.h> | 19 | #include <mach/hardware.h> |
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index a3700bc374d..5730409c0f7 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c | |||
@@ -52,8 +52,8 @@ void __init ux500_map_io(void) | |||
52 | 52 | ||
53 | void __init ux500_init_irq(void) | 53 | void __init ux500_init_irq(void) |
54 | { | 54 | { |
55 | gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); | 55 | gic_init(0, 29, __io_address(UX500_GIC_DIST_BASE), |
56 | gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE)); | 56 | __io_address(UX500_GIC_CPU_BASE)); |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * Init clocks here so that they are available for system timer | 59 | * Init clocks here so that they are available for system timer |
diff --git a/arch/arm/mach-ux500/headsmp.S b/arch/arm/mach-ux500/headsmp.S index a6be2cdf2b2..64fa451edcf 100644 --- a/arch/arm/mach-ux500/headsmp.S +++ b/arch/arm/mach-ux500/headsmp.S | |||
@@ -23,7 +23,6 @@ ENTRY(u8500_secondary_startup) | |||
23 | ldmia r4, {r5, r6} | 23 | ldmia r4, {r5, r6} |
24 | sub r4, r4, r5 | 24 | sub r4, r4, r5 |
25 | add r6, r6, r4 | 25 | add r6, r6, r4 |
26 | dsb | ||
27 | pen: ldr r7, [r6] | 26 | pen: ldr r7, [r6] |
28 | cmp r7, r0 | 27 | cmp r7, r0 |
29 | bne pen | 28 | bne pen |
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c index b782a03024b..dd8037ebccf 100644 --- a/arch/arm/mach-ux500/hotplug.c +++ b/arch/arm/mach-ux500/hotplug.c | |||
@@ -11,14 +11,11 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/completion.h> | ||
15 | 14 | ||
16 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
17 | 16 | ||
18 | extern volatile int pen_release; | 17 | extern volatile int pen_release; |
19 | 18 | ||
20 | static DECLARE_COMPLETION(cpu_killed); | ||
21 | |||
22 | static inline void platform_do_lowpower(unsigned int cpu) | 19 | static inline void platform_do_lowpower(unsigned int cpu) |
23 | { | 20 | { |
24 | flush_cache_all(); | 21 | flush_cache_all(); |
@@ -38,7 +35,7 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
38 | 35 | ||
39 | int platform_cpu_kill(unsigned int cpu) | 36 | int platform_cpu_kill(unsigned int cpu) |
40 | { | 37 | { |
41 | return wait_for_completion_timeout(&cpu_killed, 5000); | 38 | return 1; |
42 | } | 39 | } |
43 | 40 | ||
44 | /* | 41 | /* |
@@ -48,19 +45,6 @@ int platform_cpu_kill(unsigned int cpu) | |||
48 | */ | 45 | */ |
49 | void platform_cpu_die(unsigned int cpu) | 46 | void platform_cpu_die(unsigned int cpu) |
50 | { | 47 | { |
51 | #ifdef DEBUG | ||
52 | unsigned int this_cpu = hard_smp_processor_id(); | ||
53 | |||
54 | if (cpu != this_cpu) { | ||
55 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
56 | this_cpu, cpu); | ||
57 | BUG(); | ||
58 | } | ||
59 | #endif | ||
60 | |||
61 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
62 | complete(&cpu_killed); | ||
63 | |||
64 | /* directly enter low power state, skipping secure registers */ | 48 | /* directly enter low power state, skipping secure registers */ |
65 | platform_do_lowpower(cpu); | 49 | platform_do_lowpower(cpu); |
66 | } | 50 | } |
diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S index 60ea88db828..a37f585a3ec 100644 --- a/arch/arm/mach-ux500/include/mach/entry-macro.S +++ b/arch/arm/mach-ux500/include/mach/entry-macro.S | |||
@@ -11,7 +11,8 @@ | |||
11 | * warranty of any kind, whether express or implied. | 11 | * warranty of any kind, whether express or implied. |
12 | */ | 12 | */ |
13 | #include <mach/hardware.h> | 13 | #include <mach/hardware.h> |
14 | #include <asm/hardware/gic.h> | 14 | #define HAVE_GET_IRQNR_PREAMBLE |
15 | #include <asm/hardware/entry-macro-gic.S> | ||
15 | 16 | ||
16 | .macro disable_fiq | 17 | .macro disable_fiq |
17 | .endm | 18 | .endm |
@@ -22,68 +23,3 @@ | |||
22 | 23 | ||
23 | .macro arch_ret_to_user, tmp1, tmp2 | 24 | .macro arch_ret_to_user, tmp1, tmp2 |
24 | .endm | 25 | .endm |
25 | |||
26 | /* | ||
27 | * The interrupt numbering scheme is defined in the | ||
28 | * interrupt controller spec. To wit: | ||
29 | * | ||
30 | * Interrupts 0-15 are IPI | ||
31 | * 16-28 are reserved | ||
32 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
33 | * 32-1020 are global | ||
34 | * 1021-1022 are reserved | ||
35 | * 1023 is "spurious" (no interrupt) | ||
36 | * | ||
37 | * For now, we ignore all local interrupts so only return an | ||
38 | * interrupt if it's between 30 and 1020. The test_for_ipi | ||
39 | * routine below will pick up on IPIs. | ||
40 | * | ||
41 | * A simple read from the controller will tell us the number | ||
42 | * of the highest priority enabled interrupt. We then just | ||
43 | * need to check whether it is in the valid range for an | ||
44 | * IRQ (30-1020 inclusive). | ||
45 | */ | ||
46 | |||
47 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
48 | |||
49 | /* bits 12-10 = src CPU, 9-0 = int # */ | ||
50 | ldr \irqstat, [\base, #GIC_CPU_INTACK] | ||
51 | |||
52 | ldr \tmp, =1021 | ||
53 | |||
54 | bic \irqnr, \irqstat, #0x1c00 | ||
55 | |||
56 | cmp \irqnr, #29 | ||
57 | cmpcc \irqnr, \irqnr | ||
58 | cmpne \irqnr, \tmp | ||
59 | cmpcs \irqnr, \irqnr | ||
60 | |||
61 | .endm | ||
62 | |||
63 | /* We assume that irqstat (the raw value of the IRQ | ||
64 | * acknowledge register) is preserved from the macro above. | ||
65 | * If there is an IPI, we immediately signal end of | ||
66 | * interrupt on the controller, since this requires the | ||
67 | * original irqstat value which we won't easily be able | ||
68 | * to recreate later. | ||
69 | */ | ||
70 | |||
71 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
72 | bic \irqnr, \irqstat, #0x1c00 | ||
73 | cmp \irqnr, #16 | ||
74 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
75 | cmpcs \irqnr, \irqnr | ||
76 | .endm | ||
77 | |||
78 | /* As above, this assumes that irqstat and base | ||
79 | * are preserved.. | ||
80 | */ | ||
81 | |||
82 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
83 | bic \irqnr, \irqstat, #0x1c00 | ||
84 | mov \tmp, #0 | ||
85 | cmp \irqnr, #29 | ||
86 | moveq \tmp, #1 | ||
87 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
88 | cmp \tmp, #0 | ||
89 | .endm | ||
diff --git a/arch/arm/mach-ux500/include/mach/smp.h b/arch/arm/mach-ux500/include/mach/smp.h index 197e8417375..ca2b15b1b3b 100644 --- a/arch/arm/mach-ux500/include/mach/smp.h +++ b/arch/arm/mach-ux500/include/mach/smp.h | |||
@@ -10,7 +10,6 @@ | |||
10 | #define ASMARM_ARCH_SMP_H | 10 | #define ASMARM_ARCH_SMP_H |
11 | 11 | ||
12 | #include <asm/hardware/gic.h> | 12 | #include <asm/hardware/gic.h> |
13 | #include <asm/smp_mpidr.h> | ||
14 | 13 | ||
15 | /* This is required to wakeup the secondary core */ | 14 | /* This is required to wakeup the secondary core */ |
16 | extern void u8500_secondary_startup(void); | 15 | extern void u8500_secondary_startup(void); |
@@ -18,8 +17,8 @@ extern void u8500_secondary_startup(void); | |||
18 | /* | 17 | /* |
19 | * We use IRQ1 as the IPI | 18 | * We use IRQ1 as the IPI |
20 | */ | 19 | */ |
21 | static inline void smp_cross_call(const struct cpumask *mask) | 20 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
22 | { | 21 | { |
23 | gic_raise_softirq(mask, 1); | 22 | gic_raise_softirq(mask, ipi); |
24 | } | 23 | } |
25 | #endif | 24 | #endif |
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index ade2e17f253..d77e76cb7ed 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | 19 | ||
20 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
21 | #include <asm/localtimer.h> | ||
22 | #include <asm/smp_scu.h> | 21 | #include <asm/smp_scu.h> |
23 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
24 | 23 | ||
@@ -28,29 +27,35 @@ | |||
28 | */ | 27 | */ |
29 | volatile int pen_release = -1; | 28 | volatile int pen_release = -1; |
30 | 29 | ||
31 | static unsigned int __init get_core_count(void) | 30 | /* |
31 | * Write pen_release in a way that is guaranteed to be visible to all | ||
32 | * observers, irrespective of whether they're taking part in coherency | ||
33 | * or not. This is necessary for the hotplug code to work reliably. | ||
34 | */ | ||
35 | static void write_pen_release(int val) | ||
32 | { | 36 | { |
33 | return scu_get_core_count(__io_address(UX500_SCU_BASE)); | 37 | pen_release = val; |
38 | smp_wmb(); | ||
39 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
40 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
34 | } | 41 | } |
35 | 42 | ||
36 | static DEFINE_SPINLOCK(boot_lock); | 43 | static DEFINE_SPINLOCK(boot_lock); |
37 | 44 | ||
38 | void __cpuinit platform_secondary_init(unsigned int cpu) | 45 | void __cpuinit platform_secondary_init(unsigned int cpu) |
39 | { | 46 | { |
40 | trace_hardirqs_off(); | ||
41 | |||
42 | /* | 47 | /* |
43 | * if any interrupts are already enabled for the primary | 48 | * if any interrupts are already enabled for the primary |
44 | * core (e.g. timer irq), then they will not have been enabled | 49 | * core (e.g. timer irq), then they will not have been enabled |
45 | * for us: do so | 50 | * for us: do so |
46 | */ | 51 | */ |
47 | gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE)); | 52 | gic_secondary_init(0); |
48 | 53 | ||
49 | /* | 54 | /* |
50 | * let the primary processor know we're out of the | 55 | * let the primary processor know we're out of the |
51 | * pen, then head off into the C entry point | 56 | * pen, then head off into the C entry point |
52 | */ | 57 | */ |
53 | pen_release = -1; | 58 | write_pen_release(-1); |
54 | 59 | ||
55 | /* | 60 | /* |
56 | * Synchronise with the boot thread. | 61 | * Synchronise with the boot thread. |
@@ -74,11 +79,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
74 | * the holding pen - release it, then wait for it to flag | 79 | * the holding pen - release it, then wait for it to flag |
75 | * that it has been released by resetting pen_release. | 80 | * that it has been released by resetting pen_release. |
76 | */ | 81 | */ |
77 | pen_release = cpu; | 82 | write_pen_release(cpu); |
78 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
79 | outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1); | ||
80 | 83 | ||
81 | smp_cross_call(cpumask_of(cpu)); | 84 | smp_cross_call(cpumask_of(cpu), 1); |
82 | 85 | ||
83 | timeout = jiffies + (1 * HZ); | 86 | timeout = jiffies + (1 * HZ); |
84 | while (time_before(jiffies, timeout)) { | 87 | while (time_before(jiffies, timeout)) { |
@@ -97,9 +100,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
97 | 100 | ||
98 | static void __init wakeup_secondary(void) | 101 | static void __init wakeup_secondary(void) |
99 | { | 102 | { |
100 | /* nobody is to be released from the pen yet */ | ||
101 | pen_release = -1; | ||
102 | |||
103 | /* | 103 | /* |
104 | * write the address of secondary startup into the backup ram register | 104 | * write the address of secondary startup into the backup ram register |
105 | * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the | 105 | * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the |
@@ -126,40 +126,26 @@ static void __init wakeup_secondary(void) | |||
126 | */ | 126 | */ |
127 | void __init smp_init_cpus(void) | 127 | void __init smp_init_cpus(void) |
128 | { | 128 | { |
129 | unsigned int i, ncores = get_core_count(); | 129 | unsigned int i, ncores; |
130 | 130 | ||
131 | for (i = 0; i < ncores; i++) | 131 | ncores = scu_get_core_count(__io_address(UX500_SCU_BASE)); |
132 | set_cpu_possible(i, true); | ||
133 | } | ||
134 | |||
135 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
136 | { | ||
137 | unsigned int ncores = get_core_count(); | ||
138 | unsigned int cpu = smp_processor_id(); | ||
139 | int i; | ||
140 | 132 | ||
141 | /* sanity check */ | 133 | /* sanity check */ |
142 | if (ncores == 0) { | 134 | if (ncores > NR_CPUS) { |
143 | printk(KERN_ERR | ||
144 | "U8500: strange CM count of 0? Default to 1\n"); | ||
145 | ncores = 1; | ||
146 | } | ||
147 | |||
148 | if (ncores > num_possible_cpus()) { | ||
149 | printk(KERN_WARNING | 135 | printk(KERN_WARNING |
150 | "U8500: no. of cores (%d) greater than configured " | 136 | "U8500: no. of cores (%d) greater than configured " |
151 | "maximum of %d - clipping\n", | 137 | "maximum of %d - clipping\n", |
152 | ncores, num_possible_cpus()); | 138 | ncores, NR_CPUS); |
153 | ncores = num_possible_cpus(); | 139 | ncores = NR_CPUS; |
154 | } | 140 | } |
155 | 141 | ||
156 | smp_store_cpu_info(cpu); | 142 | for (i = 0; i < ncores; i++) |
143 | set_cpu_possible(i, true); | ||
144 | } | ||
157 | 145 | ||
158 | /* | 146 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
159 | * are we trying to boot more cores than exist? | 147 | { |
160 | */ | 148 | int i; |
161 | if (max_cpus > ncores) | ||
162 | max_cpus = ncores; | ||
163 | 149 | ||
164 | /* | 150 | /* |
165 | * Initialise the present map, which describes the set of CPUs | 151 | * Initialise the present map, which describes the set of CPUs |
@@ -168,13 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
168 | for (i = 0; i < max_cpus; i++) | 154 | for (i = 0; i < max_cpus; i++) |
169 | set_cpu_present(i, true); | 155 | set_cpu_present(i, true); |
170 | 156 | ||
171 | if (max_cpus > 1) { | 157 | scu_enable(__io_address(UX500_SCU_BASE)); |
172 | /* | 158 | wakeup_secondary(); |
173 | * Enable the local timer or broadcast device for the | ||
174 | * boot CPU, but only if we have more than one CPU. | ||
175 | */ | ||
176 | percpu_timer_setup(); | ||
177 | scu_enable(__io_address(UX500_SCU_BASE)); | ||
178 | wakeup_secondary(); | ||
179 | } | ||
180 | } | 159 | } |
diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig index c781f30c836..3f7b5e9d83c 100644 --- a/arch/arm/mach-versatile/Kconfig +++ b/arch/arm/mach-versatile/Kconfig | |||
@@ -4,6 +4,7 @@ menu "Versatile platform type" | |||
4 | config ARCH_VERSATILE_PB | 4 | config ARCH_VERSATILE_PB |
5 | bool "Support Versatile/PB platform" | 5 | bool "Support Versatile/PB platform" |
6 | select CPU_ARM926T | 6 | select CPU_ARM926T |
7 | select MIGHT_HAVE_PCI | ||
7 | default y | 8 | default y |
8 | help | 9 | help |
9 | Include support for the ARM(R) Versatile/PB platform. | 10 | Include support for the ARM(R) Versatile/PB platform. |
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index e38acb0f89c..13a83e45a33 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c | |||
@@ -31,8 +31,8 @@ | |||
31 | #include <linux/amba/pl022.h> | 31 | #include <linux/amba/pl022.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/gfp.h> | 33 | #include <linux/gfp.h> |
34 | #include <linux/clkdev.h> | ||
34 | 35 | ||
35 | #include <asm/clkdev.h> | ||
36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #include <asm/leds.h> | 38 | #include <asm/leds.h> |
@@ -46,10 +46,11 @@ | |||
46 | #include <asm/mach/irq.h> | 46 | #include <asm/mach/irq.h> |
47 | #include <asm/mach/time.h> | 47 | #include <asm/mach/time.h> |
48 | #include <asm/mach/map.h> | 48 | #include <asm/mach/map.h> |
49 | #include <mach/clkdev.h> | ||
50 | #include <mach/hardware.h> | 49 | #include <mach/hardware.h> |
51 | #include <mach/platform.h> | 50 | #include <mach/platform.h> |
52 | #include <plat/timer-sp.h> | 51 | #include <asm/hardware/timer-sp.h> |
52 | |||
53 | #include <plat/sched_clock.h> | ||
53 | 54 | ||
54 | #include "core.h" | 55 | #include "core.h" |
55 | 56 | ||
@@ -886,6 +887,12 @@ void __init versatile_init(void) | |||
886 | } | 887 | } |
887 | 888 | ||
888 | /* | 889 | /* |
890 | * The sched_clock counter | ||
891 | */ | ||
892 | #define REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + \ | ||
893 | VERSATILE_SYS_24MHz_OFFSET) | ||
894 | |||
895 | /* | ||
889 | * Where is the timer (VA)? | 896 | * Where is the timer (VA)? |
890 | */ | 897 | */ |
891 | #define TIMER0_VA_BASE __io_address(VERSATILE_TIMER0_1_BASE) | 898 | #define TIMER0_VA_BASE __io_address(VERSATILE_TIMER0_1_BASE) |
@@ -900,6 +907,8 @@ static void __init versatile_timer_init(void) | |||
900 | { | 907 | { |
901 | u32 val; | 908 | u32 val; |
902 | 909 | ||
910 | versatile_sched_clock_init(REFCOUNTER, 24000000); | ||
911 | |||
903 | /* | 912 | /* |
904 | * set clock frequency: | 913 | * set clock frequency: |
905 | * VERSATILE_REFCLK is 32KHz | 914 | * VERSATILE_REFCLK is 32KHz |
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index 1b71b77ade2..2c0ac7de281 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile | |||
@@ -5,4 +5,5 @@ | |||
5 | obj-y := v2m.o | 5 | obj-y := v2m.o |
6 | obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o | 6 | obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o |
7 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | 7 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o |
8 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | ||
8 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | 9 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o |
diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h index 57dd95ce41f..362780d868d 100644 --- a/arch/arm/mach-vexpress/core.h +++ b/arch/arm/mach-vexpress/core.h | |||
@@ -22,5 +22,3 @@ struct map_desc; | |||
22 | 22 | ||
23 | void v2m_map_io(struct map_desc *tile, size_t num); | 23 | void v2m_map_io(struct map_desc *tile, size_t num); |
24 | extern struct sys_timer v2m_timer; | 24 | extern struct sys_timer v2m_timer; |
25 | |||
26 | extern void __iomem *gic_cpu_base_addr; | ||
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index fd25ccd7272..e628402b754 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c | |||
@@ -8,8 +8,8 @@ | |||
8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
9 | #include <linux/amba/bus.h> | 9 | #include <linux/amba/bus.h> |
10 | #include <linux/amba/clcd.h> | 10 | #include <linux/amba/clcd.h> |
11 | #include <linux/clkdev.h> | ||
11 | 12 | ||
12 | #include <asm/clkdev.h> | ||
13 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
14 | #include <asm/hardware/arm_timer.h> | 14 | #include <asm/hardware/arm_timer.h> |
15 | #include <asm/hardware/cache-l2x0.h> | 15 | #include <asm/hardware/cache-l2x0.h> |
@@ -18,10 +18,9 @@ | |||
18 | #include <asm/pmu.h> | 18 | #include <asm/pmu.h> |
19 | #include <asm/smp_twd.h> | 19 | #include <asm/smp_twd.h> |
20 | 20 | ||
21 | #include <mach/clkdev.h> | ||
22 | #include <mach/ct-ca9x4.h> | 21 | #include <mach/ct-ca9x4.h> |
23 | 22 | ||
24 | #include <plat/timer-sp.h> | 23 | #include <asm/hardware/timer-sp.h> |
25 | 24 | ||
26 | #include <asm/mach/arch.h> | 25 | #include <asm/mach/arch.h> |
27 | #include <asm/mach/map.h> | 26 | #include <asm/mach/map.h> |
@@ -60,13 +59,10 @@ static void __init ct_ca9x4_map_io(void) | |||
60 | v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); | 59 | v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); |
61 | } | 60 | } |
62 | 61 | ||
63 | void __iomem *gic_cpu_base_addr; | ||
64 | |||
65 | static void __init ct_ca9x4_init_irq(void) | 62 | static void __init ct_ca9x4_init_irq(void) |
66 | { | 63 | { |
67 | gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU); | 64 | gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST), |
68 | gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29); | 65 | MMIO_P2V(A9_MPCORE_GIC_CPU)); |
69 | gic_cpu_init(0, gic_cpu_base_addr); | ||
70 | } | 66 | } |
71 | 67 | ||
72 | #if 0 | 68 | #if 0 |
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c new file mode 100644 index 00000000000..ea4cbfb90a6 --- /dev/null +++ b/arch/arm/mach-vexpress/hotplug.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-realview/hotplug.c | ||
3 | * | ||
4 | * Copyright (C) 2002 ARM Ltd. | ||
5 | * All Rights Reserved | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/smp.h> | ||
14 | |||
15 | #include <asm/cacheflush.h> | ||
16 | |||
17 | extern volatile int pen_release; | ||
18 | |||
19 | static inline void cpu_enter_lowpower(void) | ||
20 | { | ||
21 | unsigned int v; | ||
22 | |||
23 | flush_cache_all(); | ||
24 | asm volatile( | ||
25 | "mcr p15, 0, %1, c7, c5, 0\n" | ||
26 | " mcr p15, 0, %1, c7, c10, 4\n" | ||
27 | /* | ||
28 | * Turn off coherency | ||
29 | */ | ||
30 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
31 | " bic %0, %0, %3\n" | ||
32 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
33 | " mrc p15, 0, %0, c1, c0, 0\n" | ||
34 | " bic %0, %0, %2\n" | ||
35 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
36 | : "=&r" (v) | ||
37 | : "r" (0), "Ir" (CR_C), "Ir" (0x40) | ||
38 | : "cc"); | ||
39 | } | ||
40 | |||
41 | static inline void cpu_leave_lowpower(void) | ||
42 | { | ||
43 | unsigned int v; | ||
44 | |||
45 | asm volatile( | ||
46 | "mrc p15, 0, %0, c1, c0, 0\n" | ||
47 | " orr %0, %0, %1\n" | ||
48 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
49 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
50 | " orr %0, %0, %2\n" | ||
51 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
52 | : "=&r" (v) | ||
53 | : "Ir" (CR_C), "Ir" (0x40) | ||
54 | : "cc"); | ||
55 | } | ||
56 | |||
57 | static inline void platform_do_lowpower(unsigned int cpu, int *spurious) | ||
58 | { | ||
59 | /* | ||
60 | * there is no power-control hardware on this platform, so all | ||
61 | * we can do is put the core into WFI; this is safe as the calling | ||
62 | * code will have already disabled interrupts | ||
63 | */ | ||
64 | for (;;) { | ||
65 | /* | ||
66 | * here's the WFI | ||
67 | */ | ||
68 | asm(".word 0xe320f003\n" | ||
69 | : | ||
70 | : | ||
71 | : "memory", "cc"); | ||
72 | |||
73 | if (pen_release == cpu) { | ||
74 | /* | ||
75 | * OK, proper wakeup, we're done | ||
76 | */ | ||
77 | break; | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Getting here, means that we have come out of WFI without | ||
82 | * having been woken up - this shouldn't happen | ||
83 | * | ||
84 | * Just note it happening - when we're woken, we can report | ||
85 | * its occurrence. | ||
86 | */ | ||
87 | (*spurious)++; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | int platform_cpu_kill(unsigned int cpu) | ||
92 | { | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * platform-specific code to shutdown a CPU | ||
98 | * | ||
99 | * Called with IRQs disabled | ||
100 | */ | ||
101 | void platform_cpu_die(unsigned int cpu) | ||
102 | { | ||
103 | int spurious = 0; | ||
104 | |||
105 | /* | ||
106 | * we're ready for shutdown now, so do it | ||
107 | */ | ||
108 | cpu_enter_lowpower(); | ||
109 | platform_do_lowpower(cpu, &spurious); | ||
110 | |||
111 | /* | ||
112 | * bring this CPU back into the world of cache | ||
113 | * coherency, and then restore interrupts | ||
114 | */ | ||
115 | cpu_leave_lowpower(); | ||
116 | |||
117 | if (spurious) | ||
118 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); | ||
119 | } | ||
120 | |||
121 | int platform_cpu_disable(unsigned int cpu) | ||
122 | { | ||
123 | /* | ||
124 | * we don't allow CPU 0 to be shutdown (it is still too special | ||
125 | * e.g. clock tick interrupts) | ||
126 | */ | ||
127 | return cpu == 0 ? -EPERM : 0; | ||
128 | } | ||
diff --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S index 20e9fb514f0..73c11297509 100644 --- a/arch/arm/mach-vexpress/include/mach/entry-macro.S +++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S | |||
@@ -1,67 +1,7 @@ | |||
1 | #include <asm/hardware/gic.h> | 1 | #include <asm/hardware/entry-macro-gic.S> |
2 | 2 | ||
3 | .macro disable_fiq | 3 | .macro disable_fiq |
4 | .endm | 4 | .endm |
5 | 5 | ||
6 | .macro get_irqnr_preamble, base, tmp | ||
7 | ldr \base, =gic_cpu_base_addr | ||
8 | ldr \base, [\base] | ||
9 | .endm | ||
10 | |||
11 | .macro arch_ret_to_user, tmp1, tmp2 | 6 | .macro arch_ret_to_user, tmp1, tmp2 |
12 | .endm | 7 | .endm |
13 | |||
14 | /* | ||
15 | * The interrupt numbering scheme is defined in the | ||
16 | * interrupt controller spec. To wit: | ||
17 | * | ||
18 | * Interrupts 0-15 are IPI | ||
19 | * 16-28 are reserved | ||
20 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
21 | * 32-1020 are global | ||
22 | * 1021-1022 are reserved | ||
23 | * 1023 is "spurious" (no interrupt) | ||
24 | * | ||
25 | * For now, we ignore all local interrupts so only return an interrupt if it's | ||
26 | * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. | ||
27 | * | ||
28 | * A simple read from the controller will tell us the number of the highest | ||
29 | * priority enabled interrupt. We then just need to check whether it is in the | ||
30 | * valid range for an IRQ (30-1020 inclusive). | ||
31 | */ | ||
32 | |||
33 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
34 | ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ | ||
35 | ldr \tmp, =1021 | ||
36 | bic \irqnr, \irqstat, #0x1c00 | ||
37 | cmp \irqnr, #29 | ||
38 | cmpcc \irqnr, \irqnr | ||
39 | cmpne \irqnr, \tmp | ||
40 | cmpcs \irqnr, \irqnr | ||
41 | .endm | ||
42 | |||
43 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
44 | * register) is preserved from the macro above. | ||
45 | * If there is an IPI, we immediately signal end of interrupt on the | ||
46 | * controller, since this requires the original irqstat value which | ||
47 | * we won't easily be able to recreate later. | ||
48 | */ | ||
49 | |||
50 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
51 | bic \irqnr, \irqstat, #0x1c00 | ||
52 | cmp \irqnr, #16 | ||
53 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
54 | cmpcs \irqnr, \irqnr | ||
55 | .endm | ||
56 | |||
57 | /* As above, this assumes that irqstat and base are preserved.. */ | ||
58 | |||
59 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
60 | bic \irqnr, \irqstat, #0x1c00 | ||
61 | mov \tmp, #0 | ||
62 | cmp \irqnr, #29 | ||
63 | moveq \tmp, #1 | ||
64 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
65 | cmp \tmp, #0 | ||
66 | .endm | ||
67 | |||
diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h index 5a6da4fd247..4c05e4a9713 100644 --- a/arch/arm/mach-vexpress/include/mach/smp.h +++ b/arch/arm/mach-vexpress/include/mach/smp.h | |||
@@ -2,13 +2,12 @@ | |||
2 | #define __MACH_SMP_H | 2 | #define __MACH_SMP_H |
3 | 3 | ||
4 | #include <asm/hardware/gic.h> | 4 | #include <asm/hardware/gic.h> |
5 | #include <asm/smp_mpidr.h> | ||
6 | 5 | ||
7 | /* | 6 | /* |
8 | * We use IRQ1 as the IPI | 7 | * We use IRQ1 as the IPI |
9 | */ | 8 | */ |
10 | static inline void smp_cross_call(const struct cpumask *mask) | 9 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
11 | { | 10 | { |
12 | gic_raise_softirq(mask, 1); | 11 | gic_raise_softirq(mask, ipi); |
13 | } | 12 | } |
14 | #endif | 13 | #endif |
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c index 670970699ba..b1687b6abe6 100644 --- a/arch/arm/mach-vexpress/platsmp.c +++ b/arch/arm/mach-vexpress/platsmp.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | 18 | ||
19 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
20 | #include <asm/localtimer.h> | ||
21 | #include <asm/smp_scu.h> | 20 | #include <asm/smp_scu.h> |
22 | #include <asm/unified.h> | 21 | #include <asm/unified.h> |
23 | 22 | ||
@@ -35,6 +34,19 @@ extern void vexpress_secondary_startup(void); | |||
35 | */ | 34 | */ |
36 | volatile int __cpuinitdata pen_release = -1; | 35 | volatile int __cpuinitdata pen_release = -1; |
37 | 36 | ||
37 | /* | ||
38 | * Write pen_release in a way that is guaranteed to be visible to all | ||
39 | * observers, irrespective of whether they're taking part in coherency | ||
40 | * or not. This is necessary for the hotplug code to work reliably. | ||
41 | */ | ||
42 | static void write_pen_release(int val) | ||
43 | { | ||
44 | pen_release = val; | ||
45 | smp_wmb(); | ||
46 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
47 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
48 | } | ||
49 | |||
38 | static void __iomem *scu_base_addr(void) | 50 | static void __iomem *scu_base_addr(void) |
39 | { | 51 | { |
40 | return MMIO_P2V(A9_MPCORE_SCU); | 52 | return MMIO_P2V(A9_MPCORE_SCU); |
@@ -44,21 +56,18 @@ static DEFINE_SPINLOCK(boot_lock); | |||
44 | 56 | ||
45 | void __cpuinit platform_secondary_init(unsigned int cpu) | 57 | void __cpuinit platform_secondary_init(unsigned int cpu) |
46 | { | 58 | { |
47 | trace_hardirqs_off(); | ||
48 | |||
49 | /* | 59 | /* |
50 | * if any interrupts are already enabled for the primary | 60 | * if any interrupts are already enabled for the primary |
51 | * core (e.g. timer irq), then they will not have been enabled | 61 | * core (e.g. timer irq), then they will not have been enabled |
52 | * for us: do so | 62 | * for us: do so |
53 | */ | 63 | */ |
54 | gic_cpu_init(0, gic_cpu_base_addr); | 64 | gic_secondary_init(0); |
55 | 65 | ||
56 | /* | 66 | /* |
57 | * let the primary processor know we're out of the | 67 | * let the primary processor know we're out of the |
58 | * pen, then head off into the C entry point | 68 | * pen, then head off into the C entry point |
59 | */ | 69 | */ |
60 | pen_release = -1; | 70 | write_pen_release(-1); |
61 | smp_wmb(); | ||
62 | 71 | ||
63 | /* | 72 | /* |
64 | * Synchronise with the boot thread. | 73 | * Synchronise with the boot thread. |
@@ -83,16 +92,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
83 | * since we haven't sent them a soft interrupt, they shouldn't | 92 | * since we haven't sent them a soft interrupt, they shouldn't |
84 | * be there. | 93 | * be there. |
85 | */ | 94 | */ |
86 | pen_release = cpu; | 95 | write_pen_release(cpu); |
87 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | ||
88 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | ||
89 | 96 | ||
90 | /* | 97 | /* |
91 | * Send the secondary CPU a soft interrupt, thereby causing | 98 | * Send the secondary CPU a soft interrupt, thereby causing |
92 | * the boot monitor to read the system wide flags register, | 99 | * the boot monitor to read the system wide flags register, |
93 | * and branch to the address found there. | 100 | * and branch to the address found there. |
94 | */ | 101 | */ |
95 | smp_cross_call(cpumask_of(cpu)); | 102 | smp_cross_call(cpumask_of(cpu), 1); |
96 | 103 | ||
97 | timeout = jiffies + (1 * HZ); | 104 | timeout = jiffies + (1 * HZ); |
98 | while (time_before(jiffies, timeout)) { | 105 | while (time_before(jiffies, timeout)) { |
@@ -124,13 +131,6 @@ void __init smp_init_cpus(void) | |||
124 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; | 131 | ncores = scu_base ? scu_get_core_count(scu_base) : 1; |
125 | 132 | ||
126 | /* sanity check */ | 133 | /* sanity check */ |
127 | if (ncores == 0) { | ||
128 | printk(KERN_ERR | ||
129 | "vexpress: strange CM count of 0? Default to 1\n"); | ||
130 | |||
131 | ncores = 1; | ||
132 | } | ||
133 | |||
134 | if (ncores > NR_CPUS) { | 134 | if (ncores > NR_CPUS) { |
135 | printk(KERN_WARNING | 135 | printk(KERN_WARNING |
136 | "vexpress: no. of cores (%d) greater than configured " | 136 | "vexpress: no. of cores (%d) greater than configured " |
@@ -143,20 +143,10 @@ void __init smp_init_cpus(void) | |||
143 | set_cpu_possible(i, true); | 143 | set_cpu_possible(i, true); |
144 | } | 144 | } |
145 | 145 | ||
146 | void __init smp_prepare_cpus(unsigned int max_cpus) | 146 | void __init platform_smp_prepare_cpus(unsigned int max_cpus) |
147 | { | 147 | { |
148 | unsigned int ncores = num_possible_cpus(); | ||
149 | unsigned int cpu = smp_processor_id(); | ||
150 | int i; | 148 | int i; |
151 | 149 | ||
152 | smp_store_cpu_info(cpu); | ||
153 | |||
154 | /* | ||
155 | * are we trying to boot more cores than exist? | ||
156 | */ | ||
157 | if (max_cpus > ncores) | ||
158 | max_cpus = ncores; | ||
159 | |||
160 | /* | 150 | /* |
161 | * Initialise the present map, which describes the set of CPUs | 151 | * Initialise the present map, which describes the set of CPUs |
162 | * actually populated at the present time. | 152 | * actually populated at the present time. |
@@ -164,27 +154,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
164 | for (i = 0; i < max_cpus; i++) | 154 | for (i = 0; i < max_cpus; i++) |
165 | set_cpu_present(i, true); | 155 | set_cpu_present(i, true); |
166 | 156 | ||
157 | scu_enable(scu_base_addr()); | ||
158 | |||
167 | /* | 159 | /* |
168 | * Initialise the SCU if there are more than one CPU and let | 160 | * Write the address of secondary startup into the |
169 | * them know where to start. | 161 | * system-wide flags register. The boot monitor waits |
162 | * until it receives a soft interrupt, and then the | ||
163 | * secondary CPU branches to this address. | ||
170 | */ | 164 | */ |
171 | if (max_cpus > 1) { | 165 | writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); |
172 | /* | 166 | writel(BSYM(virt_to_phys(vexpress_secondary_startup)), |
173 | * Enable the local timer or broadcast device for the | 167 | MMIO_P2V(V2M_SYS_FLAGSSET)); |
174 | * boot CPU, but only if we have more than one CPU. | ||
175 | */ | ||
176 | percpu_timer_setup(); | ||
177 | |||
178 | scu_enable(scu_base_addr()); | ||
179 | |||
180 | /* | ||
181 | * Write the address of secondary startup into the | ||
182 | * system-wide flags register. The boot monitor waits | ||
183 | * until it receives a soft interrupt, and then the | ||
184 | * secondary CPU branches to this address. | ||
185 | */ | ||
186 | writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); | ||
187 | writel(BSYM(virt_to_phys(vexpress_secondary_startup)), | ||
188 | MMIO_P2V(V2M_SYS_FLAGSSET)); | ||
189 | } | ||
190 | } | 168 | } |
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 7eaa232180a..a9ed3428a2f 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c | |||
@@ -11,18 +11,18 @@ | |||
11 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
12 | #include <linux/sysdev.h> | 12 | #include <linux/sysdev.h> |
13 | #include <linux/usb/isp1760.h> | 13 | #include <linux/usb/isp1760.h> |
14 | #include <linux/clkdev.h> | ||
14 | 15 | ||
15 | #include <asm/clkdev.h> | ||
16 | #include <asm/sizes.h> | 16 | #include <asm/sizes.h> |
17 | #include <asm/mach/flash.h> | 17 | #include <asm/mach/flash.h> |
18 | #include <asm/mach/map.h> | 18 | #include <asm/mach/map.h> |
19 | #include <asm/mach/time.h> | 19 | #include <asm/mach/time.h> |
20 | #include <asm/hardware/arm_timer.h> | 20 | #include <asm/hardware/arm_timer.h> |
21 | #include <asm/hardware/timer-sp.h> | ||
21 | 22 | ||
22 | #include <mach/clkdev.h> | ||
23 | #include <mach/motherboard.h> | 23 | #include <mach/motherboard.h> |
24 | 24 | ||
25 | #include <plat/timer-sp.h> | 25 | #include <plat/sched_clock.h> |
26 | 26 | ||
27 | #include "core.h" | 27 | #include "core.h" |
28 | 28 | ||
@@ -50,6 +50,8 @@ void __init v2m_map_io(struct map_desc *tile, size_t num) | |||
50 | 50 | ||
51 | static void __init v2m_timer_init(void) | 51 | static void __init v2m_timer_init(void) |
52 | { | 52 | { |
53 | versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); | ||
54 | |||
53 | writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); | 55 | writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); |
54 | writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); | 56 | writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); |
55 | 57 | ||
diff --git a/arch/arm/mach-w90x900/clock.h b/arch/arm/mach-w90x900/clock.h index c56ddab3d91..b88a1b16b2e 100644 --- a/arch/arm/mach-w90x900/clock.h +++ b/arch/arm/mach-w90x900/clock.h | |||
@@ -10,7 +10,7 @@ | |||
10 | * the Free Software Foundation; either version 2 of the License. | 10 | * the Free Software Foundation; either version 2 of the License. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <asm/clkdev.h> | 13 | #include <linux/clkdev.h> |
14 | 14 | ||
15 | void nuc900_clk_enable(struct clk *clk, int enable); | 15 | void nuc900_clk_enable(struct clk *clk, int enable); |
16 | void nuc900_subclk_enable(struct clk *clk, int enable); | 16 | void nuc900_subclk_enable(struct clk *clk, int enable); |
diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index b80f769bc13..4b089cb930d 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c | |||
@@ -153,7 +153,6 @@ static struct clocksource clocksource_nuc900 = { | |||
153 | .rating = 200, | 153 | .rating = 200, |
154 | .read = nuc900_get_cycles, | 154 | .read = nuc900_get_cycles, |
155 | .mask = CLOCKSOURCE_MASK(TDR_SHIFT), | 155 | .mask = CLOCKSOURCE_MASK(TDR_SHIFT), |
156 | .shift = 10, | ||
157 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 156 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
158 | }; | 157 | }; |
159 | 158 | ||
@@ -176,9 +175,7 @@ static void __init nuc900_clocksource_init(void) | |||
176 | val |= (COUNTEN | PERIOD | PRESCALE); | 175 | val |= (COUNTEN | PERIOD | PRESCALE); |
177 | __raw_writel(val, REG_TCSR1); | 176 | __raw_writel(val, REG_TCSR1); |
178 | 177 | ||
179 | clocksource_nuc900.mult = | 178 | clocksource_register_hz(&clocksource_nuc900, rate); |
180 | clocksource_khz2mult((rate / 1000), clocksource_nuc900.shift); | ||
181 | clocksource_register(&clocksource_nuc900); | ||
182 | } | 179 | } |
183 | 180 | ||
184 | static void __init nuc900_timer_init(void) | 181 | static void __init nuc900_timer_init(void) |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index a099efed0e6..49db8b3e4a4 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -605,6 +605,14 @@ config CPU_CP15_MPU | |||
605 | help | 605 | help |
606 | Processor has the CP15 register, which has MPU related registers. | 606 | Processor has the CP15 register, which has MPU related registers. |
607 | 607 | ||
608 | config CPU_USE_DOMAINS | ||
609 | bool | ||
610 | depends on MMU | ||
611 | default y if !CPU_32v6K | ||
612 | help | ||
613 | This option enables or disables the use of domain switching | ||
614 | via the set_fs() function. | ||
615 | |||
608 | # | 616 | # |
609 | # CPU supports 36-bit I/O | 617 | # CPU supports 36-bit I/O |
610 | # | 618 | # |
@@ -634,6 +642,33 @@ config ARM_THUMBEE | |||
634 | Say Y here if you have a CPU with the ThumbEE extension and code to | 642 | Say Y here if you have a CPU with the ThumbEE extension and code to |
635 | make use of it. Say N for code that can run on CPUs without ThumbEE. | 643 | make use of it. Say N for code that can run on CPUs without ThumbEE. |
636 | 644 | ||
645 | config SWP_EMULATE | ||
646 | bool "Emulate SWP/SWPB instructions" | ||
647 | depends on CPU_V7 | ||
648 | select HAVE_PROC_CPU if PROC_FS | ||
649 | default y if SMP | ||
650 | help | ||
651 | ARMv6 architecture deprecates use of the SWP/SWPB instructions. | ||
652 | ARMv7 multiprocessing extensions introduce the ability to disable | ||
653 | these instructions, triggering an undefined instruction exception | ||
654 | when executed. Say Y here to enable software emulation of these | ||
655 | instructions for userspace (not kernel) using LDREX/STREX. | ||
656 | Also creates /proc/cpu/swp_emulation for statistics. | ||
657 | |||
658 | In some older versions of glibc [<=2.8] SWP is used during futex | ||
659 | trylock() operations with the assumption that the code will not | ||
660 | be preempted. This invalid assumption may be more likely to fail | ||
661 | with SWP emulation enabled, leading to deadlock of the user | ||
662 | application. | ||
663 | |||
664 | NOTE: when accessing uncached shared regions, LDREX/STREX rely | ||
665 | on an external transaction monitoring block called a global | ||
666 | monitor to maintain update atomicity. If your system does not | ||
667 | implement a global monitor, this option can cause programs that | ||
668 | perform SWP operations to uncached memory to deadlock. | ||
669 | |||
670 | If unsure, say Y. | ||
671 | |||
637 | config CPU_BIG_ENDIAN | 672 | config CPU_BIG_ENDIAN |
638 | bool "Build big-endian kernel" | 673 | bool "Build big-endian kernel" |
639 | depends on ARCH_SUPPORTS_BIG_ENDIAN | 674 | depends on ARCH_SUPPORTS_BIG_ENDIAN |
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index d63b6c41375..00d74a04af3 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -5,8 +5,8 @@ | |||
5 | obj-y := dma-mapping.o extable.o fault.o init.o \ | 5 | obj-y := dma-mapping.o extable.o fault.o init.o \ |
6 | iomap.o | 6 | iomap.o |
7 | 7 | ||
8 | obj-$(CONFIG_MMU) += fault-armv.o flush.o ioremap.o mmap.o \ | 8 | obj-$(CONFIG_MMU) += fault-armv.o flush.o idmap.o ioremap.o \ |
9 | pgd.o mmu.o vmregion.o | 9 | mmap.o pgd.o mmu.o vmregion.o |
10 | 10 | ||
11 | ifneq ($(CONFIG_MMU),y) | 11 | ifneq ($(CONFIG_MMU),y) |
12 | obj-y += nommu.o | 12 | obj-y += nommu.o |
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 6e77c042d8e..e0b0e7a4ec6 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c | |||
@@ -13,13 +13,9 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/highmem.h> | ||
16 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
17 | #include <asm/kmap_types.h> | ||
18 | #include <asm/fixmap.h> | ||
19 | #include <asm/pgtable.h> | ||
20 | #include <asm/tlbflush.h> | ||
21 | #include <plat/cache-feroceon-l2.h> | 18 | #include <plat/cache-feroceon-l2.h> |
22 | #include "mm.h" | ||
23 | 19 | ||
24 | /* | 20 | /* |
25 | * Low-level cache maintenance operations. | 21 | * Low-level cache maintenance operations. |
@@ -39,27 +35,30 @@ | |||
39 | * between which we don't want to be preempted. | 35 | * between which we don't want to be preempted. |
40 | */ | 36 | */ |
41 | 37 | ||
42 | static inline unsigned long l2_start_va(unsigned long paddr) | 38 | static inline unsigned long l2_get_va(unsigned long paddr) |
43 | { | 39 | { |
44 | #ifdef CONFIG_HIGHMEM | 40 | #ifdef CONFIG_HIGHMEM |
45 | /* | 41 | /* |
46 | * Let's do our own fixmap stuff in a minimal way here. | ||
47 | * Because range ops can't be done on physical addresses, | 42 | * Because range ops can't be done on physical addresses, |
48 | * we simply install a virtual mapping for it only for the | 43 | * we simply install a virtual mapping for it only for the |
49 | * TLB lookup to occur, hence no need to flush the untouched | 44 | * TLB lookup to occur, hence no need to flush the untouched |
50 | * memory mapping. This is protected with the disabling of | 45 | * memory mapping afterwards (note: a cache flush may happen |
51 | * interrupts by the caller. | 46 | * in some circumstances depending on the path taken in kunmap_atomic). |
52 | */ | 47 | */ |
53 | unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); | 48 | void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT); |
54 | unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 49 | return (unsigned long)vaddr + (paddr & ~PAGE_MASK); |
55 | set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0); | ||
56 | local_flush_tlb_kernel_page(vaddr); | ||
57 | return vaddr + (paddr & ~PAGE_MASK); | ||
58 | #else | 50 | #else |
59 | return __phys_to_virt(paddr); | 51 | return __phys_to_virt(paddr); |
60 | #endif | 52 | #endif |
61 | } | 53 | } |
62 | 54 | ||
55 | static inline void l2_put_va(unsigned long vaddr) | ||
56 | { | ||
57 | #ifdef CONFIG_HIGHMEM | ||
58 | kunmap_atomic((void *)vaddr); | ||
59 | #endif | ||
60 | } | ||
61 | |||
63 | static inline void l2_clean_pa(unsigned long addr) | 62 | static inline void l2_clean_pa(unsigned long addr) |
64 | { | 63 | { |
65 | __asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr)); | 64 | __asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr)); |
@@ -76,13 +75,14 @@ static inline void l2_clean_pa_range(unsigned long start, unsigned long end) | |||
76 | */ | 75 | */ |
77 | BUG_ON((start ^ end) >> PAGE_SHIFT); | 76 | BUG_ON((start ^ end) >> PAGE_SHIFT); |
78 | 77 | ||
79 | raw_local_irq_save(flags); | 78 | va_start = l2_get_va(start); |
80 | va_start = l2_start_va(start); | ||
81 | va_end = va_start + (end - start); | 79 | va_end = va_start + (end - start); |
80 | raw_local_irq_save(flags); | ||
82 | __asm__("mcr p15, 1, %0, c15, c9, 4\n\t" | 81 | __asm__("mcr p15, 1, %0, c15, c9, 4\n\t" |
83 | "mcr p15, 1, %1, c15, c9, 5" | 82 | "mcr p15, 1, %1, c15, c9, 5" |
84 | : : "r" (va_start), "r" (va_end)); | 83 | : : "r" (va_start), "r" (va_end)); |
85 | raw_local_irq_restore(flags); | 84 | raw_local_irq_restore(flags); |
85 | l2_put_va(va_start); | ||
86 | } | 86 | } |
87 | 87 | ||
88 | static inline void l2_clean_inv_pa(unsigned long addr) | 88 | static inline void l2_clean_inv_pa(unsigned long addr) |
@@ -106,13 +106,14 @@ static inline void l2_inv_pa_range(unsigned long start, unsigned long end) | |||
106 | */ | 106 | */ |
107 | BUG_ON((start ^ end) >> PAGE_SHIFT); | 107 | BUG_ON((start ^ end) >> PAGE_SHIFT); |
108 | 108 | ||
109 | raw_local_irq_save(flags); | 109 | va_start = l2_get_va(start); |
110 | va_start = l2_start_va(start); | ||
111 | va_end = va_start + (end - start); | 110 | va_end = va_start + (end - start); |
111 | raw_local_irq_save(flags); | ||
112 | __asm__("mcr p15, 1, %0, c15, c11, 4\n\t" | 112 | __asm__("mcr p15, 1, %0, c15, c11, 4\n\t" |
113 | "mcr p15, 1, %1, c15, c11, 5" | 113 | "mcr p15, 1, %1, c15, c11, 5" |
114 | : : "r" (va_start), "r" (va_end)); | 114 | : : "r" (va_start), "r" (va_end)); |
115 | raw_local_irq_restore(flags); | 115 | raw_local_irq_restore(flags); |
116 | l2_put_va(va_start); | ||
116 | } | 117 | } |
117 | 118 | ||
118 | static inline void l2_inv_all(void) | 119 | static inline void l2_inv_all(void) |
diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c index c3154928bcc..5a32020471e 100644 --- a/arch/arm/mm/cache-xsc3l2.c +++ b/arch/arm/mm/cache-xsc3l2.c | |||
@@ -17,14 +17,10 @@ | |||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/highmem.h> | ||
20 | #include <asm/system.h> | 21 | #include <asm/system.h> |
21 | #include <asm/cputype.h> | 22 | #include <asm/cputype.h> |
22 | #include <asm/cacheflush.h> | 23 | #include <asm/cacheflush.h> |
23 | #include <asm/kmap_types.h> | ||
24 | #include <asm/fixmap.h> | ||
25 | #include <asm/pgtable.h> | ||
26 | #include <asm/tlbflush.h> | ||
27 | #include "mm.h" | ||
28 | 24 | ||
29 | #define CR_L2 (1 << 26) | 25 | #define CR_L2 (1 << 26) |
30 | 26 | ||
@@ -71,16 +67,15 @@ static inline void xsc3_l2_inv_all(void) | |||
71 | dsb(); | 67 | dsb(); |
72 | } | 68 | } |
73 | 69 | ||
70 | static inline void l2_unmap_va(unsigned long va) | ||
71 | { | ||
74 | #ifdef CONFIG_HIGHMEM | 72 | #ifdef CONFIG_HIGHMEM |
75 | #define l2_map_save_flags(x) raw_local_save_flags(x) | 73 | if (va != -1) |
76 | #define l2_map_restore_flags(x) raw_local_irq_restore(x) | 74 | kunmap_atomic((void *)va); |
77 | #else | ||
78 | #define l2_map_save_flags(x) ((x) = 0) | ||
79 | #define l2_map_restore_flags(x) ((void)(x)) | ||
80 | #endif | 75 | #endif |
76 | } | ||
81 | 77 | ||
82 | static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, | 78 | static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va) |
83 | unsigned long flags) | ||
84 | { | 79 | { |
85 | #ifdef CONFIG_HIGHMEM | 80 | #ifdef CONFIG_HIGHMEM |
86 | unsigned long va = prev_va & PAGE_MASK; | 81 | unsigned long va = prev_va & PAGE_MASK; |
@@ -89,17 +84,10 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, | |||
89 | /* | 84 | /* |
90 | * Switching to a new page. Because cache ops are | 85 | * Switching to a new page. Because cache ops are |
91 | * using virtual addresses only, we must put a mapping | 86 | * using virtual addresses only, we must put a mapping |
92 | * in place for it. We also enable interrupts for a | 87 | * in place for it. |
93 | * short while and disable them again to protect this | ||
94 | * mapping. | ||
95 | */ | 88 | */ |
96 | unsigned long idx; | 89 | l2_unmap_va(prev_va); |
97 | raw_local_irq_restore(flags); | 90 | va = (unsigned long)kmap_atomic_pfn(pa >> PAGE_SHIFT); |
98 | idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id(); | ||
99 | va = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
100 | raw_local_irq_restore(flags | PSR_I_BIT); | ||
101 | set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0); | ||
102 | local_flush_tlb_kernel_page(va); | ||
103 | } | 91 | } |
104 | return va + (pa_offset >> (32 - PAGE_SHIFT)); | 92 | return va + (pa_offset >> (32 - PAGE_SHIFT)); |
105 | #else | 93 | #else |
@@ -109,7 +97,7 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va, | |||
109 | 97 | ||
110 | static void xsc3_l2_inv_range(unsigned long start, unsigned long end) | 98 | static void xsc3_l2_inv_range(unsigned long start, unsigned long end) |
111 | { | 99 | { |
112 | unsigned long vaddr, flags; | 100 | unsigned long vaddr; |
113 | 101 | ||
114 | if (start == 0 && end == -1ul) { | 102 | if (start == 0 && end == -1ul) { |
115 | xsc3_l2_inv_all(); | 103 | xsc3_l2_inv_all(); |
@@ -117,13 +105,12 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end) | |||
117 | } | 105 | } |
118 | 106 | ||
119 | vaddr = -1; /* to force the first mapping */ | 107 | vaddr = -1; /* to force the first mapping */ |
120 | l2_map_save_flags(flags); | ||
121 | 108 | ||
122 | /* | 109 | /* |
123 | * Clean and invalidate partial first cache line. | 110 | * Clean and invalidate partial first cache line. |
124 | */ | 111 | */ |
125 | if (start & (CACHE_LINE_SIZE - 1)) { | 112 | if (start & (CACHE_LINE_SIZE - 1)) { |
126 | vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags); | 113 | vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr); |
127 | xsc3_l2_clean_mva(vaddr); | 114 | xsc3_l2_clean_mva(vaddr); |
128 | xsc3_l2_inv_mva(vaddr); | 115 | xsc3_l2_inv_mva(vaddr); |
129 | start = (start | (CACHE_LINE_SIZE - 1)) + 1; | 116 | start = (start | (CACHE_LINE_SIZE - 1)) + 1; |
@@ -133,7 +120,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end) | |||
133 | * Invalidate all full cache lines between 'start' and 'end'. | 120 | * Invalidate all full cache lines between 'start' and 'end'. |
134 | */ | 121 | */ |
135 | while (start < (end & ~(CACHE_LINE_SIZE - 1))) { | 122 | while (start < (end & ~(CACHE_LINE_SIZE - 1))) { |
136 | vaddr = l2_map_va(start, vaddr, flags); | 123 | vaddr = l2_map_va(start, vaddr); |
137 | xsc3_l2_inv_mva(vaddr); | 124 | xsc3_l2_inv_mva(vaddr); |
138 | start += CACHE_LINE_SIZE; | 125 | start += CACHE_LINE_SIZE; |
139 | } | 126 | } |
@@ -142,31 +129,30 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end) | |||
142 | * Clean and invalidate partial last cache line. | 129 | * Clean and invalidate partial last cache line. |
143 | */ | 130 | */ |
144 | if (start < end) { | 131 | if (start < end) { |
145 | vaddr = l2_map_va(start, vaddr, flags); | 132 | vaddr = l2_map_va(start, vaddr); |
146 | xsc3_l2_clean_mva(vaddr); | 133 | xsc3_l2_clean_mva(vaddr); |
147 | xsc3_l2_inv_mva(vaddr); | 134 | xsc3_l2_inv_mva(vaddr); |
148 | } | 135 | } |
149 | 136 | ||
150 | l2_map_restore_flags(flags); | 137 | l2_unmap_va(vaddr); |
151 | 138 | ||
152 | dsb(); | 139 | dsb(); |
153 | } | 140 | } |
154 | 141 | ||
155 | static void xsc3_l2_clean_range(unsigned long start, unsigned long end) | 142 | static void xsc3_l2_clean_range(unsigned long start, unsigned long end) |
156 | { | 143 | { |
157 | unsigned long vaddr, flags; | 144 | unsigned long vaddr; |
158 | 145 | ||
159 | vaddr = -1; /* to force the first mapping */ | 146 | vaddr = -1; /* to force the first mapping */ |
160 | l2_map_save_flags(flags); | ||
161 | 147 | ||
162 | start &= ~(CACHE_LINE_SIZE - 1); | 148 | start &= ~(CACHE_LINE_SIZE - 1); |
163 | while (start < end) { | 149 | while (start < end) { |
164 | vaddr = l2_map_va(start, vaddr, flags); | 150 | vaddr = l2_map_va(start, vaddr); |
165 | xsc3_l2_clean_mva(vaddr); | 151 | xsc3_l2_clean_mva(vaddr); |
166 | start += CACHE_LINE_SIZE; | 152 | start += CACHE_LINE_SIZE; |
167 | } | 153 | } |
168 | 154 | ||
169 | l2_map_restore_flags(flags); | 155 | l2_unmap_va(vaddr); |
170 | 156 | ||
171 | dsb(); | 157 | dsb(); |
172 | } | 158 | } |
@@ -193,7 +179,7 @@ static inline void xsc3_l2_flush_all(void) | |||
193 | 179 | ||
194 | static void xsc3_l2_flush_range(unsigned long start, unsigned long end) | 180 | static void xsc3_l2_flush_range(unsigned long start, unsigned long end) |
195 | { | 181 | { |
196 | unsigned long vaddr, flags; | 182 | unsigned long vaddr; |
197 | 183 | ||
198 | if (start == 0 && end == -1ul) { | 184 | if (start == 0 && end == -1ul) { |
199 | xsc3_l2_flush_all(); | 185 | xsc3_l2_flush_all(); |
@@ -201,17 +187,16 @@ static void xsc3_l2_flush_range(unsigned long start, unsigned long end) | |||
201 | } | 187 | } |
202 | 188 | ||
203 | vaddr = -1; /* to force the first mapping */ | 189 | vaddr = -1; /* to force the first mapping */ |
204 | l2_map_save_flags(flags); | ||
205 | 190 | ||
206 | start &= ~(CACHE_LINE_SIZE - 1); | 191 | start &= ~(CACHE_LINE_SIZE - 1); |
207 | while (start < end) { | 192 | while (start < end) { |
208 | vaddr = l2_map_va(start, vaddr, flags); | 193 | vaddr = l2_map_va(start, vaddr); |
209 | xsc3_l2_clean_mva(vaddr); | 194 | xsc3_l2_clean_mva(vaddr); |
210 | xsc3_l2_inv_mva(vaddr); | 195 | xsc3_l2_inv_mva(vaddr); |
211 | start += CACHE_LINE_SIZE; | 196 | start += CACHE_LINE_SIZE; |
212 | } | 197 | } |
213 | 198 | ||
214 | l2_map_restore_flags(flags); | 199 | l2_unmap_va(vaddr); |
215 | 200 | ||
216 | dsb(); | 201 | dsb(); |
217 | } | 202 | } |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index ac6a36142fc..6b48e0a3d7a 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/device.h> | 18 | #include <linux/device.h> |
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | #include <linux/highmem.h> | ||
20 | 21 | ||
21 | #include <asm/memory.h> | 22 | #include <asm/memory.h> |
22 | #include <asm/highmem.h> | 23 | #include <asm/highmem.h> |
@@ -311,7 +312,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, | |||
311 | addr = page_address(page); | 312 | addr = page_address(page); |
312 | 313 | ||
313 | if (addr) | 314 | if (addr) |
314 | *handle = page_to_dma(dev, page); | 315 | *handle = pfn_to_dma(dev, page_to_pfn(page)); |
315 | 316 | ||
316 | return addr; | 317 | return addr; |
317 | } | 318 | } |
@@ -406,7 +407,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr | |||
406 | if (!arch_is_coherent()) | 407 | if (!arch_is_coherent()) |
407 | __dma_free_remap(cpu_addr, size); | 408 | __dma_free_remap(cpu_addr, size); |
408 | 409 | ||
409 | __dma_free_buffer(dma_to_page(dev, handle), size); | 410 | __dma_free_buffer(pfn_to_page(dma_to_pfn(dev, handle)), size); |
410 | } | 411 | } |
411 | EXPORT_SYMBOL(dma_free_coherent); | 412 | EXPORT_SYMBOL(dma_free_coherent); |
412 | 413 | ||
@@ -480,10 +481,10 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, | |||
480 | op(vaddr, len, dir); | 481 | op(vaddr, len, dir); |
481 | kunmap_high(page); | 482 | kunmap_high(page); |
482 | } else if (cache_is_vipt()) { | 483 | } else if (cache_is_vipt()) { |
483 | pte_t saved_pte; | 484 | /* unmapped pages might still be cached */ |
484 | vaddr = kmap_high_l1_vipt(page, &saved_pte); | 485 | vaddr = kmap_atomic(page); |
485 | op(vaddr + offset, len, dir); | 486 | op(vaddr + offset, len, dir); |
486 | kunmap_high_l1_vipt(page, saved_pte); | 487 | kunmap_atomic(vaddr); |
487 | } | 488 | } |
488 | } else { | 489 | } else { |
489 | vaddr = page_address(page) + offset; | 490 | vaddr = page_address(page) + offset; |
@@ -554,17 +555,20 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
554 | struct scatterlist *s; | 555 | struct scatterlist *s; |
555 | int i, j; | 556 | int i, j; |
556 | 557 | ||
558 | BUG_ON(!valid_dma_direction(dir)); | ||
559 | |||
557 | for_each_sg(sg, s, nents, i) { | 560 | for_each_sg(sg, s, nents, i) { |
558 | s->dma_address = dma_map_page(dev, sg_page(s), s->offset, | 561 | s->dma_address = __dma_map_page(dev, sg_page(s), s->offset, |
559 | s->length, dir); | 562 | s->length, dir); |
560 | if (dma_mapping_error(dev, s->dma_address)) | 563 | if (dma_mapping_error(dev, s->dma_address)) |
561 | goto bad_mapping; | 564 | goto bad_mapping; |
562 | } | 565 | } |
566 | debug_dma_map_sg(dev, sg, nents, nents, dir); | ||
563 | return nents; | 567 | return nents; |
564 | 568 | ||
565 | bad_mapping: | 569 | bad_mapping: |
566 | for_each_sg(sg, s, i, j) | 570 | for_each_sg(sg, s, i, j) |
567 | dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); | 571 | __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); |
568 | return 0; | 572 | return 0; |
569 | } | 573 | } |
570 | EXPORT_SYMBOL(dma_map_sg); | 574 | EXPORT_SYMBOL(dma_map_sg); |
@@ -585,8 +589,10 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
585 | struct scatterlist *s; | 589 | struct scatterlist *s; |
586 | int i; | 590 | int i; |
587 | 591 | ||
592 | debug_dma_unmap_sg(dev, sg, nents, dir); | ||
593 | |||
588 | for_each_sg(sg, s, nents, i) | 594 | for_each_sg(sg, s, nents, i) |
589 | dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); | 595 | __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); |
590 | } | 596 | } |
591 | EXPORT_SYMBOL(dma_unmap_sg); | 597 | EXPORT_SYMBOL(dma_unmap_sg); |
592 | 598 | ||
@@ -611,6 +617,8 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | |||
611 | __dma_page_dev_to_cpu(sg_page(s), s->offset, | 617 | __dma_page_dev_to_cpu(sg_page(s), s->offset, |
612 | s->length, dir); | 618 | s->length, dir); |
613 | } | 619 | } |
620 | |||
621 | debug_dma_sync_sg_for_cpu(dev, sg, nents, dir); | ||
614 | } | 622 | } |
615 | EXPORT_SYMBOL(dma_sync_sg_for_cpu); | 623 | EXPORT_SYMBOL(dma_sync_sg_for_cpu); |
616 | 624 | ||
@@ -635,5 +643,16 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | |||
635 | __dma_page_cpu_to_dev(sg_page(s), s->offset, | 643 | __dma_page_cpu_to_dev(sg_page(s), s->offset, |
636 | s->length, dir); | 644 | s->length, dir); |
637 | } | 645 | } |
646 | |||
647 | debug_dma_sync_sg_for_device(dev, sg, nents, dir); | ||
638 | } | 648 | } |
639 | EXPORT_SYMBOL(dma_sync_sg_for_device); | 649 | EXPORT_SYMBOL(dma_sync_sg_for_device); |
650 | |||
651 | #define PREALLOC_DMA_DEBUG_ENTRIES 4096 | ||
652 | |||
653 | static int __init dma_debug_do_init(void) | ||
654 | { | ||
655 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); | ||
656 | return 0; | ||
657 | } | ||
658 | fs_initcall(dma_debug_do_init); | ||
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 83e59f87042..01210dba022 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #include "mm.h" | 27 | #include "mm.h" |
28 | 28 | ||
29 | static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE; | 29 | static pteval_t shared_pte_mask = L_PTE_MT_BUFFERABLE; |
30 | 30 | ||
31 | #if __LINUX_ARM_ARCH__ < 6 | 31 | #if __LINUX_ARM_ARCH__ < 6 |
32 | /* | 32 | /* |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 1e21e125fe3..f10f9bac220 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -108,7 +108,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
108 | 108 | ||
109 | pte = pte_offset_map(pmd, addr); | 109 | pte = pte_offset_map(pmd, addr); |
110 | printk(", *pte=%08lx", pte_val(*pte)); | 110 | printk(", *pte=%08lx", pte_val(*pte)); |
111 | printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE])); | 111 | printk(", *ppte=%08lx", pte_val(pte[PTE_HWTABLE_PTRS])); |
112 | pte_unmap(pte); | 112 | pte_unmap(pte); |
113 | } while(0); | 113 | } while(0); |
114 | 114 | ||
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 391ffae7509..c29f2839f1d 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
13 | #include <linux/highmem.h> | ||
13 | 14 | ||
14 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
15 | #include <asm/cachetype.h> | 16 | #include <asm/cachetype.h> |
@@ -180,10 +181,10 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page) | |||
180 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); | 181 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); |
181 | kunmap_high(page); | 182 | kunmap_high(page); |
182 | } else if (cache_is_vipt()) { | 183 | } else if (cache_is_vipt()) { |
183 | pte_t saved_pte; | 184 | /* unmapped pages might still be cached */ |
184 | addr = kmap_high_l1_vipt(page, &saved_pte); | 185 | addr = kmap_atomic(page); |
185 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); | 186 | __cpuc_flush_dcache_area(addr, PAGE_SIZE); |
186 | kunmap_high_l1_vipt(page, saved_pte); | 187 | kunmap_atomic(addr); |
187 | } | 188 | } |
188 | } | 189 | } |
189 | 190 | ||
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index c435fd9e1da..807c0573abb 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c | |||
@@ -140,90 +140,3 @@ struct page *kmap_atomic_to_page(const void *ptr) | |||
140 | pte = TOP_PTE(vaddr); | 140 | pte = TOP_PTE(vaddr); |
141 | return pte_page(*pte); | 141 | return pte_page(*pte); |
142 | } | 142 | } |
143 | |||
144 | #ifdef CONFIG_CPU_CACHE_VIPT | ||
145 | |||
146 | #include <linux/percpu.h> | ||
147 | |||
148 | /* | ||
149 | * The VIVT cache of a highmem page is always flushed before the page | ||
150 | * is unmapped. Hence unmapped highmem pages need no cache maintenance | ||
151 | * in that case. | ||
152 | * | ||
153 | * However unmapped pages may still be cached with a VIPT cache, and | ||
154 | * it is not possible to perform cache maintenance on them using physical | ||
155 | * addresses unfortunately. So we have no choice but to set up a temporary | ||
156 | * virtual mapping for that purpose. | ||
157 | * | ||
158 | * Yet this VIPT cache maintenance may be triggered from DMA support | ||
159 | * functions which are possibly called from interrupt context. As we don't | ||
160 | * want to keep interrupt disabled all the time when such maintenance is | ||
161 | * taking place, we therefore allow for some reentrancy by preserving and | ||
162 | * restoring the previous fixmap entry before the interrupted context is | ||
163 | * resumed. If the reentrancy depth is 0 then there is no need to restore | ||
164 | * the previous fixmap, and leaving the current one in place allow it to | ||
165 | * be reused the next time without a TLB flush (common with DMA). | ||
166 | */ | ||
167 | |||
168 | static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth); | ||
169 | |||
170 | void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte) | ||
171 | { | ||
172 | unsigned int idx, cpu; | ||
173 | int *depth; | ||
174 | unsigned long vaddr, flags; | ||
175 | pte_t pte, *ptep; | ||
176 | |||
177 | if (!in_interrupt()) | ||
178 | preempt_disable(); | ||
179 | |||
180 | cpu = smp_processor_id(); | ||
181 | depth = &per_cpu(kmap_high_l1_vipt_depth, cpu); | ||
182 | |||
183 | idx = KM_L1_CACHE + KM_TYPE_NR * cpu; | ||
184 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
185 | ptep = TOP_PTE(vaddr); | ||
186 | pte = mk_pte(page, kmap_prot); | ||
187 | |||
188 | raw_local_irq_save(flags); | ||
189 | (*depth)++; | ||
190 | if (pte_val(*ptep) == pte_val(pte)) { | ||
191 | *saved_pte = pte; | ||
192 | } else { | ||
193 | *saved_pte = *ptep; | ||
194 | set_pte_ext(ptep, pte, 0); | ||
195 | local_flush_tlb_kernel_page(vaddr); | ||
196 | } | ||
197 | raw_local_irq_restore(flags); | ||
198 | |||
199 | return (void *)vaddr; | ||
200 | } | ||
201 | |||
202 | void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte) | ||
203 | { | ||
204 | unsigned int idx, cpu = smp_processor_id(); | ||
205 | int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu); | ||
206 | unsigned long vaddr, flags; | ||
207 | pte_t pte, *ptep; | ||
208 | |||
209 | idx = KM_L1_CACHE + KM_TYPE_NR * cpu; | ||
210 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
211 | ptep = TOP_PTE(vaddr); | ||
212 | pte = mk_pte(page, kmap_prot); | ||
213 | |||
214 | BUG_ON(pte_val(*ptep) != pte_val(pte)); | ||
215 | BUG_ON(*depth <= 0); | ||
216 | |||
217 | raw_local_irq_save(flags); | ||
218 | (*depth)--; | ||
219 | if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) { | ||
220 | set_pte_ext(ptep, saved_pte, 0); | ||
221 | local_flush_tlb_kernel_page(vaddr); | ||
222 | } | ||
223 | raw_local_irq_restore(flags); | ||
224 | |||
225 | if (!in_interrupt()) | ||
226 | preempt_enable(); | ||
227 | } | ||
228 | |||
229 | #endif /* CONFIG_CPU_CACHE_VIPT */ | ||
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c new file mode 100644 index 00000000000..57299446f78 --- /dev/null +++ b/arch/arm/mm/idmap.c | |||
@@ -0,0 +1,67 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | |||
3 | #include <asm/cputype.h> | ||
4 | #include <asm/pgalloc.h> | ||
5 | #include <asm/pgtable.h> | ||
6 | |||
7 | static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
8 | unsigned long prot) | ||
9 | { | ||
10 | pmd_t *pmd = pmd_offset(pgd, addr); | ||
11 | |||
12 | addr = (addr & PMD_MASK) | prot; | ||
13 | pmd[0] = __pmd(addr); | ||
14 | addr += SECTION_SIZE; | ||
15 | pmd[1] = __pmd(addr); | ||
16 | flush_pmd_entry(pmd); | ||
17 | } | ||
18 | |||
19 | void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) | ||
20 | { | ||
21 | unsigned long prot, next; | ||
22 | |||
23 | prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE; | ||
24 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) | ||
25 | prot |= PMD_BIT4; | ||
26 | |||
27 | pgd += pgd_index(addr); | ||
28 | do { | ||
29 | next = pgd_addr_end(addr, end); | ||
30 | idmap_add_pmd(pgd, addr, next, prot); | ||
31 | } while (pgd++, addr = next, addr != end); | ||
32 | } | ||
33 | |||
34 | #ifdef CONFIG_SMP | ||
35 | static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end) | ||
36 | { | ||
37 | pmd_t *pmd = pmd_offset(pgd, addr); | ||
38 | pmd_clear(pmd); | ||
39 | } | ||
40 | |||
41 | void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) | ||
42 | { | ||
43 | unsigned long next; | ||
44 | |||
45 | pgd += pgd_index(addr); | ||
46 | do { | ||
47 | next = pgd_addr_end(addr, end); | ||
48 | idmap_del_pmd(pgd, addr, next); | ||
49 | } while (pgd++, addr = next, addr != end); | ||
50 | } | ||
51 | #endif | ||
52 | |||
53 | /* | ||
54 | * In order to soft-boot, we need to insert a 1:1 mapping in place of | ||
55 | * the user-mode pages. This will then ensure that we have predictable | ||
56 | * results when turning the mmu off | ||
57 | */ | ||
58 | void setup_mm_for_reboot(char mode) | ||
59 | { | ||
60 | /* | ||
61 | * We need to access to user-mode page tables here. For kernel threads | ||
62 | * we don't have any user-mode mappings so we use the context that we | ||
63 | * "borrowed". | ||
64 | */ | ||
65 | identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE); | ||
66 | local_flush_tlb_all(); | ||
67 | } | ||
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 55c17a6fb22..ab506272b2d 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c | |||
@@ -204,12 +204,8 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, | |||
204 | /* | 204 | /* |
205 | * Don't allow RAM to be mapped - this causes problems with ARMv6+ | 205 | * Don't allow RAM to be mapped - this causes problems with ARMv6+ |
206 | */ | 206 | */ |
207 | if (pfn_valid(pfn)) { | 207 | if (WARN_ON(pfn_valid(pfn))) |
208 | printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory. This leads\n" | 208 | return NULL; |
209 | "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n" | ||
210 | "will fail in the next kernel release. Please fix your driver.\n"); | ||
211 | WARN_ON(1); | ||
212 | } | ||
213 | 209 | ||
214 | type = get_mem_type(mtype); | 210 | type = get_mem_type(mtype); |
215 | if (!type) | 211 | if (!type) |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 6630620380a..36960df5fb7 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -16,7 +16,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt) | |||
16 | } | 16 | } |
17 | 17 | ||
18 | struct mem_type { | 18 | struct mem_type { |
19 | unsigned int prot_pte; | 19 | pteval_t prot_pte; |
20 | unsigned int prot_l1; | 20 | unsigned int prot_l1; |
21 | unsigned int prot_sect; | 21 | unsigned int prot_sect; |
22 | unsigned int domain; | 22 | unsigned int domain; |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 72ad3e1f56c..3c67e92f7d5 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/smp_plat.h> | 24 | #include <asm/smp_plat.h> |
25 | #include <asm/tlb.h> | 25 | #include <asm/tlb.h> |
26 | #include <asm/highmem.h> | 26 | #include <asm/highmem.h> |
27 | #include <asm/traps.h> | ||
27 | 28 | ||
28 | #include <asm/mach/arch.h> | 29 | #include <asm/mach/arch.h> |
29 | #include <asm/mach/map.h> | 30 | #include <asm/mach/map.h> |
@@ -62,7 +63,7 @@ struct cachepolicy { | |||
62 | const char policy[16]; | 63 | const char policy[16]; |
63 | unsigned int cr_mask; | 64 | unsigned int cr_mask; |
64 | unsigned int pmd; | 65 | unsigned int pmd; |
65 | unsigned int pte; | 66 | pteval_t pte; |
66 | }; | 67 | }; |
67 | 68 | ||
68 | static struct cachepolicy cache_policies[] __initdata = { | 69 | static struct cachepolicy cache_policies[] __initdata = { |
@@ -190,7 +191,7 @@ void adjust_cr(unsigned long mask, unsigned long set) | |||
190 | } | 191 | } |
191 | #endif | 192 | #endif |
192 | 193 | ||
193 | #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE | 194 | #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN |
194 | #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE | 195 | #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE |
195 | 196 | ||
196 | static struct mem_type mem_types[] = { | 197 | static struct mem_type mem_types[] = { |
@@ -235,19 +236,18 @@ static struct mem_type mem_types[] = { | |||
235 | }, | 236 | }, |
236 | [MT_LOW_VECTORS] = { | 237 | [MT_LOW_VECTORS] = { |
237 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 238 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
238 | L_PTE_EXEC, | 239 | L_PTE_RDONLY, |
239 | .prot_l1 = PMD_TYPE_TABLE, | 240 | .prot_l1 = PMD_TYPE_TABLE, |
240 | .domain = DOMAIN_USER, | 241 | .domain = DOMAIN_USER, |
241 | }, | 242 | }, |
242 | [MT_HIGH_VECTORS] = { | 243 | [MT_HIGH_VECTORS] = { |
243 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 244 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
244 | L_PTE_USER | L_PTE_EXEC, | 245 | L_PTE_USER | L_PTE_RDONLY, |
245 | .prot_l1 = PMD_TYPE_TABLE, | 246 | .prot_l1 = PMD_TYPE_TABLE, |
246 | .domain = DOMAIN_USER, | 247 | .domain = DOMAIN_USER, |
247 | }, | 248 | }, |
248 | [MT_MEMORY] = { | 249 | [MT_MEMORY] = { |
249 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 250 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, |
250 | L_PTE_WRITE | L_PTE_EXEC, | ||
251 | .prot_l1 = PMD_TYPE_TABLE, | 251 | .prot_l1 = PMD_TYPE_TABLE, |
252 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, | 252 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, |
253 | .domain = DOMAIN_KERNEL, | 253 | .domain = DOMAIN_KERNEL, |
@@ -258,21 +258,20 @@ static struct mem_type mem_types[] = { | |||
258 | }, | 258 | }, |
259 | [MT_MEMORY_NONCACHED] = { | 259 | [MT_MEMORY_NONCACHED] = { |
260 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 260 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
261 | L_PTE_WRITE | L_PTE_EXEC | L_PTE_MT_BUFFERABLE, | 261 | L_PTE_MT_BUFFERABLE, |
262 | .prot_l1 = PMD_TYPE_TABLE, | 262 | .prot_l1 = PMD_TYPE_TABLE, |
263 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, | 263 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, |
264 | .domain = DOMAIN_KERNEL, | 264 | .domain = DOMAIN_KERNEL, |
265 | }, | 265 | }, |
266 | [MT_MEMORY_DTCM] = { | 266 | [MT_MEMORY_DTCM] = { |
267 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 267 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
268 | L_PTE_WRITE, | 268 | L_PTE_XN, |
269 | .prot_l1 = PMD_TYPE_TABLE, | 269 | .prot_l1 = PMD_TYPE_TABLE, |
270 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, | 270 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, |
271 | .domain = DOMAIN_KERNEL, | 271 | .domain = DOMAIN_KERNEL, |
272 | }, | 272 | }, |
273 | [MT_MEMORY_ITCM] = { | 273 | [MT_MEMORY_ITCM] = { |
274 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 274 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY, |
275 | L_PTE_WRITE | L_PTE_EXEC, | ||
276 | .prot_l1 = PMD_TYPE_TABLE, | 275 | .prot_l1 = PMD_TYPE_TABLE, |
277 | .domain = DOMAIN_KERNEL, | 276 | .domain = DOMAIN_KERNEL, |
278 | }, | 277 | }, |
@@ -479,7 +478,7 @@ static void __init build_mem_type_table(void) | |||
479 | 478 | ||
480 | pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); | 479 | pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); |
481 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | | 480 | pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | |
482 | L_PTE_DIRTY | L_PTE_WRITE | kern_pgprot); | 481 | L_PTE_DIRTY | kern_pgprot); |
483 | 482 | ||
484 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; | 483 | mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; |
485 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; | 484 | mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; |
@@ -535,7 +534,7 @@ static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned l | |||
535 | { | 534 | { |
536 | if (pmd_none(*pmd)) { | 535 | if (pmd_none(*pmd)) { |
537 | pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t)); | 536 | pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t)); |
538 | __pmd_populate(pmd, __pa(pte) | prot); | 537 | __pmd_populate(pmd, __pa(pte), prot); |
539 | } | 538 | } |
540 | BUG_ON(pmd_bad(*pmd)); | 539 | BUG_ON(pmd_bad(*pmd)); |
541 | return pte_offset_kernel(pmd, addr); | 540 | return pte_offset_kernel(pmd, addr); |
@@ -553,7 +552,7 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | |||
553 | } | 552 | } |
554 | 553 | ||
555 | static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, | 554 | static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, |
556 | unsigned long end, unsigned long phys, | 555 | unsigned long end, phys_addr_t phys, |
557 | const struct mem_type *type) | 556 | const struct mem_type *type) |
558 | { | 557 | { |
559 | pmd_t *pmd = pmd_offset(pgd, addr); | 558 | pmd_t *pmd = pmd_offset(pgd, addr); |
@@ -588,7 +587,8 @@ static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, | |||
588 | static void __init create_36bit_mapping(struct map_desc *md, | 587 | static void __init create_36bit_mapping(struct map_desc *md, |
589 | const struct mem_type *type) | 588 | const struct mem_type *type) |
590 | { | 589 | { |
591 | unsigned long phys, addr, length, end; | 590 | unsigned long addr, length, end; |
591 | phys_addr_t phys; | ||
592 | pgd_t *pgd; | 592 | pgd_t *pgd; |
593 | 593 | ||
594 | addr = md->virtual; | 594 | addr = md->virtual; |
@@ -914,12 +914,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
914 | { | 914 | { |
915 | struct map_desc map; | 915 | struct map_desc map; |
916 | unsigned long addr; | 916 | unsigned long addr; |
917 | void *vectors; | ||
918 | 917 | ||
919 | /* | 918 | /* |
920 | * Allocate the vector page early. | 919 | * Allocate the vector page early. |
921 | */ | 920 | */ |
922 | vectors = early_alloc(PAGE_SIZE); | 921 | vectors_page = early_alloc(PAGE_SIZE); |
923 | 922 | ||
924 | for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) | 923 | for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) |
925 | pmd_clear(pmd_off_k(addr)); | 924 | pmd_clear(pmd_off_k(addr)); |
@@ -959,7 +958,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
959 | * location (0xffff0000). If we aren't using high-vectors, also | 958 | * location (0xffff0000). If we aren't using high-vectors, also |
960 | * create a mapping at the low-vectors virtual address. | 959 | * create a mapping at the low-vectors virtual address. |
961 | */ | 960 | */ |
962 | map.pfn = __phys_to_pfn(virt_to_phys(vectors)); | 961 | map.pfn = __phys_to_pfn(virt_to_phys(vectors_page)); |
963 | map.virtual = 0xffff0000; | 962 | map.virtual = 0xffff0000; |
964 | map.length = PAGE_SIZE; | 963 | map.length = PAGE_SIZE; |
965 | map.type = MT_HIGH_VECTORS; | 964 | map.type = MT_HIGH_VECTORS; |
@@ -1044,38 +1043,3 @@ void __init paging_init(struct machine_desc *mdesc) | |||
1044 | empty_zero_page = virt_to_page(zero_page); | 1043 | empty_zero_page = virt_to_page(zero_page); |
1045 | __flush_dcache_page(NULL, empty_zero_page); | 1044 | __flush_dcache_page(NULL, empty_zero_page); |
1046 | } | 1045 | } |
1047 | |||
1048 | /* | ||
1049 | * In order to soft-boot, we need to insert a 1:1 mapping in place of | ||
1050 | * the user-mode pages. This will then ensure that we have predictable | ||
1051 | * results when turning the mmu off | ||
1052 | */ | ||
1053 | void setup_mm_for_reboot(char mode) | ||
1054 | { | ||
1055 | unsigned long base_pmdval; | ||
1056 | pgd_t *pgd; | ||
1057 | int i; | ||
1058 | |||
1059 | /* | ||
1060 | * We need to access to user-mode page tables here. For kernel threads | ||
1061 | * we don't have any user-mode mappings so we use the context that we | ||
1062 | * "borrowed". | ||
1063 | */ | ||
1064 | pgd = current->active_mm->pgd; | ||
1065 | |||
1066 | base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT; | ||
1067 | if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) | ||
1068 | base_pmdval |= PMD_BIT4; | ||
1069 | |||
1070 | for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) { | ||
1071 | unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval; | ||
1072 | pmd_t *pmd; | ||
1073 | |||
1074 | pmd = pmd_off(pgd, i << PGDIR_SHIFT); | ||
1075 | pmd[0] = __pmd(pmdval); | ||
1076 | pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); | ||
1077 | flush_pmd_entry(pmd); | ||
1078 | } | ||
1079 | |||
1080 | local_flush_tlb_all(); | ||
1081 | } | ||
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index 69bbfc6645a..93292a18cf7 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c | |||
@@ -17,12 +17,10 @@ | |||
17 | 17 | ||
18 | #include "mm.h" | 18 | #include "mm.h" |
19 | 19 | ||
20 | #define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD) | ||
21 | |||
22 | /* | 20 | /* |
23 | * need to get a 16k page for level 1 | 21 | * need to get a 16k page for level 1 |
24 | */ | 22 | */ |
25 | pgd_t *get_pgd_slow(struct mm_struct *mm) | 23 | pgd_t *pgd_alloc(struct mm_struct *mm) |
26 | { | 24 | { |
27 | pgd_t *new_pgd, *init_pgd; | 25 | pgd_t *new_pgd, *init_pgd; |
28 | pmd_t *new_pmd, *init_pmd; | 26 | pmd_t *new_pmd, *init_pmd; |
@@ -32,14 +30,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm) | |||
32 | if (!new_pgd) | 30 | if (!new_pgd) |
33 | goto no_pgd; | 31 | goto no_pgd; |
34 | 32 | ||
35 | memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t)); | 33 | memset(new_pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); |
36 | 34 | ||
37 | /* | 35 | /* |
38 | * Copy over the kernel and IO PGD entries | 36 | * Copy over the kernel and IO PGD entries |
39 | */ | 37 | */ |
40 | init_pgd = pgd_offset_k(0); | 38 | init_pgd = pgd_offset_k(0); |
41 | memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR, | 39 | memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD, |
42 | (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); | 40 | (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); |
43 | 41 | ||
44 | clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); | 42 | clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t)); |
45 | 43 | ||
@@ -73,28 +71,29 @@ no_pgd: | |||
73 | return NULL; | 71 | return NULL; |
74 | } | 72 | } |
75 | 73 | ||
76 | void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd) | 74 | void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) |
77 | { | 75 | { |
76 | pgd_t *pgd; | ||
78 | pmd_t *pmd; | 77 | pmd_t *pmd; |
79 | pgtable_t pte; | 78 | pgtable_t pte; |
80 | 79 | ||
81 | if (!pgd) | 80 | if (!pgd_base) |
82 | return; | 81 | return; |
83 | 82 | ||
84 | /* pgd is always present and good */ | 83 | pgd = pgd_base + pgd_index(0); |
85 | pmd = pmd_off(pgd, 0); | 84 | if (pgd_none_or_clear_bad(pgd)) |
86 | if (pmd_none(*pmd)) | 85 | goto no_pgd; |
87 | goto free; | 86 | |
88 | if (pmd_bad(*pmd)) { | 87 | pmd = pmd_offset(pgd, 0); |
89 | pmd_ERROR(*pmd); | 88 | if (pmd_none_or_clear_bad(pmd)) |
90 | pmd_clear(pmd); | 89 | goto no_pmd; |
91 | goto free; | ||
92 | } | ||
93 | 90 | ||
94 | pte = pmd_pgtable(*pmd); | 91 | pte = pmd_pgtable(*pmd); |
95 | pmd_clear(pmd); | 92 | pmd_clear(pmd); |
96 | pte_free(mm, pte); | 93 | pte_free(mm, pte); |
94 | no_pmd: | ||
95 | pgd_clear(pgd); | ||
97 | pmd_free(mm, pmd); | 96 | pmd_free(mm, pmd); |
98 | free: | 97 | no_pgd: |
99 | free_pages((unsigned long) pgd, 2); | 98 | free_pages((unsigned long) pgd_base, 2); |
100 | } | 99 | } |
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index b795afd0a2c..e32fa499194 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S | |||
@@ -91,7 +91,7 @@ | |||
91 | #if L_PTE_SHARED != PTE_EXT_SHARED | 91 | #if L_PTE_SHARED != PTE_EXT_SHARED |
92 | #error PTE shared bit mismatch | 92 | #error PTE shared bit mismatch |
93 | #endif | 93 | #endif |
94 | #if (L_PTE_EXEC+L_PTE_USER+L_PTE_WRITE+L_PTE_DIRTY+L_PTE_YOUNG+\ | 94 | #if (L_PTE_XN+L_PTE_USER+L_PTE_RDONLY+L_PTE_DIRTY+L_PTE_YOUNG+\ |
95 | L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED | 95 | L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED |
96 | #error Invalid Linux PTE bit settings | 96 | #error Invalid Linux PTE bit settings |
97 | #endif | 97 | #endif |
@@ -109,6 +109,10 @@ | |||
109 | * 110x 0 1 0 r/w r/o | 109 | * 110x 0 1 0 r/w r/o |
110 | * 11x0 0 1 0 r/w r/o | 110 | * 11x0 0 1 0 r/w r/o |
111 | * 1111 0 1 1 r/w r/w | 111 | * 1111 0 1 1 r/w r/w |
112 | * | ||
113 | * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed: | ||
114 | * 110x 1 1 1 r/o r/o | ||
115 | * 11x0 1 1 1 r/o r/o | ||
112 | */ | 116 | */ |
113 | .macro armv6_mt_table pfx | 117 | .macro armv6_mt_table pfx |
114 | \pfx\()_mt_table: | 118 | \pfx\()_mt_table: |
@@ -131,7 +135,7 @@ | |||
131 | .endm | 135 | .endm |
132 | 136 | ||
133 | .macro armv6_set_pte_ext pfx | 137 | .macro armv6_set_pte_ext pfx |
134 | str r1, [r0], #-2048 @ linux version | 138 | str r1, [r0], #2048 @ linux version |
135 | 139 | ||
136 | bic r3, r1, #0x000003fc | 140 | bic r3, r1, #0x000003fc |
137 | bic r3, r3, #PTE_TYPE_MASK | 141 | bic r3, r3, #PTE_TYPE_MASK |
@@ -142,17 +146,20 @@ | |||
142 | and r2, r1, #L_PTE_MT_MASK | 146 | and r2, r1, #L_PTE_MT_MASK |
143 | ldr r2, [ip, r2] | 147 | ldr r2, [ip, r2] |
144 | 148 | ||
145 | tst r1, #L_PTE_WRITE | 149 | eor r1, r1, #L_PTE_DIRTY |
146 | tstne r1, #L_PTE_DIRTY | 150 | tst r1, #L_PTE_DIRTY|L_PTE_RDONLY |
147 | orreq r3, r3, #PTE_EXT_APX | 151 | orrne r3, r3, #PTE_EXT_APX |
148 | 152 | ||
149 | tst r1, #L_PTE_USER | 153 | tst r1, #L_PTE_USER |
150 | orrne r3, r3, #PTE_EXT_AP1 | 154 | orrne r3, r3, #PTE_EXT_AP1 |
155 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
156 | @ allow kernel read/write access to read-only user pages | ||
151 | tstne r3, #PTE_EXT_APX | 157 | tstne r3, #PTE_EXT_APX |
152 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | 158 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
159 | #endif | ||
153 | 160 | ||
154 | tst r1, #L_PTE_EXEC | 161 | tst r1, #L_PTE_XN |
155 | orreq r3, r3, #PTE_EXT_XN | 162 | orrne r3, r3, #PTE_EXT_XN |
156 | 163 | ||
157 | orr r3, r3, r2 | 164 | orr r3, r3, r2 |
158 | 165 | ||
@@ -180,9 +187,9 @@ | |||
180 | * 1111 0xff r/w r/w | 187 | * 1111 0xff r/w r/w |
181 | */ | 188 | */ |
182 | .macro armv3_set_pte_ext wc_disable=1 | 189 | .macro armv3_set_pte_ext wc_disable=1 |
183 | str r1, [r0], #-2048 @ linux version | 190 | str r1, [r0], #2048 @ linux version |
184 | 191 | ||
185 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY | 192 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
186 | 193 | ||
187 | bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits | 194 | bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits |
188 | bic r2, r2, #PTE_TYPE_MASK | 195 | bic r2, r2, #PTE_TYPE_MASK |
@@ -191,7 +198,7 @@ | |||
191 | tst r3, #L_PTE_USER @ user? | 198 | tst r3, #L_PTE_USER @ user? |
192 | orrne r2, r2, #PTE_SMALL_AP_URO_SRW | 199 | orrne r2, r2, #PTE_SMALL_AP_URO_SRW |
193 | 200 | ||
194 | tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? | 201 | tst r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty? |
195 | orreq r2, r2, #PTE_SMALL_AP_UNO_SRW | 202 | orreq r2, r2, #PTE_SMALL_AP_UNO_SRW |
196 | 203 | ||
197 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? | 204 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? |
@@ -203,7 +210,7 @@ | |||
203 | bicne r2, r2, #PTE_BUFFERABLE | 210 | bicne r2, r2, #PTE_BUFFERABLE |
204 | #endif | 211 | #endif |
205 | .endif | 212 | .endif |
206 | str r2, [r0] @ hardware version | 213 | str r2, [r0] @ hardware version |
207 | .endm | 214 | .endm |
208 | 215 | ||
209 | 216 | ||
@@ -223,9 +230,9 @@ | |||
223 | * 1111 11 r/w r/w | 230 | * 1111 11 r/w r/w |
224 | */ | 231 | */ |
225 | .macro xscale_set_pte_ext_prologue | 232 | .macro xscale_set_pte_ext_prologue |
226 | str r1, [r0], #-2048 @ linux version | 233 | str r1, [r0] @ linux version |
227 | 234 | ||
228 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY | 235 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
229 | 236 | ||
230 | bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits | 237 | bic r2, r1, #PTE_SMALL_AP_MASK @ keep C, B bits |
231 | orr r2, r2, #PTE_TYPE_EXT @ extended page | 238 | orr r2, r2, #PTE_TYPE_EXT @ extended page |
@@ -233,7 +240,7 @@ | |||
233 | tst r3, #L_PTE_USER @ user? | 240 | tst r3, #L_PTE_USER @ user? |
234 | orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w | 241 | orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w |
235 | 242 | ||
236 | tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty? | 243 | tst r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty? |
237 | orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w | 244 | orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w |
238 | @ combined with user -> user r/w | 245 | @ combined with user -> user r/w |
239 | .endm | 246 | .endm |
@@ -242,7 +249,7 @@ | |||
242 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? | 249 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young? |
243 | movne r2, #0 @ no -> fault | 250 | movne r2, #0 @ no -> fault |
244 | 251 | ||
245 | str r2, [r0] @ hardware version | 252 | str r2, [r0, #2048]! @ hardware version |
246 | mov ip, #0 | 253 | mov ip, #0 |
247 | mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line | 254 | mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line |
248 | mcr p15, 0, ip, c7, c10, 4 @ data write barrier | 255 | mcr p15, 0, ip, c7, c10, 4 @ data write barrier |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 9b9ff5d949f..b49fab21517 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -124,15 +124,13 @@ ENDPROC(cpu_v7_switch_mm) | |||
124 | * Set a level 2 translation table entry. | 124 | * Set a level 2 translation table entry. |
125 | * | 125 | * |
126 | * - ptep - pointer to level 2 translation table entry | 126 | * - ptep - pointer to level 2 translation table entry |
127 | * (hardware version is stored at -1024 bytes) | 127 | * (hardware version is stored at +2048 bytes) |
128 | * - pte - PTE value to store | 128 | * - pte - PTE value to store |
129 | * - ext - value for extended PTE bits | 129 | * - ext - value for extended PTE bits |
130 | */ | 130 | */ |
131 | ENTRY(cpu_v7_set_pte_ext) | 131 | ENTRY(cpu_v7_set_pte_ext) |
132 | #ifdef CONFIG_MMU | 132 | #ifdef CONFIG_MMU |
133 | ARM( str r1, [r0], #-2048 ) @ linux version | 133 | str r1, [r0] @ linux version |
134 | THUMB( str r1, [r0] ) @ linux version | ||
135 | THUMB( sub r0, r0, #2048 ) | ||
136 | 134 | ||
137 | bic r3, r1, #0x000003f0 | 135 | bic r3, r1, #0x000003f0 |
138 | bic r3, r3, #PTE_TYPE_MASK | 136 | bic r3, r3, #PTE_TYPE_MASK |
@@ -142,23 +140,26 @@ ENTRY(cpu_v7_set_pte_ext) | |||
142 | tst r1, #1 << 4 | 140 | tst r1, #1 << 4 |
143 | orrne r3, r3, #PTE_EXT_TEX(1) | 141 | orrne r3, r3, #PTE_EXT_TEX(1) |
144 | 142 | ||
145 | tst r1, #L_PTE_WRITE | 143 | eor r1, r1, #L_PTE_DIRTY |
146 | tstne r1, #L_PTE_DIRTY | 144 | tst r1, #L_PTE_RDONLY | L_PTE_DIRTY |
147 | orreq r3, r3, #PTE_EXT_APX | 145 | orrne r3, r3, #PTE_EXT_APX |
148 | 146 | ||
149 | tst r1, #L_PTE_USER | 147 | tst r1, #L_PTE_USER |
150 | orrne r3, r3, #PTE_EXT_AP1 | 148 | orrne r3, r3, #PTE_EXT_AP1 |
149 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
150 | @ allow kernel read/write access to read-only user pages | ||
151 | tstne r3, #PTE_EXT_APX | 151 | tstne r3, #PTE_EXT_APX |
152 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | 152 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
153 | #endif | ||
153 | 154 | ||
154 | tst r1, #L_PTE_EXEC | 155 | tst r1, #L_PTE_XN |
155 | orreq r3, r3, #PTE_EXT_XN | 156 | orrne r3, r3, #PTE_EXT_XN |
156 | 157 | ||
157 | tst r1, #L_PTE_YOUNG | 158 | tst r1, #L_PTE_YOUNG |
158 | tstne r1, #L_PTE_PRESENT | 159 | tstne r1, #L_PTE_PRESENT |
159 | moveq r3, #0 | 160 | moveq r3, #0 |
160 | 161 | ||
161 | str r3, [r0] | 162 | str r3, [r0, #2048]! |
162 | mcr p15, 0, r0, c7, c10, 1 @ flush_pte | 163 | mcr p15, 0, r0, c7, c10, 1 @ flush_pte |
163 | #endif | 164 | #endif |
164 | mov pc, lr | 165 | mov pc, lr |
@@ -273,8 +274,6 @@ __v7_setup: | |||
273 | ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) | 274 | ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) |
274 | ALT_UP(orr r4, r4, #TTB_FLAGS_UP) | 275 | ALT_UP(orr r4, r4, #TTB_FLAGS_UP) |
275 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 | 276 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 |
276 | mov r10, #0x1f @ domains 0, 1 = manager | ||
277 | mcr p15, 0, r10, c3, c0, 0 @ load domain access register | ||
278 | /* | 277 | /* |
279 | * Memory region attributes with SCTLR.TRE=1 | 278 | * Memory region attributes with SCTLR.TRE=1 |
280 | * | 279 | * |
@@ -313,6 +312,10 @@ __v7_setup: | |||
313 | #ifdef CONFIG_CPU_ENDIAN_BE8 | 312 | #ifdef CONFIG_CPU_ENDIAN_BE8 |
314 | orr r6, r6, #1 << 25 @ big-endian page tables | 313 | orr r6, r6, #1 << 25 @ big-endian page tables |
315 | #endif | 314 | #endif |
315 | #ifdef CONFIG_SWP_EMULATE | ||
316 | orr r5, r5, #(1 << 10) @ set SW bit in "clear" | ||
317 | bic r6, r6, #(1 << 10) @ clear it in "mmuset" | ||
318 | #endif | ||
316 | mrc p15, 0, r0, c1, c0, 0 @ read control register | 319 | mrc p15, 0, r0, c1, c0, 0 @ read control register |
317 | bic r0, r0, r5 @ clear bits them | 320 | bic r0, r0, r5 @ clear bits them |
318 | orr r0, r0, r6 @ set them | 321 | orr r0, r0, r6 @ set them |
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 523408c0bb3..5a37c5e45c4 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S | |||
@@ -500,8 +500,8 @@ ENTRY(cpu_xscale_set_pte_ext) | |||
500 | @ | 500 | @ |
501 | @ Erratum 40: must set memory to write-through for user read-only pages | 501 | @ Erratum 40: must set memory to write-through for user read-only pages |
502 | @ | 502 | @ |
503 | and ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_WRITE) & ~(4 << 2) | 503 | and ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_RDONLY) & ~(4 << 2) |
504 | teq ip, #L_PTE_MT_WRITEBACK | L_PTE_USER | 504 | teq ip, #L_PTE_MT_WRITEBACK | L_PTE_USER | L_PTE_RDONLY |
505 | 505 | ||
506 | moveq r1, #L_PTE_MT_WRITETHROUGH | 506 | moveq r1, #L_PTE_MT_WRITETHROUGH |
507 | and r1, r1, #L_PTE_MT_MASK | 507 | and r1, r1, #L_PTE_MT_MASK |
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 558cdfaf76b..07f23bb42be 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/sched.h> | ||
20 | #include <linux/timex.h> | 21 | #include <linux/timex.h> |
21 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
@@ -24,6 +25,7 @@ | |||
24 | #include <linux/clockchips.h> | 25 | #include <linux/clockchips.h> |
25 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
26 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
28 | #include <asm/sched_clock.h> | ||
27 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
28 | #include <asm/mach/irq.h> | 30 | #include <asm/mach/irq.h> |
29 | #include <asm/mach/time.h> | 31 | #include <asm/mach/time.h> |
@@ -50,15 +52,21 @@ static struct clocksource iop_clocksource = { | |||
50 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 52 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
51 | }; | 53 | }; |
52 | 54 | ||
55 | static DEFINE_CLOCK_DATA(cd); | ||
56 | |||
53 | /* | 57 | /* |
54 | * IOP sched_clock() implementation via its clocksource. | 58 | * IOP sched_clock() implementation via its clocksource. |
55 | */ | 59 | */ |
56 | unsigned long long sched_clock(void) | 60 | unsigned long long notrace sched_clock(void) |
57 | { | 61 | { |
58 | cycle_t cyc = iop_clocksource_read(NULL); | 62 | u32 cyc = 0xffffffffu - read_tcr1(); |
59 | struct clocksource *cs = &iop_clocksource; | 63 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
64 | } | ||
60 | 65 | ||
61 | return clocksource_cyc2ns(cyc, cs->mult, cs->shift); | 66 | static void notrace iop_update_sched_clock(void) |
67 | { | ||
68 | u32 cyc = 0xffffffffu - read_tcr1(); | ||
69 | update_sched_clock(&cd, cyc, (u32)~0); | ||
62 | } | 70 | } |
63 | 71 | ||
64 | /* | 72 | /* |
@@ -88,6 +96,7 @@ static void iop_set_mode(enum clock_event_mode mode, | |||
88 | case CLOCK_EVT_MODE_PERIODIC: | 96 | case CLOCK_EVT_MODE_PERIODIC: |
89 | write_tmr0(tmr & ~IOP_TMR_EN); | 97 | write_tmr0(tmr & ~IOP_TMR_EN); |
90 | write_tcr0(ticks_per_jiffy - 1); | 98 | write_tcr0(ticks_per_jiffy - 1); |
99 | write_trr0(ticks_per_jiffy - 1); | ||
91 | tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN); | 100 | tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN); |
92 | break; | 101 | break; |
93 | case CLOCK_EVT_MODE_ONESHOT: | 102 | case CLOCK_EVT_MODE_ONESHOT: |
@@ -143,6 +152,8 @@ void __init iop_init_time(unsigned long tick_rate) | |||
143 | { | 152 | { |
144 | u32 timer_ctl; | 153 | u32 timer_ctl; |
145 | 154 | ||
155 | init_sched_clock(&cd, iop_update_sched_clock, 32, tick_rate); | ||
156 | |||
146 | ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ); | 157 | ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ); |
147 | iop_tick_rate = tick_rate; | 158 | iop_tick_rate = tick_rate; |
148 | 159 | ||
@@ -153,6 +164,7 @@ void __init iop_init_time(unsigned long tick_rate) | |||
153 | * Set up interrupting clockevent timer 0. | 164 | * Set up interrupting clockevent timer 0. |
154 | */ | 165 | */ |
155 | write_tmr0(timer_ctl & ~IOP_TMR_EN); | 166 | write_tmr0(timer_ctl & ~IOP_TMR_EN); |
167 | write_tisr(1); | ||
156 | setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq); | 168 | setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq); |
157 | clockevents_calc_mult_shift(&iop_clockevent, | 169 | clockevents_calc_mult_shift(&iop_clockevent, |
158 | tick_rate, IOP_MIN_RANGE); | 170 | tick_rate, IOP_MIN_RANGE); |
@@ -162,9 +174,6 @@ void __init iop_init_time(unsigned long tick_rate) | |||
162 | clockevent_delta2ns(0xf, &iop_clockevent); | 174 | clockevent_delta2ns(0xf, &iop_clockevent); |
163 | iop_clockevent.cpumask = cpumask_of(0); | 175 | iop_clockevent.cpumask = cpumask_of(0); |
164 | clockevents_register_device(&iop_clockevent); | 176 | clockevents_register_device(&iop_clockevent); |
165 | write_trr0(ticks_per_jiffy - 1); | ||
166 | write_tcr0(ticks_per_jiffy - 1); | ||
167 | write_tmr0(timer_ctl); | ||
168 | 177 | ||
169 | /* | 178 | /* |
170 | * Set up free-running clocksource timer 1. | 179 | * Set up free-running clocksource timer 1. |
@@ -172,7 +181,5 @@ void __init iop_init_time(unsigned long tick_rate) | |||
172 | write_trr1(0xffffffff); | 181 | write_trr1(0xffffffff); |
173 | write_tcr1(0xffffffff); | 182 | write_tcr1(0xffffffff); |
174 | write_tmr1(timer_ctl); | 183 | write_tmr1(timer_ctl); |
175 | clocksource_calc_mult_shift(&iop_clocksource, tick_rate, | 184 | clocksource_register_hz(&iop_clocksource, tick_rate); |
176 | IOP_MIN_RANGE); | ||
177 | clocksource_register(&iop_clocksource); | ||
178 | } | 185 | } |
diff --git a/arch/arm/plat-mxc/epit.c b/arch/arm/plat-mxc/epit.c index ee9582f4972..d69d343ff61 100644 --- a/arch/arm/plat-mxc/epit.c +++ b/arch/arm/plat-mxc/epit.c | |||
@@ -93,7 +93,6 @@ static struct clocksource clocksource_epit = { | |||
93 | .rating = 200, | 93 | .rating = 200, |
94 | .read = epit_read, | 94 | .read = epit_read, |
95 | .mask = CLOCKSOURCE_MASK(32), | 95 | .mask = CLOCKSOURCE_MASK(32), |
96 | .shift = 20, | ||
97 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 96 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
98 | }; | 97 | }; |
99 | 98 | ||
@@ -101,9 +100,7 @@ static int __init epit_clocksource_init(struct clk *timer_clk) | |||
101 | { | 100 | { |
102 | unsigned int c = clk_get_rate(timer_clk); | 101 | unsigned int c = clk_get_rate(timer_clk); |
103 | 102 | ||
104 | clocksource_epit.mult = clocksource_hz2mult(c, | 103 | clocksource_register_hz(&clocksource_epit, c); |
105 | clocksource_epit.shift); | ||
106 | clocksource_register(&clocksource_epit); | ||
107 | 104 | ||
108 | return 0; | 105 | return 0; |
109 | } | 106 | } |
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index f9a1b059a76..9f0c2610595 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c | |||
@@ -120,7 +120,6 @@ static struct clocksource clocksource_mxc = { | |||
120 | .rating = 200, | 120 | .rating = 200, |
121 | .read = mx1_2_get_cycles, | 121 | .read = mx1_2_get_cycles, |
122 | .mask = CLOCKSOURCE_MASK(32), | 122 | .mask = CLOCKSOURCE_MASK(32), |
123 | .shift = 20, | ||
124 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 123 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
125 | }; | 124 | }; |
126 | 125 | ||
@@ -131,9 +130,7 @@ static int __init mxc_clocksource_init(struct clk *timer_clk) | |||
131 | if (timer_is_v2()) | 130 | if (timer_is_v2()) |
132 | clocksource_mxc.read = v2_get_cycles; | 131 | clocksource_mxc.read = v2_get_cycles; |
133 | 132 | ||
134 | clocksource_mxc.mult = clocksource_hz2mult(c, | 133 | clocksource_register_hz(&clocksource_mxc, c); |
135 | clocksource_mxc.shift); | ||
136 | clocksource_register(&clocksource_mxc); | ||
137 | 134 | ||
138 | return 0; | 135 | return 0; |
139 | } | 136 | } |
diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig index 5da3f97c537..187f4e84bb2 100644 --- a/arch/arm/plat-nomadik/Kconfig +++ b/arch/arm/plat-nomadik/Kconfig | |||
@@ -14,6 +14,7 @@ if PLAT_NOMADIK | |||
14 | 14 | ||
15 | config HAS_MTU | 15 | config HAS_MTU |
16 | bool | 16 | bool |
17 | select HAVE_SCHED_CLOCK | ||
17 | help | 18 | help |
18 | Support for Multi Timer Unit. MTU provides access | 19 | Support for Multi Timer Unit. MTU provides access |
19 | to multiple interrupt generating programmable | 20 | to multiple interrupt generating programmable |
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index 63cdc6025bd..41723402006 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c | |||
@@ -17,9 +17,9 @@ | |||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/cnt32_to_63.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/timer.h> | ||
22 | #include <asm/mach/time.h> | 21 | #include <asm/mach/time.h> |
22 | #include <asm/sched_clock.h> | ||
23 | 23 | ||
24 | #include <plat/mtu.h> | 24 | #include <plat/mtu.h> |
25 | 25 | ||
@@ -52,81 +52,24 @@ static struct clocksource nmdk_clksrc = { | |||
52 | * Override the global weak sched_clock symbol with this | 52 | * Override the global weak sched_clock symbol with this |
53 | * local implementation which uses the clocksource to get some | 53 | * local implementation which uses the clocksource to get some |
54 | * better resolution when scheduling the kernel. | 54 | * better resolution when scheduling the kernel. |
55 | * | ||
56 | * Because the hardware timer period may be quite short | ||
57 | * (32.3 secs on the 133 MHz MTU timer selection on ux500) | ||
58 | * and because cnt32_to_63() needs to be called at least once per | ||
59 | * half period to work properly, a kernel keepwarm() timer is set up | ||
60 | * to ensure this requirement is always met. | ||
61 | * | ||
62 | * Also the sched_clock timer will wrap around at some point, | ||
63 | * here we set it to run continously for a year. | ||
64 | */ | 55 | */ |
65 | #define SCHED_CLOCK_MIN_WRAP 3600*24*365 | 56 | static DEFINE_CLOCK_DATA(cd); |
66 | static struct timer_list cnt32_to_63_keepwarm_timer; | ||
67 | static u32 sched_mult; | ||
68 | static u32 sched_shift; | ||
69 | 57 | ||
70 | unsigned long long notrace sched_clock(void) | 58 | unsigned long long notrace sched_clock(void) |
71 | { | 59 | { |
72 | u64 cycles; | 60 | u32 cyc; |
73 | 61 | ||
74 | if (unlikely(!mtu_base)) | 62 | if (unlikely(!mtu_base)) |
75 | return 0; | 63 | return 0; |
76 | 64 | ||
77 | cycles = cnt32_to_63(-readl(mtu_base + MTU_VAL(0))); | 65 | cyc = -readl(mtu_base + MTU_VAL(0)); |
78 | /* | 66 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
79 | * sched_mult is guaranteed to be even so will | ||
80 | * shift out bit 63 | ||
81 | */ | ||
82 | return (cycles * sched_mult) >> sched_shift; | ||
83 | } | 67 | } |
84 | 68 | ||
85 | /* Just kick sched_clock every so often */ | 69 | static void notrace nomadik_update_sched_clock(void) |
86 | static void cnt32_to_63_keepwarm(unsigned long data) | ||
87 | { | 70 | { |
88 | mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data)); | 71 | u32 cyc = -readl(mtu_base + MTU_VAL(0)); |
89 | (void) sched_clock(); | 72 | update_sched_clock(&cd, cyc, (u32)~0); |
90 | } | ||
91 | |||
92 | /* | ||
93 | * Set up a timer to keep sched_clock():s 32_to_63 algorithm warm | ||
94 | * once in half a 32bit timer wrap interval. | ||
95 | */ | ||
96 | static void __init nmdk_sched_clock_init(unsigned long rate) | ||
97 | { | ||
98 | u32 v; | ||
99 | unsigned long delta; | ||
100 | u64 days; | ||
101 | |||
102 | /* Find the apropriate mult and shift factors */ | ||
103 | clocks_calc_mult_shift(&sched_mult, &sched_shift, | ||
104 | rate, NSEC_PER_SEC, SCHED_CLOCK_MIN_WRAP); | ||
105 | /* We need to multiply by an even number to get rid of bit 63 */ | ||
106 | if (sched_mult & 1) | ||
107 | sched_mult++; | ||
108 | |||
109 | /* Let's see what we get, take max counter and scale it */ | ||
110 | days = (0xFFFFFFFFFFFFFFFFLLU * sched_mult) >> sched_shift; | ||
111 | do_div(days, NSEC_PER_SEC); | ||
112 | do_div(days, (3600*24)); | ||
113 | |||
114 | pr_info("sched_clock: using %d bits @ %lu Hz wrap in %lu days\n", | ||
115 | (64 - sched_shift), rate, (unsigned long) days); | ||
116 | |||
117 | /* | ||
118 | * Program a timer to kick us at half 32bit wraparound | ||
119 | * Formula: seconds per wrap = (2^32) / f | ||
120 | */ | ||
121 | v = 0xFFFFFFFFUL / rate; | ||
122 | /* We want half of the wrap time to keep cnt32_to_63 warm */ | ||
123 | v /= 2; | ||
124 | pr_debug("sched_clock: prescaled timer rate: %lu Hz, " | ||
125 | "initialize keepwarm timer every %d seconds\n", rate, v); | ||
126 | /* Convert seconds to jiffies */ | ||
127 | delta = msecs_to_jiffies(v*1000); | ||
128 | setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, delta); | ||
129 | mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + delta)); | ||
130 | } | 73 | } |
131 | 74 | ||
132 | /* Clockevent device: use one-shot mode */ | 75 | /* Clockevent device: use one-shot mode */ |
@@ -222,7 +165,6 @@ void __init nmdk_timer_init(void) | |||
222 | } else { | 165 | } else { |
223 | cr |= MTU_CRn_PRESCALE_1; | 166 | cr |= MTU_CRn_PRESCALE_1; |
224 | } | 167 | } |
225 | clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE); | ||
226 | 168 | ||
227 | /* Timer 0 is the free running clocksource */ | 169 | /* Timer 0 is the free running clocksource */ |
228 | writel(cr, mtu_base + MTU_CR(0)); | 170 | writel(cr, mtu_base + MTU_CR(0)); |
@@ -233,11 +175,11 @@ void __init nmdk_timer_init(void) | |||
233 | /* Now the clock source is ready */ | 175 | /* Now the clock source is ready */ |
234 | nmdk_clksrc.read = nmdk_read_timer; | 176 | nmdk_clksrc.read = nmdk_read_timer; |
235 | 177 | ||
236 | if (clocksource_register(&nmdk_clksrc)) | 178 | if (clocksource_register_hz(&nmdk_clksrc, rate)) |
237 | pr_err("timer: failed to initialize clock source %s\n", | 179 | pr_err("timer: failed to initialize clock source %s\n", |
238 | nmdk_clksrc.name); | 180 | nmdk_clksrc.name); |
239 | 181 | ||
240 | nmdk_sched_clock_init(rate); | 182 | init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate); |
241 | 183 | ||
242 | /* Timer 1 is used for events */ | 184 | /* Timer 1 is used for events */ |
243 | 185 | ||
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 92c5bb7909f..c9408434a85 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -11,13 +11,13 @@ choice | |||
11 | 11 | ||
12 | config ARCH_OMAP1 | 12 | config ARCH_OMAP1 |
13 | bool "TI OMAP1" | 13 | bool "TI OMAP1" |
14 | select COMMON_CLKDEV | 14 | select CLKDEV_LOOKUP |
15 | help | 15 | help |
16 | "Systems based on omap7xx, omap15xx or omap16xx" | 16 | "Systems based on omap7xx, omap15xx or omap16xx" |
17 | 17 | ||
18 | config ARCH_OMAP2PLUS | 18 | config ARCH_OMAP2PLUS |
19 | bool "TI OMAP2/3/4" | 19 | bool "TI OMAP2/3/4" |
20 | select COMMON_CLKDEV | 20 | select CLKDEV_LOOKUP |
21 | help | 21 | help |
22 | "Systems based on OMAP2, OMAP3 or OMAP4" | 22 | "Systems based on OMAP2, OMAP3 or OMAP4" |
23 | 23 | ||
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index 8722a136f3a..ea4644021fb 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c | |||
@@ -15,8 +15,11 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/io.h> | ||
19 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/io.h> | ||
20 | #include <linux/sched.h> | ||
21 | |||
22 | #include <asm/sched_clock.h> | ||
20 | 23 | ||
21 | #include <plat/common.h> | 24 | #include <plat/common.h> |
22 | #include <plat/board.h> | 25 | #include <plat/board.h> |
@@ -45,7 +48,7 @@ | |||
45 | static u32 offset_32k __read_mostly; | 48 | static u32 offset_32k __read_mostly; |
46 | 49 | ||
47 | #ifdef CONFIG_ARCH_OMAP16XX | 50 | #ifdef CONFIG_ARCH_OMAP16XX |
48 | static cycle_t omap16xx_32k_read(struct clocksource *cs) | 51 | static cycle_t notrace omap16xx_32k_read(struct clocksource *cs) |
49 | { | 52 | { |
50 | return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k; | 53 | return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k; |
51 | } | 54 | } |
@@ -54,7 +57,7 @@ static cycle_t omap16xx_32k_read(struct clocksource *cs) | |||
54 | #endif | 57 | #endif |
55 | 58 | ||
56 | #ifdef CONFIG_ARCH_OMAP2420 | 59 | #ifdef CONFIG_ARCH_OMAP2420 |
57 | static cycle_t omap2420_32k_read(struct clocksource *cs) | 60 | static cycle_t notrace omap2420_32k_read(struct clocksource *cs) |
58 | { | 61 | { |
59 | return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k; | 62 | return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k; |
60 | } | 63 | } |
@@ -63,7 +66,7 @@ static cycle_t omap2420_32k_read(struct clocksource *cs) | |||
63 | #endif | 66 | #endif |
64 | 67 | ||
65 | #ifdef CONFIG_ARCH_OMAP2430 | 68 | #ifdef CONFIG_ARCH_OMAP2430 |
66 | static cycle_t omap2430_32k_read(struct clocksource *cs) | 69 | static cycle_t notrace omap2430_32k_read(struct clocksource *cs) |
67 | { | 70 | { |
68 | return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k; | 71 | return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k; |
69 | } | 72 | } |
@@ -72,7 +75,7 @@ static cycle_t omap2430_32k_read(struct clocksource *cs) | |||
72 | #endif | 75 | #endif |
73 | 76 | ||
74 | #ifdef CONFIG_ARCH_OMAP3 | 77 | #ifdef CONFIG_ARCH_OMAP3 |
75 | static cycle_t omap34xx_32k_read(struct clocksource *cs) | 78 | static cycle_t notrace omap34xx_32k_read(struct clocksource *cs) |
76 | { | 79 | { |
77 | return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k; | 80 | return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k; |
78 | } | 81 | } |
@@ -81,7 +84,7 @@ static cycle_t omap34xx_32k_read(struct clocksource *cs) | |||
81 | #endif | 84 | #endif |
82 | 85 | ||
83 | #ifdef CONFIG_ARCH_OMAP4 | 86 | #ifdef CONFIG_ARCH_OMAP4 |
84 | static cycle_t omap44xx_32k_read(struct clocksource *cs) | 87 | static cycle_t notrace omap44xx_32k_read(struct clocksource *cs) |
85 | { | 88 | { |
86 | return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k; | 89 | return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k; |
87 | } | 90 | } |
@@ -93,7 +96,7 @@ static cycle_t omap44xx_32k_read(struct clocksource *cs) | |||
93 | * Kernel assumes that sched_clock can be called early but may not have | 96 | * Kernel assumes that sched_clock can be called early but may not have |
94 | * things ready yet. | 97 | * things ready yet. |
95 | */ | 98 | */ |
96 | static cycle_t omap_32k_read_dummy(struct clocksource *cs) | 99 | static cycle_t notrace omap_32k_read_dummy(struct clocksource *cs) |
97 | { | 100 | { |
98 | return 0; | 101 | return 0; |
99 | } | 102 | } |
@@ -103,7 +106,6 @@ static struct clocksource clocksource_32k = { | |||
103 | .rating = 250, | 106 | .rating = 250, |
104 | .read = omap_32k_read_dummy, | 107 | .read = omap_32k_read_dummy, |
105 | .mask = CLOCKSOURCE_MASK(32), | 108 | .mask = CLOCKSOURCE_MASK(32), |
106 | .shift = 10, | ||
107 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 109 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
108 | }; | 110 | }; |
109 | 111 | ||
@@ -111,10 +113,25 @@ static struct clocksource clocksource_32k = { | |||
111 | * Returns current time from boot in nsecs. It's OK for this to wrap | 113 | * Returns current time from boot in nsecs. It's OK for this to wrap |
112 | * around for now, as it's just a relative time stamp. | 114 | * around for now, as it's just a relative time stamp. |
113 | */ | 115 | */ |
114 | unsigned long long sched_clock(void) | 116 | static DEFINE_CLOCK_DATA(cd); |
117 | |||
118 | /* | ||
119 | * Constants generated by clocks_calc_mult_shift(m, s, 32768, NSEC_PER_SEC, 60). | ||
120 | * This gives a resolution of about 30us and a wrap period of about 36hrs. | ||
121 | */ | ||
122 | #define SC_MULT 4000000000u | ||
123 | #define SC_SHIFT 17 | ||
124 | |||
125 | unsigned long long notrace sched_clock(void) | ||
126 | { | ||
127 | u32 cyc = clocksource_32k.read(&clocksource_32k); | ||
128 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | ||
129 | } | ||
130 | |||
131 | static void notrace omap_update_sched_clock(void) | ||
115 | { | 132 | { |
116 | return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k), | 133 | u32 cyc = clocksource_32k.read(&clocksource_32k); |
117 | clocksource_32k.mult, clocksource_32k.shift); | 134 | update_sched_clock(&cd, cyc, (u32)~0); |
118 | } | 135 | } |
119 | 136 | ||
120 | /** | 137 | /** |
@@ -168,13 +185,13 @@ static int __init omap_init_clocksource_32k(void) | |||
168 | if (!IS_ERR(sync_32k_ick)) | 185 | if (!IS_ERR(sync_32k_ick)) |
169 | clk_enable(sync_32k_ick); | 186 | clk_enable(sync_32k_ick); |
170 | 187 | ||
171 | clocksource_32k.mult = clocksource_hz2mult(32768, | ||
172 | clocksource_32k.shift); | ||
173 | |||
174 | offset_32k = clocksource_32k.read(&clocksource_32k); | 188 | offset_32k = clocksource_32k.read(&clocksource_32k); |
175 | 189 | ||
176 | if (clocksource_register(&clocksource_32k)) | 190 | if (clocksource_register_hz(&clocksource_32k, 32768)) |
177 | printk(err, clocksource_32k.name); | 191 | printk(err, clocksource_32k.name); |
192 | |||
193 | init_fixed_sched_clock(&cd, omap_update_sched_clock, 32, | ||
194 | 32768, SC_MULT, SC_SHIFT); | ||
178 | } | 195 | } |
179 | return 0; | 196 | return 0; |
180 | } | 197 | } |
diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h index bb937f3fabe..4b2028ab4d2 100644 --- a/arch/arm/plat-omap/include/plat/clkdev_omap.h +++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h | |||
@@ -8,7 +8,7 @@ | |||
8 | #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H | 8 | #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H |
9 | #define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H | 9 | #define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H |
10 | 10 | ||
11 | #include <asm/clkdev.h> | 11 | #include <linux/clkdev.h> |
12 | 12 | ||
13 | struct omap_clk { | 13 | struct omap_clk { |
14 | u16 cpu; | 14 | u16 cpu; |
diff --git a/arch/arm/plat-omap/include/plat/io.h b/arch/arm/plat-omap/include/plat/io.h index 128b549c279..204865f91d9 100644 --- a/arch/arm/plat-omap/include/plat/io.h +++ b/arch/arm/plat-omap/include/plat/io.h | |||
@@ -294,8 +294,8 @@ static inline void omap44xx_map_common_io(void) | |||
294 | extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0, | 294 | extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0, |
295 | struct omap_sdrc_params *sdrc_cs1); | 295 | struct omap_sdrc_params *sdrc_cs1); |
296 | 296 | ||
297 | #define __arch_ioremap(p,s,t) omap_ioremap(p,s,t) | 297 | #define __arch_ioremap omap_ioremap |
298 | #define __arch_iounmap(v) omap_iounmap(v) | 298 | #define __arch_iounmap omap_iounmap |
299 | 299 | ||
300 | void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type); | 300 | void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type); |
301 | void omap_iounmap(volatile void __iomem *addr); | 301 | void omap_iounmap(volatile void __iomem *addr); |
diff --git a/arch/arm/plat-omap/include/plat/memory.h b/arch/arm/plat-omap/include/plat/memory.h index d5306bee44b..f8d922fb558 100644 --- a/arch/arm/plat-omap/include/plat/memory.h +++ b/arch/arm/plat-omap/include/plat/memory.h | |||
@@ -61,17 +61,17 @@ | |||
61 | #define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET) | 61 | #define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET) |
62 | #define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0)) | 62 | #define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0)) |
63 | 63 | ||
64 | #define __arch_page_to_dma(dev, page) \ | 64 | #define __arch_pfn_to_dma(dev, pfn) \ |
65 | ({ dma_addr_t __dma = page_to_phys(page); \ | 65 | ({ dma_addr_t __dma = __pfn_to_phys(pfn); \ |
66 | if (is_lbus_device(dev)) \ | 66 | if (is_lbus_device(dev)) \ |
67 | __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \ | 67 | __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \ |
68 | __dma; }) | 68 | __dma; }) |
69 | 69 | ||
70 | #define __arch_dma_to_page(dev, addr) \ | 70 | #define __arch_dma_to_pfn(dev, addr) \ |
71 | ({ dma_addr_t __dma = addr; \ | 71 | ({ dma_addr_t __dma = addr; \ |
72 | if (is_lbus_device(dev)) \ | 72 | if (is_lbus_device(dev)) \ |
73 | __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \ | 73 | __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \ |
74 | phys_to_page(__dma); \ | 74 | __phys_to_pfn(__dma); \ |
75 | }) | 75 | }) |
76 | 76 | ||
77 | #define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \ | 77 | #define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \ |
diff --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h index ecd6a488c49..7a10257909e 100644 --- a/arch/arm/plat-omap/include/plat/smp.h +++ b/arch/arm/plat-omap/include/plat/smp.h | |||
@@ -18,7 +18,6 @@ | |||
18 | #define OMAP_ARCH_SMP_H | 18 | #define OMAP_ARCH_SMP_H |
19 | 19 | ||
20 | #include <asm/hardware/gic.h> | 20 | #include <asm/hardware/gic.h> |
21 | #include <asm/smp_mpidr.h> | ||
22 | 21 | ||
23 | /* Needed for secondary core boot */ | 22 | /* Needed for secondary core boot */ |
24 | extern void omap_secondary_startup(void); | 23 | extern void omap_secondary_startup(void); |
@@ -29,9 +28,9 @@ extern u32 omap_read_auxcoreboot0(void); | |||
29 | /* | 28 | /* |
30 | * We use Soft IRQ1 as the IPI | 29 | * We use Soft IRQ1 as the IPI |
31 | */ | 30 | */ |
32 | static inline void smp_cross_call(const struct cpumask *mask) | 31 | static inline void smp_cross_call(const struct cpumask *mask, int ipi) |
33 | { | 32 | { |
34 | gic_raise_softirq(mask, 1); | 33 | gic_raise_softirq(mask, ipi); |
35 | } | 34 | } |
36 | 35 | ||
37 | #endif | 36 | #endif |
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 715a30177f2..c3da2478b2a 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c | |||
@@ -13,11 +13,11 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/cnt32_to_63.h> | ||
17 | #include <linux/timer.h> | 16 | #include <linux/timer.h> |
18 | #include <linux/clockchips.h> | 17 | #include <linux/clockchips.h> |
19 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
20 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <asm/sched_clock.h> | ||
21 | #include <asm/mach/time.h> | 21 | #include <asm/mach/time.h> |
22 | #include <mach/bridge-regs.h> | 22 | #include <mach/bridge-regs.h> |
23 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
@@ -44,52 +44,26 @@ static u32 ticks_per_jiffy; | |||
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Orion's sched_clock implementation. It has a resolution of | 46 | * Orion's sched_clock implementation. It has a resolution of |
47 | * at least 7.5ns (133MHz TCLK) and a maximum value of 834 days. | 47 | * at least 7.5ns (133MHz TCLK). |
48 | * | ||
49 | * Because the hardware timer period is quite short (21 secs if | ||
50 | * 200MHz TCLK) and because cnt32_to_63() needs to be called at | ||
51 | * least once per half period to work properly, a kernel timer is | ||
52 | * set up to ensure this requirement is always met. | ||
53 | */ | 48 | */ |
54 | #define TCLK2NS_SCALE_FACTOR 8 | 49 | static DEFINE_CLOCK_DATA(cd); |
55 | |||
56 | static unsigned long tclk2ns_scale; | ||
57 | 50 | ||
58 | unsigned long long sched_clock(void) | 51 | unsigned long long notrace sched_clock(void) |
59 | { | 52 | { |
60 | unsigned long long v = cnt32_to_63(0xffffffff - readl(TIMER0_VAL)); | 53 | u32 cyc = 0xffffffff - readl(TIMER0_VAL); |
61 | return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR; | 54 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
62 | } | 55 | } |
63 | 56 | ||
64 | static struct timer_list cnt32_to_63_keepwarm_timer; | ||
65 | 57 | ||
66 | static void cnt32_to_63_keepwarm(unsigned long data) | 58 | static void notrace orion_update_sched_clock(void) |
67 | { | 59 | { |
68 | mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data)); | 60 | u32 cyc = 0xffffffff - readl(TIMER0_VAL); |
69 | (void) sched_clock(); | 61 | update_sched_clock(&cd, cyc, (u32)~0); |
70 | } | 62 | } |
71 | 63 | ||
72 | static void __init setup_sched_clock(unsigned long tclk) | 64 | static void __init setup_sched_clock(unsigned long tclk) |
73 | { | 65 | { |
74 | unsigned long long v; | 66 | init_sched_clock(&cd, orion_update_sched_clock, 32, tclk); |
75 | unsigned long data; | ||
76 | |||
77 | v = NSEC_PER_SEC; | ||
78 | v <<= TCLK2NS_SCALE_FACTOR; | ||
79 | v += tclk/2; | ||
80 | do_div(v, tclk); | ||
81 | /* | ||
82 | * We want an even value to automatically clear the top bit | ||
83 | * returned by cnt32_to_63() without an additional run time | ||
84 | * instruction. So if the LSB is 1 then round it up. | ||
85 | */ | ||
86 | if (v & 1) | ||
87 | v++; | ||
88 | tclk2ns_scale = v; | ||
89 | |||
90 | data = (0xffffffffUL / tclk / 2 - 2) * HZ; | ||
91 | setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, data); | ||
92 | mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data)); | ||
93 | } | 67 | } |
94 | 68 | ||
95 | /* | 69 | /* |
@@ -102,7 +76,6 @@ static cycle_t orion_clksrc_read(struct clocksource *cs) | |||
102 | 76 | ||
103 | static struct clocksource orion_clksrc = { | 77 | static struct clocksource orion_clksrc = { |
104 | .name = "orion_clocksource", | 78 | .name = "orion_clocksource", |
105 | .shift = 20, | ||
106 | .rating = 300, | 79 | .rating = 300, |
107 | .read = orion_clksrc_read, | 80 | .read = orion_clksrc_read, |
108 | .mask = CLOCKSOURCE_MASK(32), | 81 | .mask = CLOCKSOURCE_MASK(32), |
@@ -245,8 +218,7 @@ void __init orion_time_init(unsigned int irq, unsigned int tclk) | |||
245 | writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK); | 218 | writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK); |
246 | u = readl(TIMER_CTRL); | 219 | u = readl(TIMER_CTRL); |
247 | writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL); | 220 | writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL); |
248 | orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift); | 221 | clocksource_register_hz(&orion_clksrc, tclk); |
249 | clocksource_register(&orion_clksrc); | ||
250 | 222 | ||
251 | /* | 223 | /* |
252 | * Setup clockevent timer (interrupt-driven.) | 224 | * Setup clockevent timer (interrupt-driven.) |
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 5a27b1b538f..eb105e61c74 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig | |||
@@ -8,7 +8,7 @@ config PLAT_S3C24XX | |||
8 | default y | 8 | default y |
9 | select NO_IOPORT | 9 | select NO_IOPORT |
10 | select ARCH_REQUIRE_GPIOLIB | 10 | select ARCH_REQUIRE_GPIOLIB |
11 | select S3C_DEVICE_NAND | 11 | select S3C_DEV_NAND |
12 | select S3C_GPIO_CFG_S3C24XX | 12 | select S3C_GPIO_CFG_S3C24XX |
13 | help | 13 | help |
14 | Base platform code for any Samsung S3C24XX device | 14 | Base platform code for any Samsung S3C24XX device |
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h index 298bafc0a52..2572260f990 100644 --- a/arch/arm/plat-spear/include/plat/clock.h +++ b/arch/arm/plat-spear/include/plat/clock.h | |||
@@ -15,7 +15,7 @@ | |||
15 | #define __PLAT_CLOCK_H | 15 | #define __PLAT_CLOCK_H |
16 | 16 | ||
17 | #include <linux/list.h> | 17 | #include <linux/list.h> |
18 | #include <asm/clkdev.h> | 18 | #include <linux/clkdev.h> |
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | 20 | ||
21 | /* clk structure flags */ | 21 | /* clk structure flags */ |
diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c index ab211652e4c..839c88df999 100644 --- a/arch/arm/plat-spear/time.c +++ b/arch/arm/plat-spear/time.c | |||
@@ -81,8 +81,6 @@ static struct clocksource clksrc = { | |||
81 | .rating = 200, /* its a pretty decent clock */ | 81 | .rating = 200, /* its a pretty decent clock */ |
82 | .read = clocksource_read_cycles, | 82 | .read = clocksource_read_cycles, |
83 | .mask = 0xFFFF, /* 16 bits */ | 83 | .mask = 0xFFFF, /* 16 bits */ |
84 | .mult = 0, /* to be computed */ | ||
85 | .shift = 0, /* to be computed */ | ||
86 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 84 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
87 | }; | 85 | }; |
88 | 86 | ||
@@ -105,10 +103,8 @@ static void spear_clocksource_init(void) | |||
105 | val |= CTRL_ENABLE ; | 103 | val |= CTRL_ENABLE ; |
106 | writew(val, gpt_base + CR(CLKSRC)); | 104 | writew(val, gpt_base + CR(CLKSRC)); |
107 | 105 | ||
108 | clocksource_calc_mult_shift(&clksrc, tick_rate, SPEAR_MIN_RANGE); | ||
109 | |||
110 | /* register the clocksource */ | 106 | /* register the clocksource */ |
111 | clocksource_register(&clksrc); | 107 | clocksource_register_hz(&clksrc, tick_rate); |
112 | } | 108 | } |
113 | 109 | ||
114 | static struct clock_event_device clkevt = { | 110 | static struct clock_event_device clkevt = { |
diff --git a/arch/arm/plat-stmp3xxx/clock.c b/arch/arm/plat-stmp3xxx/clock.c index e593a2a801c..2e712e17ce7 100644 --- a/arch/arm/plat-stmp3xxx/clock.c +++ b/arch/arm/plat-stmp3xxx/clock.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include <linux/err.h> | 25 | #include <linux/err.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/clkdev.h> | ||
28 | 29 | ||
29 | #include <asm/mach-types.h> | 30 | #include <asm/mach-types.h> |
30 | #include <asm/clkdev.h> | ||
31 | #include <mach/platform.h> | 31 | #include <mach/platform.h> |
32 | #include <mach/regs-clkctrl.h> | 32 | #include <mach/regs-clkctrl.h> |
33 | 33 | ||
diff --git a/arch/arm/plat-stmp3xxx/timer.c b/arch/arm/plat-stmp3xxx/timer.c index 063c7bc0e74..c395630a6ed 100644 --- a/arch/arm/plat-stmp3xxx/timer.c +++ b/arch/arm/plat-stmp3xxx/timer.c | |||
@@ -89,7 +89,6 @@ static struct clocksource cksrc_stmp3xxx = { | |||
89 | .rating = 250, | 89 | .rating = 250, |
90 | .read = stmp3xxx_clock_read, | 90 | .read = stmp3xxx_clock_read, |
91 | .mask = CLOCKSOURCE_MASK(16), | 91 | .mask = CLOCKSOURCE_MASK(16), |
92 | .shift = 10, | ||
93 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 92 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
94 | }; | 93 | }; |
95 | 94 | ||
@@ -106,8 +105,6 @@ static struct irqaction stmp3xxx_timer_irq = { | |||
106 | */ | 105 | */ |
107 | static void __init stmp3xxx_init_timer(void) | 106 | static void __init stmp3xxx_init_timer(void) |
108 | { | 107 | { |
109 | cksrc_stmp3xxx.mult = clocksource_hz2mult(CLOCK_TICK_RATE, | ||
110 | cksrc_stmp3xxx.shift); | ||
111 | ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, | 108 | ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, |
112 | ckevt_timrot.shift); | 109 | ckevt_timrot.shift); |
113 | ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot); | 110 | ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot); |
@@ -140,7 +137,7 @@ static void __init stmp3xxx_init_timer(void) | |||
140 | 137 | ||
141 | setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq); | 138 | setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq); |
142 | 139 | ||
143 | clocksource_register(&cksrc_stmp3xxx); | 140 | clocksource_register_hz(&cksrc_stmp3xxx, CLOCK_TICK_RATE); |
144 | clockevents_register_device(&ckevt_timrot); | 141 | clockevents_register_device(&ckevt_timrot); |
145 | } | 142 | } |
146 | 143 | ||
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 5cf88e8427b..16dde081993 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | obj-y := clock.o | 1 | obj-y := clock.o |
2 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o | 2 | ifneq ($(CONFIG_ARCH_INTEGRATOR),y) |
3 | obj-$(CONFIG_ARCH_REALVIEW) += sched-clock.o | 3 | obj-y += sched-clock.o |
4 | obj-$(CONFIG_ARCH_VERSATILE) += sched-clock.o | 4 | endif |
5 | ifeq ($(CONFIG_LEDS_CLASS),y) | 5 | ifeq ($(CONFIG_LEDS_CLASS),y) |
6 | obj-$(CONFIG_ARCH_REALVIEW) += leds.o | 6 | obj-$(CONFIG_ARCH_REALVIEW) += leds.o |
7 | obj-$(CONFIG_ARCH_VERSATILE) += leds.o | 7 | obj-$(CONFIG_ARCH_VERSATILE) += leds.o |
diff --git a/arch/arm/plat-versatile/include/plat/sched_clock.h b/arch/arm/plat-versatile/include/plat/sched_clock.h new file mode 100644 index 00000000000..5c3e4fc9fa0 --- /dev/null +++ b/arch/arm/plat-versatile/include/plat/sched_clock.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef ARM_PLAT_SCHED_CLOCK_H | ||
2 | #define ARM_PLAT_SCHED_CLOCK_H | ||
3 | |||
4 | void versatile_sched_clock_init(void __iomem *, unsigned long); | ||
5 | |||
6 | #endif | ||
diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c index 9696ddc238c..3d6a4c292ca 100644 --- a/arch/arm/plat-versatile/sched-clock.c +++ b/arch/arm/plat-versatile/sched-clock.c | |||
@@ -18,37 +18,41 @@ | |||
18 | * along with this program; if not, write to the Free Software | 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 | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | #include <linux/cnt32_to_63.h> | ||
22 | #include <linux/io.h> | 21 | #include <linux/io.h> |
23 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
24 | #include <asm/div64.h> | ||
25 | 23 | ||
26 | #include <mach/hardware.h> | 24 | #include <asm/sched_clock.h> |
27 | #include <mach/platform.h> | 25 | #include <plat/sched_clock.h> |
28 | 26 | ||
29 | #ifdef VERSATILE_SYS_BASE | 27 | static DEFINE_CLOCK_DATA(cd); |
30 | #define REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET) | 28 | static void __iomem *ctr; |
31 | #endif | ||
32 | |||
33 | #ifdef REALVIEW_SYS_BASE | ||
34 | #define REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET) | ||
35 | #endif | ||
36 | 29 | ||
37 | /* | 30 | /* |
38 | * This is the Realview and Versatile sched_clock implementation. This | 31 | * Constants generated by clocks_calc_mult_shift(m, s, 24MHz, NSEC_PER_SEC, 60). |
39 | * has a resolution of 41.7ns, and a maximum value of about 35583 days. | 32 | * This gives a resolution of about 41ns and a wrap period of about 178s. |
40 | * | ||
41 | * The return value is guaranteed to be monotonic in that range as | ||
42 | * long as there is always less than 89 seconds between successive | ||
43 | * calls to this function. | ||
44 | */ | 33 | */ |
45 | unsigned long long sched_clock(void) | 34 | #define SC_MULT 2796202667u |
35 | #define SC_SHIFT 26 | ||
36 | |||
37 | unsigned long long notrace sched_clock(void) | ||
46 | { | 38 | { |
47 | unsigned long long v = cnt32_to_63(readl(REFCOUNTER)); | 39 | if (ctr) { |
40 | u32 cyc = readl(ctr); | ||
41 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, | ||
42 | SC_MULT, SC_SHIFT); | ||
43 | } else | ||
44 | return 0; | ||
45 | } | ||
48 | 46 | ||
49 | /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */ | 47 | static void notrace versatile_update_sched_clock(void) |
50 | v *= 125<<1; | 48 | { |
51 | do_div(v, 3<<1); | 49 | u32 cyc = readl(ctr); |
50 | update_sched_clock(&cd, cyc, (u32)~0); | ||
51 | } | ||
52 | 52 | ||
53 | return v; | 53 | void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate) |
54 | { | ||
55 | ctr = reg; | ||
56 | init_fixed_sched_clock(&cd, versatile_update_sched_clock, | ||
57 | 32, rate, SC_MULT, SC_SHIFT); | ||
54 | } | 58 | } |
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 8063a322c79..0797cb528b4 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -10,9 +10,12 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/cpu.h> | ||
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/notifier.h> | ||
14 | #include <linux/signal.h> | 16 | #include <linux/signal.h> |
15 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/smp.h> | ||
16 | #include <linux/init.h> | 19 | #include <linux/init.h> |
17 | 20 | ||
18 | #include <asm/cputype.h> | 21 | #include <asm/cputype.h> |
@@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_info *thread) | |||
484 | put_cpu(); | 487 | put_cpu(); |
485 | } | 488 | } |
486 | 489 | ||
487 | #include <linux/smp.h> | 490 | /* |
491 | * VFP hardware can lose all context when a CPU goes offline. | ||
492 | * Safely clear our held state when a CPU has been killed, and | ||
493 | * re-enable access to VFP when the CPU comes back online. | ||
494 | * | ||
495 | * Both CPU_DYING and CPU_STARTING are called on the CPU which | ||
496 | * is being offlined/onlined. | ||
497 | */ | ||
498 | static int vfp_hotplug(struct notifier_block *b, unsigned long action, | ||
499 | void *hcpu) | ||
500 | { | ||
501 | if (action == CPU_DYING || action == CPU_DYING_FROZEN) { | ||
502 | unsigned int cpu = (long)hcpu; | ||
503 | last_VFP_context[cpu] = NULL; | ||
504 | } else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) | ||
505 | vfp_enable(NULL); | ||
506 | return NOTIFY_OK; | ||
507 | } | ||
488 | 508 | ||
489 | /* | 509 | /* |
490 | * VFP support code initialisation. | 510 | * VFP support code initialisation. |
@@ -514,6 +534,8 @@ static int __init vfp_init(void) | |||
514 | else if (vfpsid & FPSID_NODOUBLE) { | 534 | else if (vfpsid & FPSID_NODOUBLE) { |
515 | printk("no double precision support\n"); | 535 | printk("no double precision support\n"); |
516 | } else { | 536 | } else { |
537 | hotcpu_notifier(vfp_hotplug, 0); | ||
538 | |||
517 | smp_call_function(vfp_enable, NULL, 1); | 539 | smp_call_function(vfp_enable, NULL, 1); |
518 | 540 | ||
519 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ | 541 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 67a2fa2caa4..0a9b5b8b2a1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -19,6 +19,8 @@ config MIPS | |||
19 | select GENERIC_ATOMIC64 if !64BIT | 19 | select GENERIC_ATOMIC64 if !64BIT |
20 | select HAVE_DMA_ATTRS | 20 | select HAVE_DMA_ATTRS |
21 | select HAVE_DMA_API_DEBUG | 21 | select HAVE_DMA_API_DEBUG |
22 | select HAVE_GENERIC_HARDIRQS | ||
23 | select GENERIC_IRQ_PROBE | ||
22 | 24 | ||
23 | menu "Machine selection" | 25 | menu "Machine selection" |
24 | 26 | ||
@@ -1664,6 +1666,28 @@ config PAGE_SIZE_64KB | |||
1664 | 1666 | ||
1665 | endchoice | 1667 | endchoice |
1666 | 1668 | ||
1669 | config FORCE_MAX_ZONEORDER | ||
1670 | int "Maximum zone order" | ||
1671 | range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB | ||
1672 | default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB | ||
1673 | range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB | ||
1674 | default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB | ||
1675 | range 11 64 | ||
1676 | default "11" | ||
1677 | help | ||
1678 | The kernel memory allocator divides physically contiguous memory | ||
1679 | blocks into "zones", where each zone is a power of two number of | ||
1680 | pages. This option selects the largest power of two that the kernel | ||
1681 | keeps in the memory allocator. If you need to allocate very large | ||
1682 | blocks of physically contiguous memory, then you may need to | ||
1683 | increase this value. | ||
1684 | |||
1685 | This config option is actually maximum order plus one. For example, | ||
1686 | a value of 11 means that the largest free memory block is 2^10 pages. | ||
1687 | |||
1688 | The page size is not necessarily 4KB. Keep this in mind | ||
1689 | when choosing a value for this option. | ||
1690 | |||
1667 | config BOARD_SCACHE | 1691 | config BOARD_SCACHE |
1668 | bool | 1692 | bool |
1669 | 1693 | ||
@@ -1922,20 +1946,6 @@ config CPU_R4400_WORKAROUNDS | |||
1922 | bool | 1946 | bool |
1923 | 1947 | ||
1924 | # | 1948 | # |
1925 | # Use the generic interrupt handling code in kernel/irq/: | ||
1926 | # | ||
1927 | config GENERIC_HARDIRQS | ||
1928 | bool | ||
1929 | default y | ||
1930 | |||
1931 | config GENERIC_IRQ_PROBE | ||
1932 | bool | ||
1933 | default y | ||
1934 | |||
1935 | config IRQ_PER_CPU | ||
1936 | bool | ||
1937 | |||
1938 | # | ||
1939 | # - Highmem only makes sense for the 32-bit kernel. | 1949 | # - Highmem only makes sense for the 32-bit kernel. |
1940 | # - The current highmem code will only work properly on physically indexed | 1950 | # - The current highmem code will only work properly on physically indexed |
1941 | # caches such as R3000, SB1, R7000 or those that look like they're virtually | 1951 | # caches such as R3000, SB1, R7000 or those that look like they're virtually |
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index 3691630931d..9e7814db3d0 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c | |||
@@ -27,6 +27,7 @@ | |||
27 | static void alchemy_8250_pm(struct uart_port *port, unsigned int state, | 27 | static void alchemy_8250_pm(struct uart_port *port, unsigned int state, |
28 | unsigned int old_state) | 28 | unsigned int old_state) |
29 | { | 29 | { |
30 | #ifdef CONFIG_SERIAL_8250 | ||
30 | switch (state) { | 31 | switch (state) { |
31 | case 0: | 32 | case 0: |
32 | if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) { | 33 | if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) { |
@@ -49,6 +50,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state, | |||
49 | serial8250_do_pm(port, state, old_state); | 50 | serial8250_do_pm(port, state, old_state); |
50 | break; | 51 | break; |
51 | } | 52 | } |
53 | #endif | ||
52 | } | 54 | } |
53 | 55 | ||
54 | #define PORT(_base, _irq) \ | 56 | #define PORT(_base, _irq) \ |
diff --git a/arch/mips/alchemy/devboards/prom.c b/arch/mips/alchemy/devboards/prom.c index b30df5c97ad..baeb2138505 100644 --- a/arch/mips/alchemy/devboards/prom.c +++ b/arch/mips/alchemy/devboards/prom.c | |||
@@ -54,10 +54,9 @@ void __init prom_init(void) | |||
54 | 54 | ||
55 | prom_init_cmdline(); | 55 | prom_init_cmdline(); |
56 | memsize_str = prom_getenv("memsize"); | 56 | memsize_str = prom_getenv("memsize"); |
57 | if (!memsize_str) | 57 | if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize)) |
58 | memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE; | 58 | memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE; |
59 | else | 59 | |
60 | strict_strtoul(memsize_str, 0, &memsize); | ||
61 | add_memory_region(0, memsize, BOOT_MEM_RAM); | 60 | add_memory_region(0, memsize, BOOT_MEM_RAM); |
62 | } | 61 | } |
63 | 62 | ||
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c index fc0e7154e8d..2ca4ada1c29 100644 --- a/arch/mips/ar7/clock.c +++ b/arch/mips/ar7/clock.c | |||
@@ -239,12 +239,12 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock, | |||
239 | calculate(base_clock, frequency, &prediv, &postdiv, &mul); | 239 | calculate(base_clock, frequency, &prediv, &postdiv, &mul); |
240 | 240 | ||
241 | writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl); | 241 | writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl); |
242 | msleep(1); | 242 | mdelay(1); |
243 | writel(4, &clock->pll); | 243 | writel(4, &clock->pll); |
244 | while (readl(&clock->pll) & PLL_STATUS) | 244 | while (readl(&clock->pll) & PLL_STATUS) |
245 | ; | 245 | ; |
246 | writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); | 246 | writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); |
247 | msleep(75); | 247 | mdelay(75); |
248 | } | 248 | } |
249 | 249 | ||
250 | static void __init tnetd7300_init_clocks(void) | 250 | static void __init tnetd7300_init_clocks(void) |
@@ -456,7 +456,7 @@ void clk_put(struct clk *clk) | |||
456 | } | 456 | } |
457 | EXPORT_SYMBOL(clk_put); | 457 | EXPORT_SYMBOL(clk_put); |
458 | 458 | ||
459 | int __init ar7_init_clocks(void) | 459 | void __init ar7_init_clocks(void) |
460 | { | 460 | { |
461 | switch (ar7_chip_id()) { | 461 | switch (ar7_chip_id()) { |
462 | case AR7_CHIP_7100: | 462 | case AR7_CHIP_7100: |
@@ -472,7 +472,4 @@ int __init ar7_init_clocks(void) | |||
472 | } | 472 | } |
473 | /* adjust vbus clock rate */ | 473 | /* adjust vbus clock rate */ |
474 | vbus_clk.rate = bus_clk.rate / 2; | 474 | vbus_clk.rate = bus_clk.rate / 2; |
475 | |||
476 | return 0; | ||
477 | } | 475 | } |
478 | arch_initcall(ar7_init_clocks); | ||
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c index 5fb8a013408..22c93213b23 100644 --- a/arch/mips/ar7/time.c +++ b/arch/mips/ar7/time.c | |||
@@ -30,6 +30,9 @@ void __init plat_time_init(void) | |||
30 | { | 30 | { |
31 | struct clk *cpu_clk; | 31 | struct clk *cpu_clk; |
32 | 32 | ||
33 | /* Initialize ar7 clocks so the CPU clock frequency is correct */ | ||
34 | ar7_init_clocks(); | ||
35 | |||
33 | cpu_clk = clk_get(NULL, "cpu"); | 36 | cpu_clk = clk_get(NULL, "cpu"); |
34 | if (IS_ERR(cpu_clk)) { | 37 | if (IS_ERR(cpu_clk)) { |
35 | printk(KERN_ERR "unable to get cpu clock\n"); | 38 | printk(KERN_ERR "unable to get cpu clock\n"); |
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index b1aee33efd1..c95f90bf734 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <asm/reboot.h> | 32 | #include <asm/reboot.h> |
33 | #include <asm/time.h> | 33 | #include <asm/time.h> |
34 | #include <bcm47xx.h> | 34 | #include <bcm47xx.h> |
35 | #include <asm/fw/cfe/cfe_api.h> | ||
36 | #include <asm/mach-bcm47xx/nvram.h> | 35 | #include <asm/mach-bcm47xx/nvram.h> |
37 | 36 | ||
38 | struct ssb_bus ssb_bcm47xx; | 37 | struct ssb_bus ssb_bcm47xx; |
@@ -57,68 +56,112 @@ static void bcm47xx_machine_halt(void) | |||
57 | cpu_relax(); | 56 | cpu_relax(); |
58 | } | 57 | } |
59 | 58 | ||
60 | static void str2eaddr(char *str, char *dest) | 59 | #define READ_FROM_NVRAM(_outvar, name, buf) \ |
61 | { | 60 | if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\ |
62 | int i = 0; | 61 | sprom->_outvar = simple_strtoul(buf, NULL, 0); |
63 | 62 | ||
64 | if (str == NULL) { | 63 | static void bcm47xx_fill_sprom(struct ssb_sprom *sprom) |
65 | memset(dest, 0, 6); | 64 | { |
66 | return; | 65 | char buf[100]; |
66 | u32 boardflags; | ||
67 | |||
68 | memset(sprom, 0, sizeof(struct ssb_sprom)); | ||
69 | |||
70 | sprom->revision = 1; /* Fallback: Old hardware does not define this. */ | ||
71 | READ_FROM_NVRAM(revision, "sromrev", buf); | ||
72 | if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0) | ||
73 | nvram_parse_macaddr(buf, sprom->il0mac); | ||
74 | if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) | ||
75 | nvram_parse_macaddr(buf, sprom->et0mac); | ||
76 | if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) | ||
77 | nvram_parse_macaddr(buf, sprom->et1mac); | ||
78 | READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf); | ||
79 | READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf); | ||
80 | READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf); | ||
81 | READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf); | ||
82 | READ_FROM_NVRAM(board_rev, "boardrev", buf); | ||
83 | READ_FROM_NVRAM(country_code, "ccode", buf); | ||
84 | READ_FROM_NVRAM(ant_available_a, "aa5g", buf); | ||
85 | READ_FROM_NVRAM(ant_available_bg, "aa2g", buf); | ||
86 | READ_FROM_NVRAM(pa0b0, "pa0b0", buf); | ||
87 | READ_FROM_NVRAM(pa0b1, "pa0b1", buf); | ||
88 | READ_FROM_NVRAM(pa0b2, "pa0b2", buf); | ||
89 | READ_FROM_NVRAM(pa1b0, "pa1b0", buf); | ||
90 | READ_FROM_NVRAM(pa1b1, "pa1b1", buf); | ||
91 | READ_FROM_NVRAM(pa1b2, "pa1b2", buf); | ||
92 | READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf); | ||
93 | READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf); | ||
94 | READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf); | ||
95 | READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf); | ||
96 | READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf); | ||
97 | READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf); | ||
98 | READ_FROM_NVRAM(gpio0, "wl0gpio0", buf); | ||
99 | READ_FROM_NVRAM(gpio1, "wl0gpio1", buf); | ||
100 | READ_FROM_NVRAM(gpio2, "wl0gpio2", buf); | ||
101 | READ_FROM_NVRAM(gpio3, "wl0gpio3", buf); | ||
102 | READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf); | ||
103 | READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf); | ||
104 | READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf); | ||
105 | READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf); | ||
106 | READ_FROM_NVRAM(itssi_a, "pa1itssit", buf); | ||
107 | READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf); | ||
108 | READ_FROM_NVRAM(tri2g, "tri2g", buf); | ||
109 | READ_FROM_NVRAM(tri5gl, "tri5gl", buf); | ||
110 | READ_FROM_NVRAM(tri5g, "tri5g", buf); | ||
111 | READ_FROM_NVRAM(tri5gh, "tri5gh", buf); | ||
112 | READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf); | ||
113 | READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf); | ||
114 | READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf); | ||
115 | READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf); | ||
116 | READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf); | ||
117 | READ_FROM_NVRAM(bxa2g, "bxa2g", buf); | ||
118 | READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf); | ||
119 | READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf); | ||
120 | READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf); | ||
121 | READ_FROM_NVRAM(bxa5g, "bxa5g", buf); | ||
122 | READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf); | ||
123 | READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf); | ||
124 | READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf); | ||
125 | READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf); | ||
126 | READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf); | ||
127 | |||
128 | if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) { | ||
129 | boardflags = simple_strtoul(buf, NULL, 0); | ||
130 | if (boardflags) { | ||
131 | sprom->boardflags_lo = (boardflags & 0x0000FFFFU); | ||
132 | sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16; | ||
133 | } | ||
67 | } | 134 | } |
68 | 135 | if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) { | |
69 | for (;;) { | 136 | boardflags = simple_strtoul(buf, NULL, 0); |
70 | dest[i++] = (char) simple_strtoul(str, NULL, 16); | 137 | if (boardflags) { |
71 | str += 2; | 138 | sprom->boardflags2_lo = (boardflags & 0x0000FFFFU); |
72 | if (!*str++ || i == 6) | 139 | sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16; |
73 | break; | 140 | } |
74 | } | 141 | } |
75 | } | 142 | } |
76 | 143 | ||
77 | static int bcm47xx_get_invariants(struct ssb_bus *bus, | 144 | static int bcm47xx_get_invariants(struct ssb_bus *bus, |
78 | struct ssb_init_invariants *iv) | 145 | struct ssb_init_invariants *iv) |
79 | { | 146 | { |
80 | char buf[100]; | 147 | char buf[20]; |
81 | 148 | ||
82 | /* Fill boardinfo structure */ | 149 | /* Fill boardinfo structure */ |
83 | memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); | 150 | memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); |
84 | 151 | ||
85 | if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 || | 152 | if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) |
86 | nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0) | 153 | iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0); |
87 | iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); | 154 | else |
88 | if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 || | 155 | iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM; |
89 | nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) | 156 | if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0) |
90 | iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); | 157 | iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); |
91 | if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 || | 158 | if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) |
92 | nvram_getenv("boardrev", buf, sizeof(buf)) >= 0) | ||
93 | iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); | 159 | iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); |
94 | 160 | ||
95 | /* Fill sprom structure */ | 161 | bcm47xx_fill_sprom(&iv->sprom); |
96 | memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); | ||
97 | iv->sprom.revision = 3; | ||
98 | |||
99 | if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 || | ||
100 | nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0) | ||
101 | str2eaddr(buf, iv->sprom.et0mac); | ||
102 | 162 | ||
103 | if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 || | 163 | if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0) |
104 | nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0) | 164 | iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10); |
105 | str2eaddr(buf, iv->sprom.et1mac); | ||
106 | |||
107 | if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 || | ||
108 | nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) | ||
109 | iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0); | ||
110 | |||
111 | if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 || | ||
112 | nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) | ||
113 | iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0); | ||
114 | |||
115 | if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 || | ||
116 | nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0) | ||
117 | iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); | ||
118 | |||
119 | if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 || | ||
120 | nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0) | ||
121 | iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); | ||
122 | 165 | ||
123 | return 0; | 166 | return 0; |
124 | } | 167 | } |
@@ -126,12 +169,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus, | |||
126 | void __init plat_mem_setup(void) | 169 | void __init plat_mem_setup(void) |
127 | { | 170 | { |
128 | int err; | 171 | int err; |
172 | char buf[100]; | ||
173 | struct ssb_mipscore *mcore; | ||
129 | 174 | ||
130 | err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, | 175 | err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, |
131 | bcm47xx_get_invariants); | 176 | bcm47xx_get_invariants); |
132 | if (err) | 177 | if (err) |
133 | panic("Failed to initialize SSB bus (err %d)\n", err); | 178 | panic("Failed to initialize SSB bus (err %d)\n", err); |
134 | 179 | ||
180 | mcore = &ssb_bcm47xx.mipscore; | ||
181 | if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) { | ||
182 | if (strstr(buf, "console=ttyS1")) { | ||
183 | struct ssb_serial_port port; | ||
184 | |||
185 | printk(KERN_DEBUG "Swapping serial ports!\n"); | ||
186 | /* swap serial ports */ | ||
187 | memcpy(&port, &mcore->serial_ports[0], sizeof(port)); | ||
188 | memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], | ||
189 | sizeof(port)); | ||
190 | memcpy(&mcore->serial_ports[1], &port, sizeof(port)); | ||
191 | } | ||
192 | } | ||
193 | |||
135 | _machine_restart = bcm47xx_machine_restart; | 194 | _machine_restart = bcm47xx_machine_restart; |
136 | _machine_halt = bcm47xx_machine_halt; | 195 | _machine_halt = bcm47xx_machine_halt; |
137 | pm_power_off = bcm47xx_machine_halt; | 196 | pm_power_off = bcm47xx_machine_halt; |
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 06d59dcbe24..86877539c6e 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h | |||
@@ -111,8 +111,8 @@ | |||
111 | * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM | 111 | * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM |
112 | */ | 112 | */ |
113 | 113 | ||
114 | #define PRID_IMP_BMIPS4KC 0x4000 | 114 | #define PRID_IMP_BMIPS32_REV4 0x4000 |
115 | #define PRID_IMP_BMIPS32 0x8000 | 115 | #define PRID_IMP_BMIPS32_REV8 0x8000 |
116 | #define PRID_IMP_BMIPS3300 0x9000 | 116 | #define PRID_IMP_BMIPS3300 0x9000 |
117 | #define PRID_IMP_BMIPS3300_ALT 0x9100 | 117 | #define PRID_IMP_BMIPS3300_ALT 0x9100 |
118 | #define PRID_IMP_BMIPS3300_BUG 0x0000 | 118 | #define PRID_IMP_BMIPS3300_BUG 0x0000 |
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index fd1d39eb743..455c0ac7d4e 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h | |||
@@ -249,7 +249,8 @@ extern struct mips_abi mips_abi_n32; | |||
249 | 249 | ||
250 | #define SET_PERSONALITY(ex) \ | 250 | #define SET_PERSONALITY(ex) \ |
251 | do { \ | 251 | do { \ |
252 | set_personality(PER_LINUX); \ | 252 | if (personality(current->personality) != PER_LINUX) \ |
253 | set_personality(PER_LINUX); \ | ||
253 | \ | 254 | \ |
254 | current->thread.abi = &mips_abi; \ | 255 | current->thread.abi = &mips_abi; \ |
255 | } while (0) | 256 | } while (0) |
@@ -296,6 +297,8 @@ do { \ | |||
296 | 297 | ||
297 | #define SET_PERSONALITY(ex) \ | 298 | #define SET_PERSONALITY(ex) \ |
298 | do { \ | 299 | do { \ |
300 | unsigned int p; \ | ||
301 | \ | ||
299 | clear_thread_flag(TIF_32BIT_REGS); \ | 302 | clear_thread_flag(TIF_32BIT_REGS); \ |
300 | clear_thread_flag(TIF_32BIT_ADDR); \ | 303 | clear_thread_flag(TIF_32BIT_ADDR); \ |
301 | \ | 304 | \ |
@@ -304,7 +307,8 @@ do { \ | |||
304 | else \ | 307 | else \ |
305 | current->thread.abi = &mips_abi; \ | 308 | current->thread.abi = &mips_abi; \ |
306 | \ | 309 | \ |
307 | if (current->personality != PER_LINUX32) \ | 310 | p = personality(current->personality); \ |
311 | if (p != PER_LINUX32 && p != PER_LINUX) \ | ||
308 | set_personality(PER_LINUX); \ | 312 | set_personality(PER_LINUX); \ |
309 | } while (0) | 313 | } while (0) |
310 | 314 | ||
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index c98bf514ec7..5b017f23e24 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h | |||
@@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val, \ | |||
329 | "dsrl32 %L0, %L0, 0" "\n\t" \ | 329 | "dsrl32 %L0, %L0, 0" "\n\t" \ |
330 | "dsll32 %M0, %M0, 0" "\n\t" \ | 330 | "dsll32 %M0, %M0, 0" "\n\t" \ |
331 | "or %L0, %L0, %M0" "\n\t" \ | 331 | "or %L0, %L0, %M0" "\n\t" \ |
332 | ".set push" "\n\t" \ | ||
333 | ".set noreorder" "\n\t" \ | ||
334 | ".set nomacro" "\n\t" \ | ||
332 | "sd %L0, %2" "\n\t" \ | 335 | "sd %L0, %2" "\n\t" \ |
336 | ".set pop" "\n\t" \ | ||
333 | ".set mips0" "\n" \ | 337 | ".set mips0" "\n" \ |
334 | : "=r" (__tmp) \ | 338 | : "=r" (__tmp) \ |
335 | : "0" (__val), "m" (*__mem)); \ | 339 | : "0" (__val), "R" (*__mem)); \ |
336 | if (irq) \ | 340 | if (irq) \ |
337 | local_irq_restore(__flags); \ | 341 | local_irq_restore(__flags); \ |
338 | } else \ | 342 | } else \ |
@@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ | |||
355 | local_irq_save(__flags); \ | 359 | local_irq_save(__flags); \ |
356 | __asm__ __volatile__( \ | 360 | __asm__ __volatile__( \ |
357 | ".set mips3" "\t\t# __readq" "\n\t" \ | 361 | ".set mips3" "\t\t# __readq" "\n\t" \ |
362 | ".set push" "\n\t" \ | ||
363 | ".set noreorder" "\n\t" \ | ||
364 | ".set nomacro" "\n\t" \ | ||
358 | "ld %L0, %1" "\n\t" \ | 365 | "ld %L0, %1" "\n\t" \ |
366 | ".set pop" "\n\t" \ | ||
359 | "dsra32 %M0, %L0, 0" "\n\t" \ | 367 | "dsra32 %M0, %L0, 0" "\n\t" \ |
360 | "sll %L0, %L0, 0" "\n\t" \ | 368 | "sll %L0, %L0, 0" "\n\t" \ |
361 | ".set mips0" "\n" \ | 369 | ".set mips0" "\n" \ |
362 | : "=r" (__val) \ | 370 | : "=r" (__val) \ |
363 | : "m" (*__mem)); \ | 371 | : "R" (*__mem)); \ |
364 | if (irq) \ | 372 | if (irq) \ |
365 | local_irq_restore(__flags); \ | 373 | local_irq_restore(__flags); \ |
366 | } else { \ | 374 | } else { \ |
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h index 7919d76186b..07d3fadb244 100644 --- a/arch/mips/include/asm/mach-ar7/ar7.h +++ b/arch/mips/include/asm/mach-ar7/ar7.h | |||
@@ -201,7 +201,6 @@ static inline void ar7_device_off(u32 bit) | |||
201 | } | 201 | } |
202 | 202 | ||
203 | int __init ar7_gpio_init(void); | 203 | int __init ar7_gpio_init(void); |
204 | 204 | void __init ar7_init_clocks(void); | |
205 | int __init ar7_gpio_init(void); | ||
206 | 205 | ||
207 | #endif /* __AR7_H__ */ | 206 | #endif /* __AR7_H__ */ |
diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h index c58ebd8bc15..9759588ba3c 100644 --- a/arch/mips/include/asm/mach-bcm47xx/nvram.h +++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #define __NVRAM_H | 12 | #define __NVRAM_H |
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/kernel.h> | ||
15 | 16 | ||
16 | struct nvram_header { | 17 | struct nvram_header { |
17 | u32 magic; | 18 | u32 magic; |
@@ -36,4 +37,10 @@ struct nvram_header { | |||
36 | 37 | ||
37 | extern int nvram_getenv(char *name, char *val, size_t val_len); | 38 | extern int nvram_getenv(char *name, char *val, size_t val_len); |
38 | 39 | ||
40 | static inline void nvram_parse_macaddr(char *buf, u8 *macaddr) | ||
41 | { | ||
42 | sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1], | ||
43 | &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]); | ||
44 | } | ||
45 | |||
39 | #endif | 46 | #endif |
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 5742bb4d78f..5c0a3575877 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * Copyright (c) 2009 Qi Hardware inc., | 6 | * Copyright (c) 2009 Qi Hardware inc., |
7 | * Author: Xiangfu Liu <xiangfu@qi-hardware.com> | 7 | * Author: Xiangfu Liu <xiangfu@qi-hardware.com> |
8 | * Copyright 2010, Lars-Petrer Clausen <lars@metafoo.de> | 8 | * Copyright 2010, Lars-Peter Clausen <lars@metafoo.de> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2 or later | 11 | * it under the terms of the GNU General Public License version 2 or later |
@@ -235,7 +235,7 @@ static const unsigned int qi_lb60_keypad_rows[] = { | |||
235 | QI_LB60_GPIO_KEYIN(3), | 235 | QI_LB60_GPIO_KEYIN(3), |
236 | QI_LB60_GPIO_KEYIN(4), | 236 | QI_LB60_GPIO_KEYIN(4), |
237 | QI_LB60_GPIO_KEYIN(5), | 237 | QI_LB60_GPIO_KEYIN(5), |
238 | QI_LB60_GPIO_KEYIN(7), | 238 | QI_LB60_GPIO_KEYIN(6), |
239 | QI_LB60_GPIO_KEYIN8, | 239 | QI_LB60_GPIO_KEYIN8, |
240 | }; | 240 | }; |
241 | 241 | ||
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index 95bc2b5b14f..1cc9e544d16 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c | |||
@@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = { | |||
208 | 208 | ||
209 | /* PCM */ | 209 | /* PCM */ |
210 | struct platform_device jz4740_pcm_device = { | 210 | struct platform_device jz4740_pcm_device = { |
211 | .name = "jz4740-pcm", | 211 | .name = "jz4740-pcm-audio", |
212 | .id = -1, | 212 | .id = -1, |
213 | }; | 213 | }; |
214 | 214 | ||
diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c index cfeac15eb2e..4a70407f55b 100644 --- a/arch/mips/jz4740/prom.c +++ b/arch/mips/jz4740/prom.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <asm/bootinfo.h> | 23 | #include <asm/bootinfo.h> |
24 | #include <asm/mach-jz4740/base.h> | 24 | #include <asm/mach-jz4740/base.h> |
25 | 25 | ||
26 | void jz4740_init_cmdline(int argc, char *argv[]) | 26 | static __init void jz4740_init_cmdline(int argc, char *argv[]) |
27 | { | 27 | { |
28 | unsigned int count = COMMAND_LINE_SIZE - 1; | 28 | unsigned int count = COMMAND_LINE_SIZE - 1; |
29 | int i; | 29 | int i; |
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 2f4d7a99bcc..98c5a9737c1 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c | |||
@@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta, | |||
32 | cnt = read_c0_count(); | 32 | cnt = read_c0_count(); |
33 | cnt += delta; | 33 | cnt += delta; |
34 | write_c0_compare(cnt); | 34 | write_c0_compare(cnt); |
35 | res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; | 35 | res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0; |
36 | return res; | 36 | return res; |
37 | } | 37 | } |
38 | 38 | ||
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 71620e19827..68dae7b6b5d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
@@ -905,7 +905,8 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) | |||
905 | { | 905 | { |
906 | decode_configs(c); | 906 | decode_configs(c); |
907 | switch (c->processor_id & 0xff00) { | 907 | switch (c->processor_id & 0xff00) { |
908 | case PRID_IMP_BMIPS32: | 908 | case PRID_IMP_BMIPS32_REV4: |
909 | case PRID_IMP_BMIPS32_REV8: | ||
909 | c->cputype = CPU_BMIPS32; | 910 | c->cputype = CPU_BMIPS32; |
910 | __cpu_name[cpu] = "Broadcom BMIPS32"; | 911 | __cpu_name[cpu] = "Broadcom BMIPS32"; |
911 | break; | 912 | break; |
@@ -933,10 +934,6 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu) | |||
933 | __cpu_name[cpu] = "Broadcom BMIPS5000"; | 934 | __cpu_name[cpu] = "Broadcom BMIPS5000"; |
934 | c->options |= MIPS_CPU_ULRI; | 935 | c->options |= MIPS_CPU_ULRI; |
935 | break; | 936 | break; |
936 | case PRID_IMP_BMIPS4KC: | ||
937 | c->cputype = CPU_4KC; | ||
938 | __cpu_name[cpu] = "MIPS 4Kc"; | ||
939 | break; | ||
940 | } | 937 | } |
941 | } | 938 | } |
942 | 939 | ||
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 6343b4a5b83..876a75cc376 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -251,14 +251,15 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz, | |||
251 | 251 | ||
252 | SYSCALL_DEFINE1(32_personality, unsigned long, personality) | 252 | SYSCALL_DEFINE1(32_personality, unsigned long, personality) |
253 | { | 253 | { |
254 | unsigned int p = personality & 0xffffffff; | ||
254 | int ret; | 255 | int ret; |
255 | personality &= 0xffffffff; | 256 | |
256 | if (personality(current->personality) == PER_LINUX32 && | 257 | if (personality(current->personality) == PER_LINUX32 && |
257 | personality == PER_LINUX) | 258 | personality(p) == PER_LINUX) |
258 | personality = PER_LINUX32; | 259 | p = (p & ~PER_MASK) | PER_LINUX32; |
259 | ret = sys_personality(personality); | 260 | ret = sys_personality(p); |
260 | if (ret == PER_LINUX32) | 261 | if (ret != -1 && personality(ret) == PER_LINUX32) |
261 | ret = PER_LINUX; | 262 | ret = (ret & ~PER_MASK) | PER_LINUX; |
262 | return ret; | 263 | return ret; |
263 | } | 264 | } |
264 | 265 | ||
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 99960940d4a..ae167df73dd 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -142,7 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
142 | childregs->regs[7] = 0; /* Clear error flag */ | 142 | childregs->regs[7] = 0; /* Clear error flag */ |
143 | 143 | ||
144 | childregs->regs[2] = 0; /* Child gets zero as return value */ | 144 | childregs->regs[2] = 0; /* Child gets zero as return value */ |
145 | regs->regs[2] = p->pid; | ||
146 | 145 | ||
147 | if (childregs->cp0_status & ST0_CU0) { | 146 | if (childregs->cp0_status & ST0_CU0) { |
148 | childregs->regs[28] = (unsigned long) ti; | 147 | childregs->regs[28] = (unsigned long) ti; |
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index e000b278f02..9dbe5836895 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c | |||
@@ -100,7 +100,7 @@ void __init device_tree_init(void) | |||
100 | return; | 100 | return; |
101 | 101 | ||
102 | base = virt_to_phys((void *)initial_boot_params); | 102 | base = virt_to_phys((void *)initial_boot_params); |
103 | size = initial_boot_params->totalsize; | 103 | size = be32_to_cpu(initial_boot_params->totalsize); |
104 | 104 | ||
105 | /* Before we do anything, lets reserve the dt blob */ | 105 | /* Before we do anything, lets reserve the dt blob */ |
106 | reserve_mem_mach(base, size); | 106 | reserve_mem_mach(base, size); |
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 43e7cdc5ded..c0e81418ba2 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c | |||
@@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void) | |||
153 | { | 153 | { |
154 | extern int gic_present; | 154 | extern int gic_present; |
155 | 155 | ||
156 | /* This is Malta specific: IPI,performance and timer inetrrupts */ | 156 | /* This is Malta specific: IPI,performance and timer interrupts */ |
157 | if (gic_present) | 157 | if (gic_present) |
158 | change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | | 158 | change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | |
159 | STATUSF_IP6 | STATUSF_IP7); | 159 | STATUSF_IP6 | STATUSF_IP7); |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8e9fbe75894..e9710430254 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -83,7 +83,8 @@ extern asmlinkage void handle_mcheck(void); | |||
83 | extern asmlinkage void handle_reserved(void); | 83 | extern asmlinkage void handle_reserved(void); |
84 | 84 | ||
85 | extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, | 85 | extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, |
86 | struct mips_fpu_struct *ctx, int has_fpu); | 86 | struct mips_fpu_struct *ctx, int has_fpu, |
87 | void *__user *fault_addr); | ||
87 | 88 | ||
88 | void (*board_be_init)(void); | 89 | void (*board_be_init)(void); |
89 | int (*board_be_handler)(struct pt_regs *regs, int is_fixup); | 90 | int (*board_be_handler)(struct pt_regs *regs, int is_fixup); |
@@ -661,12 +662,36 @@ asmlinkage void do_ov(struct pt_regs *regs) | |||
661 | force_sig_info(SIGFPE, &info, current); | 662 | force_sig_info(SIGFPE, &info, current); |
662 | } | 663 | } |
663 | 664 | ||
665 | static int process_fpemu_return(int sig, void __user *fault_addr) | ||
666 | { | ||
667 | if (sig == SIGSEGV || sig == SIGBUS) { | ||
668 | struct siginfo si = {0}; | ||
669 | si.si_addr = fault_addr; | ||
670 | si.si_signo = sig; | ||
671 | if (sig == SIGSEGV) { | ||
672 | if (find_vma(current->mm, (unsigned long)fault_addr)) | ||
673 | si.si_code = SEGV_ACCERR; | ||
674 | else | ||
675 | si.si_code = SEGV_MAPERR; | ||
676 | } else { | ||
677 | si.si_code = BUS_ADRERR; | ||
678 | } | ||
679 | force_sig_info(sig, &si, current); | ||
680 | return 1; | ||
681 | } else if (sig) { | ||
682 | force_sig(sig, current); | ||
683 | return 1; | ||
684 | } else { | ||
685 | return 0; | ||
686 | } | ||
687 | } | ||
688 | |||
664 | /* | 689 | /* |
665 | * XXX Delayed fp exceptions when doing a lazy ctx switch XXX | 690 | * XXX Delayed fp exceptions when doing a lazy ctx switch XXX |
666 | */ | 691 | */ |
667 | asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | 692 | asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) |
668 | { | 693 | { |
669 | siginfo_t info; | 694 | siginfo_t info = {0}; |
670 | 695 | ||
671 | if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) | 696 | if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) |
672 | == NOTIFY_STOP) | 697 | == NOTIFY_STOP) |
@@ -675,6 +700,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
675 | 700 | ||
676 | if (fcr31 & FPU_CSR_UNI_X) { | 701 | if (fcr31 & FPU_CSR_UNI_X) { |
677 | int sig; | 702 | int sig; |
703 | void __user *fault_addr = NULL; | ||
678 | 704 | ||
679 | /* | 705 | /* |
680 | * Unimplemented operation exception. If we've got the full | 706 | * Unimplemented operation exception. If we've got the full |
@@ -690,7 +716,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
690 | lose_fpu(1); | 716 | lose_fpu(1); |
691 | 717 | ||
692 | /* Run the emulator */ | 718 | /* Run the emulator */ |
693 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1); | 719 | sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, |
720 | &fault_addr); | ||
694 | 721 | ||
695 | /* | 722 | /* |
696 | * We can't allow the emulated instruction to leave any of | 723 | * We can't allow the emulated instruction to leave any of |
@@ -702,8 +729,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
702 | own_fpu(1); /* Using the FPU again. */ | 729 | own_fpu(1); /* Using the FPU again. */ |
703 | 730 | ||
704 | /* If something went wrong, signal */ | 731 | /* If something went wrong, signal */ |
705 | if (sig) | 732 | process_fpemu_return(sig, fault_addr); |
706 | force_sig(sig, current); | ||
707 | 733 | ||
708 | return; | 734 | return; |
709 | } else if (fcr31 & FPU_CSR_INV_X) | 735 | } else if (fcr31 & FPU_CSR_INV_X) |
@@ -996,11 +1022,11 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
996 | 1022 | ||
997 | if (!raw_cpu_has_fpu) { | 1023 | if (!raw_cpu_has_fpu) { |
998 | int sig; | 1024 | int sig; |
1025 | void __user *fault_addr = NULL; | ||
999 | sig = fpu_emulator_cop1Handler(regs, | 1026 | sig = fpu_emulator_cop1Handler(regs, |
1000 | ¤t->thread.fpu, 0); | 1027 | ¤t->thread.fpu, |
1001 | if (sig) | 1028 | 0, &fault_addr); |
1002 | force_sig(sig, current); | 1029 | if (!process_fpemu_return(sig, fault_addr)) |
1003 | else | ||
1004 | mt_ase_fp_affinity(); | 1030 | mt_ase_fp_affinity(); |
1005 | } | 1031 | } |
1006 | 1032 | ||
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 3eb3cde2f66..6a1fdfef8fd 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c | |||
@@ -1092,6 +1092,10 @@ static int vpe_open(struct inode *inode, struct file *filp) | |||
1092 | 1092 | ||
1093 | /* this of-course trashes what was there before... */ | 1093 | /* this of-course trashes what was there before... */ |
1094 | v->pbuffer = vmalloc(P_SIZE); | 1094 | v->pbuffer = vmalloc(P_SIZE); |
1095 | if (!v->pbuffer) { | ||
1096 | pr_warning("VPE loader: unable to allocate memory\n"); | ||
1097 | return -ENOMEM; | ||
1098 | } | ||
1095 | v->plen = P_SIZE; | 1099 | v->plen = P_SIZE; |
1096 | v->load_addr = NULL; | 1100 | v->load_addr = NULL; |
1097 | v->len = 0; | 1101 | v->len = 0; |
@@ -1149,10 +1153,9 @@ static int vpe_release(struct inode *inode, struct file *filp) | |||
1149 | if (ret < 0) | 1153 | if (ret < 0) |
1150 | v->shared_ptr = NULL; | 1154 | v->shared_ptr = NULL; |
1151 | 1155 | ||
1152 | // cleanup any temp buffers | 1156 | vfree(v->pbuffer); |
1153 | if (v->pbuffer) | ||
1154 | vfree(v->pbuffer); | ||
1155 | v->plen = 0; | 1157 | v->plen = 0; |
1158 | |||
1156 | return ret; | 1159 | return ret; |
1157 | } | 1160 | } |
1158 | 1161 | ||
@@ -1169,11 +1172,6 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer, | |||
1169 | if (v == NULL) | 1172 | if (v == NULL) |
1170 | return -ENODEV; | 1173 | return -ENODEV; |
1171 | 1174 | ||
1172 | if (v->pbuffer == NULL) { | ||
1173 | printk(KERN_ERR "VPE loader: no buffer for program\n"); | ||
1174 | return -ENOMEM; | ||
1175 | } | ||
1176 | |||
1177 | if ((count + v->len) > v->plen) { | 1175 | if ((count + v->len) > v->plen) { |
1178 | printk(KERN_WARNING | 1176 | printk(KERN_WARNING |
1179 | "VPE loader: elf size too big. Perhaps strip uneeded symbols\n"); | 1177 | "VPE loader: elf size too big. Perhaps strip uneeded symbols\n"); |
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 77dc3b20110..606c8a9efe3 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S | |||
@@ -161,16 +161,16 @@ FEXPORT(__bzero) | |||
161 | 161 | ||
162 | .Lfwd_fixup: | 162 | .Lfwd_fixup: |
163 | PTR_L t0, TI_TASK($28) | 163 | PTR_L t0, TI_TASK($28) |
164 | LONG_L t0, THREAD_BUADDR(t0) | ||
165 | andi a2, 0x3f | 164 | andi a2, 0x3f |
165 | LONG_L t0, THREAD_BUADDR(t0) | ||
166 | LONG_ADDU a2, t1 | 166 | LONG_ADDU a2, t1 |
167 | jr ra | 167 | jr ra |
168 | LONG_SUBU a2, t0 | 168 | LONG_SUBU a2, t0 |
169 | 169 | ||
170 | .Lpartial_fixup: | 170 | .Lpartial_fixup: |
171 | PTR_L t0, TI_TASK($28) | 171 | PTR_L t0, TI_TASK($28) |
172 | LONG_L t0, THREAD_BUADDR(t0) | ||
173 | andi a2, LONGMASK | 172 | andi a2, LONGMASK |
173 | LONG_L t0, THREAD_BUADDR(t0) | ||
174 | LONG_ADDU a2, t1 | 174 | LONG_ADDU a2, t1 |
175 | jr ra | 175 | jr ra |
176 | LONG_SUBU a2, t0 | 176 | LONG_SUBU a2, t0 |
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c index ae4cff97a56..11b193f848f 100644 --- a/arch/mips/loongson/common/env.c +++ b/arch/mips/loongson/common/env.c | |||
@@ -29,9 +29,9 @@ unsigned long memsize, highmemsize; | |||
29 | 29 | ||
30 | #define parse_even_earlier(res, option, p) \ | 30 | #define parse_even_earlier(res, option, p) \ |
31 | do { \ | 31 | do { \ |
32 | int ret; \ | ||
32 | if (strncmp(option, (char *)p, strlen(option)) == 0) \ | 33 | if (strncmp(option, (char *)p, strlen(option)) == 0) \ |
33 | strict_strtol((char *)p + strlen(option"="), \ | 34 | ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \ |
34 | 10, &res); \ | ||
35 | } while (0) | 35 | } while (0) |
36 | 36 | ||
37 | void __init prom_init_env(void) | 37 | void __init prom_init_env(void) |
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index b2ad1b0910f..d32cb050311 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c | |||
@@ -64,7 +64,7 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, | |||
64 | 64 | ||
65 | #if __mips >= 4 && __mips != 32 | 65 | #if __mips >= 4 && __mips != 32 |
66 | static int fpux_emu(struct pt_regs *, | 66 | static int fpux_emu(struct pt_regs *, |
67 | struct mips_fpu_struct *, mips_instruction); | 67 | struct mips_fpu_struct *, mips_instruction, void *__user *); |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | /* Further private data for which no space exists in mips_fpu_struct */ | 70 | /* Further private data for which no space exists in mips_fpu_struct */ |
@@ -208,16 +208,23 @@ static inline int cop1_64bit(struct pt_regs *xcp) | |||
208 | * Two instructions if the instruction is in a branch delay slot. | 208 | * Two instructions if the instruction is in a branch delay slot. |
209 | */ | 209 | */ |
210 | 210 | ||
211 | static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | 211 | static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, |
212 | void *__user *fault_addr) | ||
212 | { | 213 | { |
213 | mips_instruction ir; | 214 | mips_instruction ir; |
214 | unsigned long emulpc, contpc; | 215 | unsigned long emulpc, contpc; |
215 | unsigned int cond; | 216 | unsigned int cond; |
216 | 217 | ||
217 | if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { | 218 | if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { |
218 | MIPS_FPU_EMU_INC_STATS(errors); | 219 | MIPS_FPU_EMU_INC_STATS(errors); |
220 | *fault_addr = (mips_instruction __user *)xcp->cp0_epc; | ||
219 | return SIGBUS; | 221 | return SIGBUS; |
220 | } | 222 | } |
223 | if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { | ||
224 | MIPS_FPU_EMU_INC_STATS(errors); | ||
225 | *fault_addr = (mips_instruction __user *)xcp->cp0_epc; | ||
226 | return SIGSEGV; | ||
227 | } | ||
221 | 228 | ||
222 | /* XXX NEC Vr54xx bug workaround */ | 229 | /* XXX NEC Vr54xx bug workaround */ |
223 | if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) | 230 | if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) |
@@ -245,10 +252,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | |||
245 | #endif | 252 | #endif |
246 | return SIGILL; | 253 | return SIGILL; |
247 | } | 254 | } |
248 | if (get_user(ir, (mips_instruction __user *) emulpc)) { | 255 | if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) { |
249 | MIPS_FPU_EMU_INC_STATS(errors); | 256 | MIPS_FPU_EMU_INC_STATS(errors); |
257 | *fault_addr = (mips_instruction __user *)emulpc; | ||
250 | return SIGBUS; | 258 | return SIGBUS; |
251 | } | 259 | } |
260 | if (__get_user(ir, (mips_instruction __user *) emulpc)) { | ||
261 | MIPS_FPU_EMU_INC_STATS(errors); | ||
262 | *fault_addr = (mips_instruction __user *)emulpc; | ||
263 | return SIGSEGV; | ||
264 | } | ||
252 | /* __compute_return_epc() will have updated cp0_epc */ | 265 | /* __compute_return_epc() will have updated cp0_epc */ |
253 | contpc = xcp->cp0_epc; | 266 | contpc = xcp->cp0_epc; |
254 | /* In order not to confuse ptrace() et al, tweak context */ | 267 | /* In order not to confuse ptrace() et al, tweak context */ |
@@ -269,10 +282,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | |||
269 | u64 val; | 282 | u64 val; |
270 | 283 | ||
271 | MIPS_FPU_EMU_INC_STATS(loads); | 284 | MIPS_FPU_EMU_INC_STATS(loads); |
272 | if (get_user(val, va)) { | 285 | |
286 | if (!access_ok(VERIFY_READ, va, sizeof(u64))) { | ||
273 | MIPS_FPU_EMU_INC_STATS(errors); | 287 | MIPS_FPU_EMU_INC_STATS(errors); |
288 | *fault_addr = va; | ||
274 | return SIGBUS; | 289 | return SIGBUS; |
275 | } | 290 | } |
291 | if (__get_user(val, va)) { | ||
292 | MIPS_FPU_EMU_INC_STATS(errors); | ||
293 | *fault_addr = va; | ||
294 | return SIGSEGV; | ||
295 | } | ||
276 | DITOREG(val, MIPSInst_RT(ir)); | 296 | DITOREG(val, MIPSInst_RT(ir)); |
277 | break; | 297 | break; |
278 | } | 298 | } |
@@ -284,10 +304,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | |||
284 | 304 | ||
285 | MIPS_FPU_EMU_INC_STATS(stores); | 305 | MIPS_FPU_EMU_INC_STATS(stores); |
286 | DIFROMREG(val, MIPSInst_RT(ir)); | 306 | DIFROMREG(val, MIPSInst_RT(ir)); |
287 | if (put_user(val, va)) { | 307 | if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { |
288 | MIPS_FPU_EMU_INC_STATS(errors); | 308 | MIPS_FPU_EMU_INC_STATS(errors); |
309 | *fault_addr = va; | ||
289 | return SIGBUS; | 310 | return SIGBUS; |
290 | } | 311 | } |
312 | if (__put_user(val, va)) { | ||
313 | MIPS_FPU_EMU_INC_STATS(errors); | ||
314 | *fault_addr = va; | ||
315 | return SIGSEGV; | ||
316 | } | ||
291 | break; | 317 | break; |
292 | } | 318 | } |
293 | 319 | ||
@@ -297,10 +323,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | |||
297 | u32 val; | 323 | u32 val; |
298 | 324 | ||
299 | MIPS_FPU_EMU_INC_STATS(loads); | 325 | MIPS_FPU_EMU_INC_STATS(loads); |
300 | if (get_user(val, va)) { | 326 | if (!access_ok(VERIFY_READ, va, sizeof(u32))) { |
301 | MIPS_FPU_EMU_INC_STATS(errors); | 327 | MIPS_FPU_EMU_INC_STATS(errors); |
328 | *fault_addr = va; | ||
302 | return SIGBUS; | 329 | return SIGBUS; |
303 | } | 330 | } |
331 | if (__get_user(val, va)) { | ||
332 | MIPS_FPU_EMU_INC_STATS(errors); | ||
333 | *fault_addr = va; | ||
334 | return SIGSEGV; | ||
335 | } | ||
304 | SITOREG(val, MIPSInst_RT(ir)); | 336 | SITOREG(val, MIPSInst_RT(ir)); |
305 | break; | 337 | break; |
306 | } | 338 | } |
@@ -312,10 +344,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | |||
312 | 344 | ||
313 | MIPS_FPU_EMU_INC_STATS(stores); | 345 | MIPS_FPU_EMU_INC_STATS(stores); |
314 | SIFROMREG(val, MIPSInst_RT(ir)); | 346 | SIFROMREG(val, MIPSInst_RT(ir)); |
315 | if (put_user(val, va)) { | 347 | if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { |
316 | MIPS_FPU_EMU_INC_STATS(errors); | 348 | MIPS_FPU_EMU_INC_STATS(errors); |
349 | *fault_addr = va; | ||
317 | return SIGBUS; | 350 | return SIGBUS; |
318 | } | 351 | } |
352 | if (__put_user(val, va)) { | ||
353 | MIPS_FPU_EMU_INC_STATS(errors); | ||
354 | *fault_addr = va; | ||
355 | return SIGSEGV; | ||
356 | } | ||
319 | break; | 357 | break; |
320 | } | 358 | } |
321 | 359 | ||
@@ -440,11 +478,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | |||
440 | contpc = (xcp->cp0_epc + | 478 | contpc = (xcp->cp0_epc + |
441 | (MIPSInst_SIMM(ir) << 2)); | 479 | (MIPSInst_SIMM(ir) << 2)); |
442 | 480 | ||
443 | if (get_user(ir, | 481 | if (!access_ok(VERIFY_READ, xcp->cp0_epc, |
444 | (mips_instruction __user *) xcp->cp0_epc)) { | 482 | sizeof(mips_instruction))) { |
445 | MIPS_FPU_EMU_INC_STATS(errors); | 483 | MIPS_FPU_EMU_INC_STATS(errors); |
484 | *fault_addr = (mips_instruction __user *)xcp->cp0_epc; | ||
446 | return SIGBUS; | 485 | return SIGBUS; |
447 | } | 486 | } |
487 | if (__get_user(ir, | ||
488 | (mips_instruction __user *) xcp->cp0_epc)) { | ||
489 | MIPS_FPU_EMU_INC_STATS(errors); | ||
490 | *fault_addr = (mips_instruction __user *)xcp->cp0_epc; | ||
491 | return SIGSEGV; | ||
492 | } | ||
448 | 493 | ||
449 | switch (MIPSInst_OPCODE(ir)) { | 494 | switch (MIPSInst_OPCODE(ir)) { |
450 | case lwc1_op: | 495 | case lwc1_op: |
@@ -506,9 +551,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) | |||
506 | 551 | ||
507 | #if __mips >= 4 && __mips != 32 | 552 | #if __mips >= 4 && __mips != 32 |
508 | case cop1x_op:{ | 553 | case cop1x_op:{ |
509 | int sig; | 554 | int sig = fpux_emu(xcp, ctx, ir, fault_addr); |
510 | 555 | if (sig) | |
511 | if ((sig = fpux_emu(xcp, ctx, ir))) | ||
512 | return sig; | 556 | return sig; |
513 | break; | 557 | break; |
514 | } | 558 | } |
@@ -604,7 +648,7 @@ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); | |||
604 | DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); | 648 | DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); |
605 | 649 | ||
606 | static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | 650 | static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, |
607 | mips_instruction ir) | 651 | mips_instruction ir, void *__user *fault_addr) |
608 | { | 652 | { |
609 | unsigned rcsr = 0; /* resulting csr */ | 653 | unsigned rcsr = 0; /* resulting csr */ |
610 | 654 | ||
@@ -624,10 +668,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | |||
624 | xcp->regs[MIPSInst_FT(ir)]); | 668 | xcp->regs[MIPSInst_FT(ir)]); |
625 | 669 | ||
626 | MIPS_FPU_EMU_INC_STATS(loads); | 670 | MIPS_FPU_EMU_INC_STATS(loads); |
627 | if (get_user(val, va)) { | 671 | if (!access_ok(VERIFY_READ, va, sizeof(u32))) { |
628 | MIPS_FPU_EMU_INC_STATS(errors); | 672 | MIPS_FPU_EMU_INC_STATS(errors); |
673 | *fault_addr = va; | ||
629 | return SIGBUS; | 674 | return SIGBUS; |
630 | } | 675 | } |
676 | if (__get_user(val, va)) { | ||
677 | MIPS_FPU_EMU_INC_STATS(errors); | ||
678 | *fault_addr = va; | ||
679 | return SIGSEGV; | ||
680 | } | ||
631 | SITOREG(val, MIPSInst_FD(ir)); | 681 | SITOREG(val, MIPSInst_FD(ir)); |
632 | break; | 682 | break; |
633 | 683 | ||
@@ -638,10 +688,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | |||
638 | MIPS_FPU_EMU_INC_STATS(stores); | 688 | MIPS_FPU_EMU_INC_STATS(stores); |
639 | 689 | ||
640 | SIFROMREG(val, MIPSInst_FS(ir)); | 690 | SIFROMREG(val, MIPSInst_FS(ir)); |
641 | if (put_user(val, va)) { | 691 | if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { |
642 | MIPS_FPU_EMU_INC_STATS(errors); | 692 | MIPS_FPU_EMU_INC_STATS(errors); |
693 | *fault_addr = va; | ||
643 | return SIGBUS; | 694 | return SIGBUS; |
644 | } | 695 | } |
696 | if (put_user(val, va)) { | ||
697 | MIPS_FPU_EMU_INC_STATS(errors); | ||
698 | *fault_addr = va; | ||
699 | return SIGSEGV; | ||
700 | } | ||
645 | break; | 701 | break; |
646 | 702 | ||
647 | case madd_s_op: | 703 | case madd_s_op: |
@@ -701,10 +757,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | |||
701 | xcp->regs[MIPSInst_FT(ir)]); | 757 | xcp->regs[MIPSInst_FT(ir)]); |
702 | 758 | ||
703 | MIPS_FPU_EMU_INC_STATS(loads); | 759 | MIPS_FPU_EMU_INC_STATS(loads); |
704 | if (get_user(val, va)) { | 760 | if (!access_ok(VERIFY_READ, va, sizeof(u64))) { |
705 | MIPS_FPU_EMU_INC_STATS(errors); | 761 | MIPS_FPU_EMU_INC_STATS(errors); |
762 | *fault_addr = va; | ||
706 | return SIGBUS; | 763 | return SIGBUS; |
707 | } | 764 | } |
765 | if (__get_user(val, va)) { | ||
766 | MIPS_FPU_EMU_INC_STATS(errors); | ||
767 | *fault_addr = va; | ||
768 | return SIGSEGV; | ||
769 | } | ||
708 | DITOREG(val, MIPSInst_FD(ir)); | 770 | DITOREG(val, MIPSInst_FD(ir)); |
709 | break; | 771 | break; |
710 | 772 | ||
@@ -714,10 +776,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | |||
714 | 776 | ||
715 | MIPS_FPU_EMU_INC_STATS(stores); | 777 | MIPS_FPU_EMU_INC_STATS(stores); |
716 | DIFROMREG(val, MIPSInst_FS(ir)); | 778 | DIFROMREG(val, MIPSInst_FS(ir)); |
717 | if (put_user(val, va)) { | 779 | if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { |
718 | MIPS_FPU_EMU_INC_STATS(errors); | 780 | MIPS_FPU_EMU_INC_STATS(errors); |
781 | *fault_addr = va; | ||
719 | return SIGBUS; | 782 | return SIGBUS; |
720 | } | 783 | } |
784 | if (__put_user(val, va)) { | ||
785 | MIPS_FPU_EMU_INC_STATS(errors); | ||
786 | *fault_addr = va; | ||
787 | return SIGSEGV; | ||
788 | } | ||
721 | break; | 789 | break; |
722 | 790 | ||
723 | case madd_d_op: | 791 | case madd_d_op: |
@@ -1242,7 +1310,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | |||
1242 | } | 1310 | } |
1243 | 1311 | ||
1244 | int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | 1312 | int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, |
1245 | int has_fpu) | 1313 | int has_fpu, void *__user *fault_addr) |
1246 | { | 1314 | { |
1247 | unsigned long oldepc, prevepc; | 1315 | unsigned long oldepc, prevepc; |
1248 | mips_instruction insn; | 1316 | mips_instruction insn; |
@@ -1252,10 +1320,16 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | |||
1252 | do { | 1320 | do { |
1253 | prevepc = xcp->cp0_epc; | 1321 | prevepc = xcp->cp0_epc; |
1254 | 1322 | ||
1255 | if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { | 1323 | if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { |
1256 | MIPS_FPU_EMU_INC_STATS(errors); | 1324 | MIPS_FPU_EMU_INC_STATS(errors); |
1325 | *fault_addr = (mips_instruction __user *)xcp->cp0_epc; | ||
1257 | return SIGBUS; | 1326 | return SIGBUS; |
1258 | } | 1327 | } |
1328 | if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { | ||
1329 | MIPS_FPU_EMU_INC_STATS(errors); | ||
1330 | *fault_addr = (mips_instruction __user *)xcp->cp0_epc; | ||
1331 | return SIGSEGV; | ||
1332 | } | ||
1259 | if (insn == 0) | 1333 | if (insn == 0) |
1260 | xcp->cp0_epc += 4; /* skip nops */ | 1334 | xcp->cp0_epc += 4; /* skip nops */ |
1261 | else { | 1335 | else { |
@@ -1267,7 +1341,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, | |||
1267 | */ | 1341 | */ |
1268 | /* convert to ieee library modes */ | 1342 | /* convert to ieee library modes */ |
1269 | ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; | 1343 | ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; |
1270 | sig = cop1Emulate(xcp, ctx); | 1344 | sig = cop1Emulate(xcp, ctx, fault_addr); |
1271 | /* revert to mips rounding mode */ | 1345 | /* revert to mips rounding mode */ |
1272 | ieee754_csr.rm = mips_rm[ieee754_csr.rm]; | 1346 | ieee754_csr.rm = mips_rm[ieee754_csr.rm]; |
1273 | } | 1347 | } |
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 4fc1a0fbe00..21ea14efb83 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c | |||
@@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask) | |||
288 | return plat_dma_supported(dev, mask); | 288 | return plat_dma_supported(dev, mask); |
289 | } | 289 | } |
290 | 290 | ||
291 | void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, | 291 | void dma_cache_sync(struct device *dev, void *vaddr, size_t size, |
292 | enum dma_data_direction direction) | 292 | enum dma_data_direction direction) |
293 | { | 293 | { |
294 | BUG_ON(direction == DMA_NONE); | 294 | BUG_ON(direction == DMA_NONE); |
@@ -298,6 +298,8 @@ void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size, | |||
298 | __dma_sync((unsigned long)vaddr, size, direction); | 298 | __dma_sync((unsigned long)vaddr, size, direction); |
299 | } | 299 | } |
300 | 300 | ||
301 | EXPORT_SYMBOL(dma_cache_sync); | ||
302 | |||
301 | static struct dma_map_ops mips_default_dma_map_ops = { | 303 | static struct dma_map_ops mips_default_dma_map_ops = { |
302 | .alloc_coherent = mips_dma_alloc_coherent, | 304 | .alloc_coherent = mips_dma_alloc_coherent, |
303 | .free_coherent = mips_dma_free_coherent, | 305 | .free_coherent = mips_dma_free_coherent, |
diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 505fecad468..9cca8de0054 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c | |||
@@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = { | |||
68 | */ | 68 | */ |
69 | static inline int mips_sc_is_activated(struct cpuinfo_mips *c) | 69 | static inline int mips_sc_is_activated(struct cpuinfo_mips *c) |
70 | { | 70 | { |
71 | unsigned int config2 = read_c0_config2(); | ||
72 | unsigned int tmp; | ||
73 | |||
71 | /* Check the bypass bit (L2B) */ | 74 | /* Check the bypass bit (L2B) */ |
72 | switch (c->cputype) { | 75 | switch (c->cputype) { |
73 | case CPU_34K: | 76 | case CPU_34K: |
@@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c) | |||
83 | c->scache.linesz = 2 << tmp; | 86 | c->scache.linesz = 2 << tmp; |
84 | else | 87 | else |
85 | return 0; | 88 | return 0; |
89 | return 1; | ||
86 | } | 90 | } |
87 | 91 | ||
88 | static inline int __init mips_sc_probe(void) | 92 | static inline int __init mips_sc_probe(void) |
diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c index b7f1d9c4a8a..434d7b1a8c6 100644 --- a/arch/mips/pmc-sierra/yosemite/py-console.c +++ b/arch/mips/pmc-sierra/yosemite/py-console.c | |||
@@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys) | |||
65 | 65 | ||
66 | __asm__ __volatile__ ( | 66 | __asm__ __volatile__ ( |
67 | " .set mips3 \n" | 67 | " .set mips3 \n" |
68 | " .set push \n" | ||
69 | " .set noreorder \n" | ||
70 | " .set nomacro \n" | ||
68 | " ld %0, %1 \n" | 71 | " ld %0, %1 \n" |
72 | " .set pop \n" | ||
69 | " lbu %0, (%0) \n" | 73 | " lbu %0, (%0) \n" |
70 | " .set mips0 \n" | 74 | " .set mips0 \n" |
71 | : "=r" (res) | 75 | : "=r" (res) |
72 | : "m" (vaddr)); | 76 | : "R" (vaddr)); |
73 | 77 | ||
74 | write_c0_status(sr); | 78 | write_c0_status(sr); |
75 | ssnop_4(); | 79 | ssnop_4(); |
@@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c) | |||
89 | 93 | ||
90 | __asm__ __volatile__ ( | 94 | __asm__ __volatile__ ( |
91 | " .set mips3 \n" | 95 | " .set mips3 \n" |
96 | " .set push \n" | ||
97 | " .set noreorder \n" | ||
98 | " .set nomacro \n" | ||
92 | " ld %0, %1 \n" | 99 | " ld %0, %1 \n" |
100 | " .set pop \n" | ||
93 | " sb %2, (%0) \n" | 101 | " sb %2, (%0) \n" |
94 | " .set mips0 \n" | 102 | " .set mips0 \n" |
95 | : "=&r" (tmp) | 103 | : "=&r" (tmp) |
96 | : "m" (vaddr), "r" (c)); | 104 | : "R" (vaddr), "r" (c)); |
97 | 105 | ||
98 | write_c0_status(sr); | 106 | write_c0_status(sr); |
99 | ssnop_4(); | 107 | ssnop_4(); |
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index c308989fc46..41707a245de 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c | |||
@@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup) | |||
82 | enum swarm_rtc_type { | 82 | enum swarm_rtc_type { |
83 | RTC_NONE, | 83 | RTC_NONE, |
84 | RTC_XICOR, | 84 | RTC_XICOR, |
85 | RTC_M4LT81 | 85 | RTC_M41T81, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | enum swarm_rtc_type swarm_rtc_type; | 88 | enum swarm_rtc_type swarm_rtc_type; |
@@ -96,7 +96,7 @@ void read_persistent_clock(struct timespec *ts) | |||
96 | sec = xicor_get_time(); | 96 | sec = xicor_get_time(); |
97 | break; | 97 | break; |
98 | 98 | ||
99 | case RTC_M4LT81: | 99 | case RTC_M41T81: |
100 | sec = m41t81_get_time(); | 100 | sec = m41t81_get_time(); |
101 | break; | 101 | break; |
102 | 102 | ||
@@ -115,7 +115,7 @@ int rtc_mips_set_time(unsigned long sec) | |||
115 | case RTC_XICOR: | 115 | case RTC_XICOR: |
116 | return xicor_set_time(sec); | 116 | return xicor_set_time(sec); |
117 | 117 | ||
118 | case RTC_M4LT81: | 118 | case RTC_M41T81: |
119 | return m41t81_set_time(sec); | 119 | return m41t81_set_time(sec); |
120 | 120 | ||
121 | case RTC_NONE: | 121 | case RTC_NONE: |
@@ -141,7 +141,7 @@ void __init plat_mem_setup(void) | |||
141 | if (xicor_probe()) | 141 | if (xicor_probe()) |
142 | swarm_rtc_type = RTC_XICOR; | 142 | swarm_rtc_type = RTC_XICOR; |
143 | if (m41t81_probe()) | 143 | if (m41t81_probe()) |
144 | swarm_rtc_type = RTC_M4LT81; | 144 | swarm_rtc_type = RTC_M41T81; |
145 | 145 | ||
146 | #ifdef CONFIG_VT | 146 | #ifdef CONFIG_VT |
147 | screen_info = (struct screen_info) { | 147 | screen_info = (struct screen_info) { |
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c index c2e44597c22..ac11754ecec 100644 --- a/arch/mn10300/kernel/irq.c +++ b/arch/mn10300/kernel/irq.c | |||
@@ -459,7 +459,7 @@ void migrate_irqs(void) | |||
459 | tmp = CROSS_GxICR(irq, new); | 459 | tmp = CROSS_GxICR(irq, new); |
460 | 460 | ||
461 | x &= GxICR_LEVEL | GxICR_ENABLE; | 461 | x &= GxICR_LEVEL | GxICR_ENABLE; |
462 | if (GxICR(irq) & GxICR_REQUEST) { | 462 | if (GxICR(irq) & GxICR_REQUEST) |
463 | x |= GxICR_REQUEST | GxICR_DETECT; | 463 | x |= GxICR_REQUEST | GxICR_DETECT; |
464 | CROSS_GxICR(irq, new) = x; | 464 | CROSS_GxICR(irq, new) = x; |
465 | tmp = CROSS_GxICR(irq, new); | 465 | tmp = CROSS_GxICR(irq, new); |
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index f860a340acc..75da468090b 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c | |||
@@ -40,21 +40,17 @@ unsigned long long sched_clock(void) | |||
40 | unsigned long long ll; | 40 | unsigned long long ll; |
41 | unsigned l[2]; | 41 | unsigned l[2]; |
42 | } tsc64, result; | 42 | } tsc64, result; |
43 | unsigned long tsc, tmp; | 43 | unsigned long tmp; |
44 | unsigned product[3]; /* 96-bit intermediate value */ | 44 | unsigned product[3]; /* 96-bit intermediate value */ |
45 | 45 | ||
46 | /* cnt32_to_63() is not safe with preemption */ | 46 | /* cnt32_to_63() is not safe with preemption */ |
47 | preempt_disable(); | 47 | preempt_disable(); |
48 | 48 | ||
49 | /* read the TSC value | 49 | /* expand the tsc to 64-bits. |
50 | */ | ||
51 | tsc = get_cycles(); | ||
52 | |||
53 | /* expand to 64-bits. | ||
54 | * - sched_clock() must be called once a minute or better or the | 50 | * - sched_clock() must be called once a minute or better or the |
55 | * following will go horribly wrong - see cnt32_to_63() | 51 | * following will go horribly wrong - see cnt32_to_63() |
56 | */ | 52 | */ |
57 | tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL; | 53 | tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL; |
58 | 54 | ||
59 | preempt_enable(); | 55 | preempt_enable(); |
60 | 56 | ||
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index fea833e18ad..e0d703c7fdf 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/of_gpio.h> | 63 | #include <linux/of_gpio.h> |
64 | #include <linux/kernel.h> | 64 | #include <linux/kernel.h> |
65 | #include <linux/slab.h> | 65 | #include <linux/slab.h> |
66 | #include <linux/fs.h> | ||
66 | #include <linux/watchdog.h> | 67 | #include <linux/watchdog.h> |
67 | #include <linux/miscdevice.h> | 68 | #include <linux/miscdevice.h> |
68 | #include <linux/uaccess.h> | 69 | #include <linux/uaccess.h> |
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 2e9d78d21fd..25cf0b34dff 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | config SUPERH | 1 | config SUPERH |
2 | def_bool y | 2 | def_bool y |
3 | select EMBEDDED | 3 | select EMBEDDED |
4 | select HAVE_CLK | 4 | select CLKDEV_LOOKUP |
5 | select HAVE_IDE if HAS_IOPORT | 5 | select HAVE_IDE if HAS_IOPORT |
6 | select HAVE_MEMBLOCK | 6 | select HAVE_MEMBLOCK |
7 | select HAVE_OPROFILE | 7 | select HAVE_OPROFILE |
diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c index a5ecfbacaf3..87618c91d17 100644 --- a/arch/sh/boards/mach-highlander/setup.c +++ b/arch/sh/boards/mach-highlander/setup.c | |||
@@ -24,10 +24,10 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/usb/r8a66597.h> | 25 | #include <linux/usb/r8a66597.h> |
26 | #include <linux/usb/m66592.h> | 26 | #include <linux/usb/m66592.h> |
27 | #include <linux/clkdev.h> | ||
27 | #include <net/ax88796.h> | 28 | #include <net/ax88796.h> |
28 | #include <asm/machvec.h> | 29 | #include <asm/machvec.h> |
29 | #include <mach/highlander.h> | 30 | #include <mach/highlander.h> |
30 | #include <asm/clkdev.h> | ||
31 | #include <asm/clock.h> | 31 | #include <asm/clock.h> |
32 | #include <asm/heartbeat.h> | 32 | #include <asm/heartbeat.h> |
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
diff --git a/arch/sh/boards/mach-se/7206/irq.c b/arch/sh/boards/mach-se/7206/irq.c index d961949600f..9070d7e6070 100644 --- a/arch/sh/boards/mach-se/7206/irq.c +++ b/arch/sh/boards/mach-se/7206/irq.c | |||
@@ -140,7 +140,7 @@ void __init init_se7206_IRQ(void) | |||
140 | make_se7206_irq(IRQ1_IRQ); /* ATA */ | 140 | make_se7206_irq(IRQ1_IRQ); /* ATA */ |
141 | make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ | 141 | make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ |
142 | 142 | ||
143 | __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR); /* ICR1 */ | 143 | __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */ |
144 | 144 | ||
145 | /* FPGA System register setup*/ | 145 | /* FPGA System register setup*/ |
146 | __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ | 146 | __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ |
diff --git a/arch/sh/include/asm/clkdev.h b/arch/sh/include/asm/clkdev.h index 5645f358128..6ba91868201 100644 --- a/arch/sh/include/asm/clkdev.h +++ b/arch/sh/include/asm/clkdev.h | |||
@@ -1,9 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/sh/include/asm/clkdev.h | 2 | * Copyright (C) 2010 Paul Mundt <lethal@linux-sh.org> |
3 | * | ||
4 | * Cloned from arch/arm/include/asm/clkdev.h: | ||
5 | * | ||
6 | * Copyright (C) 2008 Russell King. | ||
7 | * | 3 | * |
8 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
@@ -11,25 +7,25 @@ | |||
11 | * | 7 | * |
12 | * Helper for the clk API to assist looking up a struct clk. | 8 | * Helper for the clk API to assist looking up a struct clk. |
13 | */ | 9 | */ |
14 | #ifndef __ASM_CLKDEV_H | ||
15 | #define __ASM_CLKDEV_H | ||
16 | 10 | ||
17 | struct clk; | 11 | #ifndef __CLKDEV__H_ |
12 | #define __CLKDEV__H_ | ||
18 | 13 | ||
19 | struct clk_lookup { | 14 | #include <linux/bootmem.h> |
20 | struct list_head node; | 15 | #include <linux/mm.h> |
21 | const char *dev_id; | 16 | #include <linux/slab.h> |
22 | const char *con_id; | ||
23 | struct clk *clk; | ||
24 | }; | ||
25 | 17 | ||
26 | struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, | 18 | #include <asm/clock.h> |
27 | const char *dev_fmt, ...); | ||
28 | 19 | ||
29 | void clkdev_add(struct clk_lookup *cl); | 20 | static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size) |
30 | void clkdev_drop(struct clk_lookup *cl); | 21 | { |
22 | if (!slab_is_available()) | ||
23 | return alloc_bootmem_low_pages(size); | ||
24 | else | ||
25 | return kzalloc(size, GFP_KERNEL); | ||
26 | } | ||
31 | 27 | ||
32 | void clkdev_add_table(struct clk_lookup *, size_t); | 28 | #define __clk_put(clk) |
33 | int clk_add_alias(const char *, const char *, char *, struct device *); | 29 | #define __clk_get(clk) ({ 1; }) |
34 | 30 | ||
35 | #endif | 31 | #endif /* __CLKDEV_H__ */ |
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 8eed6a48544..cf652217952 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -11,7 +11,7 @@ endif | |||
11 | 11 | ||
12 | CFLAGS_REMOVE_return_address.o = -pg | 12 | CFLAGS_REMOVE_return_address.o = -pg |
13 | 13 | ||
14 | obj-y := clkdev.o debugtraps.o dma-nommu.o dumpstack.o \ | 14 | obj-y := debugtraps.o dma-nommu.o dumpstack.o \ |
15 | idle.o io.o irq.o irq_$(BITS).o kdebugfs.o \ | 15 | idle.o io.o irq.o irq_$(BITS).o kdebugfs.o \ |
16 | machvec.o nmi_debug.o process.o \ | 16 | machvec.o nmi_debug.o process.o \ |
17 | process_$(BITS).o ptrace.o ptrace_$(BITS).o \ | 17 | process_$(BITS).o ptrace.o ptrace_$(BITS).o \ |
diff --git a/arch/sh/kernel/clkdev.c b/arch/sh/kernel/clkdev.c deleted file mode 100644 index 1f800ef4a73..00000000000 --- a/arch/sh/kernel/clkdev.c +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/clkdev.c | ||
3 | * | ||
4 | * Cloned from arch/arm/common/clkdev.c: | ||
5 | * | ||
6 | * Copyright (C) 2008 Russell King. | ||
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 version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Helper for the clk API to assist looking up a struct clk. | ||
13 | */ | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/bootmem.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <asm/clock.h> | ||
27 | #include <asm/clkdev.h> | ||
28 | |||
29 | static LIST_HEAD(clocks); | ||
30 | static DEFINE_MUTEX(clocks_mutex); | ||
31 | |||
32 | /* | ||
33 | * Find the correct struct clk for the device and connection ID. | ||
34 | * We do slightly fuzzy matching here: | ||
35 | * An entry with a NULL ID is assumed to be a wildcard. | ||
36 | * If an entry has a device ID, it must match | ||
37 | * If an entry has a connection ID, it must match | ||
38 | * Then we take the most specific entry - with the following | ||
39 | * order of precedence: dev+con > dev only > con only. | ||
40 | */ | ||
41 | static struct clk *clk_find(const char *dev_id, const char *con_id) | ||
42 | { | ||
43 | struct clk_lookup *p; | ||
44 | struct clk *clk = NULL; | ||
45 | int match, best = 0; | ||
46 | |||
47 | list_for_each_entry(p, &clocks, node) { | ||
48 | match = 0; | ||
49 | if (p->dev_id) { | ||
50 | if (!dev_id || strcmp(p->dev_id, dev_id)) | ||
51 | continue; | ||
52 | match += 2; | ||
53 | } | ||
54 | if (p->con_id) { | ||
55 | if (!con_id || strcmp(p->con_id, con_id)) | ||
56 | continue; | ||
57 | match += 1; | ||
58 | } | ||
59 | if (match == 0) | ||
60 | continue; | ||
61 | |||
62 | if (match > best) { | ||
63 | clk = p->clk; | ||
64 | best = match; | ||
65 | } | ||
66 | } | ||
67 | return clk; | ||
68 | } | ||
69 | |||
70 | struct clk *clk_get_sys(const char *dev_id, const char *con_id) | ||
71 | { | ||
72 | struct clk *clk; | ||
73 | |||
74 | mutex_lock(&clocks_mutex); | ||
75 | clk = clk_find(dev_id, con_id); | ||
76 | mutex_unlock(&clocks_mutex); | ||
77 | |||
78 | return clk ? clk : ERR_PTR(-ENOENT); | ||
79 | } | ||
80 | EXPORT_SYMBOL(clk_get_sys); | ||
81 | |||
82 | void clkdev_add(struct clk_lookup *cl) | ||
83 | { | ||
84 | mutex_lock(&clocks_mutex); | ||
85 | list_add_tail(&cl->node, &clocks); | ||
86 | mutex_unlock(&clocks_mutex); | ||
87 | } | ||
88 | EXPORT_SYMBOL(clkdev_add); | ||
89 | |||
90 | void __init clkdev_add_table(struct clk_lookup *cl, size_t num) | ||
91 | { | ||
92 | mutex_lock(&clocks_mutex); | ||
93 | while (num--) { | ||
94 | list_add_tail(&cl->node, &clocks); | ||
95 | cl++; | ||
96 | } | ||
97 | mutex_unlock(&clocks_mutex); | ||
98 | } | ||
99 | |||
100 | #define MAX_DEV_ID 20 | ||
101 | #define MAX_CON_ID 16 | ||
102 | |||
103 | struct clk_lookup_alloc { | ||
104 | struct clk_lookup cl; | ||
105 | char dev_id[MAX_DEV_ID]; | ||
106 | char con_id[MAX_CON_ID]; | ||
107 | }; | ||
108 | |||
109 | struct clk_lookup * __init_refok | ||
110 | clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) | ||
111 | { | ||
112 | struct clk_lookup_alloc *cla; | ||
113 | |||
114 | if (!slab_is_available()) | ||
115 | cla = alloc_bootmem_low_pages(sizeof(*cla)); | ||
116 | else | ||
117 | cla = kzalloc(sizeof(*cla), GFP_KERNEL); | ||
118 | |||
119 | if (!cla) | ||
120 | return NULL; | ||
121 | |||
122 | cla->cl.clk = clk; | ||
123 | if (con_id) { | ||
124 | strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); | ||
125 | cla->cl.con_id = cla->con_id; | ||
126 | } | ||
127 | |||
128 | if (dev_fmt) { | ||
129 | va_list ap; | ||
130 | |||
131 | va_start(ap, dev_fmt); | ||
132 | vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); | ||
133 | cla->cl.dev_id = cla->dev_id; | ||
134 | va_end(ap); | ||
135 | } | ||
136 | |||
137 | return &cla->cl; | ||
138 | } | ||
139 | EXPORT_SYMBOL(clkdev_alloc); | ||
140 | |||
141 | int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, | ||
142 | struct device *dev) | ||
143 | { | ||
144 | struct clk *r = clk_get(dev, id); | ||
145 | struct clk_lookup *l; | ||
146 | |||
147 | if (IS_ERR(r)) | ||
148 | return PTR_ERR(r); | ||
149 | |||
150 | l = clkdev_alloc(r, alias, alias_dev_name); | ||
151 | clk_put(r); | ||
152 | if (!l) | ||
153 | return -ENODEV; | ||
154 | clkdev_add(l); | ||
155 | return 0; | ||
156 | } | ||
157 | EXPORT_SYMBOL(clk_add_alias); | ||
158 | |||
159 | /* | ||
160 | * clkdev_drop - remove a clock dynamically allocated | ||
161 | */ | ||
162 | void clkdev_drop(struct clk_lookup *cl) | ||
163 | { | ||
164 | struct clk_lookup_alloc *cla = container_of(cl, struct clk_lookup_alloc, cl); | ||
165 | |||
166 | mutex_lock(&clocks_mutex); | ||
167 | list_del(&cl->node); | ||
168 | mutex_unlock(&clocks_mutex); | ||
169 | kfree(cla); | ||
170 | } | ||
171 | EXPORT_SYMBOL(clkdev_drop); | ||
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index e2f63d68da5..dd0e0f21135 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c | |||
@@ -2,7 +2,7 @@ | |||
2 | #include <linux/compiler.h> | 2 | #include <linux/compiler.h> |
3 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
4 | #include <linux/io.h> | 4 | #include <linux/io.h> |
5 | #include <asm/clkdev.h> | 5 | #include <linux/clkdev.h> |
6 | #include <asm/clock.h> | 6 | #include <asm/clock.h> |
7 | 7 | ||
8 | static struct clk master_clk = { | 8 | static struct clk master_clk = { |
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 50f887dda56..4187cf4fe18 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c | |||
@@ -48,20 +48,4 @@ int __init clk_init(void) | |||
48 | return ret; | 48 | return ret; |
49 | } | 49 | } |
50 | 50 | ||
51 | /* | ||
52 | * Returns a clock. Note that we first try to use device id on the bus | ||
53 | * and clock name. If this fails, we try to use clock name only. | ||
54 | */ | ||
55 | struct clk *clk_get(struct device *dev, const char *con_id) | ||
56 | { | ||
57 | const char *dev_id = dev ? dev_name(dev) : NULL; | ||
58 | |||
59 | return clk_get_sys(dev_id, con_id); | ||
60 | } | ||
61 | EXPORT_SYMBOL_GPL(clk_get); | ||
62 | |||
63 | void clk_put(struct clk *clk) | ||
64 | { | ||
65 | } | ||
66 | EXPORT_SYMBOL_GPL(clk_put); | ||
67 | 51 | ||
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c index b26264dc2ae..c509c40cba4 100644 --- a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c | |||
@@ -34,7 +34,7 @@ static const int pfc_divisors[]={1,2,3,4,6,8,12}; | |||
34 | 34 | ||
35 | static void master_clk_init(struct clk *clk) | 35 | static void master_clk_init(struct clk *clk) |
36 | { | 36 | { |
37 | return 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007]; | 37 | clk->rate = 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007]; |
38 | } | 38 | } |
39 | 39 | ||
40 | static struct clk_ops sh7201_master_clk_ops = { | 40 | static struct clk_ops sh7201_master_clk_ops = { |
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c index b601fa3978d..3f6f8e98635 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <asm/clkdev.h> | 16 | #include <linux/clkdev.h> |
17 | #include <asm/clock.h> | 17 | #include <asm/clock.h> |
18 | #include <asm/freq.h> | 18 | #include <asm/freq.h> |
19 | 19 | ||
@@ -81,8 +81,7 @@ static void shoc_clk_init(struct clk *clk) | |||
81 | for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) { | 81 | for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) { |
82 | int divisor = frqcr3_divisors[i]; | 82 | int divisor = frqcr3_divisors[i]; |
83 | 83 | ||
84 | if (clk->ops->set_rate(clk, clk->parent->rate / | 84 | if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0) |
85 | divisor, 0) == 0) | ||
86 | break; | 85 | break; |
87 | } | 86 | } |
88 | 87 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 71291ae201b..93c646072c1 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <asm/clkdev.h> | 24 | #include <linux/clkdev.h> |
25 | #include <asm/clock.h> | 25 | #include <asm/clock.h> |
26 | 26 | ||
27 | /* SH7343 registers */ | 27 | /* SH7343 registers */ |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 7ce5bbcd408..049dc0628cc 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <asm/clkdev.h> | 24 | #include <linux/clkdev.h> |
25 | #include <asm/clock.h> | 25 | #include <asm/clock.h> |
26 | 26 | ||
27 | /* SH7366 registers */ | 27 | /* SH7366 registers */ |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 2030f3d9fac..9d23a36f064 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <asm/clkdev.h> | 24 | #include <linux/clkdev.h> |
25 | #include <asm/clock.h> | 25 | #include <asm/clock.h> |
26 | #include <asm/hwblk.h> | 26 | #include <asm/hwblk.h> |
27 | #include <cpu/sh7722.h> | 27 | #include <cpu/sh7722.h> |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index d3938f0d370..55493cd5bd8 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
25 | #include <asm/clkdev.h> | 25 | #include <linux/clkdev.h> |
26 | #include <asm/clock.h> | 26 | #include <asm/clock.h> |
27 | #include <asm/hwblk.h> | 27 | #include <asm/hwblk.h> |
28 | #include <cpu/sh7723.h> | 28 | #include <cpu/sh7723.h> |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 271c0b325a9..d08fa953c88 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
25 | #include <asm/clkdev.h> | 25 | #include <linux/clkdev.h> |
26 | #include <asm/clock.h> | 26 | #include <asm/clock.h> |
27 | #include <asm/hwblk.h> | 27 | #include <asm/hwblk.h> |
28 | #include <cpu/sh7724.h> | 28 | #include <cpu/sh7724.h> |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index ce39a2ae8c6..e073e3eb4c3 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <asm/clkdev.h> | 15 | #include <linux/clkdev.h> |
16 | #include <asm/clock.h> | 16 | #include <asm/clock.h> |
17 | #include <asm/freq.h> | 17 | #include <asm/freq.h> |
18 | 18 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c index 1f1df48008c..599630fc4d3 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <asm/clkdev.h> | 16 | #include <linux/clkdev.h> |
17 | #include <asm/clock.h> | 17 | #include <asm/clock.h> |
18 | #include <asm/freq.h> | 18 | #include <asm/freq.h> |
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c index 62d70635006..8894926479a 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <asm/clkdev.h> | 15 | #include <linux/clkdev.h> |
16 | #include <asm/clock.h> | 16 | #include <asm/clock.h> |
17 | #include <asm/freq.h> | 17 | #include <asm/freq.h> |
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index c3e458aaa2b..2d960247f3e 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/cpufreq.h> | 16 | #include <linux/cpufreq.h> |
17 | #include <asm/clkdev.h> | 17 | #include <linux/clkdev.h> |
18 | #include <asm/clock.h> | 18 | #include <asm/clock.h> |
19 | #include <asm/freq.h> | 19 | #include <asm/freq.h> |
20 | #include <cpu/sh7785.h> | 20 | #include <cpu/sh7785.h> |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index 597c9fbe49c..42e403be907 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <asm/clkdev.h> | 16 | #include <linux/clkdev.h> |
17 | #include <asm/clock.h> | 17 | #include <asm/clock.h> |
18 | #include <asm/freq.h> | 18 | #include <asm/freq.h> |
19 | 19 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c index 4f70df6b616..1afdb93b8cc 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <asm/clkdev.h> | 17 | #include <linux/clkdev.h> |
18 | #include <asm/clock.h> | 18 | #include <asm/clock.h> |
19 | #include <asm/freq.h> | 19 | #include <asm/freq.h> |
20 | 20 | ||
diff --git a/arch/tile/include/asm/signal.h b/arch/tile/include/asm/signal.h index c1ee1d61d44..81d92a45cd4 100644 --- a/arch/tile/include/asm/signal.h +++ b/arch/tile/include/asm/signal.h | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) | 26 | #if defined(__KERNEL__) && !defined(__ASSEMBLY__) |
27 | struct pt_regs; | 27 | struct pt_regs; |
28 | int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *); | 28 | int restore_sigcontext(struct pt_regs *, struct sigcontext __user *); |
29 | int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); | 29 | int setup_sigcontext(struct sigcontext __user *, struct pt_regs *); |
30 | void do_signal(struct pt_regs *regs); | 30 | void do_signal(struct pt_regs *regs); |
31 | #endif | 31 | #endif |
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 543d6a33aa2..dbb0dfc7bec 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c | |||
@@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | |||
290 | return ret; | 290 | return ret; |
291 | } | 291 | } |
292 | 292 | ||
293 | /* The assembly shim for this function arranges to ignore the return value. */ | ||
293 | long compat_sys_rt_sigreturn(struct pt_regs *regs) | 294 | long compat_sys_rt_sigreturn(struct pt_regs *regs) |
294 | { | 295 | { |
295 | struct compat_rt_sigframe __user *frame = | 296 | struct compat_rt_sigframe __user *frame = |
296 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); | 297 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); |
297 | sigset_t set; | 298 | sigset_t set; |
298 | long r0; | ||
299 | 299 | ||
300 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 300 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
301 | goto badframe; | 301 | goto badframe; |
@@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs) | |||
308 | recalc_sigpending(); | 308 | recalc_sigpending(); |
309 | spin_unlock_irq(¤t->sighand->siglock); | 309 | spin_unlock_irq(¤t->sighand->siglock); |
310 | 310 | ||
311 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) | 311 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
312 | goto badframe; | 312 | goto badframe; |
313 | 313 | ||
314 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) | 314 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) |
315 | goto badframe; | 315 | goto badframe; |
316 | 316 | ||
317 | return r0; | 317 | return 0; |
318 | 318 | ||
319 | badframe: | 319 | badframe: |
320 | force_sig(SIGSEGV, current); | 320 | force_sig(SIGSEGV, current); |
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index f5821626247..5eed4a02bf6 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S | |||
@@ -1342,8 +1342,8 @@ handle_syscall: | |||
1342 | lw r20, r20 | 1342 | lw r20, r20 |
1343 | 1343 | ||
1344 | /* Jump to syscall handler. */ | 1344 | /* Jump to syscall handler. */ |
1345 | jalr r20; .Lhandle_syscall_link: | 1345 | jalr r20 |
1346 | FEEDBACK_REENTER(handle_syscall) | 1346 | .Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */ |
1347 | 1347 | ||
1348 | /* | 1348 | /* |
1349 | * Write our r0 onto the stack so it gets restored instead | 1349 | * Write our r0 onto the stack so it gets restored instead |
@@ -1352,6 +1352,9 @@ handle_syscall: | |||
1352 | PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) | 1352 | PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) |
1353 | sw r29, r0 | 1353 | sw r29, r0 |
1354 | 1354 | ||
1355 | .Lsyscall_sigreturn_skip: | ||
1356 | FEEDBACK_REENTER(handle_syscall) | ||
1357 | |||
1355 | /* Do syscall trace again, if requested. */ | 1358 | /* Do syscall trace again, if requested. */ |
1356 | lw r30, r31 | 1359 | lw r30, r31 |
1357 | andi r30, r30, _TIF_SYSCALL_TRACE | 1360 | andi r30, r30, _TIF_SYSCALL_TRACE |
@@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr) | |||
1536 | }; \ | 1539 | }; \ |
1537 | STD_ENDPROC(_##x) | 1540 | STD_ENDPROC(_##x) |
1538 | 1541 | ||
1542 | /* | ||
1543 | * Special-case sigreturn to not write r0 to the stack on return. | ||
1544 | * This is technically more efficient, but it also avoids difficulties | ||
1545 | * in the 64-bit OS when handling 32-bit compat code, since we must not | ||
1546 | * sign-extend r0 for the sigreturn return-value case. | ||
1547 | */ | ||
1548 | #define PTREGS_SYSCALL_SIGRETURN(x, reg) \ | ||
1549 | STD_ENTRY(_##x); \ | ||
1550 | addli lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ | ||
1551 | { \ | ||
1552 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
1553 | j x \ | ||
1554 | }; \ | ||
1555 | STD_ENDPROC(_##x) | ||
1556 | |||
1539 | PTREGS_SYSCALL(sys_execve, r3) | 1557 | PTREGS_SYSCALL(sys_execve, r3) |
1540 | PTREGS_SYSCALL(sys_sigaltstack, r2) | 1558 | PTREGS_SYSCALL(sys_sigaltstack, r2) |
1541 | PTREGS_SYSCALL(sys_rt_sigreturn, r0) | 1559 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) |
1542 | PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) | 1560 | PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) |
1543 | 1561 | ||
1544 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ | 1562 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ |
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 8430f45daea..e90eb53173b 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -212,6 +212,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
212 | childregs->sp = sp; /* override with new user stack pointer */ | 212 | childregs->sp = sp; /* override with new user stack pointer */ |
213 | 213 | ||
214 | /* | 214 | /* |
215 | * If CLONE_SETTLS is set, set "tp" in the new task to "r4", | ||
216 | * which is passed in as arg #5 to sys_clone(). | ||
217 | */ | ||
218 | if (clone_flags & CLONE_SETTLS) | ||
219 | childregs->tp = regs->regs[4]; | ||
220 | |||
221 | /* | ||
215 | * Copy the callee-saved registers from the passed pt_regs struct | 222 | * Copy the callee-saved registers from the passed pt_regs struct |
216 | * into the context-switch callee-saved registers area. | 223 | * into the context-switch callee-saved registers area. |
217 | * This way when we start the interrupt-return sequence, the | 224 | * This way when we start the interrupt-return sequence, the |
@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev, | |||
539 | return __switch_to(prev, next, next_current_ksp0(next)); | 546 | return __switch_to(prev, next, next_current_ksp0(next)); |
540 | } | 547 | } |
541 | 548 | ||
549 | /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ | ||
542 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, | 550 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, |
543 | void __user *, parent_tidptr, void __user *, child_tidptr, | 551 | void __user *, parent_tidptr, void __user *, child_tidptr, |
544 | struct pt_regs *, regs) | 552 | struct pt_regs *, regs) |
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 757407e3669..1260321155f 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c | |||
@@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, | |||
52 | */ | 52 | */ |
53 | 53 | ||
54 | int restore_sigcontext(struct pt_regs *regs, | 54 | int restore_sigcontext(struct pt_regs *regs, |
55 | struct sigcontext __user *sc, long *pr0) | 55 | struct sigcontext __user *sc) |
56 | { | 56 | { |
57 | int err = 0; | 57 | int err = 0; |
58 | int i; | 58 | int i; |
@@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs, | |||
75 | 75 | ||
76 | regs->faultnum = INT_SWINT_1_SIGRETURN; | 76 | regs->faultnum = INT_SWINT_1_SIGRETURN; |
77 | 77 | ||
78 | err |= __get_user(*pr0, &sc->gregs[0]); | ||
79 | return err; | 78 | return err; |
80 | } | 79 | } |
81 | 80 | ||
82 | /* sigreturn() returns long since it restores r0 in the interrupted code. */ | 81 | /* The assembly shim for this function arranges to ignore the return value. */ |
83 | SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) | 82 | SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) |
84 | { | 83 | { |
85 | struct rt_sigframe __user *frame = | 84 | struct rt_sigframe __user *frame = |
86 | (struct rt_sigframe __user *)(regs->sp); | 85 | (struct rt_sigframe __user *)(regs->sp); |
87 | sigset_t set; | 86 | sigset_t set; |
88 | long r0; | ||
89 | 87 | ||
90 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 88 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
91 | goto badframe; | 89 | goto badframe; |
@@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) | |||
98 | recalc_sigpending(); | 96 | recalc_sigpending(); |
99 | spin_unlock_irq(¤t->sighand->siglock); | 97 | spin_unlock_irq(¤t->sighand->siglock); |
100 | 98 | ||
101 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) | 99 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
102 | goto badframe; | 100 | goto badframe; |
103 | 101 | ||
104 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) | 102 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) |
105 | goto badframe; | 103 | goto badframe; |
106 | 104 | ||
107 | return r0; | 105 | return 0; |
108 | 106 | ||
109 | badframe: | 107 | badframe: |
110 | force_sig(SIGSEGV, current); | 108 | force_sig(SIGSEGV, current); |
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 23f315c9f21..325c05294fc 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
@@ -355,7 +355,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, | |||
355 | if (heap > 0x3fffffffffffUL) | 355 | if (heap > 0x3fffffffffffUL) |
356 | error("Destination address too large"); | 356 | error("Destination address too large"); |
357 | #else | 357 | #else |
358 | if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) | 358 | if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff)) |
359 | error("Destination address too large"); | 359 | error("Destination address too large"); |
360 | #endif | 360 | #endif |
361 | #ifndef CONFIG_RELOCATABLE | 361 | #ifndef CONFIG_RELOCATABLE |
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 5be1542fbfa..e99d55d74df 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h | |||
@@ -72,6 +72,9 @@ struct e820map { | |||
72 | #define BIOS_BEGIN 0x000a0000 | 72 | #define BIOS_BEGIN 0x000a0000 |
73 | #define BIOS_END 0x00100000 | 73 | #define BIOS_END 0x00100000 |
74 | 74 | ||
75 | #define BIOS_ROM_BASE 0xffe00000 | ||
76 | #define BIOS_ROM_END 0xffffffff | ||
77 | |||
75 | #ifdef __KERNEL__ | 78 | #ifdef __KERNEL__ |
76 | /* see comment in arch/x86/kernel/e820.c */ | 79 | /* see comment in arch/x86/kernel/e820.c */ |
77 | extern struct e820map e820; | 80 | extern struct e820map e820; |
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 9e6fe391094..f702f82aa1e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -79,7 +79,7 @@ | |||
79 | #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT) | 79 | #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT) |
80 | #define KVM_MIN_FREE_MMU_PAGES 5 | 80 | #define KVM_MIN_FREE_MMU_PAGES 5 |
81 | #define KVM_REFILL_PAGES 25 | 81 | #define KVM_REFILL_PAGES 25 |
82 | #define KVM_MAX_CPUID_ENTRIES 40 | 82 | #define KVM_MAX_CPUID_ENTRIES 80 |
83 | #define KVM_NR_FIXED_MTRR_REGION 88 | 83 | #define KVM_NR_FIXED_MTRR_REGION 88 |
84 | #define KVM_NR_VAR_MTRR 8 | 84 | #define KVM_NR_VAR_MTRR 8 |
85 | 85 | ||
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 9e13763b609..1e994754d32 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -45,6 +45,7 @@ obj-y += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o | |||
45 | obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o | 45 | obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o |
46 | obj-y += tsc.o io_delay.o rtc.o | 46 | obj-y += tsc.o io_delay.o rtc.o |
47 | obj-y += pci-iommu_table.o | 47 | obj-y += pci-iommu_table.o |
48 | obj-y += resource.o | ||
48 | 49 | ||
49 | obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o | 50 | obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o |
50 | obj-y += process.o | 51 | obj-y += process.o |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3f838d53739..78218135b48 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -1389,6 +1389,14 @@ void __cpuinit end_local_APIC_setup(void) | |||
1389 | 1389 | ||
1390 | setup_apic_nmi_watchdog(NULL); | 1390 | setup_apic_nmi_watchdog(NULL); |
1391 | apic_pm_activate(); | 1391 | apic_pm_activate(); |
1392 | |||
1393 | /* | ||
1394 | * Now that local APIC setup is completed for BP, configure the fault | ||
1395 | * handling for interrupt remapping. | ||
1396 | */ | ||
1397 | if (!smp_processor_id() && intr_remapping_enabled) | ||
1398 | enable_drhd_fault_handling(); | ||
1399 | |||
1392 | } | 1400 | } |
1393 | 1401 | ||
1394 | #ifdef CONFIG_X86_X2APIC | 1402 | #ifdef CONFIG_X86_X2APIC |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 7cc0a721f62..fadcd743a74 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -2430,13 +2430,12 @@ static void ack_apic_level(struct irq_data *data) | |||
2430 | { | 2430 | { |
2431 | struct irq_cfg *cfg = data->chip_data; | 2431 | struct irq_cfg *cfg = data->chip_data; |
2432 | int i, do_unmask_irq = 0, irq = data->irq; | 2432 | int i, do_unmask_irq = 0, irq = data->irq; |
2433 | struct irq_desc *desc = irq_to_desc(irq); | ||
2434 | unsigned long v; | 2433 | unsigned long v; |
2435 | 2434 | ||
2436 | irq_complete_move(cfg); | 2435 | irq_complete_move(cfg); |
2437 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 2436 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
2438 | /* If we are moving the irq we need to mask it */ | 2437 | /* If we are moving the irq we need to mask it */ |
2439 | if (unlikely(desc->status & IRQ_MOVE_PENDING)) { | 2438 | if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) { |
2440 | do_unmask_irq = 1; | 2439 | do_unmask_irq = 1; |
2441 | mask_ioapic(cfg); | 2440 | mask_ioapic(cfg); |
2442 | } | 2441 | } |
@@ -3413,6 +3412,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask, | |||
3413 | msg.data |= MSI_DATA_VECTOR(cfg->vector); | 3412 | msg.data |= MSI_DATA_VECTOR(cfg->vector); |
3414 | msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; | 3413 | msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; |
3415 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); | 3414 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); |
3415 | msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest); | ||
3416 | 3416 | ||
3417 | dmar_msi_write(irq, &msg); | 3417 | dmar_msi_write(irq, &msg); |
3418 | 3418 | ||
diff --git a/arch/x86/kernel/apic/probe_64.c b/arch/x86/kernel/apic/probe_64.c index f9e4e6a5407..d8c4a6feb28 100644 --- a/arch/x86/kernel/apic/probe_64.c +++ b/arch/x86/kernel/apic/probe_64.c | |||
@@ -79,13 +79,6 @@ void __init default_setup_apic_routing(void) | |||
79 | /* need to update phys_pkg_id */ | 79 | /* need to update phys_pkg_id */ |
80 | apic->phys_pkg_id = apicid_phys_pkg_id; | 80 | apic->phys_pkg_id = apicid_phys_pkg_id; |
81 | } | 81 | } |
82 | |||
83 | /* | ||
84 | * Now that apic routing model is selected, configure the | ||
85 | * fault handling for intr remapping. | ||
86 | */ | ||
87 | if (intr_remapping_enabled) | ||
88 | enable_drhd_fault_handling(); | ||
89 | } | 82 | } |
90 | 83 | ||
91 | /* Same for both flat and physical. */ | 84 | /* Same for both flat and physical. */ |
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index bcece91dd31..c0dbd9ac24f 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -60,16 +60,18 @@ | |||
60 | #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) | 60 | #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) |
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | /* Number of possible pages in the lowmem region */ | ||
64 | LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) | ||
65 | |||
63 | /* Enough space to fit pagetables for the low memory linear map */ | 66 | /* Enough space to fit pagetables for the low memory linear map */ |
64 | MAPPING_BEYOND_END = \ | 67 | MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT |
65 | PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT | ||
66 | 68 | ||
67 | /* | 69 | /* |
68 | * Worst-case size of the kernel mapping we need to make: | 70 | * Worst-case size of the kernel mapping we need to make: |
69 | * the worst-case size of the kernel itself, plus the extra we need | 71 | * a relocatable kernel can live anywhere in lowmem, so we need to be able |
70 | * to map for the linear map. | 72 | * to map all of lowmem. |
71 | */ | 73 | */ |
72 | KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT | 74 | KERNEL_PAGES = LOWMEM_PAGES |
73 | 75 | ||
74 | INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm | 76 | INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm |
75 | RESERVE_BRK(pagetables, INIT_MAP_SIZE) | 77 | RESERVE_BRK(pagetables, INIT_MAP_SIZE) |
@@ -620,13 +622,13 @@ ENTRY(initial_code) | |||
620 | __PAGE_ALIGNED_BSS | 622 | __PAGE_ALIGNED_BSS |
621 | .align PAGE_SIZE_asm | 623 | .align PAGE_SIZE_asm |
622 | #ifdef CONFIG_X86_PAE | 624 | #ifdef CONFIG_X86_PAE |
623 | initial_pg_pmd: | 625 | ENTRY(initial_pg_pmd) |
624 | .fill 1024*KPMDS,4,0 | 626 | .fill 1024*KPMDS,4,0 |
625 | #else | 627 | #else |
626 | ENTRY(initial_page_table) | 628 | ENTRY(initial_page_table) |
627 | .fill 1024,4,0 | 629 | .fill 1024,4,0 |
628 | #endif | 630 | #endif |
629 | initial_pg_fixmap: | 631 | ENTRY(initial_pg_fixmap) |
630 | .fill 1024,4,0 | 632 | .fill 1024,4,0 |
631 | ENTRY(empty_zero_page) | 633 | ENTRY(empty_zero_page) |
632 | .fill 4096,1,0 | 634 | .fill 4096,1,0 |
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ae03cab4352..4ff5968f12d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #define HPET_DEV_FSB_CAP 0x1000 | 27 | #define HPET_DEV_FSB_CAP 0x1000 |
28 | #define HPET_DEV_PERI_CAP 0x2000 | 28 | #define HPET_DEV_PERI_CAP 0x2000 |
29 | 29 | ||
30 | #define HPET_MIN_CYCLES 128 | ||
31 | #define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1)) | ||
32 | |||
30 | #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt) | 33 | #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt) |
31 | 34 | ||
32 | /* | 35 | /* |
@@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void) | |||
299 | /* Calculate the min / max delta */ | 302 | /* Calculate the min / max delta */ |
300 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, | 303 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, |
301 | &hpet_clockevent); | 304 | &hpet_clockevent); |
302 | /* 5 usec minimum reprogramming delta. */ | 305 | /* Setup minimum reprogramming delta. */ |
303 | hpet_clockevent.min_delta_ns = 5000; | 306 | hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, |
307 | &hpet_clockevent); | ||
304 | 308 | ||
305 | /* | 309 | /* |
306 | * Start hpet with the boot cpu mask and make it | 310 | * Start hpet with the boot cpu mask and make it |
@@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta, | |||
393 | * the wraparound into account) nor a simple count down event | 397 | * the wraparound into account) nor a simple count down event |
394 | * mode. Further the write to the comparator register is | 398 | * mode. Further the write to the comparator register is |
395 | * delayed internally up to two HPET clock cycles in certain | 399 | * delayed internally up to two HPET clock cycles in certain |
396 | * chipsets (ATI, ICH9,10). We worked around that by reading | 400 | * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even |
397 | * back the compare register, but that required another | 401 | * longer delays. We worked around that by reading back the |
398 | * workaround for ICH9,10 chips where the first readout after | 402 | * compare register, but that required another workaround for |
399 | * write can return the old stale value. We already have a | 403 | * ICH9,10 chips where the first readout after write can |
400 | * minimum delta of 5us enforced, but a NMI or SMI hitting | 404 | * return the old stale value. We already had a minimum |
405 | * programming delta of 5us enforced, but a NMI or SMI hitting | ||
401 | * between the counter readout and the comparator write can | 406 | * between the counter readout and the comparator write can |
402 | * move us behind that point easily. Now instead of reading | 407 | * move us behind that point easily. Now instead of reading |
403 | * the compare register back several times, we make the ETIME | 408 | * the compare register back several times, we make the ETIME |
404 | * decision based on the following: Return ETIME if the | 409 | * decision based on the following: Return ETIME if the |
405 | * counter value after the write is less than 8 HPET cycles | 410 | * counter value after the write is less than HPET_MIN_CYCLES |
406 | * away from the event or if the counter is already ahead of | 411 | * away from the event or if the counter is already ahead of |
407 | * the event. | 412 | * the event. The minimum programming delta for the generic |
413 | * clockevents code is set to 1.5 * HPET_MIN_CYCLES. | ||
408 | */ | 414 | */ |
409 | res = (s32)(cnt - hpet_readl(HPET_COUNTER)); | 415 | res = (s32)(cnt - hpet_readl(HPET_COUNTER)); |
410 | 416 | ||
411 | return res < 8 ? -ETIME : 0; | 417 | return res < HPET_MIN_CYCLES ? -ETIME : 0; |
412 | } | 418 | } |
413 | 419 | ||
414 | static void hpet_legacy_set_mode(enum clock_event_mode mode, | 420 | static void hpet_legacy_set_mode(enum clock_event_mode mode, |
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index dcb65cc0a05..1a1b606d3e9 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
@@ -364,8 +364,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | |||
364 | 364 | ||
365 | /* For performance reasons, reuse mc area when possible */ | 365 | /* For performance reasons, reuse mc area when possible */ |
366 | if (!mc || mc_size > curr_mc_size) { | 366 | if (!mc || mc_size > curr_mc_size) { |
367 | if (mc) | 367 | vfree(mc); |
368 | vfree(mc); | ||
369 | mc = vmalloc(mc_size); | 368 | mc = vmalloc(mc_size); |
370 | if (!mc) | 369 | if (!mc) |
371 | break; | 370 | break; |
@@ -374,13 +373,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | |||
374 | 373 | ||
375 | if (get_ucode_data(mc, ucode_ptr, mc_size) || | 374 | if (get_ucode_data(mc, ucode_ptr, mc_size) || |
376 | microcode_sanity_check(mc) < 0) { | 375 | microcode_sanity_check(mc) < 0) { |
377 | vfree(mc); | ||
378 | break; | 376 | break; |
379 | } | 377 | } |
380 | 378 | ||
381 | if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) { | 379 | if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) { |
382 | if (new_mc) | 380 | vfree(new_mc); |
383 | vfree(new_mc); | ||
384 | new_rev = mc_header.rev; | 381 | new_rev = mc_header.rev; |
385 | new_mc = mc; | 382 | new_mc = mc; |
386 | mc = NULL; /* trigger new vmalloc */ | 383 | mc = NULL; /* trigger new vmalloc */ |
@@ -390,12 +387,10 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | |||
390 | leftover -= mc_size; | 387 | leftover -= mc_size; |
391 | } | 388 | } |
392 | 389 | ||
393 | if (mc) | 390 | vfree(mc); |
394 | vfree(mc); | ||
395 | 391 | ||
396 | if (leftover) { | 392 | if (leftover) { |
397 | if (new_mc) | 393 | vfree(new_mc); |
398 | vfree(new_mc); | ||
399 | state = UCODE_ERROR; | 394 | state = UCODE_ERROR; |
400 | goto out; | 395 | goto out; |
401 | } | 396 | } |
@@ -405,8 +400,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, | |||
405 | goto out; | 400 | goto out; |
406 | } | 401 | } |
407 | 402 | ||
408 | if (uci->mc) | 403 | vfree(uci->mc); |
409 | vfree(uci->mc); | ||
410 | uci->mc = (struct microcode_intel *)new_mc; | 404 | uci->mc = (struct microcode_intel *)new_mc; |
411 | 405 | ||
412 | pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", | 406 | pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", |
diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c new file mode 100644 index 00000000000..2a26819bb6a --- /dev/null +++ b/arch/x86/kernel/resource.c | |||
@@ -0,0 +1,48 @@ | |||
1 | #include <linux/ioport.h> | ||
2 | #include <asm/e820.h> | ||
3 | |||
4 | static void resource_clip(struct resource *res, resource_size_t start, | ||
5 | resource_size_t end) | ||
6 | { | ||
7 | resource_size_t low = 0, high = 0; | ||
8 | |||
9 | if (res->end < start || res->start > end) | ||
10 | return; /* no conflict */ | ||
11 | |||
12 | if (res->start < start) | ||
13 | low = start - res->start; | ||
14 | |||
15 | if (res->end > end) | ||
16 | high = res->end - end; | ||
17 | |||
18 | /* Keep the area above or below the conflict, whichever is larger */ | ||
19 | if (low > high) | ||
20 | res->end = start - 1; | ||
21 | else | ||
22 | res->start = end + 1; | ||
23 | } | ||
24 | |||
25 | static void remove_e820_regions(struct resource *avail) | ||
26 | { | ||
27 | int i; | ||
28 | struct e820entry *entry; | ||
29 | |||
30 | for (i = 0; i < e820.nr_map; i++) { | ||
31 | entry = &e820.map[i]; | ||
32 | |||
33 | resource_clip(avail, entry->addr, | ||
34 | entry->addr + entry->size - 1); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | void arch_remove_reservations(struct resource *avail) | ||
39 | { | ||
40 | /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */ | ||
41 | if (avail->flags & IORESOURCE_MEM) { | ||
42 | if (avail->start < BIOS_END) | ||
43 | avail->start = BIOS_END; | ||
44 | resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END); | ||
45 | |||
46 | remove_e820_regions(avail); | ||
47 | } | ||
48 | } | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 21c6746338a..a0f52af256a 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -501,7 +501,18 @@ static inline unsigned long long get_total_mem(void) | |||
501 | return total << PAGE_SHIFT; | 501 | return total << PAGE_SHIFT; |
502 | } | 502 | } |
503 | 503 | ||
504 | #define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF | 504 | /* |
505 | * Keep the crash kernel below this limit. On 32 bits earlier kernels | ||
506 | * would limit the kernel to the low 512 MiB due to mapping restrictions. | ||
507 | * On 64 bits, kexec-tools currently limits us to 896 MiB; increase this | ||
508 | * limit once kexec-tools are fixed. | ||
509 | */ | ||
510 | #ifdef CONFIG_X86_32 | ||
511 | # define CRASH_KERNEL_ADDR_MAX (512 << 20) | ||
512 | #else | ||
513 | # define CRASH_KERNEL_ADDR_MAX (896 << 20) | ||
514 | #endif | ||
515 | |||
505 | static void __init reserve_crashkernel(void) | 516 | static void __init reserve_crashkernel(void) |
506 | { | 517 | { |
507 | unsigned long long total_mem; | 518 | unsigned long long total_mem; |
@@ -520,10 +531,10 @@ static void __init reserve_crashkernel(void) | |||
520 | const unsigned long long alignment = 16<<20; /* 16M */ | 531 | const unsigned long long alignment = 16<<20; /* 16M */ |
521 | 532 | ||
522 | /* | 533 | /* |
523 | * kexec want bzImage is below DEFAULT_BZIMAGE_ADDR_MAX | 534 | * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX |
524 | */ | 535 | */ |
525 | crash_base = memblock_find_in_range(alignment, | 536 | crash_base = memblock_find_in_range(alignment, |
526 | DEFAULT_BZIMAGE_ADDR_MAX, crash_size, alignment); | 537 | CRASH_KERNEL_ADDR_MAX, crash_size, alignment); |
527 | 538 | ||
528 | if (crash_base == MEMBLOCK_ERROR) { | 539 | if (crash_base == MEMBLOCK_ERROR) { |
529 | pr_info("crashkernel reservation failed - No suitable area found.\n"); | 540 | pr_info("crashkernel reservation failed - No suitable area found.\n"); |
@@ -769,7 +780,6 @@ void __init setup_arch(char **cmdline_p) | |||
769 | 780 | ||
770 | x86_init.oem.arch_setup(); | 781 | x86_init.oem.arch_setup(); |
771 | 782 | ||
772 | resource_alloc_from_bottom = 0; | ||
773 | iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1; | 783 | iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1; |
774 | setup_memory_map(); | 784 | setup_memory_map(); |
775 | parse_setup_data(); | 785 | parse_setup_data(); |
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 9c253bd65e2..547128546cc 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
@@ -394,7 +394,8 @@ static void __init setup_xstate_init(void) | |||
394 | * Setup init_xstate_buf to represent the init state of | 394 | * Setup init_xstate_buf to represent the init state of |
395 | * all the features managed by the xsave | 395 | * all the features managed by the xsave |
396 | */ | 396 | */ |
397 | init_xstate_buf = alloc_bootmem(xstate_size); | 397 | init_xstate_buf = alloc_bootmem_align(xstate_size, |
398 | __alignof__(struct xsave_struct)); | ||
398 | init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; | 399 | init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; |
399 | 400 | ||
400 | clts(); | 401 | clts(); |
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index f628234fbec..3cece05e4ac 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c | |||
@@ -575,6 +575,8 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm) | |||
575 | s->pics[1].elcr_mask = 0xde; | 575 | s->pics[1].elcr_mask = 0xde; |
576 | s->pics[0].pics_state = s; | 576 | s->pics[0].pics_state = s; |
577 | s->pics[1].pics_state = s; | 577 | s->pics[1].pics_state = s; |
578 | s->pics[0].isr_ack = 0xff; | ||
579 | s->pics[1].isr_ack = 0xff; | ||
578 | 580 | ||
579 | /* | 581 | /* |
580 | * Initialize PIO device | 582 | * Initialize PIO device |
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index fb8b376bf28..fbb04aee830 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -2394,7 +2394,8 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) | |||
2394 | ASSERT(!VALID_PAGE(root)); | 2394 | ASSERT(!VALID_PAGE(root)); |
2395 | spin_lock(&vcpu->kvm->mmu_lock); | 2395 | spin_lock(&vcpu->kvm->mmu_lock); |
2396 | kvm_mmu_free_some_pages(vcpu); | 2396 | kvm_mmu_free_some_pages(vcpu); |
2397 | sp = kvm_mmu_get_page(vcpu, i << 30, i << 30, | 2397 | sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT), |
2398 | i << 30, | ||
2398 | PT32_ROOT_LEVEL, 1, ACC_ALL, | 2399 | PT32_ROOT_LEVEL, 1, ACC_ALL, |
2399 | NULL); | 2400 | NULL); |
2400 | root = __pa(sp->spt); | 2401 | root = __pa(sp->spt); |
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 1ca12298ffc..b81a9b7c2ca 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -3494,6 +3494,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu) | |||
3494 | static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) | 3494 | static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry) |
3495 | { | 3495 | { |
3496 | switch (func) { | 3496 | switch (func) { |
3497 | case 0x00000001: | ||
3498 | /* Mask out xsave bit as long as it is not supported by SVM */ | ||
3499 | entry->ecx &= ~(bit(X86_FEATURE_XSAVE)); | ||
3500 | break; | ||
3497 | case 0x80000001: | 3501 | case 0x80000001: |
3498 | if (nested) | 3502 | if (nested) |
3499 | entry->ecx |= (1 << 2); /* Set SVM bit */ | 3503 | entry->ecx |= (1 << 2); /* Set SVM bit */ |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ff21fdda0c5..81fcbe9515c 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -4227,11 +4227,6 @@ static int vmx_get_lpage_level(void) | |||
4227 | return PT_PDPE_LEVEL; | 4227 | return PT_PDPE_LEVEL; |
4228 | } | 4228 | } |
4229 | 4229 | ||
4230 | static inline u32 bit(int bitno) | ||
4231 | { | ||
4232 | return 1 << (bitno & 31); | ||
4233 | } | ||
4234 | |||
4235 | static void vmx_cpuid_update(struct kvm_vcpu *vcpu) | 4230 | static void vmx_cpuid_update(struct kvm_vcpu *vcpu) |
4236 | { | 4231 | { |
4237 | struct kvm_cpuid_entry2 *best; | 4232 | struct kvm_cpuid_entry2 *best; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index cdac9e592aa..b989e1f1e5d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -155,11 +155,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
155 | 155 | ||
156 | u64 __read_mostly host_xcr0; | 156 | u64 __read_mostly host_xcr0; |
157 | 157 | ||
158 | static inline u32 bit(int bitno) | ||
159 | { | ||
160 | return 1 << (bitno & 31); | ||
161 | } | ||
162 | |||
163 | static void kvm_on_user_return(struct user_return_notifier *urn) | 158 | static void kvm_on_user_return(struct user_return_notifier *urn) |
164 | { | 159 | { |
165 | unsigned slot; | 160 | unsigned slot; |
@@ -4569,9 +4564,11 @@ static void kvm_timer_init(void) | |||
4569 | #ifdef CONFIG_CPU_FREQ | 4564 | #ifdef CONFIG_CPU_FREQ |
4570 | struct cpufreq_policy policy; | 4565 | struct cpufreq_policy policy; |
4571 | memset(&policy, 0, sizeof(policy)); | 4566 | memset(&policy, 0, sizeof(policy)); |
4572 | cpufreq_get_policy(&policy, get_cpu()); | 4567 | cpu = get_cpu(); |
4568 | cpufreq_get_policy(&policy, cpu); | ||
4573 | if (policy.cpuinfo.max_freq) | 4569 | if (policy.cpuinfo.max_freq) |
4574 | max_tsc_khz = policy.cpuinfo.max_freq; | 4570 | max_tsc_khz = policy.cpuinfo.max_freq; |
4571 | put_cpu(); | ||
4575 | #endif | 4572 | #endif |
4576 | cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block, | 4573 | cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block, |
4577 | CPUFREQ_TRANSITION_NOTIFIER); | 4574 | CPUFREQ_TRANSITION_NOTIFIER); |
@@ -5522,6 +5519,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
5522 | 5519 | ||
5523 | mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4; | 5520 | mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4; |
5524 | kvm_x86_ops->set_cr4(vcpu, sregs->cr4); | 5521 | kvm_x86_ops->set_cr4(vcpu, sregs->cr4); |
5522 | if (sregs->cr4 & X86_CR4_OSXSAVE) | ||
5523 | update_cpuid(vcpu); | ||
5525 | if (!is_long_mode(vcpu) && is_pae(vcpu)) { | 5524 | if (!is_long_mode(vcpu) && is_pae(vcpu)) { |
5526 | load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3); | 5525 | load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3); |
5527 | mmu_reset_needed = 1; | 5526 | mmu_reset_needed = 1; |
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 2cea414489f..c600da830ce 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h | |||
@@ -70,6 +70,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu) | |||
70 | return kvm_read_cr0_bits(vcpu, X86_CR0_PG); | 70 | return kvm_read_cr0_bits(vcpu, X86_CR0_PG); |
71 | } | 71 | } |
72 | 72 | ||
73 | static inline u32 bit(int bitno) | ||
74 | { | ||
75 | return 1 << (bitno & 31); | ||
76 | } | ||
77 | |||
73 | void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); | 78 | void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); |
74 | void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); | 79 | void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); |
75 | int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq); | 80 | int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq); |
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 73b1e1a1f48..4996cf5f73a 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -531,7 +531,10 @@ static void lguest_write_cr3(unsigned long cr3) | |||
531 | { | 531 | { |
532 | lguest_data.pgdir = cr3; | 532 | lguest_data.pgdir = cr3; |
533 | lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); | 533 | lazy_hcall1(LHCALL_NEW_PGTABLE, cr3); |
534 | cr3_changed = true; | 534 | |
535 | /* These two page tables are simple, linear, and used during boot */ | ||
536 | if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table)) | ||
537 | cr3_changed = true; | ||
535 | } | 538 | } |
536 | 539 | ||
537 | static unsigned long lguest_read_cr3(void) | 540 | static unsigned long lguest_read_cr3(void) |
@@ -703,9 +706,9 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval) | |||
703 | * to forget all of them. Fortunately, this is very rare. | 706 | * to forget all of them. Fortunately, this is very rare. |
704 | * | 707 | * |
705 | * ... except in early boot when the kernel sets up the initial pagetables, | 708 | * ... except in early boot when the kernel sets up the initial pagetables, |
706 | * which makes booting astonishingly slow: 1.83 seconds! So we don't even tell | 709 | * which makes booting astonishingly slow: 48 seconds! So we don't even tell |
707 | * the Host anything changed until we've done the first page table switch, | 710 | * the Host anything changed until we've done the first real page table switch, |
708 | * which brings boot back to 0.25 seconds. | 711 | * which brings boot back to 4.3 seconds. |
709 | */ | 712 | */ |
710 | static void lguest_set_pte(pte_t *ptep, pte_t pteval) | 713 | static void lguest_set_pte(pte_t *ptep, pte_t pteval) |
711 | { | 714 | { |
@@ -1002,7 +1005,7 @@ static void lguest_time_init(void) | |||
1002 | clockevents_register_device(&lguest_clockevent); | 1005 | clockevents_register_device(&lguest_clockevent); |
1003 | 1006 | ||
1004 | /* Finally, we unblock the timer interrupt. */ | 1007 | /* Finally, we unblock the timer interrupt. */ |
1005 | enable_lguest_irq(0); | 1008 | clear_bit(0, lguest_data.blocked_interrupts); |
1006 | } | 1009 | } |
1007 | 1010 | ||
1008 | /* | 1011 | /* |
@@ -1349,9 +1352,6 @@ __init void lguest_init(void) | |||
1349 | */ | 1352 | */ |
1350 | switch_to_new_gdt(0); | 1353 | switch_to_new_gdt(0); |
1351 | 1354 | ||
1352 | /* We actually boot with all memory mapped, but let's say 128MB. */ | ||
1353 | max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT; | ||
1354 | |||
1355 | /* | 1355 | /* |
1356 | * The Host<->Guest Switcher lives at the top of our address space, and | 1356 | * The Host<->Guest Switcher lives at the top of our address space, and |
1357 | * the Host told us how big it is when we made LGUEST_INIT hypercall: | 1357 | * the Host told us how big it is when we made LGUEST_INIT hypercall: |
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index 4f420c2f2d5..e7d5382ef26 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <asm/asm-offsets.h> | 4 | #include <asm/asm-offsets.h> |
5 | #include <asm/thread_info.h> | 5 | #include <asm/thread_info.h> |
6 | #include <asm/processor-flags.h> | 6 | #include <asm/processor-flags.h> |
7 | #include <asm/pgtable.h> | ||
7 | 8 | ||
8 | /*G:020 | 9 | /*G:020 |
9 | * Our story starts with the kernel booting into startup_32 in | 10 | * Our story starts with the kernel booting into startup_32 in |
@@ -37,9 +38,113 @@ ENTRY(lguest_entry) | |||
37 | /* Set up the initial stack so we can run C code. */ | 38 | /* Set up the initial stack so we can run C code. */ |
38 | movl $(init_thread_union+THREAD_SIZE),%esp | 39 | movl $(init_thread_union+THREAD_SIZE),%esp |
39 | 40 | ||
41 | call init_pagetables | ||
42 | |||
40 | /* Jumps are relative: we're running __PAGE_OFFSET too low. */ | 43 | /* Jumps are relative: we're running __PAGE_OFFSET too low. */ |
41 | jmp lguest_init+__PAGE_OFFSET | 44 | jmp lguest_init+__PAGE_OFFSET |
42 | 45 | ||
46 | /* | ||
47 | * Initialize page tables. This creates a PDE and a set of page | ||
48 | * tables, which are located immediately beyond __brk_base. The variable | ||
49 | * _brk_end is set up to point to the first "safe" location. | ||
50 | * Mappings are created both at virtual address 0 (identity mapping) | ||
51 | * and PAGE_OFFSET for up to _end. | ||
52 | * | ||
53 | * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they | ||
54 | * don't have a stack at this point, so we can't just use call and ret. | ||
55 | */ | ||
56 | init_pagetables: | ||
57 | #if PTRS_PER_PMD > 1 | ||
58 | #define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD) | ||
59 | #else | ||
60 | #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) | ||
61 | #endif | ||
62 | #define pa(X) ((X) - __PAGE_OFFSET) | ||
63 | |||
64 | /* Enough space to fit pagetables for the low memory linear map */ | ||
65 | MAPPING_BEYOND_END = \ | ||
66 | PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT | ||
67 | #ifdef CONFIG_X86_PAE | ||
68 | |||
69 | /* | ||
70 | * In PAE mode initial_page_table is statically defined to contain | ||
71 | * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 | ||
72 | * entries). The identity mapping is handled by pointing two PGD entries | ||
73 | * to the first kernel PMD. | ||
74 | * | ||
75 | * Note the upper half of each PMD or PTE are always zero at this stage. | ||
76 | */ | ||
77 | |||
78 | #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ | ||
79 | |||
80 | xorl %ebx,%ebx /* %ebx is kept at zero */ | ||
81 | |||
82 | movl $pa(__brk_base), %edi | ||
83 | movl $pa(initial_pg_pmd), %edx | ||
84 | movl $PTE_IDENT_ATTR, %eax | ||
85 | 10: | ||
86 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ | ||
87 | movl %ecx,(%edx) /* Store PMD entry */ | ||
88 | /* Upper half already zero */ | ||
89 | addl $8,%edx | ||
90 | movl $512,%ecx | ||
91 | 11: | ||
92 | stosl | ||
93 | xchgl %eax,%ebx | ||
94 | stosl | ||
95 | xchgl %eax,%ebx | ||
96 | addl $0x1000,%eax | ||
97 | loop 11b | ||
98 | |||
99 | /* | ||
100 | * End condition: we must map up to the end + MAPPING_BEYOND_END. | ||
101 | */ | ||
102 | movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp | ||
103 | cmpl %ebp,%eax | ||
104 | jb 10b | ||
105 | 1: | ||
106 | addl $__PAGE_OFFSET, %edi | ||
107 | movl %edi, pa(_brk_end) | ||
108 | shrl $12, %eax | ||
109 | movl %eax, pa(max_pfn_mapped) | ||
110 | |||
111 | /* Do early initialization of the fixmap area */ | ||
112 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax | ||
113 | movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) | ||
114 | #else /* Not PAE */ | ||
115 | |||
116 | page_pde_offset = (__PAGE_OFFSET >> 20); | ||
117 | |||
118 | movl $pa(__brk_base), %edi | ||
119 | movl $pa(initial_page_table), %edx | ||
120 | movl $PTE_IDENT_ATTR, %eax | ||
121 | 10: | ||
122 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ | ||
123 | movl %ecx,(%edx) /* Store identity PDE entry */ | ||
124 | movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ | ||
125 | addl $4,%edx | ||
126 | movl $1024, %ecx | ||
127 | 11: | ||
128 | stosl | ||
129 | addl $0x1000,%eax | ||
130 | loop 11b | ||
131 | /* | ||
132 | * End condition: we must map up to the end + MAPPING_BEYOND_END. | ||
133 | */ | ||
134 | movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp | ||
135 | cmpl %ebp,%eax | ||
136 | jb 10b | ||
137 | addl $__PAGE_OFFSET, %edi | ||
138 | movl %edi, pa(_brk_end) | ||
139 | shrl $12, %eax | ||
140 | movl %eax, pa(max_pfn_mapped) | ||
141 | |||
142 | /* Do early initialization of the fixmap area */ | ||
143 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax | ||
144 | movl %eax,pa(initial_page_table+0xffc) | ||
145 | #endif | ||
146 | ret | ||
147 | |||
43 | /*G:055 | 148 | /*G:055 |
44 | * We create a macro which puts the assembler code between lgstart_ and lgend_ | 149 | * We create a macro which puts the assembler code between lgstart_ and lgend_ |
45 | * markers. These templates are put in the .text section: they can't be | 150 | * markers. These templates are put in the .text section: they can't be |
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index a011bcc0f94..7d90d47655b 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c | |||
@@ -630,21 +630,29 @@ static int __init_ibs_nmi(void) | |||
630 | return 0; | 630 | return 0; |
631 | } | 631 | } |
632 | 632 | ||
633 | /* initialize the APIC for the IBS interrupts if available */ | 633 | /* |
634 | * check and reserve APIC extended interrupt LVT offset for IBS if | ||
635 | * available | ||
636 | * | ||
637 | * init_ibs() preforms implicitly cpu-local operations, so pin this | ||
638 | * thread to its current CPU | ||
639 | */ | ||
640 | |||
634 | static void init_ibs(void) | 641 | static void init_ibs(void) |
635 | { | 642 | { |
636 | ibs_caps = get_ibs_caps(); | 643 | preempt_disable(); |
637 | 644 | ||
645 | ibs_caps = get_ibs_caps(); | ||
638 | if (!ibs_caps) | 646 | if (!ibs_caps) |
639 | return; | 647 | goto out; |
640 | 648 | ||
641 | if (__init_ibs_nmi()) { | 649 | if (__init_ibs_nmi() < 0) |
642 | ibs_caps = 0; | 650 | ibs_caps = 0; |
643 | return; | 651 | else |
644 | } | 652 | printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps); |
645 | 653 | ||
646 | printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", | 654 | out: |
647 | (unsigned)ibs_caps); | 655 | preempt_enable(); |
648 | } | 656 | } |
649 | 657 | ||
650 | static int (*create_arch_files)(struct super_block *sb, struct dentry *root); | 658 | static int (*create_arch_files)(struct super_block *sb, struct dentry *root); |
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index c4bb261c106..b1805b78842 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c | |||
@@ -65,21 +65,13 @@ pcibios_align_resource(void *data, const struct resource *res, | |||
65 | resource_size_t size, resource_size_t align) | 65 | resource_size_t size, resource_size_t align) |
66 | { | 66 | { |
67 | struct pci_dev *dev = data; | 67 | struct pci_dev *dev = data; |
68 | resource_size_t start = round_down(res->end - size + 1, align); | 68 | resource_size_t start = res->start; |
69 | 69 | ||
70 | if (res->flags & IORESOURCE_IO) { | 70 | if (res->flags & IORESOURCE_IO) { |
71 | 71 | if (skip_isa_ioresource_align(dev)) | |
72 | /* | 72 | return start; |
73 | * If we're avoiding ISA aliases, the largest contiguous I/O | 73 | if (start & 0x300) |
74 | * port space is 256 bytes. Clearing bits 9 and 10 preserves | 74 | start = (start + 0x3ff) & ~0x3ff; |
75 | * all 256-byte and smaller alignments, so the result will | ||
76 | * still be correctly aligned. | ||
77 | */ | ||
78 | if (!skip_isa_ioresource_align(dev)) | ||
79 | start &= ~0x300; | ||
80 | } else if (res->flags & IORESOURCE_MEM) { | ||
81 | if (start < BIOS_END) | ||
82 | start = res->end; /* fail; no space */ | ||
83 | } | 75 | } |
84 | return start; | 76 | return start; |
85 | } | 77 | } |
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index 4a2afa1bac5..b6552b189bc 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile | |||
@@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y) | |||
25 | 25 | ||
26 | export CPPFLAGS_vdso.lds += -P -C | 26 | export CPPFLAGS_vdso.lds += -P -C |
27 | 27 | ||
28 | VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \ | 28 | VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ |
29 | -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 | 29 | -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 |
30 | 30 | ||
31 | $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so | 31 | $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so |
@@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y) += sysenter | |||
69 | vdso32-images = $(vdso32.so-y:%=vdso32-%.so) | 69 | vdso32-images = $(vdso32.so-y:%=vdso32-%.so) |
70 | 70 | ||
71 | CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) | 71 | CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds) |
72 | VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1 | 72 | VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1 |
73 | 73 | ||
74 | # This makes sure the $(obj) subdirectory exists even though vdso32/ | 74 | # This makes sure the $(obj) subdirectory exists even though vdso32/ |
75 | # is not a kbuild sub-make subdirectory. | 75 | # is not a kbuild sub-make subdirectory. |