Merge branches 'depends/rmk/devel-stable' and 'tegra/dt' into next/soc
Dependencies for tegra/soc branch Conflicts: arch/arm/mach-tegra/board-dt.c Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
0782e5bb57
|
@ -0,0 +1,14 @@
|
|||
NVIDIA Tegra device tree bindings
|
||||
-------------------------------------------
|
||||
|
||||
Boards with the tegra20 SoC shall have the following properties:
|
||||
|
||||
Required root node property:
|
||||
|
||||
compatible = "nvidia,tegra20";
|
||||
|
||||
Boards with the tegra30 SoC shall have the following properties:
|
||||
|
||||
Required root node property:
|
||||
|
||||
compatible = "nvidia,tegra30";
|
|
@ -0,0 +1,13 @@
|
|||
Tegra SOC USB controllers
|
||||
|
||||
The device node for a USB controller that is part of a Tegra
|
||||
SOC is as described in the document "Open Firmware Recommended
|
||||
Practice : Universal Serial Bus" with the following modifications
|
||||
and additions :
|
||||
|
||||
Required properties :
|
||||
- compatible : Should be "nvidia,tegra20-ehci" for USB controllers
|
||||
used in host mode.
|
||||
- phy_type : Should be one of "ulpi" or "utmi".
|
||||
- nvidia,vbus-gpio : If present, specifies a gpio that needs to be
|
||||
activated for the bus to be powered.
|
|
@ -1971,7 +1971,7 @@ endchoice
|
|||
|
||||
config XIP_KERNEL
|
||||
bool "Kernel Execute-In-Place from ROM"
|
||||
depends on !ZBOOT_ROM
|
||||
depends on !ZBOOT_ROM && !ARM_LPAE
|
||||
help
|
||||
Execute-In-Place allows the kernel to run from non-volatile storage
|
||||
directly addressable by the CPU, such as NOR flash. This saves RAM
|
||||
|
@ -2001,7 +2001,7 @@ config XIP_PHYS_ADDR
|
|||
|
||||
config KEXEC
|
||||
bool "Kexec system call (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
depends on EXPERIMENTAL && (!SMP || HOTPLUG_CPU)
|
||||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
|
|
@ -659,6 +659,7 @@ __armv7_mmu_cache_on:
|
|||
mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
|
||||
mcrne p15, 0, r1, c3, c0, 0 @ load domain access control
|
||||
#endif
|
||||
mcr p15, 0, r0, c7, c5, 4 @ ISB
|
||||
mcr p15, 0, r0, c1, c0, 0 @ load control register
|
||||
mrc p15, 0, r0, c1, c0, 0 @ and read it back
|
||||
mov r0, #0
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
/dts-v1/;
|
||||
|
||||
/memreserve/ 0x1c000000 0x04000000;
|
||||
/include/ "tegra20.dtsi"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Tegra2 Harmony evaluation board";
|
||||
compatible = "nvidia,harmony", "nvidia,tegra20";
|
||||
|
||||
chosen {
|
||||
bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk0p2 rw rootwait";
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
reg = < 0x00000000 0x40000000 >;
|
||||
};
|
||||
|
@ -52,16 +47,40 @@
|
|||
ext-mic-en-gpios = <&gpio 185 0>;
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006040 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
clock-frequency = < 216000000 >;
|
||||
};
|
||||
|
||||
serial@70006400 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000000 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000200 {
|
||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||
power-gpios = <&gpio 155 0>; /* gpio PT3 */
|
||||
};
|
||||
|
||||
sdhci@c8000400 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000600 {
|
||||
cd-gpios = <&gpio 58 0>; /* gpio PH2 */
|
||||
wp-gpios = <&gpio 59 0>; /* gpio PH3 */
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/dts-v1/;
|
||||
|
||||
/include/ "tegra20.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Toshiba AC100 / Dynabook AZ";
|
||||
compatible = "compal,paz00", "nvidia,tegra20";
|
||||
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x20000000>;
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
nvec@7000c500 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,nvec";
|
||||
reg = <0x7000C500 0x100>;
|
||||
interrupts = <0 92 0x04>;
|
||||
clock-frequency = <80000>;
|
||||
request-gpios = <&gpio 170 0>;
|
||||
slave-addr = <138>;
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
clock-frequency = <216000000>;
|
||||
};
|
||||
|
||||
serial@70006040 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
clock-frequency = <216000000>;
|
||||
};
|
||||
|
||||
serial@70006400 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000000 {
|
||||
cd-gpios = <&gpio 173 0>; /* gpio PV5 */
|
||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||
power-gpios = <&gpio 155 0>; /* gpio PT3 */
|
||||
};
|
||||
|
||||
sdhci@c8000200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000400 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000600 {
|
||||
support-8bit;
|
||||
};
|
||||
};
|
|
@ -1,25 +1,65 @@
|
|||
/dts-v1/;
|
||||
|
||||
/memreserve/ 0x1c000000 0x04000000;
|
||||
/include/ "tegra20.dtsi"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Seaboard";
|
||||
compatible = "nvidia,seaboard", "nvidia,tegra20";
|
||||
|
||||
chosen {
|
||||
bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/mmcblk1p3 rw rootwait";
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = < 0x00000000 0x40000000 >;
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
clock-frequency = <400000>;
|
||||
|
||||
adt7461@4c {
|
||||
compatible = "adt7461";
|
||||
reg = <0x4c>;
|
||||
};
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006040 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
clock-frequency = < 216000000 >;
|
||||
};
|
||||
|
||||
serial@70006400 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000000 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000400 {
|
||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||
|
@ -29,4 +69,28 @@
|
|||
sdhci@c8000600 {
|
||||
support-8bit;
|
||||
};
|
||||
|
||||
usb@c5000000 {
|
||||
nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */
|
||||
};
|
||||
|
||||
gpio-keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
power {
|
||||
label = "Power";
|
||||
gpios = <&gpio 170 1>; /* gpio PV2, active low */
|
||||
linux,code = <116>; /* KEY_POWER */
|
||||
gpio-key,wakeup;
|
||||
};
|
||||
|
||||
lid {
|
||||
label = "Lid";
|
||||
gpios = <&gpio 23 0>; /* gpio PC7 */
|
||||
linux,input-type = <5>; /* EV_SW */
|
||||
linux,code = <0>; /* SW_LID */
|
||||
debounce-interval = <1>;
|
||||
gpio-key,wakeup;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/dts-v1/;
|
||||
|
||||
/include/ "tegra20.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Compulab TrimSlice board";
|
||||
compatible = "compulab,trimslice", "nvidia,tegra20";
|
||||
|
||||
memory@0 {
|
||||
reg = < 0x00000000 0x40000000 >;
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
clock-frequency = < 216000000 >;
|
||||
};
|
||||
|
||||
serial@70006040 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006400 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000000 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000400 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000600 {
|
||||
cd-gpios = <&gpio 121 0>;
|
||||
wp-gpios = <&gpio 122 0>;
|
||||
};
|
||||
};
|
|
@ -1,24 +1,59 @@
|
|||
/dts-v1/;
|
||||
|
||||
/memreserve/ 0x1c000000 0x04000000;
|
||||
/include/ "tegra20.dtsi"
|
||||
|
||||
/ {
|
||||
model = "NVIDIA Tegra2 Ventana evaluation board";
|
||||
compatible = "nvidia,ventana", "nvidia,tegra20";
|
||||
|
||||
chosen {
|
||||
bootargs = "vmalloc=192M video=tegrafb console=ttyS0,115200n8 root=/dev/ram rdinit=/sbin/init";
|
||||
};
|
||||
|
||||
memory {
|
||||
reg = < 0x00000000 0x40000000 >;
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006040 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
clock-frequency = < 216000000 >;
|
||||
};
|
||||
|
||||
serial@70006400 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000000 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000200 {
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
sdhci@c8000400 {
|
||||
cd-gpios = <&gpio 69 0>; /* gpio PI5 */
|
||||
wp-gpios = <&gpio 57 0>; /* gpio PH1 */
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
interrupt-parent = <&intc>;
|
||||
|
||||
intc: interrupt-controller@50041000 {
|
||||
compatible = "nvidia,tegra20-gic";
|
||||
compatible = "arm,cortex-a9-gic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
#interrupt-cells = <3>;
|
||||
reg = < 0x50041000 0x1000 >,
|
||||
< 0x50040100 0x0100 >;
|
||||
};
|
||||
|
@ -17,7 +17,7 @@
|
|||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C000 0x100>;
|
||||
interrupts = < 70 >;
|
||||
interrupts = < 0 38 0x04 >;
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
|
@ -25,7 +25,7 @@
|
|||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C400 0x100>;
|
||||
interrupts = < 116 >;
|
||||
interrupts = < 0 84 0x04 >;
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
|
@ -33,38 +33,32 @@
|
|||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C500 0x100>;
|
||||
interrupts = < 124 >;
|
||||
interrupts = < 0 92 0x04 >;
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2c";
|
||||
compatible = "nvidia,tegra20-i2c-dvc";
|
||||
reg = <0x7000D000 0x200>;
|
||||
interrupts = < 85 >;
|
||||
interrupts = < 0 53 0x04 >;
|
||||
};
|
||||
|
||||
i2s@70002800 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2s";
|
||||
reg = <0x70002800 0x200>;
|
||||
interrupts = < 45 >;
|
||||
interrupts = < 0 13 0x04 >;
|
||||
dma-channel = < 2 >;
|
||||
};
|
||||
|
||||
i2s@70002a00 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-i2s";
|
||||
reg = <0x70002a00 0x200>;
|
||||
interrupts = < 35 >;
|
||||
interrupts = < 0 3 0x04 >;
|
||||
dma-channel = < 1 >;
|
||||
};
|
||||
|
||||
das@70000c00 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra20-das";
|
||||
reg = <0x70000c00 0x80>;
|
||||
};
|
||||
|
@ -72,7 +66,13 @@
|
|||
gpio: gpio@6000d000 {
|
||||
compatible = "nvidia,tegra20-gpio";
|
||||
reg = < 0x6000d000 0x1000 >;
|
||||
interrupts = < 64 65 66 67 87 119 121 >;
|
||||
interrupts = < 0 32 0x04
|
||||
0 33 0x04
|
||||
0 34 0x04
|
||||
0 35 0x04
|
||||
0 55 0x04
|
||||
0 87 0x04
|
||||
0 89 0x04 >;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
@ -89,59 +89,80 @@
|
|||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006000 0x40>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 68 >;
|
||||
interrupts = < 0 36 0x04 >;
|
||||
};
|
||||
|
||||
serial@70006040 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006040 0x40>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 69 >;
|
||||
interrupts = < 0 37 0x04 >;
|
||||
};
|
||||
|
||||
serial@70006200 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006200 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 78 >;
|
||||
interrupts = < 0 46 0x04 >;
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006300 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 122 >;
|
||||
interrupts = < 0 90 0x04 >;
|
||||
};
|
||||
|
||||
serial@70006400 {
|
||||
compatible = "nvidia,tegra20-uart";
|
||||
reg = <0x70006400 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 123 >;
|
||||
interrupts = < 0 91 0x04 >;
|
||||
};
|
||||
|
||||
sdhci@c8000000 {
|
||||
compatible = "nvidia,tegra20-sdhci";
|
||||
reg = <0xc8000000 0x200>;
|
||||
interrupts = < 46 >;
|
||||
interrupts = < 0 14 0x04 >;
|
||||
};
|
||||
|
||||
sdhci@c8000200 {
|
||||
compatible = "nvidia,tegra20-sdhci";
|
||||
reg = <0xc8000200 0x200>;
|
||||
interrupts = < 47 >;
|
||||
interrupts = < 0 15 0x04 >;
|
||||
};
|
||||
|
||||
sdhci@c8000400 {
|
||||
compatible = "nvidia,tegra20-sdhci";
|
||||
reg = <0xc8000400 0x200>;
|
||||
interrupts = < 51 >;
|
||||
interrupts = < 0 19 0x04 >;
|
||||
};
|
||||
|
||||
sdhci@c8000600 {
|
||||
compatible = "nvidia,tegra20-sdhci";
|
||||
reg = <0xc8000600 0x200>;
|
||||
interrupts = < 63 >;
|
||||
interrupts = < 0 31 0x04 >;
|
||||
};
|
||||
|
||||
usb@c5000000 {
|
||||
compatible = "nvidia,tegra20-ehci", "usb-ehci";
|
||||
reg = <0xc5000000 0x4000>;
|
||||
interrupts = < 0 20 0x04 >;
|
||||
phy_type = "utmi";
|
||||
};
|
||||
|
||||
usb@c5004000 {
|
||||
compatible = "nvidia,tegra20-ehci", "usb-ehci";
|
||||
reg = <0xc5004000 0x4000>;
|
||||
interrupts = < 0 21 0x04 >;
|
||||
phy_type = "ulpi";
|
||||
};
|
||||
|
||||
usb@c5008000 {
|
||||
compatible = "nvidia,tegra20-ehci", "usb-ehci";
|
||||
reg = <0xc5008000 0x4000>;
|
||||
interrupts = < 0 97 0x04 >;
|
||||
phy_type = "utmi";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/include/ "skeleton.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "nvidia,tegra30";
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
intc: interrupt-controller@50041000 {
|
||||
compatible = "arm,cortex-a9-gic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
reg = < 0x50041000 0x1000 >,
|
||||
< 0x50040100 0x0100 >;
|
||||
};
|
||||
|
||||
i2c@7000c000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C000 0x100>;
|
||||
interrupts = < 0 38 0x04 >;
|
||||
};
|
||||
|
||||
i2c@7000c400 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C400 0x100>;
|
||||
interrupts = < 0 84 0x04 >;
|
||||
};
|
||||
|
||||
i2c@7000c500 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000C500 0x100>;
|
||||
interrupts = < 0 92 0x04 >;
|
||||
};
|
||||
|
||||
i2c@7000c700 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000c700 0x100>;
|
||||
interrupts = < 0 120 0x04 >;
|
||||
};
|
||||
|
||||
i2c@7000d000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
|
||||
reg = <0x7000D000 0x100>;
|
||||
interrupts = < 0 53 0x04 >;
|
||||
};
|
||||
|
||||
gpio: gpio@6000d000 {
|
||||
compatible = "nvidia,tegra30-gpio", "nvidia,tegra20-gpio";
|
||||
reg = < 0x6000d000 0x1000 >;
|
||||
interrupts = < 0 32 0x04 0 33 0x04 0 34 0x04 0 35 0x04 0 55 0x04 0 87 0x04 0 89 0x04 >;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
serial@70006000 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006000 0x40>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 0 36 0x04 >;
|
||||
};
|
||||
|
||||
serial@70006040 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006040 0x40>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 0 37 0x04 >;
|
||||
};
|
||||
|
||||
serial@70006200 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006200 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 0 46 0x04 >;
|
||||
};
|
||||
|
||||
serial@70006300 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006300 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 0 90 0x04 >;
|
||||
};
|
||||
|
||||
serial@70006400 {
|
||||
compatible = "nvidia,tegra30-uart", "nvidia,tegra20-uart";
|
||||
reg = <0x70006400 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = < 0 91 0x04 >;
|
||||
};
|
||||
|
||||
sdhci@78000000 {
|
||||
compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
|
||||
reg = <0x78000000 0x200>;
|
||||
interrupts = < 0 14 0x04 >;
|
||||
};
|
||||
|
||||
sdhci@78000200 {
|
||||
compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
|
||||
reg = <0x78000200 0x200>;
|
||||
interrupts = < 0 15 0x04 >;
|
||||
};
|
||||
|
||||
sdhci@78000400 {
|
||||
compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
|
||||
reg = <0x78000400 0x200>;
|
||||
interrupts = < 0 19 0x04 >;
|
||||
};
|
||||
|
||||
sdhci@78000600 {
|
||||
compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
|
||||
reg = <0x78000600 0x200>;
|
||||
interrupts = < 0 31 0x04 >;
|
||||
};
|
||||
|
||||
pinmux: pinmux@70000000 {
|
||||
compatible = "nvidia,tegra30-pinmux";
|
||||
reg = < 0x70000868 0xd0 /* Pad control registers */
|
||||
0x70003000 0x3e0 >; /* Mux registers */
|
||||
};
|
||||
};
|
|
@ -318,7 +318,7 @@ static void __init vic_set_irq_sources(void __iomem *base,
|
|||
* and 020 within the page. We call this "second block".
|
||||
*/
|
||||
static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
|
||||
u32 vic_sources)
|
||||
u32 vic_sources, struct device_node *node)
|
||||
{
|
||||
unsigned int i;
|
||||
int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0;
|
||||
|
@ -345,6 +345,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
|
|||
}
|
||||
|
||||
vic_set_irq_sources(base, irq_start, vic_sources);
|
||||
vic_register(base, irq_start, 0, node);
|
||||
}
|
||||
|
||||
static void __init __vic_init(void __iomem *base, unsigned int irq_start,
|
||||
|
@ -367,7 +368,7 @@ static void __init __vic_init(void __iomem *base, unsigned int irq_start,
|
|||
|
||||
switch(vendor) {
|
||||
case AMBA_VENDOR_ST:
|
||||
vic_init_st(base, irq_start, vic_sources);
|
||||
vic_init_st(base, irq_start, vic_sources, node);
|
||||
return;
|
||||
default:
|
||||
printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
|
||||
|
|
|
@ -186,6 +186,17 @@
|
|||
#define ALT_UP_B(label) b label
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Instruction barrier
|
||||
*/
|
||||
.macro instr_sync
|
||||
#if __LINUX_ARM_ARCH__ >= 7
|
||||
isb
|
||||
#elif __LINUX_ARM_ARCH__ == 6
|
||||
mcr p15, 0, r0, c7, c5, 4
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* SMP data memory barrier
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef __ASM_IDMAP_H
|
||||
#define __ASM_IDMAP_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/* Tag a function as requiring to be executed via an identity mapping. */
|
||||
#define __idmap __section(.idmap.text) noinline notrace
|
||||
|
||||
extern pgd_t *idmap_pgd;
|
||||
|
||||
void setup_mm_for_reboot(void);
|
||||
|
||||
#endif /* __ASM_IDMAP_H */
|
|
@ -151,7 +151,11 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
|
|||
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
|
||||
extern void copy_page(void *to, const void *from);
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#include <asm/pgtable-3level-types.h>
|
||||
#else
|
||||
#include <asm/pgtable-2level-types.h>
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
|
|
|
@ -25,12 +25,34 @@
|
|||
#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER))
|
||||
#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
|
||||
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
|
||||
}
|
||||
|
||||
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
||||
{
|
||||
BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
|
||||
free_page((unsigned long)pmd);
|
||||
}
|
||||
|
||||
static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
|
||||
{
|
||||
set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE));
|
||||
}
|
||||
|
||||
#else /* !CONFIG_ARM_LPAE */
|
||||
|
||||
/*
|
||||
* Since we have only two-level page tables, these are trivial
|
||||
*/
|
||||
#define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); })
|
||||
#define pmd_free(mm, pmd) do { } while (0)
|
||||
#define pgd_populate(mm,pmd,pte) BUG()
|
||||
#define pud_populate(mm,pmd,pte) BUG()
|
||||
|
||||
#endif /* CONFIG_ARM_LPAE */
|
||||
|
||||
extern pgd_t *pgd_alloc(struct mm_struct *mm);
|
||||
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
|
||||
|
@ -109,7 +131,9 @@ static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
|
|||
{
|
||||
pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot;
|
||||
pmdp[0] = __pmd(pmdval);
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
|
||||
#endif
|
||||
flush_pmd_entry(pmdp);
|
||||
}
|
||||
|
||||
|
|
|
@ -140,4 +140,45 @@
|
|||
#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */
|
||||
#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* The "pud_xxx()" functions here are trivial when the pmd is folded into
|
||||
* the pud: the pud entry is never bad, always exists, and can't be set or
|
||||
* cleared.
|
||||
*/
|
||||
#define pud_none(pud) (0)
|
||||
#define pud_bad(pud) (0)
|
||||
#define pud_present(pud) (1)
|
||||
#define pud_clear(pudp) do { } while (0)
|
||||
#define set_pud(pud,pudp) do { } while (0)
|
||||
|
||||
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
|
||||
{
|
||||
return (pmd_t *)pud;
|
||||
}
|
||||
|
||||
#define pmd_bad(pmd) (pmd_val(pmd) & 2)
|
||||
|
||||
#define copy_pmd(pmdpd,pmdps) \
|
||||
do { \
|
||||
pmdpd[0] = pmdps[0]; \
|
||||
pmdpd[1] = pmdps[1]; \
|
||||
flush_pmd_entry(pmdpd); \
|
||||
} while (0)
|
||||
|
||||
#define pmd_clear(pmdp) \
|
||||
do { \
|
||||
pmdp[0] = __pmd(0); \
|
||||
pmdp[1] = __pmd(0); \
|
||||
clean_pmd_entry(pmdp); \
|
||||
} while (0)
|
||||
|
||||
/* we don't need complex calculations here as the pmd is folded into the pgd */
|
||||
#define pmd_addr_end(addr,end) (end)
|
||||
|
||||
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_PGTABLE_2LEVEL_H */
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* arch/arm/include/asm/pgtable-3level-hwdef.h
|
||||
*
|
||||
* Copyright (C) 2011 ARM Ltd.
|
||||
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _ASM_PGTABLE_3LEVEL_HWDEF_H
|
||||
#define _ASM_PGTABLE_3LEVEL_HWDEF_H
|
||||
|
||||
/*
|
||||
* Hardware page table definitions.
|
||||
*
|
||||
* + Level 1/2 descriptor
|
||||
* - common
|
||||
*/
|
||||
#define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0)
|
||||
#define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0)
|
||||
#define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0)
|
||||
#define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0)
|
||||
#define PMD_BIT4 (_AT(pmdval_t, 0))
|
||||
#define PMD_DOMAIN(x) (_AT(pmdval_t, 0))
|
||||
|
||||
/*
|
||||
* - section
|
||||
*/
|
||||
#define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2)
|
||||
#define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3)
|
||||
#define PMD_SECT_S (_AT(pmdval_t, 3) << 8)
|
||||
#define PMD_SECT_AF (_AT(pmdval_t, 1) << 10)
|
||||
#define PMD_SECT_nG (_AT(pmdval_t, 1) << 11)
|
||||
#define PMD_SECT_XN (_AT(pmdval_t, 1) << 54)
|
||||
#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0))
|
||||
#define PMD_SECT_AP_READ (_AT(pmdval_t, 0))
|
||||
#define PMD_SECT_TEX(x) (_AT(pmdval_t, 0))
|
||||
|
||||
/*
|
||||
* AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
|
||||
*/
|
||||
#define PMD_SECT_UNCACHED (_AT(pmdval_t, 0) << 2) /* strongly ordered */
|
||||
#define PMD_SECT_BUFFERED (_AT(pmdval_t, 1) << 2) /* normal non-cacheable */
|
||||
#define PMD_SECT_WT (_AT(pmdval_t, 2) << 2) /* normal inner write-through */
|
||||
#define PMD_SECT_WB (_AT(pmdval_t, 3) << 2) /* normal inner write-back */
|
||||
#define PMD_SECT_WBWA (_AT(pmdval_t, 7) << 2) /* normal inner write-alloc */
|
||||
|
||||
/*
|
||||
* + Level 3 descriptor (PTE)
|
||||
*/
|
||||
#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
|
||||
#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
|
||||
#define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0)
|
||||
#define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */
|
||||
#define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */
|
||||
#define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
|
||||
#define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */
|
||||
#define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */
|
||||
#define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */
|
||||
|
||||
/*
|
||||
* 40-bit physical address supported.
|
||||
*/
|
||||
#define PHYS_MASK_SHIFT (40)
|
||||
#define PHYS_MASK ((1ULL << PHYS_MASK_SHIFT) - 1)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* arch/arm/include/asm/pgtable-3level-types.h
|
||||
*
|
||||
* Copyright (C) 2011 ARM Ltd.
|
||||
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _ASM_PGTABLE_3LEVEL_TYPES_H
|
||||
#define _ASM_PGTABLE_3LEVEL_TYPES_H
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
typedef u64 pteval_t;
|
||||
typedef u64 pmdval_t;
|
||||
typedef u64 pgdval_t;
|
||||
|
||||
#undef STRICT_MM_TYPECHECKS
|
||||
|
||||
#ifdef STRICT_MM_TYPECHECKS
|
||||
|
||||
/*
|
||||
* These are used to make use of C type-checking..
|
||||
*/
|
||||
typedef struct { pteval_t pte; } pte_t;
|
||||
typedef struct { pmdval_t pmd; } pmd_t;
|
||||
typedef struct { pgdval_t pgd; } pgd_t;
|
||||
typedef struct { pteval_t pgprot; } pgprot_t;
|
||||
|
||||
#define pte_val(x) ((x).pte)
|
||||
#define pmd_val(x) ((x).pmd)
|
||||
#define pgd_val(x) ((x).pgd)
|
||||
#define pgprot_val(x) ((x).pgprot)
|
||||
|
||||
#define __pte(x) ((pte_t) { (x) } )
|
||||
#define __pmd(x) ((pmd_t) { (x) } )
|
||||
#define __pgd(x) ((pgd_t) { (x) } )
|
||||
#define __pgprot(x) ((pgprot_t) { (x) } )
|
||||
|
||||
#else /* !STRICT_MM_TYPECHECKS */
|
||||
|
||||
typedef pteval_t pte_t;
|
||||
typedef pmdval_t pmd_t;
|
||||
typedef pgdval_t pgd_t;
|
||||
typedef pteval_t pgprot_t;
|
||||
|
||||
#define pte_val(x) (x)
|
||||
#define pmd_val(x) (x)
|
||||
#define pgd_val(x) (x)
|
||||
#define pgprot_val(x) (x)
|
||||
|
||||
#define __pte(x) (x)
|
||||
#define __pmd(x) (x)
|
||||
#define __pgd(x) (x)
|
||||
#define __pgprot(x) (x)
|
||||
|
||||
#endif /* STRICT_MM_TYPECHECKS */
|
||||
|
||||
#endif /* _ASM_PGTABLE_3LEVEL_TYPES_H */
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* arch/arm/include/asm/pgtable-3level.h
|
||||
*
|
||||
* Copyright (C) 2011 ARM Ltd.
|
||||
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _ASM_PGTABLE_3LEVEL_H
|
||||
#define _ASM_PGTABLE_3LEVEL_H
|
||||
|
||||
/*
|
||||
* With LPAE, there are 3 levels of page tables. Each level has 512 entries of
|
||||
* 8 bytes each, occupying a 4K page. The first level table covers a range of
|
||||
* 512GB, each entry representing 1GB. Since we are limited to 4GB input
|
||||
* address range, only 4 entries in the PGD are used.
|
||||
*
|
||||
* There are enough spare bits in a page table entry for the kernel specific
|
||||
* state.
|
||||
*/
|
||||
#define PTRS_PER_PTE 512
|
||||
#define PTRS_PER_PMD 512
|
||||
#define PTRS_PER_PGD 4
|
||||
|
||||
#define PTE_HWTABLE_PTRS (PTRS_PER_PTE)
|
||||
#define PTE_HWTABLE_OFF (0)
|
||||
#define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u64))
|
||||
|
||||
/*
|
||||
* PGDIR_SHIFT determines the size a top-level page table entry can map.
|
||||
*/
|
||||
#define PGDIR_SHIFT 30
|
||||
|
||||
/*
|
||||
* PMD_SHIFT determines the size a middle-level page table entry can map.
|
||||
*/
|
||||
#define PMD_SHIFT 21
|
||||
|
||||
#define PMD_SIZE (1UL << PMD_SHIFT)
|
||||
#define PMD_MASK (~(PMD_SIZE-1))
|
||||
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
|
||||
#define PGDIR_MASK (~(PGDIR_SIZE-1))
|
||||
|
||||
/*
|
||||
* section address mask and size definitions.
|
||||
*/
|
||||
#define SECTION_SHIFT 21
|
||||
#define SECTION_SIZE (1UL << SECTION_SHIFT)
|
||||
#define SECTION_MASK (~(SECTION_SIZE-1))
|
||||
|
||||
#define USER_PTRS_PER_PGD (PAGE_OFFSET / PGDIR_SIZE)
|
||||
|
||||
/*
|
||||
* "Linux" PTE definitions for LPAE.
|
||||
*
|
||||
* These bits overlap with the hardware bits but the naming is preserved for
|
||||
* consistency with the classic page table format.
|
||||
*/
|
||||
#define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Valid */
|
||||
#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
|
||||
#define L_PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */
|
||||
#define L_PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */
|
||||
#define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */
|
||||
#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */
|
||||
#define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
|
||||
#define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */
|
||||
#define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */
|
||||
#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) /* unused */
|
||||
#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */
|
||||
|
||||
/*
|
||||
* To be used in assembly code with the upper page attributes.
|
||||
*/
|
||||
#define L_PTE_XN_HIGH (1 << (54 - 32))
|
||||
#define L_PTE_DIRTY_HIGH (1 << (55 - 32))
|
||||
|
||||
/*
|
||||
* AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
|
||||
*/
|
||||
#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0) << 2) /* strongly ordered */
|
||||
#define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 1) << 2) /* normal non-cacheable */
|
||||
#define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 2) << 2) /* normal inner write-through */
|
||||
#define L_PTE_MT_WRITEBACK (_AT(pteval_t, 3) << 2) /* normal inner write-back */
|
||||
#define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 7) << 2) /* normal inner write-alloc */
|
||||
#define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 4) << 2) /* device */
|
||||
#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 4) << 2) /* device */
|
||||
#define L_PTE_MT_DEV_WC (_AT(pteval_t, 1) << 2) /* normal non-cacheable */
|
||||
#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 3) << 2) /* normal inner write-back */
|
||||
#define L_PTE_MT_MASK (_AT(pteval_t, 7) << 2)
|
||||
|
||||
/*
|
||||
* Software PGD flags.
|
||||
*/
|
||||
#define L_PGD_SWAPPER (_AT(pgdval_t, 1) << 55) /* swapper_pg_dir entry */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#define pud_none(pud) (!pud_val(pud))
|
||||
#define pud_bad(pud) (!(pud_val(pud) & 2))
|
||||
#define pud_present(pud) (pud_val(pud))
|
||||
|
||||
#define pud_clear(pudp) \
|
||||
do { \
|
||||
*pudp = __pud(0); \
|
||||
clean_pmd_entry(pudp); \
|
||||
} while (0)
|
||||
|
||||
#define set_pud(pudp, pud) \
|
||||
do { \
|
||||
*pudp = pud; \
|
||||
flush_pmd_entry(pudp); \
|
||||
} while (0)
|
||||
|
||||
static inline pmd_t *pud_page_vaddr(pud_t pud)
|
||||
{
|
||||
return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
|
||||
}
|
||||
|
||||
/* Find an entry in the second-level page table.. */
|
||||
#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
|
||||
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
|
||||
{
|
||||
return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
|
||||
}
|
||||
|
||||
#define pmd_bad(pmd) (!(pmd_val(pmd) & 2))
|
||||
|
||||
#define copy_pmd(pmdpd,pmdps) \
|
||||
do { \
|
||||
*pmdpd = *pmdps; \
|
||||
flush_pmd_entry(pmdpd); \
|
||||
} while (0)
|
||||
|
||||
#define pmd_clear(pmdp) \
|
||||
do { \
|
||||
*pmdp = __pmd(0); \
|
||||
clean_pmd_entry(pmdp); \
|
||||
} while (0)
|
||||
|
||||
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,__pte(pte_val(pte)|(ext)))
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_PGTABLE_3LEVEL_H */
|
|
@ -10,6 +10,10 @@
|
|||
#ifndef _ASMARM_PGTABLE_HWDEF_H
|
||||
#define _ASMARM_PGTABLE_HWDEF_H
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#include <asm/pgtable-3level-hwdef.h>
|
||||
#else
|
||||
#include <asm/pgtable-2level-hwdef.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,19 +11,24 @@
|
|||
#define _ASMARM_PGTABLE_H
|
||||
|
||||
#include <linux/const.h>
|
||||
#include <asm-generic/4level-fixup.h>
|
||||
#include <asm/proc-fns.h>
|
||||
|
||||
#ifndef CONFIG_MMU
|
||||
|
||||
#include <asm-generic/4level-fixup.h>
|
||||
#include "pgtable-nommu.h"
|
||||
|
||||
#else
|
||||
|
||||
#include <asm-generic/pgtable-nopud.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/pgtable-hwdef.h>
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#include <asm/pgtable-3level.h>
|
||||
#else
|
||||
#include <asm/pgtable-2level.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Just any arbitrary offset to the start of the vmalloc VM area: the
|
||||
|
@ -164,39 +169,8 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
|
|||
/* to find an entry in a kernel page-table-directory */
|
||||
#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
|
||||
|
||||
/*
|
||||
* The "pgd_xxx()" functions here are trivial for a folded two-level
|
||||
* setup: the pgd is never bad, and a pmd always exists (as it's folded
|
||||
* into the pgd entry)
|
||||
*/
|
||||
#define pgd_none(pgd) (0)
|
||||
#define pgd_bad(pgd) (0)
|
||||
#define pgd_present(pgd) (1)
|
||||
#define pgd_clear(pgdp) do { } while (0)
|
||||
#define set_pgd(pgd,pgdp) do { } while (0)
|
||||
#define set_pud(pud,pudp) do { } while (0)
|
||||
|
||||
|
||||
/* Find an entry in the second-level page table.. */
|
||||
#define pmd_offset(dir, addr) ((pmd_t *)(dir))
|
||||
|
||||
#define pmd_none(pmd) (!pmd_val(pmd))
|
||||
#define pmd_present(pmd) (pmd_val(pmd))
|
||||
#define pmd_bad(pmd) (pmd_val(pmd) & 2)
|
||||
|
||||
#define copy_pmd(pmdpd,pmdps) \
|
||||
do { \
|
||||
pmdpd[0] = pmdps[0]; \
|
||||
pmdpd[1] = pmdps[1]; \
|
||||
flush_pmd_entry(pmdpd); \
|
||||
} while (0)
|
||||
|
||||
#define pmd_clear(pmdp) \
|
||||
do { \
|
||||
pmdp[0] = __pmd(0); \
|
||||
pmdp[1] = __pmd(0); \
|
||||
clean_pmd_entry(pmdp); \
|
||||
} while (0)
|
||||
|
||||
static inline pte_t *pmd_page_vaddr(pmd_t pmd)
|
||||
{
|
||||
|
@ -205,10 +179,6 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
|
|||
|
||||
#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
|
||||
|
||||
/* we don't need complex calculations here as the pmd is folded into the pgd */
|
||||
#define pmd_addr_end(addr,end) (end)
|
||||
|
||||
|
||||
#ifndef CONFIG_HIGHPTE
|
||||
#define __pte_map(pmd) pmd_page_vaddr(*(pmd))
|
||||
#define __pte_unmap(pte) do { } while (0)
|
||||
|
@ -230,7 +200,6 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
|
|||
#define pte_page(pte) pfn_to_page(pte_pfn(pte))
|
||||
#define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot)
|
||||
|
||||
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
|
||||
#define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0)
|
||||
|
||||
#if __LINUX_ARM_ARCH__ < 6
|
||||
|
@ -347,9 +316,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|||
|
||||
#define pgtable_cache_init() do { } while (0)
|
||||
|
||||
void identity_mapping_add(pgd_t *, unsigned long, unsigned long);
|
||||
void identity_mapping_del(pgd_t *, unsigned long, unsigned long);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
|
|
@ -65,7 +65,11 @@ extern struct processor {
|
|||
* Set a possibly extended PTE. Non-extended PTEs should
|
||||
* ignore 'ext'.
|
||||
*/
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
void (*set_pte_ext)(pte_t *ptep, pte_t pte);
|
||||
#else
|
||||
void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
|
||||
#endif
|
||||
|
||||
/* Suspend/resume */
|
||||
unsigned int suspend_size;
|
||||
|
@ -79,7 +83,11 @@ extern void cpu_proc_fin(void);
|
|||
extern int cpu_do_idle(void);
|
||||
extern void cpu_dcache_clean_area(void *, int);
|
||||
extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte);
|
||||
#else
|
||||
extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
|
||||
#endif
|
||||
extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
|
||||
|
||||
/* These three are private to arch/arm/kernel/suspend.c */
|
||||
|
@ -107,6 +115,18 @@ extern void cpu_resume(void);
|
|||
|
||||
#define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#define cpu_get_pgd() \
|
||||
({ \
|
||||
unsigned long pg, pg2; \
|
||||
__asm__("mrrc p15, 0, %0, %1, c2" \
|
||||
: "=r" (pg), "=r" (pg2) \
|
||||
: \
|
||||
: "cc"); \
|
||||
pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1); \
|
||||
(pgd_t *)phys_to_virt(pg); \
|
||||
})
|
||||
#else
|
||||
#define cpu_get_pgd() \
|
||||
({ \
|
||||
unsigned long pg; \
|
||||
|
@ -115,6 +135,7 @@ extern void cpu_resume(void);
|
|||
pg &= ~0x3fff; \
|
||||
(pgd_t *)phys_to_virt(pg); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -80,6 +80,14 @@ struct siginfo;
|
|||
void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
|
||||
unsigned long err, unsigned long trap);
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#define FAULT_CODE_ALIGNMENT 33
|
||||
#define FAULT_CODE_DEBUG 34
|
||||
#else
|
||||
#define FAULT_CODE_ALIGNMENT 1
|
||||
#define FAULT_CODE_DEBUG 2
|
||||
#endif
|
||||
|
||||
void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
|
||||
struct pt_regs *),
|
||||
int sig, int code, const char *name);
|
||||
|
|
|
@ -202,8 +202,18 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
|
|||
tlb_remove_page(tlb, pte);
|
||||
}
|
||||
|
||||
static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
|
||||
unsigned long addr)
|
||||
{
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
tlb_add_flush(tlb, addr);
|
||||
tlb_remove_page(tlb, virt_to_page(pmdp));
|
||||
#endif
|
||||
}
|
||||
|
||||
#define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr)
|
||||
#define pmd_free_tlb(tlb, pmdp, addr) pmd_free((tlb)->mm, pmdp)
|
||||
#define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr)
|
||||
#define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp)
|
||||
|
||||
#define tlb_migrate_finish(mm) do { } while (0)
|
||||
|
||||
|
|
|
@ -39,8 +39,14 @@
|
|||
#error KERNEL_RAM_VADDR must start at 0xXXXX8000
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
/* LPAE requires an additional page for the PGD */
|
||||
#define PG_DIR_SIZE 0x5000
|
||||
#define PMD_ORDER 3
|
||||
#else
|
||||
#define PG_DIR_SIZE 0x4000
|
||||
#define PMD_ORDER 2
|
||||
#endif
|
||||
|
||||
.globl swapper_pg_dir
|
||||
.equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE
|
||||
|
@ -164,17 +170,36 @@ __create_page_tables:
|
|||
teq r0, r6
|
||||
bne 1b
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* Build the PGD table (first level) to point to the PMD table. A PGD
|
||||
* entry is 64-bit wide.
|
||||
*/
|
||||
mov r0, r4
|
||||
add r3, r4, #0x1000 @ first PMD table address
|
||||
orr r3, r3, #3 @ PGD block type
|
||||
mov r6, #4 @ PTRS_PER_PGD
|
||||
mov r7, #1 << (55 - 32) @ L_PGD_SWAPPER
|
||||
1: str r3, [r0], #4 @ set bottom PGD entry bits
|
||||
str r7, [r0], #4 @ set top PGD entry bits
|
||||
add r3, r3, #0x1000 @ next PMD table
|
||||
subs r6, r6, #1
|
||||
bne 1b
|
||||
|
||||
add r4, r4, #0x1000 @ point to the PMD tables
|
||||
#endif
|
||||
|
||||
ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
|
||||
|
||||
/*
|
||||
* Create identity mapping to cater for __enable_mmu.
|
||||
* This identity mapping will be removed by paging_init().
|
||||
*/
|
||||
adr r0, __enable_mmu_loc
|
||||
adr r0, __turn_mmu_on_loc
|
||||
ldmia r0, {r3, r5, r6}
|
||||
sub r0, r0, r3 @ virt->phys offset
|
||||
add r5, r5, r0 @ phys __enable_mmu
|
||||
add r6, r6, r0 @ phys __enable_mmu_end
|
||||
add r5, r5, r0 @ phys __turn_mmu_on
|
||||
add r6, r6, r0 @ phys __turn_mmu_on_end
|
||||
mov r5, r5, lsr #SECTION_SHIFT
|
||||
mov r6, r6, lsr #SECTION_SHIFT
|
||||
|
||||
|
@ -219,8 +244,8 @@ __create_page_tables:
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Then map boot params address in r2 or
|
||||
* the first 1MB of ram if boot params address is not specified.
|
||||
* Then map boot params address in r2 or the first 1MB (2MB with LPAE)
|
||||
* of ram if boot params address is not specified.
|
||||
*/
|
||||
mov r0, r2, lsr #SECTION_SHIFT
|
||||
movs r0, r0, lsl #SECTION_SHIFT
|
||||
|
@ -251,7 +276,15 @@ __create_page_tables:
|
|||
mov r3, r7, lsr #SECTION_SHIFT
|
||||
ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
|
||||
orr r3, r7, r3, lsl #SECTION_SHIFT
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
mov r7, #1 << (54 - 32) @ XN
|
||||
#else
|
||||
orr r3, r3, #PMD_SECT_XN
|
||||
#endif
|
||||
1: str r3, [r0], #4
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
str r7, [r0], #4
|
||||
#endif
|
||||
add r3, r3, #1 << SECTION_SHIFT
|
||||
cmp r0, r6
|
||||
blo 1b
|
||||
|
@ -282,15 +315,18 @@ __create_page_tables:
|
|||
add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER)
|
||||
str r3, [r0]
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
sub r4, r4, #0x1000 @ point to the PGD table
|
||||
#endif
|
||||
mov pc, lr
|
||||
ENDPROC(__create_page_tables)
|
||||
.ltorg
|
||||
.align
|
||||
__enable_mmu_loc:
|
||||
__turn_mmu_on_loc:
|
||||
.long .
|
||||
.long __enable_mmu
|
||||
.long __enable_mmu_end
|
||||
.long __turn_mmu_on
|
||||
.long __turn_mmu_on_end
|
||||
|
||||
#if defined(CONFIG_SMP)
|
||||
__CPUINIT
|
||||
|
@ -374,12 +410,17 @@ __enable_mmu:
|
|||
#ifdef CONFIG_CPU_ICACHE_DISABLE
|
||||
bic r0, r0, #CR_I
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
mov r5, #0
|
||||
mcrr p15, 0, r4, r5, c2 @ load TTBR0
|
||||
#else
|
||||
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
|
||||
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
|
||||
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
|
||||
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
|
||||
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
|
||||
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
|
||||
#endif
|
||||
b __turn_mmu_on
|
||||
ENDPROC(__enable_mmu)
|
||||
|
||||
|
@ -398,15 +439,19 @@ ENDPROC(__enable_mmu)
|
|||
* other registers depend on the function called upon completion
|
||||
*/
|
||||
.align 5
|
||||
__turn_mmu_on:
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(__turn_mmu_on)
|
||||
mov r0, r0
|
||||
instr_sync
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write control reg
|
||||
mrc p15, 0, r3, c0, c0, 0 @ read id reg
|
||||
instr_sync
|
||||
mov r3, r3
|
||||
mov r3, r13
|
||||
mov pc, r3
|
||||
__enable_mmu_end:
|
||||
__turn_mmu_on_end:
|
||||
ENDPROC(__turn_mmu_on)
|
||||
.popsection
|
||||
|
||||
|
||||
#ifdef CONFIG_SMP_ON_UP
|
||||
|
|
|
@ -1016,10 +1016,10 @@ static int __init arch_hw_breakpoint_init(void)
|
|||
}
|
||||
|
||||
/* Register debug fault handler. */
|
||||
hook_fault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
|
||||
"watchpoint debug exception");
|
||||
hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
|
||||
"breakpoint debug exception");
|
||||
hook_fault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
|
||||
TRAP_HWBKPT, "watchpoint debug exception");
|
||||
hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
|
||||
TRAP_HWBKPT, "breakpoint debug exception");
|
||||
|
||||
/* Register hotplug notifier. */
|
||||
register_cpu_notifier(&dbg_reset_nb);
|
||||
|
|
|
@ -12,12 +12,11 @@
|
|||
#include <asm/mmu_context.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
extern const unsigned char relocate_new_kernel[];
|
||||
extern const unsigned int relocate_new_kernel_size;
|
||||
|
||||
extern void setup_mm_for_reboot(void);
|
||||
|
||||
extern unsigned long kexec_start_address;
|
||||
extern unsigned long kexec_indirection_page;
|
||||
extern unsigned long kexec_mach_type;
|
||||
|
@ -111,14 +110,6 @@ void machine_kexec(struct kimage *image)
|
|||
|
||||
if (kexec_reinit)
|
||||
kexec_reinit();
|
||||
local_irq_disable();
|
||||
local_fiq_disable();
|
||||
setup_mm_for_reboot();
|
||||
flush_cache_all();
|
||||
outer_flush_all();
|
||||
outer_disable();
|
||||
cpu_proc_fin();
|
||||
outer_inv_all();
|
||||
flush_cache_all();
|
||||
cpu_reset(reboot_code_buffer_phys);
|
||||
|
||||
soft_restart(reboot_code_buffer_phys);
|
||||
}
|
||||
|
|
|
@ -92,17 +92,23 @@ static int __init hlt_setup(char *__unused)
|
|||
__setup("nohlt", nohlt_setup);
|
||||
__setup("hlt", hlt_setup);
|
||||
|
||||
void soft_restart(unsigned long addr)
|
||||
{
|
||||
/* Disable interrupts first */
|
||||
local_irq_disable();
|
||||
local_fiq_disable();
|
||||
extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
|
||||
typedef void (*phys_reset_t)(unsigned long);
|
||||
|
||||
/*
|
||||
* Tell the mm system that we are going to reboot -
|
||||
* we may need it to insert some 1:1 mappings so that
|
||||
* soft boot works.
|
||||
*/
|
||||
/*
|
||||
* A temporary stack to use for CPU reset. This is static so that we
|
||||
* don't clobber it with the identity mapping. When running with this
|
||||
* stack, any references to the current task *will not work* so you
|
||||
* should really do as little as possible before jumping to your reset
|
||||
* code.
|
||||
*/
|
||||
static u64 soft_restart_stack[16];
|
||||
|
||||
static void __soft_restart(void *addr)
|
||||
{
|
||||
phys_reset_t phys_reset;
|
||||
|
||||
/* Take out a flat memory mapping. */
|
||||
setup_mm_for_reboot();
|
||||
|
||||
/* Clean and invalidate caches */
|
||||
|
@ -114,7 +120,31 @@ void soft_restart(unsigned long addr)
|
|||
/* Push out any further dirty data, and ensure cache is empty */
|
||||
flush_cache_all();
|
||||
|
||||
cpu_reset(addr);
|
||||
/* Switch to the identity mapping. */
|
||||
phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
|
||||
phys_reset((unsigned long)addr);
|
||||
|
||||
/* Should never get here. */
|
||||
BUG();
|
||||
}
|
||||
|
||||
void soft_restart(unsigned long addr)
|
||||
{
|
||||
u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);
|
||||
|
||||
/* Disable interrupts first */
|
||||
local_irq_disable();
|
||||
local_fiq_disable();
|
||||
|
||||
/* Disable the L2 if we're the last man standing. */
|
||||
if (num_online_cpus() == 1)
|
||||
outer_disable();
|
||||
|
||||
/* Change to the new stack and continue with the reset. */
|
||||
call_with_stack(__soft_restart, (void *)addr, (void *)stack);
|
||||
|
||||
/* Should never get here. */
|
||||
BUG();
|
||||
}
|
||||
|
||||
void arm_machine_restart(char mode, const char *cmd)
|
||||
|
|
|
@ -54,14 +54,18 @@ ENDPROC(cpu_suspend_abort)
|
|||
* r0 = control register value
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text,"ax"
|
||||
ENTRY(cpu_resume_mmu)
|
||||
ldr r3, =cpu_resume_after_mmu
|
||||
instr_sync
|
||||
mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc
|
||||
mrc p15, 0, r0, c0, c0, 0 @ read id reg
|
||||
instr_sync
|
||||
mov r0, r0
|
||||
mov r0, r0
|
||||
mov pc, r3 @ jump to virtual address
|
||||
ENDPROC(cpu_resume_mmu)
|
||||
.popsection
|
||||
cpu_resume_after_mmu:
|
||||
bl cpu_init @ restore the und/abt/irq banked regs
|
||||
mov r0, #0 @ return zero on success
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <asm/cpu.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/exception.h>
|
||||
#include <asm/idmap.h>
|
||||
#include <asm/topology.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@ -61,7 +62,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
|||
{
|
||||
struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
|
||||
struct task_struct *idle = ci->idle;
|
||||
pgd_t *pgd;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
@ -83,30 +83,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
|||
init_idle(idle, cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate initial page tables to allow the new CPU to
|
||||
* enable the MMU safely. This essentially means a set
|
||||
* of our "standard" page tables, with the addition of
|
||||
* a 1:1 mapping for the physical address of the kernel.
|
||||
*/
|
||||
pgd = pgd_alloc(&init_mm);
|
||||
if (!pgd)
|
||||
return -ENOMEM;
|
||||
|
||||
if (PHYS_OFFSET != PAGE_OFFSET) {
|
||||
#ifndef CONFIG_HOTPLUG_CPU
|
||||
identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
|
||||
#endif
|
||||
identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
|
||||
identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to tell the secondary core where to find
|
||||
* its stack and the page tables.
|
||||
*/
|
||||
secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
|
||||
secondary_data.pgdir = virt_to_phys(pgd);
|
||||
secondary_data.pgdir = virt_to_phys(idmap_pgd);
|
||||
secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir);
|
||||
__cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
|
||||
outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
|
||||
|
@ -142,16 +124,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
|||
secondary_data.stack = NULL;
|
||||
secondary_data.pgdir = 0;
|
||||
|
||||
if (PHYS_OFFSET != PAGE_OFFSET) {
|
||||
#ifndef CONFIG_HOTPLUG_CPU
|
||||
identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
|
||||
#endif
|
||||
identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
|
||||
identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
|
||||
}
|
||||
|
||||
pgd_free(&init_mm, pgd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -550,6 +522,10 @@ static void ipi_cpu_stop(unsigned int cpu)
|
|||
local_fiq_disable();
|
||||
local_irq_disable();
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
platform_cpu_kill(cpu);
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
cpu_relax();
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
#include <linux/init.h>
|
||||
|
||||
#include <asm/idmap.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/suspend.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
static pgd_t *suspend_pgd;
|
||||
|
||||
extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
|
||||
extern void cpu_resume_mmu(void);
|
||||
|
||||
|
@ -21,7 +20,7 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)
|
|||
*save_ptr = virt_to_phys(ptr);
|
||||
|
||||
/* This must correspond to the LDM in cpu_resume() assembly */
|
||||
*ptr++ = virt_to_phys(suspend_pgd);
|
||||
*ptr++ = virt_to_phys(idmap_pgd);
|
||||
*ptr++ = sp;
|
||||
*ptr++ = virt_to_phys(cpu_do_resume);
|
||||
|
||||
|
@ -42,7 +41,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
|||
struct mm_struct *mm = current->active_mm;
|
||||
int ret;
|
||||
|
||||
if (!suspend_pgd)
|
||||
if (!idmap_pgd)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
@ -59,14 +58,3 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init cpu_suspend_init(void)
|
||||
{
|
||||
suspend_pgd = pgd_alloc(&init_mm);
|
||||
if (suspend_pgd) {
|
||||
unsigned long addr = virt_to_phys(cpu_resume_mmu);
|
||||
identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE);
|
||||
}
|
||||
return suspend_pgd ? 0 : -ENOMEM;
|
||||
}
|
||||
core_initcall(cpu_suspend_init);
|
||||
|
|
|
@ -13,6 +13,12 @@
|
|||
*(.proc.info.init) \
|
||||
VMLINUX_SYMBOL(__proc_info_end) = .;
|
||||
|
||||
#define IDMAP_TEXT \
|
||||
ALIGN_FUNCTION(); \
|
||||
VMLINUX_SYMBOL(__idmap_text_start) = .; \
|
||||
*(.idmap.text) \
|
||||
VMLINUX_SYMBOL(__idmap_text_end) = .;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
#define ARM_CPU_DISCARD(x)
|
||||
#define ARM_CPU_KEEP(x) x
|
||||
|
@ -92,6 +98,7 @@ SECTIONS
|
|||
SCHED_TEXT
|
||||
LOCK_TEXT
|
||||
KPROBES_TEXT
|
||||
IDMAP_TEXT
|
||||
#ifdef CONFIG_MMU
|
||||
*(.fixup)
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,8 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
|
|||
testchangebit.o testclearbit.o testsetbit.o \
|
||||
ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
|
||||
ucmpdi2.o lib1funcs.o div64.o \
|
||||
io-readsb.o io-writesb.o io-readsl.o io-writesl.o
|
||||
io-readsb.o io-writesb.o io-readsl.o io-writesl.o \
|
||||
call_with_stack.o
|
||||
|
||||
mmu-y := clear_user.o copy_page.o getuser.o putuser.o
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* arch/arm/lib/call_with_stack.S
|
||||
*
|
||||
* Copyright (C) 2011 ARM Ltd.
|
||||
* Written by Will Deacon <will.deacon@arm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
/*
|
||||
* void call_with_stack(void (*fn)(void *), void *arg, void *sp)
|
||||
*
|
||||
* Change the stack to that pointed at by sp, then invoke fn(arg) with
|
||||
* the new stack.
|
||||
*/
|
||||
ENTRY(call_with_stack)
|
||||
str sp, [r2, #-4]!
|
||||
str lr, [r2, #-4]!
|
||||
|
||||
mov sp, r2
|
||||
mov r2, r0
|
||||
mov r0, r1
|
||||
|
||||
adr lr, BSYM(1f)
|
||||
mov pc, r2
|
||||
|
||||
1: ldr lr, [sp]
|
||||
ldr sp, [sp, #4]
|
||||
mov pc, lr
|
||||
ENDPROC(call_with_stack)
|
|
@ -18,20 +18,22 @@ obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
|
|||
obj-$(CONFIG_TEGRA_PCI) += pcie.o
|
||||
obj-$(CONFIG_USB_SUPPORT) += usb_phy.o
|
||||
|
||||
obj-${CONFIG_MACH_HARMONY} += board-harmony.o
|
||||
obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o
|
||||
obj-${CONFIG_MACH_HARMONY} += board-harmony-pcie.o
|
||||
obj-${CONFIG_MACH_HARMONY} += board-harmony-power.o
|
||||
obj-$(CONFIG_MACH_HARMONY) += board-harmony.o
|
||||
obj-$(CONFIG_MACH_HARMONY) += board-harmony-pinmux.o
|
||||
obj-$(CONFIG_MACH_HARMONY) += board-harmony-pcie.o
|
||||
obj-$(CONFIG_MACH_HARMONY) += board-harmony-power.o
|
||||
|
||||
obj-${CONFIG_MACH_PAZ00} += board-paz00.o
|
||||
obj-${CONFIG_MACH_PAZ00} += board-paz00-pinmux.o
|
||||
obj-$(CONFIG_MACH_PAZ00) += board-paz00.o
|
||||
obj-$(CONFIG_MACH_PAZ00) += board-paz00-pinmux.o
|
||||
|
||||
obj-${CONFIG_MACH_SEABOARD} += board-seaboard.o
|
||||
obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o
|
||||
obj-$(CONFIG_MACH_SEABOARD) += board-seaboard.o
|
||||
obj-$(CONFIG_MACH_SEABOARD) += board-seaboard-pinmux.o
|
||||
|
||||
obj-${CONFIG_MACH_TEGRA_DT} += board-dt.o
|
||||
obj-${CONFIG_MACH_TEGRA_DT} += board-harmony-pinmux.o
|
||||
obj-${CONFIG_MACH_TEGRA_DT} += board-seaboard-pinmux.o
|
||||
obj-$(CONFIG_MACH_TEGRA_DT) += board-dt.o
|
||||
obj-$(CONFIG_MACH_TEGRA_DT) += board-harmony-pinmux.o
|
||||
obj-$(CONFIG_MACH_TEGRA_DT) += board-seaboard-pinmux.o
|
||||
obj-$(CONFIG_MACH_TEGRA_DT) += board-paz00-pinmux.o
|
||||
obj-$(CONFIG_MACH_TEGRA_DT) += board-trimslice-pinmux.o
|
||||
|
||||
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice.o
|
||||
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice-pinmux.o
|
||||
obj-$(CONFIG_MACH_TRIMSLICE) += board-trimslice.o
|
||||
obj-$(CONFIG_MACH_TRIMSLICE) += board-trimslice-pinmux.o
|
||||
|
|
|
@ -3,5 +3,7 @@ params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100
|
|||
initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00800000
|
||||
|
||||
dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
|
||||
dtb-$(CONFIG_MACH_PAZ00) += tegra-paz00.dtb
|
||||
dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
|
||||
dtb-$(CONFIG_MACH_TRIMSLICE) += tegra-trimslice.dtb
|
||||
dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
#include <mach/iomap.h>
|
||||
#include <mach/irqs.h>
|
||||
|
@ -47,9 +48,22 @@
|
|||
#include "devices.h"
|
||||
|
||||
void harmony_pinmux_init(void);
|
||||
void paz00_pinmux_init(void);
|
||||
void seaboard_pinmux_init(void);
|
||||
void trimslice_pinmux_init(void);
|
||||
void ventana_pinmux_init(void);
|
||||
|
||||
static const struct of_device_id tegra_dt_irq_match[] __initconst = {
|
||||
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init },
|
||||
{ }
|
||||
};
|
||||
|
||||
void __init tegra_dt_init_irq(void)
|
||||
{
|
||||
tegra_init_irq();
|
||||
of_irq_init(tegra_dt_irq_match);
|
||||
}
|
||||
|
||||
struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
|
||||
|
@ -58,16 +72,30 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
|
|||
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C_BASE, "tegra-i2c.0", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2c-dvc", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.0", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra-i2s.1", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra-i2s.1", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0",
|
||||
&tegra_ehci1_device.dev.platform_data),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1",
|
||||
&tegra_ehci2_device.dev.platform_data),
|
||||
OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2",
|
||||
&tegra_ehci3_device.dev.platform_data),
|
||||
{}
|
||||
};
|
||||
|
||||
static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
|
||||
/* name parent rate enabled */
|
||||
{ "uartd", "pll_p", 216000000, true },
|
||||
{ "usbd", "clk_m", 12000000, false },
|
||||
{ "usb2", "clk_m", 12000000, false },
|
||||
{ "usb3", "clk_m", 12000000, false },
|
||||
{ "pll_a", "pll_p_out1", 56448000, true },
|
||||
{ "pll_a_out0", "pll_a", 11289600, true },
|
||||
{ "cdev1", NULL, 0, true },
|
||||
{ "i2s1", "pll_a_out0", 11289600, false},
|
||||
{ "i2s2", "pll_a_out0", 11289600, false},
|
||||
{ NULL, NULL, 0, 0},
|
||||
};
|
||||
|
||||
|
@ -76,30 +104,21 @@ static struct of_device_id tegra_dt_match_table[] __initdata = {
|
|||
{}
|
||||
};
|
||||
|
||||
static struct of_device_id tegra_dt_gic_match[] __initdata = {
|
||||
{ .compatible = "nvidia,tegra20-gic", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct {
|
||||
char *machine;
|
||||
void (*init)(void);
|
||||
} pinmux_configs[] = {
|
||||
{ "compulab,trimslice", trimslice_pinmux_init },
|
||||
{ "nvidia,harmony", harmony_pinmux_init },
|
||||
{ "compal,paz00", paz00_pinmux_init },
|
||||
{ "nvidia,seaboard", seaboard_pinmux_init },
|
||||
{ "nvidia,ventana", ventana_pinmux_init },
|
||||
};
|
||||
|
||||
static void __init tegra_dt_init(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
int i;
|
||||
|
||||
node = of_find_matching_node_by_address(NULL, tegra_dt_gic_match,
|
||||
TEGRA_ARM_INT_DIST_BASE);
|
||||
if (node)
|
||||
irq_domain_add_simple(node, INT_GIC_BASE);
|
||||
|
||||
tegra_clk_init_from_table(tegra_dt_clk_init_table);
|
||||
|
||||
/*
|
||||
|
@ -121,7 +140,9 @@ static void __init tegra_dt_init(void)
|
|||
}
|
||||
|
||||
static const char * tegra_dt_board_compat[] = {
|
||||
"compulab,trimslice",
|
||||
"nvidia,harmony",
|
||||
"compal,paz00",
|
||||
"nvidia,seaboard",
|
||||
"nvidia,ventana",
|
||||
NULL
|
||||
|
@ -130,7 +151,7 @@ static const char * tegra_dt_board_compat[] = {
|
|||
DT_MACHINE_START(TEGRA_DT, "nVidia Tegra (Flattened Device Tree)")
|
||||
.map_io = tegra_map_common_io,
|
||||
.init_early = tegra_init_early,
|
||||
.init_irq = tegra_init_irq,
|
||||
.init_irq = tegra_dt_init_irq,
|
||||
.handle_irq = gic_handle_irq,
|
||||
.timer = &tegra_timer,
|
||||
.init_machine = tegra_dt_init,
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
|
@ -129,6 +130,11 @@ void __init tegra_init_irq(void)
|
|||
gic_arch_extn.irq_unmask = tegra_unmask;
|
||||
gic_arch_extn.irq_retrigger = tegra_retrigger;
|
||||
|
||||
gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
|
||||
IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
|
||||
/*
|
||||
* Check if there is a devicetree present, since the GIC will be
|
||||
* initialized elsewhere under DT.
|
||||
*/
|
||||
if (!of_have_populated_dt())
|
||||
gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
|
||||
IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
|
||||
}
|
||||
|
|
|
@ -629,6 +629,23 @@ config IO_36
|
|||
|
||||
comment "Processor Features"
|
||||
|
||||
config ARM_LPAE
|
||||
bool "Support for the Large Physical Address Extension"
|
||||
depends on MMU && CPU_V7
|
||||
help
|
||||
Say Y if you have an ARMv7 processor supporting the LPAE page
|
||||
table format and you would like to access memory beyond the
|
||||
4GB limit. The resulting kernel image will not run on
|
||||
processors without the LPA extension.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config ARCH_PHYS_ADDR_T_64BIT
|
||||
def_bool ARM_LPAE
|
||||
|
||||
config ARCH_DMA_ADDR_T_64BIT
|
||||
bool
|
||||
|
||||
config ARM_THUMB
|
||||
bool "Support Thumb user binaries"
|
||||
depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON
|
||||
|
|
|
@ -968,7 +968,7 @@ static int __init alignment_init(void)
|
|||
ai_usermode = safe_usermode(ai_usermode, false);
|
||||
}
|
||||
|
||||
hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
|
||||
hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
|
||||
"alignment exception");
|
||||
|
||||
/*
|
||||
|
|
|
@ -22,6 +22,21 @@ unsigned int cpu_last_asid = ASID_FIRST_VERSION;
|
|||
DEFINE_PER_CPU(struct mm_struct *, current_mm);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#define cpu_set_asid(asid) { \
|
||||
unsigned long ttbl, ttbh; \
|
||||
asm volatile( \
|
||||
" mrrc p15, 0, %0, %1, c2 @ read TTBR0\n" \
|
||||
" mov %1, %2, lsl #(48 - 32) @ set ASID\n" \
|
||||
" mcrr p15, 0, %0, %1, c2 @ set TTBR0\n" \
|
||||
: "=&r" (ttbl), "=&r" (ttbh) \
|
||||
: "r" (asid & ~ASID_MASK)); \
|
||||
}
|
||||
#else
|
||||
#define cpu_set_asid(asid) \
|
||||
asm(" mcr p15, 0, %0, c13, c0, 1\n" : : "r" (asid))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We fork()ed a process, and we need a new context for the child
|
||||
* to run in. We reserve version 0 for initial tasks so we will
|
||||
|
@ -37,7 +52,7 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
|||
static void flush_context(void)
|
||||
{
|
||||
/* set the reserved ASID before flushing the TLB */
|
||||
asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (0));
|
||||
cpu_set_asid(0);
|
||||
isb();
|
||||
local_flush_tlb_all();
|
||||
if (icache_is_vivt_asid_tagged()) {
|
||||
|
@ -99,7 +114,7 @@ static void reset_context(void *info)
|
|||
set_mm_context(mm, asid);
|
||||
|
||||
/* set the new ASID */
|
||||
asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (mm->context.id));
|
||||
cpu_set_asid(mm->context.id);
|
||||
isb();
|
||||
}
|
||||
|
||||
|
|
|
@ -27,19 +27,6 @@
|
|||
|
||||
#include "fault.h"
|
||||
|
||||
/*
|
||||
* Fault status register encodings. We steal bit 31 for our own purposes.
|
||||
*/
|
||||
#define FSR_LNX_PF (1 << 31)
|
||||
#define FSR_WRITE (1 << 11)
|
||||
#define FSR_FS4 (1 << 10)
|
||||
#define FSR_FS3_0 (15)
|
||||
|
||||
static inline int fsr_fs(unsigned int fsr)
|
||||
{
|
||||
return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
|
@ -123,8 +110,10 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
|
|||
|
||||
pte = pte_offset_map(pmd, addr);
|
||||
printk(", *pte=%08llx", (long long)pte_val(*pte));
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
printk(", *ppte=%08llx",
|
||||
(long long)pte_val(pte[PTE_HWTABLE_PTRS]));
|
||||
#endif
|
||||
pte_unmap(pte);
|
||||
} while(0);
|
||||
|
||||
|
@ -441,6 +430,12 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
|
|||
pmd = pmd_offset(pud, addr);
|
||||
pmd_k = pmd_offset(pud_k, addr);
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* Only one hardware entry per PMD with LPAE.
|
||||
*/
|
||||
index = 0;
|
||||
#else
|
||||
/*
|
||||
* On ARM one Linux PGD entry contains two hardware entries (see page
|
||||
* tables layout in pgtable.h). We normally guarantee that we always
|
||||
|
@ -450,6 +445,7 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
|
|||
* for the first of pair.
|
||||
*/
|
||||
index = (addr >> SECTION_SHIFT) & 1;
|
||||
#endif
|
||||
if (pmd_none(pmd_k[index]))
|
||||
goto bad_area;
|
||||
|
||||
|
@ -489,55 +485,20 @@ do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct fsr_info {
|
||||
struct fsr_info {
|
||||
int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
|
||||
int sig;
|
||||
int code;
|
||||
const char *name;
|
||||
} fsr_info[] = {
|
||||
/*
|
||||
* The following are the standard ARMv3 and ARMv4 aborts. ARMv5
|
||||
* defines these to be "precise" aborts.
|
||||
*/
|
||||
{ do_bad, SIGSEGV, 0, "vector exception" },
|
||||
{ do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },
|
||||
{ do_bad, SIGKILL, 0, "terminal exception" },
|
||||
{ do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on linefetch" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on linefetch" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on translation" },
|
||||
{ do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on translation" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
|
||||
/*
|
||||
* The following are "imprecise" aborts, which are signalled by bit
|
||||
* 10 of the FSR, and may not be recoverable. These are only
|
||||
* supported if the CPU abort handler supports bit 10.
|
||||
*/
|
||||
{ do_bad, SIGBUS, 0, "unknown 16" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 17" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 18" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 19" },
|
||||
{ do_bad, SIGBUS, 0, "lock abort" }, /* xscale */
|
||||
{ do_bad, SIGBUS, 0, "unknown 21" },
|
||||
{ do_bad, SIGBUS, BUS_OBJERR, "imprecise external abort" }, /* xscale */
|
||||
{ do_bad, SIGBUS, 0, "unknown 23" },
|
||||
{ do_bad, SIGBUS, 0, "dcache parity error" }, /* xscale */
|
||||
{ do_bad, SIGBUS, 0, "unknown 25" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 26" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 27" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 28" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 29" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 30" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 31" }
|
||||
};
|
||||
|
||||
/* FSR definition */
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#include "fsr-3level.c"
|
||||
#else
|
||||
#include "fsr-2level.c"
|
||||
#endif
|
||||
|
||||
void __init
|
||||
hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
|
||||
int sig, int code, const char *name)
|
||||
|
@ -573,42 +534,6 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
arm_notify_die("", regs, &info, fsr, 0);
|
||||
}
|
||||
|
||||
|
||||
static struct fsr_info ifsr_info[] = {
|
||||
{ do_bad, SIGBUS, 0, "unknown 0" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 1" },
|
||||
{ do_bad, SIGBUS, 0, "debug event" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "section access flag fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 4" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "page access flag fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 10" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on translation" },
|
||||
{ do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on translation" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 16" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 17" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 18" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 19" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 20" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 21" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 22" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 23" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 24" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 25" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 26" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 27" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 28" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 29" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 30" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 31" },
|
||||
};
|
||||
|
||||
void __init
|
||||
hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *),
|
||||
int sig, int code, const char *name)
|
||||
|
@ -641,6 +566,7 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
|
|||
arm_notify_die("", regs, &info, ifsr, 0);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
static int __init exceptions_init(void)
|
||||
{
|
||||
if (cpu_architecture() >= CPU_ARCH_ARMv6) {
|
||||
|
@ -663,3 +589,4 @@ static int __init exceptions_init(void)
|
|||
}
|
||||
|
||||
arch_initcall(exceptions_init);
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,28 @@
|
|||
void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
|
||||
#ifndef __ARCH_ARM_FAULT_H
|
||||
#define __ARCH_ARM_FAULT_H
|
||||
|
||||
/*
|
||||
* Fault status register encodings. We steal bit 31 for our own purposes.
|
||||
*/
|
||||
#define FSR_LNX_PF (1 << 31)
|
||||
#define FSR_WRITE (1 << 11)
|
||||
#define FSR_FS4 (1 << 10)
|
||||
#define FSR_FS3_0 (15)
|
||||
#define FSR_FS5_0 (0x3f)
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
static inline int fsr_fs(unsigned int fsr)
|
||||
{
|
||||
return fsr & FSR_FS5_0;
|
||||
}
|
||||
#else
|
||||
static inline int fsr_fs(unsigned int fsr)
|
||||
{
|
||||
return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6;
|
||||
}
|
||||
#endif
|
||||
|
||||
void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
|
||||
unsigned long search_exception_table(unsigned long addr);
|
||||
|
||||
#endif /* __ARCH_ARM_FAULT_H */
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
static struct fsr_info fsr_info[] = {
|
||||
/*
|
||||
* The following are the standard ARMv3 and ARMv4 aborts. ARMv5
|
||||
* defines these to be "precise" aborts.
|
||||
*/
|
||||
{ do_bad, SIGSEGV, 0, "vector exception" },
|
||||
{ do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },
|
||||
{ do_bad, SIGKILL, 0, "terminal exception" },
|
||||
{ do_bad, SIGBUS, BUS_ADRALN, "alignment exception" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on linefetch" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on linefetch" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on translation" },
|
||||
{ do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on translation" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
|
||||
/*
|
||||
* The following are "imprecise" aborts, which are signalled by bit
|
||||
* 10 of the FSR, and may not be recoverable. These are only
|
||||
* supported if the CPU abort handler supports bit 10.
|
||||
*/
|
||||
{ do_bad, SIGBUS, 0, "unknown 16" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 17" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 18" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 19" },
|
||||
{ do_bad, SIGBUS, 0, "lock abort" }, /* xscale */
|
||||
{ do_bad, SIGBUS, 0, "unknown 21" },
|
||||
{ do_bad, SIGBUS, BUS_OBJERR, "imprecise external abort" }, /* xscale */
|
||||
{ do_bad, SIGBUS, 0, "unknown 23" },
|
||||
{ do_bad, SIGBUS, 0, "dcache parity error" }, /* xscale */
|
||||
{ do_bad, SIGBUS, 0, "unknown 25" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 26" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 27" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 28" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 29" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 30" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 31" },
|
||||
};
|
||||
|
||||
static struct fsr_info ifsr_info[] = {
|
||||
{ do_bad, SIGBUS, 0, "unknown 0" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 1" },
|
||||
{ do_bad, SIGBUS, 0, "debug event" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "section access flag fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 4" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "page access flag fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on non-linefetch" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 10" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on translation" },
|
||||
{ do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" },
|
||||
{ do_bad, SIGBUS, 0, "external abort on translation" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 16" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 17" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 18" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 19" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 20" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 21" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 22" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 23" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 24" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 25" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 26" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 27" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 28" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 29" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 30" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 31" },
|
||||
};
|
|
@ -0,0 +1,68 @@
|
|||
static struct fsr_info fsr_info[] = {
|
||||
{ do_bad, SIGBUS, 0, "unknown 0" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 1" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 2" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 3" },
|
||||
{ do_bad, SIGBUS, 0, "reserved translation fault" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
|
||||
{ do_bad, SIGBUS, 0, "reserved access flag fault" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
|
||||
{ do_bad, SIGBUS, 0, "reserved permission fault" },
|
||||
{ do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
|
||||
{ do_sect_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous external abort" },
|
||||
{ do_bad, SIGBUS, 0, "asynchronous external abort" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 18" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 19" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous parity error" },
|
||||
{ do_bad, SIGBUS, 0, "asynchronous parity error" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 26" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 27" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
|
||||
{ do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 32" },
|
||||
{ do_bad, SIGBUS, BUS_ADRALN, "alignment fault" },
|
||||
{ do_bad, SIGBUS, 0, "debug event" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 35" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 36" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 37" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 38" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 39" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 40" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 41" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 42" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 43" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 44" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 45" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 46" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 47" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 48" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 49" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 50" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 51" },
|
||||
{ do_bad, SIGBUS, 0, "implementation fault (lockdown abort)" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 53" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 54" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 55" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 56" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 57" },
|
||||
{ do_bad, SIGBUS, 0, "implementation fault (coprocessor abort)" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 59" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 60" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 61" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 62" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 63" },
|
||||
};
|
||||
|
||||
#define ifsr_info fsr_info
|
|
@ -1,9 +1,38 @@
|
|||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/idmap.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
pgd_t *idmap_pgd;
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
|
||||
unsigned long prot)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
unsigned long next;
|
||||
|
||||
if (pud_none_or_clear_bad(pud) || (pud_val(*pud) & L_PGD_SWAPPER)) {
|
||||
pmd = pmd_alloc_one(&init_mm, addr);
|
||||
if (!pmd) {
|
||||
pr_warning("Failed to allocate identity pmd.\n");
|
||||
return;
|
||||
}
|
||||
pud_populate(&init_mm, pud, pmd);
|
||||
pmd += pmd_index(addr);
|
||||
} else
|
||||
pmd = pmd_offset(pud, addr);
|
||||
|
||||
do {
|
||||
next = pmd_addr_end(addr, end);
|
||||
*pmd = __pmd((addr & PMD_MASK) | prot);
|
||||
flush_pmd_entry(pmd);
|
||||
} while (pmd++, addr = next, addr != end);
|
||||
}
|
||||
#else /* !CONFIG_ARM_LPAE */
|
||||
static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
|
||||
unsigned long prot)
|
||||
{
|
||||
|
@ -15,6 +44,7 @@ static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
|
|||
pmd[1] = __pmd(addr);
|
||||
flush_pmd_entry(pmd);
|
||||
}
|
||||
#endif /* CONFIG_ARM_LPAE */
|
||||
|
||||
static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
|
||||
unsigned long prot)
|
||||
|
@ -28,11 +58,11 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
|
|||
} while (pud++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
|
||||
static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
|
||||
{
|
||||
unsigned long prot, next;
|
||||
|
||||
prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
|
||||
prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
|
||||
if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
|
||||
prot |= PMD_BIT4;
|
||||
|
||||
|
@ -43,48 +73,41 @@ void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
|
|||
} while (pgd++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end)
|
||||
extern char __idmap_text_start[], __idmap_text_end[];
|
||||
|
||||
static int __init init_static_idmap(void)
|
||||
{
|
||||
pmd_t *pmd = pmd_offset(pud, addr);
|
||||
pmd_clear(pmd);
|
||||
phys_addr_t idmap_start, idmap_end;
|
||||
|
||||
idmap_pgd = pgd_alloc(&init_mm);
|
||||
if (!idmap_pgd)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Add an identity mapping for the physical address of the section. */
|
||||
idmap_start = virt_to_phys((void *)__idmap_text_start);
|
||||
idmap_end = virt_to_phys((void *)__idmap_text_end);
|
||||
|
||||
pr_info("Setting up static identity map for 0x%llx - 0x%llx\n",
|
||||
(long long)idmap_start, (long long)idmap_end);
|
||||
identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end)
|
||||
{
|
||||
pud_t *pud = pud_offset(pgd, addr);
|
||||
unsigned long next;
|
||||
|
||||
do {
|
||||
next = pud_addr_end(addr, end);
|
||||
idmap_del_pmd(pud, addr, next);
|
||||
} while (pud++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)
|
||||
{
|
||||
unsigned long next;
|
||||
|
||||
pgd += pgd_index(addr);
|
||||
do {
|
||||
next = pgd_addr_end(addr, end);
|
||||
idmap_del_pud(pgd, addr, next);
|
||||
} while (pgd++, addr = next, addr != end);
|
||||
}
|
||||
#endif
|
||||
early_initcall(init_static_idmap);
|
||||
|
||||
/*
|
||||
* In order to soft-boot, we need to insert a 1:1 mapping in place of
|
||||
* the user-mode pages. This will then ensure that we have predictable
|
||||
* results when turning the mmu off
|
||||
* In order to soft-boot, we need to switch to a 1:1 mapping for the
|
||||
* cpu_reset functions. This will then ensure that we have predictable
|
||||
* results when turning off the mmu.
|
||||
*/
|
||||
void setup_mm_for_reboot(void)
|
||||
{
|
||||
/*
|
||||
* We need to access to user-mode page tables here. For kernel threads
|
||||
* we don't have any user-mode mappings so we use the context that we
|
||||
* "borrowed".
|
||||
*/
|
||||
identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE);
|
||||
/* Clean and invalidate L1. */
|
||||
flush_cache_all();
|
||||
|
||||
/* Switch to the identity mapping. */
|
||||
cpu_switch_mm(idmap_pgd, &init_mm);
|
||||
|
||||
/* Flush the TLB. */
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ void __check_kvm_seq(struct mm_struct *mm)
|
|||
} while (seq != init_mm.context.kvm_seq);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
|
||||
/*
|
||||
* Section support is unsafe on SMP - If you iounmap and ioremap a region,
|
||||
* the other CPUs will not see this change until their next context switch.
|
||||
|
@ -73,13 +73,16 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
|
|||
{
|
||||
unsigned long addr = virt, end = virt + (size & ~(SZ_1M - 1));
|
||||
pgd_t *pgd;
|
||||
pud_t *pud;
|
||||
pmd_t *pmdp;
|
||||
|
||||
flush_cache_vunmap(addr, end);
|
||||
pgd = pgd_offset_k(addr);
|
||||
pud = pud_offset(pgd, addr);
|
||||
pmdp = pmd_offset(pud, addr);
|
||||
do {
|
||||
pmd_t pmd, *pmdp = pmd_offset(pgd, addr);
|
||||
pmd_t pmd = *pmdp;
|
||||
|
||||
pmd = *pmdp;
|
||||
if (!pmd_none(pmd)) {
|
||||
/*
|
||||
* Clear the PMD from the page table, and
|
||||
|
@ -98,8 +101,8 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
|
|||
pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
|
||||
}
|
||||
|
||||
addr += PGDIR_SIZE;
|
||||
pgd++;
|
||||
addr += PMD_SIZE;
|
||||
pmdp += 2;
|
||||
} while (addr < end);
|
||||
|
||||
/*
|
||||
|
@ -118,6 +121,8 @@ remap_area_sections(unsigned long virt, unsigned long pfn,
|
|||
{
|
||||
unsigned long addr = virt, end = virt + size;
|
||||
pgd_t *pgd;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
|
||||
/*
|
||||
* Remove and free any PTE-based mapping, and
|
||||
|
@ -126,17 +131,17 @@ remap_area_sections(unsigned long virt, unsigned long pfn,
|
|||
unmap_area_sections(virt, size);
|
||||
|
||||
pgd = pgd_offset_k(addr);
|
||||
pud = pud_offset(pgd, addr);
|
||||
pmd = pmd_offset(pud, addr);
|
||||
do {
|
||||
pmd_t *pmd = pmd_offset(pgd, addr);
|
||||
|
||||
pmd[0] = __pmd(__pfn_to_phys(pfn) | type->prot_sect);
|
||||
pfn += SZ_1M >> PAGE_SHIFT;
|
||||
pmd[1] = __pmd(__pfn_to_phys(pfn) | type->prot_sect);
|
||||
pfn += SZ_1M >> PAGE_SHIFT;
|
||||
flush_pmd_entry(pmd);
|
||||
|
||||
addr += PGDIR_SIZE;
|
||||
pgd++;
|
||||
addr += PMD_SIZE;
|
||||
pmd += 2;
|
||||
} while (addr < end);
|
||||
|
||||
return 0;
|
||||
|
@ -148,6 +153,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
|
|||
{
|
||||
unsigned long addr = virt, end = virt + size;
|
||||
pgd_t *pgd;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
|
||||
/*
|
||||
* Remove and free any PTE-based mapping, and
|
||||
|
@ -156,6 +163,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
|
|||
unmap_area_sections(virt, size);
|
||||
|
||||
pgd = pgd_offset_k(virt);
|
||||
pud = pud_offset(pgd, addr);
|
||||
pmd = pmd_offset(pud, addr);
|
||||
do {
|
||||
unsigned long super_pmd_val, i;
|
||||
|
||||
|
@ -164,14 +173,12 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
|
|||
super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
pmd_t *pmd = pmd_offset(pgd, addr);
|
||||
|
||||
pmd[0] = __pmd(super_pmd_val);
|
||||
pmd[1] = __pmd(super_pmd_val);
|
||||
flush_pmd_entry(pmd);
|
||||
|
||||
addr += PGDIR_SIZE;
|
||||
pgd++;
|
||||
addr += PMD_SIZE;
|
||||
pmd += 2;
|
||||
}
|
||||
|
||||
pfn += SUPERSECTION_SIZE >> PAGE_SHIFT;
|
||||
|
@ -189,11 +196,13 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
|
|||
unsigned long addr;
|
||||
struct vm_struct * area;
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* High mappings must be supersection aligned
|
||||
*/
|
||||
if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK))
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
type = get_mem_type(mtype);
|
||||
if (!type)
|
||||
|
@ -237,7 +246,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
|
|||
return NULL;
|
||||
addr = (unsigned long)area->addr;
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
|
||||
if (DOMAIN_IO == 0 &&
|
||||
(((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
|
||||
cpu_is_xsc3()) && pfn >= 0x100000 &&
|
||||
|
@ -343,7 +352,7 @@ void __iounmap(volatile void __iomem *io_addr)
|
|||
read_unlock(&vmlist_lock);
|
||||
return;
|
||||
}
|
||||
#ifndef CONFIG_SMP
|
||||
#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
|
||||
/*
|
||||
* If this is a section based mapping we need to handle it
|
||||
* specially as the VM subsystem does not know how to handle
|
||||
|
|
|
@ -151,6 +151,7 @@ static int __init early_nowrite(char *__unused)
|
|||
}
|
||||
early_param("nowb", early_nowrite);
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
static int __init early_ecc(char *p)
|
||||
{
|
||||
if (memcmp(p, "on", 2) == 0)
|
||||
|
@ -160,6 +161,7 @@ static int __init early_ecc(char *p)
|
|||
return 0;
|
||||
}
|
||||
early_param("ecc", early_ecc);
|
||||
#endif
|
||||
|
||||
static int __init noalign_setup(char *__unused)
|
||||
{
|
||||
|
@ -229,10 +231,12 @@ static struct mem_type mem_types[] = {
|
|||
.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
|
||||
.domain = DOMAIN_KERNEL,
|
||||
},
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
[MT_MINICLEAN] = {
|
||||
.prot_sect = PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_MINICACHE,
|
||||
.domain = DOMAIN_KERNEL,
|
||||
},
|
||||
#endif
|
||||
[MT_LOW_VECTORS] = {
|
||||
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
|
||||
L_PTE_RDONLY,
|
||||
|
@ -430,6 +434,7 @@ static void __init build_mem_type_table(void)
|
|||
* ARMv6 and above have extended page tables.
|
||||
*/
|
||||
if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* Mark cache clean areas and XIP ROM read only
|
||||
* from SVC mode and no access from userspace.
|
||||
|
@ -437,6 +442,7 @@ static void __init build_mem_type_table(void)
|
|||
mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||
#endif
|
||||
|
||||
if (is_smp()) {
|
||||
/*
|
||||
|
@ -475,6 +481,18 @@ static void __init build_mem_type_table(void)
|
|||
mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* Do not generate access flag faults for the kernel mappings.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
|
||||
mem_types[i].prot_pte |= PTE_EXT_AF;
|
||||
mem_types[i].prot_sect |= PMD_SECT_AF;
|
||||
}
|
||||
kern_pgprot |= PTE_EXT_AF;
|
||||
vecs_pgprot |= PTE_EXT_AF;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
unsigned long v = pgprot_val(protection_map[i]);
|
||||
protection_map[i] = __pgprot(v | user_pgprot);
|
||||
|
@ -578,8 +596,10 @@ static void __init alloc_init_section(pud_t *pud, unsigned long addr,
|
|||
if (((addr | end | phys) & ~SECTION_MASK) == 0) {
|
||||
pmd_t *p = pmd;
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
if (addr & SECTION_SIZE)
|
||||
pmd++;
|
||||
#endif
|
||||
|
||||
do {
|
||||
*pmd = __pmd(phys | type->prot_sect);
|
||||
|
@ -609,6 +629,7 @@ static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
|
|||
} while (pud++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
static void __init create_36bit_mapping(struct map_desc *md,
|
||||
const struct mem_type *type)
|
||||
{
|
||||
|
@ -668,6 +689,7 @@ static void __init create_36bit_mapping(struct map_desc *md,
|
|||
pgd += SUPERSECTION_SIZE >> PGDIR_SHIFT;
|
||||
} while (addr != end);
|
||||
}
|
||||
#endif /* !CONFIG_ARM_LPAE */
|
||||
|
||||
/*
|
||||
* Create the page directory entries and any necessary
|
||||
|
@ -700,6 +722,7 @@ static void __init create_mapping(struct map_desc *md)
|
|||
|
||||
type = &mem_types[md->type];
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* Catch 36-bit addresses
|
||||
*/
|
||||
|
@ -707,6 +730,7 @@ static void __init create_mapping(struct map_desc *md)
|
|||
create_36bit_mapping(md, type);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
addr = md->virtual & PAGE_MASK;
|
||||
phys = __pfn_to_phys(md->pfn);
|
||||
|
@ -797,6 +821,9 @@ void __init sanity_check_meminfo(void)
|
|||
struct membank *bank = &meminfo.bank[j];
|
||||
*bank = meminfo.bank[i];
|
||||
|
||||
if (bank->start > ULONG_MAX)
|
||||
highmem = 1;
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
if (__va(bank->start) >= vmalloc_min ||
|
||||
__va(bank->start) < (void *)PAGE_OFFSET)
|
||||
|
@ -808,7 +835,7 @@ void __init sanity_check_meminfo(void)
|
|||
* Split those memory banks which are partially overlapping
|
||||
* the vmalloc area greatly simplifying things later.
|
||||
*/
|
||||
if (__va(bank->start) < vmalloc_min &&
|
||||
if (!highmem && __va(bank->start) < vmalloc_min &&
|
||||
bank->size > vmalloc_min - __va(bank->start)) {
|
||||
if (meminfo.nr_banks >= NR_BANKS) {
|
||||
printk(KERN_CRIT "NR_BANKS too low, "
|
||||
|
@ -828,6 +855,17 @@ void __init sanity_check_meminfo(void)
|
|||
#else
|
||||
bank->highmem = highmem;
|
||||
|
||||
/*
|
||||
* Highmem banks not allowed with !CONFIG_HIGHMEM.
|
||||
*/
|
||||
if (highmem) {
|
||||
printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
|
||||
"(!CONFIG_HIGHMEM).\n",
|
||||
(unsigned long long)bank->start,
|
||||
(unsigned long long)bank->start + bank->size - 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether this memory bank would entirely overlap
|
||||
* the vmalloc area.
|
||||
|
@ -920,7 +958,13 @@ static inline void prepare_page_table(void)
|
|||
pmd_clear(pmd_off_k(addr));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
/* the first page is reserved for pgd */
|
||||
#define SWAPPER_PG_DIR_SIZE (PAGE_SIZE + \
|
||||
PTRS_PER_PGD * PTRS_PER_PMD * sizeof(pmd_t))
|
||||
#else
|
||||
#define SWAPPER_PG_DIR_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reserve the special regions of memory
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/page.h>
|
||||
|
@ -17,6 +18,14 @@
|
|||
|
||||
#include "mm.h"
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#define __pgd_alloc() kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL)
|
||||
#define __pgd_free(pgd) kfree(pgd)
|
||||
#else
|
||||
#define __pgd_alloc() (pgd_t *)__get_free_pages(GFP_KERNEL, 2)
|
||||
#define __pgd_free(pgd) free_pages((unsigned long)pgd, 2)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* need to get a 16k page for level 1
|
||||
*/
|
||||
|
@ -27,7 +36,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
|
|||
pmd_t *new_pmd, *init_pmd;
|
||||
pte_t *new_pte, *init_pte;
|
||||
|
||||
new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
|
||||
new_pgd = __pgd_alloc();
|
||||
if (!new_pgd)
|
||||
goto no_pgd;
|
||||
|
||||
|
@ -42,10 +51,25 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
|
|||
|
||||
clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
|
||||
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* Allocate PMD table for modules and pkmap mappings.
|
||||
*/
|
||||
new_pud = pud_alloc(mm, new_pgd + pgd_index(MODULES_VADDR),
|
||||
MODULES_VADDR);
|
||||
if (!new_pud)
|
||||
goto no_pud;
|
||||
|
||||
new_pmd = pmd_alloc(mm, new_pud, 0);
|
||||
if (!new_pmd)
|
||||
goto no_pmd;
|
||||
#endif
|
||||
|
||||
if (!vectors_high()) {
|
||||
/*
|
||||
* On ARM, first page must always be allocated since it
|
||||
* contains the machine vectors.
|
||||
* contains the machine vectors. The vectors are always high
|
||||
* with LPAE.
|
||||
*/
|
||||
new_pud = pud_alloc(mm, new_pgd, 0);
|
||||
if (!new_pud)
|
||||
|
@ -74,7 +98,7 @@ no_pte:
|
|||
no_pmd:
|
||||
pud_free(mm, new_pud);
|
||||
no_pud:
|
||||
free_pages((unsigned long)new_pgd, 2);
|
||||
__pgd_free(new_pgd);
|
||||
no_pgd:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -111,5 +135,24 @@ no_pud:
|
|||
pgd_clear(pgd);
|
||||
pud_free(mm, pud);
|
||||
no_pgd:
|
||||
free_pages((unsigned long) pgd_base, 2);
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* Free modules/pkmap or identity pmd tables.
|
||||
*/
|
||||
for (pgd = pgd_base; pgd < pgd_base + PTRS_PER_PGD; pgd++) {
|
||||
if (pgd_none_or_clear_bad(pgd))
|
||||
continue;
|
||||
if (pgd_val(*pgd) & L_PGD_SWAPPER)
|
||||
continue;
|
||||
pud = pud_offset(pgd, 0);
|
||||
if (pud_none_or_clear_bad(pud))
|
||||
continue;
|
||||
pmd = pmd_offset(pud, 0);
|
||||
pud_clear(pud);
|
||||
pmd_free(mm, pmd);
|
||||
pgd_clear(pgd);
|
||||
pud_free(mm, pud);
|
||||
}
|
||||
#endif
|
||||
__pgd_free(pgd_base);
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ ENTRY(cpu_arm1020_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm1020_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -107,6 +108,8 @@ ENTRY(cpu_arm1020_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm1020_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm1020_do_idle()
|
||||
|
|
|
@ -95,6 +95,7 @@ ENTRY(cpu_arm1020e_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm1020e_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -107,6 +108,8 @@ ENTRY(cpu_arm1020e_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm1020e_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm1020e_do_idle()
|
||||
|
|
|
@ -84,6 +84,7 @@ ENTRY(cpu_arm1022_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm1022_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -96,6 +97,8 @@ ENTRY(cpu_arm1022_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm1022_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm1022_do_idle()
|
||||
|
|
|
@ -84,6 +84,7 @@ ENTRY(cpu_arm1026_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm1026_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -96,6 +97,8 @@ ENTRY(cpu_arm1026_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm1026_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm1026_do_idle()
|
||||
|
|
|
@ -225,6 +225,7 @@ ENTRY(cpu_arm7_set_pte_ext)
|
|||
* Params : r0 = address to jump to
|
||||
* Notes : This sets up everything for a reset
|
||||
*/
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm6_reset)
|
||||
ENTRY(cpu_arm7_reset)
|
||||
mov r1, #0
|
||||
|
@ -235,6 +236,9 @@ ENTRY(cpu_arm7_reset)
|
|||
mov r1, #0x30
|
||||
mcr p15, 0, r1, c1, c0, 0 @ turn off MMU etc
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm6_reset)
|
||||
ENDPROC(cpu_arm7_reset)
|
||||
.popsection
|
||||
|
||||
__CPUINIT
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ ENTRY(cpu_arm720_set_pte_ext)
|
|||
* Params : r0 = address to jump to
|
||||
* Notes : This sets up everything for a reset
|
||||
*/
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm720_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate cache
|
||||
|
@ -112,6 +113,8 @@ ENTRY(cpu_arm720_reset)
|
|||
bic ip, ip, #0x2100 @ ..v....s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm720_reset)
|
||||
.popsection
|
||||
|
||||
__CPUINIT
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ ENTRY(cpu_arm740_proc_fin)
|
|||
* Params : r0 = address to jump to
|
||||
* Notes : This sets up everything for a reset
|
||||
*/
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm740_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c0, 0 @ invalidate cache
|
||||
|
@ -56,6 +57,8 @@ ENTRY(cpu_arm740_reset)
|
|||
bic ip, ip, #0x0000000c @ ............wc..
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm740_reset)
|
||||
.popsection
|
||||
|
||||
__CPUINIT
|
||||
|
||||
|
|
|
@ -45,8 +45,11 @@ ENTRY(cpu_arm7tdmi_proc_fin)
|
|||
* Params : loc(r0) address to jump to
|
||||
* Purpose : Sets up everything for a reset and jump to the location for soft reset.
|
||||
*/
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm7tdmi_reset)
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm7tdmi_reset)
|
||||
.popsection
|
||||
|
||||
__CPUINIT
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ ENTRY(cpu_arm920_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm920_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -97,6 +98,8 @@ ENTRY(cpu_arm920_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm920_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm920_do_idle()
|
||||
|
|
|
@ -87,6 +87,7 @@ ENTRY(cpu_arm922_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm922_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -99,6 +100,8 @@ ENTRY(cpu_arm922_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm922_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm922_do_idle()
|
||||
|
|
|
@ -108,6 +108,7 @@ ENTRY(cpu_arm925_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm925_reset)
|
||||
/* Send software reset to MPU and DSP */
|
||||
mov ip, #0xff000000
|
||||
|
@ -115,6 +116,8 @@ ENTRY(cpu_arm925_reset)
|
|||
orr ip, ip, #0x0000ce00
|
||||
mov r4, #1
|
||||
strh r4, [ip, #0x10]
|
||||
ENDPROC(cpu_arm925_reset)
|
||||
.popsection
|
||||
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
|
|
@ -77,6 +77,7 @@ ENTRY(cpu_arm926_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm926_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -89,6 +90,8 @@ ENTRY(cpu_arm926_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm926_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm926_do_idle()
|
||||
|
|
|
@ -48,6 +48,7 @@ ENTRY(cpu_arm940_proc_fin)
|
|||
* Params : r0 = address to jump to
|
||||
* Notes : This sets up everything for a reset
|
||||
*/
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm940_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c5, 0 @ flush I cache
|
||||
|
@ -58,6 +59,8 @@ ENTRY(cpu_arm940_reset)
|
|||
bic ip, ip, #0x00001000 @ i-cache
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm940_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm940_do_idle()
|
||||
|
|
|
@ -55,6 +55,7 @@ ENTRY(cpu_arm946_proc_fin)
|
|||
* Params : r0 = address to jump to
|
||||
* Notes : This sets up everything for a reset
|
||||
*/
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm946_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c5, 0 @ flush I cache
|
||||
|
@ -65,6 +66,8 @@ ENTRY(cpu_arm946_reset)
|
|||
bic ip, ip, #0x00001000 @ i-cache
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm946_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_arm946_do_idle()
|
||||
|
|
|
@ -45,8 +45,11 @@ ENTRY(cpu_arm9tdmi_proc_fin)
|
|||
* Params : loc(r0) address to jump to
|
||||
* Purpose : Sets up everything for a reset and jump to the location for soft reset.
|
||||
*/
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_arm9tdmi_reset)
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_arm9tdmi_reset)
|
||||
.popsection
|
||||
|
||||
__CPUINIT
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ ENTRY(cpu_fa526_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 4
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_fa526_reset)
|
||||
/* TODO: Use CP8 if possible... */
|
||||
mov ip, #0
|
||||
|
@ -73,6 +74,8 @@ ENTRY(cpu_fa526_reset)
|
|||
nop
|
||||
nop
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_fa526_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_fa526_do_idle()
|
||||
|
|
|
@ -98,6 +98,7 @@ ENTRY(cpu_feroceon_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_feroceon_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -110,6 +111,8 @@ ENTRY(cpu_feroceon_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_feroceon_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_feroceon_do_idle()
|
||||
|
|
|
@ -91,8 +91,9 @@
|
|||
#if L_PTE_SHARED != PTE_EXT_SHARED
|
||||
#error PTE shared bit mismatch
|
||||
#endif
|
||||
#if (L_PTE_XN+L_PTE_USER+L_PTE_RDONLY+L_PTE_DIRTY+L_PTE_YOUNG+\
|
||||
L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED
|
||||
#if !defined (CONFIG_ARM_LPAE) && \
|
||||
(L_PTE_XN+L_PTE_USER+L_PTE_RDONLY+L_PTE_DIRTY+L_PTE_YOUNG+\
|
||||
L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED
|
||||
#error Invalid Linux PTE bit settings
|
||||
#endif
|
||||
#endif /* CONFIG_MMU */
|
||||
|
|
|
@ -69,6 +69,7 @@ ENTRY(cpu_mohawk_proc_fin)
|
|||
* (same as arm926)
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_mohawk_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -79,6 +80,8 @@ ENTRY(cpu_mohawk_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_mohawk_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_mohawk_do_idle()
|
||||
|
|
|
@ -62,6 +62,7 @@ ENTRY(cpu_sa110_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_sa110_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -74,6 +75,8 @@ ENTRY(cpu_sa110_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_sa110_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_sa110_do_idle(type)
|
||||
|
|
|
@ -70,6 +70,7 @@ ENTRY(cpu_sa1100_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_sa1100_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
|
@ -82,6 +83,8 @@ ENTRY(cpu_sa1100_reset)
|
|||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_sa1100_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_sa1100_do_idle(type)
|
||||
|
|
|
@ -55,6 +55,7 @@ ENTRY(cpu_v6_proc_fin)
|
|||
* - loc - location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_v6_reset)
|
||||
mrc p15, 0, r1, c1, c0, 0 @ ctrl register
|
||||
bic r1, r1, #0x1 @ ...............m
|
||||
|
@ -62,6 +63,8 @@ ENTRY(cpu_v6_reset)
|
|||
mov r1, #0
|
||||
mcr p15, 0, r1, c7, c5, 4 @ ISB
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_v6_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_v6_do_idle()
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* arch/arm/mm/proc-v7-2level.S
|
||||
*
|
||||
* Copyright (C) 2001 Deep Blue Solutions Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#define TTB_S (1 << 1)
|
||||
#define TTB_RGN_NC (0 << 3)
|
||||
#define TTB_RGN_OC_WBWA (1 << 3)
|
||||
#define TTB_RGN_OC_WT (2 << 3)
|
||||
#define TTB_RGN_OC_WB (3 << 3)
|
||||
#define TTB_NOS (1 << 5)
|
||||
#define TTB_IRGN_NC ((0 << 0) | (0 << 6))
|
||||
#define TTB_IRGN_WBWA ((0 << 0) | (1 << 6))
|
||||
#define TTB_IRGN_WT ((1 << 0) | (0 << 6))
|
||||
#define TTB_IRGN_WB ((1 << 0) | (1 << 6))
|
||||
|
||||
/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
|
||||
#define TTB_FLAGS_UP TTB_IRGN_WB|TTB_RGN_OC_WB
|
||||
#define PMD_FLAGS_UP PMD_SECT_WB
|
||||
|
||||
/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
|
||||
#define TTB_FLAGS_SMP TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
|
||||
#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S
|
||||
|
||||
/*
|
||||
* cpu_v7_switch_mm(pgd_phys, tsk)
|
||||
*
|
||||
* Set the translation table base pointer to be pgd_phys
|
||||
*
|
||||
* - pgd_phys - physical address of new TTB
|
||||
*
|
||||
* It is assumed that:
|
||||
* - we are not using split page tables
|
||||
*/
|
||||
ENTRY(cpu_v7_switch_mm)
|
||||
#ifdef CONFIG_MMU
|
||||
mov r2, #0
|
||||
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
|
||||
ALT_SMP(orr r0, r0, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr r0, r0, #TTB_FLAGS_UP)
|
||||
#ifdef CONFIG_ARM_ERRATA_430973
|
||||
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_ERRATA_754322
|
||||
dsb
|
||||
#endif
|
||||
mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
|
||||
isb
|
||||
1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
|
||||
isb
|
||||
#ifdef CONFIG_ARM_ERRATA_754322
|
||||
dsb
|
||||
#endif
|
||||
mcr p15, 0, r1, c13, c0, 1 @ set context ID
|
||||
isb
|
||||
#endif
|
||||
mov pc, lr
|
||||
ENDPROC(cpu_v7_switch_mm)
|
||||
|
||||
/*
|
||||
* cpu_v7_set_pte_ext(ptep, pte)
|
||||
*
|
||||
* Set a level 2 translation table entry.
|
||||
*
|
||||
* - ptep - pointer to level 2 translation table entry
|
||||
* (hardware version is stored at +2048 bytes)
|
||||
* - pte - PTE value to store
|
||||
* - ext - value for extended PTE bits
|
||||
*/
|
||||
ENTRY(cpu_v7_set_pte_ext)
|
||||
#ifdef CONFIG_MMU
|
||||
str r1, [r0] @ linux version
|
||||
|
||||
bic r3, r1, #0x000003f0
|
||||
bic r3, r3, #PTE_TYPE_MASK
|
||||
orr r3, r3, r2
|
||||
orr r3, r3, #PTE_EXT_AP0 | 2
|
||||
|
||||
tst r1, #1 << 4
|
||||
orrne r3, r3, #PTE_EXT_TEX(1)
|
||||
|
||||
eor r1, r1, #L_PTE_DIRTY
|
||||
tst r1, #L_PTE_RDONLY | L_PTE_DIRTY
|
||||
orrne r3, r3, #PTE_EXT_APX
|
||||
|
||||
tst r1, #L_PTE_USER
|
||||
orrne r3, r3, #PTE_EXT_AP1
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
@ allow kernel read/write access to read-only user pages
|
||||
tstne r3, #PTE_EXT_APX
|
||||
bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
|
||||
#endif
|
||||
|
||||
tst r1, #L_PTE_XN
|
||||
orrne r3, r3, #PTE_EXT_XN
|
||||
|
||||
tst r1, #L_PTE_YOUNG
|
||||
tstne r1, #L_PTE_PRESENT
|
||||
moveq r3, #0
|
||||
|
||||
ARM( str r3, [r0, #2048]! )
|
||||
THUMB( add r0, r0, #2048 )
|
||||
THUMB( str r3, [r0] )
|
||||
mcr p15, 0, r0, c7, c10, 1 @ flush_pte
|
||||
#endif
|
||||
mov pc, lr
|
||||
ENDPROC(cpu_v7_set_pte_ext)
|
||||
|
||||
/*
|
||||
* Memory region attributes with SCTLR.TRE=1
|
||||
*
|
||||
* n = TEX[0],C,B
|
||||
* TR = PRRR[2n+1:2n] - memory type
|
||||
* IR = NMRR[2n+1:2n] - inner cacheable property
|
||||
* OR = NMRR[2n+17:2n+16] - outer cacheable property
|
||||
*
|
||||
* n TR IR OR
|
||||
* UNCACHED 000 00
|
||||
* BUFFERABLE 001 10 00 00
|
||||
* WRITETHROUGH 010 10 10 10
|
||||
* WRITEBACK 011 10 11 11
|
||||
* reserved 110
|
||||
* WRITEALLOC 111 10 01 01
|
||||
* DEV_SHARED 100 01
|
||||
* DEV_NONSHARED 100 01
|
||||
* DEV_WC 001 10
|
||||
* DEV_CACHED 011 10
|
||||
*
|
||||
* Other attributes:
|
||||
*
|
||||
* DS0 = PRRR[16] = 0 - device shareable property
|
||||
* DS1 = PRRR[17] = 1 - device shareable property
|
||||
* NS0 = PRRR[18] = 0 - normal shareable property
|
||||
* NS1 = PRRR[19] = 1 - normal shareable property
|
||||
* NOS = PRRR[24+n] = 1 - not outer shareable
|
||||
*/
|
||||
.equ PRRR, 0xff0a81a8
|
||||
.equ NMRR, 0x40e040e0
|
||||
|
||||
/*
|
||||
* Macro for setting up the TTBRx and TTBCR registers.
|
||||
* - \ttb0 and \ttb1 updated with the corresponding flags.
|
||||
*/
|
||||
.macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp
|
||||
mcr p15, 0, \zero, c2, c0, 2 @ TTB control register
|
||||
ALT_SMP(orr \ttbr0, \ttbr0, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr \ttbr0, \ttbr0, #TTB_FLAGS_UP)
|
||||
ALT_SMP(orr \ttbr1, \ttbr1, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr \ttbr1, \ttbr1, #TTB_FLAGS_UP)
|
||||
mcr p15, 0, \ttbr1, c2, c0, 1 @ load TTB1
|
||||
.endm
|
||||
|
||||
__CPUINIT
|
||||
|
||||
/* AT
|
||||
* TFR EV X F I D LR S
|
||||
* .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM
|
||||
* rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
|
||||
* 1 0 110 0011 1100 .111 1101 < we want
|
||||
*/
|
||||
.align 2
|
||||
.type v7_crval, #object
|
||||
v7_crval:
|
||||
crval clear=0x0120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c
|
||||
|
||||
.previous
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* arch/arm/mm/proc-v7-3level.S
|
||||
*
|
||||
* Copyright (C) 2001 Deep Blue Solutions Ltd.
|
||||
* Copyright (C) 2011 ARM Ltd.
|
||||
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
||||
* based on arch/arm/mm/proc-v7-2level.S
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define TTB_IRGN_NC (0 << 8)
|
||||
#define TTB_IRGN_WBWA (1 << 8)
|
||||
#define TTB_IRGN_WT (2 << 8)
|
||||
#define TTB_IRGN_WB (3 << 8)
|
||||
#define TTB_RGN_NC (0 << 10)
|
||||
#define TTB_RGN_OC_WBWA (1 << 10)
|
||||
#define TTB_RGN_OC_WT (2 << 10)
|
||||
#define TTB_RGN_OC_WB (3 << 10)
|
||||
#define TTB_S (3 << 12)
|
||||
#define TTB_EAE (1 << 31)
|
||||
|
||||
/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
|
||||
#define TTB_FLAGS_UP (TTB_IRGN_WB|TTB_RGN_OC_WB)
|
||||
#define PMD_FLAGS_UP (PMD_SECT_WB)
|
||||
|
||||
/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
|
||||
#define TTB_FLAGS_SMP (TTB_IRGN_WBWA|TTB_S|TTB_RGN_OC_WBWA)
|
||||
#define PMD_FLAGS_SMP (PMD_SECT_WBWA|PMD_SECT_S)
|
||||
|
||||
/*
|
||||
* cpu_v7_switch_mm(pgd_phys, tsk)
|
||||
*
|
||||
* Set the translation table base pointer to be pgd_phys (physical address of
|
||||
* the new TTB).
|
||||
*/
|
||||
ENTRY(cpu_v7_switch_mm)
|
||||
#ifdef CONFIG_MMU
|
||||
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
|
||||
and r3, r1, #0xff
|
||||
mov r3, r3, lsl #(48 - 32) @ ASID
|
||||
mcrr p15, 0, r0, r3, c2 @ set TTB 0
|
||||
isb
|
||||
#endif
|
||||
mov pc, lr
|
||||
ENDPROC(cpu_v7_switch_mm)
|
||||
|
||||
/*
|
||||
* cpu_v7_set_pte_ext(ptep, pte)
|
||||
*
|
||||
* Set a level 2 translation table entry.
|
||||
* - ptep - pointer to level 3 translation table entry
|
||||
* - pte - PTE value to store (64-bit in r2 and r3)
|
||||
*/
|
||||
ENTRY(cpu_v7_set_pte_ext)
|
||||
#ifdef CONFIG_MMU
|
||||
tst r2, #L_PTE_PRESENT
|
||||
beq 1f
|
||||
tst r3, #1 << (55 - 32) @ L_PTE_DIRTY
|
||||
orreq r2, #L_PTE_RDONLY
|
||||
1: strd r2, r3, [r0]
|
||||
mcr p15, 0, r0, c7, c10, 1 @ flush_pte
|
||||
#endif
|
||||
mov pc, lr
|
||||
ENDPROC(cpu_v7_set_pte_ext)
|
||||
|
||||
/*
|
||||
* Memory region attributes for LPAE (defined in pgtable-3level.h):
|
||||
*
|
||||
* n = AttrIndx[2:0]
|
||||
*
|
||||
* n MAIR
|
||||
* UNCACHED 000 00000000
|
||||
* BUFFERABLE 001 01000100
|
||||
* DEV_WC 001 01000100
|
||||
* WRITETHROUGH 010 10101010
|
||||
* WRITEBACK 011 11101110
|
||||
* DEV_CACHED 011 11101110
|
||||
* DEV_SHARED 100 00000100
|
||||
* DEV_NONSHARED 100 00000100
|
||||
* unused 101
|
||||
* unused 110
|
||||
* WRITEALLOC 111 11111111
|
||||
*/
|
||||
.equ PRRR, 0xeeaa4400 @ MAIR0
|
||||
.equ NMRR, 0xff000004 @ MAIR1
|
||||
|
||||
/*
|
||||
* Macro for setting up the TTBRx and TTBCR registers.
|
||||
* - \ttbr1 updated.
|
||||
*/
|
||||
.macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp
|
||||
ldr \tmp, =swapper_pg_dir @ swapper_pg_dir virtual address
|
||||
cmp \ttbr1, \tmp @ PHYS_OFFSET > PAGE_OFFSET? (branch below)
|
||||
mrc p15, 0, \tmp, c2, c0, 2 @ TTB control register
|
||||
orr \tmp, \tmp, #TTB_EAE
|
||||
ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr \tmp, \tmp, #TTB_FLAGS_UP)
|
||||
ALT_SMP(orr \tmp, \tmp, #TTB_FLAGS_SMP << 16)
|
||||
ALT_UP(orr \tmp, \tmp, #TTB_FLAGS_UP << 16)
|
||||
/*
|
||||
* TTBR0/TTBR1 split (PAGE_OFFSET):
|
||||
* 0x40000000: T0SZ = 2, T1SZ = 0 (not used)
|
||||
* 0x80000000: T0SZ = 0, T1SZ = 1
|
||||
* 0xc0000000: T0SZ = 0, T1SZ = 2
|
||||
*
|
||||
* Only use this feature if PHYS_OFFSET <= PAGE_OFFSET, otherwise
|
||||
* booting secondary CPUs would end up using TTBR1 for the identity
|
||||
* mapping set up in TTBR0.
|
||||
*/
|
||||
bhi 9001f @ PHYS_OFFSET > PAGE_OFFSET?
|
||||
orr \tmp, \tmp, #(((PAGE_OFFSET >> 30) - 1) << 16) @ TTBCR.T1SZ
|
||||
#if defined CONFIG_VMSPLIT_2G
|
||||
/* PAGE_OFFSET == 0x80000000, T1SZ == 1 */
|
||||
add \ttbr1, \ttbr1, #1 << 4 @ skip two L1 entries
|
||||
#elif defined CONFIG_VMSPLIT_3G
|
||||
/* PAGE_OFFSET == 0xc0000000, T1SZ == 2 */
|
||||
add \ttbr1, \ttbr1, #4096 * (1 + 3) @ only L2 used, skip pgd+3*pmd
|
||||
#endif
|
||||
/* CONFIG_VMSPLIT_1G does not need TTBR1 adjustment */
|
||||
9001: mcr p15, 0, \tmp, c2, c0, 2 @ TTB control register
|
||||
mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
|
||||
.endm
|
||||
|
||||
__CPUINIT
|
||||
|
||||
/*
|
||||
* AT
|
||||
* TFR EV X F IHD LR S
|
||||
* .EEE ..EE PUI. .TAT 4RVI ZWRS BLDP WCAM
|
||||
* rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
|
||||
* 11 0 110 1 0011 1100 .111 1101 < we want
|
||||
*/
|
||||
.align 2
|
||||
.type v7_crval, #object
|
||||
v7_crval:
|
||||
crval clear=0x0120c302, mmuset=0x30c23c7d, ucset=0x00c01c7c
|
||||
|
||||
.previous
|
|
@ -19,24 +19,11 @@
|
|||
|
||||
#include "proc-macros.S"
|
||||
|
||||
#define TTB_S (1 << 1)
|
||||
#define TTB_RGN_NC (0 << 3)
|
||||
#define TTB_RGN_OC_WBWA (1 << 3)
|
||||
#define TTB_RGN_OC_WT (2 << 3)
|
||||
#define TTB_RGN_OC_WB (3 << 3)
|
||||
#define TTB_NOS (1 << 5)
|
||||
#define TTB_IRGN_NC ((0 << 0) | (0 << 6))
|
||||
#define TTB_IRGN_WBWA ((0 << 0) | (1 << 6))
|
||||
#define TTB_IRGN_WT ((1 << 0) | (0 << 6))
|
||||
#define TTB_IRGN_WB ((1 << 0) | (1 << 6))
|
||||
|
||||
/* PTWs cacheable, inner WB not shareable, outer WB not shareable */
|
||||
#define TTB_FLAGS_UP TTB_IRGN_WB|TTB_RGN_OC_WB
|
||||
#define PMD_FLAGS_UP PMD_SECT_WB
|
||||
|
||||
/* PTWs cacheable, inner WBWA shareable, outer WBWA not shareable */
|
||||
#define TTB_FLAGS_SMP TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
|
||||
#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S
|
||||
#ifdef CONFIG_ARM_LPAE
|
||||
#include "proc-v7-3level.S"
|
||||
#else
|
||||
#include "proc-v7-2level.S"
|
||||
#endif
|
||||
|
||||
ENTRY(cpu_v7_proc_init)
|
||||
mov pc, lr
|
||||
|
@ -63,6 +50,7 @@ ENDPROC(cpu_v7_proc_fin)
|
|||
* caches disabled.
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_v7_reset)
|
||||
mrc p15, 0, r1, c1, c0, 0 @ ctrl register
|
||||
bic r1, r1, #0x1 @ ...............m
|
||||
|
@ -71,6 +59,7 @@ ENTRY(cpu_v7_reset)
|
|||
isb
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_v7_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_v7_do_idle()
|
||||
|
@ -97,127 +86,12 @@ ENTRY(cpu_v7_dcache_clean_area)
|
|||
mov pc, lr
|
||||
ENDPROC(cpu_v7_dcache_clean_area)
|
||||
|
||||
/*
|
||||
* cpu_v7_switch_mm(pgd_phys, tsk)
|
||||
*
|
||||
* Set the translation table base pointer to be pgd_phys
|
||||
*
|
||||
* - pgd_phys - physical address of new TTB
|
||||
*
|
||||
* It is assumed that:
|
||||
* - we are not using split page tables
|
||||
*/
|
||||
ENTRY(cpu_v7_switch_mm)
|
||||
#ifdef CONFIG_MMU
|
||||
mov r2, #0
|
||||
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
|
||||
ALT_SMP(orr r0, r0, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr r0, r0, #TTB_FLAGS_UP)
|
||||
#ifdef CONFIG_ARM_ERRATA_430973
|
||||
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_ERRATA_754322
|
||||
dsb
|
||||
#endif
|
||||
mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
|
||||
isb
|
||||
1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
|
||||
isb
|
||||
#ifdef CONFIG_ARM_ERRATA_754322
|
||||
dsb
|
||||
#endif
|
||||
mcr p15, 0, r1, c13, c0, 1 @ set context ID
|
||||
isb
|
||||
#endif
|
||||
mov pc, lr
|
||||
ENDPROC(cpu_v7_switch_mm)
|
||||
|
||||
/*
|
||||
* cpu_v7_set_pte_ext(ptep, pte)
|
||||
*
|
||||
* Set a level 2 translation table entry.
|
||||
*
|
||||
* - ptep - pointer to level 2 translation table entry
|
||||
* (hardware version is stored at +2048 bytes)
|
||||
* - pte - PTE value to store
|
||||
* - ext - value for extended PTE bits
|
||||
*/
|
||||
ENTRY(cpu_v7_set_pte_ext)
|
||||
#ifdef CONFIG_MMU
|
||||
str r1, [r0] @ linux version
|
||||
|
||||
bic r3, r1, #0x000003f0
|
||||
bic r3, r3, #PTE_TYPE_MASK
|
||||
orr r3, r3, r2
|
||||
orr r3, r3, #PTE_EXT_AP0 | 2
|
||||
|
||||
tst r1, #1 << 4
|
||||
orrne r3, r3, #PTE_EXT_TEX(1)
|
||||
|
||||
eor r1, r1, #L_PTE_DIRTY
|
||||
tst r1, #L_PTE_RDONLY | L_PTE_DIRTY
|
||||
orrne r3, r3, #PTE_EXT_APX
|
||||
|
||||
tst r1, #L_PTE_USER
|
||||
orrne r3, r3, #PTE_EXT_AP1
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
@ allow kernel read/write access to read-only user pages
|
||||
tstne r3, #PTE_EXT_APX
|
||||
bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
|
||||
#endif
|
||||
|
||||
tst r1, #L_PTE_XN
|
||||
orrne r3, r3, #PTE_EXT_XN
|
||||
|
||||
tst r1, #L_PTE_YOUNG
|
||||
tstne r1, #L_PTE_PRESENT
|
||||
moveq r3, #0
|
||||
|
||||
ARM( str r3, [r0, #2048]! )
|
||||
THUMB( add r0, r0, #2048 )
|
||||
THUMB( str r3, [r0] )
|
||||
mcr p15, 0, r0, c7, c10, 1 @ flush_pte
|
||||
#endif
|
||||
mov pc, lr
|
||||
ENDPROC(cpu_v7_set_pte_ext)
|
||||
|
||||
string cpu_v7_name, "ARMv7 Processor"
|
||||
.align
|
||||
|
||||
/*
|
||||
* Memory region attributes with SCTLR.TRE=1
|
||||
*
|
||||
* n = TEX[0],C,B
|
||||
* TR = PRRR[2n+1:2n] - memory type
|
||||
* IR = NMRR[2n+1:2n] - inner cacheable property
|
||||
* OR = NMRR[2n+17:2n+16] - outer cacheable property
|
||||
*
|
||||
* n TR IR OR
|
||||
* UNCACHED 000 00
|
||||
* BUFFERABLE 001 10 00 00
|
||||
* WRITETHROUGH 010 10 10 10
|
||||
* WRITEBACK 011 10 11 11
|
||||
* reserved 110
|
||||
* WRITEALLOC 111 10 01 01
|
||||
* DEV_SHARED 100 01
|
||||
* DEV_NONSHARED 100 01
|
||||
* DEV_WC 001 10
|
||||
* DEV_CACHED 011 10
|
||||
*
|
||||
* Other attributes:
|
||||
*
|
||||
* DS0 = PRRR[16] = 0 - device shareable property
|
||||
* DS1 = PRRR[17] = 1 - device shareable property
|
||||
* NS0 = PRRR[18] = 0 - normal shareable property
|
||||
* NS1 = PRRR[19] = 1 - normal shareable property
|
||||
* NOS = PRRR[24+n] = 1 - not outer shareable
|
||||
*/
|
||||
.equ PRRR, 0xff0a81a8
|
||||
.equ NMRR, 0x40e040e0
|
||||
|
||||
/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
|
||||
.globl cpu_v7_suspend_size
|
||||
.equ cpu_v7_suspend_size, 4 * 7
|
||||
.equ cpu_v7_suspend_size, 4 * 8
|
||||
#ifdef CONFIG_ARM_CPU_SUSPEND
|
||||
ENTRY(cpu_v7_do_suspend)
|
||||
stmfd sp!, {r4 - r10, lr}
|
||||
|
@ -226,10 +100,11 @@ ENTRY(cpu_v7_do_suspend)
|
|||
stmia r0!, {r4 - r5}
|
||||
mrc p15, 0, r6, c3, c0, 0 @ Domain ID
|
||||
mrc p15, 0, r7, c2, c0, 1 @ TTB 1
|
||||
mrc p15, 0, r11, c2, c0, 2 @ TTB control register
|
||||
mrc p15, 0, r8, c1, c0, 0 @ Control register
|
||||
mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register
|
||||
mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
|
||||
stmia r0, {r6 - r10}
|
||||
stmia r0, {r6 - r11}
|
||||
ldmfd sp!, {r4 - r10, pc}
|
||||
ENDPROC(cpu_v7_do_suspend)
|
||||
|
||||
|
@ -241,13 +116,15 @@ ENTRY(cpu_v7_do_resume)
|
|||
ldmia r0!, {r4 - r5}
|
||||
mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
||||
mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID
|
||||
ldmia r0, {r6 - r10}
|
||||
ldmia r0, {r6 - r11}
|
||||
mcr p15, 0, r6, c3, c0, 0 @ Domain ID
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr r1, r1, #TTB_FLAGS_UP)
|
||||
#endif
|
||||
mcr p15, 0, r1, c2, c0, 0 @ TTB 0
|
||||
mcr p15, 0, r7, c2, c0, 1 @ TTB 1
|
||||
mcr p15, 0, ip, c2, c0, 2 @ TTB control register
|
||||
mcr p15, 0, r11, c2, c0, 2 @ TTB control register
|
||||
mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register
|
||||
teq r4, r9 @ Is it already set?
|
||||
mcrne p15, 0, r9, c1, c0, 1 @ No, so write it
|
||||
|
@ -377,12 +254,7 @@ __v7_setup:
|
|||
dsb
|
||||
#ifdef CONFIG_MMU
|
||||
mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
|
||||
mcr p15, 0, r10, c2, c0, 2 @ TTB control register
|
||||
ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr r4, r4, #TTB_FLAGS_UP)
|
||||
ALT_SMP(orr r8, r8, #TTB_FLAGS_SMP)
|
||||
ALT_UP(orr r8, r8, #TTB_FLAGS_UP)
|
||||
mcr p15, 0, r8, c2, c0, 1 @ load TTB1
|
||||
v7_ttb_setup r10, r4, r8, r5 @ TTBCR, TTBRx setup
|
||||
ldr r5, =PRRR @ PRRR
|
||||
ldr r6, =NMRR @ NMRR
|
||||
mcr p15, 0, r5, c10, c2, 0 @ write PRRR
|
||||
|
@ -404,16 +276,7 @@ __v7_setup:
|
|||
mov pc, lr @ return to head.S:__ret
|
||||
ENDPROC(__v7_setup)
|
||||
|
||||
/* AT
|
||||
* TFR EV X F I D LR S
|
||||
* .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM
|
||||
* rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
|
||||
* 1 0 110 0011 1100 .111 1101 < we want
|
||||
*/
|
||||
.type v7_crval, #object
|
||||
v7_crval:
|
||||
crval clear=0x0120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c
|
||||
|
||||
.align 2
|
||||
__v7_setup_stack:
|
||||
.space 4 * 11 @ 11 registers
|
||||
|
||||
|
@ -435,11 +298,11 @@ __v7_setup_stack:
|
|||
*/
|
||||
.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0
|
||||
ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
|
||||
PMD_FLAGS_SMP | \mm_mmuflags)
|
||||
PMD_SECT_AF | PMD_FLAGS_SMP | \mm_mmuflags)
|
||||
ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
|
||||
PMD_FLAGS_UP | \mm_mmuflags)
|
||||
.long PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_AP_WRITE | \
|
||||
PMD_SECT_AP_READ | \io_mmuflags
|
||||
PMD_SECT_AF | PMD_FLAGS_UP | \mm_mmuflags)
|
||||
.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | \
|
||||
PMD_SECT_AP_READ | PMD_SECT_AF | \io_mmuflags
|
||||
W(b) \initfunc
|
||||
.long cpu_arch_name
|
||||
.long cpu_elf_name
|
||||
|
@ -452,6 +315,7 @@ __v7_setup_stack:
|
|||
.long v7_cache_fns
|
||||
.endm
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
/*
|
||||
* ARM Ltd. Cortex A5 processor.
|
||||
*/
|
||||
|
@ -471,6 +335,7 @@ __v7_ca9mp_proc_info:
|
|||
.long 0xff0ffff0
|
||||
__v7_proc __v7_ca9mp_setup
|
||||
.size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
|
||||
#endif /* CONFIG_ARM_LPAE */
|
||||
|
||||
/*
|
||||
* ARM Ltd. Cortex A15 processor.
|
||||
|
|
|
@ -105,6 +105,7 @@ ENTRY(cpu_xsc3_proc_fin)
|
|||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_xsc3_reset)
|
||||
mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
|
||||
msr cpsr_c, r1 @ reset CPSR
|
||||
|
@ -119,6 +120,8 @@ ENTRY(cpu_xsc3_reset)
|
|||
@ already containing those two last instructions to survive.
|
||||
mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_xsc3_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_xsc3_do_idle()
|
||||
|
|
|
@ -142,6 +142,7 @@ ENTRY(cpu_xscale_proc_fin)
|
|||
* Beware PXA270 erratum E7.
|
||||
*/
|
||||
.align 5
|
||||
.pushsection .idmap.text, "ax"
|
||||
ENTRY(cpu_xscale_reset)
|
||||
mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
|
||||
msr cpsr_c, r1 @ reset CPSR
|
||||
|
@ -160,6 +161,8 @@ ENTRY(cpu_xscale_reset)
|
|||
@ already containing those two last instructions to survive.
|
||||
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
|
||||
mov pc, r0
|
||||
ENDPROC(cpu_xscale_reset)
|
||||
.popsection
|
||||
|
||||
/*
|
||||
* cpu_xscale_do_idle()
|
||||
|
|
|
@ -21,7 +21,12 @@
|
|||
#include <linux/platform_data/tegra_usb.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <mach/usb_phy.h>
|
||||
#include <mach/iomap.h>
|
||||
|
||||
#define TEGRA_USB_DMA_ALIGN 32
|
||||
|
||||
|
@ -574,6 +579,35 @@ static const struct hc_driver tegra_ehci_hc_driver = {
|
|||
.port_handed_over = ehci_port_handed_over,
|
||||
};
|
||||
|
||||
static int setup_vbus_gpio(struct platform_device *pdev)
|
||||
{
|
||||
int err = 0;
|
||||
int gpio;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
return 0;
|
||||
|
||||
gpio = of_get_named_gpio(pdev->dev.of_node, "nvidia,vbus-gpio", 0);
|
||||
if (!gpio_is_valid(gpio))
|
||||
return 0;
|
||||
|
||||
err = gpio_request(gpio, "vbus_gpio");
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "can't request vbus gpio %d", gpio);
|
||||
return err;
|
||||
}
|
||||
err = gpio_direction_output(gpio, 1);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "can't enable vbus\n");
|
||||
return err;
|
||||
}
|
||||
gpio_set_value(gpio, 1);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static int tegra_ehci_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
|
@ -590,6 +624,15 @@ static int tegra_ehci_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Right now device-tree probed devices don't get dma_mask set.
|
||||
* Since shared usb code relies on it, set it here for now.
|
||||
* Once we have dma capability bindings this can go away.
|
||||
*/
|
||||
if (!pdev->dev.dma_mask)
|
||||
pdev->dev.dma_mask = &tegra_ehci_dma_mask;
|
||||
|
||||
setup_vbus_gpio(pdev);
|
||||
|
||||
tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
|
||||
if (!tegra)
|
||||
return -ENOMEM;
|
||||
|
@ -640,6 +683,28 @@ static int tegra_ehci_probe(struct platform_device *pdev)
|
|||
goto fail_io;
|
||||
}
|
||||
|
||||
/* This is pretty ugly and needs to be fixed when we do only
|
||||
* device-tree probing. Old code relies on the platform_device
|
||||
* numbering that we lack for device-tree-instantiated devices.
|
||||
*/
|
||||
if (instance < 0) {
|
||||
switch (res->start) {
|
||||
case TEGRA_USB_BASE:
|
||||
instance = 0;
|
||||
break;
|
||||
case TEGRA_USB2_BASE:
|
||||
instance = 1;
|
||||
break;
|
||||
case TEGRA_USB3_BASE:
|
||||
instance = 2;
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
dev_err(&pdev->dev, "unknown usb instance\n");
|
||||
goto fail_phy;
|
||||
}
|
||||
}
|
||||
|
||||
tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
|
||||
TEGRA_USB_PHY_MODE_HOST);
|
||||
if (IS_ERR(tegra->phy)) {
|
||||
|
@ -773,6 +838,11 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
|
|||
hcd->driver->shutdown(hcd);
|
||||
}
|
||||
|
||||
static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
|
||||
{ .compatible = "nvidia,tegra20-ehci", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver tegra_ehci_driver = {
|
||||
.probe = tegra_ehci_probe,
|
||||
.remove = tegra_ehci_remove,
|
||||
|
@ -783,5 +853,6 @@ static struct platform_driver tegra_ehci_driver = {
|
|||
.shutdown = tegra_ehci_hcd_shutdown,
|
||||
.driver = {
|
||||
.name = "tegra-ehci",
|
||||
.of_match_table = tegra_ehci_of_match,
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue