Skip to content

Instantly share code, notes, and snippets.

@orumin
Created May 29, 2014 04:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save orumin/49141f6fb66994a227b6 to your computer and use it in GitHub Desktop.
Save orumin/49141f6fb66994a227b6 to your computer and use it in GitHub Desktop.
different with linux-3.12 and linux-rpi-3.12.y
This file has been truncated, but you can view the full file.
diff -Nur linux/arch/alpha/lib/csum_partial_copy.c rpi/arch/alpha/lib/csum_partial_copy.c
--- linux/arch/alpha/lib/csum_partial_copy.c 2014-05-29 12:18:16.434566267 +0900
+++ rpi/arch/alpha/lib/csum_partial_copy.c 2014-05-29 11:49:03.587970317 +0900
@@ -378,6 +378,11 @@
__wsum
csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
{
- return csum_partial_copy_from_user((__force const void __user *)src,
- dst, len, sum, NULL);
+ __wsum checksum;
+ mm_segment_t oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ checksum = csum_partial_copy_from_user((__force const void __user *)src,
+ dst, len, sum, NULL);
+ set_fs(oldfs);
+ return checksum;
}
diff -Nur linux/arch/arc/boot/dts/nsimosci.dts rpi/arch/arc/boot/dts/nsimosci.dts
--- linux/arch/arc/boot/dts/nsimosci.dts 2014-05-29 12:18:16.438566242 +0900
+++ rpi/arch/arc/boot/dts/nsimosci.dts 2014-05-29 11:49:03.600970208 +0900
@@ -11,13 +11,16 @@
/ {
compatible = "snps,nsimosci";
- clock-frequency = <80000000>; /* 80 MHZ */
+ clock-frequency = <20000000>; /* 20 MHZ */
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
chosen {
- bootargs = "console=tty0 consoleblank=0";
+ /* this is for console on PGU */
+ /* bootargs = "console=tty0 consoleblank=0"; */
+ /* this is for console on serial */
+ bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug";
};
aliases {
@@ -44,15 +47,14 @@
};
uart0: serial@c0000000 {
- compatible = "snps,dw-apb-uart";
+ compatible = "ns8250";
reg = <0xc0000000 0x2000>;
interrupts = <11>;
- #clock-frequency = <80000000>;
clock-frequency = <3686400>;
baud = <115200>;
reg-shift = <2>;
reg-io-width = <4>;
- status = "okay";
+ no-loopback-test = <1>;
};
pgu0: pgu@c9000000 {
diff -Nur linux/arch/arc/configs/nsimosci_defconfig rpi/arch/arc/configs/nsimosci_defconfig
--- linux/arch/arc/configs/nsimosci_defconfig 2014-05-29 12:18:16.438566242 +0900
+++ rpi/arch/arc/configs/nsimosci_defconfig 2014-05-29 11:49:03.600970208 +0900
@@ -54,6 +54,7 @@
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_ARC=y
CONFIG_SERIAL_ARC_CONSOLE=y
# CONFIG_HW_RANDOM is not set
diff -Nur linux/arch/arc/kernel/entry.S rpi/arch/arc/kernel/entry.S
--- linux/arch/arc/kernel/entry.S 2014-05-29 12:18:16.484565954 +0900
+++ rpi/arch/arc/kernel/entry.S 2014-05-29 11:49:03.616970073 +0900
@@ -610,11 +610,13 @@
resume_kernel_mode:
-#ifdef CONFIG_PREEMPT
-
- ; This is a must for preempt_schedule_irq()
+ ; Disable Interrupts from this point on
+ ; CONFIG_PREEMPT: This is a must for preempt_schedule_irq()
+ ; !CONFIG_PREEMPT: To ensure restore_regs is intr safe
IRQ_DISABLE r9
+#ifdef CONFIG_PREEMPT
+
; Can't preempt if preemption disabled
GET_CURR_THR_INFO_FROM_SP r10
ld r8, [r10, THREAD_INFO_PREEMPT_COUNT]
diff -Nur linux/arch/arc/plat-arcfpga/Kconfig rpi/arch/arc/plat-arcfpga/Kconfig
--- linux/arch/arc/plat-arcfpga/Kconfig 2014-05-29 12:18:16.494565892 +0900
+++ rpi/arch/arc/plat-arcfpga/Kconfig 2014-05-29 11:49:03.626969989 +0900
@@ -33,7 +33,6 @@
bool "ARC SMP Extensions (ISS Models only)"
default n
depends on SMP
- select ARC_HAS_COH_RTSC
help
SMP Extensions to ARC700, in a "simulation only" Model, supported in
ARC ISS (Instruction Set Simulator).
diff -Nur linux/arch/arm/boot/dts/am335x-bone-common.dtsi rpi/arch/arm/boot/dts/am335x-bone-common.dtsi
--- linux/arch/arm/boot/dts/am335x-bone-common.dtsi 2014-05-29 12:18:16.530565666 +0900
+++ rpi/arch/arm/boot/dts/am335x-bone-common.dtsi 2014-05-29 11:49:03.637969897 +0900
@@ -120,7 +120,7 @@
musb: usb@47400000 {
status = "okay";
- control@44e10000 {
+ control@44e10620 {
status = "okay";
};
@@ -141,7 +141,7 @@
dr_mode = "host";
};
- dma-controller@07402000 {
+ dma-controller@47402000 {
status = "okay";
};
};
diff -Nur linux/arch/arm/boot/dts/am335x-evm.dts rpi/arch/arm/boot/dts/am335x-evm.dts
--- linux/arch/arm/boot/dts/am335x-evm.dts 2014-05-29 12:18:16.532565654 +0900
+++ rpi/arch/arm/boot/dts/am335x-evm.dts 2014-05-29 11:49:03.638969889 +0900
@@ -174,7 +174,7 @@
musb: usb@47400000 {
status = "okay";
- control@44e10000 {
+ control@44e10620 {
status = "okay";
};
@@ -195,7 +195,7 @@
dr_mode = "host";
};
- dma-controller@07402000 {
+ dma-controller@47402000 {
status = "okay";
};
};
diff -Nur linux/arch/arm/boot/dts/am335x-evmsk.dts rpi/arch/arm/boot/dts/am335x-evmsk.dts
--- linux/arch/arm/boot/dts/am335x-evmsk.dts 2014-05-29 12:18:16.533565648 +0900
+++ rpi/arch/arm/boot/dts/am335x-evmsk.dts 2014-05-29 11:49:03.638969889 +0900
@@ -211,7 +211,7 @@
musb: usb@47400000 {
status = "okay";
- control@44e10000 {
+ control@44e10620 {
status = "okay";
};
diff -Nur linux/arch/arm/boot/dts/am33xx.dtsi rpi/arch/arm/boot/dts/am33xx.dtsi
--- linux/arch/arm/boot/dts/am33xx.dtsi 2014-05-29 12:18:16.534565641 +0900
+++ rpi/arch/arm/boot/dts/am33xx.dtsi 2014-05-29 11:49:03.638969889 +0900
@@ -346,7 +346,7 @@
ti,hwmods = "usb_otg_hs";
status = "disabled";
- ctrl_mod: control@44e10000 {
+ ctrl_mod: control@44e10620 {
compatible = "ti,am335x-usb-ctrl-module";
reg = <0x44e10620 0x10
0x44e10648 0x4>;
@@ -449,7 +449,7 @@
"tx14", "tx15";
};
- cppi41dma: dma-controller@07402000 {
+ cppi41dma: dma-controller@47402000 {
compatible = "ti,am3359-cppi41";
reg = <0x47400000 0x1000
0x47402000 0x1000
diff -Nur linux/arch/arm/boot/dts/armada-370-db.dts rpi/arch/arm/boot/dts/armada-370-db.dts
--- linux/arch/arm/boot/dts/armada-370-db.dts 2014-05-29 12:18:16.536565629 +0900
+++ rpi/arch/arm/boot/dts/armada-370-db.dts 2014-05-29 11:49:03.640969872 +0900
@@ -99,22 +99,22 @@
spi-max-frequency = <50000000>;
};
};
+ };
- pcie-controller {
+ pcie-controller {
+ status = "okay";
+ /*
+ * The two PCIe units are accessible through
+ * both standard PCIe slots and mini-PCIe
+ * slots on the board.
+ */
+ pcie@1,0 {
+ /* Port 0, Lane 0 */
+ status = "okay";
+ };
+ pcie@2,0 {
+ /* Port 1, Lane 0 */
status = "okay";
- /*
- * The two PCIe units are accessible through
- * both standard PCIe slots and mini-PCIe
- * slots on the board.
- */
- pcie@1,0 {
- /* Port 0, Lane 0 */
- status = "okay";
- };
- pcie@2,0 {
- /* Port 1, Lane 0 */
- status = "okay";
- };
};
};
};
diff -Nur linux/arch/arm/boot/dts/armada-370-xp.dtsi rpi/arch/arm/boot/dts/armada-370-xp.dtsi
--- linux/arch/arm/boot/dts/armada-370-xp.dtsi 2014-05-29 12:18:16.544565579 +0900
+++ rpi/arch/arm/boot/dts/armada-370-xp.dtsi 2014-05-29 11:49:03.640969872 +0900
@@ -117,7 +117,7 @@
coherency-fabric@20200 {
compatible = "marvell,coherency-fabric";
- reg = <0x20200 0xb0>, <0x21810 0x1c>;
+ reg = <0x20200 0xb0>, <0x21010 0x1c>;
};
serial@12000 {
@@ -143,7 +143,7 @@
};
sata@a0000 {
- compatible = "marvell,orion-sata";
+ compatible = "marvell,armada-370-sata";
reg = <0xa0000 0x5000>;
interrupts = <55>;
clocks = <&gateclk 15>, <&gateclk 30>;
@@ -156,6 +156,7 @@
#size-cells = <0>;
compatible = "marvell,orion-mdio";
reg = <0x72004 0x4>;
+ clocks = <&gateclk 4>;
};
eth0: ethernet@70000 {
diff -Nur linux/arch/arm/boot/dts/armada-xp-mv78230.dtsi rpi/arch/arm/boot/dts/armada-xp-mv78230.dtsi
--- linux/arch/arm/boot/dts/armada-xp-mv78230.dtsi 2014-05-29 12:18:16.551565535 +0900
+++ rpi/arch/arm/boot/dts/armada-xp-mv78230.dtsi 2014-05-29 11:49:03.641969863 +0900
@@ -47,7 +47,7 @@
/*
* MV78230 has 2 PCIe units Gen2.0: One unit can be
* configured as x4 or quad x1 lanes. One unit is
- * x4/x1.
+ * x1 only.
*/
pcie-controller {
compatible = "marvell,armada-xp-pcie";
@@ -61,10 +61,10 @@
ranges =
<0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */
- 0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000 /* Port 2.0 registers */
0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 /* Port 0.1 registers */
0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */
0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */
+ 0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 /* Port 1.0 registers */
0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */
0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
@@ -73,8 +73,8 @@
0x81000000 0x3 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO */
0x82000000 0x4 0 MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
0x81000000 0x4 0 MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO */
- 0x82000000 0x9 0 MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
- 0x81000000 0x9 0 MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO */>;
+ 0x82000000 0x5 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+ 0x81000000 0x5 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */>;
pcie@1,0 {
device_type = "pci";
@@ -144,20 +144,20 @@
status = "disabled";
};
- pcie@9,0 {
+ pcie@5,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
- reg = <0x4800 0 0 0 0>;
+ assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+ reg = <0x2800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
- ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
- 0x81000000 0 0 0x81000000 0x9 0 1 0>;
+ ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+ 0x81000000 0 0 0x81000000 0x5 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
- interrupt-map = <0 0 0 0 &mpic 99>;
- marvell,pcie-port = <2>;
+ interrupt-map = <0 0 0 0 &mpic 62>;
+ marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
- clocks = <&gateclk 26>;
+ clocks = <&gateclk 9>;
status = "disabled";
};
};
diff -Nur linux/arch/arm/boot/dts/armada-xp-mv78260.dtsi rpi/arch/arm/boot/dts/armada-xp-mv78260.dtsi
--- linux/arch/arm/boot/dts/armada-xp-mv78260.dtsi 2014-05-29 12:18:16.552565529 +0900
+++ rpi/arch/arm/boot/dts/armada-xp-mv78260.dtsi 2014-05-29 11:49:03.642969855 +0900
@@ -48,7 +48,7 @@
/*
* MV78260 has 3 PCIe units Gen2.0: Two units can be
* configured as x4 or quad x1 lanes. One unit is
- * x4/x1.
+ * x4 only.
*/
pcie-controller {
compatible = "marvell,armada-xp-pcie";
@@ -67,7 +67,9 @@
0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 /* Port 0.2 registers */
0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000 /* Port 0.3 registers */
0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 /* Port 1.0 registers */
- 0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000 /* Port 3.0 registers */
+ 0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000 /* Port 1.1 registers */
+ 0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000 /* Port 1.2 registers */
+ 0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000 /* Port 1.3 registers */
0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */
0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
@@ -76,10 +78,18 @@
0x81000000 0x3 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO */
0x82000000 0x4 0 MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
0x81000000 0x4 0 MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO */
- 0x82000000 0x9 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
- 0x81000000 0x9 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */
- 0x82000000 0xa 0 MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
- 0x81000000 0xa 0 MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO */>;
+
+ 0x82000000 0x5 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+ 0x81000000 0x5 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO */
+ 0x82000000 0x6 0 MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
+ 0x81000000 0x6 0 MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO */
+ 0x82000000 0x7 0 MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
+ 0x81000000 0x7 0 MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO */
+ 0x82000000 0x8 0 MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
+ 0x81000000 0x8 0 MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO */
+
+ 0x82000000 0x9 0 MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
+ 0x81000000 0x9 0 MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO */>;
pcie@1,0 {
device_type = "pci";
@@ -105,8 +115,8 @@
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
- ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
- 0x81000000 0 0 0x81000000 0x2 0 1 0>;
+ ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+ 0x81000000 0 0 0x81000000 0x2 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &mpic 59>;
marvell,pcie-port = <0>;
@@ -149,37 +159,88 @@
status = "disabled";
};
- pcie@9,0 {
+ pcie@5,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
- reg = <0x4800 0 0 0 0>;
+ assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+ reg = <0x2800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
- ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
- 0x81000000 0 0 0x81000000 0x9 0 1 0>;
+ ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+ 0x81000000 0 0 0x81000000 0x5 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
- interrupt-map = <0 0 0 0 &mpic 99>;
- marvell,pcie-port = <2>;
+ interrupt-map = <0 0 0 0 &mpic 62>;
+ marvell,pcie-port = <1>;
marvell,pcie-lane = <0>;
- clocks = <&gateclk 26>;
+ clocks = <&gateclk 9>;
status = "disabled";
};
- pcie@10,0 {
+ pcie@6,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x82000 0 0x2000>;
- reg = <0x5000 0 0 0 0>;
+ assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
+ reg = <0x3000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
- ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
- 0x81000000 0 0 0x81000000 0xa 0 1 0>;
+ ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
+ 0x81000000 0 0 0x81000000 0x6 0 1 0>;
interrupt-map-mask = <0 0 0 0>;
- interrupt-map = <0 0 0 0 &mpic 103>;
- marvell,pcie-port = <3>;
+ interrupt-map = <0 0 0 0 &mpic 63>;
+ marvell,pcie-port = <1>;
+ marvell,pcie-lane = <1>;
+ clocks = <&gateclk 10>;
+ status = "disabled";
+ };
+
+ pcie@7,0 {
+ device_type = "pci";
+ assigned-addresses = <0x82000800 0 0x88000 0 0x2000>;
+ reg = <0x3800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
+ 0x81000000 0 0 0x81000000 0x7 0 1 0>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &mpic 64>;
+ marvell,pcie-port = <1>;
+ marvell,pcie-lane = <2>;
+ clocks = <&gateclk 11>;
+ status = "disabled";
+ };
+
+ pcie@8,0 {
+ device_type = "pci";
+ assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>;
+ reg = <0x4000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
+ 0x81000000 0 0 0x81000000 0x8 0 1 0>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &mpic 65>;
+ marvell,pcie-port = <1>;
+ marvell,pcie-lane = <3>;
+ clocks = <&gateclk 12>;
+ status = "disabled";
+ };
+
+ pcie@9,0 {
+ device_type = "pci";
+ assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+ reg = <0x4800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+ 0x81000000 0 0 0x81000000 0x9 0 1 0>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &mpic 99>;
+ marvell,pcie-port = <2>;
marvell,pcie-lane = <0>;
- clocks = <&gateclk 27>;
+ clocks = <&gateclk 26>;
status = "disabled";
};
};
diff -Nur linux/arch/arm/boot/dts/at91sam9g45.dtsi rpi/arch/arm/boot/dts/at91sam9g45.dtsi
--- linux/arch/arm/boot/dts/at91sam9g45.dtsi 2014-05-29 12:18:16.565565447 +0900
+++ rpi/arch/arm/boot/dts/at91sam9g45.dtsi 2014-05-29 11:49:03.646969821 +0900
@@ -618,6 +618,7 @@
compatible = "atmel,hsmci";
reg = <0xfff80000 0x600>;
interrupts = <11 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-names = "default";
dmas = <&dma 1 AT91_DMA_CFG_PER_ID(0)>;
dma-names = "rxtx";
#address-cells = <1>;
@@ -629,6 +630,7 @@
compatible = "atmel,hsmci";
reg = <0xfffd0000 0x600>;
interrupts = <29 IRQ_TYPE_LEVEL_HIGH 0>;
+ pinctrl-names = "default";
dmas = <&dma 1 AT91_DMA_CFG_PER_ID(13)>;
dma-names = "rxtx";
#address-cells = <1>;
diff -Nur linux/arch/arm/boot/dts/bcm2835.dtsi rpi/arch/arm/boot/dts/bcm2835.dtsi
--- linux/arch/arm/boot/dts/bcm2835.dtsi 2014-05-29 12:18:16.575565385 +0900
+++ rpi/arch/arm/boot/dts/bcm2835.dtsi 2014-05-29 11:49:03.649969796 +0900
@@ -85,6 +85,8 @@
reg = <0x7e205000 0x1000>;
interrupts = <2 21>;
clocks = <&clk_i2c>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
@@ -93,6 +95,8 @@
reg = <0x7e804000 0x1000>;
interrupts = <2 21>;
clocks = <&clk_i2c>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
diff -Nur linux/arch/arm/boot/dts/cros5250-common.dtsi rpi/arch/arm/boot/dts/cros5250-common.dtsi
--- linux/arch/arm/boot/dts/cros5250-common.dtsi 2014-05-29 12:18:16.576565378 +0900
+++ rpi/arch/arm/boot/dts/cros5250-common.dtsi 2014-05-29 11:49:03.649969796 +0900
@@ -27,6 +27,13 @@
i2c2_bus: i2c2-bus {
samsung,pin-pud = <0>;
};
+
+ max77686_irq: max77686-irq {
+ samsung,pins = "gpx3-2";
+ samsung,pin-function = <0>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
};
i2c@12C60000 {
@@ -35,6 +42,11 @@
max77686@09 {
compatible = "maxim,max77686";
+ interrupt-parent = <&gpx3>;
+ interrupts = <2 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&max77686_irq>;
+ wakeup-source;
reg = <0x09>;
voltage-regulators {
diff -Nur linux/arch/arm/boot/dts/exynos5250-arndale.dts rpi/arch/arm/boot/dts/exynos5250-arndale.dts
--- linux/arch/arm/boot/dts/exynos5250-arndale.dts 2014-05-29 12:18:16.585565322 +0900
+++ rpi/arch/arm/boot/dts/exynos5250-arndale.dts 2014-05-29 11:49:03.657969729 +0900
@@ -286,6 +286,7 @@
regulator-name = "vdd_g3d";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
+ regulator-always-on;
regulator-boot-on;
op_mode = <1>;
};
diff -Nur linux/arch/arm/boot/dts/exynos5250.dtsi rpi/arch/arm/boot/dts/exynos5250.dtsi
--- linux/arch/arm/boot/dts/exynos5250.dtsi 2014-05-29 12:18:16.600565228 +0900
+++ rpi/arch/arm/boot/dts/exynos5250.dtsi 2014-05-29 11:49:03.658969720 +0900
@@ -556,7 +556,7 @@
compatible = "arm,pl330", "arm,primecell";
reg = <0x10800000 0x1000>;
interrupts = <0 33 0>;
- clocks = <&clock 271>;
+ clocks = <&clock 346>;
clock-names = "apb_pclk";
#dma-cells = <1>;
#dma-channels = <8>;
diff -Nur linux/arch/arm/boot/dts/omap4-panda-common.dtsi rpi/arch/arm/boot/dts/omap4-panda-common.dtsi
--- linux/arch/arm/boot/dts/omap4-panda-common.dtsi 2014-05-29 12:18:16.668564802 +0900
+++ rpi/arch/arm/boot/dts/omap4-panda-common.dtsi 2014-05-29 11:49:03.692969435 +0900
@@ -239,15 +239,6 @@
0xf0 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c4_sda */
>;
};
-};
-
-&omap4_pmx_wkup {
- led_wkgpio_pins: pinmux_leds_wkpins {
- pinctrl-single,pins = <
- 0x1a (PIN_OUTPUT | MUX_MODE3) /* gpio_wk7 */
- 0x1c (PIN_OUTPUT | MUX_MODE3) /* gpio_wk8 */
- >;
- };
/*
* wl12xx GPIO outputs for WLAN_EN, BT_EN, FM_EN, BT_WAKEUP
@@ -267,7 +258,7 @@
pinctrl-single,pins = <
0x38 (PIN_INPUT | MUX_MODE3) /* gpmc_ncs2.gpio_52 */
0x3a (PIN_INPUT | MUX_MODE3) /* gpmc_ncs3.gpio_53 */
- 0x108 (PIN_OUTPUT | MUX_MODE0) /* sdmmc5_clk.sdmmc5_clk */
+ 0x108 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_clk.sdmmc5_clk */
0x10a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_cmd.sdmmc5_cmd */
0x10c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_dat0.sdmmc5_dat0 */
0x10e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc5_dat1.sdmmc5_dat1 */
@@ -276,6 +267,15 @@
>;
};
};
+
+&omap4_pmx_wkup {
+ led_wkgpio_pins: pinmux_leds_wkpins {
+ pinctrl-single,pins = <
+ 0x1a (PIN_OUTPUT | MUX_MODE3) /* gpio_wk7 */
+ 0x1c (PIN_OUTPUT | MUX_MODE3) /* gpio_wk8 */
+ >;
+ };
+};
&i2c1 {
pinctrl-names = "default";
diff -Nur linux/arch/arm/boot/dts/r8a7790.dtsi rpi/arch/arm/boot/dts/r8a7790.dtsi
--- linux/arch/arm/boot/dts/r8a7790.dtsi 2014-05-29 12:18:16.682564715 +0900
+++ rpi/arch/arm/boot/dts/r8a7790.dtsi 2014-05-29 11:49:03.699969376 +0900
@@ -152,7 +152,7 @@
sdhi0: sdhi@ee100000 {
compatible = "renesas,sdhi-r8a7790";
- reg = <0 0xee100000 0 0x100>;
+ reg = <0 0xee100000 0 0x200>;
interrupt-parent = <&gic>;
interrupts = <0 165 4>;
cap-sd-highspeed;
@@ -161,7 +161,7 @@
sdhi1: sdhi@ee120000 {
compatible = "renesas,sdhi-r8a7790";
- reg = <0 0xee120000 0 0x100>;
+ reg = <0 0xee120000 0 0x200>;
interrupt-parent = <&gic>;
interrupts = <0 166 4>;
cap-sd-highspeed;
diff -Nur linux/arch/arm/boot/dts/sun6i-a31.dtsi rpi/arch/arm/boot/dts/sun6i-a31.dtsi
--- linux/arch/arm/boot/dts/sun6i-a31.dtsi 2014-05-29 12:18:16.698564614 +0900
+++ rpi/arch/arm/boot/dts/sun6i-a31.dtsi 2014-05-29 11:49:03.714969250 +0900
@@ -193,7 +193,10 @@
pio: pinctrl@01c20800 {
compatible = "allwinner,sun6i-a31-pinctrl";
reg = <0x01c20800 0x400>;
- interrupts = <0 11 1>, <0 15 1>, <0 16 1>, <0 17 1>;
+ interrupts = <0 11 4>,
+ <0 15 4>,
+ <0 16 4>,
+ <0 17 4>;
clocks = <&apb1_gates 5>;
gpio-controller;
interrupt-controller;
@@ -212,11 +215,11 @@
timer@01c20c00 {
compatible = "allwinner,sun4i-timer";
reg = <0x01c20c00 0xa0>;
- interrupts = <0 18 1>,
- <0 19 1>,
- <0 20 1>,
- <0 21 1>,
- <0 22 1>;
+ interrupts = <0 18 4>,
+ <0 19 4>,
+ <0 20 4>,
+ <0 21 4>,
+ <0 22 4>;
clocks = <&osc24M>;
};
@@ -228,7 +231,7 @@
uart0: serial@01c28000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
- interrupts = <0 0 1>;
+ interrupts = <0 0 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb2_gates 16>;
@@ -238,7 +241,7 @@
uart1: serial@01c28400 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28400 0x400>;
- interrupts = <0 1 1>;
+ interrupts = <0 1 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb2_gates 17>;
@@ -248,7 +251,7 @@
uart2: serial@01c28800 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28800 0x400>;
- interrupts = <0 2 1>;
+ interrupts = <0 2 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb2_gates 18>;
@@ -258,7 +261,7 @@
uart3: serial@01c28c00 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28c00 0x400>;
- interrupts = <0 3 1>;
+ interrupts = <0 3 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb2_gates 19>;
@@ -268,7 +271,7 @@
uart4: serial@01c29000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c29000 0x400>;
- interrupts = <0 4 1>;
+ interrupts = <0 4 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb2_gates 20>;
@@ -278,7 +281,7 @@
uart5: serial@01c29400 {
compatible = "snps,dw-apb-uart";
reg = <0x01c29400 0x400>;
- interrupts = <0 5 1>;
+ interrupts = <0 5 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb2_gates 21>;
diff -Nur linux/arch/arm/boot/dts/sun7i-a20.dtsi rpi/arch/arm/boot/dts/sun7i-a20.dtsi
--- linux/arch/arm/boot/dts/sun7i-a20.dtsi 2014-05-29 12:18:16.699564608 +0900
+++ rpi/arch/arm/boot/dts/sun7i-a20.dtsi 2014-05-29 11:49:03.714969250 +0900
@@ -170,7 +170,7 @@
emac: ethernet@01c0b000 {
compatible = "allwinner,sun4i-emac";
reg = <0x01c0b000 0x1000>;
- interrupts = <0 55 1>;
+ interrupts = <0 55 4>;
clocks = <&ahb_gates 17>;
status = "disabled";
};
@@ -186,7 +186,7 @@
pio: pinctrl@01c20800 {
compatible = "allwinner,sun7i-a20-pinctrl";
reg = <0x01c20800 0x400>;
- interrupts = <0 28 1>;
+ interrupts = <0 28 4>;
clocks = <&apb0_gates 5>;
gpio-controller;
interrupt-controller;
@@ -230,12 +230,12 @@
timer@01c20c00 {
compatible = "allwinner,sun4i-timer";
reg = <0x01c20c00 0x90>;
- interrupts = <0 22 1>,
- <0 23 1>,
- <0 24 1>,
- <0 25 1>,
- <0 67 1>,
- <0 68 1>;
+ interrupts = <0 22 4>,
+ <0 23 4>,
+ <0 24 4>,
+ <0 25 4>,
+ <0 67 4>,
+ <0 68 4>;
clocks = <&osc24M>;
};
@@ -247,7 +247,7 @@
uart0: serial@01c28000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
- interrupts = <0 1 1>;
+ interrupts = <0 1 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb1_gates 16>;
@@ -257,7 +257,7 @@
uart1: serial@01c28400 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28400 0x400>;
- interrupts = <0 2 1>;
+ interrupts = <0 2 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb1_gates 17>;
@@ -267,7 +267,7 @@
uart2: serial@01c28800 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28800 0x400>;
- interrupts = <0 3 1>;
+ interrupts = <0 3 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb1_gates 18>;
@@ -277,7 +277,7 @@
uart3: serial@01c28c00 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28c00 0x400>;
- interrupts = <0 4 1>;
+ interrupts = <0 4 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb1_gates 19>;
@@ -287,7 +287,7 @@
uart4: serial@01c29000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c29000 0x400>;
- interrupts = <0 17 1>;
+ interrupts = <0 17 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb1_gates 20>;
@@ -297,7 +297,7 @@
uart5: serial@01c29400 {
compatible = "snps,dw-apb-uart";
reg = <0x01c29400 0x400>;
- interrupts = <0 18 1>;
+ interrupts = <0 18 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb1_gates 21>;
@@ -307,7 +307,7 @@
uart6: serial@01c29800 {
compatible = "snps,dw-apb-uart";
reg = <0x01c29800 0x400>;
- interrupts = <0 19 1>;
+ interrupts = <0 19 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb1_gates 22>;
@@ -317,7 +317,7 @@
uart7: serial@01c29c00 {
compatible = "snps,dw-apb-uart";
reg = <0x01c29c00 0x400>;
- interrupts = <0 20 1>;
+ interrupts = <0 20 4>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&apb1_gates 23>;
diff -Nur linux/arch/arm/configs/bcmrpi_cutdown_defconfig rpi/arch/arm/configs/bcmrpi_cutdown_defconfig
--- linux/arch/arm/configs/bcmrpi_cutdown_defconfig 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/configs/bcmrpi_cutdown_defconfig 2014-05-29 11:49:03.751968939 +0900
@@ -0,0 +1,503 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_UID16 is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_BCM2708=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_NET_PKTGEN=m
+CONFIG_IRDA=m
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRTTY_SIR=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_BT_ATH3K=m
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_MESH=y
+CONFIG_WIMAX=m
+CONFIG_NET_9P=m
+CONFIG_NFC=m
+CONFIG_NFC_PN533=m
+CONFIG_DEVTMPFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+CONFIG_PHYLIB=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8187=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_ATH9K_HTC=m
+CONFIG_CARL9170=m
+CONFIG_B43=m
+CONFIG_B43LEGACY=m
+CONFIG_HOSTAP=m
+CONFIG_IWM=m
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RTL8192CU=m
+CONFIG_WL1251=m
+CONFIG_WL12XX_MENU=m
+CONFIG_ZD1211RW=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_KC2190=y
+# CONFIG_USB_NET_ZAURUS is not set
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_NET_KALMIA=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_NETCONSOLE=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_SERIO=m
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_BCM2708_WDT=m
+# CONFIG_MFD_SUPPORT is not set
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_ALOOP=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_BCM2835=m
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SOUND_PRIME=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELECOM=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_HOLTEK=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KYE=m
+CONFIG_HID_UCLOGIC=m
+CONFIG_HID_WALTOP=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LCPOWER=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
+CONFIG_HID_NTRIG=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_GREENASIA=m
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_HID_ZYDACRON=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=m
+CONFIG_USB_DWCOTG=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_UAS=m
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_REISERFS_FS=m
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_GFS2_FS=m
+CONFIG_OCFS2_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_FSCACHE=y
+CONFIG_CACHEFILES=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_NTFS_FS=m
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_9P_FS=m
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_BCM2708=m
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_BCM2708=m
diff -Nur linux/arch/arm/configs/bcmrpi_defconfig rpi/arch/arm/configs/bcmrpi_defconfig
--- linux/arch/arm/configs/bcmrpi_defconfig 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/configs/bcmrpi_defconfig 2014-05-29 11:49:03.751968939 +0900
@@ -0,0 +1,1096 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_MEMCG=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_BCM2708=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_SECCOMP=y
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
+CONFIG_KEXEC=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IPGRE=m
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_AUDIT=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_PE_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_L2TP=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_ATALK=m
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFB=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_CHOKE=m
+CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_CLS_CGROUP=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_EMATCH_IPSET=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+CONFIG_BATMAN_ADV=m
+CONFIG_OPENVSWITCH=m
+CONFIG_NET_PKTGEN=m
+CONFIG_HAMRADIO=y
+CONFIG_AX25=m
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_YAM=m
+CONFIG_IRDA=m
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRTTY_SIR=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_BT_ATH3K=m
+CONFIG_BT_WILINK=m
+CONFIG_CFG80211=m
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_MESH=y
+CONFIG_WIMAX=m
+CONFIG_RFKILL=m
+CONFIG_RFKILL_INPUT=y
+CONFIG_NET_9P=m
+CONFIG_NFC=m
+CONFIG_NFC_PN533=m
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=5
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_DELAY=m
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_IFB=m
+CONFIG_MACVLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_AX88179_178A=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_CDC_MBIM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_NET_KALMIA=m
+CONFIG_USB_NET_QMI_WWAN=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8187=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_ATH_CARDS=m
+CONFIG_ATH9K=m
+CONFIG_ATH9K_HTC=m
+CONFIG_CARL9170=m
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_USB=m
+CONFIG_AR5523=m
+CONFIG_B43=m
+# CONFIG_B43_PHY_N is not set
+CONFIG_B43LEGACY=m
+CONFIG_BRCMFMAC=m
+# CONFIG_BRCMFMAC_SDIO is not set
+CONFIG_BRCMFMAC_USB=y
+CONFIG_HOSTAP=m
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT3573=y
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_RT55XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RTL8192CU=m
+CONFIG_ZD1211RW=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_SERIO=m
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_TTY_PRINTK=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_BCM2708=m
+CONFIG_RAW_DRIVER=y
+CONFIG_BRCM_CHAR_DRIVERS=y
+CONFIG_BCM_VC_CMA=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_BCM2708=m
+CONFIG_SPI=y
+CONFIG_SPI_BCM2708=m
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_W1=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_DS1WM=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2408=m
+CONFIG_W1_SLAVE_DS2413=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_DS2780=m
+CONFIG_W1_SLAVE_DS2781=m
+CONFIG_W1_SLAVE_DS28E04=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_BATTERY_DS2760=m
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_BCM2835=y
+CONFIG_WATCHDOG=y
+CONFIG_BCM2708_WDT=m
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_LIRC=m
+CONFIG_RC_DEVICES=y
+CONFIG_RC_ATI_REMOTE=m
+CONFIG_IR_IMON=m
+CONFIG_IR_MCEUSB=m
+CONFIG_IR_REDRAT3=m
+CONFIG_IR_STREAMZAP=m
+CONFIG_IR_IGUANA=m
+CONFIG_IR_TTUSBIR=m
+CONFIG_RC_LOOPBACK=m
+CONFIG_IR_GPIO_CIR=m
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+CONFIG_USB_GSPCA_JL2005BCD=m
+CONFIG_USB_GSPCA_KINECT=m
+CONFIG_USB_GSPCA_KONICA=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_NW80X=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SE401=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SPCA1528=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STK1135=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TOPRO=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_VICAM=m
+CONFIG_USB_GSPCA_XIRLINK_CIT=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_USB_PWC=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_STK1160_COMMON=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_TM6000=m
+CONFIG_VIDEO_TM6000_ALSA=m
+CONFIG_VIDEO_TM6000_DVB=m
+CONFIG_DVB_USB=m
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_PCTV452E=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_FRIIO=m
+CONFIG_DVB_USB_AZ6027=m
+CONFIG_DVB_USB_TECHNISAT_USB2=m
+CONFIG_DVB_USB_V2=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_AF9035=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_AZ6007=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_IT913X=m
+CONFIG_DVB_USB_LME2510=m
+CONFIG_DVB_USB_MXL111SF=m
+CONFIG_DVB_USB_RTL28XXU=m
+CONFIG_SMS_USB_DRV=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_BCM2835=y
+CONFIG_VIDEO_BCM2835_MMAL=m
+CONFIG_RADIO_SI470X=y
+CONFIG_USB_SI470X=m
+CONFIG_I2C_SI470X=m
+CONFIG_RADIO_SI4713=m
+CONFIG_USB_MR800=m
+CONFIG_USB_DSBR=m
+CONFIG_RADIO_SHARK=m
+CONFIG_RADIO_SHARK2=m
+CONFIG_USB_KEENE=m
+CONFIG_USB_MA901=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_WL1273=m
+CONFIG_RADIO_WL128X=m
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_ALOOP=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_BCM2835=m
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SND_SOC=m
+CONFIG_SND_BCM2708_SOC_I2S=m
+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m
+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m
+CONFIG_SND_BCM2708_SOC_RPI_DAC=m
+CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+CONFIG_SOUND_PRIME=m
+CONFIG_HIDRAW=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELECOM=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_HOLTEK=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KYE=m
+CONFIG_HID_UCLOGIC=m
+CONFIG_HID_WALTOP=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LCPOWER=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
+CONFIG_HID_NTRIG=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_GREENASIA=m
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THINGM=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_HID_ZYDACRON=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=m
+CONFIG_USB_DWCOTG=y
+CONFIG_USB_PRINTER=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_ZTE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
+CONFIG_MMC_SPI=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=m
+CONFIG_LEDS_TRIGGER_CAMERA=m
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_DS3232=m
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_ISL12022=m
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF2127=m
+CONFIG_RTC_DRV_PCF8523=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_BQ32K=m
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8581=m
+CONFIG_RTC_DRV_RX8025=m
+CONFIG_RTC_DRV_EM3027=m
+CONFIG_RTC_DRV_RV3029C2=m
+CONFIG_RTC_DRV_M41T93=m
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_DS3234=m
+CONFIG_RTC_DRV_PCF2123=m
+CONFIG_RTC_DRV_RX4581=m
+CONFIG_DMADEVICES=y
+CONFIG_DMA_BCM2708=m
+CONFIG_UIO=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_STAGING=y
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+CONFIG_R8712U=m
+CONFIG_VT6656=m
+CONFIG_SPEAKUP=m
+CONFIG_SPEAKUP_SYNTH_SOFT=m
+CONFIG_STAGING_MEDIA=y
+CONFIG_DVB_AS102=m
+CONFIG_USB_SN9C102=m
+CONFIG_LIRC_STAGING=y
+CONFIG_LIRC_IGORPLUGUSB=m
+CONFIG_LIRC_IMON=m
+CONFIG_LIRC_RPI=m
+CONFIG_LIRC_SASEM=m
+CONFIG_LIRC_SERIAL=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_REISERFS_FS=m
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_GFS2_FS=m
+CONFIG_OCFS2_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FANOTIFY=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_FSCACHE=y
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_HISTOGRAM=y
+CONFIG_CACHEFILES=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_F2FS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_9P_FS=m
+CONFIG_9P_FS_POSIX_ACL=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_DLM=m
+CONFIG_PRINTK_TIME=y
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_LATENCYTOP=y
+# CONFIG_KPROBE_EVENT is not set
+CONFIG_KGDB=y
+CONFIG_KGDB_KDB=y
+CONFIG_KDB_KEYBOARD=y
+CONFIG_STRICT_DEVMEM=y
+CONFIG_CRYPTO_USER=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_SHA1_ARM=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES_ARM=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
diff -Nur linux/arch/arm/configs/bcmrpi_emergency_defconfig rpi/arch/arm/configs/bcmrpi_emergency_defconfig
--- linux/arch/arm/configs/bcmrpi_emergency_defconfig 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/configs/bcmrpi_emergency_defconfig 2014-05-29 11:49:03.752968931 +0900
@@ -0,0 +1,532 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../target_fs"
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_BCM2708=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_AEABI=y
+CONFIG_SECCOMP=y
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
+CONFIG_KEXEC=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_NET_PKTGEN=m
+CONFIG_IRDA=m
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRTTY_SIR=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_BT_ATH3K=m
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_MESH=y
+CONFIG_WIMAX=m
+CONFIG_NET_9P=m
+CONFIG_NFC=m
+CONFIG_NFC_PN533=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_MD=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+CONFIG_PHYLIB=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8187=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_ATH_COMMON=m
+CONFIG_ATH9K=m
+CONFIG_ATH9K_HTC=m
+CONFIG_CARL9170=m
+CONFIG_B43=m
+CONFIG_B43LEGACY=m
+CONFIG_HOSTAP=m
+CONFIG_IWM=m
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RTL8192CU=m
+CONFIG_WL1251=m
+CONFIG_WL12XX_MENU=m
+CONFIG_ZD1211RW=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_KC2190=y
+# CONFIG_USB_NET_ZAURUS is not set
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_NET_KALMIA=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_NETCONSOLE=m
+CONFIG_INPUT_POLLDEV=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_SERIO=m
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_BCM2708_WDT=m
+# CONFIG_MFD_SUPPORT is not set
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_ALOOP=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_BCM2835=m
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SOUND_PRIME=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELECOM=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_HOLTEK=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KYE=m
+CONFIG_HID_UCLOGIC=m
+CONFIG_HID_WALTOP=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LCPOWER=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
+CONFIG_HID_NTRIG=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_QUANTA=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_GREENASIA=m
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_HID_ZYDACRON=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=m
+CONFIG_USB_DWCOTG=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_UAS=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_REISERFS_FS=m
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_GFS2_FS=m
+CONFIG_OCFS2_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FANOTIFY=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_FSCACHE=y
+CONFIG_FSCACHE_STATS=y
+CONFIG_FSCACHE_HISTOGRAM=y
+CONFIG_CACHEFILES=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_NTFS_FS=m
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_9P_FS=m
+CONFIG_9P_FS_POSIX_ACL=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_LATENCYTOP=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_SCHED_TRACER=y
+CONFIG_STACK_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_KGDB=y
+CONFIG_KGDB_KDB=y
+CONFIG_KDB_KEYBOARD=y
+CONFIG_STRICT_DEVMEM=y
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
diff -Nur linux/arch/arm/configs/bcmrpi_quick_defconfig rpi/arch/arm/configs/bcmrpi_quick_defconfig
--- linux/arch/arm/configs/bcmrpi_quick_defconfig 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/configs/bcmrpi_quick_defconfig 2014-05-29 11:49:03.752968931 +0900
@@ -0,0 +1,197 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_LOCALVERSION="-quick"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_BCM2708=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_AX8817X is not set
+# CONFIG_USB_NET_CDCETHER is not set
+# CONFIG_USB_NET_CDC_NCM is not set
+CONFIG_USB_NET_SMSC95XX=y
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_TTY_PRINTK=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_BCM2708=y
+CONFIG_RAW_DRIVER=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_BCM2835=y
+CONFIG_WATCHDOG=y
+CONFIG_BCM2708_WDT=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DEBUG=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+CONFIG_FB=y
+CONFIG_FB_BCM2708=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_BCM2835=y
+# CONFIG_SND_USB is not set
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DWCOTG=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM2708=y
+CONFIG_MMC_SDHCI_BCM2708_DMA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FSCACHE=y
+CONFIG_CACHEFILES=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFS_FSCACHE=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+CONFIG_KGDB=y
+CONFIG_KGDB_KDB=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
diff -Nur linux/arch/arm/configs/multi_v7_defconfig rpi/arch/arm/configs/multi_v7_defconfig
--- linux/arch/arm/configs/multi_v7_defconfig 2014-05-29 12:18:16.724564452 +0900
+++ rpi/arch/arm/configs/multi_v7_defconfig 2014-05-29 11:49:03.775968737 +0900
@@ -132,12 +132,14 @@
CONFIG_USB_ISP1301=y
CONFIG_USB_MXS_PHY=y
CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
CONFIG_MMC_ARMMMCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_MMC_SDHCI_TEGRA=y
CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_MMC_SDHCI_BCM_KONA=y
CONFIG_MMC_OMAP=y
CONFIG_MMC_OMAP_HS=y
CONFIG_EDAC=y
diff -Nur linux/arch/arm/include/asm/cacheflush.h rpi/arch/arm/include/asm/cacheflush.h
--- linux/arch/arm/include/asm/cacheflush.h 2014-05-29 12:18:16.730564414 +0900
+++ rpi/arch/arm/include/asm/cacheflush.h 2014-05-29 11:49:03.792968594 +0900
@@ -212,6 +212,7 @@
static inline void __flush_icache_all(void)
{
__flush_icache_preferred();
+ dsb();
}
/*
diff -Nur linux/arch/arm/include/asm/div64.h rpi/arch/arm/include/asm/div64.h
--- linux/arch/arm/include/asm/div64.h 2014-05-29 12:18:16.731564408 +0900
+++ rpi/arch/arm/include/asm/div64.h 2014-05-29 11:49:03.795968569 +0900
@@ -156,7 +156,7 @@
/* Select the best insn combination to perform the */ \
/* actual __m * __n / (__p << 64) operation. */ \
if (!__c) { \
- asm ( "umull %Q0, %R0, %1, %Q2\n\t" \
+ asm ( "umull %Q0, %R0, %Q1, %Q2\n\t" \
"mov %Q0, #0" \
: "=&r" (__res) \
: "r" (__m), "r" (__n) \
diff -Nur linux/arch/arm/include/asm/futex.h rpi/arch/arm/include/asm/futex.h
--- linux/arch/arm/include/asm/futex.h 2014-05-29 12:18:16.733564395 +0900
+++ rpi/arch/arm/include/asm/futex.h 2014-05-29 11:49:03.798968544 +0900
@@ -3,11 +3,6 @@
#ifdef __KERNEL__
-#if defined(CONFIG_CPU_USE_DOMAINS) && defined(CONFIG_SMP)
-/* ARM doesn't provide unprivileged exclusive memory accessors */
-#include <asm-generic/futex.h>
-#else
-
#include <linux/futex.h>
#include <linux/uaccess.h>
#include <asm/errno.h>
@@ -164,6 +159,5 @@
return ret;
}
-#endif /* !(CPU_USE_DOMAINS && SMP) */
#endif /* __KERNEL__ */
#endif /* _ASM_ARM_FUTEX_H */
diff -Nur linux/arch/arm/include/asm/irqflags.h rpi/arch/arm/include/asm/irqflags.h
--- linux/arch/arm/include/asm/irqflags.h 2014-05-29 11:51:25.197806751 +0900
+++ rpi/arch/arm/include/asm/irqflags.h 2014-05-29 11:49:03.806968477 +0900
@@ -145,12 +145,22 @@
}
/*
- * restore saved IRQ & FIQ state
+ * restore saved IRQ state
*/
static inline void arch_local_irq_restore(unsigned long flags)
{
- asm volatile(
- " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
+ unsigned long temp = 0;
+ flags &= ~(1 << 6);
+ asm volatile (
+ " mrs %0, cpsr"
+ : "=r" (temp)
+ :
+ : "memory", "cc");
+ /* Preserve FIQ bit */
+ temp &= (1 << 6);
+ flags = flags | temp;
+ asm volatile (
+ " msr cpsr_c, %0 @ local_irq_restore"
:
: "r" (flags)
: "memory", "cc");
diff -Nur linux/arch/arm/include/asm/pgtable-2level.h rpi/arch/arm/include/asm/pgtable-2level.h
--- linux/arch/arm/include/asm/pgtable-2level.h 2014-05-29 12:18:16.742564339 +0900
+++ rpi/arch/arm/include/asm/pgtable-2level.h 2014-05-29 11:49:03.815968401 +0900
@@ -140,6 +140,7 @@
#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */
#define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */
#define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */
+#define L_PTE_MT_VECTORS (_AT(pteval_t, 0x0f) << 2) /* 1111 */
#define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2)
#ifndef __ASSEMBLY__
diff -Nur linux/arch/arm/include/asm/pgtable-3level.h rpi/arch/arm/include/asm/pgtable-3level.h
--- linux/arch/arm/include/asm/pgtable-3level.h 2014-05-29 12:18:16.742564339 +0900
+++ rpi/arch/arm/include/asm/pgtable-3level.h 2014-05-29 11:49:03.816968393 +0900
@@ -120,11 +120,14 @@
/*
* 2nd stage PTE definitions for LPAE.
*/
-#define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x5) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */
-#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */
-#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */
+#define L_PTE_S2_MT_UNCACHED (_AT(pteval_t, 0x0) << 2) /* strongly ordered */
+#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* normal inner write-through */
+#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* normal inner write-back */
+#define L_PTE_S2_MT_DEV_SHARED (_AT(pteval_t, 0x1) << 2) /* device */
+#define L_PTE_S2_MT_MASK (_AT(pteval_t, 0xf) << 2)
+
+#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */
+#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */
/*
* Hyp-mode PL2 PTE definitions for LPAE.
diff -Nur linux/arch/arm/include/asm/pgtable.h rpi/arch/arm/include/asm/pgtable.h
--- linux/arch/arm/include/asm/pgtable.h 2014-05-29 12:18:16.743564333 +0900
+++ rpi/arch/arm/include/asm/pgtable.h 2014-05-29 11:49:03.816968393 +0900
@@ -61,7 +61,7 @@
* mapping to be mapped at. This is particularly important for
* non-high vector CPUs.
*/
-#define FIRST_USER_ADDRESS PAGE_SIZE
+#define FIRST_USER_ADDRESS (PAGE_SIZE * 2)
/*
* Use TASK_SIZE as the ceiling argument for free_pgtables() and
diff -Nur linux/arch/arm/include/asm/spinlock.h rpi/arch/arm/include/asm/spinlock.h
--- linux/arch/arm/include/asm/spinlock.h 2014-05-29 12:18:16.745564320 +0900
+++ rpi/arch/arm/include/asm/spinlock.h 2014-05-29 11:49:03.820968359 +0900
@@ -44,18 +44,9 @@
static inline void dsb_sev(void)
{
-#if __LINUX_ARM_ARCH__ >= 7
- __asm__ __volatile__ (
- "dsb ishst\n"
- SEV
- );
-#else
- __asm__ __volatile__ (
- "mcr p15, 0, %0, c7, c10, 4\n"
- SEV
- : : "r" (0)
- );
-#endif
+
+ dsb(ishst);
+ __asm__(SEV);
}
/*
diff -Nur linux/arch/arm/include/asm/unistd.h rpi/arch/arm/include/asm/unistd.h
--- linux/arch/arm/include/asm/unistd.h 2014-05-29 12:18:16.748564301 +0900
+++ rpi/arch/arm/include/asm/unistd.h 2014-05-29 11:49:03.825968317 +0900
@@ -48,6 +48,5 @@
*/
#define __IGNORE_fadvise64_64
#define __IGNORE_migrate_pages
-#define __IGNORE_kcmp
#endif /* __ASM_ARM_UNISTD_H */
diff -Nur linux/arch/arm/Kconfig rpi/arch/arm/Kconfig
--- linux/arch/arm/Kconfig 2014-05-29 12:18:16.497565873 +0900
+++ rpi/arch/arm/Kconfig 2014-05-29 11:49:03.629969964 +0900
@@ -368,6 +368,24 @@
This enables support for systems based on Atmel
AT91RM9200 and AT91SAM9* processors.
+config ARCH_BCM2708
+ bool "Broadcom BCM2708 family"
+ select CPU_V6
+ select ARM_AMBA
+ select HAVE_CLK
+ select HAVE_SCHED_CLOCK
+ select NEED_MACH_GPIO_H
+ select NEED_MACH_MEMORY_H
+ select CLKDEV_LOOKUP
+ select ARCH_HAS_CPUFREQ
+ select GENERIC_CLOCKEVENTS
+ select ARM_ERRATA_411920
+ select MACH_BCM2708
+ select VC4
+ select FIQ
+ help
+ This enables support for Broadcom BCM2708 boards.
+
config ARCH_CLPS711X
bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
select ARCH_REQUIRE_GPIOLIB
@@ -892,7 +910,7 @@
bool "ARMv5 based platforms (ARM926T, XSCALE, PJ1, ...)"
depends on !ARCH_MULTI_V6_V7
select ARCH_MULTI_V4_V5
- select CPU_ARM926T if (!CPU_ARM946E || CPU_ARM1020 || \
+ select CPU_ARM926T if !(CPU_ARM946E || CPU_ARM1020 || \
CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || \
CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_FEROCEON)
@@ -1043,6 +1061,7 @@
source "arch/arm/mach-vt8500/Kconfig"
source "arch/arm/mach-w90x900/Kconfig"
+source "arch/arm/mach-bcm2708/Kconfig"
source "arch/arm/mach-zynq/Kconfig"
diff -Nur linux/arch/arm/Kconfig.debug rpi/arch/arm/Kconfig.debug
--- linux/arch/arm/Kconfig.debug 2014-05-29 12:18:16.498565867 +0900
+++ rpi/arch/arm/Kconfig.debug 2014-05-29 11:49:03.630969956 +0900
@@ -847,6 +847,14 @@
options; the platform specific options are deprecated
and will be soon removed.
+ config DEBUG_BCM2708_UART0
+ bool "Broadcom BCM2708 UART0 (PL011)"
+ depends on MACH_BCM2708
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to UART 0. The port must have been initialised
+ by the boot-loader before use.
+
endchoice
config DEBUG_EXYNOS_UART
diff -Nur linux/arch/arm/kernel/devtree.c rpi/arch/arm/kernel/devtree.c
--- linux/arch/arm/kernel/devtree.c 2014-05-29 12:18:16.756564251 +0900
+++ rpi/arch/arm/kernel/devtree.c 2014-05-29 11:49:03.837968216 +0900
@@ -171,7 +171,7 @@
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
{
- return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu);
+ return phys_id == cpu_logical_map(cpu);
}
/**
diff -Nur linux/arch/arm/kernel/entry-armv.S rpi/arch/arm/kernel/entry-armv.S
--- linux/arch/arm/kernel/entry-armv.S 2014-05-29 12:18:16.757564245 +0900
+++ rpi/arch/arm/kernel/entry-armv.S 2014-05-29 11:49:03.839968199 +0900
@@ -192,6 +192,7 @@
svc_entry
mov r2, sp
dabt_helper
+ THUMB( ldr r5, [sp, #S_PSR] ) @ potentially updated CPSR
svc_exit r5 @ return from exception
UNWIND(.fnend )
ENDPROC(__dabt_svc)
diff -Nur linux/arch/arm/kernel/fiqasm.S rpi/arch/arm/kernel/fiqasm.S
--- linux/arch/arm/kernel/fiqasm.S 2014-05-29 11:51:25.236806437 +0900
+++ rpi/arch/arm/kernel/fiqasm.S 2014-05-29 11:49:03.840968191 +0900
@@ -47,3 +47,7 @@
mov r0, r0 @ avoid hazard prior to ARMv4
mov pc, lr
ENDPROC(__get_fiq_regs)
+
+ENTRY(__FIQ_Branch)
+ mov pc, r8
+ENDPROC(__FIQ_Branch)
diff -Nur linux/arch/arm/kernel/machine_kexec.c rpi/arch/arm/kernel/machine_kexec.c
--- linux/arch/arm/kernel/machine_kexec.c 2014-05-29 12:18:16.767564182 +0900
+++ rpi/arch/arm/kernel/machine_kexec.c 2014-05-29 11:49:03.849968115 +0900
@@ -181,3 +181,10 @@
soft_restart(reboot_code_buffer_phys);
}
+
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_ARM_LPAE
+ VMCOREINFO_CONFIG(ARM_LPAE);
+#endif
+}
diff -Nur linux/arch/arm/kernel/process.c rpi/arch/arm/kernel/process.c
--- linux/arch/arm/kernel/process.c 2014-05-29 12:18:16.770564164 +0900
+++ rpi/arch/arm/kernel/process.c 2014-05-29 11:49:03.897967712 +0900
@@ -176,6 +176,16 @@
default_idle();
}
+char bcm2708_reboot_mode = 'h';
+
+int __init reboot_setup(char *str)
+{
+ bcm2708_reboot_mode = str[0];
+ return 1;
+}
+
+__setup("reboot=", reboot_setup);
+
/*
* Called by kexec, immediately prior to machine_kexec().
*
@@ -404,6 +414,7 @@
unsigned long get_wchan(struct task_struct *p)
{
struct stackframe frame;
+ unsigned long stack_page;
int count = 0;
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
@@ -412,9 +423,11 @@
frame.sp = thread_saved_sp(p);
frame.lr = 0; /* recovered from the stack */
frame.pc = thread_saved_pc(p);
+ stack_page = (unsigned long)task_stack_page(p);
do {
- int ret = unwind_frame(&frame);
- if (ret < 0)
+ if (frame.sp < stack_page ||
+ frame.sp >= stack_page + THREAD_SIZE ||
+ unwind_frame(&frame) < 0)
return 0;
if (!in_sched_functions(frame.pc))
return frame.pc;
diff -Nur linux/arch/arm/kernel/setup.c rpi/arch/arm/kernel/setup.c
--- linux/arch/arm/kernel/setup.c 2014-05-29 12:18:16.771564157 +0900
+++ rpi/arch/arm/kernel/setup.c 2014-05-29 11:49:03.900967687 +0900
@@ -622,6 +622,7 @@
int __init arm_add_memory(phys_addr_t start, phys_addr_t size)
{
struct membank *bank = &meminfo.bank[meminfo.nr_banks];
+ u64 aligned_start;
if (meminfo.nr_banks >= NR_BANKS) {
printk(KERN_CRIT "NR_BANKS too low, "
@@ -634,10 +635,16 @@
* Size is appropriately rounded down, start is rounded up.
*/
size -= start & ~PAGE_MASK;
- bank->start = PAGE_ALIGN(start);
+ aligned_start = PAGE_ALIGN(start);
-#ifndef CONFIG_ARM_LPAE
- if (bank->start + size < bank->start) {
+#ifndef CONFIG_ARCH_PHYS_ADDR_T_64BIT
+ if (aligned_start > ULONG_MAX) {
+ printk(KERN_CRIT "Ignoring memory at 0x%08llx outside "
+ "32-bit physical address space\n", (long long)start);
+ return -EINVAL;
+ }
+
+ if (aligned_start + size > ULONG_MAX) {
printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in "
"32-bit physical address space\n", (long long)start);
/*
@@ -645,10 +652,25 @@
* 32 bits, we use ULONG_MAX as the upper limit rather than 4GB.
* This means we lose a page after masking.
*/
- size = ULONG_MAX - bank->start;
+ size = ULONG_MAX - aligned_start;
}
#endif
+ if (aligned_start < PHYS_OFFSET) {
+ if (aligned_start + size <= PHYS_OFFSET) {
+ pr_info("Ignoring memory below PHYS_OFFSET: 0x%08llx-0x%08llx\n",
+ aligned_start, aligned_start + size);
+ return -EINVAL;
+ }
+
+ pr_info("Ignoring memory below PHYS_OFFSET: 0x%08llx-0x%08llx\n",
+ aligned_start, (u64)PHYS_OFFSET);
+
+ size -= PHYS_OFFSET - aligned_start;
+ aligned_start = PHYS_OFFSET;
+ }
+
+ bank->start = aligned_start;
bank->size = size & ~(phys_addr_t)(PAGE_SIZE - 1);
/*
diff -Nur linux/arch/arm/kernel/stacktrace.c rpi/arch/arm/kernel/stacktrace.c
--- linux/arch/arm/kernel/stacktrace.c 2014-05-29 12:18:16.774564139 +0900
+++ rpi/arch/arm/kernel/stacktrace.c 2014-05-29 11:49:03.902967670 +0900
@@ -31,7 +31,7 @@
high = ALIGN(low, THREAD_SIZE);
/* check current frame pointer is within bounds */
- if (fp < (low + 12) || fp + 4 >= high)
+ if (fp < low + 12 || fp > high - 4)
return -EINVAL;
/* restore the registers from the stack frame */
diff -Nur linux/arch/arm/kernel/traps.c rpi/arch/arm/kernel/traps.c
--- linux/arch/arm/kernel/traps.c 2014-05-29 12:18:16.776564126 +0900
+++ rpi/arch/arm/kernel/traps.c 2014-05-29 11:49:03.906967636 +0900
@@ -35,7 +35,13 @@
#include <asm/tls.h>
#include <asm/system_misc.h>
-static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+static const char *handler[]= {
+ "prefetch abort",
+ "data abort",
+ "address exception",
+ "interrupt",
+ "undefined instruction",
+};
void *vectors_page;
@@ -503,9 +509,10 @@
__do_cache_op(unsigned long start, unsigned long end)
{
int ret;
- unsigned long chunk = PAGE_SIZE;
do {
+ unsigned long chunk = min(PAGE_SIZE, end - start);
+
if (signal_pending(current)) {
struct thread_info *ti = current_thread_info();
diff -Nur linux/arch/arm/kvm/mmu.c rpi/arch/arm/kvm/mmu.c
--- linux/arch/arm/kvm/mmu.c 2014-05-29 12:18:16.782564089 +0900
+++ rpi/arch/arm/kvm/mmu.c 2014-05-29 11:49:03.911967594 +0900
@@ -41,6 +41,8 @@
static unsigned long hyp_idmap_end;
static phys_addr_t hyp_idmap_vector;
+#define pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))
+
static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
{
/*
@@ -172,14 +174,14 @@
if (boot_hyp_pgd) {
unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
- kfree(boot_hyp_pgd);
+ free_pages((unsigned long)boot_hyp_pgd, pgd_order);
boot_hyp_pgd = NULL;
}
if (hyp_pgd)
unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
- kfree(init_bounce_page);
+ free_page((unsigned long)init_bounce_page);
init_bounce_page = NULL;
mutex_unlock(&kvm_hyp_pgd_mutex);
@@ -209,7 +211,7 @@
for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
- kfree(hyp_pgd);
+ free_pages((unsigned long)hyp_pgd, pgd_order);
hyp_pgd = NULL;
}
@@ -307,6 +309,17 @@
return err;
}
+static phys_addr_t kvm_kaddr_to_phys(void *kaddr)
+{
+ if (!is_vmalloc_addr(kaddr)) {
+ BUG_ON(!virt_addr_valid(kaddr));
+ return __pa(kaddr);
+ } else {
+ return page_to_phys(vmalloc_to_page(kaddr)) +
+ offset_in_page(kaddr);
+ }
+}
+
/**
* create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode
* @from: The virtual kernel start address of the range
@@ -318,16 +331,27 @@
*/
int create_hyp_mappings(void *from, void *to)
{
- unsigned long phys_addr = virt_to_phys(from);
+ phys_addr_t phys_addr;
+ unsigned long virt_addr;
unsigned long start = KERN_TO_HYP((unsigned long)from);
unsigned long end = KERN_TO_HYP((unsigned long)to);
- /* Check for a valid kernel memory mapping */
- if (!virt_addr_valid(from) || !virt_addr_valid(to - 1))
- return -EINVAL;
+ start = start & PAGE_MASK;
+ end = PAGE_ALIGN(end);
- return __create_hyp_mappings(hyp_pgd, start, end,
- __phys_to_pfn(phys_addr), PAGE_HYP);
+ for (virt_addr = start; virt_addr < end; virt_addr += PAGE_SIZE) {
+ int err;
+
+ phys_addr = kvm_kaddr_to_phys(from + virt_addr - start);
+ err = __create_hyp_mappings(hyp_pgd, virt_addr,
+ virt_addr + PAGE_SIZE,
+ __phys_to_pfn(phys_addr),
+ PAGE_HYP);
+ if (err)
+ return err;
+ }
+
+ return 0;
}
/**
@@ -759,7 +783,7 @@
size_t len = __hyp_idmap_text_end - __hyp_idmap_text_start;
phys_addr_t phys_base;
- init_bounce_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ init_bounce_page = (void *)__get_free_page(GFP_KERNEL);
if (!init_bounce_page) {
kvm_err("Couldn't allocate HYP init bounce page\n");
err = -ENOMEM;
@@ -785,8 +809,9 @@
(unsigned long)phys_base);
}
- hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
- boot_hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
+ hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order);
+ boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order);
+
if (!hyp_pgd || !boot_hyp_pgd) {
kvm_err("Hyp mode PGD not allocated\n");
err = -ENOMEM;
diff -Nur linux/arch/arm/mach-at91/at91sam9260.c rpi/arch/arm/mach-at91/at91sam9260.c
--- linux/arch/arm/mach-at91/at91sam9260.c 2014-05-29 12:18:16.789564045 +0900
+++ rpi/arch/arm/mach-at91/at91sam9260.c 2014-05-29 11:49:03.931967426 +0900
@@ -349,6 +349,8 @@
arm_pm_idle = at91sam9_idle;
arm_pm_restart = at91sam9_alt_restart;
+ at91_sysirq_mask_rtt(AT91SAM9260_BASE_RTT);
+
/* Register GPIO subsystem */
at91_gpio_init(at91sam9260_gpio, 3);
}
diff -Nur linux/arch/arm/mach-at91/at91sam9261.c rpi/arch/arm/mach-at91/at91sam9261.c
--- linux/arch/arm/mach-at91/at91sam9261.c 2014-05-29 12:18:16.790564039 +0900
+++ rpi/arch/arm/mach-at91/at91sam9261.c 2014-05-29 11:49:03.931967426 +0900
@@ -291,6 +291,8 @@
arm_pm_idle = at91sam9_idle;
arm_pm_restart = at91sam9_alt_restart;
+ at91_sysirq_mask_rtt(AT91SAM9261_BASE_RTT);
+
/* Register GPIO subsystem */
at91_gpio_init(at91sam9261_gpio, 3);
}
diff -Nur linux/arch/arm/mach-at91/at91sam9263.c rpi/arch/arm/mach-at91/at91sam9263.c
--- linux/arch/arm/mach-at91/at91sam9263.c 2014-05-29 12:18:16.791564032 +0900
+++ rpi/arch/arm/mach-at91/at91sam9263.c 2014-05-29 11:49:03.933967410 +0900
@@ -328,6 +328,9 @@
arm_pm_idle = at91sam9_idle;
arm_pm_restart = at91sam9_alt_restart;
+ at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0);
+ at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1);
+
/* Register GPIO subsystem */
at91_gpio_init(at91sam9263_gpio, 5);
}
diff -Nur linux/arch/arm/mach-at91/at91sam9g45.c rpi/arch/arm/mach-at91/at91sam9g45.c
--- linux/arch/arm/mach-at91/at91sam9g45.c 2014-05-29 12:18:16.792564026 +0900
+++ rpi/arch/arm/mach-at91/at91sam9g45.c 2014-05-29 11:49:03.934967401 +0900
@@ -377,6 +377,9 @@
arm_pm_idle = at91sam9_idle;
arm_pm_restart = at91sam9g45_restart;
+ at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC);
+ at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT);
+
/* Register GPIO subsystem */
at91_gpio_init(at91sam9g45_gpio, 5);
}
diff -Nur linux/arch/arm/mach-at91/at91sam9n12.c rpi/arch/arm/mach-at91/at91sam9n12.c
--- linux/arch/arm/mach-at91/at91sam9n12.c 2014-05-29 12:18:16.793564020 +0900
+++ rpi/arch/arm/mach-at91/at91sam9n12.c 2014-05-29 11:49:03.936967384 +0900
@@ -223,7 +223,13 @@
at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE);
}
+static void __init at91sam9n12_initialize(void)
+{
+ at91_sysirq_mask_rtc(AT91SAM9N12_BASE_RTC);
+}
+
AT91_SOC_START(at91sam9n12)
.map_io = at91sam9n12_map_io,
.register_clocks = at91sam9n12_register_clocks,
+ .init = at91sam9n12_initialize,
AT91_SOC_END
diff -Nur linux/arch/arm/mach-at91/at91sam9rl.c rpi/arch/arm/mach-at91/at91sam9rl.c
--- linux/arch/arm/mach-at91/at91sam9rl.c 2014-05-29 12:18:16.794564013 +0900
+++ rpi/arch/arm/mach-at91/at91sam9rl.c 2014-05-29 11:49:03.936967384 +0900
@@ -294,6 +294,9 @@
arm_pm_idle = at91sam9_idle;
arm_pm_restart = at91sam9_alt_restart;
+ at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC);
+ at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT);
+
/* Register GPIO subsystem */
at91_gpio_init(at91sam9rl_gpio, 4);
}
diff -Nur linux/arch/arm/mach-at91/at91sam9x5.c rpi/arch/arm/mach-at91/at91sam9x5.c
--- linux/arch/arm/mach-at91/at91sam9x5.c 2014-05-29 12:18:16.795564007 +0900
+++ rpi/arch/arm/mach-at91/at91sam9x5.c 2014-05-29 11:49:03.936967384 +0900
@@ -322,6 +322,11 @@
at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE);
}
+static void __init at91sam9x5_initialize(void)
+{
+ at91_sysirq_mask_rtc(AT91SAM9X5_BASE_RTC);
+}
+
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
@@ -329,4 +334,5 @@
AT91_SOC_START(at91sam9x5)
.map_io = at91sam9x5_map_io,
.register_clocks = at91sam9x5_register_clocks,
+ .init = at91sam9x5_initialize,
AT91_SOC_END
diff -Nur linux/arch/arm/mach-at91/generic.h rpi/arch/arm/mach-at91/generic.h
--- linux/arch/arm/mach-at91/generic.h 2014-05-29 12:18:16.801563970 +0900
+++ rpi/arch/arm/mach-at91/generic.h 2014-05-29 11:49:03.947967292 +0900
@@ -34,6 +34,8 @@
struct device_node *parent);
extern int __init at91_aic5_of_init(struct device_node *node,
struct device_node *parent);
+extern void __init at91_sysirq_mask_rtc(u32 rtc_base);
+extern void __init at91_sysirq_mask_rtt(u32 rtt_base);
/* Timer */
diff -Nur linux/arch/arm/mach-at91/include/mach/at91sam9n12.h rpi/arch/arm/mach-at91/include/mach/at91sam9n12.h
--- linux/arch/arm/mach-at91/include/mach/at91sam9n12.h 2014-05-29 12:18:16.802563963 +0900
+++ rpi/arch/arm/mach-at91/include/mach/at91sam9n12.h 2014-05-29 11:49:03.953967241 +0900
@@ -49,6 +49,11 @@
#define AT91SAM9N12_BASE_USART3 0xf8028000
/*
+ * System Peripherals
+ */
+#define AT91SAM9N12_BASE_RTC 0xfffffeb0
+
+/*
* Internal Memory.
*/
#define AT91SAM9N12_SRAM_BASE 0x00300000 /* Internal SRAM base address */
diff -Nur linux/arch/arm/mach-at91/include/mach/at91sam9x5.h rpi/arch/arm/mach-at91/include/mach/at91sam9x5.h
--- linux/arch/arm/mach-at91/include/mach/at91sam9x5.h 2014-05-29 12:18:16.803563957 +0900
+++ rpi/arch/arm/mach-at91/include/mach/at91sam9x5.h 2014-05-29 11:49:03.954967233 +0900
@@ -55,6 +55,11 @@
#define AT91SAM9X5_BASE_USART2 0xf8024000
/*
+ * System Peripherals
+ */
+#define AT91SAM9X5_BASE_RTC 0xfffffeb0
+
+/*
* Internal Memory.
*/
#define AT91SAM9X5_SRAM_BASE 0x00300000 /* Internal SRAM base address */
diff -Nur linux/arch/arm/mach-at91/include/mach/sama5d3.h rpi/arch/arm/mach-at91/include/mach/sama5d3.h
--- linux/arch/arm/mach-at91/include/mach/sama5d3.h 2014-05-29 12:18:16.803563957 +0900
+++ rpi/arch/arm/mach-at91/include/mach/sama5d3.h 2014-05-29 11:49:03.956967216 +0900
@@ -73,6 +73,11 @@
#define SAMA5D3_BASE_USART3 0xf8024000
/*
+ * System Peripherals
+ */
+#define SAMA5D3_BASE_RTC 0xfffffeb0
+
+/*
* Internal Memory
*/
#define SAMA5D3_SRAM_BASE 0x00300000 /* Internal SRAM base address */
diff -Nur linux/arch/arm/mach-at91/Makefile rpi/arch/arm/mach-at91/Makefile
--- linux/arch/arm/mach-at91/Makefile 2014-05-29 12:18:16.787564057 +0900
+++ rpi/arch/arm/mach-at91/Makefile 2014-05-29 11:49:03.928967451 +0900
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-obj-y := irq.o gpio.o setup.o
+obj-y := irq.o gpio.o setup.o sysirq_mask.o
obj-m :=
obj-n :=
obj- :=
diff -Nur linux/arch/arm/mach-at91/sam9_smc.c rpi/arch/arm/mach-at91/sam9_smc.c
--- linux/arch/arm/mach-at91/sam9_smc.c 2014-05-29 12:18:16.805563945 +0900
+++ rpi/arch/arm/mach-at91/sam9_smc.c 2014-05-29 11:49:03.958967199 +0900
@@ -101,7 +101,7 @@
/* Pulse register */
val = __raw_readl(base + AT91_SMC_PULSE);
- config->nwe_setup = val & AT91_SMC_NWEPULSE;
+ config->nwe_pulse = val & AT91_SMC_NWEPULSE;
config->ncs_write_pulse = (val & AT91_SMC_NCS_WRPULSE) >> 8;
config->nrd_pulse = (val & AT91_SMC_NRDPULSE) >> 16;
config->ncs_read_pulse = (val & AT91_SMC_NCS_RDPULSE) >> 24;
diff -Nur linux/arch/arm/mach-at91/sama5d3.c rpi/arch/arm/mach-at91/sama5d3.c
--- linux/arch/arm/mach-at91/sama5d3.c 2014-05-29 12:18:16.805563945 +0900
+++ rpi/arch/arm/mach-at91/sama5d3.c 2014-05-29 11:49:03.958967199 +0900
@@ -95,19 +95,19 @@
.name = "twi0_clk",
.pid = SAMA5D3_ID_TWI0,
.type = CLK_TYPE_PERIPHERAL,
- .div = AT91_PMC_PCR_DIV2,
+ .div = AT91_PMC_PCR_DIV8,
};
static struct clk twi1_clk = {
.name = "twi1_clk",
.pid = SAMA5D3_ID_TWI1,
.type = CLK_TYPE_PERIPHERAL,
- .div = AT91_PMC_PCR_DIV2,
+ .div = AT91_PMC_PCR_DIV8,
};
static struct clk twi2_clk = {
.name = "twi2_clk",
.pid = SAMA5D3_ID_TWI2,
.type = CLK_TYPE_PERIPHERAL,
- .div = AT91_PMC_PCR_DIV2,
+ .div = AT91_PMC_PCR_DIV8,
};
static struct clk mmc0_clk = {
.name = "mci0_clk",
@@ -371,7 +371,13 @@
at91_init_sram(0, SAMA5D3_SRAM_BASE, SAMA5D3_SRAM_SIZE);
}
+static void __init sama5d3_initialize(void)
+{
+ at91_sysirq_mask_rtc(SAMA5D3_BASE_RTC);
+}
+
AT91_SOC_START(sama5d3)
.map_io = sama5d3_map_io,
.register_clocks = sama5d3_register_clocks,
+ .init = sama5d3_initialize,
AT91_SOC_END
diff -Nur linux/arch/arm/mach-at91/sysirq_mask.c rpi/arch/arm/mach-at91/sysirq_mask.c
--- linux/arch/arm/mach-at91/sysirq_mask.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-at91/sysirq_mask.c 2014-05-29 11:49:03.959967191 +0900
@@ -0,0 +1,71 @@
+/*
+ * sysirq_mask.c - System-interrupt masking
+ *
+ * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com>
+ *
+ * Functions to disable system interrupts from backup-powered peripherals.
+ *
+ * The RTC and RTT-peripherals are generally powered by backup power (VDDBU)
+ * and are not reset on wake-up, user, watchdog or software reset. This means
+ * that their interrupts may be enabled during early boot (e.g. after a user
+ * reset).
+ *
+ * As the RTC and RTT share the system-interrupt line with the PIT, an
+ * interrupt occurring before a handler has been installed would lead to the
+ * system interrupt being disabled and prevent the system from booting.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <mach/at91_rtt.h>
+
+#include "generic.h"
+
+#define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */
+#define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */
+
+void __init at91_sysirq_mask_rtc(u32 rtc_base)
+{
+ void __iomem *base;
+ u32 mask;
+
+ base = ioremap(rtc_base, 64);
+ if (!base)
+ return;
+
+ mask = readl_relaxed(base + AT91_RTC_IMR);
+ if (mask) {
+ pr_info("AT91: Disabling rtc irq\n");
+ writel_relaxed(mask, base + AT91_RTC_IDR);
+ (void)readl_relaxed(base + AT91_RTC_IMR); /* flush */
+ }
+
+ iounmap(base);
+}
+
+void __init at91_sysirq_mask_rtt(u32 rtt_base)
+{
+ void __iomem *base;
+ void __iomem *reg;
+ u32 mode;
+
+ base = ioremap(rtt_base, 16);
+ if (!base)
+ return;
+
+ reg = base + AT91_RTT_MR;
+
+ mode = readl_relaxed(reg);
+ if (mode & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)) {
+ pr_info("AT91: Disabling rtt irq\n");
+ mode &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
+ writel_relaxed(mode, reg);
+ (void)readl_relaxed(reg); /* flush */
+ }
+
+ iounmap(base);
+}
diff -Nur linux/arch/arm/mach-bcm2708/armctrl.c rpi/arch/arm/mach-bcm2708/armctrl.c
--- linux/arch/arm/mach-bcm2708/armctrl.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/armctrl.c 2014-05-29 11:49:03.961967174 +0900
@@ -0,0 +1,219 @@
+/*
+ * linux/arch/arm/mach-bcm2708/armctrl.c
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/version.h>
+#include <linux/syscore_ops.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include "armctrl.h"
+
+/* For support of kernels >= 3.0 assume only one VIC for now*/
+static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = {
+ INTERRUPT_VC_JPEG,
+ INTERRUPT_VC_USB,
+ INTERRUPT_VC_3D,
+ INTERRUPT_VC_DMA2,
+ INTERRUPT_VC_DMA3,
+ INTERRUPT_VC_I2C,
+ INTERRUPT_VC_SPI,
+ INTERRUPT_VC_I2SPCM,
+ INTERRUPT_VC_SDIO,
+ INTERRUPT_VC_UART,
+ INTERRUPT_VC_ARASANSDIO
+};
+
+static void armctrl_mask_irq(struct irq_data *d)
+{
+ static const unsigned int disables[4] = {
+ ARM_IRQ_DIBL1,
+ ARM_IRQ_DIBL2,
+ ARM_IRQ_DIBL3,
+ 0
+ };
+
+ if (d->irq >= FIQ_START) {
+ writel(0, __io_address(ARM_IRQ_FAST));
+ } else {
+ unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
+ writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3]));
+ }
+}
+
+static void armctrl_unmask_irq(struct irq_data *d)
+{
+ static const unsigned int enables[4] = {
+ ARM_IRQ_ENBL1,
+ ARM_IRQ_ENBL2,
+ ARM_IRQ_ENBL3,
+ 0
+ };
+
+ if (d->irq >= FIQ_START) {
+ unsigned int data =
+ (unsigned int)irq_get_chip_data(d->irq) - FIQ_START;
+ writel(0x80 | data, __io_address(ARM_IRQ_FAST));
+ } else {
+ unsigned int data = (unsigned int)irq_get_chip_data(d->irq);
+ writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3]));
+ }
+}
+
+#if defined(CONFIG_PM)
+
+/* for kernels 3.xx use the new syscore_ops apis but for older kernels use the sys dev class */
+
+/* Static defines
+ * struct armctrl_device - VIC PM device (< 3.xx)
+ * @sysdev: The system device which is registered. (< 3.xx)
+ * @irq: The IRQ number for the base of the VIC.
+ * @base: The register base for the VIC.
+ * @resume_sources: A bitmask of interrupts for resume.
+ * @resume_irqs: The IRQs enabled for resume.
+ * @int_select: Save for VIC_INT_SELECT.
+ * @int_enable: Save for VIC_INT_ENABLE.
+ * @soft_int: Save for VIC_INT_SOFT.
+ * @protect: Save for VIC_PROTECT.
+ */
+struct armctrl_info {
+ void __iomem *base;
+ int irq;
+ u32 resume_sources;
+ u32 resume_irqs;
+ u32 int_select;
+ u32 int_enable;
+ u32 soft_int;
+ u32 protect;
+} armctrl;
+
+static int armctrl_suspend(void)
+{
+ return 0;
+}
+
+static void armctrl_resume(void)
+{
+ return;
+}
+
+/**
+ * armctrl_pm_register - Register a VIC for later power management control
+ * @base: The base address of the VIC.
+ * @irq: The base IRQ for the VIC.
+ * @resume_sources: bitmask of interrupts allowed for resume sources.
+ *
+ * For older kernels (< 3.xx) do -
+ * Register the VIC with the system device tree so that it can be notified
+ * of suspend and resume requests and ensure that the correct actions are
+ * taken to re-instate the settings on resume.
+ */
+static void __init armctrl_pm_register(void __iomem * base, unsigned int irq,
+ u32 resume_sources)
+{
+ armctrl.base = base;
+ armctrl.resume_sources = resume_sources;
+ armctrl.irq = irq;
+}
+
+static int armctrl_set_wake(struct irq_data *d, unsigned int on)
+{
+ unsigned int off = d->irq & 31;
+ u32 bit = 1 << off;
+
+ if (!(bit & armctrl.resume_sources))
+ return -EINVAL;
+
+ if (on)
+ armctrl.resume_irqs |= bit;
+ else
+ armctrl.resume_irqs &= ~bit;
+
+ return 0;
+}
+
+#else
+static inline void armctrl_pm_register(void __iomem * base, unsigned int irq,
+ u32 arg1)
+{
+}
+
+#define armctrl_suspend NULL
+#define armctrl_resume NULL
+#define armctrl_set_wake NULL
+#endif /* CONFIG_PM */
+
+static struct syscore_ops armctrl_syscore_ops = {
+ .suspend = armctrl_suspend,
+ .resume = armctrl_resume,
+};
+
+/**
+ * armctrl_syscore_init - initicall to register VIC pm functions
+ *
+ * This is called via late_initcall() to register
+ * the resources for the VICs due to the early
+ * nature of the VIC's registration.
+*/
+static int __init armctrl_syscore_init(void)
+{
+ register_syscore_ops(&armctrl_syscore_ops);
+ return 0;
+}
+
+late_initcall(armctrl_syscore_init);
+
+static struct irq_chip armctrl_chip = {
+ .name = "ARMCTRL",
+ .irq_ack = armctrl_mask_irq,
+ .irq_mask = armctrl_mask_irq,
+ .irq_unmask = armctrl_unmask_irq,
+ .irq_set_wake = armctrl_set_wake,
+};
+
+/**
+ * armctrl_init - initialise a vectored interrupt controller
+ * @base: iomem base address
+ * @irq_start: starting interrupt number, must be muliple of 32
+ * @armctrl_sources: bitmask of interrupt sources to allow
+ * @resume_sources: bitmask of interrupt sources to allow for resume
+ */
+int __init armctrl_init(void __iomem * base, unsigned int irq_start,
+ u32 armctrl_sources, u32 resume_sources)
+{
+ unsigned int irq;
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ unsigned int data = irq;
+ if (irq >= INTERRUPT_JPEG && irq <= INTERRUPT_ARASANSDIO)
+ data = remap_irqs[irq - INTERRUPT_JPEG];
+
+ irq_set_chip(irq, &armctrl_chip);
+ irq_set_chip_data(irq, (void *)data);
+ irq_set_handler(irq, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED);
+ }
+
+ armctrl_pm_register(base, irq_start, resume_sources);
+ init_FIQ(FIQ_START);
+ return 0;
+}
diff -Nur linux/arch/arm/mach-bcm2708/armctrl.h rpi/arch/arm/mach-bcm2708/armctrl.h
--- linux/arch/arm/mach-bcm2708/armctrl.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/armctrl.h 2014-05-29 11:49:03.961967174 +0900
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/arm/mach-bcm2708/armctrl.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 __BCM2708_ARMCTRL_H
+#define __BCM2708_ARMCTRL_H
+
+extern int __init armctrl_init(void __iomem * base, unsigned int irq_start,
+ u32 armctrl_sources, u32 resume_sources);
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/bcm2708.c rpi/arch/arm/mach-bcm2708/bcm2708.c
--- linux/arch/arm/mach-bcm2708/bcm2708.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/bcm2708.c 2014-05-29 11:49:03.961967174 +0900
@@ -0,0 +1,1031 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708.c
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/serial_8250.h>
+#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
+#include <linux/interrupt.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/clockchips.h>
+#include <linux/cnt32_to_63.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/w1-gpio.h>
+
+#include <linux/version.h>
+#include <linux/clkdev.h>
+#include <asm/system.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <linux/sched_clock.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/timex.h>
+#include <mach/dma.h>
+#include <mach/vcio.h>
+#include <mach/system.h>
+
+#include <linux/delay.h>
+
+#include "bcm2708.h"
+#include "armctrl.h"
+#include "clock.h"
+
+#ifdef CONFIG_BCM_VC_CMA
+#include <linux/broadcom/vc_cma.h>
+#endif
+
+
+/* Effectively we have an IOMMU (ARM<->VideoCore map) that is set up to
+ * give us IO access only to 64Mbytes of physical memory (26 bits). We could
+ * represent this window by setting our dmamasks to 26 bits but, in fact
+ * we're not going to use addresses outside this range (they're not in real
+ * memory) so we don't bother.
+ *
+ * In the future we might include code to use this IOMMU to remap other
+ * physical addresses onto VideoCore memory then the use of 32-bits would be
+ * more legitimate.
+ */
+#define DMA_MASK_BITS_COMMON 32
+
+// use GPIO 4 for the one-wire GPIO pin, if enabled
+#define W1_GPIO 4
+// ensure one-wire GPIO pullup is disabled by default
+#define W1_PULLUP -1
+
+/* command line parameters */
+static unsigned boardrev, serial;
+static unsigned uart_clock;
+static unsigned disk_led_gpio = 16;
+static unsigned disk_led_active_low = 1;
+static unsigned reboot_part = 0;
+static unsigned w1_gpio_pin = W1_GPIO;
+static unsigned w1_gpio_pullup = W1_PULLUP;
+
+static void __init bcm2708_init_led(void);
+
+void __init bcm2708_init_irq(void)
+{
+ armctrl_init(__io_address(ARMCTRL_IC_BASE), 0, 0, 0);
+}
+
+static struct map_desc bcm2708_io_desc[] __initdata = {
+ {
+ .virtual = IO_ADDRESS(ARMCTRL_BASE),
+ .pfn = __phys_to_pfn(ARMCTRL_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE},
+ {
+ .virtual = IO_ADDRESS(UART0_BASE),
+ .pfn = __phys_to_pfn(UART0_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE},
+ {
+ .virtual = IO_ADDRESS(UART1_BASE),
+ .pfn = __phys_to_pfn(UART1_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE},
+ {
+ .virtual = IO_ADDRESS(DMA_BASE),
+ .pfn = __phys_to_pfn(DMA_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE},
+ {
+ .virtual = IO_ADDRESS(MCORE_BASE),
+ .pfn = __phys_to_pfn(MCORE_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE},
+ {
+ .virtual = IO_ADDRESS(ST_BASE),
+ .pfn = __phys_to_pfn(ST_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE},
+ {
+ .virtual = IO_ADDRESS(USB_BASE),
+ .pfn = __phys_to_pfn(USB_BASE),
+ .length = SZ_128K,
+ .type = MT_DEVICE},
+ {
+ .virtual = IO_ADDRESS(PM_BASE),
+ .pfn = __phys_to_pfn(PM_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE},
+ {
+ .virtual = IO_ADDRESS(GPIO_BASE),
+ .pfn = __phys_to_pfn(GPIO_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE}
+};
+
+void __init bcm2708_map_io(void)
+{
+ iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc));
+}
+
+/* The STC is a free running counter that increments at the rate of 1MHz */
+#define STC_FREQ_HZ 1000000
+
+static inline uint32_t timer_read(void)
+{
+ /* STC: a free running counter that increments at the rate of 1MHz */
+ return readl(__io_address(ST_BASE + 0x04));
+}
+
+static unsigned long bcm2708_read_current_timer(void)
+{
+ return timer_read();
+}
+
+static u32 notrace bcm2708_read_sched_clock(void)
+{
+ return timer_read();
+}
+
+static cycle_t clksrc_read(struct clocksource *cs)
+{
+ return timer_read();
+}
+
+static struct clocksource clocksource_stc = {
+ .name = "stc",
+ .rating = 300,
+ .read = clksrc_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+unsigned long frc_clock_ticks32(void)
+{
+ return timer_read();
+}
+
+static void __init bcm2708_clocksource_init(void)
+{
+ if (clocksource_register_hz(&clocksource_stc, STC_FREQ_HZ)) {
+ printk(KERN_ERR "timer: failed to initialize clock "
+ "source %s\n", clocksource_stc.name);
+ }
+}
+
+
+/*
+ * These are fixed clocks.
+ */
+static struct clk ref24_clk = {
+ .rate = UART0_CLOCK, /* The UART is clocked at 3MHz via APB_CLK */
+};
+
+static struct clk osc_clk = {
+#ifdef CONFIG_ARCH_BCM2708_CHIPIT
+ .rate = 27000000,
+#else
+ .rate = 500000000, /* ARM clock is set from the VideoCore booter */
+#endif
+};
+
+/* warning - the USB needs a clock > 34MHz */
+
+static struct clk sdhost_clk = {
+#ifdef CONFIG_ARCH_BCM2708_CHIPIT
+ .rate = 4000000, /* 4MHz */
+#else
+ .rate = 250000000, /* 250MHz */
+#endif
+};
+
+static struct clk_lookup lookups[] = {
+ { /* UART0 */
+ .dev_id = "dev:f1",
+ .clk = &ref24_clk,
+ },
+ { /* USB */
+ .dev_id = "bcm2708_usb",
+ .clk = &osc_clk,
+ }, { /* SPI */
+ .dev_id = "bcm2708_spi.0",
+ .clk = &sdhost_clk,
+ }, { /* BSC0 */
+ .dev_id = "bcm2708_i2c.0",
+ .clk = &sdhost_clk,
+ }, { /* BSC1 */
+ .dev_id = "bcm2708_i2c.1",
+ .clk = &sdhost_clk,
+ }
+};
+
+#define UART0_IRQ { IRQ_UART, 0 /*NO_IRQ*/ }
+#define UART0_DMA { 15, 14 }
+
+AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);
+
+static struct amba_device *amba_devs[] __initdata = {
+ &uart0_device,
+};
+
+static struct resource bcm2708_dmaman_resources[] = {
+ {
+ .start = DMA_BASE,
+ .end = DMA_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device bcm2708_dmaman_device = {
+ .name = BCM_DMAMAN_DRIVER_NAME,
+ .id = 0, /* first bcm2708_dma */
+ .resource = bcm2708_dmaman_resources,
+ .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources),
+};
+
+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
+static struct w1_gpio_platform_data w1_gpio_pdata = {
+ .pin = W1_GPIO,
+ .ext_pullup_enable_pin = W1_PULLUP,
+ .is_open_drain = 0,
+};
+
+static struct platform_device w1_device = {
+ .name = "w1-gpio",
+ .id = -1,
+ .dev.platform_data = &w1_gpio_pdata,
+};
+#endif
+
+static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+static struct platform_device bcm2708_fb_device = {
+ .name = "bcm2708_fb",
+ .id = -1, /* only one bcm2708_fb */
+ .resource = NULL,
+ .num_resources = 0,
+ .dev = {
+ .dma_mask = &fb_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+ },
+};
+
+static struct plat_serial8250_port bcm2708_uart1_platform_data[] = {
+ {
+ .mapbase = UART1_BASE + 0x40,
+ .irq = IRQ_AUX,
+ .uartclk = 125000000,
+ .regshift = 2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST,
+ .type = PORT_8250,
+ },
+ {},
+};
+
+static struct platform_device bcm2708_uart1_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = bcm2708_uart1_platform_data,
+ },
+};
+
+static struct resource bcm2708_usb_resources[] = {
+ [0] = {
+ .start = USB_BASE,
+ .end = USB_BASE + SZ_128K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MPHI_BASE,
+ .end = MPHI_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = IRQ_HOSTPORT,
+ .end = IRQ_HOSTPORT,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = IRQ_USB,
+ .end = IRQ_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+
+static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+static struct platform_device bcm2708_usb_device = {
+ .name = "bcm2708_usb",
+ .id = -1, /* only one bcm2708_usb */
+ .resource = bcm2708_usb_resources,
+ .num_resources = ARRAY_SIZE(bcm2708_usb_resources),
+ .dev = {
+ .dma_mask = &usb_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+ },
+};
+
+static struct resource bcm2708_vcio_resources[] = {
+ [0] = { /* mailbox/semaphore/doorbell access */
+ .start = MCORE_BASE,
+ .end = MCORE_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+static struct platform_device bcm2708_vcio_device = {
+ .name = BCM_VCIO_DRIVER_NAME,
+ .id = -1, /* only one VideoCore I/O area */
+ .resource = bcm2708_vcio_resources,
+ .num_resources = ARRAY_SIZE(bcm2708_vcio_resources),
+ .dev = {
+ .dma_mask = &vcio_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+ },
+};
+
+#ifdef CONFIG_BCM2708_GPIO
+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
+
+static struct resource bcm2708_gpio_resources[] = {
+ [0] = { /* general purpose I/O */
+ .start = GPIO_BASE,
+ .end = GPIO_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+static struct platform_device bcm2708_gpio_device = {
+ .name = BCM_GPIO_DRIVER_NAME,
+ .id = -1, /* only one VideoCore I/O area */
+ .resource = bcm2708_gpio_resources,
+ .num_resources = ARRAY_SIZE(bcm2708_gpio_resources),
+ .dev = {
+ .dma_mask = &gpio_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+ },
+};
+#endif
+
+static struct resource bcm2708_systemtimer_resources[] = {
+ [0] = { /* system timer access */
+ .start = ST_BASE,
+ .end = ST_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_TIMER3,
+ .end = IRQ_TIMER3,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+static struct platform_device bcm2708_systemtimer_device = {
+ .name = "bcm2708_systemtimer",
+ .id = -1, /* only one VideoCore I/O area */
+ .resource = bcm2708_systemtimer_resources,
+ .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources),
+ .dev = {
+ .dma_mask = &systemtimer_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+ },
+};
+
+#ifdef CONFIG_MMC_SDHCI_BCM2708 /* Arasan emmc SD */
+static struct resource bcm2708_emmc_resources[] = {
+ [0] = {
+ .start = EMMC_BASE,
+ .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */
+ /* the memory map actually makes SZ_4K available */
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_ARASANSDIO,
+ .end = IRQ_ARASANSDIO,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 bcm2708_emmc_dmamask = 0xffffffffUL;
+
+struct platform_device bcm2708_emmc_device = {
+ .name = "bcm2708_sdhci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bcm2708_emmc_resources),
+ .resource = bcm2708_emmc_resources,
+ .dev = {
+ .dma_mask = &bcm2708_emmc_dmamask,
+ .coherent_dma_mask = 0xffffffffUL},
+};
+#endif /* CONFIG_MMC_SDHCI_BCM2708 */
+
+static struct resource bcm2708_powerman_resources[] = {
+ [0] = {
+ .start = PM_BASE,
+ .end = PM_BASE + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+struct platform_device bcm2708_powerman_device = {
+ .name = "bcm2708_powerman",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bcm2708_powerman_resources),
+ .resource = bcm2708_powerman_resources,
+ .dev = {
+ .dma_mask = &powerman_dmamask,
+ .coherent_dma_mask = 0xffffffffUL},
+};
+
+
+static struct platform_device bcm2708_alsa_devices[] = {
+ [0] = {
+ .name = "bcm2835_AUD0",
+ .id = 0, /* first audio device */
+ .resource = 0,
+ .num_resources = 0,
+ },
+ [1] = {
+ .name = "bcm2835_AUD1",
+ .id = 1, /* second audio device */
+ .resource = 0,
+ .num_resources = 0,
+ },
+ [2] = {
+ .name = "bcm2835_AUD2",
+ .id = 2, /* third audio device */
+ .resource = 0,
+ .num_resources = 0,
+ },
+ [3] = {
+ .name = "bcm2835_AUD3",
+ .id = 3, /* forth audio device */
+ .resource = 0,
+ .num_resources = 0,
+ },
+ [4] = {
+ .name = "bcm2835_AUD4",
+ .id = 4, /* fifth audio device */
+ .resource = 0,
+ .num_resources = 0,
+ },
+ [5] = {
+ .name = "bcm2835_AUD5",
+ .id = 5, /* sixth audio device */
+ .resource = 0,
+ .num_resources = 0,
+ },
+ [6] = {
+ .name = "bcm2835_AUD6",
+ .id = 6, /* seventh audio device */
+ .resource = 0,
+ .num_resources = 0,
+ },
+ [7] = {
+ .name = "bcm2835_AUD7",
+ .id = 7, /* eighth audio device */
+ .resource = 0,
+ .num_resources = 0,
+ },
+};
+
+static struct resource bcm2708_spi_resources[] = {
+ {
+ .start = SPI0_BASE,
+ .end = SPI0_BASE + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_SPI,
+ .end = IRQ_SPI,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+
+static u64 bcm2708_spi_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+static struct platform_device bcm2708_spi_device = {
+ .name = "bcm2708_spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bcm2708_spi_resources),
+ .resource = bcm2708_spi_resources,
+ .dev = {
+ .dma_mask = &bcm2708_spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON)},
+};
+
+#ifdef CONFIG_BCM2708_SPIDEV
+static struct spi_board_info bcm2708_spi_devices[] = {
+#ifdef CONFIG_SPI_SPIDEV
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 500000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ }, {
+ .modalias = "spidev",
+ .max_speed_hz = 500000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ }
+#endif
+};
+#endif
+
+static struct resource bcm2708_bsc0_resources[] = {
+ {
+ .start = BSC0_BASE,
+ .end = BSC0_BASE + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = INTERRUPT_I2C,
+ .end = INTERRUPT_I2C,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device bcm2708_bsc0_device = {
+ .name = "bcm2708_i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bcm2708_bsc0_resources),
+ .resource = bcm2708_bsc0_resources,
+};
+
+
+static struct resource bcm2708_bsc1_resources[] = {
+ {
+ .start = BSC1_BASE,
+ .end = BSC1_BASE + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = INTERRUPT_I2C,
+ .end = INTERRUPT_I2C,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device bcm2708_bsc1_device = {
+ .name = "bcm2708_i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bcm2708_bsc1_resources),
+ .resource = bcm2708_bsc1_resources,
+};
+
+static struct platform_device bcm2835_hwmon_device = {
+ .name = "bcm2835_hwmon",
+};
+
+static struct platform_device bcm2835_thermal_device = {
+ .name = "bcm2835_thermal",
+};
+
+#ifdef CONFIG_SND_BCM2708_SOC_I2S_MODULE
+static struct resource bcm2708_i2s_resources[] = {
+ {
+ .start = I2S_BASE,
+ .end = I2S_BASE + 0x20,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PCM_CLOCK_BASE,
+ .end = PCM_CLOCK_BASE + 0x02,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device bcm2708_i2s_device = {
+ .name = "bcm2708-i2s",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources),
+ .resource = bcm2708_i2s_resources,
+};
+#endif
+
+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE)
+static struct platform_device snd_hifiberry_dac_device = {
+ .name = "snd-hifiberry-dac",
+ .id = 0,
+ .num_resources = 0,
+};
+
+static struct platform_device snd_pcm5102a_codec_device = {
+ .name = "pcm5102a-codec",
+ .id = -1,
+ .num_resources = 0,
+};
+#endif
+
+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE)
+static struct platform_device snd_hifiberry_digi_device = {
+ .name = "snd-hifiberry-digi",
+ .id = 0,
+ .num_resources = 0,
+};
+
+static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("wm8804", 0x3b)
+ },
+};
+
+#endif
+
+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE)
+static struct platform_device snd_rpi_dac_device = {
+ .name = "snd-rpi-dac",
+ .id = 0,
+ .num_resources = 0,
+};
+
+static struct platform_device snd_pcm1794a_codec_device = {
+ .name = "pcm1794a-codec",
+ .id = -1,
+ .num_resources = 0,
+};
+#endif
+
+
+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE)
+static struct platform_device snd_rpi_iqaudio_dac_device = {
+ .name = "snd-rpi-iqaudio-dac",
+ .id = 0,
+ .num_resources = 0,
+};
+
+// Use the actual device name rather than generic driver name
+static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("pcm5122", 0x4c)
+ },
+};
+#endif
+
+int __init bcm_register_device(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = platform_device_register(pdev);
+ if (ret)
+ pr_debug("Unable to register platform device '%s': %d\n",
+ pdev->name, ret);
+
+ return ret;
+}
+
+int calc_rsts(int partition)
+{
+ return PM_PASSWORD |
+ ((partition & (1 << 0)) << 0) |
+ ((partition & (1 << 1)) << 1) |
+ ((partition & (1 << 2)) << 2) |
+ ((partition & (1 << 3)) << 3) |
+ ((partition & (1 << 4)) << 4) |
+ ((partition & (1 << 5)) << 5);
+}
+
+static void bcm2708_restart(enum reboot_mode mode, const char *cmd)
+{
+ extern char bcm2708_reboot_mode;
+ uint32_t pm_rstc, pm_wdog;
+ uint32_t timeout = 10;
+ uint32_t pm_rsts = 0;
+
+ if(bcm2708_reboot_mode == 'q')
+ {
+ // NOOBS < 1.3 booting with reboot=q
+ pm_rsts = readl(__io_address(PM_RSTS));
+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRQ_SET;
+ }
+ else if(bcm2708_reboot_mode == 'p')
+ {
+ // NOOBS < 1.3 halting
+ pm_rsts = readl(__io_address(PM_RSTS));
+ pm_rsts = PM_PASSWORD | pm_rsts | PM_RSTS_HADWRH_SET;
+ }
+ else
+ {
+ pm_rsts = calc_rsts(reboot_part);
+ }
+
+ writel(pm_rsts, __io_address(PM_RSTS));
+
+ /* Setup watchdog for reset */
+ pm_rstc = readl(__io_address(PM_RSTC));
+
+ pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0)
+ pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
+
+ writel(pm_wdog, __io_address(PM_WDOG));
+ writel(pm_rstc, __io_address(PM_RSTC));
+}
+
+/* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */
+static void bcm2708_power_off(void)
+{
+ extern char bcm2708_reboot_mode;
+ if(bcm2708_reboot_mode == 'q')
+ {
+ // NOOBS < v1.3
+ bcm2708_restart('p', "");
+ }
+ else
+ {
+ /* partition 63 is special code for HALT the bootloader knows not to boot*/
+ reboot_part = 63;
+ /* continue with normal reset mechanism */
+ bcm2708_restart(0, "");
+ }
+}
+
+void __init bcm2708_init(void)
+{
+ int i;
+
+#if defined(CONFIG_BCM_VC_CMA)
+ vc_cma_early_init();
+#endif
+ printk("bcm2708.uart_clock = %d\n", uart_clock);
+ pm_power_off = bcm2708_power_off;
+
+ if (uart_clock)
+ lookups[0].clk->rate = uart_clock;
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+
+ bcm_register_device(&bcm2708_dmaman_device);
+ bcm_register_device(&bcm2708_vcio_device);
+#ifdef CONFIG_BCM2708_GPIO
+ bcm_register_device(&bcm2708_gpio_device);
+#endif
+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
+ w1_gpio_pdata.pin = w1_gpio_pin;
+ w1_gpio_pdata.ext_pullup_enable_pin = w1_gpio_pullup;
+ platform_device_register(&w1_device);
+#endif
+ bcm_register_device(&bcm2708_systemtimer_device);
+ bcm_register_device(&bcm2708_fb_device);
+ bcm_register_device(&bcm2708_usb_device);
+ bcm_register_device(&bcm2708_uart1_device);
+ bcm_register_device(&bcm2708_powerman_device);
+
+#ifdef CONFIG_MMC_SDHCI_BCM2708
+ bcm_register_device(&bcm2708_emmc_device);
+#endif
+ bcm2708_init_led();
+ for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
+ bcm_register_device(&bcm2708_alsa_devices[i]);
+
+ bcm_register_device(&bcm2708_spi_device);
+ bcm_register_device(&bcm2708_bsc0_device);
+ bcm_register_device(&bcm2708_bsc1_device);
+
+ bcm_register_device(&bcm2835_hwmon_device);
+ bcm_register_device(&bcm2835_thermal_device);
+
+#ifdef CONFIG_SND_BCM2708_SOC_I2S_MODULE
+ bcm_register_device(&bcm2708_i2s_device);
+#endif
+
+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE)
+ bcm_register_device(&snd_hifiberry_dac_device);
+ bcm_register_device(&snd_pcm5102a_codec_device);
+#endif
+
+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE)
+ bcm_register_device(&snd_hifiberry_digi_device);
+ i2c_register_board_info(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices));
+#endif
+
+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE)
+ bcm_register_device(&snd_rpi_dac_device);
+ bcm_register_device(&snd_pcm1794a_codec_device);
+#endif
+
+#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE)
+ bcm_register_device(&snd_rpi_iqaudio_dac_device);
+ i2c_register_board_info(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices));
+#endif
+
+
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+ amba_device_register(d, &iomem_resource);
+ }
+ system_rev = boardrev;
+ system_serial_low = serial;
+
+#ifdef CONFIG_BCM2708_SPIDEV
+ spi_register_board_info(bcm2708_spi_devices,
+ ARRAY_SIZE(bcm2708_spi_devices));
+#endif
+}
+
+static void timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_ONESHOT: /* Leave the timer disabled, .set_next_event will enable it */
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ break;
+ case CLOCK_EVT_MODE_PERIODIC:
+
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_RESUME:
+
+ default:
+ printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n",
+ (int)mode);
+ break;
+ }
+
+}
+
+static int timer_set_next_event(unsigned long cycles,
+ struct clock_event_device *unused)
+{
+ unsigned long stc;
+ do {
+ stc = readl(__io_address(ST_BASE + 0x04));
+ /* We could take a FIQ here, which may push ST above STC3 */
+ writel(stc + cycles, __io_address(ST_BASE + 0x18));
+ } while ((signed long) (readl(__io_address(ST_BASE + 0x04)) - stc)
+ >= (signed long) cycles);
+ return 0;
+}
+
+static struct clock_event_device timer0_clockevent = {
+ .name = "timer0",
+ .shift = 32,
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = timer_set_mode,
+ .set_next_event = timer_set_next_event,
+};
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t bcm2708_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &timer0_clockevent;
+
+ writel(1 << 3, __io_address(ST_BASE + 0x00)); /* stcs clear timer int */
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction bcm2708_timer_irq = {
+ .name = "BCM2708 Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = bcm2708_timer_interrupt,
+};
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+
+static struct delay_timer bcm2708_delay_timer = {
+ .read_current_timer = bcm2708_read_current_timer,
+ .freq = STC_FREQ_HZ,
+};
+
+static void __init bcm2708_timer_init(void)
+{
+ /* init high res timer */
+ bcm2708_clocksource_init();
+
+ /*
+ * Initialise to a known state (all timers off)
+ */
+ writel(0, __io_address(ARM_T_CONTROL));
+ /*
+ * Make irqs happen for the system timer
+ */
+ setup_irq(IRQ_TIMER3, &bcm2708_timer_irq);
+
+ setup_sched_clock(bcm2708_read_sched_clock, 32, STC_FREQ_HZ);
+
+ timer0_clockevent.mult =
+ div_sc(STC_FREQ_HZ, NSEC_PER_SEC, timer0_clockevent.shift);
+ timer0_clockevent.max_delta_ns =
+ clockevent_delta2ns(0xffffffff, &timer0_clockevent);
+ timer0_clockevent.min_delta_ns =
+ clockevent_delta2ns(0xf, &timer0_clockevent);
+
+ timer0_clockevent.cpumask = cpumask_of(0);
+ clockevents_register_device(&timer0_clockevent);
+
+ register_current_timer_delay(&bcm2708_delay_timer);
+}
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led bcm2708_leds[] = {
+ [0] = {
+ .gpio = 16,
+ .name = "led0",
+ .default_trigger = "mmc0",
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led_platform_data bcm2708_led_pdata = {
+ .num_leds = ARRAY_SIZE(bcm2708_leds),
+ .leds = bcm2708_leds,
+};
+
+static struct platform_device bcm2708_led_device = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &bcm2708_led_pdata,
+ },
+};
+
+static void __init bcm2708_init_led(void)
+{
+ bcm2708_leds[0].gpio = disk_led_gpio;
+ bcm2708_leds[0].active_low = disk_led_active_low;
+ platform_device_register(&bcm2708_led_device);
+}
+#else
+static inline void bcm2708_init_led(void)
+{
+}
+#endif
+
+void __init bcm2708_init_early(void)
+{
+ /*
+ * Some devices allocate their coherent buffers from atomic
+ * context. Increase size of atomic coherent pool to make sure such
+ * the allocations won't fail.
+ */
+ init_dma_coherent_pool_size(SZ_4M);
+}
+
+static void __init board_reserve(void)
+{
+#if defined(CONFIG_BCM_VC_CMA)
+ vc_cma_reserve();
+#endif
+}
+
+MACHINE_START(BCM2708, "BCM2708")
+ /* Maintainer: Broadcom Europe Ltd. */
+ .map_io = bcm2708_map_io,
+ .init_irq = bcm2708_init_irq,
+ .init_time = bcm2708_timer_init,
+ .init_machine = bcm2708_init,
+ .init_early = bcm2708_init_early,
+ .reserve = board_reserve,
+ .restart = bcm2708_restart,
+MACHINE_END
+
+module_param(boardrev, uint, 0644);
+module_param(serial, uint, 0644);
+module_param(uart_clock, uint, 0644);
+module_param(disk_led_gpio, uint, 0644);
+module_param(disk_led_active_low, uint, 0644);
+module_param(reboot_part, uint, 0644);
+module_param(w1_gpio_pin, uint, 0644);
+module_param(w1_gpio_pullup, uint, 0644);
diff -Nur linux/arch/arm/mach-bcm2708/bcm2708_gpio.c rpi/arch/arm/mach-bcm2708/bcm2708_gpio.c
--- linux/arch/arm/mach-bcm2708/bcm2708_gpio.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/bcm2708_gpio.c 2014-05-29 11:49:03.962967166 +0900
@@ -0,0 +1,361 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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.
+ *
+ */
+
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <mach/gpio.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <mach/platform.h>
+
+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
+#define DRIVER_NAME BCM_GPIO_DRIVER_NAME
+#define BCM_GPIO_USE_IRQ 1
+
+#define GPIOFSEL(x) (0x00+(x)*4)
+#define GPIOSET(x) (0x1c+(x)*4)
+#define GPIOCLR(x) (0x28+(x)*4)
+#define GPIOLEV(x) (0x34+(x)*4)
+#define GPIOEDS(x) (0x40+(x)*4)
+#define GPIOREN(x) (0x4c+(x)*4)
+#define GPIOFEN(x) (0x58+(x)*4)
+#define GPIOHEN(x) (0x64+(x)*4)
+#define GPIOLEN(x) (0x70+(x)*4)
+#define GPIOAREN(x) (0x7c+(x)*4)
+#define GPIOAFEN(x) (0x88+(x)*4)
+#define GPIOUD(x) (0x94+(x)*4)
+#define GPIOUDCLK(x) (0x98+(x)*4)
+
+enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT,
+ GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4,
+ GPIO_FSEL_ALT0, GPIO_FSEL_ALT1,
+ GPIO_FSEL_ALT2, GPIO_FSEL_ALT3,
+};
+
+ /* Each of the two spinlocks protects a different set of hardware
+ * regiters and data structurs. This decouples the code of the IRQ from
+ * the GPIO code. This also makes the case of a GPIO routine call from
+ * the IRQ code simpler.
+ */
+static DEFINE_SPINLOCK(lock); /* GPIO registers */
+
+struct bcm2708_gpio {
+ struct list_head list;
+ void __iomem *base;
+ struct gpio_chip gc;
+ unsigned long rising;
+ unsigned long falling;
+ unsigned long high;
+ unsigned long low;
+};
+
+static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,
+ int function)
+{
+ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
+ unsigned long flags;
+ unsigned gpiodir;
+ unsigned gpio_bank = offset / 10;
+ unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3;
+
+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function);
+ if (offset >= BCM2708_NR_GPIOS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&lock, flags);
+
+ gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank));
+ gpiodir &= ~(7 << gpio_field_offset);
+ gpiodir |= function << gpio_field_offset;
+ writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank));
+ spin_unlock_irqrestore(&lock, flags);
+ gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank));
+
+ return 0;
+}
+
+static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset)
+{
+ return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT);
+}
+
+static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value);
+static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset,
+ int value)
+{
+ int ret;
+ ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT);
+ if (ret >= 0)
+ bcm2708_gpio_set(gc, offset, value);
+ return ret;
+}
+
+static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
+ unsigned gpio_bank = offset / 32;
+ unsigned gpio_field_offset = (offset - 32 * gpio_bank);
+ unsigned lev;
+
+ if (offset >= BCM2708_NR_GPIOS)
+ return 0;
+ lev = readl(gpio->base + GPIOLEV(gpio_bank));
+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset));
+ return 0x1 & (lev >> gpio_field_offset);
+}
+
+static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
+ unsigned gpio_bank = offset / 32;
+ unsigned gpio_field_offset = (offset - 32 * gpio_bank);
+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value);
+ if (offset >= BCM2708_NR_GPIOS)
+ return;
+ if (value)
+ writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank));
+ else
+ writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank));
+}
+
+/*************************************************************************************************************************
+ * bcm2708 GPIO IRQ
+ */
+
+#if BCM_GPIO_USE_IRQ
+
+static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ return gpio_to_irq(gpio);
+}
+
+static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type)
+{
+ unsigned irq = d->irq;
+ struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
+
+ gpio->rising &= ~(1 << irq_to_gpio(irq));
+ gpio->falling &= ~(1 << irq_to_gpio(irq));
+ gpio->high &= ~(1 << irq_to_gpio(irq));
+ gpio->low &= ~(1 << irq_to_gpio(irq));
+
+ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ return -EINVAL;
+
+ if (type & IRQ_TYPE_EDGE_RISING)
+ gpio->rising |= (1 << irq_to_gpio(irq));
+ if (type & IRQ_TYPE_EDGE_FALLING)
+ gpio->falling |= (1 << irq_to_gpio(irq));
+ if (type & IRQ_TYPE_LEVEL_HIGH)
+ gpio->high |= (1 << irq_to_gpio(irq));
+ if (type & IRQ_TYPE_LEVEL_LOW)
+ gpio->low |= (1 << irq_to_gpio(irq));
+ return 0;
+}
+
+static void bcm2708_gpio_irq_mask(struct irq_data *d)
+{
+ unsigned irq = d->irq;
+ struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
+ unsigned gn = irq_to_gpio(irq);
+ unsigned gb = gn / 32;
+ unsigned long rising = readl(gpio->base + GPIOREN(gb));
+ unsigned long falling = readl(gpio->base + GPIOFEN(gb));
+ unsigned long high = readl(gpio->base + GPIOHEN(gb));
+ unsigned long low = readl(gpio->base + GPIOLEN(gb));
+
+ gn = gn % 32;
+
+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
+ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
+ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
+ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
+}
+
+static void bcm2708_gpio_irq_unmask(struct irq_data *d)
+{
+ unsigned irq = d->irq;
+ struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
+ unsigned gn = irq_to_gpio(irq);
+ unsigned gb = gn / 32;
+ unsigned long rising = readl(gpio->base + GPIOREN(gb));
+ unsigned long falling = readl(gpio->base + GPIOFEN(gb));
+ unsigned long high = readl(gpio->base + GPIOHEN(gb));
+ unsigned long low = readl(gpio->base + GPIOLEN(gb));
+
+ gn = gn % 32;
+
+ writel(1 << gn, gpio->base + GPIOEDS(gb));
+
+ if (gpio->rising & (1 << gn)) {
+ writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
+ } else {
+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
+ }
+
+ if (gpio->falling & (1 << gn)) {
+ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
+ } else {
+ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
+ }
+
+ if (gpio->high & (1 << gn)) {
+ writel(high | (1 << gn), gpio->base + GPIOHEN(gb));
+ } else {
+ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
+ }
+
+ if (gpio->low & (1 << gn)) {
+ writel(low | (1 << gn), gpio->base + GPIOLEN(gb));
+ } else {
+ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
+ }
+}
+
+static struct irq_chip bcm2708_irqchip = {
+ .name = "GPIO",
+ .irq_enable = bcm2708_gpio_irq_unmask,
+ .irq_disable = bcm2708_gpio_irq_mask,
+ .irq_unmask = bcm2708_gpio_irq_unmask,
+ .irq_mask = bcm2708_gpio_irq_mask,
+ .irq_set_type = bcm2708_gpio_irq_set_type,
+};
+
+static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id)
+{
+ unsigned long edsr;
+ unsigned bank;
+ int i;
+ unsigned gpio;
+ for (bank = 0; bank <= 1; bank++) {
+ edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank));
+ for_each_set_bit(i, &edsr, 32) {
+ gpio = i + bank * 32;
+ generic_handle_irq(gpio_to_irq(gpio));
+ }
+ writel(0xffffffff, __io_address(GPIO_BASE) + GPIOEDS(bank));
+ }
+ return IRQ_HANDLED;
+}
+
+static struct irqaction bcm2708_gpio_irq = {
+ .name = "BCM2708 GPIO catchall handler",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = bcm2708_gpio_interrupt,
+};
+
+static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)
+{
+ unsigned irq;
+
+ ucb->gc.to_irq = bcm2708_gpio_to_irq;
+
+ for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) {
+ irq_set_chip_data(irq, ucb);
+ irq_set_chip(irq, &bcm2708_irqchip);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+ setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq);
+}
+
+#else
+
+static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)
+{
+}
+
+#endif /* #if BCM_GPIO_USE_IRQ ***************************************************************************************************************** */
+
+static int bcm2708_gpio_probe(struct platform_device *dev)
+{
+ struct bcm2708_gpio *ucb;
+ struct resource *res;
+ int err = 0;
+
+ printk(KERN_INFO DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev);
+
+ ucb = kzalloc(sizeof(*ucb), GFP_KERNEL);
+ if (NULL == ucb) {
+ printk(KERN_ERR DRIVER_NAME ": failed to allocate "
+ "mailbox memory\n");
+ err = -ENOMEM;
+ goto err;
+ }
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
+ platform_set_drvdata(dev, ucb);
+ ucb->base = __io_address(GPIO_BASE);
+
+ ucb->gc.label = "bcm2708_gpio";
+ ucb->gc.base = 0;
+ ucb->gc.ngpio = BCM2708_NR_GPIOS;
+ ucb->gc.owner = THIS_MODULE;
+
+ ucb->gc.direction_input = bcm2708_gpio_dir_in;
+ ucb->gc.direction_output = bcm2708_gpio_dir_out;
+ ucb->gc.get = bcm2708_gpio_get;
+ ucb->gc.set = bcm2708_gpio_set;
+ ucb->gc.can_sleep = 0;
+
+ bcm2708_gpio_irq_init(ucb);
+
+ err = gpiochip_add(&ucb->gc);
+ if (err)
+ goto err;
+
+err:
+ return err;
+
+}
+
+static int bcm2708_gpio_remove(struct platform_device *dev)
+{
+ int err = 0;
+ struct bcm2708_gpio *ucb = platform_get_drvdata(dev);
+
+ printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev);
+
+ err = gpiochip_remove(&ucb->gc);
+
+ platform_set_drvdata(dev, NULL);
+ kfree(ucb);
+
+ return err;
+}
+
+static struct platform_driver bcm2708_gpio_driver = {
+ .probe = bcm2708_gpio_probe,
+ .remove = bcm2708_gpio_remove,
+ .driver = {
+ .name = "bcm2708_gpio"},
+};
+
+static int __init bcm2708_gpio_init(void)
+{
+ return platform_driver_register(&bcm2708_gpio_driver);
+}
+
+static void __exit bcm2708_gpio_exit(void)
+{
+ platform_driver_unregister(&bcm2708_gpio_driver);
+}
+
+module_init(bcm2708_gpio_init);
+module_exit(bcm2708_gpio_exit);
+
+MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver");
+MODULE_LICENSE("GPL");
diff -Nur linux/arch/arm/mach-bcm2708/bcm2708.h rpi/arch/arm/mach-bcm2708/bcm2708.h
--- linux/arch/arm/mach-bcm2708/bcm2708.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/bcm2708.h 2014-05-29 11:49:03.961967174 +0900
@@ -0,0 +1,49 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708.h
+ *
+ * BCM2708 machine support header
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 __BCM2708_BCM2708_H
+#define __BCM2708_BCM2708_H
+
+#include <linux/amba/bus.h>
+
+extern void __init bcm2708_init(void);
+extern void __init bcm2708_init_irq(void);
+extern void __init bcm2708_map_io(void);
+extern struct sys_timer bcm2708_timer;
+extern unsigned int mmc_status(struct device *dev);
+
+#define AMBA_DEVICE(name, busid, base, plat) \
+static struct amba_device name##_device = { \
+ .dev = { \
+ .coherent_dma_mask = ~0, \
+ .init_name = busid, \
+ .platform_data = plat, \
+ }, \
+ .res = { \
+ .start = base##_BASE, \
+ .end = (base##_BASE) + SZ_4K - 1,\
+ .flags = IORESOURCE_MEM, \
+ }, \
+ .irq = base##_IRQ, \
+}
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/clock.c rpi/arch/arm/mach-bcm2708/clock.c
--- linux/arch/arm/mach-bcm2708/clock.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/clock.c 2014-05-29 11:49:03.962967166 +0900
@@ -0,0 +1,61 @@
+/*
+ * linux/arch/arm/mach-bcm2708/clock.c
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+
+#include <asm/clkdev.h>
+
+#include "clock.h"
+
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ return clk->rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ return -EIO;
+}
+EXPORT_SYMBOL(clk_set_rate);
diff -Nur linux/arch/arm/mach-bcm2708/clock.h rpi/arch/arm/mach-bcm2708/clock.h
--- linux/arch/arm/mach-bcm2708/clock.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/clock.h 2014-05-29 11:49:03.962967166 +0900
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/mach-bcm2708/clock.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+struct module;
+
+struct clk {
+ unsigned long rate;
+};
diff -Nur linux/arch/arm/mach-bcm2708/dma.c rpi/arch/arm/mach-bcm2708/dma.c
--- linux/arch/arm/mach-bcm2708/dma.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/dma.c 2014-05-29 11:49:03.962967166 +0900
@@ -0,0 +1,407 @@
+/*
+ * linux/arch/arm/mach-bcm2708/dma.c
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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.
+ */
+
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+/*****************************************************************************\
+ * *
+ * Configuration *
+ * *
+\*****************************************************************************/
+
+#define CACHE_LINE_MASK 31
+#define DRIVER_NAME BCM_DMAMAN_DRIVER_NAME
+#define DEFAULT_DMACHAN_BITMAP 0x10 /* channel 4 only */
+
+/* valid only for channels 0 - 14, 15 has its own base address */
+#define BCM2708_DMA_CHAN(n) ((n)<<8) /* base address */
+#define BCM2708_DMA_CHANIO(dma_base, n) \
+ ((void __iomem *)((char *)(dma_base)+BCM2708_DMA_CHAN(n)))
+
+
+/*****************************************************************************\
+ * *
+ * DMA Auxilliary Functions *
+ * *
+\*****************************************************************************/
+
+/* A DMA buffer on an arbitrary boundary may separate a cache line into a
+ section inside the DMA buffer and another section outside it.
+ Even if we flush DMA buffers from the cache there is always the chance that
+ during a DMA someone will access the part of a cache line that is outside
+ the DMA buffer - which will then bring in unwelcome data.
+ Without being able to dictate our own buffer pools we must insist that
+ DMA buffers consist of a whole number of cache lines.
+*/
+
+extern int
+bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len)
+{
+ int i;
+
+ for (i = 0; i < sg_len; i++) {
+ if (sg_ptr[i].offset & CACHE_LINE_MASK ||
+ sg_ptr[i].length & CACHE_LINE_MASK)
+ return 0;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(bcm_sg_suitable_for_dma);
+
+extern void
+bcm_dma_start(void __iomem *dma_chan_base, dma_addr_t control_block)
+{
+ dsb(); /* ARM data synchronization (push) operation */
+
+ writel(control_block, dma_chan_base + BCM2708_DMA_ADDR);
+ writel(BCM2708_DMA_ACTIVE, dma_chan_base + BCM2708_DMA_CS);
+}
+
+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base)
+{
+ dsb();
+
+ /* ugly busy wait only option for now */
+ while (readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE)
+ cpu_relax();
+}
+
+EXPORT_SYMBOL_GPL(bcm_dma_start);
+
+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base)
+{
+ dsb();
+
+ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE;
+}
+EXPORT_SYMBOL_GPL(bcm_dma_is_busy);
+
+/* Complete an ongoing DMA (assuming its results are to be ignored)
+ Does nothing if there is no DMA in progress.
+ This routine waits for the current AXI transfer to complete before
+ terminating the current DMA. If the current transfer is hung on a DREQ used
+ by an uncooperative peripheral the AXI transfer may never complete. In this
+ case the routine times out and return a non-zero error code.
+ Use of this routine doesn't guarantee that the ongoing or aborted DMA
+ does not produce an interrupt.
+*/
+extern int
+bcm_dma_abort(void __iomem *dma_chan_base)
+{
+ unsigned long int cs;
+ int rc = 0;
+
+ cs = readl(dma_chan_base + BCM2708_DMA_CS);
+
+ if (BCM2708_DMA_ACTIVE & cs) {
+ long int timeout = 10000;
+
+ /* write 0 to the active bit - pause the DMA */
+ writel(0, dma_chan_base + BCM2708_DMA_CS);
+
+ /* wait for any current AXI transfer to complete */
+ while (0 != (cs & BCM2708_DMA_ISPAUSED) && --timeout >= 0)
+ cs = readl(dma_chan_base + BCM2708_DMA_CS);
+
+ if (0 != (cs & BCM2708_DMA_ISPAUSED)) {
+ /* we'll un-pause when we set of our next DMA */
+ rc = -ETIMEDOUT;
+
+ } else if (BCM2708_DMA_ACTIVE & cs) {
+ /* terminate the control block chain */
+ writel(0, dma_chan_base + BCM2708_DMA_NEXTCB);
+
+ /* abort the whole DMA */
+ writel(BCM2708_DMA_ABORT | BCM2708_DMA_ACTIVE,
+ dma_chan_base + BCM2708_DMA_CS);
+ }
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(bcm_dma_abort);
+
+
+/***************************************************************************** \
+ * *
+ * DMA Manager Device Methods *
+ * *
+\*****************************************************************************/
+
+struct vc_dmaman {
+ void __iomem *dma_base;
+ u32 chan_available; /* bitmap of available channels */
+ u32 has_feature[BCM_DMA_FEATURE_COUNT]; /* bitmap of feature presence */
+};
+
+static void vc_dmaman_init(struct vc_dmaman *dmaman, void __iomem *dma_base,
+ u32 chans_available)
+{
+ dmaman->dma_base = dma_base;
+ dmaman->chan_available = chans_available;
+ dmaman->has_feature[BCM_DMA_FEATURE_FAST_ORD] = 0x0c; /* chans 2 & 3 */
+ dmaman->has_feature[BCM_DMA_FEATURE_BULK_ORD] = 0x01; /* chan 0 */
+}
+
+static int vc_dmaman_chan_alloc(struct vc_dmaman *dmaman,
+ unsigned preferred_feature_set)
+{
+ u32 chans;
+ int feature;
+
+ chans = dmaman->chan_available;
+ for (feature = 0; feature < BCM_DMA_FEATURE_COUNT; feature++)
+ /* select the subset of available channels with the desired
+ feature so long as some of the candidate channels have that
+ feature */
+ if ((preferred_feature_set & (1 << feature)) &&
+ (chans & dmaman->has_feature[feature]))
+ chans &= dmaman->has_feature[feature];
+
+ if (chans) {
+ int chan = 0;
+ /* return the ordinal of the first channel in the bitmap */
+ while (chans != 0 && (chans & 1) == 0) {
+ chans >>= 1;
+ chan++;
+ }
+ /* claim the channel */
+ dmaman->chan_available &= ~(1 << chan);
+ return chan;
+ } else
+ return -ENOMEM;
+}
+
+static int vc_dmaman_chan_free(struct vc_dmaman *dmaman, int chan)
+{
+ if (chan < 0)
+ return -EINVAL;
+ else if ((1 << chan) & dmaman->chan_available)
+ return -EIDRM;
+ else {
+ dmaman->chan_available |= (1 << chan);
+ return 0;
+ }
+}
+
+/*****************************************************************************\
+ * *
+ * DMA IRQs *
+ * *
+\*****************************************************************************/
+
+static unsigned char bcm_dma_irqs[] = {
+ IRQ_DMA0,
+ IRQ_DMA1,
+ IRQ_DMA2,
+ IRQ_DMA3,
+ IRQ_DMA4,
+ IRQ_DMA5,
+ IRQ_DMA6,
+ IRQ_DMA7,
+ IRQ_DMA8,
+ IRQ_DMA9,
+ IRQ_DMA10,
+ IRQ_DMA11,
+ IRQ_DMA12
+};
+
+
+/***************************************************************************** \
+ * *
+ * DMA Manager Monitor *
+ * *
+\*****************************************************************************/
+
+static struct device *dmaman_dev; /* we assume there's only one! */
+
+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,
+ void __iomem **out_dma_base, int *out_dma_irq)
+{
+ if (!dmaman_dev)
+ return -ENODEV;
+ else {
+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev);
+ int rc;
+
+ device_lock(dmaman_dev);
+ rc = vc_dmaman_chan_alloc(dmaman, preferred_feature_set);
+ if (rc >= 0) {
+ *out_dma_base = BCM2708_DMA_CHANIO(dmaman->dma_base,
+ rc);
+ *out_dma_irq = bcm_dma_irqs[rc];
+ }
+ device_unlock(dmaman_dev);
+
+ return rc;
+ }
+}
+EXPORT_SYMBOL_GPL(bcm_dma_chan_alloc);
+
+extern int bcm_dma_chan_free(int channel)
+{
+ if (dmaman_dev) {
+ struct vc_dmaman *dmaman = dev_get_drvdata(dmaman_dev);
+ int rc;
+
+ device_lock(dmaman_dev);
+ rc = vc_dmaman_chan_free(dmaman, channel);
+ device_unlock(dmaman_dev);
+
+ return rc;
+ } else
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(bcm_dma_chan_free);
+
+static int dev_dmaman_register(const char *dev_name, struct device *dev)
+{
+ int rc = dmaman_dev ? -EINVAL : 0;
+ dmaman_dev = dev;
+ return rc;
+}
+
+static void dev_dmaman_deregister(const char *dev_name, struct device *dev)
+{
+ dmaman_dev = NULL;
+}
+
+/*****************************************************************************\
+ * *
+ * DMA Device *
+ * *
+\*****************************************************************************/
+
+static int dmachans = -1; /* module parameter */
+
+static int bcm_dmaman_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct vc_dmaman *dmaman;
+ struct resource *dma_res = NULL;
+ void __iomem *dma_base = NULL;
+ int have_dma_region = 0;
+
+ dmaman = kzalloc(sizeof(*dmaman), GFP_KERNEL);
+ if (NULL == dmaman) {
+ printk(KERN_ERR DRIVER_NAME ": failed to allocate "
+ "DMA management memory\n");
+ ret = -ENOMEM;
+ } else {
+
+ dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (dma_res == NULL) {
+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory "
+ "resource\n");
+ ret = -ENODEV;
+ } else if (!request_mem_region(dma_res->start,
+ resource_size(dma_res),
+ DRIVER_NAME)) {
+ dev_err(&pdev->dev, "cannot obtain DMA region\n");
+ ret = -EBUSY;
+ } else {
+ have_dma_region = 1;
+ dma_base = ioremap(dma_res->start,
+ resource_size(dma_res));
+ if (!dma_base) {
+ dev_err(&pdev->dev, "cannot map DMA region\n");
+ ret = -ENOMEM;
+ } else {
+ /* use module parameter if one was provided */
+ if (dmachans > 0)
+ vc_dmaman_init(dmaman, dma_base,
+ dmachans);
+ else
+ vc_dmaman_init(dmaman, dma_base,
+ DEFAULT_DMACHAN_BITMAP);
+
+ platform_set_drvdata(pdev, dmaman);
+ dev_dmaman_register(DRIVER_NAME, &pdev->dev);
+
+ printk(KERN_INFO DRIVER_NAME ": DMA manager "
+ "at %p\n", dma_base);
+ }
+ }
+ }
+ if (ret != 0) {
+ if (dma_base)
+ iounmap(dma_base);
+ if (dma_res && have_dma_region)
+ release_mem_region(dma_res->start,
+ resource_size(dma_res));
+ if (dmaman)
+ kfree(dmaman);
+ }
+ return ret;
+}
+
+static int bcm_dmaman_remove(struct platform_device *pdev)
+{
+ struct vc_dmaman *dmaman = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ dev_dmaman_deregister(DRIVER_NAME, &pdev->dev);
+ kfree(dmaman);
+
+ return 0;
+}
+
+static struct platform_driver bcm_dmaman_driver = {
+ .probe = bcm_dmaman_probe,
+ .remove = bcm_dmaman_remove,
+
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+/*****************************************************************************\
+ * *
+ * Driver init/exit *
+ * *
+\*****************************************************************************/
+
+static int __init bcm_dmaman_drv_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&bcm_dmaman_driver);
+ if (ret != 0) {
+ printk(KERN_ERR DRIVER_NAME ": failed to register "
+ "on platform\n");
+ }
+
+ return ret;
+}
+
+static void __exit bcm_dmaman_drv_exit(void)
+{
+ platform_driver_unregister(&bcm_dmaman_driver);
+}
+
+module_init(bcm_dmaman_drv_init);
+module_exit(bcm_dmaman_drv_exit);
+
+module_param(dmachans, int, 0644);
+
+MODULE_AUTHOR("Gray Girling <grayg@broadcom.com>");
+MODULE_DESCRIPTION("DMA channel manager driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM");
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/arm_control.h rpi/arch/arm/mach-bcm2708/include/mach/arm_control.h
--- linux/arch/arm/mach-bcm2708/include/mach/arm_control.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/arm_control.h 2014-05-29 11:49:03.963967157 +0900
@@ -0,0 +1,419 @@
+/*
+ * linux/arch/arm/mach-bcm2708/arm_control.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 __BCM2708_ARM_CONTROL_H
+#define __BCM2708_ARM_CONTROL_H
+
+/*
+ * Definitions and addresses for the ARM CONTROL logic
+ * This file is manually generated.
+ */
+
+#define ARM_BASE 0x7E00B000
+
+/* Basic configuration */
+#define ARM_CONTROL0 HW_REGISTER_RW(ARM_BASE+0x000)
+#define ARM_C0_SIZ128M 0x00000000
+#define ARM_C0_SIZ256M 0x00000001
+#define ARM_C0_SIZ512M 0x00000002
+#define ARM_C0_SIZ1G 0x00000003
+#define ARM_C0_BRESP0 0x00000000
+#define ARM_C0_BRESP1 0x00000004
+#define ARM_C0_BRESP2 0x00000008
+#define ARM_C0_BOOTHI 0x00000010
+#define ARM_C0_UNUSED05 0x00000020 /* free */
+#define ARM_C0_FULLPERI 0x00000040
+#define ARM_C0_UNUSED78 0x00000180 /* free */
+#define ARM_C0_JTAGMASK 0x00000E00
+#define ARM_C0_JTAGOFF 0x00000000
+#define ARM_C0_JTAGBASH 0x00000800 /* Debug on GPIO off */
+#define ARM_C0_JTAGGPIO 0x00000C00 /* Debug on GPIO on */
+#define ARM_C0_APROTMSK 0x0000F000
+#define ARM_C0_DBG0SYNC 0x00010000 /* VPU0 halt sync */
+#define ARM_C0_DBG1SYNC 0x00020000 /* VPU1 halt sync */
+#define ARM_C0_SWDBGREQ 0x00040000 /* HW debug request */
+#define ARM_C0_PASSHALT 0x00080000 /* ARM halt passed to debugger */
+#define ARM_C0_PRIO_PER 0x00F00000 /* per priority mask */
+#define ARM_C0_PRIO_L2 0x0F000000
+#define ARM_C0_PRIO_UC 0xF0000000
+
+#define ARM_C0_APROTPASS 0x0000A000 /* Translate 1:1 */
+#define ARM_C0_APROTUSER 0x00000000 /* Only user mode */
+#define ARM_C0_APROTSYST 0x0000F000 /* Only system mode */
+
+
+#define ARM_CONTROL1 HW_REGISTER_RW(ARM_BASE+0x440)
+#define ARM_C1_TIMER 0x00000001 /* re-route timer IRQ to VC */
+#define ARM_C1_MAIL 0x00000002 /* re-route Mail IRQ to VC */
+#define ARM_C1_BELL0 0x00000004 /* re-route Doorbell 0 to VC */
+#define ARM_C1_BELL1 0x00000008 /* re-route Doorbell 1 to VC */
+#define ARM_C1_PERSON 0x00000100 /* peripherals on */
+#define ARM_C1_REQSTOP 0x00000200 /* ASYNC bridge request stop */
+
+#define ARM_STATUS HW_REGISTER_RW(ARM_BASE+0x444)
+#define ARM_S_ACKSTOP 0x80000000 /* Bridge stopped */
+#define ARM_S_READPEND 0x000003FF /* pending reads counter */
+#define ARM_S_WRITPEND 0x000FFC00 /* pending writes counter */
+
+#define ARM_ERRHALT HW_REGISTER_RW(ARM_BASE+0x448)
+#define ARM_EH_PERIBURST 0x00000001 /* Burst write seen on peri bus */
+#define ARM_EH_ILLADDRS1 0x00000002 /* Address bits 25-27 error */
+#define ARM_EH_ILLADDRS2 0x00000004 /* Address bits 31-28 error */
+#define ARM_EH_VPU0HALT 0x00000008 /* VPU0 halted & in debug mode */
+#define ARM_EH_VPU1HALT 0x00000010 /* VPU1 halted & in debug mode */
+#define ARM_EH_ARMHALT 0x00000020 /* ARM in halted debug mode */
+
+#define ARM_ID_SECURE HW_REGISTER_RW(ARM_BASE+0x00C)
+#define ARM_ID HW_REGISTER_RW(ARM_BASE+0x44C)
+#define ARM_IDVAL 0x364D5241
+
+/* Translation memory */
+#define ARM_TRANSLATE HW_REGISTER_RW(ARM_BASE+0x100)
+/* 32 locations: 0x100.. 0x17F */
+/* 32 spare means we CAN go to 64 pages.... */
+
+
+/* Interrupts */
+#define ARM_IRQ_PEND0 HW_REGISTER_RW(ARM_BASE+0x200) /* Top IRQ bits */
+#define ARM_I0_TIMER 0x00000001 /* timer IRQ */
+#define ARM_I0_MAIL 0x00000002 /* Mail IRQ */
+#define ARM_I0_BELL0 0x00000004 /* Doorbell 0 */
+#define ARM_I0_BELL1 0x00000008 /* Doorbell 1 */
+#define ARM_I0_BANK1 0x00000100 /* Bank1 IRQ */
+#define ARM_I0_BANK2 0x00000200 /* Bank2 IRQ */
+
+#define ARM_IRQ_PEND1 HW_REGISTER_RW(ARM_BASE+0x204) /* All bank1 IRQ bits */
+/* todo: all I1_interrupt sources */
+#define ARM_IRQ_PEND2 HW_REGISTER_RW(ARM_BASE+0x208) /* All bank2 IRQ bits */
+/* todo: all I2_interrupt sources */
+
+#define ARM_IRQ_FAST HW_REGISTER_RW(ARM_BASE+0x20C) /* FIQ control */
+#define ARM_IF_INDEX 0x0000007F /* FIQ select */
+#define ARM_IF_ENABLE 0x00000080 /* FIQ enable */
+#define ARM_IF_VCMASK 0x0000003F /* FIQ = (index from VC source) */
+#define ARM_IF_TIMER 0x00000040 /* FIQ = ARM timer */
+#define ARM_IF_MAIL 0x00000041 /* FIQ = ARM Mail */
+#define ARM_IF_BELL0 0x00000042 /* FIQ = ARM Doorbell 0 */
+#define ARM_IF_BELL1 0x00000043 /* FIQ = ARM Doorbell 1 */
+#define ARM_IF_VP0HALT 0x00000044 /* FIQ = VPU0 Halt seen */
+#define ARM_IF_VP1HALT 0x00000045 /* FIQ = VPU1 Halt seen */
+#define ARM_IF_ILLEGAL 0x00000046 /* FIQ = Illegal access seen */
+
+#define ARM_IRQ_ENBL1 HW_REGISTER_RW(ARM_BASE+0x210) /* Bank1 enable bits */
+#define ARM_IRQ_ENBL2 HW_REGISTER_RW(ARM_BASE+0x214) /* Bank2 enable bits */
+#define ARM_IRQ_ENBL3 HW_REGISTER_RW(ARM_BASE+0x218) /* ARM irqs enable bits */
+#define ARM_IRQ_DIBL1 HW_REGISTER_RW(ARM_BASE+0x21C) /* Bank1 disable bits */
+#define ARM_IRQ_DIBL2 HW_REGISTER_RW(ARM_BASE+0x220) /* Bank2 disable bits */
+#define ARM_IRQ_DIBL3 HW_REGISTER_RW(ARM_BASE+0x224) /* ARM irqs disable bits */
+#define ARM_IE_TIMER 0x00000001 /* Timer IRQ */
+#define ARM_IE_MAIL 0x00000002 /* Mail IRQ */
+#define ARM_IE_BELL0 0x00000004 /* Doorbell 0 */
+#define ARM_IE_BELL1 0x00000008 /* Doorbell 1 */
+#define ARM_IE_VP0HALT 0x00000010 /* VPU0 Halt */
+#define ARM_IE_VP1HALT 0x00000020 /* VPU1 Halt */
+#define ARM_IE_ILLEGAL 0x00000040 /* Illegal access seen */
+
+/* Timer */
+/* For reg. fields see sp804 spec. */
+#define ARM_T_LOAD HW_REGISTER_RW(ARM_BASE+0x400)
+#define ARM_T_VALUE HW_REGISTER_RW(ARM_BASE+0x404)
+#define ARM_T_CONTROL HW_REGISTER_RW(ARM_BASE+0x408)
+#define ARM_T_IRQCNTL HW_REGISTER_RW(ARM_BASE+0x40C)
+#define ARM_T_RAWIRQ HW_REGISTER_RW(ARM_BASE+0x410)
+#define ARM_T_MSKIRQ HW_REGISTER_RW(ARM_BASE+0x414)
+#define ARM_T_RELOAD HW_REGISTER_RW(ARM_BASE+0x418)
+#define ARM_T_PREDIV HW_REGISTER_RW(ARM_BASE+0x41c)
+#define ARM_T_FREECNT HW_REGISTER_RW(ARM_BASE+0x420)
+
+#define TIMER_CTRL_ONESHOT (1 << 0)
+#define TIMER_CTRL_32BIT (1 << 1)
+#define TIMER_CTRL_DIV1 (0 << 2)
+#define TIMER_CTRL_DIV16 (1 << 2)
+#define TIMER_CTRL_DIV256 (2 << 2)
+#define TIMER_CTRL_IE (1 << 5)
+#define TIMER_CTRL_PERIODIC (1 << 6)
+#define TIMER_CTRL_ENABLE (1 << 7)
+#define TIMER_CTRL_DBGHALT (1 << 8)
+#define TIMER_CTRL_ENAFREE (1 << 9)
+#define TIMER_CTRL_FREEDIV_SHIFT 16)
+#define TIMER_CTRL_FREEDIV_MASK 0xff
+
+/* Semaphores, Doorbells, Mailboxes */
+#define ARM_SBM_OWN0 (ARM_BASE+0x800)
+#define ARM_SBM_OWN1 (ARM_BASE+0x900)
+#define ARM_SBM_OWN2 (ARM_BASE+0xA00)
+#define ARM_SBM_OWN3 (ARM_BASE+0xB00)
+
+/* MAILBOXES
+ * Register flags are common across all
+ * owner registers. See end of this section
+ *
+ * Semaphores, Doorbells, Mailboxes Owner 0
+ *
+ */
+
+#define ARM_0_SEMS HW_REGISTER_RW(ARM_SBM_OWN0+0x00)
+#define ARM_0_SEM0 HW_REGISTER_RW(ARM_SBM_OWN0+0x00)
+#define ARM_0_SEM1 HW_REGISTER_RW(ARM_SBM_OWN0+0x04)
+#define ARM_0_SEM2 HW_REGISTER_RW(ARM_SBM_OWN0+0x08)
+#define ARM_0_SEM3 HW_REGISTER_RW(ARM_SBM_OWN0+0x0C)
+#define ARM_0_SEM4 HW_REGISTER_RW(ARM_SBM_OWN0+0x10)
+#define ARM_0_SEM5 HW_REGISTER_RW(ARM_SBM_OWN0+0x14)
+#define ARM_0_SEM6 HW_REGISTER_RW(ARM_SBM_OWN0+0x18)
+#define ARM_0_SEM7 HW_REGISTER_RW(ARM_SBM_OWN0+0x1C)
+#define ARM_0_BELL0 HW_REGISTER_RW(ARM_SBM_OWN0+0x40)
+#define ARM_0_BELL1 HW_REGISTER_RW(ARM_SBM_OWN0+0x44)
+#define ARM_0_BELL2 HW_REGISTER_RW(ARM_SBM_OWN0+0x48)
+#define ARM_0_BELL3 HW_REGISTER_RW(ARM_SBM_OWN0+0x4C)
+/* MAILBOX 0 access in Owner 0 area */
+/* Some addresses should ONLY be used by owner 0 */
+#define ARM_0_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) */
+#define ARM_0_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN0+0x80) /* .. 0x8C (4 locations) Normal read */
+#define ARM_0_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN0+0x90) /* none-pop read */
+#define ARM_0_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN0+0x94) /* Sender read (only LS 2 bits) */
+#define ARM_0_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN0+0x98) /* Status read */
+#define ARM_0_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0x9C) /* Config read/write */
+/* MAILBOX 1 access in Owner 0 area */
+/* Owner 0 should only WRITE to this mailbox */
+#define ARM_0_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) /* .. 0xAC (4 locations) */
+/*#define ARM_0_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN0+0xA0) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_0_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN0+0xB0) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_0_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN0+0xB4) */ /* DO NOT USE THIS !!!!! */
+#define ARM_0_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN0+0xB8) /* Status read */
+/*#define ARM_0_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN0+0xBC) */ /* DO NOT USE THIS !!!!! */
+/* General SEM, BELL, MAIL config/status */
+#define ARM_0_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE0) /* semaphore clear/debug register */
+#define ARM_0_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN0+0xE4) /* Doorbells clear/debug register */
+#define ARM_0_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xF8) /* ALL interrupts */
+#define ARM_0_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN0+0xFC) /* IRQS pending for owner 0 */
+
+/* Semaphores, Doorbells, Mailboxes Owner 1 */
+#define ARM_1_SEMS HW_REGISTER_RW(ARM_SBM_OWN1+0x00)
+#define ARM_1_SEM0 HW_REGISTER_RW(ARM_SBM_OWN1+0x00)
+#define ARM_1_SEM1 HW_REGISTER_RW(ARM_SBM_OWN1+0x04)
+#define ARM_1_SEM2 HW_REGISTER_RW(ARM_SBM_OWN1+0x08)
+#define ARM_1_SEM3 HW_REGISTER_RW(ARM_SBM_OWN1+0x0C)
+#define ARM_1_SEM4 HW_REGISTER_RW(ARM_SBM_OWN1+0x10)
+#define ARM_1_SEM5 HW_REGISTER_RW(ARM_SBM_OWN1+0x14)
+#define ARM_1_SEM6 HW_REGISTER_RW(ARM_SBM_OWN1+0x18)
+#define ARM_1_SEM7 HW_REGISTER_RW(ARM_SBM_OWN1+0x1C)
+#define ARM_1_BELL0 HW_REGISTER_RW(ARM_SBM_OWN1+0x40)
+#define ARM_1_BELL1 HW_REGISTER_RW(ARM_SBM_OWN1+0x44)
+#define ARM_1_BELL2 HW_REGISTER_RW(ARM_SBM_OWN1+0x48)
+#define ARM_1_BELL3 HW_REGISTER_RW(ARM_SBM_OWN1+0x4C)
+/* MAILBOX 0 access in Owner 0 area */
+/* Owner 1 should only WRITE to this mailbox */
+#define ARM_1_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0x80) /* .. 0x8C (4 locations) */
+/*#define ARM_1_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN1+0x80) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_1_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN1+0x90) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_1_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN1+0x94) */ /* DO NOT USE THIS !!!!! */
+#define ARM_1_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN1+0x98) /* Status read */
+/*#define ARM_1_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0x9C) */ /* DO NOT USE THIS !!!!! */
+/* MAILBOX 1 access in Owner 0 area */
+#define ARM_1_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) */
+#define ARM_1_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN1+0xA0) /* .. 0xAC (4 locations) Normal read */
+#define ARM_1_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN1+0xB0) /* none-pop read */
+#define ARM_1_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN1+0xB4) /* Sender read (only LS 2 bits) */
+#define ARM_1_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN1+0xB8) /* Status read */
+#define ARM_1_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN1+0xBC)
+/* General SEM, BELL, MAIL config/status */
+#define ARM_1_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE0) /* semaphore clear/debug register */
+#define ARM_1_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN1+0xE4) /* Doorbells clear/debug register */
+#define ARM_1_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xFC) /* IRQS pending for owner 1 */
+#define ARM_1_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN1+0xF8) /* ALL interrupts */
+
+/* Semaphores, Doorbells, Mailboxes Owner 2 */
+#define ARM_2_SEMS HW_REGISTER_RW(ARM_SBM_OWN2+0x00)
+#define ARM_2_SEM0 HW_REGISTER_RW(ARM_SBM_OWN2+0x00)
+#define ARM_2_SEM1 HW_REGISTER_RW(ARM_SBM_OWN2+0x04)
+#define ARM_2_SEM2 HW_REGISTER_RW(ARM_SBM_OWN2+0x08)
+#define ARM_2_SEM3 HW_REGISTER_RW(ARM_SBM_OWN2+0x0C)
+#define ARM_2_SEM4 HW_REGISTER_RW(ARM_SBM_OWN2+0x10)
+#define ARM_2_SEM5 HW_REGISTER_RW(ARM_SBM_OWN2+0x14)
+#define ARM_2_SEM6 HW_REGISTER_RW(ARM_SBM_OWN2+0x18)
+#define ARM_2_SEM7 HW_REGISTER_RW(ARM_SBM_OWN2+0x1C)
+#define ARM_2_BELL0 HW_REGISTER_RW(ARM_SBM_OWN2+0x40)
+#define ARM_2_BELL1 HW_REGISTER_RW(ARM_SBM_OWN2+0x44)
+#define ARM_2_BELL2 HW_REGISTER_RW(ARM_SBM_OWN2+0x48)
+#define ARM_2_BELL3 HW_REGISTER_RW(ARM_SBM_OWN2+0x4C)
+/* MAILBOX 0 access in Owner 2 area */
+/* Owner 2 should only WRITE to this mailbox */
+#define ARM_2_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0x80) /* .. 0x8C (4 locations) */
+/*#define ARM_2_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN2+0x80) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_2_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN2+0x90) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_2_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN2+0x94) */ /* DO NOT USE THIS !!!!! */
+#define ARM_2_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN2+0x98) /* Status read */
+/*#define ARM_2_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0x9C) */ /* DO NOT USE THIS !!!!! */
+/* MAILBOX 1 access in Owner 2 area */
+/* Owner 2 should only WRITE to this mailbox */
+#define ARM_2_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) /* .. 0xAC (4 locations) */
+/*#define ARM_2_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN2+0xA0) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_2_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN2+0xB0) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_2_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN2+0xB4) */ /* DO NOT USE THIS !!!!! */
+#define ARM_2_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN2+0xB8) /* Status read */
+/*#define ARM_2_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN2+0xBC) */ /* DO NOT USE THIS !!!!! */
+/* General SEM, BELL, MAIL config/status */
+#define ARM_2_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE0) /* semaphore clear/debug register */
+#define ARM_2_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN2+0xE4) /* Doorbells clear/debug register */
+#define ARM_2_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xFC) /* IRQS pending for owner 2 */
+#define ARM_2_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN2+0xF8) /* ALL interrupts */
+
+/* Semaphores, Doorbells, Mailboxes Owner 3 */
+#define ARM_3_SEMS HW_REGISTER_RW(ARM_SBM_OWN3+0x00)
+#define ARM_3_SEM0 HW_REGISTER_RW(ARM_SBM_OWN3+0x00)
+#define ARM_3_SEM1 HW_REGISTER_RW(ARM_SBM_OWN3+0x04)
+#define ARM_3_SEM2 HW_REGISTER_RW(ARM_SBM_OWN3+0x08)
+#define ARM_3_SEM3 HW_REGISTER_RW(ARM_SBM_OWN3+0x0C)
+#define ARM_3_SEM4 HW_REGISTER_RW(ARM_SBM_OWN3+0x10)
+#define ARM_3_SEM5 HW_REGISTER_RW(ARM_SBM_OWN3+0x14)
+#define ARM_3_SEM6 HW_REGISTER_RW(ARM_SBM_OWN3+0x18)
+#define ARM_3_SEM7 HW_REGISTER_RW(ARM_SBM_OWN3+0x1C)
+#define ARM_3_BELL0 HW_REGISTER_RW(ARM_SBM_OWN3+0x40)
+#define ARM_3_BELL1 HW_REGISTER_RW(ARM_SBM_OWN3+0x44)
+#define ARM_3_BELL2 HW_REGISTER_RW(ARM_SBM_OWN3+0x48)
+#define ARM_3_BELL3 HW_REGISTER_RW(ARM_SBM_OWN3+0x4C)
+/* MAILBOX 0 access in Owner 3 area */
+/* Owner 3 should only WRITE to this mailbox */
+#define ARM_3_MAIL0_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0x80) /* .. 0x8C (4 locations) */
+/*#define ARM_3_MAIL0_RD HW_REGISTER_RW(ARM_SBM_OWN3+0x80) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_3_MAIL0_POL HW_REGISTER_RW(ARM_SBM_OWN3+0x90) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_3_MAIL0_SND HW_REGISTER_RW(ARM_SBM_OWN3+0x94) */ /* DO NOT USE THIS !!!!! */
+#define ARM_3_MAIL0_STA HW_REGISTER_RW(ARM_SBM_OWN3+0x98) /* Status read */
+/*#define ARM_3_MAIL0_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0x9C) */ /* DO NOT USE THIS !!!!! */
+/* MAILBOX 1 access in Owner 3 area */
+/* Owner 3 should only WRITE to this mailbox */
+#define ARM_3_MAIL1_WRT HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) /* .. 0xAC (4 locations) */
+/*#define ARM_3_MAIL1_RD HW_REGISTER_RW(ARM_SBM_OWN3+0xA0) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_3_MAIL1_POL HW_REGISTER_RW(ARM_SBM_OWN3+0xB0) */ /* DO NOT USE THIS !!!!! */
+/*#define ARM_3_MAIL1_SND HW_REGISTER_RW(ARM_SBM_OWN3+0xB4) */ /* DO NOT USE THIS !!!!! */
+#define ARM_3_MAIL1_STA HW_REGISTER_RW(ARM_SBM_OWN3+0xB8) /* Status read */
+/*#define ARM_3_MAIL1_CNF HW_REGISTER_RW(ARM_SBM_OWN3+0xBC) */ /* DO NOT USE THIS !!!!! */
+/* General SEM, BELL, MAIL config/status */
+#define ARM_3_SEMCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE0) /* semaphore clear/debug register */
+#define ARM_3_BELLCLRDBG HW_REGISTER_RW(ARM_SBM_OWN3+0xE4) /* Doorbells clear/debug register */
+#define ARM_3_MY_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xFC) /* IRQS pending for owner 3 */
+#define ARM_3_ALL_IRQS HW_REGISTER_RW(ARM_SBM_OWN3+0xF8) /* ALL interrupts */
+
+
+
+/* Mailbox flags. Valid for all owners */
+
+/* Mailbox status register (...0x98) */
+#define ARM_MS_FULL 0x80000000
+#define ARM_MS_EMPTY 0x40000000
+#define ARM_MS_LEVEL 0x400000FF /* Max. value depdnds on mailbox depth parameter */
+
+/* MAILBOX config/status register (...0x9C) */
+/* ANY write to this register clears the error bits! */
+#define ARM_MC_IHAVEDATAIRQEN 0x00000001 /* mailbox irq enable: has data */
+#define ARM_MC_IHAVESPACEIRQEN 0x00000002 /* mailbox irq enable: has space */
+#define ARM_MC_OPPISEMPTYIRQEN 0x00000004 /* mailbox irq enable: Opp. is empty */
+#define ARM_MC_MAIL_CLEAR 0x00000008 /* mailbox clear write 1, then 0 */
+#define ARM_MC_IHAVEDATAIRQPEND 0x00000010 /* mailbox irq pending: has space */
+#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mailbox irq pending: Opp. is empty */
+#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mailbox irq pending */
+/* Bit 7 is unused */
+#define ARM_MC_ERRNOOWN 0x00000100 /* error : none owner read from mailbox */
+#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */
+#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */
+
+/* Semaphore clear/debug register (...0xE0) */
+#define ARM_SD_OWN0 0x00000003 /* Owner of sem 0 */
+#define ARM_SD_OWN1 0x0000000C /* Owner of sem 1 */
+#define ARM_SD_OWN2 0x00000030 /* Owner of sem 2 */
+#define ARM_SD_OWN3 0x000000C0 /* Owner of sem 3 */
+#define ARM_SD_OWN4 0x00000300 /* Owner of sem 4 */
+#define ARM_SD_OWN5 0x00000C00 /* Owner of sem 5 */
+#define ARM_SD_OWN6 0x00003000 /* Owner of sem 6 */
+#define ARM_SD_OWN7 0x0000C000 /* Owner of sem 7 */
+#define ARM_SD_SEM0 0x00010000 /* Status of sem 0 */
+#define ARM_SD_SEM1 0x00020000 /* Status of sem 1 */
+#define ARM_SD_SEM2 0x00040000 /* Status of sem 2 */
+#define ARM_SD_SEM3 0x00080000 /* Status of sem 3 */
+#define ARM_SD_SEM4 0x00100000 /* Status of sem 4 */
+#define ARM_SD_SEM5 0x00200000 /* Status of sem 5 */
+#define ARM_SD_SEM6 0x00400000 /* Status of sem 6 */
+#define ARM_SD_SEM7 0x00800000 /* Status of sem 7 */
+
+/* Doorbells clear/debug register (...0xE4) */
+#define ARM_BD_OWN0 0x00000003 /* Owner of doorbell 0 */
+#define ARM_BD_OWN1 0x0000000C /* Owner of doorbell 1 */
+#define ARM_BD_OWN2 0x00000030 /* Owner of doorbell 2 */
+#define ARM_BD_OWN3 0x000000C0 /* Owner of doorbell 3 */
+#define ARM_BD_BELL0 0x00000100 /* Status of doorbell 0 */
+#define ARM_BD_BELL1 0x00000200 /* Status of doorbell 1 */
+#define ARM_BD_BELL2 0x00000400 /* Status of doorbell 2 */
+#define ARM_BD_BELL3 0x00000800 /* Status of doorbell 3 */
+
+/* MY IRQS register (...0xF8) */
+#define ARM_MYIRQ_BELL 0x00000001 /* This owner has a doorbell IRQ */
+#define ARM_MYIRQ_MAIL 0x00000002 /* This owner has a mailbox IRQ */
+
+/* ALL IRQS register (...0xF8) */
+#define ARM_AIS_BELL0 0x00000001 /* Doorbell 0 IRQ pending */
+#define ARM_AIS_BELL1 0x00000002 /* Doorbell 1 IRQ pending */
+#define ARM_AIS_BELL2 0x00000004 /* Doorbell 2 IRQ pending */
+#define ARM_AIS_BELL3 0x00000008 /* Doorbell 3 IRQ pending */
+#define ARM_AIS0_HAVEDATA 0x00000010 /* MAIL 0 has data IRQ pending */
+#define ARM_AIS0_HAVESPAC 0x00000020 /* MAIL 0 has space IRQ pending */
+#define ARM_AIS0_OPPEMPTY 0x00000040 /* MAIL 0 opposite is empty IRQ */
+#define ARM_AIS1_HAVEDATA 0x00000080 /* MAIL 1 has data IRQ pending */
+#define ARM_AIS1_HAVESPAC 0x00000100 /* MAIL 1 has space IRQ pending */
+#define ARM_AIS1_OPPEMPTY 0x00000200 /* MAIL 1 opposite is empty IRQ */
+/* Note that bell-0, bell-1 and MAIL0 IRQ go only to the ARM */
+/* Whilst that bell-2, bell-3 and MAIL1 IRQ go only to the VC */
+/* */
+/* ARM JTAG BASH */
+/* */
+#define AJB_BASE 0x7e2000c0
+
+#define AJBCONF HW_REGISTER_RW(AJB_BASE+0x00)
+#define AJB_BITS0 0x000000
+#define AJB_BITS4 0x000004
+#define AJB_BITS8 0x000008
+#define AJB_BITS12 0x00000C
+#define AJB_BITS16 0x000010
+#define AJB_BITS20 0x000014
+#define AJB_BITS24 0x000018
+#define AJB_BITS28 0x00001C
+#define AJB_BITS32 0x000020
+#define AJB_BITS34 0x000022
+#define AJB_OUT_MS 0x000040
+#define AJB_OUT_LS 0x000000
+#define AJB_INV_CLK 0x000080
+#define AJB_D0_RISE 0x000100
+#define AJB_D0_FALL 0x000000
+#define AJB_D1_RISE 0x000200
+#define AJB_D1_FALL 0x000000
+#define AJB_IN_RISE 0x000400
+#define AJB_IN_FALL 0x000000
+#define AJB_ENABLE 0x000800
+#define AJB_HOLD0 0x000000
+#define AJB_HOLD1 0x001000
+#define AJB_HOLD2 0x002000
+#define AJB_HOLD3 0x003000
+#define AJB_RESETN 0x004000
+#define AJB_CLKSHFT 16
+#define AJB_BUSY 0x80000000
+#define AJBTMS HW_REGISTER_RW(AJB_BASE+0x04)
+#define AJBTDI HW_REGISTER_RW(AJB_BASE+0x08)
+#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c)
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/arm_power.h rpi/arch/arm/mach-bcm2708/include/mach/arm_power.h
--- linux/arch/arm/mach-bcm2708/include/mach/arm_power.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/arm_power.h 2014-05-29 11:49:03.963967157 +0900
@@ -0,0 +1,60 @@
+/*
+ * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _ARM_POWER_H
+#define _ARM_POWER_H
+
+/* Use meaningful names on each side */
+#ifdef __VIDEOCORE__
+#define PREFIX(x) ARM_##x
+#else
+#define PREFIX(x) BCM_##x
+#endif
+
+enum {
+ PREFIX(POWER_SDCARD_BIT),
+ PREFIX(POWER_UART_BIT),
+ PREFIX(POWER_MINIUART_BIT),
+ PREFIX(POWER_USB_BIT),
+ PREFIX(POWER_I2C0_BIT),
+ PREFIX(POWER_I2C1_BIT),
+ PREFIX(POWER_I2C2_BIT),
+ PREFIX(POWER_SPI_BIT),
+ PREFIX(POWER_CCP2TX_BIT),
+
+ PREFIX(POWER_MAX)
+};
+
+enum {
+ PREFIX(POWER_SDCARD) = (1 << PREFIX(POWER_SDCARD_BIT)),
+ PREFIX(POWER_UART) = (1 << PREFIX(POWER_UART_BIT)),
+ PREFIX(POWER_MINIUART) = (1 << PREFIX(POWER_MINIUART_BIT)),
+ PREFIX(POWER_USB) = (1 << PREFIX(POWER_USB_BIT)),
+ PREFIX(POWER_I2C0) = (1 << PREFIX(POWER_I2C0_BIT)),
+ PREFIX(POWER_I2C1_MASK) = (1 << PREFIX(POWER_I2C1_BIT)),
+ PREFIX(POWER_I2C2_MASK) = (1 << PREFIX(POWER_I2C2_BIT)),
+ PREFIX(POWER_SPI_MASK) = (1 << PREFIX(POWER_SPI_BIT)),
+ PREFIX(POWER_CCP2TX_MASK) = (1 << PREFIX(POWER_CCP2TX_BIT)),
+
+ PREFIX(POWER_MASK) = (1 << PREFIX(POWER_MAX)) - 1,
+ PREFIX(POWER_NONE) = 0
+};
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/clkdev.h rpi/arch/arm/mach-bcm2708/include/mach/clkdev.h
--- linux/arch/arm/mach-bcm2708/include/mach/clkdev.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/clkdev.h 2014-05-29 11:49:03.963967157 +0900
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/debug-macro.S rpi/arch/arm/mach-bcm2708/include/mach/debug-macro.S
--- linux/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2014-05-29 11:49:03.963967157 +0900
@@ -0,0 +1,22 @@
+/* arch/arm/mach-bcm2708/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * 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.
+ *
+*/
+
+#include <mach/platform.h>
+
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =UART0_BASE
+ ldr \rv, =IO_ADDRESS(UART0_BASE)
+ .endm
+
+#include <debug/pl01x.S>
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/dma.h rpi/arch/arm/mach-bcm2708/include/mach/dma.h
--- linux/arch/arm/mach-bcm2708/include/mach/dma.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/dma.h 2014-05-29 11:49:03.963967157 +0900
@@ -0,0 +1,90 @@
+/*
+ * linux/arch/arm/mach-bcm2708/include/mach/dma.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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.
+ */
+
+
+#ifndef _MACH_BCM2708_DMA_H
+#define _MACH_BCM2708_DMA_H
+
+#define BCM_DMAMAN_DRIVER_NAME "bcm2708_dma"
+
+/* DMA CS Control and Status bits */
+#define BCM2708_DMA_ACTIVE (1 << 0)
+#define BCM2708_DMA_INT (1 << 2)
+#define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */
+#define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */
+#define BCM2708_DMA_ERR (1 << 8)
+#define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */
+#define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */
+
+/* DMA control block "info" field bits */
+#define BCM2708_DMA_INT_EN (1 << 0)
+#define BCM2708_DMA_TDMODE (1 << 1)
+#define BCM2708_DMA_WAIT_RESP (1 << 3)
+#define BCM2708_DMA_D_INC (1 << 4)
+#define BCM2708_DMA_D_WIDTH (1 << 5)
+#define BCM2708_DMA_D_DREQ (1 << 6)
+#define BCM2708_DMA_S_INC (1 << 8)
+#define BCM2708_DMA_S_WIDTH (1 << 9)
+#define BCM2708_DMA_S_DREQ (1 << 10)
+
+#define BCM2708_DMA_BURST(x) (((x)&0xf) << 12)
+#define BCM2708_DMA_PER_MAP(x) ((x) << 16)
+#define BCM2708_DMA_WAITS(x) (((x)&0x1f) << 21)
+
+#define BCM2708_DMA_DREQ_EMMC 11
+#define BCM2708_DMA_DREQ_SDHOST 13
+
+#define BCM2708_DMA_CS 0x00 /* Control and Status */
+#define BCM2708_DMA_ADDR 0x04
+/* the current control block appears in the following registers - read only */
+#define BCM2708_DMA_INFO 0x08
+#define BCM2708_DMA_SOURCE_AD 0x0c
+#define BCM2708_DMA_DEST_AD 0x10
+#define BCM2708_DMA_NEXTCB 0x1C
+#define BCM2708_DMA_DEBUG 0x20
+
+#define BCM2708_DMA4_CS (BCM2708_DMA_CHAN(4)+BCM2708_DMA_CS)
+#define BCM2708_DMA4_ADDR (BCM2708_DMA_CHAN(4)+BCM2708_DMA_ADDR)
+
+#define BCM2708_DMA_TDMODE_LEN(w, h) ((h) << 16 | (w))
+
+struct bcm2708_dma_cb {
+ unsigned long info;
+ unsigned long src;
+ unsigned long dst;
+ unsigned long length;
+ unsigned long stride;
+ unsigned long next;
+ unsigned long pad[2];
+};
+struct scatterlist;
+
+extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len);
+extern void bcm_dma_start(void __iomem *dma_chan_base,
+ dma_addr_t control_block);
+extern void bcm_dma_wait_idle(void __iomem *dma_chan_base);
+extern bool bcm_dma_is_busy(void __iomem *dma_chan_base);
+extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base);
+
+/* When listing features we can ask for when allocating DMA channels give
+ those with higher priority smaller ordinal numbers */
+#define BCM_DMA_FEATURE_FAST_ORD 0
+#define BCM_DMA_FEATURE_BULK_ORD 1
+#define BCM_DMA_FEATURE_FAST (1<<BCM_DMA_FEATURE_FAST_ORD)
+#define BCM_DMA_FEATURE_BULK (1<<BCM_DMA_FEATURE_BULK_ORD)
+#define BCM_DMA_FEATURE_COUNT 2
+
+/* return channel no or -ve error */
+extern int bcm_dma_chan_alloc(unsigned preferred_feature_set,
+ void __iomem **out_dma_base, int *out_dma_irq);
+extern int bcm_dma_chan_free(int channel);
+
+
+#endif /* _MACH_BCM2708_DMA_H */
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/entry-macro.S rpi/arch/arm/mach-bcm2708/include/mach/entry-macro.S
--- linux/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2014-05-29 11:49:03.963967157 +0900
@@ -0,0 +1,69 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for BCM2708 platforms
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <mach/hardware.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ ldr \base, =IO_ADDRESS(ARMCTRL_IC_BASE)
+ .endm
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ /* get masked status */
+ ldr \irqstat, [\base, #(ARM_IRQ_PEND0 - ARMCTRL_IC_BASE)]
+ mov \irqnr, #(ARM_IRQ0_BASE + 31)
+ and \tmp, \irqstat, #0x300 @ save bits 8 and 9
+ /* clear bits 8 and 9, and test */
+ bics \irqstat, \irqstat, #0x300
+ bne 1010f
+
+ tst \tmp, #0x100
+ ldrne \irqstat, [\base, #(ARM_IRQ_PEND1 - ARMCTRL_IC_BASE)]
+ movne \irqnr, #(ARM_IRQ1_BASE + 31)
+ @ Mask out the interrupts also present in PEND0 - see SW-5809
+ bicne \irqstat, #((1<<7) | (1<<9) | (1<<10))
+ bicne \irqstat, #((1<<18) | (1<<19))
+ bne 1010f
+
+ tst \tmp, #0x200
+ ldrne \irqstat, [\base, #(ARM_IRQ_PEND2 - ARMCTRL_IC_BASE)]
+ movne \irqnr, #(ARM_IRQ2_BASE + 31)
+ @ Mask out the interrupts also present in PEND0 - see SW-5809
+ bicne \irqstat, #((1<<21) | (1<<22) | (1<<23) | (1<<24) | (1<<25))
+ bicne \irqstat, #((1<<30))
+ beq 1020f
+
+1010:
+ @ For non-zero x, LSB(x) = 31 - CLZ(x^(x-1))
+ @ N.B. CLZ is an ARM5 instruction.
+ sub \tmp, \irqstat, #1
+ eor \irqstat, \irqstat, \tmp
+ clz \tmp, \irqstat
+ sub \irqnr, \tmp
+
+1020: @ EQ will be set if no irqs pending
+
+ .endm
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/frc.h rpi/arch/arm/mach-bcm2708/include/mach/frc.h
--- linux/arch/arm/mach-bcm2708/include/mach/frc.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/frc.h 2014-05-29 11:49:03.964967149 +0900
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/timex.h
+ *
+ * BCM2708 free running counter (timer)
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _MACH_FRC_H
+#define _MACH_FRC_H
+
+#define FRC_TICK_RATE (1000000)
+
+/*! Free running counter incrementing at the CLOCK_TICK_RATE
+ (slightly faster than frc_clock_ticks63()
+ */
+extern unsigned long frc_clock_ticks32(void);
+
+/*! Free running counter incrementing at the CLOCK_TICK_RATE
+ * Note - top bit should be ignored (see cnt32_to_63)
+ */
+extern unsigned long long frc_clock_ticks63(void);
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/gpio.h rpi/arch/arm/mach-bcm2708/include/mach/gpio.h
--- linux/arch/arm/mach-bcm2708/include/mach/gpio.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/gpio.h 2014-05-29 11:49:03.964967149 +0900
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/gpio.h
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#define BCM2708_NR_GPIOS 54 // number of gpio lines
+
+#define gpio_to_irq(x) ((x) + GPIO_IRQ_START)
+#define irq_to_gpio(x) ((x) - GPIO_IRQ_START)
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/hardware.h rpi/arch/arm/mach-bcm2708/include/mach/hardware.h
--- linux/arch/arm/mach-bcm2708/include/mach/hardware.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/hardware.h 2014-05-29 11:49:03.964967149 +0900
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/hardware.h
+ *
+ * This file contains the hardware definitions of the BCM2708 devices.
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#include <mach/platform.h>
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/io.h rpi/arch/arm/mach-bcm2708/include/mach/io.h
--- linux/arch/arm/mach-bcm2708/include/mach/io.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/io.h 2014-05-29 11:49:03.964967149 +0900
@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/io.h
+ *
+ * Copyright (C) 2003 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) __typesafe_io(a)
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/irqs.h rpi/arch/arm/mach-bcm2708/include/mach/irqs.h
--- linux/arch/arm/mach-bcm2708/include/mach/irqs.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/irqs.h 2014-05-29 11:49:03.964967149 +0900
@@ -0,0 +1,197 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/irqs.h
+ *
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2003 ARM Limited
+ * Copyright (C) 2000 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _BCM2708_IRQS_H_
+#define _BCM2708_IRQS_H_
+
+#include <mach/platform.h>
+
+/*
+ * IRQ interrupts definitions are the same as the INT definitions
+ * held within platform.h
+ */
+#define IRQ_ARMCTRL_START 0
+#define IRQ_TIMER0 (IRQ_ARMCTRL_START + INTERRUPT_TIMER0)
+#define IRQ_TIMER1 (IRQ_ARMCTRL_START + INTERRUPT_TIMER1)
+#define IRQ_TIMER2 (IRQ_ARMCTRL_START + INTERRUPT_TIMER2)
+#define IRQ_TIMER3 (IRQ_ARMCTRL_START + INTERRUPT_TIMER3)
+#define IRQ_CODEC0 (IRQ_ARMCTRL_START + INTERRUPT_CODEC0)
+#define IRQ_CODEC1 (IRQ_ARMCTRL_START + INTERRUPT_CODEC1)
+#define IRQ_CODEC2 (IRQ_ARMCTRL_START + INTERRUPT_CODEC2)
+#define IRQ_JPEG (IRQ_ARMCTRL_START + INTERRUPT_JPEG)
+#define IRQ_ISP (IRQ_ARMCTRL_START + INTERRUPT_ISP)
+#define IRQ_USB (IRQ_ARMCTRL_START + INTERRUPT_USB)
+#define IRQ_3D (IRQ_ARMCTRL_START + INTERRUPT_3D)
+#define IRQ_TRANSPOSER (IRQ_ARMCTRL_START + INTERRUPT_TRANSPOSER)
+#define IRQ_MULTICORESYNC0 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC0)
+#define IRQ_MULTICORESYNC1 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC1)
+#define IRQ_MULTICORESYNC2 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC2)
+#define IRQ_MULTICORESYNC3 (IRQ_ARMCTRL_START + INTERRUPT_MULTICORESYNC3)
+#define IRQ_DMA0 (IRQ_ARMCTRL_START + INTERRUPT_DMA0)
+#define IRQ_DMA1 (IRQ_ARMCTRL_START + INTERRUPT_DMA1)
+#define IRQ_DMA2 (IRQ_ARMCTRL_START + INTERRUPT_DMA2)
+#define IRQ_DMA3 (IRQ_ARMCTRL_START + INTERRUPT_DMA3)
+#define IRQ_DMA4 (IRQ_ARMCTRL_START + INTERRUPT_DMA4)
+#define IRQ_DMA5 (IRQ_ARMCTRL_START + INTERRUPT_DMA5)
+#define IRQ_DMA6 (IRQ_ARMCTRL_START + INTERRUPT_DMA6)
+#define IRQ_DMA7 (IRQ_ARMCTRL_START + INTERRUPT_DMA7)
+#define IRQ_DMA8 (IRQ_ARMCTRL_START + INTERRUPT_DMA8)
+#define IRQ_DMA9 (IRQ_ARMCTRL_START + INTERRUPT_DMA9)
+#define IRQ_DMA10 (IRQ_ARMCTRL_START + INTERRUPT_DMA10)
+#define IRQ_DMA11 (IRQ_ARMCTRL_START + INTERRUPT_DMA11)
+#define IRQ_DMA12 (IRQ_ARMCTRL_START + INTERRUPT_DMA12)
+#define IRQ_AUX (IRQ_ARMCTRL_START + INTERRUPT_AUX)
+#define IRQ_ARM (IRQ_ARMCTRL_START + INTERRUPT_ARM)
+#define IRQ_VPUDMA (IRQ_ARMCTRL_START + INTERRUPT_VPUDMA)
+#define IRQ_HOSTPORT (IRQ_ARMCTRL_START + INTERRUPT_HOSTPORT)
+#define IRQ_VIDEOSCALER (IRQ_ARMCTRL_START + INTERRUPT_VIDEOSCALER)
+#define IRQ_CCP2TX (IRQ_ARMCTRL_START + INTERRUPT_CCP2TX)
+#define IRQ_SDC (IRQ_ARMCTRL_START + INTERRUPT_SDC)
+#define IRQ_DSI0 (IRQ_ARMCTRL_START + INTERRUPT_DSI0)
+#define IRQ_AVE (IRQ_ARMCTRL_START + INTERRUPT_AVE)
+#define IRQ_CAM0 (IRQ_ARMCTRL_START + INTERRUPT_CAM0)
+#define IRQ_CAM1 (IRQ_ARMCTRL_START + INTERRUPT_CAM1)
+#define IRQ_HDMI0 (IRQ_ARMCTRL_START + INTERRUPT_HDMI0)
+#define IRQ_HDMI1 (IRQ_ARMCTRL_START + INTERRUPT_HDMI1)
+#define IRQ_PIXELVALVE1 (IRQ_ARMCTRL_START + INTERRUPT_PIXELVALVE1)
+#define IRQ_I2CSPISLV (IRQ_ARMCTRL_START + INTERRUPT_I2CSPISLV)
+#define IRQ_DSI1 (IRQ_ARMCTRL_START + INTERRUPT_DSI1)
+#define IRQ_PWA0 (IRQ_ARMCTRL_START + INTERRUPT_PWA0)
+#define IRQ_PWA1 (IRQ_ARMCTRL_START + INTERRUPT_PWA1)
+#define IRQ_CPR (IRQ_ARMCTRL_START + INTERRUPT_CPR)
+#define IRQ_SMI (IRQ_ARMCTRL_START + INTERRUPT_SMI)
+#define IRQ_GPIO0 (IRQ_ARMCTRL_START + INTERRUPT_GPIO0)
+#define IRQ_GPIO1 (IRQ_ARMCTRL_START + INTERRUPT_GPIO1)
+#define IRQ_GPIO2 (IRQ_ARMCTRL_START + INTERRUPT_GPIO2)
+#define IRQ_GPIO3 (IRQ_ARMCTRL_START + INTERRUPT_GPIO3)
+#define IRQ_I2C (IRQ_ARMCTRL_START + INTERRUPT_I2C)
+#define IRQ_SPI (IRQ_ARMCTRL_START + INTERRUPT_SPI)
+#define IRQ_I2SPCM (IRQ_ARMCTRL_START + INTERRUPT_I2SPCM)
+#define IRQ_SDIO (IRQ_ARMCTRL_START + INTERRUPT_SDIO)
+#define IRQ_UART (IRQ_ARMCTRL_START + INTERRUPT_UART)
+#define IRQ_SLIMBUS (IRQ_ARMCTRL_START + INTERRUPT_SLIMBUS)
+#define IRQ_VEC (IRQ_ARMCTRL_START + INTERRUPT_VEC)
+#define IRQ_CPG (IRQ_ARMCTRL_START + INTERRUPT_CPG)
+#define IRQ_RNG (IRQ_ARMCTRL_START + INTERRUPT_RNG)
+#define IRQ_ARASANSDIO (IRQ_ARMCTRL_START + INTERRUPT_ARASANSDIO)
+#define IRQ_AVSPMON (IRQ_ARMCTRL_START + INTERRUPT_AVSPMON)
+
+#define IRQ_ARM_TIMER (IRQ_ARMCTRL_START + INTERRUPT_ARM_TIMER)
+#define IRQ_ARM_MAILBOX (IRQ_ARMCTRL_START + INTERRUPT_ARM_MAILBOX)
+#define IRQ_ARM_DOORBELL_0 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_0)
+#define IRQ_ARM_DOORBELL_1 (IRQ_ARMCTRL_START + INTERRUPT_ARM_DOORBELL_1)
+#define IRQ_VPU0_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU0_HALTED)
+#define IRQ_VPU1_HALTED (IRQ_ARMCTRL_START + INTERRUPT_VPU1_HALTED)
+#define IRQ_ILLEGAL_TYPE0 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE0)
+#define IRQ_ILLEGAL_TYPE1 (IRQ_ARMCTRL_START + INTERRUPT_ILLEGAL_TYPE1)
+#define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1)
+#define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2)
+
+#define FIQ_START HARD_IRQS
+
+/*
+ * FIQ interrupts definitions are the same as the INT definitions.
+ */
+#define FIQ_TIMER0 (FIQ_START+INTERRUPT_TIMER0)
+#define FIQ_TIMER1 (FIQ_START+INTERRUPT_TIMER1)
+#define FIQ_TIMER2 (FIQ_START+INTERRUPT_TIMER2)
+#define FIQ_TIMER3 (FIQ_START+INTERRUPT_TIMER3)
+#define FIQ_CODEC0 (FIQ_START+INTERRUPT_CODEC0)
+#define FIQ_CODEC1 (FIQ_START+INTERRUPT_CODEC1)
+#define FIQ_CODEC2 (FIQ_START+INTERRUPT_CODEC2)
+#define FIQ_JPEG (FIQ_START+INTERRUPT_JPEG)
+#define FIQ_ISP (FIQ_START+INTERRUPT_ISP)
+#define FIQ_USB (FIQ_START+INTERRUPT_USB)
+#define FIQ_3D (FIQ_START+INTERRUPT_3D)
+#define FIQ_TRANSPOSER (FIQ_START+INTERRUPT_TRANSPOSER)
+#define FIQ_MULTICORESYNC0 (FIQ_START+INTERRUPT_MULTICORESYNC0)
+#define FIQ_MULTICORESYNC1 (FIQ_START+INTERRUPT_MULTICORESYNC1)
+#define FIQ_MULTICORESYNC2 (FIQ_START+INTERRUPT_MULTICORESYNC2)
+#define FIQ_MULTICORESYNC3 (FIQ_START+INTERRUPT_MULTICORESYNC3)
+#define FIQ_DMA0 (FIQ_START+INTERRUPT_DMA0)
+#define FIQ_DMA1 (FIQ_START+INTERRUPT_DMA1)
+#define FIQ_DMA2 (FIQ_START+INTERRUPT_DMA2)
+#define FIQ_DMA3 (FIQ_START+INTERRUPT_DMA3)
+#define FIQ_DMA4 (FIQ_START+INTERRUPT_DMA4)
+#define FIQ_DMA5 (FIQ_START+INTERRUPT_DMA5)
+#define FIQ_DMA6 (FIQ_START+INTERRUPT_DMA6)
+#define FIQ_DMA7 (FIQ_START+INTERRUPT_DMA7)
+#define FIQ_DMA8 (FIQ_START+INTERRUPT_DMA8)
+#define FIQ_DMA9 (FIQ_START+INTERRUPT_DMA9)
+#define FIQ_DMA10 (FIQ_START+INTERRUPT_DMA10)
+#define FIQ_DMA11 (FIQ_START+INTERRUPT_DMA11)
+#define FIQ_DMA12 (FIQ_START+INTERRUPT_DMA12)
+#define FIQ_AUX (FIQ_START+INTERRUPT_AUX)
+#define FIQ_ARM (FIQ_START+INTERRUPT_ARM)
+#define FIQ_VPUDMA (FIQ_START+INTERRUPT_VPUDMA)
+#define FIQ_HOSTPORT (FIQ_START+INTERRUPT_HOSTPORT)
+#define FIQ_VIDEOSCALER (FIQ_START+INTERRUPT_VIDEOSCALER)
+#define FIQ_CCP2TX (FIQ_START+INTERRUPT_CCP2TX)
+#define FIQ_SDC (FIQ_START+INTERRUPT_SDC)
+#define FIQ_DSI0 (FIQ_START+INTERRUPT_DSI0)
+#define FIQ_AVE (FIQ_START+INTERRUPT_AVE)
+#define FIQ_CAM0 (FIQ_START+INTERRUPT_CAM0)
+#define FIQ_CAM1 (FIQ_START+INTERRUPT_CAM1)
+#define FIQ_HDMI0 (FIQ_START+INTERRUPT_HDMI0)
+#define FIQ_HDMI1 (FIQ_START+INTERRUPT_HDMI1)
+#define FIQ_PIXELVALVE1 (FIQ_START+INTERRUPT_PIXELVALVE1)
+#define FIQ_I2CSPISLV (FIQ_START+INTERRUPT_I2CSPISLV)
+#define FIQ_DSI1 (FIQ_START+INTERRUPT_DSI1)
+#define FIQ_PWA0 (FIQ_START+INTERRUPT_PWA0)
+#define FIQ_PWA1 (FIQ_START+INTERRUPT_PWA1)
+#define FIQ_CPR (FIQ_START+INTERRUPT_CPR)
+#define FIQ_SMI (FIQ_START+INTERRUPT_SMI)
+#define FIQ_GPIO0 (FIQ_START+INTERRUPT_GPIO0)
+#define FIQ_GPIO1 (FIQ_START+INTERRUPT_GPIO1)
+#define FIQ_GPIO2 (FIQ_START+INTERRUPT_GPIO2)
+#define FIQ_GPIO3 (FIQ_START+INTERRUPT_GPIO3)
+#define FIQ_I2C (FIQ_START+INTERRUPT_I2C)
+#define FIQ_SPI (FIQ_START+INTERRUPT_SPI)
+#define FIQ_I2SPCM (FIQ_START+INTERRUPT_I2SPCM)
+#define FIQ_SDIO (FIQ_START+INTERRUPT_SDIO)
+#define FIQ_UART (FIQ_START+INTERRUPT_UART)
+#define FIQ_SLIMBUS (FIQ_START+INTERRUPT_SLIMBUS)
+#define FIQ_VEC (FIQ_START+INTERRUPT_VEC)
+#define FIQ_CPG (FIQ_START+INTERRUPT_CPG)
+#define FIQ_RNG (FIQ_START+INTERRUPT_RNG)
+#define FIQ_ARASANSDIO (FIQ_START+INTERRUPT_ARASANSDIO)
+#define FIQ_AVSPMON (FIQ_START+INTERRUPT_AVSPMON)
+
+#define FIQ_ARM_TIMER (FIQ_START+INTERRUPT_ARM_TIMER)
+#define FIQ_ARM_MAILBOX (FIQ_START+INTERRUPT_ARM_MAILBOX)
+#define FIQ_ARM_DOORBELL_0 (FIQ_START+INTERRUPT_ARM_DOORBELL_0)
+#define FIQ_ARM_DOORBELL_1 (FIQ_START+INTERRUPT_ARM_DOORBELL_1)
+#define FIQ_VPU0_HALTED (FIQ_START+INTERRUPT_VPU0_HALTED)
+#define FIQ_VPU1_HALTED (FIQ_START+INTERRUPT_VPU1_HALTED)
+#define FIQ_ILLEGAL_TYPE0 (FIQ_START+INTERRUPT_ILLEGAL_TYPE0)
+#define FIQ_ILLEGAL_TYPE1 (FIQ_START+INTERRUPT_ILLEGAL_TYPE1)
+#define FIQ_PENDING1 (FIQ_START+INTERRUPT_PENDING1)
+#define FIQ_PENDING2 (FIQ_START+INTERRUPT_PENDING2)
+
+#define HARD_IRQS (64 + 21)
+#define FIQ_IRQS (64 + 21)
+#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS)
+#define GPIO_IRQS (32*5)
+#define SPARE_IRQS (64)
+#define NR_IRQS (HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_IRQS)
+
+#endif /* _BCM2708_IRQS_H_ */
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/memory.h rpi/arch/arm/mach-bcm2708/include/mach/memory.h
--- linux/arch/arm/mach-bcm2708/include/mach/memory.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/memory.h 2014-05-29 11:49:03.964967149 +0900
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/memory.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/* Memory overview:
+
+ [ARMcore] <--virtual addr-->
+ [ARMmmu] <--physical addr-->
+ [GERTmap] <--bus add-->
+ [VCperiph]
+
+*/
+
+/*
+ * Physical DRAM offset.
+ */
+#define PLAT_PHYS_OFFSET UL(0x00000000)
+#define VC_ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */
+
+#ifdef CONFIG_BCM2708_NOL2CACHE
+ #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */
+#else
+ #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */
+#endif
+
+/* We're using the memory at 64M in the VideoCore for Linux - this adjustment
+ * will provide the offset into this area as well as setting the bits that
+ * stop the L1 and L2 cache from being used
+ *
+ * WARNING: this only works because the ARM is given memory at a fixed location
+ * (ARMMEM_OFFSET)
+ */
+#define BUS_OFFSET (VC_ARMMEM_OFFSET + _REAL_BUS_OFFSET)
+#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET))
+#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET))
+#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PLAT_PHYS_OFFSET))
+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PLAT_PHYS_OFFSET))
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/platform.h rpi/arch/arm/mach-bcm2708/include/mach/platform.h
--- linux/arch/arm/mach-bcm2708/include/mach/platform.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/platform.h 2014-05-29 11:49:03.965967141 +0900
@@ -0,0 +1,228 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/platform.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _BCM2708_PLATFORM_H
+#define _BCM2708_PLATFORM_H
+
+
+/* macros to get at IO space when running virtually */
+#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
+
+#define __io_address(n) IOMEM(IO_ADDRESS(n))
+
+
+/*
+ * SDRAM
+ */
+#define BCM2708_SDRAM_BASE 0x00000000
+
+/*
+ * Logic expansion modules
+ *
+ */
+
+
+/* ------------------------------------------------------------------------
+ * BCM2708 ARMCTRL Registers
+ * ------------------------------------------------------------------------
+ */
+
+#define HW_REGISTER_RW(addr) (addr)
+#define HW_REGISTER_RO(addr) (addr)
+
+#include "arm_control.h"
+#undef ARM_BASE
+
+/*
+ * Definitions and addresses for the ARM CONTROL logic
+ * This file is manually generated.
+ */
+
+#define BCM2708_PERI_BASE 0x20000000
+#define IC0_BASE (BCM2708_PERI_BASE + 0x2000)
+#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */
+#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */
+#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */
+#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */
+#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */
+#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */
+#define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */
+#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */
+#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */
+#define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */
+#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */
+#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */
+#define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */
+#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */
+#define EMMC_BASE (BCM2708_PERI_BASE + 0x300000) /* eMMC interface */
+#define SMI_BASE (BCM2708_PERI_BASE + 0x600000) /* SMI */
+#define BSC1_BASE (BCM2708_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */
+#define USB_BASE (BCM2708_PERI_BASE + 0x980000) /* DTC_OTG USB controller */
+#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/
+
+#define ARMCTRL_BASE (ARM_BASE + 0x000)
+#define ARMCTRL_IC_BASE (ARM_BASE + 0x200) /* ARM interrupt controller */
+#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) /* Timer 0 and 1 */
+#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) /* User 0 (ARM)'s Semaphores Doorbells and Mailboxes */
+
+
+/*
+ * Interrupt assignments
+ */
+
+#define ARM_IRQ1_BASE 0
+#define INTERRUPT_TIMER0 (ARM_IRQ1_BASE + 0)
+#define INTERRUPT_TIMER1 (ARM_IRQ1_BASE + 1)
+#define INTERRUPT_TIMER2 (ARM_IRQ1_BASE + 2)
+#define INTERRUPT_TIMER3 (ARM_IRQ1_BASE + 3)
+#define INTERRUPT_CODEC0 (ARM_IRQ1_BASE + 4)
+#define INTERRUPT_CODEC1 (ARM_IRQ1_BASE + 5)
+#define INTERRUPT_CODEC2 (ARM_IRQ1_BASE + 6)
+#define INTERRUPT_VC_JPEG (ARM_IRQ1_BASE + 7)
+#define INTERRUPT_ISP (ARM_IRQ1_BASE + 8)
+#define INTERRUPT_VC_USB (ARM_IRQ1_BASE + 9)
+#define INTERRUPT_VC_3D (ARM_IRQ1_BASE + 10)
+#define INTERRUPT_TRANSPOSER (ARM_IRQ1_BASE + 11)
+#define INTERRUPT_MULTICORESYNC0 (ARM_IRQ1_BASE + 12)
+#define INTERRUPT_MULTICORESYNC1 (ARM_IRQ1_BASE + 13)
+#define INTERRUPT_MULTICORESYNC2 (ARM_IRQ1_BASE + 14)
+#define INTERRUPT_MULTICORESYNC3 (ARM_IRQ1_BASE + 15)
+#define INTERRUPT_DMA0 (ARM_IRQ1_BASE + 16)
+#define INTERRUPT_DMA1 (ARM_IRQ1_BASE + 17)
+#define INTERRUPT_VC_DMA2 (ARM_IRQ1_BASE + 18)
+#define INTERRUPT_VC_DMA3 (ARM_IRQ1_BASE + 19)
+#define INTERRUPT_DMA4 (ARM_IRQ1_BASE + 20)
+#define INTERRUPT_DMA5 (ARM_IRQ1_BASE + 21)
+#define INTERRUPT_DMA6 (ARM_IRQ1_BASE + 22)
+#define INTERRUPT_DMA7 (ARM_IRQ1_BASE + 23)
+#define INTERRUPT_DMA8 (ARM_IRQ1_BASE + 24)
+#define INTERRUPT_DMA9 (ARM_IRQ1_BASE + 25)
+#define INTERRUPT_DMA10 (ARM_IRQ1_BASE + 26)
+#define INTERRUPT_DMA11 (ARM_IRQ1_BASE + 27)
+#define INTERRUPT_DMA12 (ARM_IRQ1_BASE + 28)
+#define INTERRUPT_AUX (ARM_IRQ1_BASE + 29)
+#define INTERRUPT_ARM (ARM_IRQ1_BASE + 30)
+#define INTERRUPT_VPUDMA (ARM_IRQ1_BASE + 31)
+
+#define ARM_IRQ2_BASE 32
+#define INTERRUPT_HOSTPORT (ARM_IRQ2_BASE + 0)
+#define INTERRUPT_VIDEOSCALER (ARM_IRQ2_BASE + 1)
+#define INTERRUPT_CCP2TX (ARM_IRQ2_BASE + 2)
+#define INTERRUPT_SDC (ARM_IRQ2_BASE + 3)
+#define INTERRUPT_DSI0 (ARM_IRQ2_BASE + 4)
+#define INTERRUPT_AVE (ARM_IRQ2_BASE + 5)
+#define INTERRUPT_CAM0 (ARM_IRQ2_BASE + 6)
+#define INTERRUPT_CAM1 (ARM_IRQ2_BASE + 7)
+#define INTERRUPT_HDMI0 (ARM_IRQ2_BASE + 8)
+#define INTERRUPT_HDMI1 (ARM_IRQ2_BASE + 9)
+#define INTERRUPT_PIXELVALVE1 (ARM_IRQ2_BASE + 10)
+#define INTERRUPT_I2CSPISLV (ARM_IRQ2_BASE + 11)
+#define INTERRUPT_DSI1 (ARM_IRQ2_BASE + 12)
+#define INTERRUPT_PWA0 (ARM_IRQ2_BASE + 13)
+#define INTERRUPT_PWA1 (ARM_IRQ2_BASE + 14)
+#define INTERRUPT_CPR (ARM_IRQ2_BASE + 15)
+#define INTERRUPT_SMI (ARM_IRQ2_BASE + 16)
+#define INTERRUPT_GPIO0 (ARM_IRQ2_BASE + 17)
+#define INTERRUPT_GPIO1 (ARM_IRQ2_BASE + 18)
+#define INTERRUPT_GPIO2 (ARM_IRQ2_BASE + 19)
+#define INTERRUPT_GPIO3 (ARM_IRQ2_BASE + 20)
+#define INTERRUPT_VC_I2C (ARM_IRQ2_BASE + 21)
+#define INTERRUPT_VC_SPI (ARM_IRQ2_BASE + 22)
+#define INTERRUPT_VC_I2SPCM (ARM_IRQ2_BASE + 23)
+#define INTERRUPT_VC_SDIO (ARM_IRQ2_BASE + 24)
+#define INTERRUPT_VC_UART (ARM_IRQ2_BASE + 25)
+#define INTERRUPT_SLIMBUS (ARM_IRQ2_BASE + 26)
+#define INTERRUPT_VEC (ARM_IRQ2_BASE + 27)
+#define INTERRUPT_CPG (ARM_IRQ2_BASE + 28)
+#define INTERRUPT_RNG (ARM_IRQ2_BASE + 29)
+#define INTERRUPT_VC_ARASANSDIO (ARM_IRQ2_BASE + 30)
+#define INTERRUPT_AVSPMON (ARM_IRQ2_BASE + 31)
+
+#define ARM_IRQ0_BASE 64
+#define INTERRUPT_ARM_TIMER (ARM_IRQ0_BASE + 0)
+#define INTERRUPT_ARM_MAILBOX (ARM_IRQ0_BASE + 1)
+#define INTERRUPT_ARM_DOORBELL_0 (ARM_IRQ0_BASE + 2)
+#define INTERRUPT_ARM_DOORBELL_1 (ARM_IRQ0_BASE + 3)
+#define INTERRUPT_VPU0_HALTED (ARM_IRQ0_BASE + 4)
+#define INTERRUPT_VPU1_HALTED (ARM_IRQ0_BASE + 5)
+#define INTERRUPT_ILLEGAL_TYPE0 (ARM_IRQ0_BASE + 6)
+#define INTERRUPT_ILLEGAL_TYPE1 (ARM_IRQ0_BASE + 7)
+#define INTERRUPT_PENDING1 (ARM_IRQ0_BASE + 8)
+#define INTERRUPT_PENDING2 (ARM_IRQ0_BASE + 9)
+#define INTERRUPT_JPEG (ARM_IRQ0_BASE + 10)
+#define INTERRUPT_USB (ARM_IRQ0_BASE + 11)
+#define INTERRUPT_3D (ARM_IRQ0_BASE + 12)
+#define INTERRUPT_DMA2 (ARM_IRQ0_BASE + 13)
+#define INTERRUPT_DMA3 (ARM_IRQ0_BASE + 14)
+#define INTERRUPT_I2C (ARM_IRQ0_BASE + 15)
+#define INTERRUPT_SPI (ARM_IRQ0_BASE + 16)
+#define INTERRUPT_I2SPCM (ARM_IRQ0_BASE + 17)
+#define INTERRUPT_SDIO (ARM_IRQ0_BASE + 18)
+#define INTERRUPT_UART (ARM_IRQ0_BASE + 19)
+#define INTERRUPT_ARASANSDIO (ARM_IRQ0_BASE + 20)
+
+#define MAXIRQNUM (32 + 32 + 20)
+#define MAXFIQNUM (32 + 32 + 20)
+
+#define MAX_TIMER 2
+#define MAX_PERIOD 699050
+#define TICKS_PER_uSEC 1
+
+/*
+ * These are useconds NOT ticks.
+ *
+ */
+#define mSEC_1 1000
+#define mSEC_5 (mSEC_1 * 5)
+#define mSEC_10 (mSEC_1 * 10)
+#define mSEC_25 (mSEC_1 * 25)
+#define SEC_1 (mSEC_1 * 1000)
+
+/*
+ * Watchdog
+ */
+#define PM_RSTC (PM_BASE+0x1c)
+#define PM_RSTS (PM_BASE+0x20)
+#define PM_WDOG (PM_BASE+0x24)
+
+#define PM_WDOG_RESET 0000000000
+#define PM_PASSWORD 0x5a000000
+#define PM_WDOG_TIME_SET 0x000fffff
+#define PM_RSTC_WRCFG_CLR 0xffffffcf
+#define PM_RSTC_WRCFG_SET 0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
+#define PM_RSTC_RESET 0x00000102
+
+#define PM_RSTS_HADPOR_SET 0x00001000
+#define PM_RSTS_HADSRH_SET 0x00000400
+#define PM_RSTS_HADSRF_SET 0x00000200
+#define PM_RSTS_HADSRQ_SET 0x00000100
+#define PM_RSTS_HADWRH_SET 0x00000040
+#define PM_RSTS_HADWRF_SET 0x00000020
+#define PM_RSTS_HADWRQ_SET 0x00000010
+#define PM_RSTS_HADDRH_SET 0x00000004
+#define PM_RSTS_HADDRF_SET 0x00000002
+#define PM_RSTS_HADDRQ_SET 0x00000001
+
+#define UART0_CLOCK 3000000
+
+#endif
+
+/* END */
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/power.h rpi/arch/arm/mach-bcm2708/include/mach/power.h
--- linux/arch/arm/mach-bcm2708/include/mach/power.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/power.h 2014-05-29 11:49:03.965967141 +0900
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/mach-bcm2708/power.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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 device provides a shared mechanism for controlling the power to
+ * VideoCore subsystems.
+ */
+
+#ifndef _MACH_BCM2708_POWER_H
+#define _MACH_BCM2708_POWER_H
+
+#include <linux/types.h>
+#include <mach/arm_power.h>
+
+typedef unsigned int BCM_POWER_HANDLE_T;
+
+extern int bcm_power_open(BCM_POWER_HANDLE_T *handle);
+extern int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request);
+extern int bcm_power_close(BCM_POWER_HANDLE_T handle);
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/system.h rpi/arch/arm/mach-bcm2708/include/mach/system.h
--- linux/arch/arm/mach-bcm2708/include/mach/system.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/system.h 2014-05-29 11:49:03.965967141 +0900
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/system.h
+ *
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2003 ARM Limited
+ * Copyright (C) 2000 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+static inline void arch_idle(void)
+{
+ /*
+ * This should do all the clock switching
+ * and wait for interrupt tricks
+ */
+ cpu_do_idle();
+}
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/timex.h rpi/arch/arm/mach-bcm2708/include/mach/timex.h
--- linux/arch/arm/mach-bcm2708/include/mach/timex.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/timex.h 2014-05-29 11:49:03.965967141 +0900
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/timex.h
+ *
+ * BCM2708 sysem clock frequency
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 CLOCK_TICK_RATE (1000000)
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/uncompress.h rpi/arch/arm/mach-bcm2708/include/mach/uncompress.h
--- linux/arch/arm/mach-bcm2708/include/mach/uncompress.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/uncompress.h 2014-05-29 11:49:03.965967141 +0900
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-bcn2708/include/mach/uncompress.h
+ *
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2003 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/io.h>
+#include <linux/amba/serial.h>
+#include <mach/hardware.h>
+
+#define UART_BAUD 115200
+
+#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR)
+#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR)
+#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD)
+#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD)
+#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH)
+#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR)
+
+/*
+ * This does not append a newline
+ */
+static inline void putc(int c)
+{
+ while (__raw_readl(BCM2708_UART_FR) & UART01x_FR_TXFF)
+ barrier();
+
+ __raw_writel(c, BCM2708_UART_DR);
+}
+
+static inline void flush(void)
+{
+ int fr;
+
+ do {
+ fr = __raw_readl(BCM2708_UART_FR);
+ barrier();
+ } while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE);
+}
+
+static inline void arch_decomp_setup(void)
+{
+ int temp, div, rem, frac;
+
+ temp = 16 * UART_BAUD;
+ div = UART0_CLOCK / temp;
+ rem = UART0_CLOCK % temp;
+ temp = (8 * rem) / UART_BAUD;
+ frac = (temp >> 1) + (temp & 1);
+
+ /* Make sure the UART is disabled before we start */
+ __raw_writel(0, BCM2708_UART_CR);
+
+ /* Set the baud rate */
+ __raw_writel(div, BCM2708_UART_IBRD);
+ __raw_writel(frac, BCM2708_UART_FBRD);
+
+ /* Set the UART to 8n1, FIFO enabled */
+ __raw_writel(UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN, BCM2708_UART_LCRH);
+
+ /* Enable the UART */
+ __raw_writel(UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE,
+ BCM2708_UART_CR);
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_wdog()
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/vcio.h rpi/arch/arm/mach-bcm2708/include/mach/vcio.h
--- linux/arch/arm/mach-bcm2708/include/mach/vcio.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/vcio.h 2014-05-29 11:49:03.966967132 +0900
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/vcio.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 _MACH_BCM2708_VCIO_H
+#define _MACH_BCM2708_VCIO_H
+
+/* Routines to handle I/O via the VideoCore "ARM control" registers
+ * (semaphores, doorbells, mailboxes)
+ */
+
+#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio"
+
+/* Constants shared with the ARM identifying separate mailbox channels */
+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */
+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */
+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */
+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */
+#define MBOX_CHAN_COUNT 9
+
+/* Mailbox property tags */
+enum {
+ VCMSG_PROPERTY_END = 0x00000000,
+ VCMSG_GET_FIRMWARE_REVISION = 0x00000001,
+ VCMSG_GET_BOARD_MODEL = 0x00010001,
+ VCMSG_GET_BOARD_REVISION = 0x00020002,
+ VCMSG_GET_BOARD_MAC_ADDRESS = 0x00020003,
+ VCMSG_GET_BOARD_SERIAL = 0x00020004,
+ VCMSG_GET_ARM_MEMORY = 0x00020005,
+ VCMSG_GET_VC_MEMORY = 0x00020006,
+ VCMSG_GET_CLOCKS = 0x00020007,
+ VCMSG_GET_COMMAND_LINE = 0x00050001,
+ VCMSG_GET_DMA_CHANNELS = 0x00060001,
+ VCMSG_GET_POWER_STATE = 0x00020001,
+ VCMSG_GET_TIMING = 0x00020002,
+ VCMSG_SET_POWER_STATE = 0x00028001,
+ VCMSG_GET_CLOCK_STATE = 0x00030001,
+ VCMSG_SET_CLOCK_STATE = 0x00038001,
+ VCMSG_GET_CLOCK_RATE = 0x00030002,
+ VCMSG_SET_CLOCK_RATE = 0x00038002,
+ VCMSG_GET_VOLTAGE = 0x00030003,
+ VCMSG_SET_VOLTAGE = 0x00038003,
+ VCMSG_GET_MAX_CLOCK = 0x00030004,
+ VCMSG_GET_MAX_VOLTAGE = 0x00030005,
+ VCMSG_GET_TEMPERATURE = 0x00030006,
+ VCMSG_GET_MIN_CLOCK = 0x00030007,
+ VCMSG_GET_MIN_VOLTAGE = 0x00030008,
+ VCMSG_GET_TURBO = 0x00030009,
+ VCMSG_SET_TURBO = 0x00038009,
+ VCMSG_SET_ALLOCATE_BUFFER = 0x00040001,
+ VCMSG_SET_RELEASE_BUFFER = 0x00048001,
+ VCMSG_SET_BLANK_SCREEN = 0x00040002,
+ VCMSG_TST_BLANK_SCREEN = 0x00044002,
+ VCMSG_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
+ VCMSG_TST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
+ VCMSG_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
+ VCMSG_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
+ VCMSG_TST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
+ VCMSG_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
+ VCMSG_GET_DEPTH = 0x00040005,
+ VCMSG_TST_DEPTH = 0x00044005,
+ VCMSG_SET_DEPTH = 0x00048005,
+ VCMSG_GET_PIXEL_ORDER = 0x00040006,
+ VCMSG_TST_PIXEL_ORDER = 0x00044006,
+ VCMSG_SET_PIXEL_ORDER = 0x00048006,
+ VCMSG_GET_ALPHA_MODE = 0x00040007,
+ VCMSG_TST_ALPHA_MODE = 0x00044007,
+ VCMSG_SET_ALPHA_MODE = 0x00048007,
+ VCMSG_GET_PITCH = 0x00040008,
+ VCMSG_TST_PITCH = 0x00044008,
+ VCMSG_SET_PITCH = 0x00048008,
+ VCMSG_GET_VIRTUAL_OFFSET = 0x00040009,
+ VCMSG_TST_VIRTUAL_OFFSET = 0x00044009,
+ VCMSG_SET_VIRTUAL_OFFSET = 0x00048009,
+ VCMSG_GET_OVERSCAN = 0x0004000a,
+ VCMSG_TST_OVERSCAN = 0x0004400a,
+ VCMSG_SET_OVERSCAN = 0x0004800a,
+ VCMSG_GET_PALETTE = 0x0004000b,
+ VCMSG_TST_PALETTE = 0x0004400b,
+ VCMSG_SET_PALETTE = 0x0004800b,
+ VCMSG_GET_LAYER = 0x0004000c,
+ VCMSG_TST_LAYER = 0x0004400c,
+ VCMSG_SET_LAYER = 0x0004800c,
+ VCMSG_GET_TRANSFORM = 0x0004000d,
+ VCMSG_TST_TRANSFORM = 0x0004400d,
+ VCMSG_SET_TRANSFORM = 0x0004800d,
+};
+
+extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28);
+extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28);
+extern int /*rc*/ bcm_mailbox_property(void *data, int size);
+
+#include <linux/ioctl.h>
+
+/*
+ * The major device number. We can't rely on dynamic
+ * registration any more, because ioctls need to know
+ * it.
+ */
+#define MAJOR_NUM 100
+
+/*
+ * Set the message of the device driver
+ */
+#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *)
+/*
+ * _IOWR means that we're creating an ioctl command
+ * number for passing information from a user process
+ * to the kernel module and from the kernel module to user process
+ *
+ * The first arguments, MAJOR_NUM, is the major device
+ * number we're using.
+ *
+ * The second argument is the number of the command
+ * (there could be several with different meanings).
+ *
+ * The third argument is the type we want to get from
+ * the process to the kernel.
+ */
+
+/*
+ * The name of the device file
+ */
+#define DEVICE_FILE_NAME "char_dev"
+
+#endif
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/vc_mem.h rpi/arch/arm/mach-bcm2708/include/mach/vc_mem.h
--- linux/arch/arm/mach-bcm2708/include/mach/vc_mem.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/vc_mem.h 2014-05-29 11:49:03.965967141 +0900
@@ -0,0 +1,35 @@
+/*****************************************************************************
+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+#if !defined( VC_MEM_H )
+#define VC_MEM_H
+
+#include <linux/ioctl.h>
+
+#define VC_MEM_IOC_MAGIC 'v'
+
+#define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )
+#define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )
+#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )
+#define VC_MEM_IOC_MEM_LOAD _IOR( VC_MEM_IOC_MAGIC, 3, unsigned int )
+
+#if defined( __KERNEL__ )
+#define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
+
+extern unsigned long mm_vc_mem_phys_addr;
+extern unsigned int mm_vc_mem_size;
+extern int vc_mem_get_current_size( void );
+#endif
+
+#endif /* VC_MEM_H */
diff -Nur linux/arch/arm/mach-bcm2708/include/mach/vmalloc.h rpi/arch/arm/mach-bcm2708/include/mach/vmalloc.h
--- linux/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2014-05-29 11:49:03.966967132 +0900
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/vmalloc.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 VMALLOC_END (0xe8000000)
diff -Nur linux/arch/arm/mach-bcm2708/Kconfig rpi/arch/arm/mach-bcm2708/Kconfig
--- linux/arch/arm/mach-bcm2708/Kconfig 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/Kconfig 2014-05-29 11:49:03.960967183 +0900
@@ -0,0 +1,41 @@
+menu "Broadcom BCM2708 Implementations"
+ depends on ARCH_BCM2708
+
+config MACH_BCM2708
+ bool "Broadcom BCM2708 Development Platform"
+ select NEED_MACH_MEMORY_H
+ select NEED_MACH_IO_H
+ select CPU_V6
+ help
+ Include support for the Broadcom(R) BCM2708 platform.
+
+config BCM2708_GPIO
+ bool "BCM2708 gpio support"
+ depends on MACH_BCM2708
+ select ARCH_REQUIRE_GPIOLIB
+ default y
+ help
+ Include support for the Broadcom(R) BCM2708 gpio.
+
+config BCM2708_VCMEM
+ bool "Videocore Memory"
+ depends on MACH_BCM2708
+ default y
+ help
+ Helper for videocore memory access and total size allocation.
+
+config BCM2708_NOL2CACHE
+ bool "Videocore L2 cache disable"
+ depends on MACH_BCM2708
+ default n
+ help
+ Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt.
+
+config BCM2708_SPIDEV
+ bool "Bind spidev to SPI0 master"
+ depends on MACH_BCM2708
+ depends on SPI
+ default y
+ help
+ Binds spidev driver to the SPI0 master
+endmenu
diff -Nur linux/arch/arm/mach-bcm2708/Makefile rpi/arch/arm/mach-bcm2708/Makefile
--- linux/arch/arm/mach-bcm2708/Makefile 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/Makefile 2014-05-29 11:49:03.960967183 +0900
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o
+obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o
+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
diff -Nur linux/arch/arm/mach-bcm2708/Makefile.boot rpi/arch/arm/mach-bcm2708/Makefile.boot
--- linux/arch/arm/mach-bcm2708/Makefile.boot 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/Makefile.boot 2014-05-29 11:49:03.961967174 +0900
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x00008000
+params_phys-y := 0x00000100
+initrd_phys-y := 0x00800000
diff -Nur linux/arch/arm/mach-bcm2708/power.c rpi/arch/arm/mach-bcm2708/power.c
--- linux/arch/arm/mach-bcm2708/power.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/power.c 2014-05-29 11:49:03.966967132 +0900
@@ -0,0 +1,194 @@
+/*
+ * linux/arch/arm/mach-bcm2708/power.c
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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 device provides a shared mechanism for controlling the power to
+ * VideoCore subsystems.
+ */
+
+#include <linux/module.h>
+#include <linux/semaphore.h>
+#include <linux/bug.h>
+#include <mach/power.h>
+#include <mach/vcio.h>
+#include <mach/arm_power.h>
+
+#define DRIVER_NAME "bcm2708_power"
+
+#define BCM_POWER_MAXCLIENTS 4
+#define BCM_POWER_NOCLIENT (1<<31)
+
+/* Some drivers expect there devices to be permanently powered */
+#define BCM_POWER_ALWAYS_ON (BCM_POWER_USB)
+
+#if 1
+#define DPRINTK printk
+#else
+#define DPRINTK if (0) printk
+#endif
+
+struct state_struct {
+ uint32_t global_request;
+ uint32_t client_request[BCM_POWER_MAXCLIENTS];
+ struct semaphore client_mutex;
+ struct semaphore mutex;
+} g_state;
+
+int bcm_power_open(BCM_POWER_HANDLE_T *handle)
+{
+ BCM_POWER_HANDLE_T i;
+ int ret = -EBUSY;
+
+ down(&g_state.client_mutex);
+
+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) {
+ if (g_state.client_request[i] == BCM_POWER_NOCLIENT) {
+ g_state.client_request[i] = BCM_POWER_NONE;
+ *handle = i;
+ ret = 0;
+ break;
+ }
+ }
+
+ up(&g_state.client_mutex);
+
+ DPRINTK("bcm_power_open() -> %d\n", *handle);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(bcm_power_open);
+
+int bcm_power_request(BCM_POWER_HANDLE_T handle, uint32_t request)
+{
+ int rc = 0;
+
+ DPRINTK("bcm_power_request(%d, %x)\n", handle, request);
+
+ if ((handle < BCM_POWER_MAXCLIENTS) &&
+ (g_state.client_request[handle] != BCM_POWER_NOCLIENT)) {
+ if (down_interruptible(&g_state.mutex) != 0) {
+ DPRINTK("bcm_power_request -> interrupted\n");
+ return -EINTR;
+ }
+
+ if (request != g_state.client_request[handle]) {
+ uint32_t others_request = 0;
+ uint32_t global_request;
+ BCM_POWER_HANDLE_T i;
+
+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++) {
+ if (i != handle)
+ others_request |=
+ g_state.client_request[i];
+ }
+ others_request &= ~BCM_POWER_NOCLIENT;
+
+ global_request = request | others_request;
+ if (global_request != g_state.global_request) {
+ uint32_t actual;
+
+ /* Send a request to VideoCore */
+ bcm_mailbox_write(MBOX_CHAN_POWER,
+ global_request << 4);
+
+ /* Wait for a response during power-up */
+ if (global_request & ~g_state.global_request) {
+ rc = bcm_mailbox_read(MBOX_CHAN_POWER,
+ &actual);
+ DPRINTK
+ ("bcm_mailbox_read -> %08x, %d\n",
+ actual, rc);
+ actual >>= 4;
+ } else {
+ rc = 0;
+ actual = global_request;
+ }
+
+ if (rc == 0) {
+ if (actual != global_request) {
+ printk(KERN_ERR
+ "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n",
+ __func__,
+ g_state.global_request,
+ global_request, actual, request, others_request);
+ /* A failure */
+ BUG_ON((others_request & actual)
+ != others_request);
+ request &= actual;
+ rc = -EIO;
+ }
+
+ g_state.global_request = actual;
+ g_state.client_request[handle] =
+ request;
+ }
+ }
+ }
+ up(&g_state.mutex);
+ } else {
+ rc = -EINVAL;
+ }
+ DPRINTK("bcm_power_request -> %d\n", rc);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(bcm_power_request);
+
+int bcm_power_close(BCM_POWER_HANDLE_T handle)
+{
+ int rc;
+
+ DPRINTK("bcm_power_close(%d)\n", handle);
+
+ rc = bcm_power_request(handle, BCM_POWER_NONE);
+ if (rc == 0)
+ g_state.client_request[handle] = BCM_POWER_NOCLIENT;
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(bcm_power_close);
+
+static int __init bcm_power_init(void)
+{
+#if defined(BCM_POWER_ALWAYS_ON)
+ BCM_POWER_HANDLE_T always_on_handle;
+#endif
+ int rc = 0;
+ int i;
+
+ printk(KERN_INFO "bcm_power: Broadcom power driver\n");
+ bcm_mailbox_write(MBOX_CHAN_POWER, 0);
+
+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++)
+ g_state.client_request[i] = BCM_POWER_NOCLIENT;
+
+ sema_init(&g_state.client_mutex, 1);
+ sema_init(&g_state.mutex, 1);
+
+ g_state.global_request = 0;
+
+#if defined(BCM_POWER_ALWAYS_ON)
+ if (BCM_POWER_ALWAYS_ON) {
+ bcm_power_open(&always_on_handle);
+ bcm_power_request(always_on_handle, BCM_POWER_ALWAYS_ON);
+ }
+#endif
+
+ return rc;
+}
+
+static void __exit bcm_power_exit(void)
+{
+ bcm_mailbox_write(MBOX_CHAN_POWER, 0);
+}
+
+arch_initcall(bcm_power_init); /* Initialize early */
+module_exit(bcm_power_exit);
+
+MODULE_AUTHOR("Phil Elwell");
+MODULE_DESCRIPTION("Interface to BCM2708 power management");
+MODULE_LICENSE("GPL");
diff -Nur linux/arch/arm/mach-bcm2708/vcio.c rpi/arch/arm/mach-bcm2708/vcio.c
--- linux/arch/arm/mach-bcm2708/vcio.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/vcio.c 2014-05-29 11:49:03.967967124 +0900
@@ -0,0 +1,474 @@
+/*
+ * linux/arch/arm/mach-bcm2708/vcio.c
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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 device provides a shared mechanism for writing to the mailboxes,
+ * semaphores, doorbells etc. that are shared between the ARM and the
+ * VideoCore processor
+ */
+
+#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <linux/io.h>
+
+#include <mach/vcio.h>
+#include <mach/platform.h>
+
+#include <asm/uaccess.h>
+
+
+#define DRIVER_NAME BCM_VCIO_DRIVER_NAME
+
+/* ----------------------------------------------------------------------
+ * Mailbox
+ * -------------------------------------------------------------------- */
+
+/* offsets from a mail box base address */
+#define MAIL_WRT 0x00 /* write - and next 4 words */
+#define MAIL_RD 0x00 /* read - and next 4 words */
+#define MAIL_POL 0x10 /* read without popping the fifo */
+#define MAIL_SND 0x14 /* sender ID (bottom two bits) */
+#define MAIL_STA 0x18 /* status */
+#define MAIL_CNF 0x1C /* configuration */
+
+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf))
+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf))
+#define MBOX_CHAN(msg) ((msg) & 0xf)
+#define MBOX_DATA28(msg) ((msg) & ~0xf)
+#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4)
+
+#define MBOX_MAGIC 0xd0d0c0de
+
+struct vc_mailbox {
+ struct device *dev; /* parent device */
+ void __iomem *status;
+ void __iomem *config;
+ void __iomem *read;
+ void __iomem *write;
+ uint32_t msg[MBOX_CHAN_COUNT];
+ struct semaphore sema[MBOX_CHAN_COUNT];
+ uint32_t magic;
+};
+
+static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev,
+ uint32_t addr_mbox)
+{
+ int i;
+
+ mbox_out->dev = dev;
+ mbox_out->status = __io_address(addr_mbox + MAIL_STA);
+ mbox_out->config = __io_address(addr_mbox + MAIL_CNF);
+ mbox_out->read = __io_address(addr_mbox + MAIL_RD);
+ /* Write to the other mailbox */
+ mbox_out->write =
+ __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) +
+ MAIL_WRT);
+
+ for (i = 0; i < MBOX_CHAN_COUNT; i++) {
+ mbox_out->msg[i] = 0;
+ sema_init(&mbox_out->sema[i], 0);
+ }
+
+ /* Enable the interrupt on data reception */
+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config);
+
+ mbox_out->magic = MBOX_MAGIC;
+}
+
+static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28)
+{
+ int rc;
+
+ if (mbox->magic != MBOX_MAGIC)
+ rc = -EINVAL;
+ else {
+ /* wait for the mailbox FIFO to have some space in it */
+ while (0 != (readl(mbox->status) & ARM_MS_FULL))
+ cpu_relax();
+
+ writel(MBOX_MSG(chan, data28), mbox->write);
+ rc = 0;
+ }
+ return rc;
+}
+
+static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28)
+{
+ int rc;
+
+ if (mbox->magic != MBOX_MAGIC)
+ rc = -EINVAL;
+ else {
+ down(&mbox->sema[chan]);
+ *data28 = MBOX_DATA28(mbox->msg[chan]);
+ mbox->msg[chan] = 0;
+ rc = 0;
+ }
+ return rc;
+}
+
+static irqreturn_t mbox_irq(int irq, void *dev_id)
+{
+ /* wait for the mailbox FIFO to have some data in it */
+ struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id;
+ int status = readl(mbox->status);
+ int ret = IRQ_NONE;
+
+ while (!(status & ARM_MS_EMPTY)) {
+ uint32_t msg = readl(mbox->read);
+ int chan = MBOX_CHAN(msg);
+ if (chan < MBOX_CHAN_COUNT) {
+ if (mbox->msg[chan]) {
+ /* Overflow */
+ printk(KERN_ERR DRIVER_NAME
+ ": mbox chan %d overflow - drop %08x\n",
+ chan, msg);
+ } else {
+ mbox->msg[chan] = (msg | 0xf);
+ up(&mbox->sema[chan]);
+ }
+ } else {
+ printk(KERN_ERR DRIVER_NAME
+ ": invalid channel selector (msg %08x)\n", msg);
+ }
+ ret = IRQ_HANDLED;
+ status = readl(mbox->status);
+ }
+ return ret;
+}
+
+static struct irqaction mbox_irqaction = {
+ .name = "ARM Mailbox IRQ",
+ .flags = IRQF_DISABLED | IRQF_IRQPOLL,
+ .handler = mbox_irq,
+};
+
+/* ----------------------------------------------------------------------
+ * Mailbox Methods
+ * -------------------------------------------------------------------- */
+
+static struct device *mbox_dev; /* we assume there's only one! */
+
+static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28)
+{
+ int rc;
+
+ struct vc_mailbox *mailbox = dev_get_drvdata(dev);
+ device_lock(dev);
+ rc = mbox_write(mailbox, chan, data28);
+ device_unlock(dev);
+
+ return rc;
+}
+
+static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28)
+{
+ int rc;
+
+ struct vc_mailbox *mailbox = dev_get_drvdata(dev);
+ device_lock(dev);
+ rc = mbox_read(mailbox, chan, data28);
+ device_unlock(dev);
+
+ return rc;
+}
+
+extern int bcm_mailbox_write(unsigned chan, uint32_t data28)
+{
+ if (mbox_dev)
+ return dev_mbox_write(mbox_dev, chan, data28);
+ else
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(bcm_mailbox_write);
+
+extern int bcm_mailbox_read(unsigned chan, uint32_t *data28)
+{
+ if (mbox_dev)
+ return dev_mbox_read(mbox_dev, chan, data28);
+ else
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(bcm_mailbox_read);
+
+static void dev_mbox_register(const char *dev_name, struct device *dev)
+{
+ mbox_dev = dev;
+}
+
+static int mbox_copy_from_user(void *dst, const void *src, int size)
+{
+ if ( (uint32_t)src < TASK_SIZE)
+ {
+ return copy_from_user(dst, src, size);
+ }
+ else
+ {
+ memcpy( dst, src, size );
+ return 0;
+ }
+}
+
+static int mbox_copy_to_user(void *dst, const void *src, int size)
+{
+ if ( (uint32_t)dst < TASK_SIZE)
+ {
+ return copy_to_user(dst, src, size);
+ }
+ else
+ {
+ memcpy( dst, src, size );
+ return 0;
+ }
+}
+
+static DEFINE_MUTEX(mailbox_lock);
+extern int bcm_mailbox_property(void *data, int size)
+{
+ uint32_t success;
+ dma_addr_t mem_bus; /* the memory address accessed from videocore */
+ void *mem_kern; /* the memory address accessed from driver */
+ int s = 0;
+
+ mutex_lock(&mailbox_lock);
+ /* allocate some memory for the messages communicating with GPU */
+ mem_kern = dma_alloc_coherent(NULL, PAGE_ALIGN(size), &mem_bus, GFP_ATOMIC);
+ if (mem_kern) {
+ /* create the message */
+ mbox_copy_from_user(mem_kern, data, size);
+
+ /* send the message */
+ wmb();
+ s = bcm_mailbox_write(MBOX_CHAN_PROPERTY, (uint32_t)mem_bus);
+ if (s == 0) {
+ s = bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success);
+ }
+ if (s == 0) {
+ /* copy the response */
+ rmb();
+ mbox_copy_to_user(data, mem_kern, size);
+ }
+ dma_free_coherent(NULL, PAGE_ALIGN(size), mem_kern, mem_bus);
+ } else {
+ s = -ENOMEM;
+ }
+ if (s != 0)
+ printk(KERN_ERR DRIVER_NAME ": %s failed (%d)\n", __func__, s);
+
+ mutex_unlock(&mailbox_lock);
+ return s;
+}
+EXPORT_SYMBOL_GPL(bcm_mailbox_property);
+
+/* ----------------------------------------------------------------------
+ * Platform Device for Mailbox
+ * -------------------------------------------------------------------- */
+
+/*
+ * Is the device open right now? Used to prevent
+ * concurent access into the same device
+ */
+static int Device_Open = 0;
+
+/*
+ * This is called whenever a process attempts to open the device file
+ */
+static int device_open(struct inode *inode, struct file *file)
+{
+ /*
+ * We don't want to talk to two processes at the same time
+ */
+ if (Device_Open)
+ return -EBUSY;
+
+ Device_Open++;
+ /*
+ * Initialize the message
+ */
+ try_module_get(THIS_MODULE);
+ return 0;
+}
+
+static int device_release(struct inode *inode, struct file *file)
+{
+ /*
+ * We're now ready for our next caller
+ */
+ Device_Open--;
+
+ module_put(THIS_MODULE);
+ return 0;
+}
+
+/*
+ * This function is called whenever a process tries to do an ioctl on our
+ * device file. We get two extra parameters (additional to the inode and file
+ * structures, which all device functions get): the number of the ioctl called
+ * and the parameter given to the ioctl function.
+ *
+ * If the ioctl is write or read/write (meaning output is returned to the
+ * calling process), the ioctl call returns the output of this function.
+ *
+ */
+static long device_ioctl(struct file *file, /* see include/linux/fs.h */
+ unsigned int ioctl_num, /* number and param for ioctl */
+ unsigned long ioctl_param)
+{
+ unsigned size;
+ /*
+ * Switch according to the ioctl called
+ */
+ switch (ioctl_num) {
+ case IOCTL_MBOX_PROPERTY:
+ /*
+ * Receive a pointer to a message (in user space) and set that
+ * to be the device's message. Get the parameter given to
+ * ioctl by the process.
+ */
+ mbox_copy_from_user(&size, (void *)ioctl_param, sizeof size);
+ return bcm_mailbox_property((void *)ioctl_param, size);
+ break;
+ default:
+ printk(KERN_ERR DRIVER_NAME "unknown ioctl: %d\n", ioctl_num);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Module Declarations */
+
+/*
+ * This structure will hold the functions to be called
+ * when a process does something to the device we
+ * created. Since a pointer to this structure is kept in
+ * the devices table, it can't be local to
+ * init_module. NULL is for unimplemented functios.
+ */
+struct file_operations fops = {
+ .unlocked_ioctl = device_ioctl,
+ .open = device_open,
+ .release = device_release, /* a.k.a. close */
+};
+
+static int bcm_vcio_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct vc_mailbox *mailbox;
+
+ mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL);
+ if (NULL == mailbox) {
+ printk(KERN_ERR DRIVER_NAME ": failed to allocate "
+ "mailbox memory\n");
+ ret = -ENOMEM;
+ } else {
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory "
+ "resource\n");
+ ret = -ENODEV;
+ kfree(mailbox);
+ } else {
+ /* should be based on the registers from res really */
+ mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD);
+
+ platform_set_drvdata(pdev, mailbox);
+ dev_mbox_register(DRIVER_NAME, &pdev->dev);
+
+ mbox_irqaction.dev_id = mailbox;
+ setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction);
+ printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n",
+ __io_address(ARM_0_MAIL0_RD));
+ }
+ }
+
+ if (ret == 0) {
+ /*
+ * Register the character device
+ */
+ ret = register_chrdev(MAJOR_NUM, DEVICE_FILE_NAME, &fops);
+
+ /*
+ * Negative values signify an error
+ */
+ if (ret < 0) {
+ printk(KERN_ERR DRIVER_NAME
+ "Failed registering the character device %d\n", ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static int bcm_vcio_remove(struct platform_device *pdev)
+{
+ struct vc_mailbox *mailbox = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(mailbox);
+
+ return 0;
+}
+
+static struct platform_driver bcm_mbox_driver = {
+ .probe = bcm_vcio_probe,
+ .remove = bcm_vcio_remove,
+
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init bcm_mbox_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n");
+
+ ret = platform_driver_register(&bcm_mbox_driver);
+ if (ret != 0) {
+ printk(KERN_ERR DRIVER_NAME ": failed to register "
+ "on platform\n");
+ }
+
+ return ret;
+}
+
+static void __exit bcm_mbox_exit(void)
+{
+ platform_driver_unregister(&bcm_mbox_driver);
+}
+
+arch_initcall(bcm_mbox_init); /* Initialize early */
+module_exit(bcm_mbox_exit);
+
+MODULE_AUTHOR("Gray Girling");
+MODULE_DESCRIPTION("ARM I/O to VideoCore processor");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bcm-mbox");
diff -Nur linux/arch/arm/mach-bcm2708/vc_mem.c rpi/arch/arm/mach-bcm2708/vc_mem.c
--- linux/arch/arm/mach-bcm2708/vc_mem.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-bcm2708/vc_mem.c 2014-05-29 11:49:03.966967132 +0900
@@ -0,0 +1,432 @@
+/*****************************************************************************
+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <asm/uaccess.h>
+#include <linux/dma-mapping.h>
+
+#ifdef CONFIG_ARCH_KONA
+#include <chal/chal_ipc.h>
+#elif CONFIG_ARCH_BCM2708
+#else
+#include <csp/chal_ipc.h>
+#endif
+
+#include "mach/vc_mem.h"
+#include <mach/vcio.h>
+
+#define DRIVER_NAME "vc-mem"
+
+// Device (/dev) related variables
+static dev_t vc_mem_devnum = 0;
+static struct class *vc_mem_class = NULL;
+static struct cdev vc_mem_cdev;
+static int vc_mem_inited = 0;
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *vc_mem_debugfs_entry;
+#endif
+
+/*
+ * Videocore memory addresses and size
+ *
+ * Drivers that wish to know the videocore memory addresses and sizes should
+ * use these variables instead of the MM_IO_BASE and MM_ADDR_IO defines in
+ * headers. This allows the other drivers to not be tied down to a a certain
+ * address/size at compile time.
+ *
+ * In the future, the goal is to have the videocore memory virtual address and
+ * size be calculated at boot time rather than at compile time. The decision of
+ * where the videocore memory resides and its size would be in the hands of the
+ * bootloader (and/or kernel). When that happens, the values of these variables
+ * would be calculated and assigned in the init function.
+ */
+// in the 2835 VC in mapped above ARM, but ARM has full access to VC space
+unsigned long mm_vc_mem_phys_addr = 0x00000000;
+unsigned int mm_vc_mem_size = 0;
+unsigned int mm_vc_mem_base = 0;
+
+EXPORT_SYMBOL(mm_vc_mem_phys_addr);
+EXPORT_SYMBOL(mm_vc_mem_size);
+EXPORT_SYMBOL(mm_vc_mem_base);
+
+static uint phys_addr = 0;
+static uint mem_size = 0;
+static uint mem_base = 0;
+
+
+/****************************************************************************
+*
+* vc_mem_open
+*
+***************************************************************************/
+
+static int
+vc_mem_open(struct inode *inode, struct file *file)
+{
+ (void) inode;
+ (void) file;
+
+ pr_debug("%s: called file = 0x%p\n", __func__, file);
+
+ return 0;
+}
+
+/****************************************************************************
+*
+* vc_mem_release
+*
+***************************************************************************/
+
+static int
+vc_mem_release(struct inode *inode, struct file *file)
+{
+ (void) inode;
+ (void) file;
+
+ pr_debug("%s: called file = 0x%p\n", __func__, file);
+
+ return 0;
+}
+
+/****************************************************************************
+*
+* vc_mem_get_size
+*
+***************************************************************************/
+
+static void
+vc_mem_get_size(void)
+{
+}
+
+/****************************************************************************
+*
+* vc_mem_get_base
+*
+***************************************************************************/
+
+static void
+vc_mem_get_base(void)
+{
+}
+
+/****************************************************************************
+*
+* vc_mem_get_current_size
+*
+***************************************************************************/
+
+int
+vc_mem_get_current_size(void)
+{
+ return mm_vc_mem_size;
+}
+
+EXPORT_SYMBOL_GPL(vc_mem_get_current_size);
+
+/****************************************************************************
+*
+* vc_mem_ioctl
+*
+***************************************************************************/
+
+static long
+vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int rc = 0;
+
+ (void) cmd;
+ (void) arg;
+
+ pr_debug("%s: called file = 0x%p\n", __func__, file);
+
+ switch (cmd) {
+ case VC_MEM_IOC_MEM_PHYS_ADDR:
+ {
+ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n",
+ __func__, (void *) mm_vc_mem_phys_addr);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,
+ sizeof (mm_vc_mem_phys_addr)) != 0) {
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case VC_MEM_IOC_MEM_SIZE:
+ {
+ // Get the videocore memory size first
+ vc_mem_get_size();
+
+ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__,
+ mm_vc_mem_size);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_size,
+ sizeof (mm_vc_mem_size)) != 0) {
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case VC_MEM_IOC_MEM_BASE:
+ {
+ // Get the videocore memory base
+ vc_mem_get_base();
+
+ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__,
+ mm_vc_mem_base);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_base,
+ sizeof (mm_vc_mem_base)) != 0) {
+ rc = -EFAULT;
+ }
+ break;
+ }
+ case VC_MEM_IOC_MEM_LOAD:
+ {
+ // Get the videocore memory base
+ vc_mem_get_base();
+
+ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__,
+ mm_vc_mem_base);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_base,
+ sizeof (mm_vc_mem_base)) != 0) {
+ rc = -EFAULT;
+ }
+ break;
+ }
+ default:
+ {
+ return -ENOTTY;
+ }
+ }
+ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc);
+
+ return rc;
+}
+
+/****************************************************************************
+*
+* vc_mem_mmap
+*
+***************************************************************************/
+
+static int
+vc_mem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ int rc = 0;
+ unsigned long length = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n",
+ __func__, (long) vma->vm_start, (long) vma->vm_end,
+ (long) vma->vm_pgoff);
+
+ if (offset + length > mm_vc_mem_size) {
+ pr_err("%s: length %ld is too big\n", __func__, length);
+ return -EINVAL;
+ }
+ // Do not cache the memory map
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ rc = remap_pfn_range(vma, vma->vm_start,
+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) +
+ vma->vm_pgoff, length, vma->vm_page_prot);
+ if (rc != 0) {
+ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc);
+ }
+
+ return rc;
+}
+
+/****************************************************************************
+*
+* File Operations for the driver.
+*
+***************************************************************************/
+
+static const struct file_operations vc_mem_fops = {
+ .owner = THIS_MODULE,
+ .open = vc_mem_open,
+ .release = vc_mem_release,
+ .unlocked_ioctl = vc_mem_ioctl,
+ .mmap = vc_mem_mmap,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static void vc_mem_debugfs_deinit(void)
+{
+ debugfs_remove_recursive(vc_mem_debugfs_entry);
+ vc_mem_debugfs_entry = NULL;
+}
+
+
+static int vc_mem_debugfs_init(
+ struct device *dev)
+{
+ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL);
+ if (!vc_mem_debugfs_entry) {
+ dev_warn(dev, "could not create debugfs entry\n");
+ return -EFAULT;
+ }
+
+ if (!debugfs_create_x32("vc_mem_phys_addr",
+ 0444,
+ vc_mem_debugfs_entry,
+ (u32 *)&mm_vc_mem_phys_addr)) {
+ dev_warn(dev, "%s:could not create vc_mem_phys entry\n",
+ __func__);
+ goto fail;
+ }
+
+ if (!debugfs_create_x32("vc_mem_size",
+ 0444,
+ vc_mem_debugfs_entry,
+ (u32 *)&mm_vc_mem_size)) {
+ dev_warn(dev, "%s:could not create vc_mem_size entry\n",
+ __func__);
+ goto fail;
+ }
+
+ if (!debugfs_create_x32("vc_mem_base",
+ 0444,
+ vc_mem_debugfs_entry,
+ (u32 *)&mm_vc_mem_base)) {
+ dev_warn(dev, "%s:could not create vc_mem_base entry\n",
+ __func__);
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ vc_mem_debugfs_deinit();
+ return -EFAULT;
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
+
+/****************************************************************************
+*
+* vc_mem_init
+*
+***************************************************************************/
+
+static int __init
+vc_mem_init(void)
+{
+ int rc = -EFAULT;
+ struct device *dev;
+
+ pr_debug("%s: called\n", __func__);
+
+ mm_vc_mem_phys_addr = phys_addr;
+ mm_vc_mem_size = mem_size;
+ mm_vc_mem_base = mem_base;
+
+ vc_mem_get_size();
+
+ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));
+
+ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {
+ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n",
+ __func__, rc);
+ goto out_err;
+ }
+
+ cdev_init(&vc_mem_cdev, &vc_mem_fops);
+ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {
+ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc);
+ goto out_unregister;
+ }
+
+ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME);
+ if (IS_ERR(vc_mem_class)) {
+ rc = PTR_ERR(vc_mem_class);
+ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc);
+ goto out_cdev_del;
+ }
+
+ dev = device_create(vc_mem_class, NULL, vc_mem_devnum, NULL,
+ DRIVER_NAME);
+ if (IS_ERR(dev)) {
+ rc = PTR_ERR(dev);
+ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc);
+ goto out_class_destroy;
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ /* don't fail if the debug entries cannot be created */
+ vc_mem_debugfs_init(dev);
+#endif
+
+ vc_mem_inited = 1;
+ return 0;
+
+ device_destroy(vc_mem_class, vc_mem_devnum);
+
+ out_class_destroy:
+ class_destroy(vc_mem_class);
+ vc_mem_class = NULL;
+
+ out_cdev_del:
+ cdev_del(&vc_mem_cdev);
+
+ out_unregister:
+ unregister_chrdev_region(vc_mem_devnum, 1);
+
+ out_err:
+ return -1;
+}
+
+/****************************************************************************
+*
+* vc_mem_exit
+*
+***************************************************************************/
+
+static void __exit
+vc_mem_exit(void)
+{
+ pr_debug("%s: called\n", __func__);
+
+ if (vc_mem_inited) {
+#if CONFIG_DEBUG_FS
+ vc_mem_debugfs_deinit();
+#endif
+ device_destroy(vc_mem_class, vc_mem_devnum);
+ class_destroy(vc_mem_class);
+ cdev_del(&vc_mem_cdev);
+ unregister_chrdev_region(vc_mem_devnum, 1);
+ }
+}
+
+module_init(vc_mem_init);
+module_exit(vc_mem_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Broadcom Corporation");
+
+module_param(phys_addr, uint, 0644);
+module_param(mem_size, uint, 0644);
+module_param(mem_base, uint, 0644);
+
diff -Nur linux/arch/arm/mach-footbridge/common.c rpi/arch/arm/mach-footbridge/common.c
--- linux/arch/arm/mach-footbridge/common.c 2014-05-29 12:18:16.840563725 +0900
+++ rpi/arch/arm/mach-footbridge/common.c 2014-05-29 11:49:04.011966754 +0900
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
+#include <video/vga.h>
#include <asm/pgtable.h>
#include <asm/page.h>
@@ -196,6 +197,8 @@
iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
}
+
+ vga_base = PCIMEM_BASE;
}
void footbridge_restart(enum reboot_mode mode, const char *cmd)
diff -Nur linux/arch/arm/mach-footbridge/dc21285.c rpi/arch/arm/mach-footbridge/dc21285.c
--- linux/arch/arm/mach-footbridge/dc21285.c 2014-05-29 12:18:16.841563719 +0900
+++ rpi/arch/arm/mach-footbridge/dc21285.c 2014-05-29 11:49:04.012966746 +0900
@@ -18,7 +18,6 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/spinlock.h>
-#include <video/vga.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
@@ -291,7 +290,6 @@
int cfn_mode;
pcibios_min_mem = 0x81000000;
- vga_base = PCIMEM_BASE;
mem_size = (unsigned int)high_memory - PAGE_OFFSET;
for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
diff -Nur linux/arch/arm/mach-footbridge/dc21285-timer.c rpi/arch/arm/mach-footbridge/dc21285-timer.c
--- linux/arch/arm/mach-footbridge/dc21285-timer.c 2014-05-29 12:18:16.840563725 +0900
+++ rpi/arch/arm/mach-footbridge/dc21285-timer.c 2014-05-29 11:49:04.011966754 +0900
@@ -96,11 +96,12 @@
void __init footbridge_timer_init(void)
{
struct clock_event_device *ce = &ckevt_dc21285;
+ unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
- clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16);
+ clocksource_register_hz(&cksrc_dc21285, rate);
setup_irq(ce->irq, &footbridge_timer_irq);
ce->cpumask = cpumask_of(smp_processor_id());
- clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff);
+ clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
}
diff -Nur linux/arch/arm/mach-footbridge/ebsa285.c rpi/arch/arm/mach-footbridge/ebsa285.c
--- linux/arch/arm/mach-footbridge/ebsa285.c 2014-05-29 12:18:16.841563719 +0900
+++ rpi/arch/arm/mach-footbridge/ebsa285.c 2014-05-29 11:49:04.012966746 +0900
@@ -30,21 +30,24 @@
const char *name;
const char *trigger;
} ebsa285_leds[] = {
- { "ebsa285:amber", "heartbeat", },
- { "ebsa285:green", "cpu0", },
+ { "ebsa285:amber", "cpu0", },
+ { "ebsa285:green", "heartbeat", },
{ "ebsa285:red",},
};
+static unsigned char hw_led_state;
+
static void ebsa285_led_set(struct led_classdev *cdev,
enum led_brightness b)
{
struct ebsa285_led *led = container_of(cdev,
struct ebsa285_led, cdev);
- if (b != LED_OFF)
- *XBUS_LEDS |= led->mask;
+ if (b == LED_OFF)
+ hw_led_state |= led->mask;
else
- *XBUS_LEDS &= ~led->mask;
+ hw_led_state &= ~led->mask;
+ *XBUS_LEDS = hw_led_state;
}
static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
@@ -52,18 +55,19 @@
struct ebsa285_led *led = container_of(cdev,
struct ebsa285_led, cdev);
- return (*XBUS_LEDS & led->mask) ? LED_FULL : LED_OFF;
+ return hw_led_state & led->mask ? LED_OFF : LED_FULL;
}
static int __init ebsa285_leds_init(void)
{
int i;
- if (machine_is_ebsa285())
+ if (!machine_is_ebsa285())
return -ENODEV;
- /* 3 LEDS All ON */
- *XBUS_LEDS |= XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+ /* 3 LEDS all off */
+ hw_led_state = XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+ *XBUS_LEDS = hw_led_state;
for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
struct ebsa285_led *led;
diff -Nur linux/arch/arm/mach-highbank/highbank.c rpi/arch/arm/mach-highbank/highbank.c
--- linux/arch/arm/mach-highbank/highbank.c 2014-05-29 12:18:16.844563700 +0900
+++ rpi/arch/arm/mach-highbank/highbank.c 2014-05-29 11:49:04.020966678 +0900
@@ -17,12 +17,15 @@
#include <linux/clkdev.h>
#include <linux/clocksource.h>
#include <linux/dma-mapping.h>
+#include <linux/input.h>
#include <linux/io.h>
#include <linux/irqchip.h>
+#include <linux/mailbox.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
+#include <linux/reboot.h>
#include <linux/amba/bus.h>
#include <linux/clk-provider.h>
@@ -63,6 +66,7 @@
static void highbank_l2x0_disable(void)
{
+ outer_flush_all();
/* Disable PL310 L2 Cache controller */
highbank_smc1(0x102, 0x0);
}
@@ -153,6 +157,24 @@
.notifier_call = highbank_platform_notifier,
};
+static int hb_keys_notifier(struct notifier_block *nb, unsigned long event, void *data)
+{
+ u32 key = *(u32 *)data;
+
+ if (event != 0x1000)
+ return 0;
+
+ if (key == KEY_POWER)
+ orderly_poweroff(false);
+ else if (key == 0xffff)
+ ctrl_alt_del();
+
+ return 0;
+}
+static struct notifier_block hb_keys_nb = {
+ .notifier_call = hb_keys_notifier,
+};
+
static void __init highbank_init(void)
{
pm_power_off = highbank_power_off;
@@ -161,6 +183,8 @@
bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
bus_register_notifier(&amba_bustype, &highbank_amba_nb);
+ pl320_ipc_register_notifier(&hb_keys_nb);
+
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
diff -Nur linux/arch/arm/mach-imx/clk-imx6q.c rpi/arch/arm/mach-imx/clk-imx6q.c
--- linux/arch/arm/mach-imx/clk-imx6q.c 2014-05-29 12:18:16.851563657 +0900
+++ rpi/arch/arm/mach-imx/clk-imx6q.c 2014-05-29 11:49:04.027966619 +0900
@@ -428,7 +428,7 @@
clk[asrc_podf] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3);
clk[spdif_pred] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
clk[spdif_podf] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
- clk[can_root] = imx_clk_divider("can_root", "pll3_usb_otg", base + 0x20, 2, 6);
+ clk[can_root] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6);
clk[ecspi_root] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6);
clk[gpu2d_core_podf] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3);
clk[gpu3d_core_podf] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3);
diff -Nur linux/arch/arm/mach-integrator/integrator_cp.c rpi/arch/arm/mach-integrator/integrator_cp.c
--- linux/arch/arm/mach-integrator/integrator_cp.c 2014-05-29 12:18:16.869563544 +0900
+++ rpi/arch/arm/mach-integrator/integrator_cp.c 2014-05-29 11:49:04.069966267 +0900
@@ -199,7 +199,8 @@
static void cp_clcd_enable(struct clcd_fb *fb)
{
struct fb_var_screeninfo *var = &fb->fb.var;
- u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
+ u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2
+ | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1;
if (var->bits_per_pixel <= 8 ||
(var->bits_per_pixel == 16 && var->green.length == 5))
diff -Nur linux/arch/arm/mach-mvebu/armada-370-xp.c rpi/arch/arm/mach-mvebu/armada-370-xp.c
--- linux/arch/arm/mach-mvebu/armada-370-xp.c 2014-05-29 12:18:16.896563375 +0900
+++ rpi/arch/arm/mach-mvebu/armada-370-xp.c 2014-05-29 11:49:04.139965679 +0900
@@ -21,6 +21,7 @@
#include <linux/clocksource.h>
#include <linux/dma-mapping.h>
#include <linux/mbus.h>
+#include <linux/slab.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -28,6 +29,7 @@
#include "armada-370-xp.h"
#include "common.h"
#include "coherency.h"
+#include "mvebu-soc-id.h"
static void __init armada_370_xp_map_io(void)
{
@@ -45,8 +47,38 @@
#endif
}
+static void __init i2c_quirk(void)
+{
+ struct device_node *np;
+ u32 dev, rev;
+
+ /*
+ * Only revisons more recent than A0 support the offload
+ * mechanism. We can exit only if we are sure that we can
+ * get the SoC revision and it is more recent than A0.
+ */
+ if (mvebu_get_soc_id(&rev, &dev) == 0 && dev > MV78XX0_A0_REV)
+ return;
+
+ for_each_compatible_node(np, NULL, "marvell,mv78230-i2c") {
+ struct property *new_compat;
+
+ new_compat = kzalloc(sizeof(*new_compat), GFP_KERNEL);
+
+ new_compat->name = kstrdup("compatible", GFP_KERNEL);
+ new_compat->length = sizeof("marvell,mv78230-a0-i2c");
+ new_compat->value = kstrdup("marvell,mv78230-a0-i2c",
+ GFP_KERNEL);
+
+ of_update_property(np, new_compat);
+ }
+ return;
+}
+
static void __init armada_370_xp_dt_init(void)
{
+ if (of_machine_is_compatible("plathome,openblocks-ax3-4"))
+ i2c_quirk();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
diff -Nur linux/arch/arm/mach-mvebu/Makefile rpi/arch/arm/mach-mvebu/Makefile
--- linux/arch/arm/mach-mvebu/Makefile 2014-05-29 12:18:16.896563375 +0900
+++ rpi/arch/arm/mach-mvebu/Makefile 2014-05-29 11:49:04.139965679 +0900
@@ -3,7 +3,7 @@
AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
-obj-y += system-controller.o
+obj-y += system-controller.o mvebu-soc-id.o
obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o
obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
diff -Nur linux/arch/arm/mach-mvebu/mvebu-soc-id.c rpi/arch/arm/mach-mvebu/mvebu-soc-id.c
--- linux/arch/arm/mach-mvebu/mvebu-soc-id.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-mvebu/mvebu-soc-id.c 2014-05-29 11:49:04.141965662 +0900
@@ -0,0 +1,119 @@
+/*
+ * ID and revision information for mvebu SoCs
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * All the mvebu SoCs have information related to their variant and
+ * revision that can be read from the PCI control register. This is
+ * done before the PCI initialization to avoid any conflict. Once the
+ * ID and revision are retrieved, the mapping is freed.
+ */
+
+#define pr_fmt(fmt) "mvebu-soc-id: " fmt
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include "mvebu-soc-id.h"
+
+#define PCIE_DEV_ID_OFF 0x0
+#define PCIE_DEV_REV_OFF 0x8
+
+#define SOC_ID_MASK 0xFFFF0000
+#define SOC_REV_MASK 0xFF
+
+static u32 soc_dev_id;
+static u32 soc_rev;
+static bool is_id_valid;
+
+static const struct of_device_id mvebu_pcie_of_match_table[] = {
+ { .compatible = "marvell,armada-xp-pcie", },
+ { .compatible = "marvell,armada-370-pcie", },
+ {},
+};
+
+int mvebu_get_soc_id(u32 *dev, u32 *rev)
+{
+ if (is_id_valid) {
+ *dev = soc_dev_id;
+ *rev = soc_rev;
+ return 0;
+ } else
+ return -1;
+}
+
+static int __init mvebu_soc_id_init(void)
+{
+ struct device_node *np;
+ int ret = 0;
+ void __iomem *pci_base;
+ struct clk *clk;
+ struct device_node *child;
+
+ np = of_find_matching_node(NULL, mvebu_pcie_of_match_table);
+ if (!np)
+ return ret;
+
+ /*
+ * ID and revision are available from any port, so we
+ * just pick the first one
+ */
+ child = of_get_next_child(np, NULL);
+ if (child == NULL) {
+ pr_err("cannot get pci node\n");
+ ret = -ENOMEM;
+ goto clk_err;
+ }
+
+ clk = of_clk_get_by_name(child, NULL);
+ if (IS_ERR(clk)) {
+ pr_err("cannot get clock\n");
+ ret = -ENOMEM;
+ goto clk_err;
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ pr_err("cannot enable clock\n");
+ goto clk_err;
+ }
+
+ pci_base = of_iomap(child, 0);
+ if (pci_base == NULL) {
+ pr_err("cannot map registers\n");
+ ret = -ENOMEM;
+ goto res_ioremap;
+ }
+
+ /* SoC ID */
+ soc_dev_id = readl(pci_base + PCIE_DEV_ID_OFF) >> 16;
+
+ /* SoC revision */
+ soc_rev = readl(pci_base + PCIE_DEV_REV_OFF) & SOC_REV_MASK;
+
+ is_id_valid = true;
+
+ pr_info("MVEBU SoC ID=0x%X, Rev=0x%X\n", soc_dev_id, soc_rev);
+
+ iounmap(pci_base);
+
+res_ioremap:
+ clk_disable_unprepare(clk);
+
+clk_err:
+ of_node_put(child);
+ of_node_put(np);
+
+ return ret;
+}
+core_initcall(mvebu_soc_id_init);
+
diff -Nur linux/arch/arm/mach-mvebu/mvebu-soc-id.h rpi/arch/arm/mach-mvebu/mvebu-soc-id.h
--- linux/arch/arm/mach-mvebu/mvebu-soc-id.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/arm/mach-mvebu/mvebu-soc-id.h 2014-05-29 11:49:04.141965662 +0900
@@ -0,0 +1,32 @@
+/*
+ * Marvell EBU SoC ID and revision definitions.
+ *
+ * Copyright (C) 2014 Marvell Semiconductor
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __LINUX_MVEBU_SOC_ID_H
+#define __LINUX_MVEBU_SOC_ID_H
+
+/* Armada XP ID */
+#define MV78230_DEV_ID 0x7823
+#define MV78260_DEV_ID 0x7826
+#define MV78460_DEV_ID 0x7846
+
+/* Armada XP Revision */
+#define MV78XX0_A0_REV 0x1
+#define MV78XX0_B0_REV 0x2
+
+#ifdef CONFIG_ARCH_MVEBU
+int mvebu_get_soc_id(u32 *dev, u32 *rev);
+#else
+static inline int mvebu_get_soc_id(u32 *dev, u32 *rev)
+{
+ return -1;
+}
+#endif
+
+#endif /* __LINUX_MVEBU_SOC_ID_H */
diff -Nur linux/arch/arm/mach-omap2/board-ldp.c rpi/arch/arm/mach-omap2/board-ldp.c
--- linux/arch/arm/mach-omap2/board-ldp.c 2014-05-29 12:18:16.911563281 +0900
+++ rpi/arch/arm/mach-omap2/board-ldp.c 2014-05-29 11:49:04.177965359 +0900
@@ -243,12 +243,18 @@
static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
{
+ int res;
+
/* LCD enable GPIO */
ldp_lcd_pdata.enable_gpio = gpio + 7;
/* Backlight enable GPIO */
ldp_lcd_pdata.backlight_gpio = gpio + 15;
+ res = platform_device_register(&ldp_lcd_device);
+ if (res)
+ pr_err("Unable to register LCD: %d\n", res);
+
return 0;
}
@@ -347,7 +353,6 @@
static struct platform_device *ldp_devices[] __initdata = {
&ldp_gpio_keys_device,
- &ldp_lcd_device,
};
#ifdef CONFIG_OMAP_MUX
diff -Nur linux/arch/arm/mach-omap2/gpmc.c rpi/arch/arm/mach-omap2/gpmc.c
--- linux/arch/arm/mach-omap2/gpmc.c 2014-05-29 12:18:16.946563062 +0900
+++ rpi/arch/arm/mach-omap2/gpmc.c 2014-05-29 11:49:04.214965048 +0900
@@ -1339,7 +1339,7 @@
of_property_read_bool(np, "gpmc,time-para-granularity");
}
-#ifdef CONFIG_MTD_NAND
+#if IS_ENABLED(CONFIG_MTD_NAND)
static const char * const nand_ecc_opts[] = {
[OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw",
@@ -1409,7 +1409,7 @@
}
#endif
-#ifdef CONFIG_MTD_ONENAND
+#if IS_ENABLED(CONFIG_MTD_ONENAND)
static int gpmc_probe_onenand_child(struct platform_device *pdev,
struct device_node *child)
{
diff -Nur linux/arch/arm/mach-omap2/irq.c rpi/arch/arm/mach-omap2/irq.c
--- linux/arch/arm/mach-omap2/irq.c 2014-05-29 12:18:16.952563024 +0900
+++ rpi/arch/arm/mach-omap2/irq.c 2014-05-29 11:49:04.218965015 +0900
@@ -222,6 +222,7 @@
static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs)
{
u32 irqnr;
+ int handled_irq = 0;
do {
irqnr = readl_relaxed(base_addr + 0x98);
@@ -233,7 +234,7 @@
goto out;
irqnr = readl_relaxed(base_addr + 0xd8);
-#ifdef CONFIG_SOC_TI81XX
+#if IS_ENABLED(CONFIG_SOC_TI81XX) || IS_ENABLED(CONFIG_SOC_AM33XX)
if (irqnr)
goto out;
irqnr = readl_relaxed(base_addr + 0xf8);
@@ -249,8 +250,15 @@
if (irqnr) {
irqnr = irq_find_mapping(domain, irqnr);
handle_IRQ(irqnr, regs);
+ handled_irq = 1;
}
} while (irqnr);
+
+ /* If an irq is masked or deasserted while active, we will
+ * keep ending up here with no irq handled. So remove it from
+ * the INTC with an ack.*/
+ if (!handled_irq)
+ omap_ack_irq(NULL);
}
asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs)
diff -Nur linux/arch/arm/mach-omap2/omap4-common.c rpi/arch/arm/mach-omap2/omap4-common.c
--- linux/arch/arm/mach-omap2/omap4-common.c 2014-05-29 12:18:16.971562905 +0900
+++ rpi/arch/arm/mach-omap2/omap4-common.c 2014-05-29 11:49:04.226964948 +0900
@@ -163,6 +163,7 @@
static void omap4_l2x0_disable(void)
{
+ outer_flush_all();
/* Disable PL310 L2 Cache controller */
omap_smc1(0x102, 0x0);
}
diff -Nur linux/arch/arm/mach-omap2/omap_device.c rpi/arch/arm/mach-omap2/omap_device.c
--- linux/arch/arm/mach-omap2/omap_device.c 2014-05-29 12:18:16.972562899 +0900
+++ rpi/arch/arm/mach-omap2/omap_device.c 2014-05-29 11:49:04.228964931 +0900
@@ -621,6 +621,7 @@
if (!ret && !pm_runtime_status_suspended(dev)) {
if (pm_generic_runtime_suspend(dev) == 0) {
+ pm_runtime_set_suspended(dev);
omap_device_idle(pdev);
od->flags |= OMAP_DEVICE_SUSPENDED;
}
@@ -634,10 +635,18 @@
struct platform_device *pdev = to_platform_device(dev);
struct omap_device *od = to_omap_device(pdev);
- if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
- !pm_runtime_status_suspended(dev)) {
+ if (od->flags & OMAP_DEVICE_SUSPENDED) {
od->flags &= ~OMAP_DEVICE_SUSPENDED;
omap_device_enable(pdev);
+ /*
+ * XXX: we run before core runtime pm has resumed itself. At
+ * this point in time, we just restore the runtime pm state and
+ * considering symmetric operations in resume, we donot expect
+ * to fail. If we failed, something changed in core runtime_pm
+ * framework OR some device driver messed things up, hence, WARN
+ */
+ WARN(pm_runtime_set_active(dev),
+ "Could not set %s runtime state active\n", dev_name(dev));
pm_generic_runtime_resume(dev);
}
diff -Nur linux/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c rpi/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
--- linux/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c 2014-05-29 12:18:16.977562868 +0900
+++ rpi/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c 2014-05-29 11:49:04.233964889 +0900
@@ -796,7 +796,7 @@
/* gpmc */
static struct omap_hwmod_irq_info omap2xxx_gpmc_irqs[] = {
- { .irq = 20 },
+ { .irq = 20 + OMAP_INTC_START, },
{ .irq = -1 }
};
@@ -841,7 +841,7 @@
};
static struct omap_hwmod_irq_info omap2_rng_mpu_irqs[] = {
- { .irq = 52 },
+ { .irq = 52 + OMAP_INTC_START, },
{ .irq = -1 }
};
diff -Nur linux/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c rpi/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
--- linux/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c 2014-05-29 12:18:16.981562843 +0900
+++ rpi/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c 2014-05-29 11:49:04.237964855 +0900
@@ -1943,7 +1943,8 @@
.syss_offs = 0x0014,
.sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+ SYSS_HAS_RESET_STATUS),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
.sysc_fields = &omap_hwmod_sysc_type1,
@@ -1967,7 +1968,7 @@
static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
.name = "usb_host_hs",
.class = &omap3xxx_usb_host_hs_hwmod_class,
- .clkdm_name = "l3_init_clkdm",
+ .clkdm_name = "usbhost_clkdm",
.mpu_irqs = omap3xxx_usb_host_hs_irqs,
.main_clk = "usbhost_48m_fck",
.prcm = {
@@ -2021,15 +2022,7 @@
* hence HWMOD_SWSUP_MSTANDBY
*/
- /*
- * During system boot; If the hwmod framework resets the module
- * the module will have smart idle settings; which can lead to deadlock
- * (above Errata Id:i660); so, dont reset the module during boot;
- * Use HWMOD_INIT_NO_RESET.
- */
-
- .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
- HWMOD_INIT_NO_RESET,
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
};
/*
@@ -2060,7 +2053,7 @@
static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
.name = "usb_tll_hs",
.class = &omap3xxx_usb_tll_hs_hwmod_class,
- .clkdm_name = "l3_init_clkdm",
+ .clkdm_name = "core_l4_clkdm",
.mpu_irqs = omap3xxx_usb_tll_hs_irqs,
.main_clk = "usbtll_fck",
.prcm = {
@@ -2172,7 +2165,7 @@
};
static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
- { .irq = 20 },
+ { .irq = 20 + OMAP_INTC_START, },
{ .irq = -1 }
};
@@ -3006,7 +2999,7 @@
static struct omap_hwmod omap3xxx_mmu_isp_hwmod;
static struct omap_hwmod_irq_info omap3xxx_mmu_isp_irqs[] = {
- { .irq = 24 },
+ { .irq = 24 + OMAP_INTC_START, },
{ .irq = -1 }
};
@@ -3048,7 +3041,7 @@
static struct omap_hwmod omap3xxx_mmu_iva_hwmod;
static struct omap_hwmod_irq_info omap3xxx_mmu_iva_irqs[] = {
- { .irq = 28 },
+ { .irq = 28 + OMAP_INTC_START, },
{ .irq = -1 }
};
diff -Nur linux/arch/arm/mach-omap2/omap_hwmod_7xx_data.c rpi/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
--- linux/arch/arm/mach-omap2/omap_hwmod_7xx_data.c 2014-05-29 12:18:16.987562805 +0900
+++ rpi/arch/arm/mach-omap2/omap_hwmod_7xx_data.c 2014-05-29 11:49:04.240964830 +0900
@@ -1637,7 +1637,7 @@
.class = &dra7xx_uart_hwmod_class,
.clkdm_name = "l4per_clkdm",
.main_clk = "uart1_gfclk_mux",
- .flags = HWMOD_SWSUP_SIDLE_ACT,
+ .flags = HWMOD_SWSUP_SIDLE_ACT | DEBUG_OMAP2UART1_FLAGS,
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L4PER_UART1_CLKCTRL_OFFSET,
diff -Nur linux/arch/arm/mach-omap2/omap_hwmod.c rpi/arch/arm/mach-omap2/omap_hwmod.c
--- linux/arch/arm/mach-omap2/omap_hwmod.c 2014-05-29 12:18:16.974562887 +0900
+++ rpi/arch/arm/mach-omap2/omap_hwmod.c 2014-05-29 11:49:04.230964914 +0900
@@ -399,7 +399,7 @@
}
/**
- * _set_softreset: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v
+ * _set_softreset: set OCP_SYSCONFIG.SOFTRESET bit in @v
* @oh: struct omap_hwmod *
* @v: pointer to register contents to modify
*
@@ -427,6 +427,36 @@
}
/**
+ * _clear_softreset: clear OCP_SYSCONFIG.SOFTRESET bit in @v
+ * @oh: struct omap_hwmod *
+ * @v: pointer to register contents to modify
+ *
+ * Clear the SOFTRESET bit in @v for hwmod @oh. Returns -EINVAL upon
+ * error or 0 upon success.
+ */
+static int _clear_softreset(struct omap_hwmod *oh, u32 *v)
+{
+ u32 softrst_mask;
+
+ if (!oh->class->sysc ||
+ !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
+ return -EINVAL;
+
+ if (!oh->class->sysc->sysc_fields) {
+ WARN(1,
+ "omap_hwmod: %s: sysc_fields absent for sysconfig class\n",
+ oh->name);
+ return -EINVAL;
+ }
+
+ softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
+
+ *v &= ~softrst_mask;
+
+ return 0;
+}
+
+/**
* _wait_softreset_complete - wait for an OCP softreset to complete
* @oh: struct omap_hwmod * to wait on
*
@@ -1911,6 +1941,12 @@
ret = _set_softreset(oh, &v);
if (ret)
goto dis_opt_clks;
+
+ _write_sysconfig(v, oh);
+ ret = _clear_softreset(oh, &v);
+ if (ret)
+ goto dis_opt_clks;
+
_write_sysconfig(v, oh);
if (oh->class->sysc->srst_udelay)
@@ -2361,21 +2397,23 @@
* Cache the virtual address used by the MPU to access this IP block's
* registers. This address is needed early so the OCP registers that
* are part of the device's address space can be ioremapped properly.
- * No return value.
+ *
+ * Returns 0 on success, -EINVAL if an invalid hwmod is passed, and
+ * -ENXIO on absent or invalid register target address space.
*/
-static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data)
+static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data)
{
struct omap_hwmod_addr_space *mem;
void __iomem *va_start = NULL;
struct device_node *np;
if (!oh)
- return;
+ return -EINVAL;
_save_mpu_port_index(oh);
if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
- return;
+ return -ENXIO;
mem = _find_mpu_rt_addr_space(oh);
if (!mem) {
@@ -2384,7 +2422,7 @@
/* Extract the IO space from device tree blob */
if (!of_have_populated_dt())
- return;
+ return -ENXIO;
np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh);
if (np)
@@ -2395,13 +2433,14 @@
if (!va_start) {
pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
- return;
+ return -ENXIO;
}
pr_debug("omap_hwmod: %s: MPU register target at va %p\n",
oh->name, va_start);
oh->_mpu_rt_va = va_start;
+ return 0;
}
/**
@@ -2414,8 +2453,8 @@
* registered at this point. This is the first of two phases for
* hwmod initialization. Code called here does not touch any hardware
* registers, it simply prepares internal data structures. Returns 0
- * upon success or if the hwmod isn't registered, or -EINVAL upon
- * failure.
+ * upon success or if the hwmod isn't registered or if the hwmod's
+ * address space is not defined, or -EINVAL upon failure.
*/
static int __init _init(struct omap_hwmod *oh, void *data)
{
@@ -2424,8 +2463,14 @@
if (oh->_state != _HWMOD_STATE_REGISTERED)
return 0;
- if (oh->class->sysc)
- _init_mpu_rt_base(oh, NULL);
+ if (oh->class->sysc) {
+ r = _init_mpu_rt_base(oh, NULL);
+ if (r < 0) {
+ WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
+ oh->name);
+ return 0;
+ }
+ }
r = _init_clocks(oh, NULL);
if (r < 0) {
@@ -3149,6 +3194,11 @@
if (ret)
goto error;
_write_sysconfig(v, oh);
+
+ ret = _clear_softreset(oh, &v);
+ if (ret)
+ goto error;
+ _write_sysconfig(v, oh);
error:
return ret;
diff -Nur linux/arch/arm/mach-omap2/pm.h rpi/arch/arm/mach-omap2/pm.h
--- linux/arch/arm/mach-omap2/pm.h 2014-05-29 12:18:16.989562793 +0900
+++ rpi/arch/arm/mach-omap2/pm.h 2014-05-29 11:49:04.244964796 +0900
@@ -103,7 +103,7 @@
#define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD (1 << 0)
-#if defined(CONFIG_ARCH_OMAP4)
+#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
extern u16 pm44xx_errata;
#define IS_PM44XX_ERRATUM(id) (pm44xx_errata & (id))
#else
diff -Nur linux/arch/arm/mach-pxa/reset.c rpi/arch/arm/mach-pxa/reset.c
--- linux/arch/arm/mach-pxa/reset.c 2014-05-29 12:18:17.091562154 +0900
+++ rpi/arch/arm/mach-pxa/reset.c 2014-05-29 11:49:04.317964183 +0900
@@ -13,6 +13,7 @@
#include <mach/regs-ost.h>
#include <mach/reset.h>
+#include <mach/smemc.h>
unsigned int reset_status;
EXPORT_SYMBOL(reset_status);
@@ -81,6 +82,12 @@
writel_relaxed(OSSR_M3, OSSR);
/* ... in 100 ms */
writel_relaxed(readl_relaxed(OSCR) + 368640, OSMR3);
+ /*
+ * SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71)
+ * we put SDRAM into self-refresh to prevent that
+ */
+ while (1)
+ writel_relaxed(MDREFR_SLFRSH, MDREFR);
}
void pxa_restart(enum reboot_mode mode, const char *cmd)
@@ -104,4 +111,3 @@
break;
}
}
-
diff -Nur linux/arch/arm/mach-pxa/tosa.c rpi/arch/arm/mach-pxa/tosa.c
--- linux/arch/arm/mach-pxa/tosa.c 2014-05-29 12:18:17.094562135 +0900
+++ rpi/arch/arm/mach-pxa/tosa.c 2014-05-29 11:49:04.321964150 +0900
@@ -425,57 +425,57 @@
* Tosa Keyboard
*/
static const uint32_t tosakbd_keymap[] = {
- KEY(0, 2, KEY_W),
- KEY(0, 6, KEY_K),
- KEY(0, 7, KEY_BACKSPACE),
- KEY(0, 8, KEY_P),
- KEY(1, 1, KEY_Q),
- KEY(1, 2, KEY_E),
- KEY(1, 3, KEY_T),
- KEY(1, 4, KEY_Y),
- KEY(1, 6, KEY_O),
- KEY(1, 7, KEY_I),
- KEY(1, 8, KEY_COMMA),
- KEY(2, 1, KEY_A),
- KEY(2, 2, KEY_D),
- KEY(2, 3, KEY_G),
- KEY(2, 4, KEY_U),
- KEY(2, 6, KEY_L),
- KEY(2, 7, KEY_ENTER),
- KEY(2, 8, KEY_DOT),
- KEY(3, 1, KEY_Z),
- KEY(3, 2, KEY_C),
- KEY(3, 3, KEY_V),
- KEY(3, 4, KEY_J),
- KEY(3, 5, TOSA_KEY_ADDRESSBOOK),
- KEY(3, 6, TOSA_KEY_CANCEL),
- KEY(3, 7, TOSA_KEY_CENTER),
- KEY(3, 8, TOSA_KEY_OK),
- KEY(3, 9, KEY_LEFTSHIFT),
- KEY(4, 1, KEY_S),
- KEY(4, 2, KEY_R),
- KEY(4, 3, KEY_B),
- KEY(4, 4, KEY_N),
- KEY(4, 5, TOSA_KEY_CALENDAR),
- KEY(4, 6, TOSA_KEY_HOMEPAGE),
- KEY(4, 7, KEY_LEFTCTRL),
- KEY(4, 8, TOSA_KEY_LIGHT),
- KEY(4, 10, KEY_RIGHTSHIFT),
- KEY(5, 1, KEY_TAB),
- KEY(5, 2, KEY_SLASH),
- KEY(5, 3, KEY_H),
- KEY(5, 4, KEY_M),
- KEY(5, 5, TOSA_KEY_MENU),
- KEY(5, 7, KEY_UP),
- KEY(5, 11, TOSA_KEY_FN),
- KEY(6, 1, KEY_X),
- KEY(6, 2, KEY_F),
- KEY(6, 3, KEY_SPACE),
- KEY(6, 4, KEY_APOSTROPHE),
- KEY(6, 5, TOSA_KEY_MAIL),
- KEY(6, 6, KEY_LEFT),
- KEY(6, 7, KEY_DOWN),
- KEY(6, 8, KEY_RIGHT),
+ KEY(0, 1, KEY_W),
+ KEY(0, 5, KEY_K),
+ KEY(0, 6, KEY_BACKSPACE),
+ KEY(0, 7, KEY_P),
+ KEY(1, 0, KEY_Q),
+ KEY(1, 1, KEY_E),
+ KEY(1, 2, KEY_T),
+ KEY(1, 3, KEY_Y),
+ KEY(1, 5, KEY_O),
+ KEY(1, 6, KEY_I),
+ KEY(1, 7, KEY_COMMA),
+ KEY(2, 0, KEY_A),
+ KEY(2, 1, KEY_D),
+ KEY(2, 2, KEY_G),
+ KEY(2, 3, KEY_U),
+ KEY(2, 5, KEY_L),
+ KEY(2, 6, KEY_ENTER),
+ KEY(2, 7, KEY_DOT),
+ KEY(3, 0, KEY_Z),
+ KEY(3, 1, KEY_C),
+ KEY(3, 2, KEY_V),
+ KEY(3, 3, KEY_J),
+ KEY(3, 4, TOSA_KEY_ADDRESSBOOK),
+ KEY(3, 5, TOSA_KEY_CANCEL),
+ KEY(3, 6, TOSA_KEY_CENTER),
+ KEY(3, 7, TOSA_KEY_OK),
+ KEY(3, 8, KEY_LEFTSHIFT),
+ KEY(4, 0, KEY_S),
+ KEY(4, 1, KEY_R),
+ KEY(4, 2, KEY_B),
+ KEY(4, 3, KEY_N),
+ KEY(4, 4, TOSA_KEY_CALENDAR),
+ KEY(4, 5, TOSA_KEY_HOMEPAGE),
+ KEY(4, 6, KEY_LEFTCTRL),
+ KEY(4, 7, TOSA_KEY_LIGHT),
+ KEY(4, 9, KEY_RIGHTSHIFT),
+ KEY(5, 0, KEY_TAB),
+ KEY(5, 1, KEY_SLASH),
+ KEY(5, 2, KEY_H),
+ KEY(5, 3, KEY_M),
+ KEY(5, 4, TOSA_KEY_MENU),
+ KEY(5, 6, KEY_UP),
+ KEY(5, 10, TOSA_KEY_FN),
+ KEY(6, 0, KEY_X),
+ KEY(6, 1, KEY_F),
+ KEY(6, 2, KEY_SPACE),
+ KEY(6, 3, KEY_APOSTROPHE),
+ KEY(6, 4, TOSA_KEY_MAIL),
+ KEY(6, 5, KEY_LEFT),
+ KEY(6, 6, KEY_DOWN),
+ KEY(6, 7, KEY_RIGHT),
};
static struct matrix_keymap_data tosakbd_keymap_data = {
diff -Nur linux/arch/arm/mach-sa1100/assabet.c rpi/arch/arm/mach-sa1100/assabet.c
--- linux/arch/arm/mach-sa1100/assabet.c 2014-05-29 12:18:17.138561860 +0900
+++ rpi/arch/arm/mach-sa1100/assabet.c 2014-05-29 11:49:04.391963561 +0900
@@ -512,6 +512,9 @@
* Its called GPCLKR0 in my SA1110 manual.
*/
Ser1SDCR0 |= SDCR0_SUS;
+ MSC1 = (MSC1 & ~0xffff) |
+ MSC_NonBrst | MSC_32BitStMem |
+ MSC_RdAcc(2) | MSC_WrAcc(2) | MSC_Rec(0);
if (!machine_has_neponset())
sa1100_register_uart_fns(&assabet_port_fns);
diff -Nur linux/arch/arm/mach-sa1100/include/mach/collie.h rpi/arch/arm/mach-sa1100/include/mach/collie.h
--- linux/arch/arm/mach-sa1100/include/mach/collie.h 2014-05-29 12:18:17.141561841 +0900
+++ rpi/arch/arm/mach-sa1100/include/mach/collie.h 2014-05-29 11:49:04.397963511 +0900
@@ -13,6 +13,8 @@
#ifndef __ASM_ARCH_COLLIE_H
#define __ASM_ARCH_COLLIE_H
+#include "hardware.h" /* Gives GPIO_MAX */
+
extern void locomolcd_power(int on);
#define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1)
diff -Nur linux/arch/arm/mach-shmobile/board-armadillo800eva.c rpi/arch/arm/mach-shmobile/board-armadillo800eva.c
--- linux/arch/arm/mach-shmobile/board-armadillo800eva.c 2014-05-29 12:18:17.147561804 +0900
+++ rpi/arch/arm/mach-shmobile/board-armadillo800eva.c 2014-05-29 11:49:04.407963427 +0900
@@ -482,7 +482,7 @@
.id = 0,
.dev = {
.platform_data = &lcdc0_info,
- .coherent_dma_mask = ~0,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
},
};
@@ -579,7 +579,7 @@
.id = 1,
.dev = {
.platform_data = &hdmi_lcdc_info,
- .coherent_dma_mask = ~0,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
},
};
diff -Nur linux/arch/arm/mach-shmobile/board-kzm9g.c rpi/arch/arm/mach-shmobile/board-kzm9g.c
--- linux/arch/arm/mach-shmobile/board-kzm9g.c 2014-05-29 12:18:17.149561791 +0900
+++ rpi/arch/arm/mach-shmobile/board-kzm9g.c 2014-05-29 11:49:04.409963410 +0900
@@ -334,7 +334,7 @@
.resource = lcdc_resources,
.dev = {
.platform_data = &lcdc_info,
- .coherent_dma_mask = ~0,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
},
};
diff -Nur linux/arch/arm/mach-shmobile/board-mackerel.c rpi/arch/arm/mach-shmobile/board-mackerel.c
--- linux/arch/arm/mach-shmobile/board-mackerel.c 2014-05-29 12:18:17.151561779 +0900
+++ rpi/arch/arm/mach-shmobile/board-mackerel.c 2014-05-29 11:49:04.410963402 +0900
@@ -409,7 +409,7 @@
.resource = lcdc_resources,
.dev = {
.platform_data = &lcdc_info,
- .coherent_dma_mask = ~0,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
},
};
@@ -499,7 +499,7 @@
.id = 1,
.dev = {
.platform_data = &hdmi_lcdc_info,
- .coherent_dma_mask = ~0,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
},
};
diff -Nur linux/arch/arm/mach-tegra/common.c rpi/arch/arm/mach-tegra/common.c
--- linux/arch/arm/mach-tegra/common.c 2014-05-29 12:18:17.255561128 +0900
+++ rpi/arch/arm/mach-tegra/common.c 2014-05-29 11:49:04.436963183 +0900
@@ -22,6 +22,7 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/of.h>
#include <linux/reboot.h>
#include <linux/irqchip.h>
#include <linux/clk-provider.h>
@@ -82,10 +83,20 @@
static void __init tegra_init_cache(void)
{
#ifdef CONFIG_CACHE_L2X0
+ static const struct of_device_id pl310_ids[] __initconst = {
+ { .compatible = "arm,pl310-cache", },
+ {}
+ };
+
+ struct device_node *np;
int ret;
void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
u32 aux_ctrl, cache_type;
+ np = of_find_matching_node(NULL, pl310_ids);
+ if (!np)
+ return;
+
cache_type = readl(p + L2X0_CACHE_TYPE);
aux_ctrl = (cache_type & 0x700) << (17-8);
aux_ctrl |= 0x7C400001;
diff -Nur linux/arch/arm/Makefile rpi/arch/arm/Makefile
--- linux/arch/arm/Makefile 2014-05-29 12:18:16.498565867 +0900
+++ rpi/arch/arm/Makefile 2014-05-29 11:49:03.630969956 +0900
@@ -146,6 +146,7 @@
# by CONFIG_* macro name.
machine-$(CONFIG_ARCH_AT91) += at91
machine-$(CONFIG_ARCH_BCM) += bcm
+machine-$(CONFIG_ARCH_BCM2708) += bcm2708
machine-$(CONFIG_ARCH_BCM2835) += bcm2835
machine-$(CONFIG_ARCH_CLPS711X) += clps711x
machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx
diff -Nur linux/arch/arm/mm/dma-mapping.c rpi/arch/arm/mm/dma-mapping.c
--- linux/arch/arm/mm/dma-mapping.c 2014-05-29 12:18:17.292560896 +0900
+++ rpi/arch/arm/mm/dma-mapping.c 2014-05-29 11:49:04.480962814 +0900
@@ -1325,7 +1325,7 @@
*handle = DMA_ERROR_CODE;
size = PAGE_ALIGN(size);
- if (gfp & GFP_ATOMIC)
+ if (!(gfp & __GFP_WAIT))
return __iommu_alloc_atomic(dev, size, handle);
/*
diff -Nur linux/arch/arm/mm/extable.c rpi/arch/arm/mm/extable.c
--- linux/arch/arm/mm/extable.c 2014-05-29 12:18:17.292560896 +0900
+++ rpi/arch/arm/mm/extable.c 2014-05-29 11:49:04.480962814 +0900
@@ -9,8 +9,13 @@
const struct exception_table_entry *fixup;
fixup = search_exception_tables(instruction_pointer(regs));
- if (fixup)
+ if (fixup) {
regs->ARM_pc = fixup->fixup;
+#ifdef CONFIG_THUMB2_KERNEL
+ /* Clear the IT state to avoid nasty surprises in the fixup */
+ regs->ARM_cpsr &= ~PSR_IT_MASK;
+#endif
+ }
return fixup != NULL;
}
diff -Nur linux/arch/arm/mm/flush.c rpi/arch/arm/mm/flush.c
--- linux/arch/arm/mm/flush.c 2014-05-29 12:18:17.293560890 +0900
+++ rpi/arch/arm/mm/flush.c 2014-05-29 11:49:04.481962805 +0900
@@ -175,16 +175,16 @@
unsigned long i;
if (cache_is_vipt_nonaliasing()) {
for (i = 0; i < (1 << compound_order(page)); i++) {
- void *addr = kmap_atomic(page);
+ void *addr = kmap_atomic(page + i);
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
kunmap_atomic(addr);
}
} else {
for (i = 0; i < (1 << compound_order(page)); i++) {
- void *addr = kmap_high_get(page);
+ void *addr = kmap_high_get(page + i);
if (addr) {
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
- kunmap_high(page);
+ kunmap_high(page + i);
}
}
}
diff -Nur linux/arch/arm/mm/Kconfig rpi/arch/arm/mm/Kconfig
--- linux/arch/arm/mm/Kconfig 2014-05-29 12:18:17.288560921 +0900
+++ rpi/arch/arm/mm/Kconfig 2014-05-29 11:49:04.472962881 +0900
@@ -358,7 +358,7 @@
# ARMv6
config CPU_V6
- bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
+ bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708
select CPU_32v6
select CPU_ABRT_EV6
select CPU_CACHE_V6
@@ -446,7 +446,6 @@
config CPU_32v6
bool
- select CPU_USE_DOMAINS if CPU_V6 && MMU
select TLS_REG_EMUL if !CPU_32v6K && !MMU
config CPU_32v6K
@@ -671,7 +670,7 @@
config SWP_EMULATE
bool "Emulate SWP/SWPB instructions"
- depends on !CPU_USE_DOMAINS && CPU_V7
+ depends on CPU_V7
default y if SMP
select HAVE_PROC_CPU if PROC_FS
help
diff -Nur linux/arch/arm/mm/mmap.c rpi/arch/arm/mm/mmap.c
--- linux/arch/arm/mm/mmap.c 2014-05-29 12:18:17.295560877 +0900
+++ rpi/arch/arm/mm/mmap.c 2014-05-29 11:49:04.483962789 +0900
@@ -146,7 +146,7 @@
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
info.length = len;
- info.low_limit = PAGE_SIZE;
+ info.low_limit = FIRST_USER_ADDRESS;
info.high_limit = mm->mmap_base;
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
info.align_offset = pgoff << PAGE_SHIFT;
@@ -202,13 +202,11 @@
}
/*
- * We don't use supersection mappings for mmap() on /dev/mem, which
- * means that we can't map the memory area above the 4G barrier into
- * userspace.
+ * Do not allow /dev/mem mappings beyond the supported physical range.
*/
int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
- return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
+ return (pfn + (size >> PAGE_SHIFT)) <= (1 + (PHYS_MASK >> PAGE_SHIFT));
}
#ifdef CONFIG_STRICT_DEVMEM
diff -Nur linux/arch/arm/mm/mm.h rpi/arch/arm/mm/mm.h
--- linux/arch/arm/mm/mm.h 2014-05-29 12:18:17.295560877 +0900
+++ rpi/arch/arm/mm/mm.h 2014-05-29 11:49:04.483962789 +0900
@@ -38,6 +38,7 @@
struct mem_type {
pteval_t prot_pte;
+ pteval_t prot_pte_s2;
pmdval_t prot_l1;
pmdval_t prot_sect;
unsigned int domain;
diff -Nur linux/arch/arm/mm/mmu.c rpi/arch/arm/mm/mmu.c
--- linux/arch/arm/mm/mmu.c 2014-05-29 12:18:17.296560871 +0900
+++ rpi/arch/arm/mm/mmu.c 2014-05-29 11:49:04.484962780 +0900
@@ -229,12 +229,16 @@
#endif /* ifdef CONFIG_CPU_CP15 / else */
#define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
+#define PROT_PTE_S2_DEVICE PROT_PTE_DEVICE
#define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE
static struct mem_type mem_types[] = {
[MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */
.prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
L_PTE_SHARED,
+ .prot_pte_s2 = s2_policy(PROT_PTE_S2_DEVICE) |
+ s2_policy(L_PTE_S2_MT_DEV_SHARED) |
+ L_PTE_SHARED,
.prot_l1 = PMD_TYPE_TABLE,
.prot_sect = PROT_SECT_DEVICE | PMD_SECT_S,
.domain = DOMAIN_IO,
@@ -456,7 +460,18 @@
cp = &cache_policies[cachepolicy];
vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
s2_pgprot = cp->pte_s2;
- hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte;
+ hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte;
+ s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2;
+
+ /*
+ * We don't use domains on ARMv6 (since this causes problems with
+ * v6/v7 kernels), so we must use a separate memory type for user
+ * r/o, kernel r/w to map the vectors page.
+ */
+#ifndef CONFIG_ARM_LPAE
+ if (cpu_arch == CPU_ARCH_ARMv6)
+ vecs_pgprot |= L_PTE_MT_VECTORS;
+#endif
/*
* ARMv6 and above have extended page tables.
diff -Nur linux/arch/arm/mm/pgd.c rpi/arch/arm/mm/pgd.c
--- linux/arch/arm/mm/pgd.c 2014-05-29 12:18:17.297560865 +0900
+++ rpi/arch/arm/mm/pgd.c 2014-05-29 11:49:04.485962772 +0900
@@ -87,7 +87,8 @@
init_pud = pud_offset(init_pgd, 0);
init_pmd = pmd_offset(init_pud, 0);
init_pte = pte_offset_map(init_pmd, 0);
- set_pte_ext(new_pte, *init_pte, 0);
+ set_pte_ext(new_pte + 0, init_pte[0], 0);
+ set_pte_ext(new_pte + 1, init_pte[1], 0);
pte_unmap(init_pte);
pte_unmap(new_pte);
}
diff -Nur linux/arch/arm/mm/proc-macros.S rpi/arch/arm/mm/proc-macros.S
--- linux/arch/arm/mm/proc-macros.S 2014-05-29 12:18:17.297560865 +0900
+++ rpi/arch/arm/mm/proc-macros.S 2014-05-29 11:49:04.489962738 +0900
@@ -112,13 +112,9 @@
* 100x 1 0 1 r/o no acc
* 10x0 1 0 1 r/o no acc
* 1011 0 0 1 r/w no acc
- * 110x 0 1 0 r/w r/o
- * 11x0 0 1 0 r/w r/o
- * 1111 0 1 1 r/w r/w
- *
- * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
* 110x 1 1 1 r/o r/o
* 11x0 1 1 1 r/o r/o
+ * 1111 0 1 1 r/w r/w
*/
.macro armv6_mt_table pfx
\pfx\()_mt_table:
@@ -137,7 +133,7 @@
.long PTE_EXT_TEX(2) @ L_PTE_MT_DEV_NONSHARED
.long 0x00 @ unused
.long 0x00 @ unused
- .long 0x00 @ unused
+ .long PTE_CACHEABLE | PTE_BUFFERABLE | PTE_EXT_APX @ L_PTE_MT_VECTORS
.endm
.macro armv6_set_pte_ext pfx
@@ -158,24 +154,21 @@
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
+
+ @ user read-only -> kernel read-only
+ bicne r3, r3, #PTE_EXT_AP0
tst r1, #L_PTE_XN
orrne r3, r3, #PTE_EXT_XN
- orr r3, r3, r2
+ eor r3, r3, r2
tst r1, #L_PTE_YOUNG
tstne r1, #L_PTE_PRESENT
moveq r3, #0
-#ifndef CONFIG_CPU_USE_DOMAINS
tstne r1, #L_PTE_NONE
movne r3, #0
-#endif
str r3, [r0]
mcr p15, 0, r0, c7, c10, 1 @ flush_pte
diff -Nur linux/arch/arm/mm/proc-v6.S rpi/arch/arm/mm/proc-v6.S
--- linux/arch/arm/mm/proc-v6.S 2014-05-29 12:18:17.298560858 +0900
+++ rpi/arch/arm/mm/proc-v6.S 2014-05-29 11:49:04.490962730 +0900
@@ -73,10 +73,19 @@
*
* IRQs are already disabled.
*/
+
+/* See jira SW-5991 for details of this workaround */
ENTRY(cpu_v6_do_idle)
- mov r1, #0
- mcr p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode
- mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt
+ .align 5
+ mov r1, #2
+1: subs r1, #1
+ nop
+ mcreq p15, 0, r1, c7, c10, 4 @ DWB - WFI may enter a low-power mode
+ mcreq p15, 0, r1, c7, c0, 4 @ wait for interrupt
+ nop
+ nop
+ nop
+ bne 1b
mov pc, lr
ENTRY(cpu_v6_dcache_clean_area)
@@ -208,7 +217,6 @@
mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache
- mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
#ifdef CONFIG_MMU
mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
mcr p15, 0, r0, c2, c0, 2 @ TTB control register
@@ -218,6 +226,8 @@
ALT_UP(orr r8, r8, #TTB_FLAGS_UP)
mcr p15, 0, r8, c2, c0, 1 @ load TTB1
#endif /* CONFIG_MMU */
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer and
+ @ complete invalidations
adr r5, v6_crval
ldmia r5, {r5, r6}
#ifdef CONFIG_CPU_ENDIAN_BE8
diff -Nur linux/arch/arm/mm/proc-v7-2level.S rpi/arch/arm/mm/proc-v7-2level.S
--- linux/arch/arm/mm/proc-v7-2level.S 2014-05-29 12:18:17.298560858 +0900
+++ rpi/arch/arm/mm/proc-v7-2level.S 2014-05-29 11:49:04.491962721 +0900
@@ -90,21 +90,14 @@
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_VALID
-#ifndef CONFIG_CPU_USE_DOMAINS
eorne r1, r1, #L_PTE_NONE
tstne r1, #L_PTE_NONE
-#endif
moveq r3, #0
ARM( str r3, [r0, #2048]! )
diff -Nur linux/arch/arm/mm/proc-v7.S rpi/arch/arm/mm/proc-v7.S
--- linux/arch/arm/mm/proc-v7.S 2014-05-29 12:18:17.298560858 +0900
+++ rpi/arch/arm/mm/proc-v7.S 2014-05-29 11:49:04.491962721 +0900
@@ -344,7 +344,6 @@
4: mov r10, #0
mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
- dsb
#ifdef CONFIG_MMU
mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
v7_ttb_setup r10, r4, r8, r5 @ TTBCR, TTBRx setup
@@ -353,6 +352,7 @@
mcr p15, 0, r5, c10, c2, 0 @ write PRRR
mcr p15, 0, r6, c10, c2, 1 @ write NMRR
#endif
+ dsb @ Complete invalidations
#ifndef CONFIG_ARM_THUMBEE
mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE
and r0, r0, #(0xf << 12) @ ThumbEE enabled field
diff -Nur linux/arch/arm/net/bpf_jit_32.c rpi/arch/arm/net/bpf_jit_32.c
--- linux/arch/arm/net/bpf_jit_32.c 2014-05-29 12:18:17.299560852 +0900
+++ rpi/arch/arm/net/bpf_jit_32.c 2014-05-29 11:49:04.494962696 +0900
@@ -637,10 +637,10 @@
emit(ARM_MUL(r_A, r_A, r_X), ctx);
break;
case BPF_S_ALU_DIV_K:
- /* current k == reciprocal_value(userspace k) */
+ if (k == 1)
+ break;
emit_mov_i(r_scratch, k, ctx);
- /* A = top 32 bits of the product */
- emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
+ emit_udiv(r_A, r_A, r_scratch, ctx);
break;
case BPF_S_ALU_DIV_X:
update_on_xread(ctx);
diff -Nur linux/arch/arm/plat-orion/irq.c rpi/arch/arm/plat-orion/irq.c
--- linux/arch/arm/plat-orion/irq.c 2014-05-29 12:18:17.303560827 +0900
+++ rpi/arch/arm/plat-orion/irq.c 2014-05-29 11:49:04.510962562 +0900
@@ -15,8 +15,51 @@
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <asm/exception.h>
#include <plat/irq.h>
#include <plat/orion-gpio.h>
+#include <mach/bridge-regs.h>
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+/*
+ * Compiling with both non-DT and DT support enabled, will
+ * break asm irq handler used by non-DT boards. Therefore,
+ * we provide a C-style irq handler even for non-DT boards,
+ * if MULTI_IRQ_HANDLER is set.
+ *
+ * Notes:
+ * - this is prepared for Kirkwood and Dove only, update
+ * accordingly if you add Orion5x or MV78x00.
+ * - Orion5x uses different macro names and has only one
+ * set of CAUSE/MASK registers.
+ * - MV78x00 uses the same macro names but has a third
+ * set of CAUSE/MASK registers.
+ *
+ */
+
+static void __iomem *orion_irq_base = IRQ_VIRT_BASE;
+
+asmlinkage void
+__exception_irq_entry orion_legacy_handle_irq(struct pt_regs *regs)
+{
+ u32 stat;
+
+ stat = readl_relaxed(orion_irq_base + IRQ_CAUSE_LOW_OFF);
+ stat &= readl_relaxed(orion_irq_base + IRQ_MASK_LOW_OFF);
+ if (stat) {
+ unsigned int hwirq = __fls(stat);
+ handle_IRQ(hwirq, regs);
+ return;
+ }
+ stat = readl_relaxed(orion_irq_base + IRQ_CAUSE_HIGH_OFF);
+ stat &= readl_relaxed(orion_irq_base + IRQ_MASK_HIGH_OFF);
+ if (stat) {
+ unsigned int hwirq = 32 + __fls(stat);
+ handle_IRQ(hwirq, regs);
+ return;
+ }
+}
+#endif
void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
{
@@ -35,6 +78,10 @@
ct->chip.irq_unmask = irq_gc_mask_set_bit;
irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+ set_handle_irq(orion_legacy_handle_irq);
+#endif
}
#ifdef CONFIG_OF
diff -Nur linux/arch/arm/tools/mach-types rpi/arch/arm/tools/mach-types
--- linux/arch/arm/tools/mach-types 2014-05-29 11:51:25.905801063 +0900
+++ rpi/arch/arm/tools/mach-types 2014-05-29 11:49:04.535962352 +0900
@@ -522,6 +522,7 @@
prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103
paz00 MACH_PAZ00 PAZ00 3128
acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129
+bcm2708 MACH_BCM2708 BCM2708 3138
ag5evm MACH_AG5EVM AG5EVM 3189
ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206
wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207
diff -Nur linux/arch/arm64/boot/dts/foundation-v8.dts rpi/arch/arm64/boot/dts/foundation-v8.dts
--- linux/arch/arm64/boot/dts/foundation-v8.dts 2014-05-29 12:18:17.318560733 +0900
+++ rpi/arch/arm64/boot/dts/foundation-v8.dts 2014-05-29 11:49:04.542962293 +0900
@@ -6,6 +6,8 @@
/dts-v1/;
+/memreserve/ 0x80000000 0x00010000;
+
/ {
model = "Foundation-v8A";
compatible = "arm,foundation-aarch64", "arm,vexpress";
diff -Nur linux/arch/arm64/include/asm/cacheflush.h rpi/arch/arm64/include/asm/cacheflush.h
--- linux/arch/arm64/include/asm/cacheflush.h 2014-05-29 12:18:17.321560714 +0900
+++ rpi/arch/arm64/include/asm/cacheflush.h 2014-05-29 11:49:04.545962268 +0900
@@ -116,6 +116,7 @@
static inline void __flush_icache_all(void)
{
asm("ic ialluis");
+ dsb();
}
#define flush_dcache_mmap_lock(mapping) \
diff -Nur linux/arch/arm64/include/asm/pgtable.h rpi/arch/arm64/include/asm/pgtable.h
--- linux/arch/arm64/include/asm/pgtable.h 2014-05-29 12:18:17.328560671 +0900
+++ rpi/arch/arm64/include/asm/pgtable.h 2014-05-29 11:49:04.556962175 +0900
@@ -25,10 +25,11 @@
* Software defined PTE bits definition.
*/
#define PTE_VALID (_AT(pteval_t, 1) << 0)
-#define PTE_PROT_NONE (_AT(pteval_t, 1) << 2) /* only when !PTE_VALID */
-#define PTE_FILE (_AT(pteval_t, 1) << 3) /* only when !pte_present() */
+#define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */
#define PTE_DIRTY (_AT(pteval_t, 1) << 55)
#define PTE_SPECIAL (_AT(pteval_t, 1) << 56)
+ /* bit 57 for PMD_SECT_SPLITTING */
+#define PTE_PROT_NONE (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */
/*
* VMALLOC and SPARSEMEM_VMEMMAP ranges.
@@ -135,10 +136,10 @@
/*
* The following only work if pte_present(). Undefined behaviour otherwise.
*/
-#define pte_present(pte) (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))
-#define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY)
-#define pte_young(pte) (pte_val(pte) & PTE_AF)
-#define pte_special(pte) (pte_val(pte) & PTE_SPECIAL)
+#define pte_present(pte) (!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
+#define pte_dirty(pte) (!!(pte_val(pte) & PTE_DIRTY))
+#define pte_young(pte) (!!(pte_val(pte) & PTE_AF))
+#define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))
#define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY))
#define pte_exec(pte) (!(pte_val(pte) & PTE_UXN))
@@ -167,7 +168,7 @@
pte_t *ptep, pte_t pte)
{
if (pte_valid_user(pte)) {
- if (pte_exec(pte))
+ if (!pte_special(pte) && pte_exec(pte))
__sync_icache_dcache(pte, addr);
if (!pte_dirty(pte))
pte = pte_wrprotect(pte);
@@ -252,11 +253,11 @@
* Mark the prot value as uncacheable and unbufferable.
*/
#define pgprot_noncached(prot) \
- __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE))
+ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN)
#define pgprot_writecombine(prot) \
- __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE))
+ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
#define pgprot_dmacoherent(prot) \
- __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
+ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
#define __HAVE_PHYS_MEM_ACCESS_PROT
struct file;
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
@@ -357,18 +358,20 @@
/*
* Encode and decode a swap entry:
- * bits 0, 2: present (must both be zero)
- * bit 3: PTE_FILE
- * bits 4-8: swap type
- * bits 9-63: swap offset
+ * bits 0-1: present (must be zero)
+ * bit 2: PTE_FILE
+ * bits 3-8: swap type
+ * bits 9-57: swap offset
*/
-#define __SWP_TYPE_SHIFT 4
+#define __SWP_TYPE_SHIFT 3
#define __SWP_TYPE_BITS 6
+#define __SWP_OFFSET_BITS 49
#define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1)
#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
+#define __SWP_OFFSET_MASK ((1UL << __SWP_OFFSET_BITS) - 1)
#define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
-#define __swp_offset(x) ((x).val >> __SWP_OFFSET_SHIFT)
+#define __swp_offset(x) (((x).val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK)
#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
@@ -382,15 +385,15 @@
/*
* Encode and decode a file entry:
- * bits 0, 2: present (must both be zero)
- * bit 3: PTE_FILE
- * bits 4-63: file offset / PAGE_SIZE
+ * bits 0-1: present (must be zero)
+ * bit 2: PTE_FILE
+ * bits 3-57: file offset / PAGE_SIZE
*/
#define pte_file(pte) (pte_val(pte) & PTE_FILE)
-#define pte_to_pgoff(x) (pte_val(x) >> 4)
-#define pgoff_to_pte(x) __pte(((x) << 4) | PTE_FILE)
+#define pte_to_pgoff(x) (pte_val(x) >> 3)
+#define pgoff_to_pte(x) __pte(((x) << 3) | PTE_FILE)
-#define PTE_FILE_MAX_BITS 60
+#define PTE_FILE_MAX_BITS 55
extern int kern_addr_valid(unsigned long addr);
diff -Nur linux/arch/arm64/include/asm/pgtable-hwdef.h rpi/arch/arm64/include/asm/pgtable-hwdef.h
--- linux/arch/arm64/include/asm/pgtable-hwdef.h 2014-05-29 12:18:17.327560677 +0900
+++ rpi/arch/arm64/include/asm/pgtable-hwdef.h 2014-05-29 11:49:04.556962175 +0900
@@ -43,7 +43,7 @@
* Section
*/
#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_PROT_NONE (_AT(pmdval_t, 1) << 2)
+#define PMD_SECT_PROT_NONE (_AT(pmdval_t, 1) << 58)
#define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */
#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */
#define PMD_SECT_S (_AT(pmdval_t, 3) << 8)
diff -Nur linux/arch/arm64/include/asm/syscall.h rpi/arch/arm64/include/asm/syscall.h
--- linux/arch/arm64/include/asm/syscall.h 2014-05-29 12:18:17.330560658 +0900
+++ rpi/arch/arm64/include/asm/syscall.h 2014-05-29 11:49:04.559962150 +0900
@@ -59,6 +59,9 @@
unsigned int i, unsigned int n,
unsigned long *args)
{
+ if (n == 0)
+ return;
+
if (i + n > SYSCALL_MAX_ARGS) {
unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
@@ -82,6 +85,9 @@
unsigned int i, unsigned int n,
const unsigned long *args)
{
+ if (n == 0)
+ return;
+
if (i + n > SYSCALL_MAX_ARGS) {
pr_warning("%s called with max args %d, handling only %d\n",
__func__, i + n, SYSCALL_MAX_ARGS);
diff -Nur linux/arch/arm64/kernel/ptrace.c rpi/arch/arm64/kernel/ptrace.c
--- linux/arch/arm64/kernel/ptrace.c 2014-05-29 12:18:17.340560596 +0900
+++ rpi/arch/arm64/kernel/ptrace.c 2014-05-29 11:49:04.573962032 +0900
@@ -214,31 +214,29 @@
{
int err, len, type, disabled = !ctrl.enabled;
- if (disabled) {
- len = 0;
- type = HW_BREAKPOINT_EMPTY;
- } else {
- err = arch_bp_generic_fields(ctrl, &len, &type);
- if (err)
- return err;
+ attr->disabled = disabled;
+ if (disabled)
+ return 0;
- switch (note_type) {
- case NT_ARM_HW_BREAK:
- if ((type & HW_BREAKPOINT_X) != type)
- return -EINVAL;
- break;
- case NT_ARM_HW_WATCH:
- if ((type & HW_BREAKPOINT_RW) != type)
- return -EINVAL;
- break;
- default:
+ err = arch_bp_generic_fields(ctrl, &len, &type);
+ if (err)
+ return err;
+
+ switch (note_type) {
+ case NT_ARM_HW_BREAK:
+ if ((type & HW_BREAKPOINT_X) != type)
+ return -EINVAL;
+ break;
+ case NT_ARM_HW_WATCH:
+ if ((type & HW_BREAKPOINT_RW) != type)
return -EINVAL;
- }
+ break;
+ default:
+ return -EINVAL;
}
attr->bp_len = len;
attr->bp_type = type;
- attr->disabled = disabled;
return 0;
}
diff -Nur linux/arch/arm64/kernel/stacktrace.c rpi/arch/arm64/kernel/stacktrace.c
--- linux/arch/arm64/kernel/stacktrace.c 2014-05-29 12:18:17.342560583 +0900
+++ rpi/arch/arm64/kernel/stacktrace.c 2014-05-29 11:49:04.575962016 +0900
@@ -48,7 +48,11 @@
frame->sp = fp + 0x10;
frame->fp = *(unsigned long *)(fp);
- frame->pc = *(unsigned long *)(fp + 8);
+ /*
+ * -4 here because we care about the PC at time of bl,
+ * not where the return will go.
+ */
+ frame->pc = *(unsigned long *)(fp + 8) - 4;
return 0;
}
diff -Nur linux/arch/arm64/kernel/vdso/gettimeofday.S rpi/arch/arm64/kernel/vdso/gettimeofday.S
--- linux/arch/arm64/kernel/vdso/gettimeofday.S 2014-05-29 12:18:17.344560571 +0900
+++ rpi/arch/arm64/kernel/vdso/gettimeofday.S 2014-05-29 11:49:04.577961999 +0900
@@ -103,6 +103,8 @@
bl __do_get_tspec
seqcnt_check w9, 1b
+ mov x30, x2
+
cmp w0, #CLOCK_MONOTONIC
b.ne 6f
@@ -118,6 +120,9 @@
ccmp w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
b.ne 8f
+ /* xtime_coarse_nsec is already right-shifted */
+ mov x12, #0
+
/* Get coarse timespec. */
adr vdso_data, _vdso_data
3: seqcnt_acquire
@@ -156,7 +161,7 @@
lsr x11, x11, x12
stp x10, x11, [x1, #TSPEC_TV_SEC]
mov x0, xzr
- ret x2
+ ret
7:
mov x30, x2
8: /* Syscall fallback. */
diff -Nur linux/arch/arm64/kernel/vdso/Makefile rpi/arch/arm64/kernel/vdso/Makefile
--- linux/arch/arm64/kernel/vdso/Makefile 2014-05-29 12:18:17.343560577 +0900
+++ rpi/arch/arm64/kernel/vdso/Makefile 2014-05-29 11:49:04.576962007 +0900
@@ -48,7 +48,7 @@
# Actual build commands
quiet_cmd_vdsold = VDSOL $@
- cmd_vdsold = $(CC) $(c_flags) -Wl,-T $^ -o $@
+ cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
quiet_cmd_vdsoas = VDSOA $@
cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
diff -Nur linux/arch/arm64/kernel/vdso.c rpi/arch/arm64/kernel/vdso.c
--- linux/arch/arm64/kernel/vdso.c 2014-05-29 12:18:17.343560577 +0900
+++ rpi/arch/arm64/kernel/vdso.c 2014-05-29 11:49:04.576962007 +0900
@@ -235,6 +235,8 @@
vdso_data->use_syscall = use_syscall;
vdso_data->xtime_coarse_sec = xtime_coarse.tv_sec;
vdso_data->xtime_coarse_nsec = xtime_coarse.tv_nsec;
+ vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec;
+ vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
if (!use_syscall) {
vdso_data->cs_cycle_last = tk->clock->cycle_last;
@@ -242,8 +244,6 @@
vdso_data->xtime_clock_nsec = tk->xtime_nsec;
vdso_data->cs_mult = tk->mult;
vdso_data->cs_shift = tk->shift;
- vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec;
- vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
}
smp_wmb();
diff -Nur linux/arch/arm64/mm/mmu.c rpi/arch/arm64/mm/mmu.c
--- linux/arch/arm64/mm/mmu.c 2014-05-29 12:18:17.350560533 +0900
+++ rpi/arch/arm64/mm/mmu.c 2014-05-29 11:49:04.587961915 +0900
@@ -203,10 +203,18 @@
do {
next = pmd_addr_end(addr, end);
/* try section mapping first */
- if (((addr | next | phys) & ~SECTION_MASK) == 0)
+ if (((addr | next | phys) & ~SECTION_MASK) == 0) {
+ pmd_t old_pmd =*pmd;
set_pmd(pmd, __pmd(phys | prot_sect_kernel));
- else
+ /*
+ * Check for previous table entries created during
+ * boot (__create_page_tables) and flush them.
+ */
+ if (!pmd_none(old_pmd))
+ flush_tlb_all();
+ } else {
alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys));
+ }
phys += next - addr;
} while (pmd++, addr = next, addr != end);
}
diff -Nur linux/arch/avr32/boards/mimc200/fram.c rpi/arch/avr32/boards/mimc200/fram.c
--- linux/arch/avr32/boards/mimc200/fram.c 2014-05-29 12:18:17.354560508 +0900
+++ rpi/arch/avr32/boards/mimc200/fram.c 2014-05-29 11:49:04.595961848 +0900
@@ -11,6 +11,7 @@
#define FRAM_VERSION "1.0"
#include <linux/miscdevice.h>
+#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/io.h>
diff -Nur linux/arch/avr32/boot/u-boot/head.S rpi/arch/avr32/boot/u-boot/head.S
--- linux/arch/avr32/boot/u-boot/head.S 2014-05-29 12:18:17.354560508 +0900
+++ rpi/arch/avr32/boot/u-boot/head.S 2014-05-29 11:49:04.596961839 +0900
@@ -8,6 +8,8 @@
* published by the Free Software Foundation.
*/
#include <asm/setup.h>
+#include <asm/thread_info.h>
+#include <asm/sysreg.h>
/*
* The kernel is loaded where we want it to be and all caches
@@ -20,11 +22,6 @@
.section .init.text,"ax"
.global _start
_start:
- /* Check if the boot loader actually provided a tag table */
- lddpc r0, magic_number
- cp.w r12, r0
- brne no_tag_table
-
/* Initialize .bss */
lddpc r2, bss_start_addr
lddpc r3, end_addr
@@ -34,6 +31,25 @@
cp r2, r3
brlo 1b
+ /* Initialize status register */
+ lddpc r0, init_sr
+ mtsr SYSREG_SR, r0
+
+ /* Set initial stack pointer */
+ lddpc sp, stack_addr
+ sub sp, -THREAD_SIZE
+
+#ifdef CONFIG_FRAME_POINTER
+ /* Mark last stack frame */
+ mov lr, 0
+ mov r7, 0
+#endif
+
+ /* Check if the boot loader actually provided a tag table */
+ lddpc r0, magic_number
+ cp.w r12, r0
+ brne no_tag_table
+
/*
* Save the tag table address for later use. This must be done
* _after_ .bss has been initialized...
@@ -53,8 +69,15 @@
.long __bss_start
end_addr:
.long _end
+init_sr:
+ .long 0x007f0000 /* Supervisor mode, everything masked */
+stack_addr:
+ .long init_thread_union
+panic_addr:
+ .long panic
no_tag_table:
sub r12, pc, (. - 2f)
- bral panic
+ /* branch to panic() which can be far away with that construct */
+ lddpc pc, panic_addr
2: .asciz "Boot loader didn't provide correct magic number\n"
diff -Nur linux/arch/avr32/kernel/entry-avr32b.S rpi/arch/avr32/kernel/entry-avr32b.S
--- linux/arch/avr32/kernel/entry-avr32b.S 2014-05-29 12:18:17.367560427 +0900
+++ rpi/arch/avr32/kernel/entry-avr32b.S 2014-05-29 11:49:04.616961671 +0900
@@ -401,9 +401,10 @@
/* We should never get here... */
bad_return:
sub r12, pc, (. - 1f)
- bral panic
+ lddpc pc, 2f
.align 2
1: .asciz "Return from critical exception!"
+2: .long panic
.align 1
do_bus_error_write:
diff -Nur linux/arch/avr32/kernel/head.S rpi/arch/avr32/kernel/head.S
--- linux/arch/avr32/kernel/head.S 2014-05-29 12:18:17.367560427 +0900
+++ rpi/arch/avr32/kernel/head.S 2014-05-29 11:49:04.616961671 +0900
@@ -10,33 +10,13 @@
#include <linux/linkage.h>
#include <asm/page.h>
-#include <asm/thread_info.h>
-#include <asm/sysreg.h>
.section .init.text,"ax"
.global kernel_entry
kernel_entry:
- /* Initialize status register */
- lddpc r0, init_sr
- mtsr SYSREG_SR, r0
-
- /* Set initial stack pointer */
- lddpc sp, stack_addr
- sub sp, -THREAD_SIZE
-
-#ifdef CONFIG_FRAME_POINTER
- /* Mark last stack frame */
- mov lr, 0
- mov r7, 0
-#endif
-
/* Start the show */
lddpc pc, kernel_start_addr
.align 2
-init_sr:
- .long 0x007f0000 /* Supervisor mode, everything masked */
-stack_addr:
- .long init_thread_union
kernel_start_addr:
.long start_kernel
diff -Nur linux/arch/avr32/Makefile rpi/arch/avr32/Makefile
--- linux/arch/avr32/Makefile 2014-05-29 12:18:17.351560527 +0900
+++ rpi/arch/avr32/Makefile 2014-05-29 11:49:04.589961898 +0900
@@ -11,7 +11,7 @@
KBUILD_DEFCONFIG := atstk1002_defconfig
-KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic
+KBUILD_CFLAGS += -pipe -fno-builtin -mno-pic -D__linux__
KBUILD_AFLAGS += -mrelax -mno-pic
KBUILD_CFLAGS_MODULE += -mno-relax
LDFLAGS_vmlinux += --relax
diff -Nur linux/arch/cris/include/asm/io.h rpi/arch/cris/include/asm/io.h
--- linux/arch/cris/include/asm/io.h 2014-05-29 12:18:17.429560038 +0900
+++ rpi/arch/cris/include/asm/io.h 2014-05-29 11:49:04.889959378 +0900
@@ -3,6 +3,7 @@
#include <asm/page.h> /* for __va, __pa */
#include <arch/io.h>
+#include <asm-generic/iomap.h>
#include <linux/kernel.h>
struct cris_io_operations
diff -Nur linux/arch/ia64/include/asm/processor.h rpi/arch/ia64/include/asm/processor.h
--- linux/arch/ia64/include/asm/processor.h 2014-05-29 12:18:17.484559694 +0900
+++ rpi/arch/ia64/include/asm/processor.h 2014-05-29 11:49:05.055957983 +0900
@@ -319,7 +319,7 @@
regs->loadrs = 0; \
regs->r8 = get_dumpable(current->mm); /* set "don't zap registers" flag */ \
regs->r12 = new_sp - 16; /* allocate 16 byte scratch area */ \
- if (unlikely(!get_dumpable(current->mm))) { \
+ if (unlikely(get_dumpable(current->mm) != SUID_DUMP_USER)) { \
/* \
* Zap scratch regs to avoid leaking bits between processes with different \
* uid/privileges. \
diff -Nur linux/arch/m68k/Kconfig rpi/arch/m68k/Kconfig
--- linux/arch/m68k/Kconfig 2014-05-29 12:18:17.519559475 +0900
+++ rpi/arch/m68k/Kconfig 2014-05-29 11:49:05.211956673 +0900
@@ -16,6 +16,7 @@
select FPU if MMU
select ARCH_WANT_IPC_PARSE_VERSION
select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
+ select HAVE_FUTEX_CMPXCHG if MMU && FUTEX
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_REL
select MODULES_USE_ELF_RELA
diff -Nur linux/arch/mips/include/asm/mipsregs.h rpi/arch/mips/include/asm/mipsregs.h
--- linux/arch/mips/include/asm/mipsregs.h 2014-05-29 12:18:17.651558649 +0900
+++ rpi/arch/mips/include/asm/mipsregs.h 2014-05-29 11:49:09.497920699 +0900
@@ -14,6 +14,7 @@
#define _ASM_MIPSREGS_H
#include <linux/linkage.h>
+#include <linux/types.h>
#include <asm/hazards.h>
#include <asm/war.h>
diff -Nur linux/arch/mips/kvm/kvm_mips_emul.c rpi/arch/mips/kvm/kvm_mips_emul.c
--- linux/arch/mips/kvm/kvm_mips_emul.c 2014-05-29 12:18:17.689558411 +0900
+++ rpi/arch/mips/kvm/kvm_mips_emul.c 2014-05-29 11:49:10.879909109 +0900
@@ -1571,17 +1571,17 @@
arch->gprs[rt] = kvm_read_c0_guest_userlocal(cop0);
#else
/* UserLocal not implemented */
- er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
+ er = EMULATE_FAIL;
#endif
break;
default:
- printk("RDHWR not supported\n");
+ kvm_debug("RDHWR %#x not supported @ %p\n", rd, opc);
er = EMULATE_FAIL;
break;
}
} else {
- printk("Emulate RI not supported @ %p: %#x\n", opc, inst);
+ kvm_debug("Emulate RI not supported @ %p: %#x\n", opc, inst);
er = EMULATE_FAIL;
}
@@ -1590,6 +1590,7 @@
*/
if (er == EMULATE_FAIL) {
vcpu->arch.pc = curr_pc;
+ er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu);
}
return er;
}
diff -Nur linux/arch/mips/power/hibernate.S rpi/arch/mips/power/hibernate.S
--- linux/arch/mips/power/hibernate.S 2014-05-29 12:18:17.728558167 +0900
+++ rpi/arch/mips/power/hibernate.S 2014-05-29 11:49:10.976908296 +0900
@@ -43,6 +43,7 @@
bne t1, t3, 1b
PTR_L t0, PBE_NEXT(t0)
bnez t0, 0b
+ jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */
PTR_LA t0, saved_regs
PTR_L ra, PT_R31(t0)
PTR_L sp, PT_R29(t0)
diff -Nur linux/arch/parisc/include/asm/cacheflush.h rpi/arch/parisc/include/asm/cacheflush.h
--- linux/arch/parisc/include/asm/cacheflush.h 2014-05-29 12:18:17.759557973 +0900
+++ rpi/arch/parisc/include/asm/cacheflush.h 2014-05-29 11:49:11.097907282 +0900
@@ -125,15 +125,10 @@
void mark_rodata_ro(void);
#endif
-#ifdef CONFIG_PA8X00
-/* Only pa8800, pa8900 needs this */
-
#include <asm/kmap_types.h>
#define ARCH_HAS_KMAP
-void kunmap_parisc(void *addr);
-
static inline void *kmap(struct page *page)
{
might_sleep();
@@ -142,7 +137,7 @@
static inline void kunmap(struct page *page)
{
- kunmap_parisc(page_address(page));
+ flush_kernel_dcache_page_addr(page_address(page));
}
static inline void *kmap_atomic(struct page *page)
@@ -153,14 +148,13 @@
static inline void __kunmap_atomic(void *addr)
{
- kunmap_parisc(addr);
+ flush_kernel_dcache_page_addr(addr);
pagefault_enable();
}
#define kmap_atomic_prot(page, prot) kmap_atomic(page)
#define kmap_atomic_pfn(pfn) kmap_atomic(pfn_to_page(pfn))
#define kmap_atomic_to_page(ptr) virt_to_page(ptr)
-#endif
#endif /* _PARISC_CACHEFLUSH_H */
diff -Nur linux/arch/parisc/include/asm/page.h rpi/arch/parisc/include/asm/page.h
--- linux/arch/parisc/include/asm/page.h 2014-05-29 12:18:17.760557967 +0900
+++ rpi/arch/parisc/include/asm/page.h 2014-05-29 11:49:11.103907231 +0900
@@ -28,9 +28,9 @@
void clear_page_asm(void *page);
void copy_page_asm(void *to, void *from);
-void clear_user_page(void *vto, unsigned long vaddr, struct page *pg);
+#define clear_user_page(vto, vaddr, page) clear_page_asm(vto)
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
- struct page *pg);
+ struct page *pg);
/* #define CONFIG_PARISC_TMPALIAS */
diff -Nur linux/arch/parisc/include/asm/socket.h rpi/arch/parisc/include/asm/socket.h
--- linux/arch/parisc/include/asm/socket.h 1970-01-01 09:00:00.000000000 +0900
+++ rpi/arch/parisc/include/asm/socket.h 2014-05-29 11:49:11.108907189 +0900
@@ -0,0 +1,11 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <uapi/asm/socket.h>
+
+/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
+ * have to define SOCK_NONBLOCK to a different value here.
+ */
+#define SOCK_NONBLOCK 0x40000000
+
+#endif /* _ASM_SOCKET_H */
diff -Nur linux/arch/parisc/include/uapi/asm/socket.h rpi/arch/parisc/include/uapi/asm/socket.h
--- linux/arch/parisc/include/uapi/asm/socket.h 2014-05-29 12:18:17.764557942 +0900
+++ rpi/arch/parisc/include/uapi/asm/socket.h 2014-05-29 11:49:11.115907131 +0900
@@ -1,5 +1,5 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
+#ifndef _UAPI_ASM_SOCKET_H
+#define _UAPI_ASM_SOCKET_H
#include <asm/sockios.h>
@@ -75,9 +75,4 @@
#define SO_BUSY_POLL 0x4027
-/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
- * have to define SOCK_NONBLOCK to a different value here.
- */
-#define SOCK_NONBLOCK 0x40000000
-
-#endif /* _ASM_SOCKET_H */
+#endif /* _UAPI_ASM_SOCKET_H */
diff -Nur linux/arch/parisc/kernel/cache.c rpi/arch/parisc/kernel/cache.c
--- linux/arch/parisc/kernel/cache.c 2014-05-29 12:18:17.766557929 +0900
+++ rpi/arch/parisc/kernel/cache.c 2014-05-29 11:49:11.118907106 +0900
@@ -388,41 +388,20 @@
}
EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
-void clear_user_page(void *vto, unsigned long vaddr, struct page *page)
-{
- clear_page_asm(vto);
- if (!parisc_requires_coherency())
- flush_kernel_dcache_page_asm(vto);
-}
-EXPORT_SYMBOL(clear_user_page);
-
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
struct page *pg)
{
- /* Copy using kernel mapping. No coherency is needed
- (all in kmap/kunmap) on machines that don't support
- non-equivalent aliasing. However, the `from' page
- needs to be flushed before it can be accessed through
- the kernel mapping. */
+ /* Copy using kernel mapping. No coherency is needed (all in
+ kunmap) for the `to' page. However, the `from' page needs to
+ be flushed through a mapping equivalent to the user mapping
+ before it can be accessed through the kernel mapping. */
preempt_disable();
flush_dcache_page_asm(__pa(vfrom), vaddr);
preempt_enable();
copy_page_asm(vto, vfrom);
- if (!parisc_requires_coherency())
- flush_kernel_dcache_page_asm(vto);
}
EXPORT_SYMBOL(copy_user_page);
-#ifdef CONFIG_PA8X00
-
-void kunmap_parisc(void *addr)
-{
- if (parisc_requires_coherency())
- flush_kernel_dcache_page_addr(addr);
-}
-EXPORT_SYMBOL(kunmap_parisc);
-#endif
-
void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
{
unsigned long flags;
diff -Nur linux/arch/parisc/kernel/syscall_table.S rpi/arch/parisc/kernel/syscall_table.S
--- linux/arch/parisc/kernel/syscall_table.S 2014-05-29 12:18:17.774557879 +0900
+++ rpi/arch/parisc/kernel/syscall_table.S 2014-05-29 11:49:11.132906988 +0900
@@ -392,7 +392,7 @@
ENTRY_COMP(vmsplice)
ENTRY_COMP(move_pages) /* 295 */
ENTRY_SAME(getcpu)
- ENTRY_SAME(epoll_pwait)
+ ENTRY_COMP(epoll_pwait)
ENTRY_COMP(statfs64)
ENTRY_COMP(fstatfs64)
ENTRY_COMP(kexec_load) /* 300 */
diff -Nur linux/arch/parisc/kernel/sys_parisc.c rpi/arch/parisc/kernel/sys_parisc.c
--- linux/arch/parisc/kernel/sys_parisc.c 2014-05-29 12:18:17.773557885 +0900
+++ rpi/arch/parisc/kernel/sys_parisc.c 2014-05-29 11:49:11.130907005 +0900
@@ -61,8 +61,15 @@
return (unsigned long) mapping >> 8;
}
-static unsigned long get_shared_area(struct address_space *mapping,
- unsigned long addr, unsigned long len, unsigned long pgoff)
+static unsigned long shared_align_offset(struct file *filp, unsigned long pgoff)
+{
+ struct address_space *mapping = filp ? filp->f_mapping : NULL;
+
+ return (get_offset(mapping) + pgoff) << PAGE_SHIFT;
+}
+
+static unsigned long get_shared_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff)
{
struct vm_unmapped_area_info info;
@@ -71,7 +78,7 @@
info.low_limit = PAGE_ALIGN(addr);
info.high_limit = TASK_SIZE;
info.align_mask = PAGE_MASK & (SHMLBA - 1);
- info.align_offset = (get_offset(mapping) + pgoff) << PAGE_SHIFT;
+ info.align_offset = shared_align_offset(filp, pgoff);
return vm_unmapped_area(&info);
}
@@ -82,20 +89,18 @@
return -ENOMEM;
if (flags & MAP_FIXED) {
if ((flags & MAP_SHARED) &&
- (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
+ (addr - shared_align_offset(filp, pgoff)) & (SHMLBA - 1))
return -EINVAL;
return addr;
}
if (!addr)
addr = TASK_UNMAPPED_BASE;
- if (filp) {
- addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
- } else if(flags & MAP_SHARED) {
- addr = get_shared_area(NULL, addr, len, pgoff);
- } else {
+ if (filp || (flags & MAP_SHARED))
+ addr = get_shared_area(filp, addr, len, pgoff);
+ else
addr = get_unshared_area(addr, len);
- }
+
return addr;
}
diff -Nur linux/arch/powerpc/boot/util.S rpi/arch/powerpc/boot/util.S
--- linux/arch/powerpc/boot/util.S 2014-05-29 12:18:17.816557616 +0900
+++ rpi/arch/powerpc/boot/util.S 2014-05-29 11:49:11.229906175 +0900
@@ -71,18 +71,32 @@
add r4,r4,r5
addi r4,r4,-1
divw r4,r4,r5 /* BUS ticks */
+#ifdef CONFIG_8xx
+1: mftbu r5
+ mftb r6
+ mftbu r7
+#else
1: mfspr r5, SPRN_TBRU
mfspr r6, SPRN_TBRL
mfspr r7, SPRN_TBRU
+#endif
cmpw 0,r5,r7
bne 1b /* Get [synced] base time */
addc r9,r6,r4 /* Compute end time */
addze r8,r5
+#ifdef CONFIG_8xx
+2: mftbu r5
+#else
2: mfspr r5, SPRN_TBRU
+#endif
cmpw 0,r5,r8
blt 2b
bgt 3f
+#ifdef CONFIG_8xx
+ mftb r6
+#else
mfspr r6, SPRN_TBRL
+#endif
cmpw 0,r6,r9
blt 2b
3: blr
diff -Nur linux/arch/powerpc/include/asm/compat.h rpi/arch/powerpc/include/asm/compat.h
--- linux/arch/powerpc/include/asm/compat.h 2014-05-29 12:18:17.870557278 +0900
+++ rpi/arch/powerpc/include/asm/compat.h 2014-05-29 11:49:11.276905781 +0900
@@ -8,7 +8,11 @@
#include <linux/sched.h>
#define COMPAT_USER_HZ 100
+#ifdef __BIG_ENDIAN__
#define COMPAT_UTS_MACHINE "ppc\0\0"
+#else
+#define COMPAT_UTS_MACHINE "ppcle\0\0"
+#endif
typedef u32 compat_size_t;
typedef s32 compat_ssize_t;
@@ -200,10 +204,11 @@
/*
* We can't access below the stack pointer in the 32bit ABI and
- * can access 288 bytes in the 64bit ABI
+ * can access 288 bytes in the 64bit big-endian ABI,
+ * or 512 bytes with the new ELFv2 little-endian ABI.
*/
if (!is_32bit_task())
- usp -= 288;
+ usp -= USER_REDZONE_SIZE;
return (void __user *) (usp - len);
}
diff -Nur linux/arch/powerpc/include/asm/eeh.h rpi/arch/powerpc/include/asm/eeh.h
--- linux/arch/powerpc/include/asm/eeh.h 2014-05-29 12:18:17.872557266 +0900
+++ rpi/arch/powerpc/include/asm/eeh.h 2014-05-29 11:49:11.283905723 +0900
@@ -117,6 +117,16 @@
return edev ? edev->pdev : NULL;
}
+/* Return values from eeh_ops::next_error */
+enum {
+ EEH_NEXT_ERR_NONE = 0,
+ EEH_NEXT_ERR_INF,
+ EEH_NEXT_ERR_FROZEN_PE,
+ EEH_NEXT_ERR_FENCED_PHB,
+ EEH_NEXT_ERR_DEAD_PHB,
+ EEH_NEXT_ERR_DEAD_IOC
+};
+
/*
* The struct is used to trace the registered EEH operation
* callback functions. Actually, those operation callback
diff -Nur linux/arch/powerpc/include/asm/exception-64s.h rpi/arch/powerpc/include/asm/exception-64s.h
--- linux/arch/powerpc/include/asm/exception-64s.h 2014-05-29 12:18:17.874557253 +0900
+++ rpi/arch/powerpc/include/asm/exception-64s.h 2014-05-29 11:49:11.285905706 +0900
@@ -265,7 +265,7 @@
subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \
beq- 1f; \
ld r1,PACAKSAVE(r13); /* kernel stack to use */ \
-1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \
+1: cmpdi cr1,r1,-INT_FRAME_SIZE; /* check if r1 is in userspace */ \
blt+ cr1,3f; /* abort if it is */ \
li r1,(n); /* will be reloaded later */ \
sth r1,PACA_TRAP_SAVE(r13); \
diff -Nur linux/arch/powerpc/include/asm/pgalloc-32.h rpi/arch/powerpc/include/asm/pgalloc-32.h
--- linux/arch/powerpc/include/asm/pgalloc-32.h 2014-05-29 12:18:17.885557184 +0900
+++ rpi/arch/powerpc/include/asm/pgalloc-32.h 2014-05-29 11:49:11.309905505 +0900
@@ -84,10 +84,8 @@
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
unsigned long address)
{
- struct page *page = page_address(table);
-
tlb_flush_pgtable(tlb, address);
- pgtable_page_dtor(page);
- pgtable_free_tlb(tlb, page, 0);
+ pgtable_page_dtor(table);
+ pgtable_free_tlb(tlb, page_address(table), 0);
}
#endif /* _ASM_POWERPC_PGALLOC_32_H */
diff -Nur linux/arch/powerpc/include/asm/pgalloc-64.h rpi/arch/powerpc/include/asm/pgalloc-64.h
--- linux/arch/powerpc/include/asm/pgalloc-64.h 2014-05-29 12:18:17.886557178 +0900
+++ rpi/arch/powerpc/include/asm/pgalloc-64.h 2014-05-29 11:49:11.309905505 +0900
@@ -144,11 +144,9 @@
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
unsigned long address)
{
- struct page *page = page_address(table);
-
tlb_flush_pgtable(tlb, address);
- pgtable_page_dtor(page);
- pgtable_free_tlb(tlb, page, 0);
+ pgtable_page_dtor(table);
+ pgtable_free_tlb(tlb, page_address(table), 0);
}
#else /* if CONFIG_PPC_64K_PAGES */
diff -Nur linux/arch/powerpc/include/asm/ppc_asm.h rpi/arch/powerpc/include/asm/ppc_asm.h
--- linux/arch/powerpc/include/asm/ppc_asm.h 2014-05-29 12:18:17.888557166 +0900
+++ rpi/arch/powerpc/include/asm/ppc_asm.h 2014-05-29 11:49:11.314905463 +0900
@@ -438,6 +438,8 @@
cmpwi dest,0; \
beq- 90b; \
END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)
+#elif defined(CONFIG_8xx)
+#define MFTB(dest) mftb dest
#else
#define MFTB(dest) mfspr dest, SPRN_TBRL
#endif
@@ -478,13 +480,6 @@
std ra,TASKTHREADPPR(rb); \
END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945)
-#define RESTORE_PPR(ra, rb) \
-BEGIN_FTR_SECTION_NESTED(946) \
- ld ra,PACACURRENT(r13); \
- ld rb,TASKTHREADPPR(ra); \
- mtspr SPRN_PPR,rb; /* Restore PPR */ \
-END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
-
#endif
/*
diff -Nur linux/arch/powerpc/include/asm/ptrace.h rpi/arch/powerpc/include/asm/ptrace.h
--- linux/arch/powerpc/include/asm/ptrace.h 2014-05-29 12:18:17.890557153 +0900
+++ rpi/arch/powerpc/include/asm/ptrace.h 2014-05-29 11:49:11.318905429 +0900
@@ -28,11 +28,23 @@
#ifdef __powerpc64__
+/*
+ * Size of redzone that userspace is allowed to use below the stack
+ * pointer. This is 288 in the 64-bit big-endian ELF ABI, and 512 in
+ * the new ELFv2 little-endian ABI, so we allow the larger amount.
+ *
+ * For kernel code we allow a 288-byte redzone, in order to conserve
+ * kernel stack space; gcc currently only uses 288 bytes, and will
+ * hopefully allow explicit control of the redzone size in future.
+ */
+#define USER_REDZONE_SIZE 512
+#define KERNEL_REDZONE_SIZE 288
+
#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
#define STACK_FRAME_LR_SAVE 2 /* Location of LR in stack frame */
#define STACK_FRAME_REGS_MARKER ASM_CONST(0x7265677368657265)
#define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + \
- STACK_FRAME_OVERHEAD + 288)
+ STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
#define STACK_FRAME_MARKER 12
/* Size of dummy stack frame allocated when calling signal handler. */
@@ -41,6 +53,8 @@
#else /* __powerpc64__ */
+#define USER_REDZONE_SIZE 0
+#define KERNEL_REDZONE_SIZE 0
#define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */
#define STACK_FRAME_LR_SAVE 1 /* Location of LR in stack frame */
#define STACK_FRAME_REGS_MARKER ASM_CONST(0x72656773)
diff -Nur linux/arch/powerpc/include/asm/reg.h rpi/arch/powerpc/include/asm/reg.h
--- linux/arch/powerpc/include/asm/reg.h 2014-05-29 12:18:17.891557147 +0900
+++ rpi/arch/powerpc/include/asm/reg.h 2014-05-29 11:49:11.319905421 +0900
@@ -208,6 +208,7 @@
#define SPRN_ACOP 0x1F /* Available Coprocessor Register */
#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
#define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */
+#define TEXASR_FS __MASK(63-36) /* Transaction Failure Summary */
#define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */
#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
#define SPRN_CTRLF 0x088
@@ -1154,12 +1155,19 @@
#else /* __powerpc64__ */
+#if defined(CONFIG_8xx)
+#define mftbl() ({unsigned long rval; \
+ asm volatile("mftbl %0" : "=r" (rval)); rval;})
+#define mftbu() ({unsigned long rval; \
+ asm volatile("mftbu %0" : "=r" (rval)); rval;})
+#else
#define mftbl() ({unsigned long rval; \
asm volatile("mfspr %0, %1" : "=r" (rval) : \
"i" (SPRN_TBRL)); rval;})
#define mftbu() ({unsigned long rval; \
asm volatile("mfspr %0, %1" : "=r" (rval) : \
"i" (SPRN_TBRU)); rval;})
+#endif
#endif /* !__powerpc64__ */
#define mttbl(v) asm volatile("mttbl %0":: "r"(v))
diff -Nur linux/arch/powerpc/include/asm/timex.h rpi/arch/powerpc/include/asm/timex.h
--- linux/arch/powerpc/include/asm/timex.h 2014-05-29 12:18:17.897557109 +0900
+++ rpi/arch/powerpc/include/asm/timex.h 2014-05-29 11:49:11.329905337 +0900
@@ -29,7 +29,11 @@
ret = 0;
__asm__ __volatile__(
+#ifdef CONFIG_8xx
+ "97: mftb %0\n"
+#else
"97: mfspr %0, %2\n"
+#endif
"99:\n"
".section __ftr_fixup,\"a\"\n"
".align 2\n"
@@ -41,7 +45,11 @@
" .long 0\n"
" .long 0\n"
".previous"
+#ifdef CONFIG_8xx
+ : "=r" (ret) : "i" (CPU_FTR_601));
+#else
: "=r" (ret) : "i" (CPU_FTR_601), "i" (SPRN_TBRL));
+#endif
return ret;
#endif
}
diff -Nur linux/arch/powerpc/include/asm/topology.h rpi/arch/powerpc/include/asm/topology.h
--- linux/arch/powerpc/include/asm/topology.h 2014-05-29 12:18:17.897557109 +0900
+++ rpi/arch/powerpc/include/asm/topology.h 2014-05-29 11:49:11.329905337 +0900
@@ -22,7 +22,15 @@
static inline int cpu_to_node(int cpu)
{
- return numa_cpu_lookup_table[cpu];
+ int nid;
+
+ nid = numa_cpu_lookup_table[cpu];
+
+ /*
+ * During early boot, the numa-cpu lookup table might not have been
+ * setup for all CPUs yet. In such cases, default to node 0.
+ */
+ return (nid < 0) ? 0 : nid;
}
#define parent_node(node) (node)
diff -Nur linux/arch/powerpc/kernel/cacheinfo.c rpi/arch/powerpc/kernel/cacheinfo.c
--- linux/arch/powerpc/kernel/cacheinfo.c 2014-05-29 12:18:17.904557065 +0900
+++ rpi/arch/powerpc/kernel/cacheinfo.c 2014-05-29 11:49:11.345905203 +0900
@@ -794,6 +794,9 @@
{
remove_index_dirs(cache_dir);
+ /* Remove cache dir from sysfs */
+ kobject_del(cache_dir->kobj);
+
kobject_put(cache_dir->kobj);
kfree(cache_dir);
diff -Nur linux/arch/powerpc/kernel/crash_dump.c rpi/arch/powerpc/kernel/crash_dump.c
--- linux/arch/powerpc/kernel/crash_dump.c 2014-05-29 12:18:17.906557053 +0900
+++ rpi/arch/powerpc/kernel/crash_dump.c 2014-05-29 11:49:11.348905178 +0900
@@ -98,17 +98,19 @@
size_t csize, unsigned long offset, int userbuf)
{
void *vaddr;
+ phys_addr_t paddr;
if (!csize)
return 0;
csize = min_t(size_t, csize, PAGE_SIZE);
+ paddr = pfn << PAGE_SHIFT;
- if ((min_low_pfn < pfn) && (pfn < max_pfn)) {
- vaddr = __va(pfn << PAGE_SHIFT);
+ if (memblock_is_region_memory(paddr, csize)) {
+ vaddr = __va(paddr);
csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
} else {
- vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
+ vaddr = __ioremap(paddr, PAGE_SIZE, 0);
csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
iounmap(vaddr);
}
diff -Nur linux/arch/powerpc/kernel/eeh.c rpi/arch/powerpc/kernel/eeh.c
--- linux/arch/powerpc/kernel/eeh.c 2014-05-29 12:18:17.908557040 +0900
+++ rpi/arch/powerpc/kernel/eeh.c 2014-05-29 11:49:11.350905161 +0900
@@ -687,6 +687,15 @@
for (i = 0; i < 16; i++)
eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]);
+
+ /*
+ * For PCI bridges including root port, we need enable bus
+ * master explicitly. Otherwise, it can't fetch IODA table
+ * entries correctly. So we cache the bit in advance so that
+ * we can restore it after reset, either PHB range or PE range.
+ */
+ if (edev->mode & EEH_DEV_BRIDGE)
+ edev->config_space[1] |= PCI_COMMAND_MASTER;
}
/**
diff -Nur linux/arch/powerpc/kernel/eeh_driver.c rpi/arch/powerpc/kernel/eeh_driver.c
--- linux/arch/powerpc/kernel/eeh_driver.c 2014-05-29 12:18:17.908557040 +0900
+++ rpi/arch/powerpc/kernel/eeh_driver.c 2014-05-29 11:49:11.351905153 +0900
@@ -626,84 +626,90 @@
{
struct eeh_pe *pe, *phb_pe;
struct pci_bus *bus;
- struct pci_controller *hose, *tmp;
+ struct pci_controller *hose;
unsigned long flags;
- int rc = 0;
+ int rc;
- /*
- * The return value from next_error() has been classified as follows.
- * It might be good to enumerate them. However, next_error() is only
- * supported by PowerNV platform for now. So it would be fine to use
- * integer directly:
- *
- * 4 - Dead IOC 3 - Dead PHB
- * 2 - Fenced PHB 1 - Frozen PE
- * 0 - No error found
- *
- */
- rc = eeh_ops->next_error(&pe);
- if (rc <= 0)
- return;
-
- switch (rc) {
- case 4:
- /* Mark all PHBs in dead state */
- eeh_serialize_lock(&flags);
- list_for_each_entry_safe(hose, tmp,
- &hose_list, list_node) {
- phb_pe = eeh_phb_pe_get(hose);
- if (!phb_pe) continue;
- eeh_pe_state_mark(phb_pe,
- EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+ do {
+ rc = eeh_ops->next_error(&pe);
+
+ switch (rc) {
+ case EEH_NEXT_ERR_DEAD_IOC:
+ /* Mark all PHBs in dead state */
+ eeh_serialize_lock(&flags);
+
+ /* Purge all events */
+ eeh_remove_event(NULL);
+
+ list_for_each_entry(hose, &hose_list, list_node) {
+ phb_pe = eeh_phb_pe_get(hose);
+ if (!phb_pe) continue;
+
+ eeh_pe_state_mark(phb_pe,
+ EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+ }
+
+ eeh_serialize_unlock(flags);
+
+ break;
+ case EEH_NEXT_ERR_FROZEN_PE:
+ case EEH_NEXT_ERR_FENCED_PHB:
+ case EEH_NEXT_ERR_DEAD_PHB:
+ /* Mark the PE in fenced state */
+ eeh_serialize_lock(&flags);
+
+ /* Purge all events of the PHB */
+ eeh_remove_event(pe);
+
+ if (rc == EEH_NEXT_ERR_DEAD_PHB)
+ eeh_pe_state_mark(pe,
+ EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
+ else
+ eeh_pe_state_mark(pe,
+ EEH_PE_ISOLATED | EEH_PE_RECOVERING);
+
+ eeh_serialize_unlock(flags);
+
+ break;
+ case EEH_NEXT_ERR_NONE:
+ return;
+ default:
+ pr_warn("%s: Invalid value %d from next_error()\n",
+ __func__, rc);
+ return;
}
- eeh_serialize_unlock(flags);
- /* Purge all events */
- eeh_remove_event(NULL);
- break;
- case 3:
- case 2:
- case 1:
- /* Mark the PE in fenced state */
- eeh_serialize_lock(&flags);
- if (rc == 3)
- eeh_pe_state_mark(pe,
- EEH_PE_ISOLATED | EEH_PE_PHB_DEAD);
- else
- eeh_pe_state_mark(pe,
- EEH_PE_ISOLATED | EEH_PE_RECOVERING);
- eeh_serialize_unlock(flags);
-
- /* Purge all events of the PHB */
- eeh_remove_event(pe);
- break;
- default:
- pr_err("%s: Invalid value %d from next_error()\n",
- __func__, rc);
- return;
- }
-
- /*
- * For fenced PHB and frozen PE, it's handled as normal
- * event. We have to remove the affected PHBs for dead
- * PHB and IOC
- */
- if (rc == 2 || rc == 1)
- eeh_handle_normal_event(pe);
- else {
- list_for_each_entry_safe(hose, tmp,
- &hose_list, list_node) {
- phb_pe = eeh_phb_pe_get(hose);
- if (!phb_pe || !(phb_pe->state & EEH_PE_PHB_DEAD))
- continue;
-
- bus = eeh_pe_bus_get(phb_pe);
- /* Notify all devices that they're about to go down. */
- eeh_pe_dev_traverse(pe, eeh_report_failure, NULL);
- pcibios_remove_pci_devices(bus);
+ /*
+ * For fenced PHB and frozen PE, it's handled as normal
+ * event. We have to remove the affected PHBs for dead
+ * PHB and IOC
+ */
+ if (rc == EEH_NEXT_ERR_FROZEN_PE ||
+ rc == EEH_NEXT_ERR_FENCED_PHB) {
+ eeh_handle_normal_event(pe);
+ } else {
+ list_for_each_entry(hose, &hose_list, list_node) {
+ phb_pe = eeh_phb_pe_get(hose);
+ if (!phb_pe ||
+ !(phb_pe->state & EEH_PE_PHB_DEAD))
+ continue;
+
+ /* Notify all devices to be down */
+ bus = eeh_pe_bus_get(phb_pe);
+ eeh_pe_dev_traverse(pe,
+ eeh_report_failure, NULL);
+ pcibios_remove_pci_devices(bus);
+ }
}
- }
+
+ /*
+ * If we have detected dead IOC, we needn't proceed
+ * any more since all PHBs would have been removed
+ */
+ if (rc == EEH_NEXT_ERR_DEAD_IOC)
+ break;
+ } while (rc != EEH_NEXT_ERR_NONE);
}
/**
diff -Nur linux/arch/powerpc/kernel/entry_64.S rpi/arch/powerpc/kernel/entry_64.S
--- linux/arch/powerpc/kernel/entry_64.S 2014-05-29 12:18:17.910557028 +0900
+++ rpi/arch/powerpc/kernel/entry_64.S 2014-05-29 11:49:11.354905127 +0900
@@ -820,6 +820,12 @@
andi. r0,r3,MSR_RI
beq- unrecov_restore
+ /* Load PPR from thread struct before we clear MSR:RI */
+BEGIN_FTR_SECTION
+ ld r2,PACACURRENT(r13)
+ ld r2,TASKTHREADPPR(r2)
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
+
/*
* Clear RI before restoring r13. If we are returning to
* userspace and we take an exception after restoring r13,
@@ -840,8 +846,10 @@
*/
andi. r0,r3,MSR_PR
beq 1f
+BEGIN_FTR_SECTION
+ mtspr SPRN_PPR,r2 /* Restore PPR */
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
ACCOUNT_CPU_USER_EXIT(r2, r4)
- RESTORE_PPR(r2, r4)
REST_GPR(13, r1)
1:
mtspr SPRN_SRR1,r3
diff -Nur linux/arch/powerpc/kernel/head_64.S rpi/arch/powerpc/kernel/head_64.S
--- linux/arch/powerpc/kernel/head_64.S 2014-05-29 12:18:17.915556996 +0900
+++ rpi/arch/powerpc/kernel/head_64.S 2014-05-29 11:49:11.360905077 +0900
@@ -467,6 +467,7 @@
mtctr r8
bctr
+.balign 8
p_end: .llong _end - _stext
4: /* Now copy the rest of the kernel up to _end */
diff -Nur linux/arch/powerpc/kernel/misc_32.S rpi/arch/powerpc/kernel/misc_32.S
--- linux/arch/powerpc/kernel/misc_32.S 2014-05-29 12:18:17.925556934 +0900
+++ rpi/arch/powerpc/kernel/misc_32.S 2014-05-29 11:49:11.369905002 +0900
@@ -57,11 +57,14 @@
mtlr r0
blr
+/*
+ * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp);
+ */
_GLOBAL(call_do_irq)
mflr r0
stw r0,4(r1)
lwz r10,THREAD+KSP_LIMIT(r2)
- addi r11,r3,THREAD_INFO_GAP
+ addi r11,r4,THREAD_INFO_GAP
stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
mr r1,r4
stw r10,8(r1)
diff -Nur linux/arch/powerpc/kernel/process.c rpi/arch/powerpc/kernel/process.c
--- linux/arch/powerpc/kernel/process.c 2014-05-29 12:18:17.930556903 +0900
+++ rpi/arch/powerpc/kernel/process.c 2014-05-29 11:49:11.376904943 +0900
@@ -525,6 +525,31 @@
tm_save_sprs(thr);
}
+extern void __tm_recheckpoint(struct thread_struct *thread,
+ unsigned long orig_msr);
+
+void tm_recheckpoint(struct thread_struct *thread,
+ unsigned long orig_msr)
+{
+ unsigned long flags;
+
+ /* We really can't be interrupted here as the TEXASR registers can't
+ * change and later in the trecheckpoint code, we have a userspace R1.
+ * So let's hard disable over this region.
+ */
+ local_irq_save(flags);
+ hard_irq_disable();
+
+ /* The TM SPRs are restored here, so that TEXASR.FS can be set
+ * before the trecheckpoint and no explosion occurs.
+ */
+ tm_restore_sprs(thread);
+
+ __tm_recheckpoint(thread, orig_msr);
+
+ local_irq_restore(flags);
+}
+
static inline void tm_recheckpoint_new_task(struct task_struct *new)
{
unsigned long msr;
@@ -543,13 +568,10 @@
if (!new->thread.regs)
return;
- /* The TM SPRs are restored here, so that TEXASR.FS can be set
- * before the trecheckpoint and no explosion occurs.
- */
- tm_restore_sprs(&new->thread);
-
- if (!MSR_TM_ACTIVE(new->thread.regs->msr))
+ if (!MSR_TM_ACTIVE(new->thread.regs->msr)){
+ tm_restore_sprs(&new->thread);
return;
+ }
msr = new->thread.tm_orig_msr;
/* Recheckpoint to restore original checkpointed register state. */
TM_DEBUG("*** tm_recheckpoint of pid %d "
@@ -928,6 +950,15 @@
flush_altivec_to_thread(src);
flush_vsx_to_thread(src);
flush_spe_to_thread(src);
+ /*
+ * Flush TM state out so we can copy it. __switch_to_tm() does this
+ * flush but it removes the checkpointed state from the current CPU and
+ * transitions the CPU out of TM mode. Hence we need to call
+ * tm_recheckpoint_new_task() (on the same task) to restore the
+ * checkpointed state back and the TM mode.
+ */
+ __switch_to_tm(src);
+ tm_recheckpoint_new_task(src);
*dst = *src;
diff -Nur linux/arch/powerpc/kernel/reloc_64.S rpi/arch/powerpc/kernel/reloc_64.S
--- linux/arch/powerpc/kernel/reloc_64.S 2014-05-29 12:18:18.006556427 +0900
+++ rpi/arch/powerpc/kernel/reloc_64.S 2014-05-29 11:49:11.381904901 +0900
@@ -81,6 +81,7 @@
6: blr
+.balign 8
p_dyn: .llong __dynamic_start - 0b
p_rela: .llong __rela_dyn_start - 0b
p_st: .llong _stext - 0b
diff -Nur linux/arch/powerpc/kernel/signal_32.c rpi/arch/powerpc/kernel/signal_32.c
--- linux/arch/powerpc/kernel/signal_32.c 2014-05-29 12:18:18.038556227 +0900
+++ rpi/arch/powerpc/kernel/signal_32.c 2014-05-29 11:49:11.409904666 +0900
@@ -445,6 +445,12 @@
#endif /* CONFIG_ALTIVEC */
if (copy_fpr_to_user(&frame->mc_fregs, current))
return 1;
+
+ /*
+ * Clear the MSR VSX bit to indicate there is no valid state attached
+ * to this context, except in the specific case below where we set it.
+ */
+ msr &= ~MSR_VSX;
#ifdef CONFIG_VSX
/*
* Copy VSR 0-31 upper half from thread_struct to local
@@ -866,6 +872,8 @@
* transactional versions should be loaded.
*/
tm_enable();
+ /* Make sure the transaction is marked as failed */
+ current->thread.tm_texasr |= TEXASR_FS;
/* This loads the checkpointed FP/VEC state, if used */
tm_recheckpoint(&current->thread, msr);
/* Get the top half of the MSR */
diff -Nur linux/arch/powerpc/kernel/signal_64.c rpi/arch/powerpc/kernel/signal_64.c
--- linux/arch/powerpc/kernel/signal_64.c 2014-05-29 12:18:18.039556220 +0900
+++ rpi/arch/powerpc/kernel/signal_64.c 2014-05-29 11:49:11.409904666 +0900
@@ -65,8 +65,8 @@
struct siginfo __user *pinfo;
void __user *puc;
struct siginfo info;
- /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
- char abigap[288];
+ /* New 64 bit little-endian ABI allows redzone of 512 bytes below sp */
+ char abigap[USER_REDZONE_SIZE];
} __attribute__ ((aligned (16)));
static const char fmt32[] = KERN_INFO \
@@ -121,6 +121,12 @@
flush_fp_to_thread(current);
/* copy fpr regs and fpscr */
err |= copy_fpr_to_user(&sc->fp_regs, current);
+
+ /*
+ * Clear the MSR VSX bit to indicate there is no valid state attached
+ * to this context, except in the specific case below where we set it.
+ */
+ msr &= ~MSR_VSX;
#ifdef CONFIG_VSX
/*
* Copy VSX low doubleword to local buffer for formatting,
@@ -513,6 +519,8 @@
}
#endif
tm_enable();
+ /* Make sure the transaction is marked as failed */
+ current->thread.tm_texasr |= TEXASR_FS;
/* This loads the checkpointed FP/VEC state, if used */
tm_recheckpoint(&current->thread, msr);
diff -Nur linux/arch/powerpc/kernel/time.c rpi/arch/powerpc/kernel/time.c
--- linux/arch/powerpc/kernel/time.c 2014-05-29 12:18:18.043556195 +0900
+++ rpi/arch/powerpc/kernel/time.c 2014-05-29 11:49:11.414904624 +0900
@@ -213,8 +213,6 @@
if (i == be64_to_cpu(vpa->dtl_idx))
return 0;
while (i < be64_to_cpu(vpa->dtl_idx)) {
- if (dtl_consumer)
- dtl_consumer(dtl, i);
dtb = be64_to_cpu(dtl->timebase);
tb_delta = be32_to_cpu(dtl->enqueue_to_dispatch_time) +
be32_to_cpu(dtl->ready_to_enqueue_time);
@@ -227,6 +225,8 @@
}
if (dtb > stop_tb)
break;
+ if (dtl_consumer)
+ dtl_consumer(dtl, i);
stolen += tb_delta;
++i;
++dtl;
diff -Nur linux/arch/powerpc/kernel/tm.S rpi/arch/powerpc/kernel/tm.S
--- linux/arch/powerpc/kernel/tm.S 2014-05-29 12:18:18.044556189 +0900
+++ rpi/arch/powerpc/kernel/tm.S 2014-05-29 11:49:11.414904624 +0900
@@ -306,7 +306,7 @@
* Call with IRQs off, stacks get all out of sync for
* some periods in here!
*/
-_GLOBAL(tm_recheckpoint)
+_GLOBAL(__tm_recheckpoint)
mfcr r5
mflr r0
std r5, 8(r1)
diff -Nur linux/arch/powerpc/kernel/vdso32/gettimeofday.S rpi/arch/powerpc/kernel/vdso32/gettimeofday.S
--- linux/arch/powerpc/kernel/vdso32/gettimeofday.S 2014-05-29 12:18:18.048556164 +0900
+++ rpi/arch/powerpc/kernel/vdso32/gettimeofday.S 2014-05-29 11:49:11.418904591 +0900
@@ -232,9 +232,15 @@
lwz r6,(CFG_TB_ORIG_STAMP+4)(r9)
/* Get a stable TB value */
+#ifdef CONFIG_8xx
+2: mftbu r3
+ mftbl r4
+ mftbu r0
+#else
2: mfspr r3, SPRN_TBRU
mfspr r4, SPRN_TBRL
mfspr r0, SPRN_TBRU
+#endif
cmplw cr0,r3,r0
bne- 2b
diff -Nur linux/arch/powerpc/kernel/vio.c rpi/arch/powerpc/kernel/vio.c
--- linux/arch/powerpc/kernel/vio.c 2014-05-29 12:18:18.054556127 +0900
+++ rpi/arch/powerpc/kernel/vio.c 2014-05-29 11:49:11.422904557 +0900
@@ -1531,12 +1531,12 @@
dn = dev->of_node;
if (!dn) {
- strcat(buf, "\n");
+ strcpy(buf, "\n");
return strlen(buf);
}
cp = of_get_property(dn, "compatible", NULL);
if (!cp) {
- strcat(buf, "\n");
+ strcpy(buf, "\n");
return strlen(buf);
}
diff -Nur linux/arch/powerpc/kvm/book3s_64_mmu_hv.c rpi/arch/powerpc/kvm/book3s_64_mmu_hv.c
--- linux/arch/powerpc/kvm/book3s_64_mmu_hv.c 2014-05-29 12:18:18.060556089 +0900
+++ rpi/arch/powerpc/kvm/book3s_64_mmu_hv.c 2014-05-29 11:49:11.426904524 +0900
@@ -473,11 +473,14 @@
slb_v = vcpu->kvm->arch.vrma_slb_v;
}
+ preempt_disable();
/* Find the HPTE in the hash table */
index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
HPTE_V_VALID | HPTE_V_ABSENT);
- if (index < 0)
+ if (index < 0) {
+ preempt_enable();
return -ENOENT;
+ }
hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
v = hptep[0] & ~HPTE_V_HVLOCK;
gr = kvm->arch.revmap[index].guest_rpte;
@@ -485,6 +488,7 @@
/* Unlock the HPTE */
asm volatile("lwsync" : : : "memory");
hptep[0] = v;
+ preempt_enable();
gpte->eaddr = eaddr;
gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff);
diff -Nur linux/arch/powerpc/kvm/book3s_hv.c rpi/arch/powerpc/kvm/book3s_hv.c
--- linux/arch/powerpc/kvm/book3s_hv.c 2014-05-29 12:18:18.062556077 +0900
+++ rpi/arch/powerpc/kvm/book3s_hv.c 2014-05-29 11:49:11.428904507 +0900
@@ -82,10 +82,13 @@
/* CPU points to the first thread of the core */
if (cpu != me && cpu >= 0 && cpu < nr_cpu_ids) {
+#ifdef CONFIG_KVM_XICS
int real_cpu = cpu + vcpu->arch.ptid;
if (paca[real_cpu].kvm_hstate.xics_phys)
xics_wake_cpu(real_cpu);
- else if (cpu_online(cpu))
+ else
+#endif
+ if (cpu_online(cpu))
smp_send_reschedule(cpu);
}
put_cpu();
@@ -1089,7 +1092,9 @@
smp_wmb();
#if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
if (vcpu->arch.ptid) {
+#ifdef CONFIG_KVM_XICS
xics_wake_cpu(cpu);
+#endif
++vc->n_woken;
}
#endif
diff -Nur linux/arch/powerpc/kvm/book3s_hv_rm_mmu.c rpi/arch/powerpc/kvm/book3s_hv_rm_mmu.c
--- linux/arch/powerpc/kvm/book3s_hv_rm_mmu.c 2014-05-29 12:18:18.064556064 +0900
+++ rpi/arch/powerpc/kvm/book3s_hv_rm_mmu.c 2014-05-29 11:49:11.429904499 +0900
@@ -749,6 +749,10 @@
20, /* 1M, unsupported */
};
+/* When called from virtmode, this func should be protected by
+ * preempt_disable(), otherwise, the holding of HPTE_V_HVLOCK
+ * can trigger deadlock issue.
+ */
long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
unsigned long valid)
{
diff -Nur linux/arch/powerpc/kvm/e500_mmu.c rpi/arch/powerpc/kvm/e500_mmu.c
--- linux/arch/powerpc/kvm/e500_mmu.c 2014-05-29 12:18:18.093555883 +0900
+++ rpi/arch/powerpc/kvm/e500_mmu.c 2014-05-29 11:49:11.442904390 +0900
@@ -127,7 +127,7 @@
}
static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
- unsigned int eaddr, int as)
+ gva_t eaddr, int as)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
unsigned int victim, tsized;
diff -Nur linux/arch/powerpc/mm/gup.c rpi/arch/powerpc/mm/gup.c
--- linux/arch/powerpc/mm/gup.c 2014-05-29 12:18:18.103555820 +0900
+++ rpi/arch/powerpc/mm/gup.c 2014-05-29 11:49:11.461904231 +0900
@@ -123,6 +123,7 @@
struct mm_struct *mm = current->mm;
unsigned long addr, len, end;
unsigned long next;
+ unsigned long flags;
pgd_t *pgdp;
int nr = 0;
@@ -156,7 +157,7 @@
* So long as we atomically load page table pointers versus teardown,
* we can follow the address down to the the page and take a ref on it.
*/
- local_irq_disable();
+ local_irq_save(flags);
pgdp = pgd_offset(mm, addr);
do {
@@ -179,7 +180,7 @@
break;
} while (pgdp++, addr = next, addr != end);
- local_irq_enable();
+ local_irq_restore(flags);
return nr;
}
diff -Nur linux/arch/powerpc/mm/numa.c rpi/arch/powerpc/mm/numa.c
--- linux/arch/powerpc/mm/numa.c 2014-05-29 12:18:18.110555776 +0900
+++ rpi/arch/powerpc/mm/numa.c 2014-05-29 11:49:11.468904172 +0900
@@ -31,6 +31,8 @@
#include <asm/sparsemem.h>
#include <asm/prom.h>
#include <asm/smp.h>
+#include <asm/cputhreads.h>
+#include <asm/topology.h>
#include <asm/firmware.h>
#include <asm/paca.h>
#include <asm/hvcall.h>
@@ -152,9 +154,22 @@
}
}
-static void map_cpu_to_node(int cpu, int node)
+static void reset_numa_cpu_lookup_table(void)
+{
+ unsigned int cpu;
+
+ for_each_possible_cpu(cpu)
+ numa_cpu_lookup_table[cpu] = -1;
+}
+
+static void update_numa_cpu_lookup_table(unsigned int cpu, int node)
{
numa_cpu_lookup_table[cpu] = node;
+}
+
+static void map_cpu_to_node(int cpu, int node)
+{
+ update_numa_cpu_lookup_table(cpu, node);
dbg("adding cpu %d to node %d\n", cpu, node);
@@ -522,11 +537,24 @@
*/
static int numa_setup_cpu(unsigned long lcpu)
{
- int nid = 0;
- struct device_node *cpu = of_get_cpu_node(lcpu, NULL);
+ int nid;
+ struct device_node *cpu;
+
+ /*
+ * If a valid cpu-to-node mapping is already available, use it
+ * directly instead of querying the firmware, since it represents
+ * the most recent mapping notified to us by the platform (eg: VPHN).
+ */
+ if ((nid = numa_cpu_lookup_table[lcpu]) >= 0) {
+ map_cpu_to_node(lcpu, nid);
+ return nid;
+ }
+
+ cpu = of_get_cpu_node(lcpu, NULL);
if (!cpu) {
WARN_ON(1);
+ nid = 0;
goto out;
}
@@ -1068,6 +1096,7 @@
*/
setup_node_to_cpumask_map();
+ reset_numa_cpu_lookup_table();
register_cpu_notifier(&ppc64_numa_nb);
cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE,
(void *)(unsigned long)boot_cpuid);
@@ -1446,6 +1475,33 @@
return 0;
}
+static int update_lookup_table(void *data)
+{
+ struct topology_update_data *update;
+
+ if (!data)
+ return -EINVAL;
+
+ /*
+ * Upon topology update, the numa-cpu lookup table needs to be updated
+ * for all threads in the core, including offline CPUs, to ensure that
+ * future hotplug operations respect the cpu-to-node associativity
+ * properly.
+ */
+ for (update = data; update; update = update->next) {
+ int nid, base, j;
+
+ nid = update->new_nid;
+ base = cpu_first_thread_sibling(update->cpu);
+
+ for (j = 0; j < threads_per_core; j++) {
+ update_numa_cpu_lookup_table(base + j, nid);
+ }
+ }
+
+ return 0;
+}
+
/*
* Update the node maps and sysfs entries for each cpu whose home node
* has changed. Returns 1 when the topology has changed, and 0 otherwise.
@@ -1514,6 +1570,14 @@
stop_machine(update_cpu_topology, &updates[0], &updated_cpus);
+ /*
+ * Update the numa-cpu lookup table with the new mappings, even for
+ * offline CPUs. It is best to perform this update from the stop-
+ * machine context.
+ */
+ stop_machine(update_lookup_table, &updates[0],
+ cpumask_of(raw_smp_processor_id()));
+
for (ud = &updates[0]; ud; ud = ud->next) {
unregister_cpu_under_node(ud->cpu, ud->old_nid);
register_cpu_under_node(ud->cpu, ud->new_nid);
diff -Nur linux/arch/powerpc/mm/slice.c rpi/arch/powerpc/mm/slice.c
--- linux/arch/powerpc/mm/slice.c 2014-05-29 12:18:18.112555764 +0900
+++ rpi/arch/powerpc/mm/slice.c 2014-05-29 11:49:11.471904147 +0900
@@ -258,7 +258,7 @@
slice = GET_HIGH_SLICE_INDEX(addr);
*boundary_addr = (slice + end) ?
((slice + end) << SLICE_HIGH_SHIFT) : SLICE_LOW_TOP;
- return !!(available.high_slices & (1u << slice));
+ return !!(available.high_slices & (1ul << slice));
}
}
diff -Nur linux/arch/powerpc/net/bpf_jit_comp.c rpi/arch/powerpc/net/bpf_jit_comp.c
--- linux/arch/powerpc/net/bpf_jit_comp.c 2014-05-29 12:18:18.115555745 +0900
+++ rpi/arch/powerpc/net/bpf_jit_comp.c 2014-05-29 11:49:11.474904122 +0900
@@ -209,10 +209,11 @@
}
PPC_DIVWU(r_A, r_A, r_X);
break;
- case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
+ case BPF_S_ALU_DIV_K: /* A /= K */
+ if (K == 1)
+ break;
PPC_LI32(r_scratch1, K);
- /* Top 32 bits of 64bit result -> A */
- PPC_MULHWU(r_A, r_A, r_scratch1);
+ PPC_DIVWU(r_A, r_A, r_scratch1);
break;
case BPF_S_ALU_AND_X:
ctx->seen |= SEEN_XREG;
diff -Nur linux/arch/powerpc/platforms/512x/mpc512x_shared.c rpi/arch/powerpc/platforms/512x/mpc512x_shared.c
--- linux/arch/powerpc/platforms/512x/mpc512x_shared.c 2014-05-29 12:18:18.121555707 +0900
+++ rpi/arch/powerpc/platforms/512x/mpc512x_shared.c 2014-05-29 11:49:11.490903987 +0900
@@ -303,6 +303,9 @@
diu_ops.release_bootmem = mpc512x_release_bootmem;
}
+#else
+void __init mpc512x_setup_diu(void) { /* EMPTY */ }
+void __init mpc512x_init_diu(void) { /* EMPTY */ }
#endif
void __init mpc512x_init_IRQ(void)
diff -Nur linux/arch/powerpc/platforms/52xx/Kconfig rpi/arch/powerpc/platforms/52xx/Kconfig
--- linux/arch/powerpc/platforms/52xx/Kconfig 2014-05-29 12:18:18.122555701 +0900
+++ rpi/arch/powerpc/platforms/52xx/Kconfig 2014-05-29 11:49:11.490903987 +0900
@@ -57,5 +57,5 @@
config PPC_MPC5200_LPBFIFO
tristate "MPC5200 LocalPlus bus FIFO driver"
- depends on PPC_MPC52xx
+ depends on PPC_MPC52xx && PPC_BESTCOMM
select PPC_BESTCOMM_GEN_BD
diff -Nur linux/arch/powerpc/platforms/powernv/eeh-ioda.c rpi/arch/powerpc/platforms/powernv/eeh-ioda.c
--- linux/arch/powerpc/platforms/powernv/eeh-ioda.c 2014-05-29 12:18:18.321554456 +0900
+++ rpi/arch/powerpc/platforms/powernv/eeh-ioda.c 2014-05-29 11:49:11.553903459 +0900
@@ -463,8 +463,7 @@
static int ioda_eeh_reset(struct eeh_pe *pe, int option)
{
struct pci_controller *hose = pe->phb;
- struct eeh_dev *edev;
- struct pci_dev *dev;
+ struct pci_bus *bus;
int ret;
/*
@@ -493,31 +492,11 @@
if (pe->type & EEH_PE_PHB) {
ret = ioda_eeh_phb_reset(hose, option);
} else {
- if (pe->type & EEH_PE_DEVICE) {
- /*
- * If it's device PE, we didn't refer to the parent
- * PCI bus yet. So we have to figure it out indirectly.
- */
- edev = list_first_entry(&pe->edevs,
- struct eeh_dev, list);
- dev = eeh_dev_to_pci_dev(edev);
- dev = dev->bus->self;
- } else {
- /*
- * If it's bus PE, the parent PCI bus is already there
- * and just pick it up.
- */
- dev = pe->bus->self;
- }
-
- /*
- * Do reset based on the fact that the direct upstream bridge
- * is root bridge (port) or not.
- */
- if (dev->bus->number == 0)
+ bus = eeh_pe_bus_get(pe);
+ if (pci_is_root_bus(bus))
ret = ioda_eeh_root_reset(hose, option);
else
- ret = ioda_eeh_bridge_reset(hose, dev, option);
+ ret = ioda_eeh_bridge_reset(hose, bus->self, option);
}
return ret;
@@ -787,12 +766,12 @@
*/
static int ioda_eeh_next_error(struct eeh_pe **pe)
{
- struct pci_controller *hose, *tmp;
+ struct pci_controller *hose;
struct pnv_phb *phb;
u64 frozen_pe_no;
u16 err_type, severity;
long rc;
- int ret = 1;
+ int ret = EEH_NEXT_ERR_NONE;
/*
* While running here, it's safe to purge the event queue.
@@ -802,7 +781,7 @@
eeh_remove_event(NULL);
opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul);
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+ list_for_each_entry(hose, &hose_list, list_node) {
/*
* If the subordinate PCI buses of the PHB has been
* removed, we needn't take care of it any more.
@@ -841,19 +820,19 @@
switch (err_type) {
case OPAL_EEH_IOC_ERROR:
if (severity == OPAL_EEH_SEV_IOC_DEAD) {
- list_for_each_entry_safe(hose, tmp,
- &hose_list, list_node) {
+ list_for_each_entry(hose, &hose_list,
+ list_node) {
phb = hose->private_data;
phb->eeh_state |= PNV_EEH_STATE_REMOVED;
}
pr_err("EEH: dead IOC detected\n");
- ret = 4;
- goto out;
+ ret = EEH_NEXT_ERR_DEAD_IOC;
} else if (severity == OPAL_EEH_SEV_INF) {
pr_info("EEH: IOC informative error "
"detected\n");
ioda_eeh_hub_diag(hose);
+ ret = EEH_NEXT_ERR_NONE;
}
break;
@@ -865,21 +844,20 @@
pr_err("EEH: dead PHB#%x detected\n",
hose->global_number);
phb->eeh_state |= PNV_EEH_STATE_REMOVED;
- ret = 3;
- goto out;
+ ret = EEH_NEXT_ERR_DEAD_PHB;
} else if (severity == OPAL_EEH_SEV_PHB_FENCED) {
if (ioda_eeh_get_phb_pe(hose, pe))
break;
pr_err("EEH: fenced PHB#%x detected\n",
hose->global_number);
- ret = 2;
- goto out;
+ ret = EEH_NEXT_ERR_FENCED_PHB;
} else if (severity == OPAL_EEH_SEV_INF) {
pr_info("EEH: PHB#%x informative error "
"detected\n",
hose->global_number);
ioda_eeh_phb_diag(hose);
+ ret = EEH_NEXT_ERR_NONE;
}
break;
@@ -889,13 +867,23 @@
pr_err("EEH: Frozen PE#%x on PHB#%x detected\n",
(*pe)->addr, (*pe)->phb->global_number);
- ret = 1;
- goto out;
+ ret = EEH_NEXT_ERR_FROZEN_PE;
+ break;
+ default:
+ pr_warn("%s: Unexpected error type %d\n",
+ __func__, err_type);
}
+
+ /*
+ * If we have no errors on the specific PHB or only
+ * informative error there, we continue poking it.
+ * Otherwise, we need actions to be taken by upper
+ * layer.
+ */
+ if (ret > EEH_NEXT_ERR_INF)
+ break;
}
- ret = 0;
-out:
return ret;
}
diff -Nur linux/arch/powerpc/platforms/powernv/pci-ioda.c rpi/arch/powerpc/platforms/powernv/pci-ioda.c
--- linux/arch/powerpc/platforms/powernv/pci-ioda.c 2014-05-29 12:18:18.327554418 +0900
+++ rpi/arch/powerpc/platforms/powernv/pci-ioda.c 2014-05-29 11:49:11.556903434 +0900
@@ -153,13 +153,23 @@
rid_end = pe->rid + 1;
}
- /* Associate PE in PELT */
+ /*
+ * Associate PE in PELT. We need add the PE into the
+ * corresponding PELT-V as well. Otherwise, the error
+ * originated from the PE might contribute to other
+ * PEs.
+ */
rc = opal_pci_set_pe(phb->opal_id, pe->pe_number, pe->rid,
bcomp, dcomp, fcomp, OPAL_MAP_PE);
if (rc) {
pe_err(pe, "OPAL error %ld trying to setup PELT table\n", rc);
return -ENXIO;
}
+
+ rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number,
+ pe->pe_number, OPAL_ADD_PE_TO_DOMAIN);
+ if (rc)
+ pe_warn(pe, "OPAL error %d adding self to PELTV\n", rc);
opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number,
OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
diff -Nur linux/arch/powerpc/platforms/pseries/hotplug-cpu.c rpi/arch/powerpc/platforms/pseries/hotplug-cpu.c
--- linux/arch/powerpc/platforms/pseries/hotplug-cpu.c 2014-05-29 12:18:18.334554374 +0900
+++ rpi/arch/powerpc/platforms/pseries/hotplug-cpu.c 2014-05-29 11:49:11.566903350 +0900
@@ -35,12 +35,7 @@
#include "offline_states.h"
/* This version can't take the spinlock, because it never returns */
-static struct rtas_args rtas_stop_self_args = {
- .token = RTAS_UNKNOWN_SERVICE,
- .nargs = 0,
- .nret = 1,
- .rets = &rtas_stop_self_args.args[0],
-};
+static int rtas_stop_self_token = RTAS_UNKNOWN_SERVICE;
static DEFINE_PER_CPU(enum cpu_state_vals, preferred_offline_state) =
CPU_STATE_OFFLINE;
@@ -93,15 +88,20 @@
static void rtas_stop_self(void)
{
- struct rtas_args *args = &rtas_stop_self_args;
+ struct rtas_args args = {
+ .token = cpu_to_be32(rtas_stop_self_token),
+ .nargs = 0,
+ .nret = 1,
+ .rets = &args.args[0],
+ };
local_irq_disable();
- BUG_ON(args->token == RTAS_UNKNOWN_SERVICE);
+ BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
printk("cpu %u (hwid %u) Ready to die...\n",
smp_processor_id(), hard_smp_processor_id());
- enter_rtas(__pa(args));
+ enter_rtas(__pa(&args));
panic("Alas, I survived.\n");
}
@@ -392,10 +392,10 @@
}
}
- rtas_stop_self_args.token = rtas_token("stop-self");
+ rtas_stop_self_token = rtas_token("stop-self");
qcss_tok = rtas_token("query-cpu-stopped-state");
- if (rtas_stop_self_args.token == RTAS_UNKNOWN_SERVICE ||
+ if (rtas_stop_self_token == RTAS_UNKNOWN_SERVICE ||
qcss_tok == RTAS_UNKNOWN_SERVICE) {
printk(KERN_INFO "CPU Hotplug not supported by firmware "
"- disabling.\n");
diff -Nur linux/arch/s390/appldata/appldata_base.c rpi/arch/s390/appldata/appldata_base.c
--- linux/arch/s390/appldata/appldata_base.c 2014-05-29 12:18:18.379554093 +0900
+++ rpi/arch/s390/appldata/appldata_base.c 2014-05-29 11:49:11.612902965 +0900
@@ -527,6 +527,7 @@
{
int rc;
+ init_virt_timer(&appldata_timer);
appldata_timer.function = appldata_timer_function;
appldata_timer.data = (unsigned long) &appldata_work;
diff -Nur linux/arch/s390/crypto/aes_s390.c rpi/arch/s390/crypto/aes_s390.c
--- linux/arch/s390/crypto/aes_s390.c 2014-05-29 12:18:18.380554087 +0900
+++ rpi/arch/s390/crypto/aes_s390.c 2014-05-29 11:49:11.615902940 +0900
@@ -25,6 +25,7 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/spinlock.h>
#include "crypt_s390.h"
#define AES_KEYLEN_128 1
@@ -32,10 +33,10 @@
#define AES_KEYLEN_256 4
static u8 *ctrblk;
+static DEFINE_SPINLOCK(ctrblk_lock);
static char keylen_flag;
struct s390_aes_ctx {
- u8 iv[AES_BLOCK_SIZE];
u8 key[AES_MAX_KEY_SIZE];
long enc;
long dec;
@@ -56,8 +57,7 @@
struct s390_xts_ctx {
u8 key[32];
- u8 xts_param[16];
- struct pcc_param pcc;
+ u8 pcc_key[32];
long enc;
long dec;
int key_len;
@@ -441,30 +441,36 @@
return aes_set_key(tfm, in_key, key_len);
}
-static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
+static int cbc_aes_crypt(struct blkcipher_desc *desc, long func,
struct blkcipher_walk *walk)
{
+ struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
int ret = blkcipher_walk_virt(desc, walk);
unsigned int nbytes = walk->nbytes;
+ struct {
+ u8 iv[AES_BLOCK_SIZE];
+ u8 key[AES_MAX_KEY_SIZE];
+ } param;
if (!nbytes)
goto out;
- memcpy(param, walk->iv, AES_BLOCK_SIZE);
+ memcpy(param.iv, walk->iv, AES_BLOCK_SIZE);
+ memcpy(param.key, sctx->key, sctx->key_len);
do {
/* only use complete blocks */
unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
u8 *out = walk->dst.virt.addr;
u8 *in = walk->src.virt.addr;
- ret = crypt_s390_kmc(func, param, out, in, n);
+ ret = crypt_s390_kmc(func, &param, out, in, n);
if (ret < 0 || ret != n)
return -EIO;
nbytes &= AES_BLOCK_SIZE - 1;
ret = blkcipher_walk_done(desc, walk, nbytes);
} while ((nbytes = walk->nbytes));
- memcpy(walk->iv, param, AES_BLOCK_SIZE);
+ memcpy(walk->iv, param.iv, AES_BLOCK_SIZE);
out:
return ret;
@@ -481,7 +487,7 @@
return fallback_blk_enc(desc, dst, src, nbytes);
blkcipher_walk_init(&walk, dst, src, nbytes);
- return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
+ return cbc_aes_crypt(desc, sctx->enc, &walk);
}
static int cbc_aes_decrypt(struct blkcipher_desc *desc,
@@ -495,7 +501,7 @@
return fallback_blk_dec(desc, dst, src, nbytes);
blkcipher_walk_init(&walk, dst, src, nbytes);
- return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
+ return cbc_aes_crypt(desc, sctx->dec, &walk);
}
static struct crypto_alg cbc_aes_alg = {
@@ -586,7 +592,7 @@
xts_ctx->enc = KM_XTS_128_ENCRYPT;
xts_ctx->dec = KM_XTS_128_DECRYPT;
memcpy(xts_ctx->key + 16, in_key, 16);
- memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16);
+ memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16);
break;
case 48:
xts_ctx->enc = 0;
@@ -597,7 +603,7 @@
xts_ctx->enc = KM_XTS_256_ENCRYPT;
xts_ctx->dec = KM_XTS_256_DECRYPT;
memcpy(xts_ctx->key, in_key, 32);
- memcpy(xts_ctx->pcc.key, in_key + 32, 32);
+ memcpy(xts_ctx->pcc_key, in_key + 32, 32);
break;
default:
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -616,29 +622,33 @@
unsigned int nbytes = walk->nbytes;
unsigned int n;
u8 *in, *out;
- void *param;
+ struct pcc_param pcc_param;
+ struct {
+ u8 key[32];
+ u8 init[16];
+ } xts_param;
if (!nbytes)
goto out;
- memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block));
- memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit));
- memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts));
- memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak));
- param = xts_ctx->pcc.key + offset;
- ret = crypt_s390_pcc(func, param);
+ memset(pcc_param.block, 0, sizeof(pcc_param.block));
+ memset(pcc_param.bit, 0, sizeof(pcc_param.bit));
+ memset(pcc_param.xts, 0, sizeof(pcc_param.xts));
+ memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak));
+ memcpy(pcc_param.key, xts_ctx->pcc_key, 32);
+ ret = crypt_s390_pcc(func, &pcc_param.key[offset]);
if (ret < 0)
return -EIO;
- memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16);
- param = xts_ctx->key + offset;
+ memcpy(xts_param.key, xts_ctx->key, 32);
+ memcpy(xts_param.init, pcc_param.xts, 16);
do {
/* only use complete blocks */
n = nbytes & ~(AES_BLOCK_SIZE - 1);
out = walk->dst.virt.addr;
in = walk->src.virt.addr;
- ret = crypt_s390_km(func, param, out, in, n);
+ ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n);
if (ret < 0 || ret != n)
return -EIO;
@@ -748,43 +758,67 @@
return aes_set_key(tfm, in_key, key_len);
}
+static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
+{
+ unsigned int i, n;
+
+ /* only use complete blocks, max. PAGE_SIZE */
+ n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(AES_BLOCK_SIZE - 1);
+ for (i = AES_BLOCK_SIZE; i < n; i += AES_BLOCK_SIZE) {
+ memcpy(ctrptr + i, ctrptr + i - AES_BLOCK_SIZE,
+ AES_BLOCK_SIZE);
+ crypto_inc(ctrptr + i, AES_BLOCK_SIZE);
+ }
+ return n;
+}
+
static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
struct s390_aes_ctx *sctx, struct blkcipher_walk *walk)
{
int ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE);
- unsigned int i, n, nbytes;
- u8 buf[AES_BLOCK_SIZE];
- u8 *out, *in;
+ unsigned int n, nbytes;
+ u8 buf[AES_BLOCK_SIZE], ctrbuf[AES_BLOCK_SIZE];
+ u8 *out, *in, *ctrptr = ctrbuf;
if (!walk->nbytes)
return ret;
- memcpy(ctrblk, walk->iv, AES_BLOCK_SIZE);
+ if (spin_trylock(&ctrblk_lock))
+ ctrptr = ctrblk;
+
+ memcpy(ctrptr, walk->iv, AES_BLOCK_SIZE);
while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
out = walk->dst.virt.addr;
in = walk->src.virt.addr;
while (nbytes >= AES_BLOCK_SIZE) {
- /* only use complete blocks, max. PAGE_SIZE */
- n = (nbytes > PAGE_SIZE) ? PAGE_SIZE :
- nbytes & ~(AES_BLOCK_SIZE - 1);
- for (i = AES_BLOCK_SIZE; i < n; i += AES_BLOCK_SIZE) {
- memcpy(ctrblk + i, ctrblk + i - AES_BLOCK_SIZE,
- AES_BLOCK_SIZE);
- crypto_inc(ctrblk + i, AES_BLOCK_SIZE);
- }
- ret = crypt_s390_kmctr(func, sctx->key, out, in, n, ctrblk);
- if (ret < 0 || ret != n)
+ if (ctrptr == ctrblk)
+ n = __ctrblk_init(ctrptr, nbytes);
+ else
+ n = AES_BLOCK_SIZE;
+ ret = crypt_s390_kmctr(func, sctx->key, out, in,
+ n, ctrptr);
+ if (ret < 0 || ret != n) {
+ if (ctrptr == ctrblk)
+ spin_unlock(&ctrblk_lock);
return -EIO;
+ }
if (n > AES_BLOCK_SIZE)
- memcpy(ctrblk, ctrblk + n - AES_BLOCK_SIZE,
+ memcpy(ctrptr, ctrptr + n - AES_BLOCK_SIZE,
AES_BLOCK_SIZE);
- crypto_inc(ctrblk, AES_BLOCK_SIZE);
+ crypto_inc(ctrptr, AES_BLOCK_SIZE);
out += n;
in += n;
nbytes -= n;
}
ret = blkcipher_walk_done(desc, walk, nbytes);
}
+ if (ctrptr == ctrblk) {
+ if (nbytes)
+ memcpy(ctrbuf, ctrptr, AES_BLOCK_SIZE);
+ else
+ memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE);
+ spin_unlock(&ctrblk_lock);
+ }
/*
* final block may be < AES_BLOCK_SIZE, copy only nbytes
*/
@@ -792,14 +826,15 @@
out = walk->dst.virt.addr;
in = walk->src.virt.addr;
ret = crypt_s390_kmctr(func, sctx->key, buf, in,
- AES_BLOCK_SIZE, ctrblk);
+ AES_BLOCK_SIZE, ctrbuf);
if (ret < 0 || ret != AES_BLOCK_SIZE)
return -EIO;
memcpy(out, buf, nbytes);
- crypto_inc(ctrblk, AES_BLOCK_SIZE);
+ crypto_inc(ctrbuf, AES_BLOCK_SIZE);
ret = blkcipher_walk_done(desc, walk, 0);
+ memcpy(walk->iv, ctrbuf, AES_BLOCK_SIZE);
}
- memcpy(walk->iv, ctrblk, AES_BLOCK_SIZE);
+
return ret;
}
diff -Nur linux/arch/s390/crypto/des_s390.c rpi/arch/s390/crypto/des_s390.c
--- linux/arch/s390/crypto/des_s390.c 2014-05-29 12:18:18.381554080 +0900
+++ rpi/arch/s390/crypto/des_s390.c 2014-05-29 11:49:11.615902940 +0900
@@ -25,6 +25,7 @@
#define DES3_KEY_SIZE (3 * DES_KEY_SIZE)
static u8 *ctrblk;
+static DEFINE_SPINLOCK(ctrblk_lock);
struct s390_des_ctx {
u8 iv[DES_BLOCK_SIZE];
@@ -105,29 +106,35 @@
}
static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
- u8 *iv, struct blkcipher_walk *walk)
+ struct blkcipher_walk *walk)
{
+ struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
int ret = blkcipher_walk_virt(desc, walk);
unsigned int nbytes = walk->nbytes;
+ struct {
+ u8 iv[DES_BLOCK_SIZE];
+ u8 key[DES3_KEY_SIZE];
+ } param;
if (!nbytes)
goto out;
- memcpy(iv, walk->iv, DES_BLOCK_SIZE);
+ memcpy(param.iv, walk->iv, DES_BLOCK_SIZE);
+ memcpy(param.key, ctx->key, DES3_KEY_SIZE);
do {
/* only use complete blocks */
unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
u8 *out = walk->dst.virt.addr;
u8 *in = walk->src.virt.addr;
- ret = crypt_s390_kmc(func, iv, out, in, n);
+ ret = crypt_s390_kmc(func, &param, out, in, n);
if (ret < 0 || ret != n)
return -EIO;
nbytes &= DES_BLOCK_SIZE - 1;
ret = blkcipher_walk_done(desc, walk, nbytes);
} while ((nbytes = walk->nbytes));
- memcpy(walk->iv, iv, DES_BLOCK_SIZE);
+ memcpy(walk->iv, param.iv, DES_BLOCK_SIZE);
out:
return ret;
@@ -179,22 +186,20 @@
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
{
- struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
struct blkcipher_walk walk;
blkcipher_walk_init(&walk, dst, src, nbytes);
- return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, ctx->iv, &walk);
+ return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, &walk);
}
static int cbc_des_decrypt(struct blkcipher_desc *desc,
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
{
- struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
struct blkcipher_walk walk;
blkcipher_walk_init(&walk, dst, src, nbytes);
- return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, ctx->iv, &walk);
+ return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, &walk);
}
static struct crypto_alg cbc_des_alg = {
@@ -327,22 +332,20 @@
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
{
- struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
struct blkcipher_walk walk;
blkcipher_walk_init(&walk, dst, src, nbytes);
- return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, ctx->iv, &walk);
+ return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, &walk);
}
static int cbc_des3_decrypt(struct blkcipher_desc *desc,
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
{
- struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
struct blkcipher_walk walk;
blkcipher_walk_init(&walk, dst, src, nbytes);
- return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, ctx->iv, &walk);
+ return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, &walk);
}
static struct crypto_alg cbc_des3_alg = {
@@ -366,54 +369,80 @@
}
};
+static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
+{
+ unsigned int i, n;
+
+ /* align to block size, max. PAGE_SIZE */
+ n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1);
+ for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
+ memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
+ crypto_inc(ctrptr + i, DES_BLOCK_SIZE);
+ }
+ return n;
+}
+
static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
- struct s390_des_ctx *ctx, struct blkcipher_walk *walk)
+ struct s390_des_ctx *ctx,
+ struct blkcipher_walk *walk)
{
int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
- unsigned int i, n, nbytes;
- u8 buf[DES_BLOCK_SIZE];
- u8 *out, *in;
+ unsigned int n, nbytes;
+ u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE];
+ u8 *out, *in, *ctrptr = ctrbuf;
+
+ if (!walk->nbytes)
+ return ret;
- memcpy(ctrblk, walk->iv, DES_BLOCK_SIZE);
+ if (spin_trylock(&ctrblk_lock))
+ ctrptr = ctrblk;
+
+ memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE);
while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
out = walk->dst.virt.addr;
in = walk->src.virt.addr;
while (nbytes >= DES_BLOCK_SIZE) {
- /* align to block size, max. PAGE_SIZE */
- n = (nbytes > PAGE_SIZE) ? PAGE_SIZE :
- nbytes & ~(DES_BLOCK_SIZE - 1);
- for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
- memcpy(ctrblk + i, ctrblk + i - DES_BLOCK_SIZE,
- DES_BLOCK_SIZE);
- crypto_inc(ctrblk + i, DES_BLOCK_SIZE);
- }
- ret = crypt_s390_kmctr(func, ctx->key, out, in, n, ctrblk);
- if (ret < 0 || ret != n)
+ if (ctrptr == ctrblk)
+ n = __ctrblk_init(ctrptr, nbytes);
+ else
+ n = DES_BLOCK_SIZE;
+ ret = crypt_s390_kmctr(func, ctx->key, out, in,
+ n, ctrptr);
+ if (ret < 0 || ret != n) {
+ if (ctrptr == ctrblk)
+ spin_unlock(&ctrblk_lock);
return -EIO;
+ }
if (n > DES_BLOCK_SIZE)
- memcpy(ctrblk, ctrblk + n - DES_BLOCK_SIZE,
+ memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE,
DES_BLOCK_SIZE);
- crypto_inc(ctrblk, DES_BLOCK_SIZE);
+ crypto_inc(ctrptr, DES_BLOCK_SIZE);
out += n;
in += n;
nbytes -= n;
}
ret = blkcipher_walk_done(desc, walk, nbytes);
}
-
+ if (ctrptr == ctrblk) {
+ if (nbytes)
+ memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE);
+ else
+ memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
+ spin_unlock(&ctrblk_lock);
+ }
/* final block may be < DES_BLOCK_SIZE, copy only nbytes */
if (nbytes) {
out = walk->dst.virt.addr;
in = walk->src.virt.addr;
ret = crypt_s390_kmctr(func, ctx->key, buf, in,
- DES_BLOCK_SIZE, ctrblk);
+ DES_BLOCK_SIZE, ctrbuf);
if (ret < 0 || ret != DES_BLOCK_SIZE)
return -EIO;
memcpy(out, buf, nbytes);
- crypto_inc(ctrblk, DES_BLOCK_SIZE);
+ crypto_inc(ctrbuf, DES_BLOCK_SIZE);
ret = blkcipher_walk_done(desc, walk, 0);
+ memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE);
}
- memcpy(walk->iv, ctrblk, DES_BLOCK_SIZE);
return ret;
}
diff -Nur linux/arch/s390/include/asm/ccwdev.h rpi/arch/s390/include/asm/ccwdev.h
--- linux/arch/s390/include/asm/ccwdev.h 2014-05-29 12:18:18.387554043 +0900
+++ rpi/arch/s390/include/asm/ccwdev.h 2014-05-29 11:49:11.621902889 +0900
@@ -219,7 +219,7 @@
#define to_ccwdev(n) container_of(n, struct ccw_device, dev)
#define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
-extern struct ccw_device *ccw_device_probe_console(void);
+extern struct ccw_device *ccw_device_probe_console(struct ccw_driver *);
extern void ccw_device_wait_idle(struct ccw_device *);
extern int ccw_device_force_console(struct ccw_device *);
diff -Nur linux/arch/s390/include/asm/timex.h rpi/arch/s390/include/asm/timex.h
--- linux/arch/s390/include/asm/timex.h 2014-05-29 12:18:18.402553949 +0900
+++ rpi/arch/s390/include/asm/timex.h 2014-05-29 11:49:11.640902730 +0900
@@ -71,9 +71,11 @@
typedef unsigned long long cycles_t;
-static inline void get_tod_clock_ext(char *clk)
+static inline void get_tod_clock_ext(char clk[16])
{
- asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
+ typedef struct { char _[sizeof(clk)]; } addrtype;
+
+ asm volatile("stcke %0" : "=Q" (*(addrtype *) clk) : : "cc");
}
static inline unsigned long long get_tod_clock(void)
diff -Nur linux/arch/s390/include/asm/vdso.h rpi/arch/s390/include/asm/vdso.h
--- linux/arch/s390/include/asm/vdso.h 2014-05-29 12:18:18.404553936 +0900
+++ rpi/arch/s390/include/asm/vdso.h 2014-05-29 11:49:11.642902713 +0900
@@ -26,8 +26,9 @@
__u64 wtom_clock_nsec; /* 0x28 */
__u32 tz_minuteswest; /* Minutes west of Greenwich 0x30 */
__u32 tz_dsttime; /* Type of dst correction 0x34 */
- __u32 ectg_available;
- __u32 ntp_mult; /* NTP adjusted multiplier 0x3C */
+ __u32 ectg_available; /* ECTG instruction present 0x38 */
+ __u32 tk_mult; /* Mult. used for xtime_nsec 0x3c */
+ __u32 tk_shift; /* Shift used for xtime_nsec 0x40 */
};
struct vdso_per_cpu_data {
diff -Nur linux/arch/s390/include/uapi/asm/statfs.h rpi/arch/s390/include/uapi/asm/statfs.h
--- linux/arch/s390/include/uapi/asm/statfs.h 2014-05-29 12:18:18.405553930 +0900
+++ rpi/arch/s390/include/uapi/asm/statfs.h 2014-05-29 11:49:11.649902655 +0900
@@ -35,11 +35,11 @@
struct statfs64 {
unsigned int f_type;
unsigned int f_bsize;
- unsigned long f_blocks;
- unsigned long f_bfree;
- unsigned long f_bavail;
- unsigned long f_files;
- unsigned long f_ffree;
+ unsigned long long f_blocks;
+ unsigned long long f_bfree;
+ unsigned long long f_bavail;
+ unsigned long long f_files;
+ unsigned long long f_ffree;
__kernel_fsid_t f_fsid;
unsigned int f_namelen;
unsigned int f_frsize;
diff -Nur linux/arch/s390/Kconfig rpi/arch/s390/Kconfig
--- linux/arch/s390/Kconfig 2014-05-29 12:18:18.378554099 +0900
+++ rpi/arch/s390/Kconfig 2014-05-29 11:49:11.610902982 +0900
@@ -100,7 +100,7 @@
select GENERIC_CLOCKEVENTS
select GENERIC_CPU_DEVICES if !SMP
select GENERIC_SMP_IDLE_THREAD
- select GENERIC_TIME_VSYSCALL_OLD
+ select GENERIC_TIME_VSYSCALL
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
select HAVE_ARCH_SECCOMP_FILTER
@@ -116,6 +116,7 @@
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+ select HAVE_FUTEX_CMPXCHG if FUTEX
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZ4
diff -Nur linux/arch/s390/kernel/asm-offsets.c rpi/arch/s390/kernel/asm-offsets.c
--- linux/arch/s390/kernel/asm-offsets.c 2014-05-29 12:18:18.406553924 +0900
+++ rpi/arch/s390/kernel/asm-offsets.c 2014-05-29 11:49:11.651902638 +0900
@@ -65,7 +65,8 @@
DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
- DEFINE(__VDSO_NTP_MULT, offsetof(struct vdso_data, ntp_mult));
+ DEFINE(__VDSO_TK_MULT, offsetof(struct vdso_data, tk_mult));
+ DEFINE(__VDSO_TK_SHIFT, offsetof(struct vdso_data, tk_shift));
DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base));
DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time));
/* constants used by the vdso */
diff -Nur linux/arch/s390/kernel/head64.S rpi/arch/s390/kernel/head64.S
--- linux/arch/s390/kernel/head64.S 2014-05-29 12:18:18.415553868 +0900
+++ rpi/arch/s390/kernel/head64.S 2014-05-29 11:49:11.661902554 +0900
@@ -59,7 +59,7 @@
.quad 0 # cr12: tracing off
.quad 0 # cr13: home space segment table
.quad 0xc0000000 # cr14: machine check handling off
- .quad 0 # cr15: linkage stack operations
+ .quad .Llinkage_stack # cr15: linkage stack operations
.Lpcmsk:.quad 0x0000000180000000
.L4malign:.quad 0xffffffffffc00000
.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
@@ -67,12 +67,15 @@
.Lparmaddr:
.quad PARMAREA
.align 64
-.Lduct: .long 0,0,0,0,.Lduald,0,0,0
+.Lduct: .long 0,.Laste,.Laste,0,.Lduald,0,0,0
.long 0,0,0,0,0,0,0,0
+.Laste: .quad 0,0xffffffffffffffff,0,0,0,0,0,0
.align 128
.Lduald:.rept 8
.long 0x80000000,0,0,0 # invalid access-list entries
.endr
+.Llinkage_stack:
+ .long 0,0,0x89000000,0,0,0,0x8a000000,0
ENTRY(_ehead)
diff -Nur linux/arch/s390/kernel/smp.c rpi/arch/s390/kernel/smp.c
--- linux/arch/s390/kernel/smp.c 2014-05-29 12:18:18.422553824 +0900
+++ rpi/arch/s390/kernel/smp.c 2014-05-29 11:49:11.669902487 +0900
@@ -929,7 +929,7 @@
idle_count = ACCESS_ONCE(idle->idle_count);
if (ACCESS_ONCE(idle->clock_idle_enter))
idle_count++;
- } while ((sequence & 1) || (idle->sequence != sequence));
+ } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
return sprintf(buf, "%llu\n", idle_count);
}
static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -947,7 +947,7 @@
idle_time = ACCESS_ONCE(idle->idle_time);
idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
- } while ((sequence & 1) || (idle->sequence != sequence));
+ } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
return sprintf(buf, "%llu\n", idle_time >> 12);
}
diff -Nur linux/arch/s390/kernel/time.c rpi/arch/s390/kernel/time.c
--- linux/arch/s390/kernel/time.c 2014-05-29 12:18:18.424553811 +0900
+++ rpi/arch/s390/kernel/time.c 2014-05-29 11:49:11.671902470 +0900
@@ -108,20 +108,10 @@
set_clock_comparator(S390_lowcore.clock_comparator);
}
-static int s390_next_ktime(ktime_t expires,
+static int s390_next_event(unsigned long delta,
struct clock_event_device *evt)
{
- struct timespec ts;
- u64 nsecs;
-
- ts.tv_sec = ts.tv_nsec = 0;
- monotonic_to_bootbased(&ts);
- nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires));
- do_div(nsecs, 125);
- S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9);
- /* Program the maximum value if we have an overflow (== year 2042) */
- if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc))
- S390_lowcore.clock_comparator = -1ULL;
+ S390_lowcore.clock_comparator = get_tod_clock() + delta;
set_clock_comparator(S390_lowcore.clock_comparator);
return 0;
}
@@ -146,15 +136,14 @@
cpu = smp_processor_id();
cd = &per_cpu(comparators, cpu);
cd->name = "comparator";
- cd->features = CLOCK_EVT_FEAT_ONESHOT |
- CLOCK_EVT_FEAT_KTIME;
+ cd->features = CLOCK_EVT_FEAT_ONESHOT;
cd->mult = 16777;
cd->shift = 12;
cd->min_delta_ns = 1;
cd->max_delta_ns = LONG_MAX;
cd->rating = 400;
cd->cpumask = cpumask_of(cpu);
- cd->set_next_ktime = s390_next_ktime;
+ cd->set_next_event = s390_next_event;
cd->set_mode = s390_set_mode;
clockevents_register_device(cd);
@@ -221,21 +210,30 @@
return &clocksource_tod;
}
-void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
- struct clocksource *clock, u32 mult)
+void update_vsyscall(struct timekeeper *tk)
{
- if (clock != &clocksource_tod)
+ u64 nsecps;
+
+ if (tk->clock != &clocksource_tod)
return;
/* Make userspace gettimeofday spin until we're done. */
++vdso_data->tb_update_count;
smp_wmb();
- vdso_data->xtime_tod_stamp = clock->cycle_last;
- vdso_data->xtime_clock_sec = wall_time->tv_sec;
- vdso_data->xtime_clock_nsec = wall_time->tv_nsec;
- vdso_data->wtom_clock_sec = wtm->tv_sec;
- vdso_data->wtom_clock_nsec = wtm->tv_nsec;
- vdso_data->ntp_mult = mult;
+ vdso_data->xtime_tod_stamp = tk->clock->cycle_last;
+ vdso_data->xtime_clock_sec = tk->xtime_sec;
+ vdso_data->xtime_clock_nsec = tk->xtime_nsec;
+ vdso_data->wtom_clock_sec =
+ tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
+ vdso_data->wtom_clock_nsec = tk->xtime_nsec +
+ + (tk->wall_to_monotonic.tv_nsec << tk->shift);
+ nsecps = (u64) NSEC_PER_SEC << tk->shift;
+ while (vdso_data->wtom_clock_nsec >= nsecps) {
+ vdso_data->wtom_clock_nsec -= nsecps;
+ vdso_data->wtom_clock_sec++;
+ }
+ vdso_data->tk_mult = tk->mult;
+ vdso_data->tk_shift = tk->shift;
smp_wmb();
++vdso_data->tb_update_count;
}
diff -Nur linux/arch/s390/kernel/vdso32/clock_gettime.S rpi/arch/s390/kernel/vdso32/clock_gettime.S
--- linux/arch/s390/kernel/vdso32/clock_gettime.S 2014-05-29 12:18:18.425553805 +0900
+++ rpi/arch/s390/kernel/vdso32/clock_gettime.S 2014-05-29 11:49:11.673902454 +0900
@@ -38,25 +38,21 @@
sl %r1,__VDSO_XTIME_STAMP+4(%r5)
brc 3,2f
ahi %r0,-1
-2: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
+2: ms %r0,__VDSO_TK_MULT(%r5) /* * tk->mult */
lr %r2,%r0
- l %r0,__VDSO_NTP_MULT(%r5)
+ l %r0,__VDSO_TK_MULT(%r5)
ltr %r1,%r1
mr %r0,%r0
jnm 3f
- a %r0,__VDSO_NTP_MULT(%r5)
+ a %r0,__VDSO_TK_MULT(%r5)
3: alr %r0,%r2
- srdl %r0,12
- al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */
- al %r1,__VDSO_XTIME_NSEC+4(%r5)
- brc 12,4f
- ahi %r0,1
-4: l %r2,__VDSO_XTIME_SEC+4(%r5)
- al %r0,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic */
+ al %r0,__VDSO_WTOM_NSEC(%r5)
al %r1,__VDSO_WTOM_NSEC+4(%r5)
brc 12,5f
ahi %r0,1
-5: al %r2,__VDSO_WTOM_SEC+4(%r5)
+5: l %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
+ srdl %r0,0(%r2) /* >> tk->shift */
+ l %r2,__VDSO_WTOM_SEC+4(%r5)
cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */
jne 1b
basr %r5,0
@@ -86,20 +82,21 @@
sl %r1,__VDSO_XTIME_STAMP+4(%r5)
brc 3,12f
ahi %r0,-1
-12: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
+12: ms %r0,__VDSO_TK_MULT(%r5) /* * tk->mult */
lr %r2,%r0
- l %r0,__VDSO_NTP_MULT(%r5)
+ l %r0,__VDSO_TK_MULT(%r5)
ltr %r1,%r1
mr %r0,%r0
jnm 13f
- a %r0,__VDSO_NTP_MULT(%r5)
+ a %r0,__VDSO_TK_MULT(%r5)
13: alr %r0,%r2
- srdl %r0,12
- al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */
+ al %r0,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
al %r1,__VDSO_XTIME_NSEC+4(%r5)
brc 12,14f
ahi %r0,1
-14: l %r2,__VDSO_XTIME_SEC+4(%r5)
+14: l %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
+ srdl %r0,0(%r2) /* >> tk->shift */
+ l %r2,__VDSO_XTIME_SEC+4(%r5)
cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */
jne 11b
basr %r5,0
diff -Nur linux/arch/s390/kernel/vdso32/gettimeofday.S rpi/arch/s390/kernel/vdso32/gettimeofday.S
--- linux/arch/s390/kernel/vdso32/gettimeofday.S 2014-05-29 12:18:18.426553799 +0900
+++ rpi/arch/s390/kernel/vdso32/gettimeofday.S 2014-05-29 11:49:11.673902454 +0900
@@ -35,15 +35,14 @@
sl %r1,__VDSO_XTIME_STAMP+4(%r5)
brc 3,3f
ahi %r0,-1
-3: ms %r0,__VDSO_NTP_MULT(%r5) /* cyc2ns(clock,cycle_delta) */
+3: ms %r0,__VDSO_TK_MULT(%r5) /* * tk->mult */
st %r0,24(%r15)
- l %r0,__VDSO_NTP_MULT(%r5)
+ l %r0,__VDSO_TK_MULT(%r5)
ltr %r1,%r1
mr %r0,%r0
jnm 4f
- a %r0,__VDSO_NTP_MULT(%r5)
+ a %r0,__VDSO_TK_MULT(%r5)
4: al %r0,24(%r15)
- srdl %r0,12
al %r0,__VDSO_XTIME_NSEC(%r5) /* + xtime */
al %r1,__VDSO_XTIME_NSEC+4(%r5)
brc 12,5f
@@ -51,6 +50,8 @@
5: mvc 24(4,%r15),__VDSO_XTIME_SEC+4(%r5)
cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */
jne 1b
+ l %r4,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
+ srdl %r0,0(%r4) /* >> tk->shift */
l %r4,24(%r15) /* get tv_sec from stack */
basr %r5,0
6: ltr %r0,%r0
diff -Nur linux/arch/s390/kernel/vdso64/clock_gettime.S rpi/arch/s390/kernel/vdso64/clock_gettime.S
--- linux/arch/s390/kernel/vdso64/clock_gettime.S 2014-05-29 12:18:18.426553799 +0900
+++ rpi/arch/s390/kernel/vdso64/clock_gettime.S 2014-05-29 11:49:11.674902445 +0900
@@ -34,14 +34,13 @@
tmll %r4,0x0001 /* pending update ? loop */
jnz 0b
stck 48(%r15) /* Store TOD clock */
+ lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
+ lg %r0,__VDSO_WTOM_SEC(%r5)
lg %r1,48(%r15)
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
- msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
- srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
- alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */
- lg %r0,__VDSO_XTIME_SEC(%r5)
- alg %r1,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic */
- alg %r0,__VDSO_WTOM_SEC(%r5)
+ msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
+ alg %r1,__VDSO_WTOM_NSEC(%r5)
+ srlg %r1,%r1,0(%r2) /* >> tk->shift */
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
jne 0b
larl %r5,13f
@@ -62,12 +61,13 @@
tmll %r4,0x0001 /* pending update ? loop */
jnz 5b
stck 48(%r15) /* Store TOD clock */
+ lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
lg %r1,48(%r15)
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
- msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
- srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
- alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime */
- lg %r0,__VDSO_XTIME_SEC(%r5)
+ msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
+ alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
+ srlg %r1,%r1,0(%r2) /* >> tk->shift */
+ lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
jne 5b
larl %r5,13f
diff -Nur linux/arch/s390/kernel/vdso64/gettimeofday.S rpi/arch/s390/kernel/vdso64/gettimeofday.S
--- linux/arch/s390/kernel/vdso64/gettimeofday.S 2014-05-29 12:18:18.427553792 +0900
+++ rpi/arch/s390/kernel/vdso64/gettimeofday.S 2014-05-29 11:49:11.674902445 +0900
@@ -31,12 +31,13 @@
stck 48(%r15) /* Store TOD clock */
lg %r1,48(%r15)
sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
- msgf %r1,__VDSO_NTP_MULT(%r5) /* * NTP adjustment */
- srlg %r1,%r1,12 /* cyc2ns(clock,cycle_delta) */
- alg %r1,__VDSO_XTIME_NSEC(%r5) /* + xtime.tv_nsec */
- lg %r0,__VDSO_XTIME_SEC(%r5) /* xtime.tv_sec */
+ msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
+ alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
+ lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
jne 0b
+ lgf %r5,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
+ srlg %r1,%r1,0(%r5) /* >> tk->shift */
larl %r5,5f
2: clg %r1,0(%r5)
jl 3f
diff -Nur linux/arch/s390/kernel/vtime.c rpi/arch/s390/kernel/vtime.c
--- linux/arch/s390/kernel/vtime.c 2014-05-29 12:18:18.427553792 +0900
+++ rpi/arch/s390/kernel/vtime.c 2014-05-29 11:49:11.675902437 +0900
@@ -191,7 +191,7 @@
sequence = ACCESS_ONCE(idle->sequence);
idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
- } while ((sequence & 1) || (idle->sequence != sequence));
+ } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
}
diff -Nur linux/arch/s390/kvm/diag.c rpi/arch/s390/kvm/diag.c
--- linux/arch/s390/kvm/diag.c 2014-05-29 12:18:18.428553786 +0900
+++ rpi/arch/s390/kvm/diag.c 2014-05-29 11:49:11.676902428 +0900
@@ -122,7 +122,7 @@
* - gpr 4 contains the index on the bus (optionally)
*/
ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
- vcpu->run->s.regs.gprs[2],
+ vcpu->run->s.regs.gprs[2] & 0xffffffff,
8, &vcpu->run->s.regs.gprs[3],
vcpu->run->s.regs.gprs[4]);
srcu_read_unlock(&vcpu->kvm->srcu, idx);
@@ -139,7 +139,7 @@
int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
{
- int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16;
+ int code = kvm_s390_get_base_disp_rs(vcpu) & 0xffff;
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
diff -Nur linux/arch/s390/kvm/kvm-s390.c rpi/arch/s390/kvm/kvm-s390.c
--- linux/arch/s390/kvm/kvm-s390.c 2014-05-29 12:18:18.430553774 +0900
+++ rpi/arch/s390/kvm/kvm-s390.c 2014-05-29 11:49:11.677902420 +0900
@@ -788,7 +788,8 @@
if (rc)
break;
if (kvm_is_ucontrol(vcpu->kvm))
- rc = -EOPNOTSUPP;
+ /* Don't exit for host interrupts. */
+ rc = vcpu->arch.sie_block->icptcode ? -EOPNOTSUPP : 0;
else
rc = kvm_handle_sie_intercept(vcpu);
} while (!signal_pending(current) && !rc);
diff -Nur linux/arch/s390/lib/uaccess_pt.c rpi/arch/s390/lib/uaccess_pt.c
--- linux/arch/s390/lib/uaccess_pt.c 2014-05-29 12:18:18.433553755 +0900
+++ rpi/arch/s390/lib/uaccess_pt.c 2014-05-29 11:49:11.681902386 +0900
@@ -78,11 +78,14 @@
* contains the (negative) exception code.
*/
#ifdef CONFIG_64BIT
+
static unsigned long follow_table(struct mm_struct *mm,
unsigned long address, int write)
{
unsigned long *table = (unsigned long *)__pa(mm->pgd);
+ if (unlikely(address > mm->context.asce_limit - 1))
+ return -0x38UL;
switch (mm->context.asce_bits & _ASCE_TYPE_MASK) {
case _ASCE_TYPE_REGION1:
table = table + ((address >> 53) & 0x7ff);
diff -Nur linux/arch/s390/mm/page-states.c rpi/arch/s390/mm/page-states.c
--- linux/arch/s390/mm/page-states.c 2014-05-29 12:18:18.437553730 +0900
+++ rpi/arch/s390/mm/page-states.c 2014-05-29 11:49:11.686902344 +0900
@@ -12,6 +12,8 @@
#include <linux/mm.h>
#include <linux/gfp.h>
#include <linux/init.h>
+#include <asm/setup.h>
+#include <asm/ipl.h>
#define ESSA_SET_STABLE 1
#define ESSA_SET_UNUSED 2
@@ -41,6 +43,14 @@
if (!cmma_flag)
return;
+ /*
+ * Disable CMM for dump, otherwise the tprot based memory
+ * detection can fail because of unstable pages.
+ */
+ if (OLDMEM_BASE || ipl_info.type == IPL_TYPE_FCP_DUMP) {
+ cmma_flag = 0;
+ return;
+ }
asm volatile(
" .insn rrf,0xb9ab0000,%1,%1,0,0\n"
"0: la %0,0\n"
diff -Nur linux/arch/s390/net/bpf_jit_comp.c rpi/arch/s390/net/bpf_jit_comp.c
--- linux/arch/s390/net/bpf_jit_comp.c 2014-05-29 12:18:18.439553717 +0900
+++ rpi/arch/s390/net/bpf_jit_comp.c 2014-05-29 11:49:11.688902328 +0900
@@ -276,7 +276,6 @@
case BPF_S_LD_W_IND:
case BPF_S_LD_H_IND:
case BPF_S_LD_B_IND:
- case BPF_S_LDX_B_MSH:
case BPF_S_LD_IMM:
case BPF_S_LD_MEM:
case BPF_S_MISC_TXA:
@@ -368,14 +367,16 @@
EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
/* lhi %r4,0 */
EMIT4(0xa7480000);
- /* dr %r4,%r12 */
- EMIT2(0x1d4c);
+ /* dlr %r4,%r12 */
+ EMIT4(0xb997004c);
break;
- case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */
- /* m %r4,<d(K)>(%r13) */
- EMIT4_DISP(0x5c40d000, EMIT_CONST(K));
- /* lr %r5,%r4 */
- EMIT2(0x1854);
+ case BPF_S_ALU_DIV_K: /* A /= K */
+ if (K == 1)
+ break;
+ /* lhi %r4,0 */
+ EMIT4(0xa7480000);
+ /* dl %r4,<d(K)>(%r13) */
+ EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K));
break;
case BPF_S_ALU_MOD_X: /* A %= X */
jit->seen |= SEEN_XREG | SEEN_RET0;
@@ -385,16 +386,21 @@
EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
/* lhi %r4,0 */
EMIT4(0xa7480000);
- /* dr %r4,%r12 */
- EMIT2(0x1d4c);
+ /* dlr %r4,%r12 */
+ EMIT4(0xb997004c);
/* lr %r5,%r4 */
EMIT2(0x1854);
break;
case BPF_S_ALU_MOD_K: /* A %= K */
+ if (K == 1) {
+ /* lhi %r5,0 */
+ EMIT4(0xa7580000);
+ break;
+ }
/* lhi %r4,0 */
EMIT4(0xa7480000);
- /* d %r4,<d(K)>(%r13) */
- EMIT4_DISP(0x5d40d000, EMIT_CONST(K));
+ /* dl %r4,<d(K)>(%r13) */
+ EMIT6_DISP(0xe340d000, 0x0097, EMIT_CONST(K));
/* lr %r5,%r4 */
EMIT2(0x1854);
break;
diff -Nur linux/arch/sh/boards/mach-ecovec24/setup.c rpi/arch/sh/boards/mach-ecovec24/setup.c
--- linux/arch/sh/boards/mach-ecovec24/setup.c 2014-05-29 12:18:18.448553661 +0900
+++ rpi/arch/sh/boards/mach-ecovec24/setup.c 2014-05-29 11:49:11.727902001 +0900
@@ -15,6 +15,7 @@
#include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mtd/physmap.h>
+#include <linux/mfd/tmio.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
diff -Nur linux/arch/sh/kernel/dumpstack.c rpi/arch/sh/kernel/dumpstack.c
--- linux/arch/sh/kernel/dumpstack.c 2014-05-29 12:18:18.475553492 +0900
+++ rpi/arch/sh/kernel/dumpstack.c 2014-05-29 11:49:11.857900911 +0900
@@ -115,7 +115,7 @@
*/
static void print_trace_address(void *data, unsigned long addr, int reliable)
{
- printk(data);
+ printk("%s", (char *)data);
printk_address(addr, reliable);
}
diff -Nur linux/arch/sh/kernel/kgdb.c rpi/arch/sh/kernel/kgdb.c
--- linux/arch/sh/kernel/kgdb.c 2014-05-29 12:18:18.478553473 +0900
+++ rpi/arch/sh/kernel/kgdb.c 2014-05-29 11:49:11.861900878 +0900
@@ -13,6 +13,7 @@
#include <linux/kdebug.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/sched.h>
#include <asm/cacheflush.h>
#include <asm/traps.h>
diff -Nur linux/arch/sh/kernel/sh_ksyms_32.c rpi/arch/sh/kernel/sh_ksyms_32.c
--- linux/arch/sh/kernel/sh_ksyms_32.c 2014-05-29 12:18:18.480553461 +0900
+++ rpi/arch/sh/kernel/sh_ksyms_32.c 2014-05-29 11:49:11.867900827 +0900
@@ -20,6 +20,11 @@
EXPORT_SYMBOL(copy_page);
EXPORT_SYMBOL(__clear_user);
EXPORT_SYMBOL(empty_zero_page);
+#ifdef CONFIG_FLATMEM
+/* need in pfn_valid macro */
+EXPORT_SYMBOL(min_low_pfn);
+EXPORT_SYMBOL(max_low_pfn);
+#endif
#define DECLARE_EXPORT(name) \
extern void name(void);EXPORT_SYMBOL(name)
diff -Nur linux/arch/sh/lib/Makefile rpi/arch/sh/lib/Makefile
--- linux/arch/sh/lib/Makefile 2014-05-29 12:18:18.481553455 +0900
+++ rpi/arch/sh/lib/Makefile 2014-05-29 11:49:11.872900785 +0900
@@ -6,7 +6,7 @@
checksum.o strlen.o div64.o div64-generic.o
# Extracted from libgcc
-lib-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
+obj-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \
ashlsi3.o ashrsi3.o ashiftrt.o lshrsi3.o \
udiv_qrnnd.o
diff -Nur linux/arch/sparc/include/asm/pgtable_64.h rpi/arch/sparc/include/asm/pgtable_64.h
--- linux/arch/sparc/include/asm/pgtable_64.h 2014-05-29 12:18:18.489553404 +0900
+++ rpi/arch/sparc/include/asm/pgtable_64.h 2014-05-29 11:49:11.928900316 +0900
@@ -616,7 +616,7 @@
}
#define pte_accessible pte_accessible
-static inline unsigned long pte_accessible(pte_t a)
+static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
{
return pte_val(a) & _PAGE_VALID;
}
@@ -806,7 +806,7 @@
* SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
* and SUN4V pte layout, so this inline test is fine.
*/
- if (likely(mm != &init_mm) && pte_accessible(orig))
+ if (likely(mm != &init_mm) && pte_accessible(mm, orig))
tlb_batch_add(mm, addr, ptep, orig, fullmm);
}
diff -Nur linux/arch/sparc/Kconfig rpi/arch/sparc/Kconfig
--- linux/arch/sparc/Kconfig 2014-05-29 12:18:18.485553429 +0900
+++ rpi/arch/sparc/Kconfig 2014-05-29 11:49:11.891900626 +0900
@@ -25,7 +25,7 @@
select RTC_DRV_M48T59
select HAVE_DMA_ATTRS
select HAVE_DMA_API_DEBUG
- select HAVE_ARCH_JUMP_LABEL
+ select HAVE_ARCH_JUMP_LABEL if SPARC64
select GENERIC_IRQ_SHOW
select ARCH_WANT_IPC_PARSE_VERSION
select USE_GENERIC_SMP_HELPERS if SMP
diff -Nur linux/arch/sparc/kernel/process_64.c rpi/arch/sparc/kernel/process_64.c
--- linux/arch/sparc/kernel/process_64.c 2014-05-29 12:18:18.524553185 +0900
+++ rpi/arch/sparc/kernel/process_64.c 2014-05-29 11:49:11.979899888 +0900
@@ -57,9 +57,12 @@
{
if (tlb_type != hypervisor) {
touch_nmi_watchdog();
+ local_irq_enable();
} else {
unsigned long pstate;
+ local_irq_enable();
+
/* The sun4v sleeping code requires that we have PSTATE.IE cleared over
* the cpu sleep hypervisor call.
*/
@@ -81,7 +84,6 @@
: "=&r" (pstate)
: "i" (PSTATE_IE));
}
- local_irq_enable();
}
#ifdef CONFIG_HOTPLUG_CPU
diff -Nur linux/arch/sparc/kernel/syscalls.S rpi/arch/sparc/kernel/syscalls.S
--- linux/arch/sparc/kernel/syscalls.S 2014-05-29 12:18:18.532553135 +0900
+++ rpi/arch/sparc/kernel/syscalls.S 2014-05-29 11:49:11.993899771 +0900
@@ -189,7 +189,8 @@
mov %i0, %l5 ! IEU1
5: call %l7 ! CTI Group brk forced
srl %i5, 0, %o5 ! IEU1
- ba,a,pt %xcc, 3f
+ ba,pt %xcc, 3f
+ sra %o0, 0, %o0
/* Linux native system calls enter here... */
.align 32
@@ -217,7 +218,6 @@
3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
ret_sys_call:
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
- sra %o0, 0, %o0
mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
sllx %g2, 32, %g2
diff -Nur linux/arch/sparc/net/bpf_jit_comp.c rpi/arch/sparc/net/bpf_jit_comp.c
--- linux/arch/sparc/net/bpf_jit_comp.c 2014-05-29 12:18:18.548553035 +0900
+++ rpi/arch/sparc/net/bpf_jit_comp.c 2014-05-29 11:49:12.024899511 +0900
@@ -497,9 +497,20 @@
case BPF_S_ALU_MUL_K: /* A *= K */
emit_alu_K(MUL, K);
break;
- case BPF_S_ALU_DIV_K: /* A /= K */
- emit_alu_K(MUL, K);
- emit_read_y(r_A);
+ case BPF_S_ALU_DIV_K: /* A /= K with K != 0*/
+ if (K == 1)
+ break;
+ emit_write_y(G0);
+#ifdef CONFIG_SPARC32
+ /* The Sparc v8 architecture requires
+ * three instructions between a %y
+ * register write and the first use.
+ */
+ emit_nop();
+ emit_nop();
+ emit_nop();
+#endif
+ emit_alu_K(DIV, K);
break;
case BPF_S_ALU_DIV_X: /* A /= X; */
emit_cmpi(r_X, 0);
diff -Nur linux/arch/tile/include/asm/compat.h rpi/arch/tile/include/asm/compat.h
--- linux/arch/tile/include/asm/compat.h 2014-05-29 12:18:18.550553023 +0900
+++ rpi/arch/tile/include/asm/compat.h 2014-05-29 11:49:12.039899386 +0900
@@ -281,7 +281,6 @@
u32 dummy, u32 low, u32 high);
long compat_sys_pwrite64(unsigned int fd, char __user *ubuf, size_t count,
u32 dummy, u32 low, u32 high);
-long compat_sys_lookup_dcookie(u32 low, u32 high, char __user *buf, size_t len);
long compat_sys_sync_file_range2(int fd, unsigned int flags,
u32 offset_lo, u32 offset_hi,
u32 nbytes_lo, u32 nbytes_hi);
diff -Nur linux/arch/x86/boot/compressed/eboot.c rpi/arch/x86/boot/compressed/eboot.c
--- linux/arch/x86/boot/compressed/eboot.c 2014-05-29 12:18:18.576552860 +0900
+++ rpi/arch/x86/boot/compressed/eboot.c 2014-05-29 11:49:12.187898146 +0900
@@ -865,6 +865,9 @@
* Because the x86 boot code expects to be passed a boot_params we
* need to create one ourselves (usually the bootloader would create
* one for us).
+ *
+ * The caller is responsible for filling out ->code32_start in the
+ * returned boot_params.
*/
struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
{
@@ -921,8 +924,6 @@
hdr->vid_mode = 0xffff;
hdr->boot_flag = 0xAA55;
- hdr->code32_start = (__u64)(unsigned long)image->image_base;
-
hdr->type_of_loader = 0x21;
/* Convert unicode cmdline to ascii */
diff -Nur linux/arch/x86/boot/compressed/head_32.S rpi/arch/x86/boot/compressed/head_32.S
--- linux/arch/x86/boot/compressed/head_32.S 2014-05-29 12:18:18.577552854 +0900
+++ rpi/arch/x86/boot/compressed/head_32.S 2014-05-29 11:49:12.188898137 +0900
@@ -50,6 +50,13 @@
pushl %eax
pushl %esi
pushl %ecx
+
+ call reloc
+reloc:
+ popl %ecx
+ subl reloc, %ecx
+ movl %ecx, BP_code32_start(%eax)
+
sub $0x4, %esp
ENTRY(efi_stub_entry)
@@ -63,12 +70,7 @@
hlt
jmp 1b
2:
- call 3f
-3:
- popl %eax
- subl $3b, %eax
- subl BP_pref_address(%esi), %eax
- add BP_code32_start(%esi), %eax
+ movl BP_code32_start(%esi), %eax
leal preferred_addr(%eax), %eax
jmp *%eax
diff -Nur linux/arch/x86/boot/compressed/head_64.S rpi/arch/x86/boot/compressed/head_64.S
--- linux/arch/x86/boot/compressed/head_64.S 2014-05-29 12:18:18.577552854 +0900
+++ rpi/arch/x86/boot/compressed/head_64.S 2014-05-29 11:49:12.188898137 +0900
@@ -215,6 +215,8 @@
cmpq $0,%rax
je 1f
mov %rax, %rdx
+ leaq startup_32(%rip), %rax
+ movl %eax, BP_code32_start(%rdx)
popq %rsi
popq %rdi
@@ -228,12 +230,7 @@
hlt
jmp 1b
2:
- call 3f
-3:
- popq %rax
- subq $3b, %rax
- subq BP_pref_address(%rsi), %rax
- add BP_code32_start(%esi), %eax
+ movl BP_code32_start(%esi), %eax
leaq preferred_addr(%rax), %rax
jmp *%rax
diff -Nur linux/arch/x86/boot/compressed/Makefile rpi/arch/x86/boot/compressed/Makefile
--- linux/arch/x86/boot/compressed/Makefile 2014-05-29 12:18:18.575552866 +0900
+++ rpi/arch/x86/boot/compressed/Makefile 2014-05-29 11:49:12.186898154 +0900
@@ -13,6 +13,7 @@
cflags-$(CONFIG_X86_32) := -march=i386
cflags-$(CONFIG_X86_64) := -mcmodel=small
KBUILD_CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -mno-mmx -mno-sse
KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
diff -Nur linux/arch/x86/boot/Makefile rpi/arch/x86/boot/Makefile
--- linux/arch/x86/boot/Makefile 2014-05-29 12:18:18.574552873 +0900
+++ rpi/arch/x86/boot/Makefile 2014-05-29 11:49:12.184898171 +0900
@@ -53,18 +53,18 @@
# How to compile the 16-bit code. Note we always compile for -march=i386,
# that way we can complain to the user if the CPU is insufficient.
-KBUILD_CFLAGS := $(USERINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+KBUILD_CFLAGS := $(USERINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ \
-DDISABLE_BRANCH_PROFILING \
-Wall -Wstrict-prototypes \
-march=i386 -mregparm=3 \
-include $(srctree)/$(src)/code16gcc.h \
-fno-strict-aliasing -fomit-frame-pointer -fno-pic \
+ -mno-mmx -mno-sse \
$(call cc-option, -ffreestanding) \
$(call cc-option, -fno-toplevel-reorder,\
- $(call cc-option, -fno-unit-at-a-time)) \
+ $(call cc-option, -fno-unit-at-a-time)) \
$(call cc-option, -fno-stack-protector) \
$(call cc-option, -mpreferred-stack-boundary=2)
-KBUILD_CFLAGS += $(call cc-option, -m32)
KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
GCOV_PROFILE := n
diff -Nur linux/arch/x86/crypto/ghash-clmulni-intel_asm.S rpi/arch/x86/crypto/ghash-clmulni-intel_asm.S
--- linux/arch/x86/crypto/ghash-clmulni-intel_asm.S 2014-05-29 12:18:18.586552797 +0900
+++ rpi/arch/x86/crypto/ghash-clmulni-intel_asm.S 2014-05-29 11:49:12.206897986 +0900
@@ -24,10 +24,6 @@
.align 16
.Lbswap_mask:
.octa 0x000102030405060708090a0b0c0d0e0f
-.Lpoly:
- .octa 0xc2000000000000000000000000000001
-.Ltwo_one:
- .octa 0x00000001000000000000000000000001
#define DATA %xmm0
#define SHASH %xmm1
@@ -134,28 +130,3 @@
.Lupdate_just_ret:
ret
ENDPROC(clmul_ghash_update)
-
-/*
- * void clmul_ghash_setkey(be128 *shash, const u8 *key);
- *
- * Calculate hash_key << 1 mod poly
- */
-ENTRY(clmul_ghash_setkey)
- movaps .Lbswap_mask, BSWAP
- movups (%rsi), %xmm0
- PSHUFB_XMM BSWAP %xmm0
- movaps %xmm0, %xmm1
- psllq $1, %xmm0
- psrlq $63, %xmm1
- movaps %xmm1, %xmm2
- pslldq $8, %xmm1
- psrldq $8, %xmm2
- por %xmm1, %xmm0
- # reduction
- pshufd $0b00100100, %xmm2, %xmm1
- pcmpeqd .Ltwo_one, %xmm1
- pand .Lpoly, %xmm1
- pxor %xmm1, %xmm0
- movups %xmm0, (%rdi)
- ret
-ENDPROC(clmul_ghash_setkey)
diff -Nur linux/arch/x86/crypto/ghash-clmulni-intel_glue.c rpi/arch/x86/crypto/ghash-clmulni-intel_glue.c
--- linux/arch/x86/crypto/ghash-clmulni-intel_glue.c 2014-05-29 12:18:18.587552791 +0900
+++ rpi/arch/x86/crypto/ghash-clmulni-intel_glue.c 2014-05-29 11:49:12.206897986 +0900
@@ -30,8 +30,6 @@
void clmul_ghash_update(char *dst, const char *src, unsigned int srclen,
const be128 *shash);
-void clmul_ghash_setkey(be128 *shash, const u8 *key);
-
struct ghash_async_ctx {
struct cryptd_ahash *cryptd_tfm;
};
@@ -58,13 +56,23 @@
const u8 *key, unsigned int keylen)
{
struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
+ be128 *x = (be128 *)key;
+ u64 a, b;
if (keylen != GHASH_BLOCK_SIZE) {
crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL;
}
- clmul_ghash_setkey(&ctx->shash, key);
+ /* perform multiplication by 'x' in GF(2^128) */
+ a = be64_to_cpu(x->a);
+ b = be64_to_cpu(x->b);
+
+ ctx->shash.a = (__be64)((b << 1) | (a >> 63));
+ ctx->shash.b = (__be64)((a << 1) | (b >> 63));
+
+ if (a >> 63)
+ ctx->shash.b ^= cpu_to_be64(0xc2);
return 0;
}
diff -Nur linux/arch/x86/crypto/sha256_ssse3_glue.c rpi/arch/x86/crypto/sha256_ssse3_glue.c
--- linux/arch/x86/crypto/sha256_ssse3_glue.c 2014-05-29 12:18:18.589552779 +0900
+++ rpi/arch/x86/crypto/sha256_ssse3_glue.c 2014-05-29 11:49:12.212897936 +0900
@@ -281,7 +281,7 @@
/* allow AVX to override SSSE3, it's a little faster */
if (avx_usable()) {
#ifdef CONFIG_AS_AVX2
- if (boot_cpu_has(X86_FEATURE_AVX2))
+ if (boot_cpu_has(X86_FEATURE_AVX2) && boot_cpu_has(X86_FEATURE_BMI2))
sha256_transform_asm = sha256_transform_rorx;
else
#endif
diff -Nur linux/arch/x86/include/asm/fpu-internal.h rpi/arch/x86/include/asm/fpu-internal.h
--- linux/arch/x86/include/asm/fpu-internal.h 2014-05-29 12:18:18.597552729 +0900
+++ rpi/arch/x86/include/asm/fpu-internal.h 2014-05-29 11:49:12.232897768 +0900
@@ -293,12 +293,13 @@
/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
is pending. Clear the x87 state here by setting it to fixed
values. "m" is a random variable that should be in L1 */
- alternative_input(
- ASM_NOP8 ASM_NOP2,
- "emms\n\t" /* clear stack tags */
- "fildl %P[addr]", /* set F?P to defined value */
- X86_FEATURE_FXSAVE_LEAK,
- [addr] "m" (tsk->thread.fpu.has_fpu));
+ if (unlikely(static_cpu_has(X86_FEATURE_FXSAVE_LEAK))) {
+ asm volatile(
+ "fnclex\n\t"
+ "emms\n\t"
+ "fildl %P[addr]" /* set F?P to defined value */
+ : : [addr] "m" (tsk->thread.fpu.has_fpu));
+ }
return fpu_restore_checking(&tsk->thread.fpu);
}
diff -Nur linux/arch/x86/include/asm/kdebug.h rpi/arch/x86/include/asm/kdebug.h
--- linux/arch/x86/include/asm/kdebug.h 2014-05-29 12:18:18.600552710 +0900
+++ rpi/arch/x86/include/asm/kdebug.h 2014-05-29 11:49:12.239897710 +0900
@@ -21,7 +21,7 @@
DIE_NMIUNKNOWN,
};
-extern void printk_address(unsigned long address, int reliable);
+extern void printk_address(unsigned long address);
extern void die(const char *, struct pt_regs *,long);
extern int __must_check __die(const char *, struct pt_regs *, long);
extern void show_trace(struct task_struct *t, struct pt_regs *regs,
diff -Nur linux/arch/x86/include/asm/kvm_para.h rpi/arch/x86/include/asm/kvm_para.h
--- linux/arch/x86/include/asm/kvm_para.h 2014-05-29 12:18:18.601552704 +0900
+++ rpi/arch/x86/include/asm/kvm_para.h 2014-05-29 11:49:12.242897685 +0900
@@ -85,28 +85,9 @@
return ret;
}
-static inline uint32_t kvm_cpuid_base(void)
-{
- if (boot_cpu_data.cpuid_level < 0)
- return 0; /* So we don't blow up on old processors */
-
- if (cpu_has_hypervisor)
- return hypervisor_cpuid_base("KVMKVMKVM\0\0\0", 0);
-
- return 0;
-}
-
-static inline bool kvm_para_available(void)
-{
- return kvm_cpuid_base() != 0;
-}
-
-static inline unsigned int kvm_arch_para_features(void)
-{
- return cpuid_eax(KVM_CPUID_FEATURES);
-}
-
#ifdef CONFIG_KVM_GUEST
+bool kvm_para_available(void);
+unsigned int kvm_arch_para_features(void);
void __init kvm_guest_init(void);
void kvm_async_pf_task_wait(u32 token);
void kvm_async_pf_task_wake(u32 token);
@@ -126,6 +107,16 @@
#define kvm_async_pf_task_wait(T) do {} while(0)
#define kvm_async_pf_task_wake(T) do {} while(0)
+static inline bool kvm_para_available(void)
+{
+ return 0;
+}
+
+static inline unsigned int kvm_arch_para_features(void)
+{
+ return 0;
+}
+
static inline u32 kvm_read_and_reset_pf_reason(void)
{
return 0;
diff -Nur linux/arch/x86/include/asm/pgtable.h rpi/arch/x86/include/asm/pgtable.h
--- linux/arch/x86/include/asm/pgtable.h 2014-05-29 12:18:18.609552654 +0900
+++ rpi/arch/x86/include/asm/pgtable.h 2014-05-29 11:49:12.255897576 +0900
@@ -452,9 +452,16 @@
}
#define pte_accessible pte_accessible
-static inline int pte_accessible(pte_t a)
+static inline bool pte_accessible(struct mm_struct *mm, pte_t a)
{
- return pte_flags(a) & _PAGE_PRESENT;
+ if (pte_flags(a) & _PAGE_PRESENT)
+ return true;
+
+ if ((pte_flags(a) & (_PAGE_PROTNONE | _PAGE_NUMA)) &&
+ mm_tlb_flush_pending(mm))
+ return true;
+
+ return false;
}
static inline int pte_hidden(pte_t pte)
diff -Nur linux/arch/x86/include/asm/pgtable_types.h rpi/arch/x86/include/asm/pgtable_types.h
--- linux/arch/x86/include/asm/pgtable_types.h 2014-05-29 12:18:18.609552654 +0900
+++ rpi/arch/x86/include/asm/pgtable_types.h 2014-05-29 11:49:12.256897567 +0900
@@ -121,7 +121,8 @@
/* Set of bits not changed in pte_modify */
#define _PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \
- _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY)
+ _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY | \
+ _PAGE_SOFT_DIRTY)
#define _HPAGE_CHG_MASK (_PAGE_CHG_MASK | _PAGE_PSE)
#define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT)
diff -Nur linux/arch/x86/include/asm/topology.h rpi/arch/x86/include/asm/topology.h
--- linux/arch/x86/include/asm/topology.h 2014-05-29 12:18:18.614552622 +0900
+++ rpi/arch/x86/include/asm/topology.h 2014-05-29 11:49:12.267897475 +0900
@@ -119,9 +119,10 @@
extern const struct cpumask *cpu_coregroup_mask(int cpu);
-#ifdef ENABLE_TOPO_DEFINES
#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id)
#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id)
+
+#ifdef ENABLE_TOPO_DEFINES
#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu))
#define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu))
#endif
diff -Nur linux/arch/x86/include/uapi/asm/msr-index.h rpi/arch/x86/include/uapi/asm/msr-index.h
--- linux/arch/x86/include/uapi/asm/msr-index.h 2014-05-29 12:18:18.624552560 +0900
+++ rpi/arch/x86/include/uapi/asm/msr-index.h 2014-05-29 11:49:12.283897341 +0900
@@ -182,6 +182,7 @@
#define MSR_AMD64_PATCH_LOADER 0xc0010020
#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
#define MSR_AMD64_OSVW_STATUS 0xc0010141
+#define MSR_AMD64_LS_CFG 0xc0011020
#define MSR_AMD64_DC_CFG 0xc0011022
#define MSR_AMD64_BU_CFG2 0xc001102a
#define MSR_AMD64_IBSFETCHCTL 0xc0011030
diff -Nur linux/arch/x86/kernel/cpu/amd.c rpi/arch/x86/kernel/cpu/amd.c
--- linux/arch/x86/kernel/cpu/amd.c 2014-05-29 12:18:18.640552460 +0900
+++ rpi/arch/x86/kernel/cpu/amd.c 2014-05-29 11:49:12.305897157 +0900
@@ -508,6 +508,16 @@
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
}
#endif
+
+ /* F16h erratum 793, CVE-2013-6885 */
+ if (c->x86 == 0x16 && c->x86_model <= 0xf) {
+ u64 val;
+
+ rdmsrl(MSR_AMD64_LS_CFG, val);
+ if (!(val & BIT(15)))
+ wrmsrl(MSR_AMD64_LS_CFG, val | BIT(15));
+ }
+
}
static const int amd_erratum_383[];
diff -Nur linux/arch/x86/kernel/cpu/common.c rpi/arch/x86/kernel/cpu/common.c
--- linux/arch/x86/kernel/cpu/common.c 2014-05-29 12:18:18.641552453 +0900
+++ rpi/arch/x86/kernel/cpu/common.c 2014-05-29 11:49:12.306897148 +0900
@@ -284,8 +284,13 @@
raw_local_save_flags(eflags);
BUG_ON(eflags & X86_EFLAGS_AC);
- if (cpu_has(c, X86_FEATURE_SMAP))
+ if (cpu_has(c, X86_FEATURE_SMAP)) {
+#ifdef CONFIG_X86_SMAP
set_in_cr4(X86_CR4_SMAP);
+#else
+ clear_in_cr4(X86_CR4_SMAP);
+#endif
+ }
}
/*
diff -Nur linux/arch/x86/kernel/cpu/intel.c rpi/arch/x86/kernel/cpu/intel.c
--- linux/arch/x86/kernel/cpu/intel.c 2014-05-29 12:18:18.642552447 +0900
+++ rpi/arch/x86/kernel/cpu/intel.c 2014-05-29 11:49:12.307897140 +0900
@@ -387,7 +387,8 @@
set_cpu_cap(c, X86_FEATURE_PEBS);
}
- if (c->x86 == 6 && c->x86_model == 29 && cpu_has_clflush)
+ if (c->x86 == 6 && cpu_has_clflush &&
+ (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
set_cpu_cap(c, X86_FEATURE_CLFLUSH_MONITOR);
#ifdef CONFIG_X86_64
@@ -627,7 +628,7 @@
tlb_flushall_shift = 5;
break;
case 0x63a: /* Ivybridge */
- tlb_flushall_shift = 1;
+ tlb_flushall_shift = 2;
break;
default:
tlb_flushall_shift = 6;
diff -Nur linux/arch/x86/kernel/cpu/perf_event_amd_ibs.c rpi/arch/x86/kernel/cpu/perf_event_amd_ibs.c
--- linux/arch/x86/kernel/cpu/perf_event_amd_ibs.c 2014-05-29 12:18:18.650552397 +0900
+++ rpi/arch/x86/kernel/cpu/perf_event_amd_ibs.c 2014-05-29 11:49:12.318897048 +0900
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
+#include <linux/syscore_ops.h>
#include <asm/apic.h>
@@ -816,6 +817,18 @@
return ret;
}
+static void ibs_eilvt_setup(void)
+{
+ /*
+ * Force LVT offset assignment for family 10h: The offsets are
+ * not assigned by the BIOS for this family, so the OS is
+ * responsible for doing it. If the OS assignment fails, fall
+ * back to BIOS settings and try to setup this.
+ */
+ if (boot_cpu_data.x86 == 0x10)
+ force_ibs_eilvt_setup();
+}
+
static inline int get_ibs_lvt_offset(void)
{
u64 val;
@@ -851,6 +864,36 @@
setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
}
+#ifdef CONFIG_PM
+
+static int perf_ibs_suspend(void)
+{
+ clear_APIC_ibs(NULL);
+ return 0;
+}
+
+static void perf_ibs_resume(void)
+{
+ ibs_eilvt_setup();
+ setup_APIC_ibs(NULL);
+}
+
+static struct syscore_ops perf_ibs_syscore_ops = {
+ .resume = perf_ibs_resume,
+ .suspend = perf_ibs_suspend,
+};
+
+static void perf_ibs_pm_init(void)
+{
+ register_syscore_ops(&perf_ibs_syscore_ops);
+}
+
+#else
+
+static inline void perf_ibs_pm_init(void) { }
+
+#endif
+
static int
perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
{
@@ -877,18 +920,12 @@
if (!caps)
return -ENODEV; /* ibs not supported by the cpu */
- /*
- * Force LVT offset assignment for family 10h: The offsets are
- * not assigned by the BIOS for this family, so the OS is
- * responsible for doing it. If the OS assignment fails, fall
- * back to BIOS settings and try to setup this.
- */
- if (boot_cpu_data.x86 == 0x10)
- force_ibs_eilvt_setup();
+ ibs_eilvt_setup();
if (!ibs_eilvt_valid())
goto out;
+ perf_ibs_pm_init();
get_online_cpus();
ibs_caps = caps;
/* make ibs_caps visible to other cpus: */
diff -Nur linux/arch/x86/kernel/cpu/perf_event.c rpi/arch/x86/kernel/cpu/perf_event.c
--- linux/arch/x86/kernel/cpu/perf_event.c 2014-05-29 12:18:18.649552403 +0900
+++ rpi/arch/x86/kernel/cpu/perf_event.c 2014-05-29 11:49:12.316897065 +0900
@@ -1192,6 +1192,9 @@
for (i = 0; i < cpuc->n_events; i++) {
if (event == cpuc->event_list[i]) {
+ if (i >= cpuc->n_events - cpuc->n_added)
+ --cpuc->n_added;
+
if (x86_pmu.put_event_constraints)
x86_pmu.put_event_constraints(cpuc, event);
diff -Nur linux/arch/x86/kernel/crash.c rpi/arch/x86/kernel/crash.c
--- linux/arch/x86/kernel/crash.c 2014-05-29 12:18:18.660552334 +0900
+++ rpi/arch/x86/kernel/crash.c 2014-05-29 11:49:12.325896989 +0900
@@ -127,12 +127,12 @@
cpu_emergency_vmxoff();
cpu_emergency_svm_disable();
- lapic_shutdown();
#ifdef CONFIG_X86_IO_APIC
/* Prevent crash_kexec() from deadlocking on ioapic_lock. */
ioapic_zap_locks();
disable_IO_APIC();
#endif
+ lapic_shutdown();
#ifdef CONFIG_HPET_TIMER
hpet_disable();
#endif
diff -Nur linux/arch/x86/kernel/dumpstack.c rpi/arch/x86/kernel/dumpstack.c
--- linux/arch/x86/kernel/dumpstack.c 2014-05-29 12:18:18.661552328 +0900
+++ rpi/arch/x86/kernel/dumpstack.c 2014-05-29 11:49:12.326896981 +0900
@@ -25,12 +25,17 @@
int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
static int die_counter;
-void printk_address(unsigned long address, int reliable)
+static void printk_stack_address(unsigned long address, int reliable)
{
pr_cont(" [<%p>] %s%pB\n",
(void *)address, reliable ? "" : "? ", (void *)address);
}
+void printk_address(unsigned long address)
+{
+ pr_cont(" [<%p>] %pS\n", (void *)address, (void *)address);
+}
+
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
static void
print_ftrace_graph_addr(unsigned long addr, void *data,
@@ -151,7 +156,7 @@
{
touch_nmi_watchdog();
printk(data);
- printk_address(addr, reliable);
+ printk_stack_address(addr, reliable);
}
static const struct stacktrace_ops print_trace_ops = {
@@ -281,7 +286,7 @@
#else
/* Executive summary in case the oops scrolled away */
printk(KERN_ALERT "RIP ");
- printk_address(regs->ip, 1);
+ printk_address(regs->ip);
printk(" RSP <%016lx>\n", regs->sp);
#endif
return 0;
diff -Nur linux/arch/x86/kernel/early-quirks.c rpi/arch/x86/kernel/early-quirks.c
--- linux/arch/x86/kernel/early-quirks.c 2014-05-29 12:18:18.663552316 +0900
+++ rpi/arch/x86/kernel/early-quirks.c 2014-05-29 11:49:12.328896964 +0900
@@ -203,18 +203,15 @@
revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID);
/*
- * Revision 13 of all triggering devices id in this quirk have
- * a problem draining interrupts when irq remapping is enabled,
- * and should be flagged as broken. Additionally revisions 0x12
- * and 0x22 of device id 0x3405 has this problem.
+ * Revision <= 13 of all triggering devices id in this quirk
+ * have a problem draining interrupts when irq remapping is
+ * enabled, and should be flagged as broken. Additionally
+ * revision 0x22 of device id 0x3405 has this problem.
*/
- if (revision == 0x13)
+ if (revision <= 0x13)
set_irq_remapping_broken();
- else if ((device == 0x3405) &&
- ((revision == 0x12) ||
- (revision == 0x22)))
+ else if (device == 0x3405 && revision == 0x22)
set_irq_remapping_broken();
-
}
/*
diff -Nur linux/arch/x86/kernel/entry_32.S rpi/arch/x86/kernel/entry_32.S
--- linux/arch/x86/kernel/entry_32.S 2014-05-29 12:18:18.664552309 +0900
+++ rpi/arch/x86/kernel/entry_32.S 2014-05-29 11:49:12.329896956 +0900
@@ -1085,7 +1085,7 @@
pushl $0 /* Pass NULL as regs pointer */
movl 4*4(%esp), %eax
movl 0x4(%ebp), %edx
- leal function_trace_op, %ecx
+ movl function_trace_op, %ecx
subl $MCOUNT_INSN_SIZE, %eax
.globl ftrace_call
@@ -1143,7 +1143,7 @@
movl 12*4(%esp), %eax /* Load ip (1st parameter) */
subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */
movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */
- leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
+ movl function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
pushl %esp /* Save pt_regs as 4th parameter */
GLOBAL(ftrace_regs_call)
diff -Nur linux/arch/x86/kernel/entry_64.S rpi/arch/x86/kernel/entry_64.S
--- linux/arch/x86/kernel/entry_64.S 2014-05-29 12:18:18.665552303 +0900
+++ rpi/arch/x86/kernel/entry_64.S 2014-05-29 11:49:12.330896947 +0900
@@ -88,7 +88,7 @@
MCOUNT_SAVE_FRAME \skip
/* Load the ftrace_ops into the 3rd parameter */
- leaq function_trace_op, %rdx
+ movq function_trace_op(%rip), %rdx
/* Load ip into the first parameter */
movq RIP(%rsp), %rdi
diff -Nur linux/arch/x86/kernel/ftrace.c rpi/arch/x86/kernel/ftrace.c
--- linux/arch/x86/kernel/ftrace.c 2014-05-29 12:18:18.666552297 +0900
+++ rpi/arch/x86/kernel/ftrace.c 2014-05-29 11:49:12.330896947 +0900
@@ -77,8 +77,7 @@
return addr >= start && addr < end;
}
-static int
-do_ftrace_mod_code(unsigned long ip, const void *new_code)
+static unsigned long text_ip_addr(unsigned long ip)
{
/*
* On x86_64, kernel text mappings are mapped read-only with
@@ -91,7 +90,7 @@
if (within(ip, (unsigned long)_text, (unsigned long)_etext))
ip = (unsigned long)__va(__pa_symbol(ip));
- return probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE);
+ return ip;
}
static const unsigned char *ftrace_nop_replace(void)
@@ -123,8 +122,10 @@
if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
return -EINVAL;
+ ip = text_ip_addr(ip);
+
/* replace the text with the new text */
- if (do_ftrace_mod_code(ip, new_code))
+ if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE))
return -EPERM;
sync_core();
@@ -221,33 +222,56 @@
return -EINVAL;
}
-int ftrace_update_ftrace_func(ftrace_func_t func)
+static unsigned long ftrace_update_func;
+
+static int update_ftrace_func(unsigned long ip, void *new)
{
- unsigned long ip = (unsigned long)(&ftrace_call);
- unsigned char old[MCOUNT_INSN_SIZE], *new;
+ unsigned char old[MCOUNT_INSN_SIZE];
int ret;
- memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
- new = ftrace_call_replace(ip, (unsigned long)func);
+ memcpy(old, (void *)ip, MCOUNT_INSN_SIZE);
+
+ ftrace_update_func = ip;
+ /* Make sure the breakpoints see the ftrace_update_func update */
+ smp_wmb();
/* See comment above by declaration of modifying_ftrace_code */
atomic_inc(&modifying_ftrace_code);
ret = ftrace_modify_code(ip, old, new);
+ atomic_dec(&modifying_ftrace_code);
+
+ return ret;
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+ unsigned long ip = (unsigned long)(&ftrace_call);
+ unsigned char *new;
+ int ret;
+
+ new = ftrace_call_replace(ip, (unsigned long)func);
+ ret = update_ftrace_func(ip, new);
+
/* Also update the regs callback function */
if (!ret) {
ip = (unsigned long)(&ftrace_regs_call);
- memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE);
new = ftrace_call_replace(ip, (unsigned long)func);
- ret = ftrace_modify_code(ip, old, new);
+ ret = update_ftrace_func(ip, new);
}
- atomic_dec(&modifying_ftrace_code);
-
return ret;
}
+static int is_ftrace_caller(unsigned long ip)
+{
+ if (ip == ftrace_update_func)
+ return 1;
+
+ return 0;
+}
+
/*
* A breakpoint was added to the code address we are about to
* modify, and this is the handle that will just skip over it.
@@ -257,10 +281,13 @@
*/
int ftrace_int3_handler(struct pt_regs *regs)
{
+ unsigned long ip;
+
if (WARN_ON_ONCE(!regs))
return 0;
- if (!ftrace_location(regs->ip - 1))
+ ip = regs->ip - 1;
+ if (!ftrace_location(ip) && !is_ftrace_caller(ip))
return 0;
regs->ip += MCOUNT_INSN_SIZE - 1;
@@ -632,8 +659,8 @@
ret = -EPERM;
goto out;
}
- run_sync();
out:
+ run_sync();
return ret;
fail_update:
@@ -665,45 +692,41 @@
#ifdef CONFIG_DYNAMIC_FTRACE
extern void ftrace_graph_call(void);
-static int ftrace_mod_jmp(unsigned long ip,
- int old_offset, int new_offset)
+static unsigned char *ftrace_jmp_replace(unsigned long ip, unsigned long addr)
{
- unsigned char code[MCOUNT_INSN_SIZE];
+ static union ftrace_code_union calc;
- if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE))
- return -EFAULT;
+ /* Jmp not a call (ignore the .e8) */
+ calc.e8 = 0xe9;
+ calc.offset = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr);
- if (code[0] != 0xe9 || old_offset != *(int *)(&code[1]))
- return -EINVAL;
+ /*
+ * ftrace external locks synchronize the access to the static variable.
+ */
+ return calc.code;
+}
- *(int *)(&code[1]) = new_offset;
+static int ftrace_mod_jmp(unsigned long ip, void *func)
+{
+ unsigned char *new;
- if (do_ftrace_mod_code(ip, &code))
- return -EPERM;
+ new = ftrace_jmp_replace(ip, (unsigned long)func);
- return 0;
+ return update_ftrace_func(ip, new);
}
int ftrace_enable_ftrace_graph_caller(void)
{
unsigned long ip = (unsigned long)(&ftrace_graph_call);
- int old_offset, new_offset;
- old_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE);
- new_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE);
-
- return ftrace_mod_jmp(ip, old_offset, new_offset);
+ return ftrace_mod_jmp(ip, &ftrace_graph_caller);
}
int ftrace_disable_ftrace_graph_caller(void)
{
unsigned long ip = (unsigned long)(&ftrace_graph_call);
- int old_offset, new_offset;
-
- old_offset = (unsigned long)(&ftrace_graph_caller) - (ip + MCOUNT_INSN_SIZE);
- new_offset = (unsigned long)(&ftrace_stub) - (ip + MCOUNT_INSN_SIZE);
- return ftrace_mod_jmp(ip, old_offset, new_offset);
+ return ftrace_mod_jmp(ip, &ftrace_stub);
}
#endif /* !CONFIG_DYNAMIC_FTRACE */
diff -Nur linux/arch/x86/kernel/head_32.S rpi/arch/x86/kernel/head_32.S
--- linux/arch/x86/kernel/head_32.S 2014-05-29 12:18:18.667552291 +0900
+++ rpi/arch/x86/kernel/head_32.S 2014-05-29 11:49:12.331896939 +0900
@@ -544,6 +544,10 @@
/* This is global to keep gas from relaxing the jumps */
ENTRY(early_idt_handler)
cld
+
+ cmpl $2,(%esp) # X86_TRAP_NMI
+ je is_nmi # Ignore NMI
+
cmpl $2,%ss:early_recursion_flag
je hlt_loop
incl %ss:early_recursion_flag
@@ -594,8 +598,9 @@
pop %edx
pop %ecx
pop %eax
- addl $8,%esp /* drop vector number and error code */
decl %ss:early_recursion_flag
+is_nmi:
+ addl $8,%esp /* drop vector number and error code */
iret
ENDPROC(early_idt_handler)
diff -Nur linux/arch/x86/kernel/head_64.S rpi/arch/x86/kernel/head_64.S
--- linux/arch/x86/kernel/head_64.S 2014-05-29 12:18:18.667552291 +0900
+++ rpi/arch/x86/kernel/head_64.S 2014-05-29 11:49:12.331896939 +0900
@@ -343,6 +343,9 @@
ENTRY(early_idt_handler)
cld
+ cmpl $2,(%rsp) # X86_TRAP_NMI
+ je is_nmi # Ignore NMI
+
cmpl $2,early_recursion_flag(%rip)
jz 1f
incl early_recursion_flag(%rip)
@@ -405,8 +408,9 @@
popq %rdx
popq %rcx
popq %rax
- addq $16,%rsp # drop vector number and error code
decl early_recursion_flag(%rip)
+is_nmi:
+ addq $16,%rsp # drop vector number and error code
INTERRUPT_RETURN
ENDPROC(early_idt_handler)
diff -Nur linux/arch/x86/kernel/i387.c rpi/arch/x86/kernel/i387.c
--- linux/arch/x86/kernel/i387.c 2014-05-29 12:18:18.670552272 +0900
+++ rpi/arch/x86/kernel/i387.c 2014-05-29 11:49:12.333896922 +0900
@@ -86,10 +86,19 @@
void __kernel_fpu_end(void)
{
- if (use_eager_fpu())
- math_state_restore();
- else
+ if (use_eager_fpu()) {
+ /*
+ * For eager fpu, most the time, tsk_used_math() is true.
+ * Restore the user math as we are done with the kernel usage.
+ * At few instances during thread exit, signal handling etc,
+ * tsk_used_math() is false. Those few places will take proper
+ * actions, so we don't need to restore the math here.
+ */
+ if (likely(tsk_used_math(current)))
+ math_state_restore();
+ } else {
stts();
+ }
}
EXPORT_SYMBOL(__kernel_fpu_end);
diff -Nur linux/arch/x86/kernel/kvm.c rpi/arch/x86/kernel/kvm.c
--- linux/arch/x86/kernel/kvm.c 2014-05-29 12:18:18.674552247 +0900
+++ rpi/arch/x86/kernel/kvm.c 2014-05-29 11:49:12.338896880 +0900
@@ -500,6 +500,38 @@
#endif
}
+static noinline uint32_t __kvm_cpuid_base(void)
+{
+ if (boot_cpu_data.cpuid_level < 0)
+ return 0; /* So we don't blow up on old processors */
+
+ if (cpu_has_hypervisor)
+ return hypervisor_cpuid_base("KVMKVMKVM\0\0\0", 0);
+
+ return 0;
+}
+
+static inline uint32_t kvm_cpuid_base(void)
+{
+ static int kvm_cpuid_base = -1;
+
+ if (kvm_cpuid_base == -1)
+ kvm_cpuid_base = __kvm_cpuid_base();
+
+ return kvm_cpuid_base;
+}
+
+bool kvm_para_available(void)
+{
+ return kvm_cpuid_base() != 0;
+}
+EXPORT_SYMBOL_GPL(kvm_para_available);
+
+unsigned int kvm_arch_para_features(void)
+{
+ return cpuid_eax(kvm_cpuid_base() | KVM_CPUID_FEATURES);
+}
+
static uint32_t __init kvm_detect(void)
{
return kvm_cpuid_base();
diff -Nur linux/arch/x86/kernel/ldt.c rpi/arch/x86/kernel/ldt.c
--- linux/arch/x86/kernel/ldt.c 2014-05-29 12:18:18.675552240 +0900
+++ rpi/arch/x86/kernel/ldt.c 2014-05-29 11:49:12.339896872 +0900
@@ -229,6 +229,17 @@
}
}
+ /*
+ * On x86-64 we do not support 16-bit segments due to
+ * IRET leaking the high bits of the kernel stack address.
+ */
+#ifdef CONFIG_X86_64
+ if (!ldt_info.seg_32bit) {
+ error = -EINVAL;
+ goto out_unlock;
+ }
+#endif
+
fill_ldt(&ldt, &ldt_info);
if (oldmode)
ldt.avl = 0;
diff -Nur linux/arch/x86/kernel/microcode_amd.c rpi/arch/x86/kernel/microcode_amd.c
--- linux/arch/x86/kernel/microcode_amd.c 2014-05-29 12:18:18.676552234 +0900
+++ rpi/arch/x86/kernel/microcode_amd.c 2014-05-29 11:49:12.339896872 +0900
@@ -431,7 +431,7 @@
snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
if (request_firmware(&fw, (const char *)fw_name, device)) {
- pr_err("failed to load file %s\n", fw_name);
+ pr_debug("failed to load file %s\n", fw_name);
goto out;
}
diff -Nur linux/arch/x86/kernel/pci-dma.c rpi/arch/x86/kernel/pci-dma.c
--- linux/arch/x86/kernel/pci-dma.c 2014-05-29 12:18:18.681552203 +0900
+++ rpi/arch/x86/kernel/pci-dma.c 2014-05-29 11:49:12.345896822 +0900
@@ -100,8 +100,10 @@
flag |= __GFP_ZERO;
again:
page = NULL;
- if (!(flag & GFP_ATOMIC))
+ /* CMA can be used only in the context which permits sleeping */
+ if (flag & __GFP_WAIT)
page = dma_alloc_from_contiguous(dev, count, get_order(size));
+ /* fallback */
if (!page)
page = alloc_pages_node(dev_to_node(dev), flag, get_order(size));
if (!page)
diff -Nur linux/arch/x86/kernel/process_64.c rpi/arch/x86/kernel/process_64.c
--- linux/arch/x86/kernel/process_64.c 2014-05-29 12:18:18.683552191 +0900
+++ rpi/arch/x86/kernel/process_64.c 2014-05-29 11:49:12.348896796 +0900
@@ -63,7 +63,7 @@
unsigned int ds, cs, es;
printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
- printk_address(regs->ip, 1);
+ printk_address(regs->ip);
printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss,
regs->sp, regs->flags);
printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n",
diff -Nur linux/arch/x86/kernel/process.c rpi/arch/x86/kernel/process.c
--- linux/arch/x86/kernel/process.c 2014-05-29 12:18:18.681552203 +0900
+++ rpi/arch/x86/kernel/process.c 2014-05-29 11:49:12.347896805 +0900
@@ -391,9 +391,9 @@
* The switch back from broadcast mode needs to be
* called with interrupts disabled.
*/
- local_irq_disable();
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
- local_irq_enable();
+ local_irq_disable();
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+ local_irq_enable();
} else
default_idle();
}
diff -Nur linux/arch/x86/kernel/quirks.c rpi/arch/x86/kernel/quirks.c
--- linux/arch/x86/kernel/quirks.c 2014-05-29 12:18:18.684552184 +0900
+++ rpi/arch/x86/kernel/quirks.c 2014-05-29 11:49:12.349896788 +0900
@@ -529,7 +529,7 @@
return;
pci_read_config_dword(nb_ht, 0x60, &val);
- node = val & 7;
+ node = pcibus_to_node(dev->bus) | (val & 7);
/*
* Some hardware may return an invalid node ID,
* so check it first:
@@ -571,3 +571,40 @@
quirk_amd_nb_node);
#endif
+
+#ifdef CONFIG_PCI
+/*
+ * Processor does not ensure DRAM scrub read/write sequence
+ * is atomic wrt accesses to CC6 save state area. Therefore
+ * if a concurrent scrub read/write access is to same address
+ * the entry may appear as if it is not written. This quirk
+ * applies to Fam16h models 00h-0Fh
+ *
+ * See "Revision Guide" for AMD F16h models 00h-0fh,
+ * document 51810 rev. 3.04, Nov 2013
+ */
+static void amd_disable_seq_and_redirect_scrub(struct pci_dev *dev)
+{
+ u32 val;
+
+ /*
+ * Suggested workaround:
+ * set D18F3x58[4:0] = 00h and set D18F3x5C[0] = 0b
+ */
+ pci_read_config_dword(dev, 0x58, &val);
+ if (val & 0x1F) {
+ val &= ~(0x1F);
+ pci_write_config_dword(dev, 0x58, val);
+ }
+
+ pci_read_config_dword(dev, 0x5C, &val);
+ if (val & BIT(0)) {
+ val &= ~BIT(0);
+ pci_write_config_dword(dev, 0x5c, val);
+ }
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3,
+ amd_disable_seq_and_redirect_scrub);
+
+#endif
diff -Nur linux/arch/x86/kernel/reboot.c rpi/arch/x86/kernel/reboot.c
--- linux/arch/x86/kernel/reboot.c 2014-05-29 12:18:18.685552178 +0900
+++ rpi/arch/x86/kernel/reboot.c 2014-05-29 11:49:12.350896780 +0900
@@ -550,6 +550,10 @@
void native_machine_shutdown(void)
{
/* Stop the cpus and apics */
+#ifdef CONFIG_X86_IO_APIC
+ disable_IO_APIC();
+#endif
+
#ifdef CONFIG_SMP
/*
* Stop all of the others. Also disable the local irq to
@@ -562,10 +566,6 @@
lapic_shutdown();
-#ifdef CONFIG_X86_IO_APIC
- disable_IO_APIC();
-#endif
-
#ifdef CONFIG_HPET_TIMER
hpet_disable();
#endif
diff -Nur linux/arch/x86/kvm/emulate.c rpi/arch/x86/kvm/emulate.c
--- linux/arch/x86/kvm/emulate.c 2014-05-29 12:18:18.696552109 +0900
+++ rpi/arch/x86/kvm/emulate.c 2014-05-29 11:49:12.366896646 +0900
@@ -4040,7 +4040,10 @@
case OpMem8:
ctxt->memop.bytes = 1;
if (ctxt->memop.type == OP_REG) {
- ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, 1);
+ int highbyte_regs = ctxt->rex_prefix == 0;
+
+ ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm,
+ highbyte_regs);
fetch_register_operand(&ctxt->memop);
}
goto mem_common;
diff -Nur linux/arch/x86/kvm/i8254.c rpi/arch/x86/kvm/i8254.c
--- linux/arch/x86/kvm/i8254.c 2014-05-29 12:18:18.697552103 +0900
+++ rpi/arch/x86/kvm/i8254.c 2014-05-29 11:49:12.366896646 +0900
@@ -37,6 +37,7 @@
#include "irq.h"
#include "i8254.h"
+#include "x86.h"
#ifndef CONFIG_X86_64
#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
@@ -349,6 +350,23 @@
atomic_set(&ps->pending, 0);
ps->irq_ack = 1;
+ /*
+ * Do not allow the guest to program periodic timers with small
+ * interval, since the hrtimers are not throttled by the host
+ * scheduler.
+ */
+ if (ps->is_periodic) {
+ s64 min_period = min_timer_period_us * 1000LL;
+
+ if (ps->period < min_period) {
+ pr_info_ratelimited(
+ "kvm: requested %lld ns "
+ "i8254 timer period limited to %lld ns\n",
+ ps->period, min_period);
+ ps->period = min_period;
+ }
+ }
+
hrtimer_start(&ps->timer, ktime_add_ns(ktime_get(), interval),
HRTIMER_MODE_ABS);
}
diff -Nur linux/arch/x86/kvm/lapic.c rpi/arch/x86/kvm/lapic.c
--- linux/arch/x86/kvm/lapic.c 2014-05-29 12:18:18.698552097 +0900
+++ rpi/arch/x86/kvm/lapic.c 2014-05-29 11:49:12.368896629 +0900
@@ -71,9 +71,6 @@
#define VEC_POS(v) ((v) & (32 - 1))
#define REG_POS(v) (((v) >> 5) << 4)
-static unsigned int min_timer_period_us = 500;
-module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
-
static inline void apic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val)
{
*((u32 *) (apic->regs + reg_off)) = val;
@@ -143,6 +140,8 @@
return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff;
}
+#define KVM_X2APIC_CID_BITS 0
+
static void recalculate_apic_map(struct kvm *kvm)
{
struct kvm_apic_map *new, *old = NULL;
@@ -180,7 +179,8 @@
if (apic_x2apic_mode(apic)) {
new->ldr_bits = 32;
new->cid_shift = 16;
- new->cid_mask = new->lid_mask = 0xffff;
+ new->cid_mask = (1 << KVM_X2APIC_CID_BITS) - 1;
+ new->lid_mask = 0xffff;
} else if (kvm_apic_sw_enabled(apic) &&
!new->cid_mask /* flat mode */ &&
kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_CLUSTER) {
@@ -841,7 +841,8 @@
ASSERT(apic != NULL);
/* if initial count is 0, current count should also be 0 */
- if (kvm_apic_get_reg(apic, APIC_TMICT) == 0)
+ if (kvm_apic_get_reg(apic, APIC_TMICT) == 0 ||
+ apic->lapic_timer.period == 0)
return 0;
remaining = hrtimer_get_remaining(&apic->lapic_timer.timer);
@@ -1346,8 +1347,12 @@
return;
}
+ if (!kvm_vcpu_is_bsp(apic->vcpu))
+ value &= ~MSR_IA32_APICBASE_BSP;
+ vcpu->arch.apic_base = value;
+
/* update jump label if enable bit changes */
- if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) {
+ if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) {
if (value & MSR_IA32_APICBASE_ENABLE)
static_key_slow_dec_deferred(&apic_hw_disabled);
else
@@ -1355,10 +1360,6 @@
recalculate_apic_map(vcpu->kvm);
}
- if (!kvm_vcpu_is_bsp(apic->vcpu))
- value &= ~MSR_IA32_APICBASE_BSP;
-
- vcpu->arch.apic_base = value;
if ((old_value ^ value) & X2APIC_ENABLE) {
if (value & X2APIC_ENABLE) {
u32 id = kvm_apic_id(apic);
@@ -1691,7 +1692,6 @@
void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
{
u32 data;
- void *vapic;
if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention))
apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic);
@@ -1699,9 +1699,8 @@
if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
return;
- vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
- data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr));
- kunmap_atomic(vapic);
+ kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
+ sizeof(u32));
apic_set_tpr(vcpu->arch.apic, data & 0xff);
}
@@ -1737,7 +1736,6 @@
u32 data, tpr;
int max_irr, max_isr;
struct kvm_lapic *apic = vcpu->arch.apic;
- void *vapic;
apic_sync_pv_eoi_to_guest(vcpu, apic);
@@ -1753,18 +1751,24 @@
max_isr = 0;
data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24);
- vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
- *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data;
- kunmap_atomic(vapic);
+ kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
+ sizeof(u32));
}
-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
+int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
{
- vcpu->arch.apic->vapic_addr = vapic_addr;
- if (vapic_addr)
+ if (vapic_addr) {
+ if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
+ &vcpu->arch.apic->vapic_cache,
+ vapic_addr, sizeof(u32)))
+ return -EINVAL;
__set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
- else
+ } else {
__clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
+ }
+
+ vcpu->arch.apic->vapic_addr = vapic_addr;
+ return 0;
}
int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data)
diff -Nur linux/arch/x86/kvm/lapic.h rpi/arch/x86/kvm/lapic.h
--- linux/arch/x86/kvm/lapic.h 2014-05-29 12:18:18.698552097 +0900
+++ rpi/arch/x86/kvm/lapic.h 2014-05-29 11:49:12.368896629 +0900
@@ -34,7 +34,7 @@
*/
void *regs;
gpa_t vapic_addr;
- struct page *vapic_page;
+ struct gfn_to_hva_cache vapic_cache;
unsigned long pending_events;
unsigned int sipi_vector;
};
@@ -76,7 +76,7 @@
void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset);
void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector);
-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
+int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
diff -Nur linux/arch/x86/kvm/mmu.c rpi/arch/x86/kvm/mmu.c
--- linux/arch/x86/kvm/mmu.c 2014-05-29 12:18:18.700552084 +0900
+++ rpi/arch/x86/kvm/mmu.c 2014-05-29 11:49:12.370896612 +0900
@@ -2664,6 +2664,9 @@
int emulate = 0;
gfn_t pseudo_gfn;
+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+ return 0;
+
for_each_shadow_entry(vcpu, (u64)gfn << PAGE_SHIFT, iterator) {
if (iterator.level == level) {
mmu_set_spte(vcpu, iterator.sptep, ACC_ALL,
@@ -2834,6 +2837,9 @@
bool ret = false;
u64 spte = 0ull;
+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+ return false;
+
if (!page_fault_can_be_fast(error_code))
return false;
@@ -3229,6 +3235,9 @@
struct kvm_shadow_walk_iterator iterator;
u64 spte = 0ull;
+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+ return spte;
+
walk_shadow_page_lockless_begin(vcpu);
for_each_shadow_entry_lockless(vcpu, addr, iterator, spte)
if (!is_shadow_present_pte(spte))
@@ -4557,6 +4566,9 @@
u64 spte;
int nr_sptes = 0;
+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+ return nr_sptes;
+
walk_shadow_page_lockless_begin(vcpu);
for_each_shadow_entry_lockless(vcpu, addr, iterator, spte) {
sptes[iterator.level-1] = spte;
diff -Nur linux/arch/x86/kvm/paging_tmpl.h rpi/arch/x86/kvm/paging_tmpl.h
--- linux/arch/x86/kvm/paging_tmpl.h 2014-05-29 12:18:18.701552078 +0900
+++ rpi/arch/x86/kvm/paging_tmpl.h 2014-05-29 11:49:12.372896595 +0900
@@ -569,6 +569,9 @@
if (FNAME(gpte_changed)(vcpu, gw, top_level))
goto out_gpte_changed;
+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+ goto out_gpte_changed;
+
for (shadow_walk_init(&it, vcpu, addr);
shadow_walk_okay(&it) && it.level > gw->level;
shadow_walk_next(&it)) {
@@ -820,6 +823,11 @@
*/
mmu_topup_memory_caches(vcpu);
+ if (!VALID_PAGE(vcpu->arch.mmu.root_hpa)) {
+ WARN_ON(1);
+ return;
+ }
+
spin_lock(&vcpu->kvm->mmu_lock);
for_each_shadow_entry(vcpu, gva, iterator) {
level = iterator.level;
diff -Nur linux/arch/x86/kvm/svm.c rpi/arch/x86/kvm/svm.c
--- linux/arch/x86/kvm/svm.c 2014-05-29 12:18:18.703552065 +0900
+++ rpi/arch/x86/kvm/svm.c 2014-05-29 11:49:12.374896579 +0900
@@ -2993,10 +2993,8 @@
u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
/* instruction emulation calls kvm_set_cr8() */
r = cr_interception(svm);
- if (irqchip_in_kernel(svm->vcpu.kvm)) {
- clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
+ if (irqchip_in_kernel(svm->vcpu.kvm))
return r;
- }
if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
return r;
kvm_run->exit_reason = KVM_EXIT_SET_TPR;
@@ -3558,6 +3556,8 @@
if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK))
return;
+ clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
+
if (irr == -1)
return;
diff -Nur linux/arch/x86/kvm/vmx.c rpi/arch/x86/kvm/vmx.c
--- linux/arch/x86/kvm/vmx.c 2014-05-29 12:18:18.706552046 +0900
+++ rpi/arch/x86/kvm/vmx.c 2014-05-29 11:49:12.378896545 +0900
@@ -7294,8 +7294,8 @@
struct vcpu_vmx *vmx = to_vmx(vcpu);
free_vpid(vmx);
- free_nested(vmx);
free_loaded_vmcs(vmx->loaded_vmcs);
+ free_nested(vmx);
kfree(vmx->guest_msrs);
kvm_vcpu_uninit(vcpu);
kmem_cache_free(kvm_vcpu_cache, vmx);
@@ -8218,8 +8218,7 @@
vcpu->arch.cr4_guest_owned_bits = ~vmcs_readl(CR4_GUEST_HOST_MASK);
kvm_set_cr4(vcpu, vmcs12->host_cr4);
- if (nested_cpu_has_ept(vmcs12))
- nested_ept_uninit_mmu_context(vcpu);
+ nested_ept_uninit_mmu_context(vcpu);
kvm_set_cr3(vcpu, vmcs12->host_cr3);
kvm_mmu_reset_context(vcpu);
diff -Nur linux/arch/x86/kvm/x86.c rpi/arch/x86/kvm/x86.c
--- linux/arch/x86/kvm/x86.c 2014-05-29 12:18:18.710552022 +0900
+++ rpi/arch/x86/kvm/x86.c 2014-05-29 11:49:12.381896520 +0900
@@ -94,6 +94,9 @@
static bool ignore_msrs = 0;
module_param(ignore_msrs, bool, S_IRUGO | S_IWUSR);
+unsigned int min_timer_period_us = 500;
+module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
+
bool kvm_has_tsc_control;
EXPORT_SYMBOL_GPL(kvm_has_tsc_control);
u32 kvm_max_guest_tsc_khz;
@@ -3192,8 +3195,7 @@
r = -EFAULT;
if (copy_from_user(&va, argp, sizeof va))
goto out;
- r = 0;
- kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
+ r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
break;
}
case KVM_X86_SETUP_MCE: {
@@ -5718,36 +5720,6 @@
!kvm_event_needs_reinjection(vcpu);
}
-static int vapic_enter(struct kvm_vcpu *vcpu)
-{
- struct kvm_lapic *apic = vcpu->arch.apic;
- struct page *page;
-
- if (!apic || !apic->vapic_addr)
- return 0;
-
- page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
- if (is_error_page(page))
- return -EFAULT;
-
- vcpu->arch.apic->vapic_page = page;
- return 0;
-}
-
-static void vapic_exit(struct kvm_vcpu *vcpu)
-{
- struct kvm_lapic *apic = vcpu->arch.apic;
- int idx;
-
- if (!apic || !apic->vapic_addr)
- return;
-
- idx = srcu_read_lock(&vcpu->kvm->srcu);
- kvm_release_page_dirty(apic->vapic_page);
- mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
- srcu_read_unlock(&vcpu->kvm->srcu, idx);
-}
-
static void update_cr8_intercept(struct kvm_vcpu *vcpu)
{
int max_irr, tpr;
@@ -6047,11 +6019,6 @@
struct kvm *kvm = vcpu->kvm;
vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
- r = vapic_enter(vcpu);
- if (r) {
- srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
- return r;
- }
r = 1;
while (r > 0) {
@@ -6110,8 +6077,6 @@
srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
- vapic_exit(vcpu);
-
return r;
}
@@ -6176,7 +6141,7 @@
frag->len -= len;
}
- if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
+ if (vcpu->mmio_cur_fragment >= vcpu->mmio_nr_fragments) {
vcpu->mmio_needed = 0;
/* FIXME: return into emulator if single-stepping. */
diff -Nur linux/arch/x86/kvm/x86.h rpi/arch/x86/kvm/x86.h
--- linux/arch/x86/kvm/x86.h 2014-05-29 12:18:18.710552022 +0900
+++ rpi/arch/x86/kvm/x86.h 2014-05-29 11:49:12.382896511 +0900
@@ -124,5 +124,7 @@
extern u64 host_xcr0;
+extern unsigned int min_timer_period_us;
+
extern struct static_key kvm_no_apic_vcpu;
#endif
diff -Nur linux/arch/x86/Makefile rpi/arch/x86/Makefile
--- linux/arch/x86/Makefile 2014-05-29 12:18:18.574552873 +0900
+++ rpi/arch/x86/Makefile 2014-05-29 11:49:12.184898171 +0900
@@ -31,6 +31,9 @@
KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return
+ # Don't autogenerate MMX or SSE instructions
+ KBUILD_CFLAGS += -mno-mmx -mno-sse
+
# Never want PIC in a 32-bit kernel, prevent breakage with GCC built
# with nonstandard options
KBUILD_CFLAGS += -fno-pic
@@ -57,8 +60,11 @@
KBUILD_AFLAGS += -m64
KBUILD_CFLAGS += -m64
+ # Don't autogenerate MMX or SSE instructions
+ KBUILD_CFLAGS += -mno-mmx -mno-sse
+
# Use -mpreferred-stack-boundary=3 if supported.
- KBUILD_CFLAGS += $(call cc-option,-mno-sse -mpreferred-stack-boundary=3)
+ KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
# FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
diff -Nur linux/arch/x86/mm/fault.c rpi/arch/x86/mm/fault.c
--- linux/arch/x86/mm/fault.c 2014-05-29 12:18:18.717551978 +0900
+++ rpi/arch/x86/mm/fault.c 2014-05-29 11:49:12.404896327 +0900
@@ -596,7 +596,7 @@
printk(KERN_CONT " at %p\n", (void *) address);
printk(KERN_ALERT "IP:");
- printk_address(regs->ip, 1);
+ printk_address(regs->ip);
dump_pagetable(address);
}
@@ -980,6 +980,12 @@
static inline bool smap_violation(int error_code, struct pt_regs *regs)
{
+ if (!IS_ENABLED(CONFIG_X86_SMAP))
+ return false;
+
+ if (!static_cpu_has(X86_FEATURE_SMAP))
+ return false;
+
if (error_code & PF_USER)
return false;
@@ -1081,11 +1087,9 @@
if (unlikely(error_code & PF_RSVD))
pgtable_bad(regs, error_code, address);
- if (static_cpu_has(X86_FEATURE_SMAP)) {
- if (unlikely(smap_violation(error_code, regs))) {
- bad_area_nosemaphore(regs, error_code, address);
- return;
- }
+ if (unlikely(smap_violation(error_code, regs))) {
+ bad_area_nosemaphore(regs, error_code, address);
+ return;
}
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
diff -Nur linux/arch/x86/mm/gup.c rpi/arch/x86/mm/gup.c
--- linux/arch/x86/mm/gup.c 2014-05-29 12:18:18.717551978 +0900
+++ rpi/arch/x86/mm/gup.c 2014-05-29 11:49:12.405896319 +0900
@@ -83,6 +83,12 @@
pte_t pte = gup_get_pte(ptep);
struct page *page;
+ /* Similar to the PMD case, NUMA hinting must take slow path */
+ if (pte_numa(pte)) {
+ pte_unmap(ptep);
+ return 0;
+ }
+
if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {
pte_unmap(ptep);
return 0;
@@ -167,6 +173,13 @@
if (pmd_none(pmd) || pmd_trans_splitting(pmd))
return 0;
if (unlikely(pmd_large(pmd))) {
+ /*
+ * NUMA hinting faults need to be handled in the GUP
+ * slowpath for accounting purposes and so that they
+ * can be serialised against THP migration.
+ */
+ if (pmd_numa(pmd))
+ return 0;
if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))
return 0;
} else {
diff -Nur linux/arch/x86/mm/srat.c rpi/arch/x86/mm/srat.c
--- linux/arch/x86/mm/srat.c 2014-05-29 12:18:18.725551928 +0900
+++ rpi/arch/x86/mm/srat.c 2014-05-29 11:49:12.416896227 +0900
@@ -42,15 +42,25 @@
return acpi_numa < 0;
}
-/* Callback for SLIT parsing */
+/*
+ * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for
+ * I/O localities since SRAT does not list them. I/O localities are
+ * not supported at this point.
+ */
void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
{
int i, j;
- for (i = 0; i < slit->locality_count; i++)
- for (j = 0; j < slit->locality_count; j++)
+ for (i = 0; i < slit->locality_count; i++) {
+ if (pxm_to_node(i) == NUMA_NO_NODE)
+ continue;
+ for (j = 0; j < slit->locality_count; j++) {
+ if (pxm_to_node(j) == NUMA_NO_NODE)
+ continue;
numa_set_distance(pxm_to_node(i), pxm_to_node(j),
slit->entry[slit->locality_count * i + j]);
+ }
+ }
}
/* Callback for Proximity Domain -> x2APIC mapping */
diff -Nur linux/arch/x86/net/bpf_jit_comp.c rpi/arch/x86/net/bpf_jit_comp.c
--- linux/arch/x86/net/bpf_jit_comp.c 2014-05-29 12:18:18.726551921 +0900
+++ rpi/arch/x86/net/bpf_jit_comp.c 2014-05-29 11:49:12.417896218 +0900
@@ -359,15 +359,21 @@
EMIT2(0x89, 0xd0); /* mov %edx,%eax */
break;
case BPF_S_ALU_MOD_K: /* A %= K; */
+ if (K == 1) {
+ CLEAR_A();
+ break;
+ }
EMIT2(0x31, 0xd2); /* xor %edx,%edx */
EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */
EMIT2(0xf7, 0xf1); /* div %ecx */
EMIT2(0x89, 0xd0); /* mov %edx,%eax */
break;
- case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
- EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */
- EMIT(K, 4);
- EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */
+ case BPF_S_ALU_DIV_K: /* A /= K */
+ if (K == 1)
+ break;
+ EMIT2(0x31, 0xd2); /* xor %edx,%edx */
+ EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */
+ EMIT2(0xf7, 0xf1); /* div %ecx */
break;
case BPF_S_ALU_AND_X:
seen |= SEEN_XREG;
@@ -788,5 +794,7 @@
if (fp->bpf_func != sk_run_filter) {
INIT_WORK(&fp->work, bpf_jit_free_deferred);
schedule_work(&fp->work);
+ } else {
+ kfree(fp);
}
}
diff -Nur linux/arch/x86/net/bpf_jit.S rpi/arch/x86/net/bpf_jit.S
--- linux/arch/x86/net/bpf_jit.S 2014-05-29 12:18:18.726551921 +0900
+++ rpi/arch/x86/net/bpf_jit.S 2014-05-29 11:49:12.417896218 +0900
@@ -140,7 +140,7 @@
push %r9; \
push SKBDATA; \
/* rsi already has offset */ \
- mov $SIZE,%ecx; /* size */ \
+ mov $SIZE,%edx; /* size */ \
call bpf_internal_load_pointer_neg_helper; \
test %rax,%rax; \
pop SKBDATA; \
diff -Nur linux/arch/x86/platform/efi/efi.c rpi/arch/x86/platform/efi/efi.c
--- linux/arch/x86/platform/efi/efi.c 2014-05-29 12:18:18.734551871 +0900
+++ rpi/arch/x86/platform/efi/efi.c 2014-05-29 11:49:12.428896126 +0900
@@ -440,7 +440,7 @@
* - Not within any part of the kernel
* - Not the bios reserved area
*/
- if ((start+size >= __pa_symbol(_text)
+ if ((start + size > __pa_symbol(_text)
&& start <= __pa_symbol(_end)) ||
!e820_all_mapped(start, start+size, E820_RAM) ||
memblock_is_region_reserved(start, size)) {
@@ -768,13 +768,6 @@
set_bit(EFI_MEMMAP, &x86_efi_facility);
-#ifdef CONFIG_X86_32
- if (efi_is_native()) {
- x86_platform.get_wallclock = efi_get_time;
- x86_platform.set_wallclock = efi_set_rtc_mmss;
- }
-#endif
-
#if EFI_DEBUG
print_efi_memmap();
#endif
diff -Nur linux/arch/x86/platform/uv/tlb_uv.c rpi/arch/x86/platform/uv/tlb_uv.c
--- linux/arch/x86/platform/uv/tlb_uv.c 2014-05-29 12:18:18.740551834 +0900
+++ rpi/arch/x86/platform/uv/tlb_uv.c 2014-05-29 11:49:12.436896059 +0900
@@ -1070,12 +1070,13 @@
unsigned long status;
bcp = &per_cpu(bau_control, cpu);
- stat = bcp->statp;
- stat->s_enters++;
if (bcp->nobau)
return cpumask;
+ stat = bcp->statp;
+ stat->s_enters++;
+
if (bcp->busy) {
descriptor_status =
read_lmmr(UVH_LB_BAU_SB_ACTIVATION_STATUS_0);
diff -Nur linux/arch/x86/realmode/rm/Makefile rpi/arch/x86/realmode/rm/Makefile
--- linux/arch/x86/realmode/rm/Makefile 2014-05-29 12:18:18.742551821 +0900
+++ rpi/arch/x86/realmode/rm/Makefile 2014-05-29 11:49:12.440896025 +0900
@@ -73,9 +73,10 @@
-march=i386 -mregparm=3 \
-include $(srctree)/$(src)/../../boot/code16gcc.h \
-fno-strict-aliasing -fomit-frame-pointer -fno-pic \
+ -mno-mmx -mno-sse \
$(call cc-option, -ffreestanding) \
$(call cc-option, -fno-toplevel-reorder,\
- $(call cc-option, -fno-unit-at-a-time)) \
+ $(call cc-option, -fno-unit-at-a-time)) \
$(call cc-option, -fno-stack-protector) \
$(call cc-option, -mpreferred-stack-boundary=2)
KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
diff -Nur linux/arch/x86/xen/platform-pci-unplug.c rpi/arch/x86/xen/platform-pci-unplug.c
--- linux/arch/x86/xen/platform-pci-unplug.c 2014-05-29 12:18:18.755551740 +0900
+++ rpi/arch/x86/xen/platform-pci-unplug.c 2014-05-29 11:49:12.470895774 +0900
@@ -69,6 +69,80 @@
return 0;
}
+bool xen_has_pv_devices()
+{
+ if (!xen_domain())
+ return false;
+
+ /* PV domains always have them. */
+ if (xen_pv_domain())
+ return true;
+
+ /* And user has xen_platform_pci=0 set in guest config as
+ * driver did not modify the value. */
+ if (xen_platform_pci_unplug == 0)
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_NEVER)
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_ALL)
+ return true;
+
+ /* This is an odd one - we are going to run legacy
+ * and PV drivers at the same time. */
+ if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY)
+ return true;
+
+ /* And the caller has to follow with xen_pv_{disk,nic}_devices
+ * to be certain which driver can load. */
+ return false;
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_devices);
+
+static bool __xen_has_pv_device(int state)
+{
+ /* HVM domains might or might not */
+ if (xen_hvm_domain() && (xen_platform_pci_unplug & state))
+ return true;
+
+ return xen_has_pv_devices();
+}
+
+bool xen_has_pv_nic_devices(void)
+{
+ return __xen_has_pv_device(XEN_UNPLUG_ALL_NICS | XEN_UNPLUG_ALL);
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_nic_devices);
+
+bool xen_has_pv_disk_devices(void)
+{
+ return __xen_has_pv_device(XEN_UNPLUG_ALL_IDE_DISKS |
+ XEN_UNPLUG_AUX_IDE_DISKS | XEN_UNPLUG_ALL);
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_disk_devices);
+
+/*
+ * This one is odd - it determines whether you want to run PV _and_
+ * legacy (IDE) drivers together. This combination is only possible
+ * under HVM.
+ */
+bool xen_has_pv_and_legacy_disk_devices(void)
+{
+ if (!xen_domain())
+ return false;
+
+ /* N.B. This is only ever used in HVM mode */
+ if (xen_pv_domain())
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_and_legacy_disk_devices);
+
void xen_unplug_emulated_devices(void)
{
int r;
diff -Nur linux/arch/xtensa/include/asm/traps.h rpi/arch/xtensa/include/asm/traps.h
--- linux/arch/xtensa/include/asm/traps.h 2014-05-29 12:18:18.767551665 +0900
+++ rpi/arch/xtensa/include/asm/traps.h 2014-05-29 11:49:12.490895606 +0900
@@ -22,25 +22,37 @@
static inline void spill_registers(void)
{
-
+#if XCHAL_NUM_AREGS > 16
__asm__ __volatile__ (
- "movi a14, "__stringify((1 << PS_EXCM_BIT) | LOCKLEVEL)"\n\t"
- "mov a12, a0\n\t"
- "rsr a13, sar\n\t"
- "xsr a14, ps\n\t"
- "movi a0, _spill_registers\n\t"
- "rsync\n\t"
- "callx0 a0\n\t"
- "mov a0, a12\n\t"
- "wsr a13, sar\n\t"
- "wsr a14, ps\n\t"
- : :
-#if defined(CONFIG_FRAME_POINTER)
- : "a2", "a3", "a4", "a11", "a12", "a13", "a14", "a15",
+ " call12 1f\n"
+ " _j 2f\n"
+ " retw\n"
+ " .align 4\n"
+ "1:\n"
+ " _entry a1, 48\n"
+ " addi a12, a0, 3\n"
+#if XCHAL_NUM_AREGS > 32
+ " .rept (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n"
+ " _entry a1, 48\n"
+ " mov a12, a0\n"
+ " .endr\n"
+#endif
+ " _entry a1, 48\n"
+#if XCHAL_NUM_AREGS % 12 == 0
+ " mov a8, a8\n"
+#elif XCHAL_NUM_AREGS % 12 == 4
+ " mov a12, a12\n"
+#elif XCHAL_NUM_AREGS % 12 == 8
+ " mov a4, a4\n"
+#endif
+ " retw\n"
+ "2:\n"
+ : : : "a12", "a13", "memory");
#else
- : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15",
+ __asm__ __volatile__ (
+ " mov a12, a12\n"
+ : : : "memory");
#endif
- "memory");
}
#endif /* _XTENSA_TRAPS_H */
diff -Nur linux/arch/xtensa/kernel/entry.S rpi/arch/xtensa/kernel/entry.S
--- linux/arch/xtensa/kernel/entry.S 2014-05-29 12:18:18.769551652 +0900
+++ rpi/arch/xtensa/kernel/entry.S 2014-05-29 11:49:12.498895539 +0900
@@ -1117,6 +1117,13 @@
* We basically restore WINDOWBASE and WINDOWSTART to the condition when
* we entered the spill routine and jump to the user exception handler.
*
+ * Note that we only need to restore the bits in windowstart that have not
+ * been spilled yet by the _spill_register routine. Luckily, a3 contains a
+ * rotated windowstart with only those bits set for frames that haven't been
+ * spilled yet. Because a3 is rotated such that bit 0 represents the register
+ * frame for the current windowbase - 1, we need to rotate a3 left by the
+ * value of the current windowbase + 1 and move it to windowstart.
+ *
* a0: value of depc, original value in depc
* a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
* a3: exctable, original value in excsave1
@@ -1131,10 +1138,15 @@
/* We need to make sure the current registers (a0-a3) are preserved.
* To do this, we simply set the bit for the current window frame
* in WS, so that the exception handlers save them to the task stack.
+ *
+ * Note: we use a3 to set the windowbase, so we take a special care
+ * of it, saving it in the original _spill_registers frame across
+ * the exception handler call.
*/
xsr a3, excsave1 # get spill-mask
slli a3, a3, 1 # shift left by one
+ addi a3, a3, 1 # set the bit for the current window frame
slli a2, a3, 32-WSBITS
src a2, a3, a2 # a2 = xxwww1yyxxxwww1yy......
@@ -1794,6 +1806,43 @@
ENDPROC(system_call)
+/*
+ * Spill live registers on the kernel stack macro.
+ *
+ * Entry condition: ps.woe is set, ps.excm is cleared
+ * Exit condition: windowstart has single bit set
+ * May clobber: a12, a13
+ */
+ .macro spill_registers_kernel
+
+#if XCHAL_NUM_AREGS > 16
+ call12 1f
+ _j 2f
+ retw
+ .align 4
+1:
+ _entry a1, 48
+ addi a12, a0, 3
+#if XCHAL_NUM_AREGS > 32
+ .rept (XCHAL_NUM_AREGS - 32) / 12
+ _entry a1, 48
+ mov a12, a0
+ .endr
+#endif
+ _entry a1, 48
+#if XCHAL_NUM_AREGS % 12 == 0
+ mov a8, a8
+#elif XCHAL_NUM_AREGS % 12 == 4
+ mov a12, a12
+#elif XCHAL_NUM_AREGS % 12 == 8
+ mov a4, a4
+#endif
+ retw
+2:
+#else
+ mov a12, a12
+#endif
+ .endm
/*
* Task switch.
@@ -1806,21 +1855,20 @@
entry a1, 16
- mov a12, a2 # preserve 'prev' (a2)
- mov a13, a3 # and 'next' (a3)
+ mov a10, a2 # preserve 'prev' (a2)
+ mov a11, a3 # and 'next' (a3)
l32i a4, a2, TASK_THREAD_INFO
l32i a5, a3, TASK_THREAD_INFO
- save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
+ save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
- s32i a0, a12, THREAD_RA # save return address
- s32i a1, a12, THREAD_SP # save stack pointer
+ s32i a0, a10, THREAD_RA # save return address
+ s32i a1, a10, THREAD_SP # save stack pointer
/* Disable ints while we manipulate the stack pointer. */
- movi a14, (1 << PS_EXCM_BIT) | LOCKLEVEL
- xsr a14, ps
+ rsil a14, LOCKLEVEL
rsr a3, excsave1
rsync
s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */
@@ -1835,7 +1883,7 @@
/* Flush register file. */
- call0 _spill_registers # destroys a3, a4, and SAR
+ spill_registers_kernel
/* Set kernel stack (and leave critical section)
* Note: It's save to set it here. The stack will not be overwritten
@@ -1851,13 +1899,13 @@
/* restore context of the task 'next' */
- l32i a0, a13, THREAD_RA # restore return address
- l32i a1, a13, THREAD_SP # restore stack pointer
+ l32i a0, a11, THREAD_RA # restore return address
+ l32i a1, a11, THREAD_SP # restore stack pointer
- load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
+ load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
wsr a14, ps
- mov a2, a12 # return 'prev'
+ mov a2, a10 # return 'prev'
rsync
retw
diff -Nur linux/arch/xtensa/platforms/xtfpga/setup.c rpi/arch/xtensa/platforms/xtfpga/setup.c
--- linux/arch/xtensa/platforms/xtfpga/setup.c 2014-05-29 12:18:18.776551609 +0900
+++ rpi/arch/xtensa/platforms/xtfpga/setup.c 2014-05-29 11:49:12.513895414 +0900
@@ -194,7 +194,7 @@
* Ethernet -- OpenCores Ethernet MAC (ethoc driver)
*/
-static struct resource ethoc_res[] __initdata = {
+static struct resource ethoc_res[] = {
[0] = { /* register space */
.start = OETH_REGS_PADDR,
.end = OETH_REGS_PADDR + OETH_REGS_SIZE - 1,
@@ -212,7 +212,7 @@
},
};
-static struct ethoc_platform_data ethoc_pdata __initdata = {
+static struct ethoc_platform_data ethoc_pdata = {
/*
* The MAC address for these boards is 00:50:c2:13:6f:xx.
* The last byte (here as zero) is read from the DIP switches on the
@@ -222,7 +222,7 @@
.phy_id = -1,
};
-static struct platform_device ethoc_device __initdata = {
+static struct platform_device ethoc_device = {
.name = "ethoc",
.id = -1,
.num_resources = ARRAY_SIZE(ethoc_res),
@@ -236,13 +236,13 @@
* UART
*/
-static struct resource serial_resource __initdata = {
+static struct resource serial_resource = {
.start = DUART16552_PADDR,
.end = DUART16552_PADDR + 0x1f,
.flags = IORESOURCE_MEM,
};
-static struct plat_serial8250_port serial_platform_data[] __initdata = {
+static struct plat_serial8250_port serial_platform_data[] = {
[0] = {
.mapbase = DUART16552_PADDR,
.irq = DUART16552_INTNUM,
@@ -255,7 +255,7 @@
{ },
};
-static struct platform_device xtavnet_uart __initdata = {
+static struct platform_device xtavnet_uart = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
diff -Nur linux/block/blk-cgroup.h rpi/block/blk-cgroup.h
--- linux/block/blk-cgroup.h 2014-05-29 12:18:18.778551596 +0900
+++ rpi/block/blk-cgroup.h 2014-05-29 11:49:12.520895355 +0900
@@ -430,9 +430,9 @@
uint64_t v;
do {
- start = u64_stats_fetch_begin(&stat->syncp);
+ start = u64_stats_fetch_begin_bh(&stat->syncp);
v = stat->cnt;
- } while (u64_stats_fetch_retry(&stat->syncp, start));
+ } while (u64_stats_fetch_retry_bh(&stat->syncp, start));
return v;
}
@@ -498,9 +498,9 @@
struct blkg_rwstat tmp;
do {
- start = u64_stats_fetch_begin(&rwstat->syncp);
+ start = u64_stats_fetch_begin_bh(&rwstat->syncp);
tmp = *rwstat;
- } while (u64_stats_fetch_retry(&rwstat->syncp, start));
+ } while (u64_stats_fetch_retry_bh(&rwstat->syncp, start));
return tmp;
}
diff -Nur linux/block/blk-core.c rpi/block/blk-core.c
--- linux/block/blk-core.c 2014-05-29 12:18:18.780551583 +0900
+++ rpi/block/blk-core.c 2014-05-29 11:49:12.523895330 +0900
@@ -645,10 +645,12 @@
__set_bit(QUEUE_FLAG_BYPASS, &q->queue_flags);
if (blkcg_init_queue(q))
- goto fail_id;
+ goto fail_bdi;
return q;
+fail_bdi:
+ bdi_destroy(&q->backing_dev_info);
fail_id:
ida_simple_remove(&blk_queue_ida, q->id);
fail_q:
@@ -739,9 +741,17 @@
q->sg_reserved_size = INT_MAX;
+ /* Protect q->elevator from elevator_change */
+ mutex_lock(&q->sysfs_lock);
+
/* init elevator */
- if (elevator_init(q, NULL))
+ if (elevator_init(q, NULL)) {
+ mutex_unlock(&q->sysfs_lock);
return NULL;
+ }
+
+ mutex_unlock(&q->sysfs_lock);
+
return q;
}
EXPORT_SYMBOL(blk_init_allocated_queue);
@@ -2227,6 +2237,7 @@
if (unlikely(blk_bidi_rq(req)))
req->next_rq->resid_len = blk_rq_bytes(req->next_rq);
+ BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags));
blk_add_timer(req);
}
EXPORT_SYMBOL(blk_start_request);
diff -Nur linux/block/blk.h rpi/block/blk.h
--- linux/block/blk.h 2014-05-29 12:18:18.786551546 +0900
+++ rpi/block/blk.h 2014-05-29 11:49:12.529895280 +0900
@@ -96,7 +96,7 @@
q->flush_queue_delayed = 1;
return NULL;
}
- if (unlikely(blk_queue_dying(q)) ||
+ if (unlikely(blk_queue_bypass(q)) ||
!q->elevator->type->ops.elevator_dispatch_fn(q, 0))
return NULL;
}
diff -Nur linux/block/blk-lib.c rpi/block/blk-lib.c
--- linux/block/blk-lib.c 2014-05-29 12:18:18.783551565 +0900
+++ rpi/block/blk-lib.c 2014-05-29 11:49:12.525895313 +0900
@@ -121,6 +121,14 @@
atomic_inc(&bb.done);
submit_bio(type, bio);
+
+ /*
+ * We can loop for a long time in here, if someone does
+ * full device discards (like mkfs). Be nice and allow
+ * us to schedule out to avoid softlocking if preempt
+ * is disabled.
+ */
+ cond_resched();
}
blk_finish_plug(&plug);
diff -Nur linux/block/blk-settings.c rpi/block/blk-settings.c
--- linux/block/blk-settings.c 2014-05-29 12:18:18.784551558 +0900
+++ rpi/block/blk-settings.c 2014-05-29 11:49:12.526895305 +0900
@@ -144,6 +144,7 @@
lim->discard_zeroes_data = 1;
lim->max_segments = USHRT_MAX;
lim->max_hw_sectors = UINT_MAX;
+ lim->max_segment_size = UINT_MAX;
lim->max_sectors = UINT_MAX;
lim->max_write_same_sectors = UINT_MAX;
}
diff -Nur linux/block/blk-timeout.c rpi/block/blk-timeout.c
--- linux/block/blk-timeout.c 2014-05-29 12:18:18.786551546 +0900
+++ rpi/block/blk-timeout.c 2014-05-29 11:49:12.529895280 +0900
@@ -91,8 +91,8 @@
__blk_complete_request(req);
break;
case BLK_EH_RESET_TIMER:
- blk_clear_rq_complete(req);
blk_add_timer(req);
+ blk_clear_rq_complete(req);
break;
case BLK_EH_NOT_HANDLED:
/*
@@ -174,7 +174,6 @@
return;
BUG_ON(!list_empty(&req->timeout_list));
- BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags));
/*
* Some LLDs, like scsi, peek at the timeout to prevent a
diff -Nur linux/block/elevator.c rpi/block/elevator.c
--- linux/block/elevator.c 2014-05-29 12:18:18.791551515 +0900
+++ rpi/block/elevator.c 2014-05-29 11:49:12.573894911 +0900
@@ -186,6 +186,12 @@
struct elevator_type *e = NULL;
int err;
+ /*
+ * q->sysfs_lock must be held to provide mutual exclusion between
+ * elevator_switch() and here.
+ */
+ lockdep_assert_held(&q->sysfs_lock);
+
if (unlikely(q->elevator))
return 0;
@@ -959,7 +965,7 @@
/*
* Switch this queue to the given IO scheduler.
*/
-int elevator_change(struct request_queue *q, const char *name)
+static int __elevator_change(struct request_queue *q, const char *name)
{
char elevator_name[ELV_NAME_MAX];
struct elevator_type *e;
@@ -981,6 +987,18 @@
return elevator_switch(q, e);
}
+
+int elevator_change(struct request_queue *q, const char *name)
+{
+ int ret;
+
+ /* Protect q->elevator from elevator_init() */
+ mutex_lock(&q->sysfs_lock);
+ ret = __elevator_change(q, name);
+ mutex_unlock(&q->sysfs_lock);
+
+ return ret;
+}
EXPORT_SYMBOL(elevator_change);
ssize_t elv_iosched_store(struct request_queue *q, const char *name,
@@ -991,7 +1009,7 @@
if (!q->elevator)
return count;
- ret = elevator_change(q, name);
+ ret = __elevator_change(q, name);
if (!ret)
return count;
diff -Nur linux/crypto/algif_hash.c rpi/crypto/algif_hash.c
--- linux/crypto/algif_hash.c 2014-05-29 12:18:18.796551483 +0900
+++ rpi/crypto/algif_hash.c 2014-05-29 11:49:12.589894777 +0900
@@ -114,6 +114,9 @@
struct hash_ctx *ctx = ask->private;
int err;
+ if (flags & MSG_SENDPAGE_NOTLAST)
+ flags |= MSG_MORE;
+
lock_sock(sk);
sg_init_table(ctx->sgl.sg, 1);
sg_set_page(ctx->sgl.sg, page, size, offset);
@@ -161,8 +164,6 @@
else if (len < ds)
msg->msg_flags |= MSG_TRUNC;
- msg->msg_namelen = 0;
-
lock_sock(sk);
if (ctx->more) {
ctx->more = 0;
diff -Nur linux/crypto/algif_skcipher.c rpi/crypto/algif_skcipher.c
--- linux/crypto/algif_skcipher.c 2014-05-29 12:18:18.797551477 +0900
+++ rpi/crypto/algif_skcipher.c 2014-05-29 11:49:12.589894777 +0900
@@ -378,6 +378,9 @@
struct skcipher_sg_list *sgl;
int err = -EINVAL;
+ if (flags & MSG_SENDPAGE_NOTLAST)
+ flags |= MSG_MORE;
+
lock_sock(sk);
if (!ctx->more && ctx->used)
goto unlock;
@@ -432,7 +435,6 @@
long copied = 0;
lock_sock(sk);
- msg->msg_namelen = 0;
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
iovlen--, iov++) {
unsigned long seglen = iov->iov_len;
diff -Nur linux/crypto/ansi_cprng.c rpi/crypto/ansi_cprng.c
--- linux/crypto/ansi_cprng.c 2014-05-29 12:18:18.797551477 +0900
+++ rpi/crypto/ansi_cprng.c 2014-05-29 11:49:12.590894768 +0900
@@ -230,11 +230,11 @@
*/
if (byte_count < DEFAULT_BLK_SZ) {
empty_rbuf:
- for (; ctx->rand_data_valid < DEFAULT_BLK_SZ;
- ctx->rand_data_valid++) {
+ while (ctx->rand_data_valid < DEFAULT_BLK_SZ) {
*ptr = ctx->rand_data[ctx->rand_data_valid];
ptr++;
byte_count--;
+ ctx->rand_data_valid++;
if (byte_count == 0)
goto done;
}
diff -Nur linux/crypto/asymmetric_keys/x509_parser.h rpi/crypto/asymmetric_keys/x509_parser.h
--- linux/crypto/asymmetric_keys/x509_parser.h 2014-05-29 12:18:18.799551465 +0900
+++ rpi/crypto/asymmetric_keys/x509_parser.h 2014-05-29 11:49:12.593894743 +0900
@@ -9,6 +9,7 @@
* 2 of the Licence, or (at your option) any later version.
*/
+#include <linux/time.h>
#include <crypto/public_key.h>
struct x509_certificate {
diff -Nur linux/crypto/asymmetric_keys/x509_public_key.c rpi/crypto/asymmetric_keys/x509_public_key.c
--- linux/crypto/asymmetric_keys/x509_public_key.c 2014-05-29 12:18:18.799551465 +0900
+++ rpi/crypto/asymmetric_keys/x509_public_key.c 2014-05-29 11:49:12.593894743 +0900
@@ -106,7 +106,6 @@
static int x509_key_preparse(struct key_preparsed_payload *prep)
{
struct x509_certificate *cert;
- struct tm now;
size_t srlen, sulen;
char *desc = NULL;
int ret;
@@ -137,43 +136,6 @@
goto error_free_cert;
}
- time_to_tm(CURRENT_TIME.tv_sec, 0, &now);
- pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n",
- now.tm_year + 1900, now.tm_mon + 1, now.tm_mday,
- now.tm_hour, now.tm_min, now.tm_sec);
- if (now.tm_year < cert->valid_from.tm_year ||
- (now.tm_year == cert->valid_from.tm_year &&
- (now.tm_mon < cert->valid_from.tm_mon ||
- (now.tm_mon == cert->valid_from.tm_mon &&
- (now.tm_mday < cert->valid_from.tm_mday ||
- (now.tm_mday == cert->valid_from.tm_mday &&
- (now.tm_hour < cert->valid_from.tm_hour ||
- (now.tm_hour == cert->valid_from.tm_hour &&
- (now.tm_min < cert->valid_from.tm_min ||
- (now.tm_min == cert->valid_from.tm_min &&
- (now.tm_sec < cert->valid_from.tm_sec
- ))))))))))) {
- pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
- ret = -EKEYREJECTED;
- goto error_free_cert;
- }
- if (now.tm_year > cert->valid_to.tm_year ||
- (now.tm_year == cert->valid_to.tm_year &&
- (now.tm_mon > cert->valid_to.tm_mon ||
- (now.tm_mon == cert->valid_to.tm_mon &&
- (now.tm_mday > cert->valid_to.tm_mday ||
- (now.tm_mday == cert->valid_to.tm_mday &&
- (now.tm_hour > cert->valid_to.tm_hour ||
- (now.tm_hour == cert->valid_to.tm_hour &&
- (now.tm_min > cert->valid_to.tm_min ||
- (now.tm_min == cert->valid_to.tm_min &&
- (now.tm_sec > cert->valid_to.tm_sec
- ))))))))))) {
- pr_warn("Cert %s has expired\n", cert->fingerprint);
- ret = -EKEYEXPIRED;
- goto error_free_cert;
- }
-
cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];
cert->pub->id_type = PKEY_ID_X509;
diff -Nur linux/crypto/authenc.c rpi/crypto/authenc.c
--- linux/crypto/authenc.c 2014-05-29 12:18:18.802551446 +0900
+++ rpi/crypto/authenc.c 2014-05-29 11:49:12.596894718 +0900
@@ -368,9 +368,10 @@
if (!err) {
struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
- struct ablkcipher_request *abreq = aead_request_ctx(areq);
- u8 *iv = (u8 *)(abreq + 1) +
- crypto_ablkcipher_reqsize(ctx->enc);
+ struct authenc_request_ctx *areq_ctx = aead_request_ctx(areq);
+ struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+ + ctx->reqoff);
+ u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(ctx->enc);
err = crypto_authenc_genicv(areq, iv, 0);
}
diff -Nur linux/crypto/ccm.c rpi/crypto/ccm.c
--- linux/crypto/ccm.c 2014-05-29 12:18:18.804551433 +0900
+++ rpi/crypto/ccm.c 2014-05-29 11:49:12.601894676 +0900
@@ -271,7 +271,8 @@
}
/* compute plaintext into mac */
- get_data_to_compute(cipher, pctx, plain, cryptlen);
+ if (cryptlen)
+ get_data_to_compute(cipher, pctx, plain, cryptlen);
out:
return err;
diff -Nur linux/Documentation/devicetree/bindings/ata/marvell.txt rpi/Documentation/devicetree/bindings/ata/marvell.txt
--- linux/Documentation/devicetree/bindings/ata/marvell.txt 2014-05-29 12:18:16.052568659 +0900
+++ rpi/Documentation/devicetree/bindings/ata/marvell.txt 2014-05-29 11:49:03.015975124 +0900
@@ -1,7 +1,7 @@
* Marvell Orion SATA
Required Properties:
-- compatibility : "marvell,orion-sata"
+- compatibility : "marvell,orion-sata" or "marvell,armada-370-sata"
- reg : Address range of controller
- interrupts : Interrupt controller is using
- nr-ports : Number of SATA ports in use.
diff -Nur linux/Documentation/devicetree/bindings/clock/exynos5250-clock.txt rpi/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
--- linux/Documentation/devicetree/bindings/clock/exynos5250-clock.txt 2014-05-29 12:18:16.054568646 +0900
+++ rpi/Documentation/devicetree/bindings/clock/exynos5250-clock.txt 2014-05-29 11:49:03.019975091 +0900
@@ -159,6 +159,8 @@
mixer 343
hdmi 344
g2d 345
+ mdma0 346
+ smmu_mdma0 347
[Clock Muxes]
diff -Nur linux/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt rpi/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
--- linux/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt 2014-05-29 12:18:16.063568590 +0900
+++ rpi/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt 2014-05-29 11:49:03.040974914 +0900
@@ -5,7 +5,11 @@
- reg : Offset and length of the register set for the device
- compatible : Should be "marvell,mv64xxx-i2c" or "allwinner,sun4i-i2c"
- or "marvell,mv78230-i2c"
+ or "marvell,mv78230-i2c" or "marvell,mv78230-a0-i2c"
+ Note: Only use "marvell,mv78230-a0-i2c" for a very rare,
+ initial version of the SoC which had broken offload
+ support. Linux auto-detects this and sets it
+ appropriately.
- interrupts : The interrupt number
Optional properties :
diff -Nur linux/Documentation/devicetree/bindings/net/micrel-ks8851.txt rpi/Documentation/devicetree/bindings/net/micrel-ks8851.txt
--- linux/Documentation/devicetree/bindings/net/micrel-ks8851.txt 2014-05-29 12:18:16.080568484 +0900
+++ rpi/Documentation/devicetree/bindings/net/micrel-ks8851.txt 2014-05-29 11:49:03.077974603 +0900
@@ -7,3 +7,4 @@
Optional properties:
- local-mac-address : Ethernet mac address to use
+- vdd-supply: supply for Ethernet mac
diff -Nur linux/Documentation/devicetree/bindings/spi/efm32-spi.txt rpi/Documentation/devicetree/bindings/spi/efm32-spi.txt
--- linux/Documentation/devicetree/bindings/spi/efm32-spi.txt 2014-05-29 12:18:16.097568377 +0900
+++ rpi/Documentation/devicetree/bindings/spi/efm32-spi.txt 2014-05-29 11:49:03.123974216 +0900
@@ -3,7 +3,7 @@
Required properties:
- #address-cells: see spi-bus.txt
- #size-cells: see spi-bus.txt
-- compatible: should be "efm32,spi"
+- compatible: should be "energymicro,efm32-spi"
- reg: Offset and length of the register set for the controller
- interrupts: pair specifying rx and tx irq
- clocks: phandle to the spi clock
@@ -15,7 +15,7 @@
spi1: spi@0x4000c400 { /* USART1 */
#address-cells = <1>;
#size-cells = <0>;
- compatible = "efm32,spi";
+ compatible = "energymicro,efm32-spi";
reg = <0x4000c400 0x400>;
interrupts = <15 16>;
clocks = <&cmu 20>;
diff -Nur linux/Documentation/filesystems/proc.txt rpi/Documentation/filesystems/proc.txt
--- linux/Documentation/filesystems/proc.txt 2014-05-29 12:18:16.128568183 +0900
+++ rpi/Documentation/filesystems/proc.txt 2014-05-29 11:49:03.189973662 +0900
@@ -1376,8 +1376,8 @@
For example, if a task is using all allowed memory, its badness score will be
1000. If it is using half of its allowed memory, its score will be 500.
-There is an additional factor included in the badness score: root
-processes are given 3% extra memory over other tasks.
+There is an additional factor included in the badness score: the current memory
+and swap usage is discounted by 3% for root processes.
The amount of "allowed" memory depends on the context in which the oom killer
was called. If it is due to the memory assigned to the allocating task's cpuset
diff -Nur linux/Documentation/i2c/busses/i2c-i801 rpi/Documentation/i2c/busses/i2c-i801
--- linux/Documentation/i2c/busses/i2c-i801 2014-05-29 12:18:16.177567876 +0900
+++ rpi/Documentation/i2c/busses/i2c-i801 2014-05-29 11:49:03.231973309 +0900
@@ -25,6 +25,8 @@
* Intel Avoton (SOC)
* Intel Wellsburg (PCH)
* Intel Coleto Creek (PCH)
+ * Intel Wildcat Point-LP (PCH)
+ * Intel BayTrail (SOC)
Datasheets: Publicly available at the Intel website
On Intel Patsburg and later chipsets, both the normal host SMBus controller
diff -Nur linux/Documentation/i2c/busses/i2c-piix4 rpi/Documentation/i2c/busses/i2c-piix4
--- linux/Documentation/i2c/busses/i2c-piix4 2014-05-29 12:18:16.183567839 +0900
+++ rpi/Documentation/i2c/busses/i2c-piix4 2014-05-29 11:49:03.232973301 +0900
@@ -13,7 +13,7 @@
* AMD SP5100 (SB700 derivative found on some server mainboards)
Datasheet: Publicly available at the AMD website
http://support.amd.com/us/Embedded_TechDocs/44413.pdf
- * AMD Hudson-2, CZ
+ * AMD Hudson-2, ML, CZ
Datasheet: Not publicly available
* Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
Datasheet: Publicly available at the SMSC website http://www.smsc.com
diff -Nur linux/Documentation/kernel-parameters.txt rpi/Documentation/kernel-parameters.txt
--- linux/Documentation/kernel-parameters.txt 2014-05-29 12:18:16.212567657 +0900
+++ rpi/Documentation/kernel-parameters.txt 2014-05-29 11:49:03.276972931 +0900
@@ -1515,6 +1515,8 @@
* atapi_dmadir: Enable ATAPI DMADIR bridge support
+ * disable: Disable this device.
+
If there are multiple matching configurations changing
the same attribute, the last one is used.
diff -Nur linux/Documentation/networking/ip-sysctl.txt rpi/Documentation/networking/ip-sysctl.txt
--- linux/Documentation/networking/ip-sysctl.txt 2014-05-29 12:18:16.230567545 +0900
+++ rpi/Documentation/networking/ip-sysctl.txt 2014-05-29 11:49:03.333972452 +0900
@@ -588,9 +588,6 @@
typical pfifo_fast qdiscs.
tcp_limit_output_bytes limits the number of bytes on qdisc
or device to reduce artificial RTT/cwnd and reduce bufferbloat.
- Note: For GSO/TSO enabled flows, we try to have at least two
- packets in flight. Reducing tcp_limit_output_bytes might also
- reduce the size of individual GSO packet (64KB being the max)
Default: 131072
tcp_challenge_ack_limit - INTEGER
diff -Nur linux/Documentation/networking/packet_mmap.txt rpi/Documentation/networking/packet_mmap.txt
--- linux/Documentation/networking/packet_mmap.txt 2014-05-29 12:18:16.233567526 +0900
+++ rpi/Documentation/networking/packet_mmap.txt 2014-05-29 11:49:03.340972393 +0900
@@ -123,6 +123,16 @@
[shutdown] close() --------> destruction of the transmission socket and
deallocation of all associated resources.
+Socket creation and destruction is also straight forward, and is done
+the same way as in capturing described in the previous paragraph:
+
+ int fd = socket(PF_PACKET, mode, 0);
+
+The protocol can optionally be 0 in case we only want to transmit
+via this socket, which avoids an expensive call to packet_rcv().
+In this case, you also need to bind(2) the TX_RING with sll_protocol = 0
+set. Otherwise, htons(ETH_P_ALL) or any other protocol, for example.
+
Binding the socket to your network interface is mandatory (with zero copy) to
know the header size of frames used in the circular buffer.
diff -Nur linux/Documentation/sysctl/kernel.txt rpi/Documentation/sysctl/kernel.txt
--- linux/Documentation/sysctl/kernel.txt 2014-05-29 12:18:16.310567044 +0900
+++ rpi/Documentation/sysctl/kernel.txt 2014-05-29 11:49:03.442971536 +0900
@@ -290,13 +290,24 @@
kptr_restrict:
This toggle indicates whether restrictions are placed on
-exposing kernel addresses via /proc and other interfaces. When
-kptr_restrict is set to (0), there are no restrictions. When
-kptr_restrict is set to (1), the default, kernel pointers
-printed using the %pK format specifier will be replaced with 0's
-unless the user has CAP_SYSLOG. When kptr_restrict is set to
-(2), kernel pointers printed using %pK will be replaced with 0's
-regardless of privileges.
+exposing kernel addresses via /proc and other interfaces.
+
+When kptr_restrict is set to (0), the default, there are no restrictions.
+
+When kptr_restrict is set to (1), kernel pointers printed using the %pK
+format specifier will be replaced with 0's unless the user has CAP_SYSLOG
+and effective user and group ids are equal to the real ids. This is
+because %pK checks are done at read() time rather than open() time, so
+if permissions are elevated between the open() and the read() (e.g via
+a setuid binary) then %pK will not leak kernel pointers to unprivileged
+users. Note, this is a temporary solution only. The correct long-term
+solution is to do the permission checks at open() time. Consider removing
+world read permissions from files that use %pK, and using dmesg_restrict
+to protect against uses of %pK in dmesg(8) if leaking kernel pointer
+values to unprivileged users is a concern.
+
+When kptr_restrict is set to (2), kernel pointers printed using
+%pK will be replaced with 0's regardless of privileges.
==============================================================
diff -Nur linux/Documentation/video4linux/bcm2835-v4l2.txt rpi/Documentation/video4linux/bcm2835-v4l2.txt
--- linux/Documentation/video4linux/bcm2835-v4l2.txt 1970-01-01 09:00:00.000000000 +0900
+++ rpi/Documentation/video4linux/bcm2835-v4l2.txt 2014-05-29 11:49:03.472971284 +0900
@@ -0,0 +1,60 @@
+
+BCM2835 (aka Raspberry Pi) V4L2 driver
+======================================
+
+1. Copyright
+============
+
+Copyright © 2013 Raspberry Pi (Trading) Ltd.
+
+2. License
+==========
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+3. Quick Start
+==============
+
+You need a version 1.0 or later of v4l2-ctl, available from:
+ git://git.linuxtv.org/v4l-utils.git
+
+$ sudo modprobe bcm2835-v4l2
+
+Turn on the overlay:
+
+$ v4l2-ctl --overlay=1
+
+Turn off the overlay:
+
+$ v4l2-ctl --overlay=0
+
+Set the capture format for video:
+
+$ v4l2-ctl --set-fmt-video=width=1920,height=1088,pixelformat=4
+
+(Note: 1088 not 1080).
+
+Capture:
+
+$ v4l2-ctl --stream-mmap=3 --stream-count=100 --stream-to=somefile.h264
+
+Stills capture:
+
+$ v4l2-ctl --set-fmt-video=width=2592,height=1944,pixelformat=3
+$ v4l2-ctl --stream-mmap=3 --stream-count=1 --stream-to=somefile.jpg
+
+List of available formats:
+
+$ v4l2-ctl --list-formats
diff -Nur linux/Documentation/video4linux/gspca.txt rpi/Documentation/video4linux/gspca.txt
--- linux/Documentation/video4linux/gspca.txt 2014-05-29 12:18:16.359566737 +0900
+++ rpi/Documentation/video4linux/gspca.txt 2014-05-29 11:49:03.479971225 +0900
@@ -55,6 +55,7 @@
sonixj 0458:7025 Genius Eye 311Q
sn9c20x 0458:7029 Genius Look 320s
sonixj 0458:702e Genius Slim 310 NB
+sn9c20x 0458:7045 Genius Look 1320 V2
sn9c20x 0458:704a Genius Slim 1320
sn9c20x 0458:704c Genius i-Look 1321
sn9c20x 045e:00f4 LifeCam VX-6000 (SN9C20x + OV9650)
diff -Nur linux/drivers/acpi/acpica/nsrepair.c rpi/drivers/acpi/acpica/nsrepair.c
--- linux/drivers/acpi/acpica/nsrepair.c 2014-05-29 12:18:18.871551014 +0900
+++ rpi/drivers/acpi/acpica/nsrepair.c 2014-05-29 11:49:12.681894006 +0900
@@ -207,13 +207,30 @@
* this predefined name. Either one return value is expected, or none,
* for both methods and other objects.
*
- * Exit now if there is no return object. Warning if one was expected.
+ * Try to fix if there was no return object. Warning if failed to fix.
*/
if (!return_object) {
if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) {
- ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
- ACPI_WARN_ALWAYS,
- "Missing expected return value"));
+ if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
+ ACPI_WARN_PREDEFINED((AE_INFO,
+ info->full_pathname,
+ ACPI_WARN_ALWAYS,
+ "Found unexpected NULL package element"));
+
+ status =
+ acpi_ns_repair_null_element(info,
+ expected_btypes,
+ package_index,
+ return_object_ptr);
+ if (ACPI_SUCCESS(status)) {
+ return (AE_OK); /* Repair was successful */
+ }
+ } else {
+ ACPI_WARN_PREDEFINED((AE_INFO,
+ info->full_pathname,
+ ACPI_WARN_ALWAYS,
+ "Missing expected return value"));
+ }
return (AE_AML_NO_RETURN_VALUE);
}
diff -Nur linux/drivers/acpi/battery.c rpi/drivers/acpi/battery.c
--- linux/drivers/acpi/battery.c 2014-05-29 12:18:18.911550764 +0900
+++ rpi/drivers/acpi/battery.c 2014-05-29 11:49:12.727893621 +0900
@@ -68,6 +68,7 @@
MODULE_DESCRIPTION("ACPI Battery Driver");
MODULE_LICENSE("GPL");
+static int battery_bix_broken_package;
static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
@@ -443,7 +444,12 @@
ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
return -ENODEV;
}
- if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
+
+ if (battery_bix_broken_package)
+ result = extract_package(battery, buffer.pointer,
+ extended_info_offsets + 1,
+ ARRAY_SIZE(extended_info_offsets) - 1);
+ else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
result = extract_package(battery, buffer.pointer,
extended_info_offsets,
ARRAY_SIZE(extended_info_offsets));
@@ -1054,6 +1060,17 @@
return 0;
}
+static struct dmi_system_id bat_dmi_table[] = {
+ {
+ .ident = "NEC LZ750/LS",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
+ },
+ },
+ {},
+};
+
static int acpi_battery_add(struct acpi_device *device)
{
int result = 0;
@@ -1163,6 +1180,8 @@
if (!acpi_battery_dir)
return;
#endif
+ if (dmi_check_system(bat_dmi_table))
+ battery_bix_broken_package = 1;
if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_battery_dir(acpi_battery_dir);
diff -Nur linux/drivers/acpi/blacklist.c rpi/drivers/acpi/blacklist.c
--- linux/drivers/acpi/blacklist.c 2014-05-29 12:18:18.911550764 +0900
+++ rpi/drivers/acpi/blacklist.c 2014-05-29 11:49:12.728893612 +0900
@@ -297,6 +297,54 @@
DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
},
},
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "ThinkPad Edge E530",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "ThinkPad Edge E530",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "Acer Aspire V5-573G",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "Acer Aspire V5-572G",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "ThinkPad T431s",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
+ },
+ },
+ {
+ .callback = dmi_disable_osi_win8,
+ .ident = "ThinkPad T430",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
+ },
+ },
/*
* BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
diff -Nur linux/drivers/acpi/bus.c rpi/drivers/acpi/bus.c
--- linux/drivers/acpi/bus.c 2014-05-29 12:18:18.912550757 +0900
+++ rpi/drivers/acpi/bus.c 2014-05-29 11:49:12.729893604 +0900
@@ -33,6 +33,7 @@
#include <linux/proc_fs.h>
#include <linux/acpi.h>
#include <linux/slab.h>
+#include <linux/regulator/machine.h>
#ifdef CONFIG_X86
#include <asm/mpspec.h>
#endif
@@ -156,6 +157,16 @@
}
EXPORT_SYMBOL(acpi_bus_get_private_data);
+void acpi_bus_no_hotplug(acpi_handle handle)
+{
+ struct acpi_device *adev = NULL;
+
+ acpi_bus_get_device(handle, &adev);
+ if (adev)
+ adev->flags.no_hotplug = true;
+}
+EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
+
static void acpi_print_osc_error(acpi_handle handle,
struct acpi_osc_context *context, char *error)
{
@@ -565,6 +576,14 @@
goto error0;
}
+ /*
+ * If the system is using ACPI then we can be reasonably
+ * confident that any regulators are managed by the firmware
+ * so tell the regulator core it has everything it needs to
+ * know.
+ */
+ regulator_has_full_constraints();
+
return;
error0:
diff -Nur linux/drivers/acpi/button.c rpi/drivers/acpi/button.c
--- linux/drivers/acpi/button.c 2014-05-29 12:18:18.913550751 +0900
+++ rpi/drivers/acpi/button.c 2014-05-29 11:49:12.729893604 +0900
@@ -302,6 +302,10 @@
input_sync(input);
pm_wakeup_event(&device->dev, 0);
+ acpi_bus_generate_netlink_event(
+ device->pnp.device_class,
+ dev_name(&device->dev),
+ event, ++button->pushed);
}
break;
default:
diff -Nur linux/drivers/acpi/ec.c rpi/drivers/acpi/ec.c
--- linux/drivers/acpi/ec.c 2014-05-29 12:18:18.918550720 +0900
+++ rpi/drivers/acpi/ec.c 2014-05-29 11:49:12.732893579 +0900
@@ -70,6 +70,8 @@
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */
+#define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query
+ * when trying to clear the EC */
enum {
EC_FLAGS_QUERY_PENDING, /* Query is pending */
@@ -123,6 +125,7 @@
static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
+static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
/* --------------------------------------------------------------------------
Transaction Management
@@ -175,9 +178,10 @@
static void advance_transaction(struct acpi_ec *ec, u8 status)
{
unsigned long flags;
- struct transaction *t = ec->curr;
+ struct transaction *t;
spin_lock_irqsave(&ec->lock, flags);
+ t = ec->curr;
if (!t)
goto unlock;
if (t->wlen > t->wi) {
@@ -209,13 +213,13 @@
spin_unlock_irqrestore(&ec->lock, flags);
}
-static int acpi_ec_sync_query(struct acpi_ec *ec);
+static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)
{
if (state & ACPI_EC_FLAG_SCI) {
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
- return acpi_ec_sync_query(ec);
+ return acpi_ec_sync_query(ec, NULL);
}
return 0;
}
@@ -467,6 +471,27 @@
EXPORT_SYMBOL(ec_get_handle);
+/*
+ * Process _Q events that might have accumulated in the EC.
+ * Run with locked ec mutex.
+ */
+static void acpi_ec_clear(struct acpi_ec *ec)
+{
+ int i, status;
+ u8 value = 0;
+
+ for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
+ status = acpi_ec_sync_query(ec, &value);
+ if (status || !value)
+ break;
+ }
+
+ if (unlikely(i == ACPI_EC_CLEAR_MAX))
+ pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
+ else
+ pr_info("%d stale EC events cleared\n", i);
+}
+
void acpi_ec_block_transactions(void)
{
struct acpi_ec *ec = first_ec;
@@ -490,6 +515,10 @@
mutex_lock(&ec->mutex);
/* Allow transactions to be carried out again */
clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
+
+ if (EC_FLAGS_CLEAR_ON_RESUME)
+ acpi_ec_clear(ec);
+
mutex_unlock(&ec->mutex);
}
@@ -579,13 +608,18 @@
kfree(handler);
}
-static int acpi_ec_sync_query(struct acpi_ec *ec)
+static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
{
u8 value = 0;
int status;
struct acpi_ec_query_handler *handler, *copy;
- if ((status = acpi_ec_query_unlocked(ec, &value)))
+
+ status = acpi_ec_query_unlocked(ec, &value);
+ if (data)
+ *data = value;
+ if (status)
return status;
+
list_for_each_entry(handler, &ec->list, node) {
if (value == handler->query_bit) {
/* have custom handler for this bit */
@@ -608,7 +642,7 @@
if (!ec)
return;
mutex_lock(&ec->mutex);
- acpi_ec_sync_query(ec);
+ acpi_ec_sync_query(ec, NULL);
mutex_unlock(&ec->mutex);
}
@@ -847,6 +881,13 @@
/* EC is fully operational, allow queries */
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+
+ /* Clear stale _Q events if hardware might require that */
+ if (EC_FLAGS_CLEAR_ON_RESUME) {
+ mutex_lock(&ec->mutex);
+ acpi_ec_clear(ec);
+ mutex_unlock(&ec->mutex);
+ }
return ret;
}
@@ -948,6 +989,30 @@
return 0;
}
+/*
+ * On some hardware it is necessary to clear events accumulated by the EC during
+ * sleep. These ECs stop reporting GPEs until they are manually polled, if too
+ * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=44161
+ *
+ * Ideally, the EC should also be instructed NOT to accumulate events during
+ * sleep (which Windows seems to do somehow), but the interface to control this
+ * behaviour is not known at this time.
+ *
+ * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
+ * however it is very likely that other Samsung models are affected.
+ *
+ * On systems which don't accumulate _Q events during sleep, this extra check
+ * should be harmless.
+ */
+static int ec_clear_on_resume(const struct dmi_system_id *id)
+{
+ pr_debug("Detected system needing EC poll on resume.\n");
+ EC_FLAGS_CLEAR_ON_RESUME = 1;
+ return 0;
+}
+
static struct dmi_system_id ec_dmi_table[] __initdata = {
{
ec_skip_dsdt_scan, "Compal JFL92", {
@@ -991,6 +1056,9 @@
ec_validate_ecdt, "ASUS hardware", {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
+ {
+ ec_clear_on_resume, "Samsung hardware", {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
{},
};
diff -Nur linux/drivers/acpi/pci_irq.c rpi/drivers/acpi/pci_irq.c
--- linux/drivers/acpi/pci_irq.c 2014-05-29 12:18:18.924550682 +0900
+++ rpi/drivers/acpi/pci_irq.c 2014-05-29 11:49:12.736893545 +0900
@@ -432,6 +432,7 @@
pin_name(pin));
}
+ kfree(entry);
return 0;
}
diff -Nur linux/drivers/acpi/pci_root.c rpi/drivers/acpi/pci_root.c
--- linux/drivers/acpi/pci_root.c 2014-05-29 12:18:18.925550676 +0900
+++ rpi/drivers/acpi/pci_root.c 2014-05-29 11:49:12.737893537 +0900
@@ -63,6 +63,9 @@
.ids = root_device_ids,
.attach = acpi_pci_root_add,
.detach = acpi_pci_root_remove,
+ .hotplug = {
+ .ignore = true,
+ },
};
static DEFINE_MUTEX(osc_lock);
@@ -608,9 +611,12 @@
ej_event->device = device;
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+ get_device(&device->dev);
status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status)) {
+ put_device(&device->dev);
kfree(ej_event);
+ }
}
static void _handle_hotplug_event_root(struct work_struct *work)
diff -Nur linux/drivers/acpi/processor_idle.c rpi/drivers/acpi/processor_idle.c
--- linux/drivers/acpi/processor_idle.c 2014-05-29 12:18:18.929550651 +0900
+++ rpi/drivers/acpi/processor_idle.c 2014-05-29 11:49:12.740893512 +0900
@@ -119,17 +119,10 @@
*/
static void acpi_safe_halt(void)
{
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we
- * test NEED_RESCHED:
- */
- smp_mb();
- if (!need_resched()) {
+ if (!tif_need_resched()) {
safe_halt();
local_irq_disable();
}
- current_thread_info()->status |= TS_POLLING;
}
#ifdef ARCH_APICTIMER_STOPS_ON_C3
@@ -737,6 +730,11 @@
if (unlikely(!pr))
return -EINVAL;
+ if (cx->entry_method == ACPI_CSTATE_FFH) {
+ if (current_set_polling_and_test())
+ return -EINVAL;
+ }
+
lapic_timer_state_broadcast(pr, cx, 1);
acpi_idle_do_entry(cx);
@@ -790,18 +788,9 @@
if (unlikely(!pr))
return -EINVAL;
- if (cx->entry_method != ACPI_CSTATE_FFH) {
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
-
- if (unlikely(need_resched())) {
- current_thread_info()->status |= TS_POLLING;
+ if (cx->entry_method == ACPI_CSTATE_FFH) {
+ if (current_set_polling_and_test())
return -EINVAL;
- }
}
/*
@@ -819,9 +808,6 @@
sched_clock_idle_wakeup_event(0);
- if (cx->entry_method != ACPI_CSTATE_FFH)
- current_thread_info()->status |= TS_POLLING;
-
lapic_timer_state_broadcast(pr, cx, 0);
return index;
}
@@ -858,18 +844,9 @@
}
}
- if (cx->entry_method != ACPI_CSTATE_FFH) {
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
-
- if (unlikely(need_resched())) {
- current_thread_info()->status |= TS_POLLING;
+ if (cx->entry_method == ACPI_CSTATE_FFH) {
+ if (current_set_polling_and_test())
return -EINVAL;
- }
}
acpi_unlazy_tlb(smp_processor_id());
@@ -915,9 +892,6 @@
sched_clock_idle_wakeup_event(0);
- if (cx->entry_method != ACPI_CSTATE_FFH)
- current_thread_info()->status |= TS_POLLING;
-
lapic_timer_state_broadcast(pr, cx, 0);
return index;
}
diff -Nur linux/drivers/acpi/processor_throttling.c rpi/drivers/acpi/processor_throttling.c
--- linux/drivers/acpi/processor_throttling.c 2014-05-29 12:18:18.931550639 +0900
+++ rpi/drivers/acpi/processor_throttling.c 2014-05-29 11:49:12.741893503 +0900
@@ -59,6 +59,12 @@
int target_state; /* target T-state */
};
+struct acpi_processor_throttling_arg {
+ struct acpi_processor *pr;
+ int target_state;
+ bool force;
+};
+
#define THROTTLING_PRECHANGE (1)
#define THROTTLING_POSTCHANGE (2)
@@ -1063,16 +1069,24 @@
return 0;
}
+static long acpi_processor_throttling_fn(void *data)
+{
+ struct acpi_processor_throttling_arg *arg = data;
+ struct acpi_processor *pr = arg->pr;
+
+ return pr->throttling.acpi_processor_set_throttling(pr,
+ arg->target_state, arg->force);
+}
+
int acpi_processor_set_throttling(struct acpi_processor *pr,
int state, bool force)
{
- cpumask_var_t saved_mask;
int ret = 0;
unsigned int i;
struct acpi_processor *match_pr;
struct acpi_processor_throttling *p_throttling;
+ struct acpi_processor_throttling_arg arg;
struct throttling_tstate t_state;
- cpumask_var_t online_throttling_cpus;
if (!pr)
return -EINVAL;
@@ -1083,14 +1097,6 @@
if ((state < 0) || (state > (pr->throttling.state_count - 1)))
return -EINVAL;
- if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
- return -ENOMEM;
-
- if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
- free_cpumask_var(saved_mask);
- return -ENOMEM;
- }
-
if (cpu_is_offline(pr->id)) {
/*
* the cpu pointed by pr->id is offline. Unnecessary to change
@@ -1099,17 +1105,15 @@
return -ENODEV;
}
- cpumask_copy(saved_mask, &current->cpus_allowed);
t_state.target_state = state;
p_throttling = &(pr->throttling);
- cpumask_and(online_throttling_cpus, cpu_online_mask,
- p_throttling->shared_cpu_map);
+
/*
* The throttling notifier will be called for every
* affected cpu in order to get one proper T-state.
* The notifier event is THROTTLING_PRECHANGE.
*/
- for_each_cpu(i, online_throttling_cpus) {
+ for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
&t_state);
@@ -1121,21 +1125,18 @@
* it can be called only for the cpu pointed by pr.
*/
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
- /* FIXME: use work_on_cpu() */
- if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
- /* Can't migrate to the pr->id CPU. Exit */
- ret = -ENODEV;
- goto exit;
- }
- ret = p_throttling->acpi_processor_set_throttling(pr,
- t_state.target_state, force);
+ arg.pr = pr;
+ arg.target_state = state;
+ arg.force = force;
+ ret = work_on_cpu(pr->id, acpi_processor_throttling_fn, &arg);
} else {
/*
* When the T-state coordination is SW_ALL or HW_ALL,
* it is necessary to set T-state for every affected
* cpus.
*/
- for_each_cpu(i, online_throttling_cpus) {
+ for_each_cpu_and(i, cpu_online_mask,
+ p_throttling->shared_cpu_map) {
match_pr = per_cpu(processors, i);
/*
* If the pointer is invalid, we will report the
@@ -1156,13 +1157,12 @@
"on CPU %d\n", i));
continue;
}
- t_state.cpu = i;
- /* FIXME: use work_on_cpu() */
- if (set_cpus_allowed_ptr(current, cpumask_of(i)))
- continue;
- ret = match_pr->throttling.
- acpi_processor_set_throttling(
- match_pr, t_state.target_state, force);
+
+ arg.pr = match_pr;
+ arg.target_state = state;
+ arg.force = force;
+ ret = work_on_cpu(pr->id, acpi_processor_throttling_fn,
+ &arg);
}
}
/*
@@ -1171,17 +1171,12 @@
* affected cpu to update the T-states.
* The notifier event is THROTTLING_POSTCHANGE
*/
- for_each_cpu(i, online_throttling_cpus) {
+ for_each_cpu_and(i, cpu_online_mask, p_throttling->shared_cpu_map) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
&t_state);
}
- /* restore the previous state */
- /* FIXME: use work_on_cpu() */
- set_cpus_allowed_ptr(current, saved_mask);
-exit:
- free_cpumask_var(online_throttling_cpus);
- free_cpumask_var(saved_mask);
+
return ret;
}
diff -Nur linux/drivers/acpi/resource.c rpi/drivers/acpi/resource.c
--- linux/drivers/acpi/resource.c 2014-05-29 12:18:18.931550639 +0900
+++ rpi/drivers/acpi/resource.c 2014-05-29 11:49:12.742893495 +0900
@@ -77,18 +77,24 @@
switch (ares->type) {
case ACPI_RESOURCE_TYPE_MEMORY24:
memory24 = &ares->data.memory24;
+ if (!memory24->address_length)
+ return false;
acpi_dev_get_memresource(res, memory24->minimum,
memory24->address_length,
memory24->write_protect);
break;
case ACPI_RESOURCE_TYPE_MEMORY32:
memory32 = &ares->data.memory32;
+ if (!memory32->address_length)
+ return false;
acpi_dev_get_memresource(res, memory32->minimum,
memory32->address_length,
memory32->write_protect);
break;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
fixed_memory32 = &ares->data.fixed_memory32;
+ if (!fixed_memory32->address_length)
+ return false;
acpi_dev_get_memresource(res, fixed_memory32->address,
fixed_memory32->address_length,
fixed_memory32->write_protect);
@@ -144,12 +150,16 @@
switch (ares->type) {
case ACPI_RESOURCE_TYPE_IO:
io = &ares->data.io;
+ if (!io->address_length)
+ return false;
acpi_dev_get_ioresource(res, io->minimum,
io->address_length,
io->io_decode);
break;
case ACPI_RESOURCE_TYPE_FIXED_IO:
fixed_io = &ares->data.fixed_io;
+ if (!fixed_io->address_length)
+ return false;
acpi_dev_get_ioresource(res, fixed_io->address,
fixed_io->address_length,
ACPI_DECODE_10);
diff -Nur linux/drivers/acpi/scan.c rpi/drivers/acpi/scan.c
--- linux/drivers/acpi/scan.c 2014-05-29 12:18:18.933550626 +0900
+++ rpi/drivers/acpi/scan.c 2014-05-29 11:49:12.744893478 +0900
@@ -331,8 +331,6 @@
goto out;
}
}
- acpi_evaluate_hotplug_ost(handle, ost_source,
- ACPI_OST_SC_INSERT_IN_PROGRESS, NULL);
error = acpi_bus_scan(handle);
if (error) {
acpi_handle_warn(handle, "Namespace scan failure\n");
@@ -1814,7 +1812,7 @@
*/
list_for_each_entry(hwid, &pnp.ids, list) {
handler = acpi_scan_match_handler(hwid->id, NULL);
- if (handler) {
+ if (handler && !handler->hotplug.ignore) {
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
acpi_hotplug_notify_cb, handler);
break;
diff -Nur linux/drivers/acpi/sleep.c rpi/drivers/acpi/sleep.c
--- linux/drivers/acpi/sleep.c 2014-05-29 12:18:18.934550620 +0900
+++ rpi/drivers/acpi/sleep.c 2014-05-29 11:49:12.745893470 +0900
@@ -75,6 +75,17 @@
return 0;
}
+static bool acpi_sleep_state_supported(u8 sleep_state)
+{
+ acpi_status status;
+ u8 type_a, type_b;
+
+ status = acpi_get_sleep_type_data(sleep_state, &type_a, &type_b);
+ return ACPI_SUCCESS(status) && (!acpi_gbl_reduced_hardware
+ || (acpi_gbl_FADT.sleep_control.address
+ && acpi_gbl_FADT.sleep_status.address));
+}
+
#ifdef CONFIG_ACPI_SLEEP
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
@@ -608,15 +619,9 @@
{
int i;
- for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++) {
- acpi_status status;
- u8 type_a, type_b;
-
- status = acpi_get_sleep_type_data(i, &type_a, &type_b);
- if (ACPI_SUCCESS(status)) {
+ for (i = ACPI_STATE_S1; i < ACPI_STATE_S4; i++)
+ if (acpi_sleep_state_supported(i))
sleep_states[i] = 1;
- }
- }
suspend_set_ops(old_suspend_ordering ?
&acpi_suspend_ops_old : &acpi_suspend_ops);
@@ -670,11 +675,8 @@
/* Reprogram control registers */
acpi_leave_sleep_state_prep(ACPI_STATE_S4);
/* Check the hardware signature */
- if (facs && s4_hardware_signature != facs->hardware_signature) {
- printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
- "cannot resume!\n");
- panic("ACPI S4 hardware signature mismatch");
- }
+ if (facs && s4_hardware_signature != facs->hardware_signature)
+ pr_crit("ACPI: Hardware changed while hibernated, success doubtful!\n");
/* Restore the NVS memory area */
suspend_nvs_restore();
/* Allow EC transactions to happen. */
@@ -747,11 +749,7 @@
static void acpi_sleep_hibernate_setup(void)
{
- acpi_status status;
- u8 type_a, type_b;
-
- status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b);
- if (ACPI_FAILURE(status))
+ if (!acpi_sleep_state_supported(ACPI_STATE_S4))
return;
hibernation_set_ops(old_suspend_ordering ?
@@ -800,8 +798,6 @@
int __init acpi_sleep_init(void)
{
- acpi_status status;
- u8 type_a, type_b;
char supported[ACPI_S_STATE_COUNT * 3 + 1];
char *pos = supported;
int i;
@@ -816,8 +812,7 @@
acpi_sleep_suspend_setup();
acpi_sleep_hibernate_setup();
- status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
- if (ACPI_SUCCESS(status)) {
+ if (acpi_sleep_state_supported(ACPI_STATE_S5)) {
sleep_states[ACPI_STATE_S5] = 1;
pm_power_off_prepare = acpi_power_off_prepare;
pm_power_off = acpi_power_off;
diff -Nur linux/drivers/acpi/video.c rpi/drivers/acpi/video.c
--- linux/drivers/acpi/video.c 2014-05-29 12:18:18.938550595 +0900
+++ rpi/drivers/acpi/video.c 2014-05-29 11:49:12.748893445 +0900
@@ -729,6 +729,7 @@
union acpi_object *o;
struct acpi_video_device_brightness *br = NULL;
int result = -EINVAL;
+ u32 value;
if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
@@ -759,7 +760,12 @@
printk(KERN_ERR PREFIX "Invalid data\n");
continue;
}
- br->levels[count] = (u32) o->integer.value;
+ value = (u32) o->integer.value;
+ /* Skip duplicate entries */
+ if (count > 2 && br->levels[count - 1] == value)
+ continue;
+
+ br->levels[count] = value;
if (br->levels[count] > max_level)
max_level = br->levels[count];
@@ -832,7 +838,7 @@
for (i = 2; i < br->count; i++)
if (level_old == br->levels[i])
break;
- if (i == br->count)
+ if (i == br->count || !level)
level = max_level;
}
diff -Nur linux/drivers/ata/ahci.c rpi/drivers/ata/ahci.c
--- linux/drivers/ata/ahci.c 2014-05-29 12:18:18.943550563 +0900
+++ rpi/drivers/ata/ahci.c 2014-05-29 11:49:12.752893411 +0900
@@ -61,6 +61,7 @@
/* board IDs by feature in alphabetical order */
board_ahci,
board_ahci_ign_iferr,
+ board_ahci_noncq,
board_ahci_nosntf,
board_ahci_yes_fbs,
@@ -119,6 +120,13 @@
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
+ [board_ahci_noncq] = {
+ AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ),
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+ },
[board_ahci_nosntf] = {
AHCI_HFLAGS (AHCI_HFLAG_NO_SNTF),
.flags = AHCI_FLAG_COMMON,
@@ -292,6 +300,10 @@
{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
+ { PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */
+ { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */
+ { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
+ { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -423,6 +435,9 @@
.driver_data = board_ahci_yes_fbs }, /* 88se9128 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
.driver_data = board_ahci_yes_fbs }, /* 88se9125 */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_MARVELL_EXT, 0x9178,
+ PCI_VENDOR_ID_MARVELL_EXT, 0x9170),
+ .driver_data = board_ahci_yes_fbs }, /* 88se9170 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
.driver_data = board_ahci_yes_fbs }, /* 88se9172 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
@@ -431,6 +446,8 @@
.driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
.driver_data = board_ahci_yes_fbs },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230),
+ .driver_data = board_ahci_yes_fbs },
/* Promise */
{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */
@@ -441,6 +458,12 @@
{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */
{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */
+ /*
+ * Samsung SSDs found on some macbooks. NCQ times out.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=60731
+ */
+ { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq },
+
/* Enmotus */
{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
@@ -1146,18 +1169,18 @@
return rc;
for (i = 0; i < host->n_ports; i++) {
- const char* desc;
struct ahci_port_priv *pp = host->ports[i]->private_data;
- /* pp is NULL for dummy ports */
- if (pp)
- desc = pp->irq_desc;
- else
- desc = dev_driver_string(host->dev);
+ /* Do not receive interrupts sent by dummy ports */
+ if (!pp) {
+ disable_irq(irq + i);
+ continue;
+ }
- rc = devm_request_threaded_irq(host->dev,
- irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
- desc, host->ports[i]);
+ rc = devm_request_threaded_irq(host->dev, irq + i,
+ ahci_hw_interrupt,
+ ahci_thread_fn, IRQF_SHARED,
+ pp->irq_desc, host->ports[i]);
if (rc)
goto out_free_irqs;
}
diff -Nur linux/drivers/ata/ahci_imx.c rpi/drivers/ata/ahci_imx.c
--- linux/drivers/ata/ahci_imx.c 2014-05-29 12:18:18.944550557 +0900
+++ rpi/drivers/ata/ahci_imx.c 2014-05-29 11:49:12.753893403 +0900
@@ -60,7 +60,7 @@
/*
* set PHY Paremeters, two steps to configure the GPR13,
* one write for rest of parameters, mask of first write
- * is 0x07fffffd, and the other one write for setting
+ * is 0x07ffffff, and the other one write for setting
* the mpll_clk_en.
*/
regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK
@@ -71,6 +71,7 @@
| IMX6Q_GPR13_SATA_TX_ATTEN_MASK
| IMX6Q_GPR13_SATA_TX_BOOST_MASK
| IMX6Q_GPR13_SATA_TX_LVL_MASK
+ | IMX6Q_GPR13_SATA_MPLL_CLK_EN
| IMX6Q_GPR13_SATA_TX_EDGE_RATE
, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB
| IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M
diff -Nur linux/drivers/ata/libahci.c rpi/drivers/ata/libahci.c
--- linux/drivers/ata/libahci.c 2014-05-29 12:18:18.947550538 +0900
+++ rpi/drivers/ata/libahci.c 2014-05-29 11:49:12.755893386 +0900
@@ -1275,9 +1275,11 @@
{
struct ata_port *ap = link->ap;
struct ahci_host_priv *hpriv = ap->host->private_data;
+ struct ahci_port_priv *pp = ap->private_data;
const char *reason = NULL;
unsigned long now, msecs;
struct ata_taskfile tf;
+ bool fbs_disabled = false;
int rc;
DPRINTK("ENTER\n");
@@ -1287,6 +1289,16 @@
if (rc && rc != -EOPNOTSUPP)
ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc);
+ /*
+ * According to AHCI-1.2 9.3.9: if FBS is enable, software shall
+ * clear PxFBS.EN to '0' prior to issuing software reset to devices
+ * that is attached to port multiplier.
+ */
+ if (!ata_is_host_link(link) && pp->fbs_enabled) {
+ ahci_disable_fbs(ap);
+ fbs_disabled = true;
+ }
+
ata_tf_init(link->device, &tf);
/* issue the first D2H Register FIS */
@@ -1327,6 +1339,10 @@
} else
*class = ahci_dev_classify(ap);
+ /* re-enable FBS if disabled before */
+ if (fbs_disabled)
+ ahci_enable_fbs(ap);
+
DPRINTK("EXIT, class=%u\n", *class);
return 0;
diff -Nur linux/drivers/ata/libata-core.c rpi/drivers/ata/libata-core.c
--- linux/drivers/ata/libata-core.c 2014-05-29 12:18:18.952550507 +0900
+++ rpi/drivers/ata/libata-core.c 2014-05-29 11:49:12.760893344 +0900
@@ -2149,9 +2149,16 @@
"failed to get NCQ Send/Recv Log Emask 0x%x\n",
err_mask);
} else {
+ u8 *cmds = dev->ncq_send_recv_cmds;
+
dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
- memcpy(dev->ncq_send_recv_cmds, ap->sector_buf,
- ATA_LOG_NCQ_SEND_RECV_SIZE);
+ memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE);
+
+ if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) {
+ ata_dev_dbg(dev, "disabling queued TRIM support\n");
+ cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &=
+ ~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM;
+ }
}
}
@@ -2215,6 +2222,16 @@
if (rc)
return rc;
+ /* some WD SATA-1 drives have issues with LPM, turn on NOLPM for them */
+ if ((dev->horkage & ATA_HORKAGE_WD_BROKEN_LPM) &&
+ (id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2)
+ dev->horkage |= ATA_HORKAGE_NOLPM;
+
+ if (dev->horkage & ATA_HORKAGE_NOLPM) {
+ ata_dev_warn(dev, "LPM support broken, forcing max_power\n");
+ dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER;
+ }
+
/* let ACPI work its magic */
rc = ata_acpi_on_devcfg(dev);
if (rc)
@@ -4126,6 +4143,7 @@
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 },
{ "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA },
{ "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 },
+ { "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 },
/* Devices we expect to fail diagnostics */
@@ -4155,6 +4173,10 @@
{ "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ |
ATA_HORKAGE_FIRMWARE_WARN },
+ /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
+ { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+ { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+
/* Blacklist entries taken from Silicon Image 3124/3132
Windows driver .inf file - also several Linux problem reports */
{ "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
@@ -4201,6 +4223,29 @@
{ "PIONEER DVD-RW DVR-212D", NULL, ATA_HORKAGE_NOSETXFER },
{ "PIONEER DVD-RW DVR-216D", NULL, ATA_HORKAGE_NOSETXFER },
+ /* devices that don't properly handle queued TRIM commands */
+ { "Micron_M500*", "MU0[1-4]*", ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "Crucial_CT???M500SSD*", "MU0[1-4]*", ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "Micron_M550*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
+ { "Crucial_CT???M550SSD*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
+
+ /*
+ * Some WD SATA-I drives spin up and down erratically when the link
+ * is put into the slumber mode. We don't have full list of the
+ * affected devices. Disable LPM if the device matches one of the
+ * known prefixes and is SATA-1. As a side effect LPM partial is
+ * lost too.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=57211
+ */
+ { "WDC WD800JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
+ { "WDC WD1200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
+ { "WDC WD1600JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
+ { "WDC WD2000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
+ { "WDC WD2500JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
+ { "WDC WD3000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
+ { "WDC WD3200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
+
/* End Marker */
{ }
};
@@ -4749,21 +4794,26 @@
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
{
struct ata_queued_cmd *qc = NULL;
- unsigned int i;
+ unsigned int i, tag;
/* no command while frozen */
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
return NULL;
- /* the last tag is reserved for internal command. */
- for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
- if (!test_and_set_bit(i, &ap->qc_allocated)) {
- qc = __ata_qc_from_tag(ap, i);
+ for (i = 0; i < ATA_MAX_QUEUE; i++) {
+ tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE;
+
+ /* the last tag is reserved for internal command. */
+ if (tag == ATA_TAG_INTERNAL)
+ continue;
+
+ if (!test_and_set_bit(tag, &ap->qc_allocated)) {
+ qc = __ata_qc_from_tag(ap, tag);
+ qc->tag = tag;
+ ap->last_tag = tag;
break;
}
-
- if (qc)
- qc->tag = i;
+ }
return qc;
}
@@ -6519,6 +6569,7 @@
{ "norst", .lflags = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
{ "rstonce", .lflags = ATA_LFLAG_RST_ONCE },
{ "atapi_dmadir", .horkage_on = ATA_HORKAGE_ATAPI_DMADIR },
+ { "disable", .horkage_on = ATA_HORKAGE_DISABLE },
};
char *start = *cur, *p = *cur;
char *id, *val, *endp;
diff -Nur linux/drivers/ata/libata-pmp.c rpi/drivers/ata/libata-pmp.c
--- linux/drivers/ata/libata-pmp.c 2014-05-29 12:18:18.955550488 +0900
+++ rpi/drivers/ata/libata-pmp.c 2014-05-29 11:49:12.763893319 +0900
@@ -447,8 +447,11 @@
* otherwise. Don't try hard to recover it.
*/
ap->pmp_link[ap->nr_pmp_links - 1].flags |= ATA_LFLAG_NO_RETRY;
- } else if (vendor == 0x197b && devid == 0x2352) {
- /* chip found in Thermaltake BlackX Duet, jmicron JMB350? */
+ } else if (vendor == 0x197b && (devid == 0x2352 || devid == 0x0325)) {
+ /*
+ * 0x2352: found in Thermaltake BlackX Duet, jmicron JMB350?
+ * 0x0325: jmicron JMB394.
+ */
ata_for_each_link(link, ap, EDGE) {
/* SRST breaks detection and disks get misclassified
* LPM disabled to avoid potential problems
diff -Nur linux/drivers/ata/libata-scsi.c rpi/drivers/ata/libata-scsi.c
--- linux/drivers/ata/libata-scsi.c 2014-05-29 12:18:18.958550470 +0900
+++ rpi/drivers/ata/libata-scsi.c 2014-05-29 11:49:12.765893302 +0900
@@ -111,12 +111,14 @@
[ATA_LPM_MIN_POWER] = "min_power",
};
-static ssize_t ata_scsi_lpm_store(struct device *dev,
+static ssize_t ata_scsi_lpm_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct Scsi_Host *shost = class_to_shost(dev);
+ struct Scsi_Host *shost = class_to_shost(device);
struct ata_port *ap = ata_shost_to_port(shost);
+ struct ata_link *link;
+ struct ata_device *dev;
enum ata_lpm_policy policy;
unsigned long flags;
@@ -132,10 +134,20 @@
return -EINVAL;
spin_lock_irqsave(ap->lock, flags);
+
+ ata_for_each_link(link, ap, EDGE) {
+ ata_for_each_dev(dev, &ap->link, ENABLED) {
+ if (dev->horkage & ATA_HORKAGE_NOLPM) {
+ count = -EOPNOTSUPP;
+ goto out_unlock;
+ }
+ }
+ }
+
ap->target_lpm_policy = policy;
ata_port_schedule_eh(ap);
+out_unlock:
spin_unlock_irqrestore(ap->lock, flags);
-
return count;
}
@@ -3625,6 +3637,7 @@
shost->max_lun = 1;
shost->max_channel = 1;
shost->max_cmd_len = 16;
+ shost->no_write_same = 1;
/* Schedule policy is determined by ->qc_defer()
* callback and it needs to see every deferred qc.
@@ -3871,6 +3884,27 @@
return;
}
+ /*
+ * XXX - UGLY HACK
+ *
+ * The block layer suspend/resume path is fundamentally broken due
+ * to freezable kthreads and workqueue and may deadlock if a block
+ * device gets removed while resume is in progress. I don't know
+ * what the solution is short of removing freezable kthreads and
+ * workqueues altogether.
+ *
+ * The following is an ugly hack to avoid kicking off device
+ * removal while freezer is active. This is a joke but does avoid
+ * this particular deadlock scenario.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=62801
+ * http://marc.info/?l=linux-kernel&m=138695698516487
+ */
+#ifdef CONFIG_FREEZER
+ while (pm_freezing)
+ msleep(10);
+#endif
+
DPRINTK("ENTER\n");
mutex_lock(&ap->scsi_scan_mutex);
diff -Nur linux/drivers/ata/libata-transport.c rpi/drivers/ata/libata-transport.c
--- linux/drivers/ata/libata-transport.c 2014-05-29 12:18:18.958550470 +0900
+++ rpi/drivers/ata/libata-transport.c 2014-05-29 11:49:12.767893285 +0900
@@ -321,25 +321,25 @@
/*
* ATA link attributes
*/
+static int noop(int x) { return x; }
-
-#define ata_link_show_linkspeed(field) \
+#define ata_link_show_linkspeed(field, format) \
static ssize_t \
show_ata_link_##field(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct ata_link *link = transport_class_to_link(dev); \
\
- return sprintf(buf,"%s\n", sata_spd_string(fls(link->field))); \
+ return sprintf(buf, "%s\n", sata_spd_string(format(link->field))); \
}
-#define ata_link_linkspeed_attr(field) \
- ata_link_show_linkspeed(field) \
+#define ata_link_linkspeed_attr(field, format) \
+ ata_link_show_linkspeed(field, format) \
static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL)
-ata_link_linkspeed_attr(hw_sata_spd_limit);
-ata_link_linkspeed_attr(sata_spd_limit);
-ata_link_linkspeed_attr(sata_spd);
+ata_link_linkspeed_attr(hw_sata_spd_limit, fls);
+ata_link_linkspeed_attr(sata_spd_limit, fls);
+ata_link_linkspeed_attr(sata_spd, noop);
static DECLARE_TRANSPORT_CLASS(ata_link_class,
diff -Nur linux/drivers/ata/sata_mv.c rpi/drivers/ata/sata_mv.c
--- linux/drivers/ata/sata_mv.c 2014-05-29 12:18:18.991550263 +0900
+++ rpi/drivers/ata/sata_mv.c 2014-05-29 11:49:12.797893034 +0900
@@ -304,6 +304,7 @@
MV5_LTMODE = 0x30,
MV5_PHY_CTL = 0x0C,
SATA_IFCFG = 0x050,
+ LP_PHY_CTL = 0x058,
MV_M2_PREAMP_MASK = 0x7e0,
@@ -431,6 +432,7 @@
MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */
MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */
MV_HP_QUIRK_LED_BLINK_EN = (1 << 12), /* is led blinking enabled? */
+ MV_HP_FIX_LP_PHY_CTL = (1 << 13), /* fix speed in LP_PHY_CTL ? */
/* Port private flags (pp_flags) */
MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
@@ -1358,6 +1360,7 @@
if (ofs != 0xffffffffU) {
void __iomem *addr = mv_ap_base(link->ap) + ofs;
+ struct mv_host_priv *hpriv = link->ap->host->private_data;
if (sc_reg_in == SCR_CONTROL) {
/*
* Workaround for 88SX60x1 FEr SATA#26:
@@ -1374,6 +1377,18 @@
*/
if ((val & 0xf) == 1 || (readl(addr) & 0xf) == 1)
val |= 0xf000;
+
+ if (hpriv->hp_flags & MV_HP_FIX_LP_PHY_CTL) {
+ void __iomem *lp_phy_addr =
+ mv_ap_base(link->ap) + LP_PHY_CTL;
+ /*
+ * Set PHY speed according to SControl speed.
+ */
+ if ((val & 0xf0) == 0x10)
+ writelfl(0x7, lp_phy_addr);
+ else
+ writelfl(0x227, lp_phy_addr);
+ }
}
writelfl(val, addr);
return 0;
@@ -4110,6 +4125,15 @@
if (rc)
goto err;
+ /*
+ * To allow disk hotplug on Armada 370/XP SoCs, the PHY speed must be
+ * updated in the LP_PHY_CTL register.
+ */
+ if (pdev->dev.of_node &&
+ of_device_is_compatible(pdev->dev.of_node,
+ "marvell,armada-370-sata"))
+ hpriv->hp_flags |= MV_HP_FIX_LP_PHY_CTL;
+
/* initialize adapter */
rc = mv_init_host(host);
if (rc)
@@ -4209,6 +4233,7 @@
#ifdef CONFIG_OF
static struct of_device_id mv_sata_dt_ids[] = {
+ { .compatible = "marvell,armada-370-sata", },
{ .compatible = "marvell,orion-sata", },
{},
};
diff -Nur linux/drivers/ata/sata_sil.c rpi/drivers/ata/sata_sil.c
--- linux/drivers/ata/sata_sil.c 2014-05-29 12:18:18.995550238 +0900
+++ rpi/drivers/ata/sata_sil.c 2014-05-29 11:49:12.801893000 +0900
@@ -157,6 +157,7 @@
{ "ST380011ASL", SIL_QUIRK_MOD15WRITE },
{ "ST3120022ASL", SIL_QUIRK_MOD15WRITE },
{ "ST3160021ASL", SIL_QUIRK_MOD15WRITE },
+ { "TOSHIBA MK2561GSYN", SIL_QUIRK_MOD15WRITE },
{ "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX },
{ }
};
diff -Nur linux/drivers/atm/idt77252.c rpi/drivers/atm/idt77252.c
--- linux/drivers/atm/idt77252.c 2014-05-29 12:18:19.006550169 +0900
+++ rpi/drivers/atm/idt77252.c 2014-05-29 11:49:12.817892866 +0900
@@ -3511,7 +3511,7 @@
tmp = dev_get_by_name(&init_net, tname); /* jhs: was "tmp = dev_get(tname);" */
if (tmp) {
memcpy(card->atmdev->esi, tmp->dev_addr, 6);
-
+ dev_put(tmp);
printk("%s: ESI %pM\n", card->name, card->atmdev->esi);
}
/*
diff -Nur linux/drivers/base/dd.c rpi/drivers/base/dd.c
--- linux/drivers/base/dd.c 2014-05-29 12:18:19.014550119 +0900
+++ rpi/drivers/base/dd.c 2014-05-29 11:49:12.834892724 +0900
@@ -499,7 +499,7 @@
BUS_NOTIFY_UNBIND_DRIVER,
dev);
- pm_runtime_put(dev);
+ pm_runtime_put_sync(dev);
if (dev->bus && dev->bus->remove)
dev->bus->remove(dev);
diff -Nur linux/drivers/base/firmware_class.c rpi/drivers/base/firmware_class.c
--- linux/drivers/base/firmware_class.c 2014-05-29 12:18:19.017550100 +0900
+++ rpi/drivers/base/firmware_class.c 2014-05-29 11:49:12.837892699 +0900
@@ -1529,6 +1529,7 @@
switch (mode) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
+ case PM_RESTORE_PREPARE:
kill_requests_without_uevent();
device_cache_fw_images();
break;
diff -Nur linux/drivers/block/aoe/aoecmd.c rpi/drivers/block/aoe/aoecmd.c
--- linux/drivers/block/aoe/aoecmd.c 2014-05-29 12:18:19.042549944 +0900
+++ rpi/drivers/block/aoe/aoecmd.c 2014-05-29 11:49:12.870892422 +0900
@@ -905,7 +905,7 @@
/* Non-zero page count for non-head members of
* compound pages is no longer allowed by the kernel.
*/
- page = compound_trans_head(bv->bv_page);
+ page = compound_head(bv->bv_page);
atomic_inc(&page->_count);
}
}
@@ -918,7 +918,7 @@
int i;
bio_for_each_segment(bv, bio, i) {
- page = compound_trans_head(bv->bv_page);
+ page = compound_head(bv->bv_page);
atomic_dec(&page->_count);
}
}
diff -Nur linux/drivers/block/brd.c rpi/drivers/block/brd.c
--- linux/drivers/block/brd.c 2014-05-29 12:18:19.043549938 +0900
+++ rpi/drivers/block/brd.c 2014-05-29 11:49:12.872892405 +0900
@@ -545,7 +545,7 @@
mutex_lock(&brd_devices_mutex);
brd = brd_init_one(MINOR(dev) >> part_shift);
- kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM);
+ kobj = brd ? get_disk(brd->brd_disk) : NULL;
mutex_unlock(&brd_devices_mutex);
*part = 0;
diff -Nur linux/drivers/block/floppy.c rpi/drivers/block/floppy.c
--- linux/drivers/block/floppy.c 2014-05-29 12:18:19.065549800 +0900
+++ rpi/drivers/block/floppy.c 2014-05-29 11:49:12.909892095 +0900
@@ -3053,7 +3053,10 @@
int ret;
while (ptr) {
- ret = copy_to_user(param, ptr, sizeof(*ptr));
+ struct floppy_raw_cmd cmd = *ptr;
+ cmd.next = NULL;
+ cmd.kernel_data = NULL;
+ ret = copy_to_user(param, &cmd, sizeof(cmd));
if (ret)
return -EFAULT;
param += sizeof(struct floppy_raw_cmd);
@@ -3107,10 +3110,11 @@
return -ENOMEM;
*rcmd = ptr;
ret = copy_from_user(ptr, param, sizeof(*ptr));
- if (ret)
- return -EFAULT;
ptr->next = NULL;
ptr->buffer_length = 0;
+ ptr->kernel_data = NULL;
+ if (ret)
+ return -EFAULT;
param += sizeof(struct floppy_raw_cmd);
if (ptr->cmd_count > 33)
/* the command may now also take up the space
@@ -3126,7 +3130,6 @@
for (i = 0; i < 16; i++)
ptr->reply[i] = 0;
ptr->resultcode = 0;
- ptr->kernel_data = NULL;
if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
if (ptr->length <= 0)
@@ -3691,9 +3694,12 @@
if (!(mode & FMODE_NDELAY)) {
if (mode & (FMODE_READ|FMODE_WRITE)) {
UDRS->last_checked = 0;
+ clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
check_disk_change(bdev);
if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
goto out;
+ if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
+ goto out;
}
res = -EROFS;
if ((mode & FMODE_WRITE) &&
@@ -3746,17 +3752,29 @@
* a disk in the drive, and whether that disk is writable.
*/
-static void floppy_rb0_complete(struct bio *bio, int err)
+struct rb0_cbdata {
+ int drive;
+ struct completion complete;
+};
+
+static void floppy_rb0_cb(struct bio *bio, int err)
{
- complete((struct completion *)bio->bi_private);
+ struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private;
+ int drive = cbdata->drive;
+
+ if (err) {
+ pr_info("floppy: error %d while reading block 0", err);
+ set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
+ }
+ complete(&cbdata->complete);
}
-static int __floppy_read_block_0(struct block_device *bdev)
+static int __floppy_read_block_0(struct block_device *bdev, int drive)
{
struct bio bio;
struct bio_vec bio_vec;
- struct completion complete;
struct page *page;
+ struct rb0_cbdata cbdata;
size_t size;
page = alloc_page(GFP_NOIO);
@@ -3769,6 +3787,8 @@
if (!size)
size = 1024;
+ cbdata.drive = drive;
+
bio_init(&bio);
bio.bi_io_vec = &bio_vec;
bio_vec.bv_page = page;
@@ -3779,13 +3799,14 @@
bio.bi_bdev = bdev;
bio.bi_sector = 0;
bio.bi_flags = (1 << BIO_QUIET);
- init_completion(&complete);
- bio.bi_private = &complete;
- bio.bi_end_io = floppy_rb0_complete;
+ bio.bi_private = &cbdata;
+ bio.bi_end_io = floppy_rb0_cb;
submit_bio(READ, &bio);
process_fd_request();
- wait_for_completion(&complete);
+
+ init_completion(&cbdata.complete);
+ wait_for_completion(&cbdata.complete);
__free_page(page);
@@ -3827,7 +3848,7 @@
UDRS->generation++;
if (drive_no_geom(drive)) {
/* auto-sensing */
- res = __floppy_read_block_0(opened_bdev[drive]);
+ res = __floppy_read_block_0(opened_bdev[drive], drive);
} else {
if (cf)
poll_drive(false, FD_RAW_NEED_DISK);
diff -Nur linux/drivers/block/loop.c rpi/drivers/block/loop.c
--- linux/drivers/block/loop.c 2014-05-29 12:18:19.066549794 +0900
+++ rpi/drivers/block/loop.c 2014-05-29 11:49:12.911892079 +0900
@@ -894,13 +894,6 @@
bio_list_init(&lo->lo_bio_list);
- /*
- * set queue make_request_fn, and add limits based on lower level
- * device
- */
- blk_queue_make_request(lo->lo_queue, loop_make_request);
- lo->lo_queue->queuedata = lo;
-
if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
blk_queue_flush(lo->lo_queue, REQ_FLUSH);
@@ -1618,6 +1611,8 @@
if (!lo)
goto out;
+ lo->lo_state = Lo_unbound;
+
/* allocate id, if @id >= 0, we're requesting that specific id */
if (i >= 0) {
err = idr_alloc(&loop_index_idr, lo, i, i + 1, GFP_KERNEL);
@@ -1633,7 +1628,13 @@
err = -ENOMEM;
lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
if (!lo->lo_queue)
- goto out_free_dev;
+ goto out_free_idr;
+
+ /*
+ * set queue make_request_fn
+ */
+ blk_queue_make_request(lo->lo_queue, loop_make_request);
+ lo->lo_queue->queuedata = lo;
disk = lo->lo_disk = alloc_disk(1 << part_shift);
if (!disk)
@@ -1678,6 +1679,8 @@
out_free_queue:
blk_cleanup_queue(lo->lo_queue);
+out_free_idr:
+ idr_remove(&loop_index_idr, i);
out_free_dev:
kfree(lo);
out:
@@ -1741,7 +1744,7 @@
if (err < 0)
err = loop_add(&lo, MINOR(dev) >> part_shift);
if (err < 0)
- kobj = ERR_PTR(err);
+ kobj = NULL;
else
kobj = get_disk(lo->lo_disk);
mutex_unlock(&loop_index_mutex);
diff -Nur linux/drivers/block/mtip32xx/mtip32xx.c rpi/drivers/block/mtip32xx/mtip32xx.c
--- linux/drivers/block/mtip32xx/mtip32xx.c 2014-05-29 12:18:19.069549775 +0900
+++ rpi/drivers/block/mtip32xx/mtip32xx.c 2014-05-29 11:49:12.915892045 +0900
@@ -621,6 +621,12 @@
*/
writel(1 << bit, port->completed[group]);
+ /* Unmap the DMA scatter list entries */
+ dma_unmap_sg(&port->dd->pdev->dev,
+ command->sg,
+ command->scatter_ents,
+ command->direction);
+
/* Call the async completion callback. */
if (likely(command->async_callback))
command->async_callback(command->async_data,
@@ -628,12 +634,6 @@
command->async_callback = NULL;
command->comp_func = NULL;
- /* Unmap the DMA scatter list entries */
- dma_unmap_sg(&port->dd->pdev->dev,
- command->sg,
- command->scatter_ents,
- command->direction);
-
/*
* Clear the allocated bit and active tag for the
* command.
@@ -711,6 +711,12 @@
"Command tag %d failed due to TFE\n", tag);
}
+ /* Unmap the DMA scatter list entries */
+ dma_unmap_sg(&dd->pdev->dev,
+ command->sg,
+ command->scatter_ents,
+ command->direction);
+
/* Upper layer callback */
if (likely(command->async_callback))
command->async_callback(command->async_data, cb_status);
@@ -718,12 +724,6 @@
command->async_callback = NULL;
command->comp_func = NULL;
- /* Unmap the DMA scatter list entries */
- dma_unmap_sg(&dd->pdev->dev,
- command->sg,
- command->scatter_ents,
- command->direction);
-
/* Clear the allocated and active bits for the command */
atomic_set(&port->commands[tag].active, 0);
release_slot(port, tag);
@@ -4040,6 +4040,7 @@
blk_queue_max_hw_sectors(dd->queue, 0xffff);
blk_queue_max_segment_size(dd->queue, 0x400000);
blk_queue_io_min(dd->queue, 4096);
+ blk_queue_bounce_limit(dd->queue, dd->pdev->dma_mask);
/*
* write back cache is not supported in the device. FUA depends on
diff -Nur linux/drivers/block/xen-blkback/blkback.c rpi/drivers/block/xen-blkback/blkback.c
--- linux/drivers/block/xen-blkback/blkback.c 2014-05-29 12:18:19.085549675 +0900
+++ rpi/drivers/block/xen-blkback/blkback.c 2014-05-29 11:49:12.938891852 +0900
@@ -887,6 +887,8 @@
unsigned long secure;
struct phys_req preq;
+ xen_blkif_get(blkif);
+
preq.sector_number = req->u.discard.sector_number;
preq.nr_sects = req->u.discard.nr_sectors;
@@ -899,7 +901,6 @@
}
blkif->st_ds_req++;
- xen_blkif_get(blkif);
secure = (blkif->vbd.discard_secure &&
(req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
BLKDEV_DISCARD_SECURE : 0;
diff -Nur linux/drivers/block/xen-blkfront.c rpi/drivers/block/xen-blkfront.c
--- linux/drivers/block/xen-blkfront.c 2014-05-29 12:18:19.087549663 +0900
+++ rpi/drivers/block/xen-blkfront.c 2014-05-29 11:49:12.940891836 +0900
@@ -1278,7 +1278,7 @@
char *type;
int len;
/* no unplug has been done: do not hook devices != xen vbds */
- if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY) {
+ if (xen_has_pv_and_legacy_disk_devices()) {
int major;
if (!VDEV_IS_EXTENDED(vdevice))
@@ -1852,13 +1852,16 @@
case XenbusStateReconfiguring:
case XenbusStateReconfigured:
case XenbusStateUnknown:
- case XenbusStateClosed:
break;
case XenbusStateConnected:
blkfront_connect(info);
break;
+ case XenbusStateClosed:
+ if (dev->state == XenbusStateClosed)
+ break;
+ /* Missed the backend's Closing state -- fallthrough */
case XenbusStateClosing:
blkfront_closing(info);
break;
@@ -2022,7 +2025,7 @@
if (!xen_domain())
return -ENODEV;
- if (xen_hvm_domain() && !xen_platform_pci_unplug)
+ if (!xen_has_pv_disk_devices())
return -ENODEV;
if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) {
diff -Nur linux/drivers/bluetooth/btusb.c rpi/drivers/bluetooth/btusb.c
--- linux/drivers/bluetooth/btusb.c 2014-05-29 12:18:19.093549625 +0900
+++ rpi/drivers/bluetooth/btusb.c 2014-05-29 11:49:12.946891785 +0900
@@ -223,6 +223,7 @@
/* Intel Bluetooth device */
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
+ { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
{ } /* Terminating entry */
};
@@ -1628,7 +1629,6 @@
#ifdef CONFIG_PM
.suspend = btusb_suspend,
.resume = btusb_resume,
- .reset_resume = btusb_resume,
#endif
.id_table = btusb_table,
.supports_autosuspend = 1,
diff -Nur linux/drivers/char/broadcom/Kconfig rpi/drivers/char/broadcom/Kconfig
--- linux/drivers/char/broadcom/Kconfig 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/char/broadcom/Kconfig 2014-05-29 11:49:12.966891618 +0900
@@ -0,0 +1,16 @@
+#
+# Broadcom char driver config
+#
+
+menuconfig BRCM_CHAR_DRIVERS
+ bool "Broadcom Char Drivers"
+ help
+ Broadcom's char drivers
+
+config BCM_VC_CMA
+ bool "Videocore CMA"
+ depends on CMA && BRCM_CHAR_DRIVERS && BCM2708_VCHIQ
+ default n
+ help
+ Helper for videocore CMA access.
+
diff -Nur linux/drivers/char/broadcom/Makefile rpi/drivers/char/broadcom/Makefile
--- linux/drivers/char/broadcom/Makefile 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/char/broadcom/Makefile 2014-05-29 11:49:12.966891618 +0900
@@ -0,0 +1 @@
+obj-$(CONFIG_BCM_VC_CMA) += vc_cma/
diff -Nur linux/drivers/char/broadcom/vc_cma/Makefile rpi/drivers/char/broadcom/vc_cma/Makefile
--- linux/drivers/char/broadcom/vc_cma/Makefile 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/char/broadcom/vc_cma/Makefile 2014-05-29 11:49:12.966891618 +0900
@@ -0,0 +1,14 @@
+ccflags-y += -Wall -Wstrict-prototypes -Wno-trigraphs
+ccflags-y += -Werror
+ccflags-y += -Iinclude/linux/broadcom
+ccflags-y += -Idrivers/misc/vc04_services
+ccflags-y += -Idrivers/misc/vc04_services/interface/vchi
+ccflags-y += -Idrivers/misc/vc04_services/interface/vchiq_arm
+
+ccflags-y += -D__KERNEL__
+ccflags-y += -D__linux__
+ccflags-y += -Werror
+
+obj-$(CONFIG_BCM_VC_CMA) += vc-cma.o
+
+vc-cma-objs := vc_cma.o
diff -Nur linux/drivers/char/broadcom/vc_cma/vc_cma.c rpi/drivers/char/broadcom/vc_cma/vc_cma.c
--- linux/drivers/char/broadcom/vc_cma/vc_cma.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/char/broadcom/vc_cma/vc_cma.c 2014-05-29 11:49:12.967891609 +0900
@@ -0,0 +1,1143 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the above-listed copyright holders may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2, as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <asm/cacheflush.h>
+
+#include "vc_cma.h"
+
+#include "vchiq_util.h"
+#include "vchiq_connected.h"
+//#include "debug_sym.h"
+//#include "vc_mem.h"
+
+#define DRIVER_NAME "vc-cma"
+
+#define LOG_DBG(fmt, ...) \
+ if (vc_cma_debug) \
+ printk(KERN_INFO fmt "\n", ##__VA_ARGS__)
+#define LOG_ERR(fmt, ...) \
+ printk(KERN_ERR fmt "\n", ##__VA_ARGS__)
+
+#define VC_CMA_FOURCC VCHIQ_MAKE_FOURCC('C', 'M', 'A', ' ')
+#define VC_CMA_VERSION 2
+
+#define VC_CMA_CHUNK_ORDER 6 /* 256K */
+#define VC_CMA_CHUNK_SIZE (4096 << VC_CMA_CHUNK_ORDER)
+#define VC_CMA_MAX_PARAMS_PER_MSG \
+ ((VCHIQ_MAX_MSG_SIZE - sizeof(unsigned short))/sizeof(unsigned short))
+#define VC_CMA_RESERVE_COUNT_MAX 16
+
+#define PAGES_PER_CHUNK (VC_CMA_CHUNK_SIZE / PAGE_SIZE)
+
+#define VCADDR_TO_PHYSADDR(vcaddr) (mm_vc_mem_phys_addr + vcaddr)
+
+#define loud_error(...) \
+ LOG_ERR("===== " __VA_ARGS__)
+
+enum {
+ VC_CMA_MSG_QUIT,
+ VC_CMA_MSG_OPEN,
+ VC_CMA_MSG_TICK,
+ VC_CMA_MSG_ALLOC, /* chunk count */
+ VC_CMA_MSG_FREE, /* chunk, chunk, ... */
+ VC_CMA_MSG_ALLOCATED, /* chunk, chunk, ... */
+ VC_CMA_MSG_REQUEST_ALLOC, /* chunk count */
+ VC_CMA_MSG_REQUEST_FREE, /* chunk count */
+ VC_CMA_MSG_RESERVE, /* bytes lo, bytes hi */
+ VC_CMA_MSG_UPDATE_RESERVE,
+ VC_CMA_MSG_MAX
+};
+
+struct cma_msg {
+ unsigned short type;
+ unsigned short params[VC_CMA_MAX_PARAMS_PER_MSG];
+};
+
+struct vc_cma_reserve_user {
+ unsigned int pid;
+ unsigned int reserve;
+};
+
+/* Device (/dev) related variables */
+static dev_t vc_cma_devnum;
+static struct class *vc_cma_class;
+static struct cdev vc_cma_cdev;
+static int vc_cma_inited;
+static int vc_cma_debug;
+
+/* Proc entry */
+static struct proc_dir_entry *vc_cma_proc_entry;
+
+phys_addr_t vc_cma_base;
+struct page *vc_cma_base_page;
+unsigned int vc_cma_size;
+EXPORT_SYMBOL(vc_cma_size);
+unsigned int vc_cma_initial;
+unsigned int vc_cma_chunks;
+unsigned int vc_cma_chunks_used;
+unsigned int vc_cma_chunks_reserved;
+
+static int in_loud_error;
+
+unsigned int vc_cma_reserve_total;
+unsigned int vc_cma_reserve_count;
+struct vc_cma_reserve_user vc_cma_reserve_users[VC_CMA_RESERVE_COUNT_MAX];
+static DEFINE_SEMAPHORE(vc_cma_reserve_mutex);
+static DEFINE_SEMAPHORE(vc_cma_worker_queue_push_mutex);
+
+static u64 vc_cma_dma_mask = DMA_BIT_MASK(32);
+static struct platform_device vc_cma_device = {
+ .name = "vc-cma",
+ .id = 0,
+ .dev = {
+ .dma_mask = &vc_cma_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static VCHIQ_INSTANCE_T cma_instance;
+static VCHIQ_SERVICE_HANDLE_T cma_service;
+static VCHIU_QUEUE_T cma_msg_queue;
+static struct task_struct *cma_worker;
+
+static int vc_cma_set_reserve(unsigned int reserve, unsigned int pid);
+static int vc_cma_alloc_chunks(int num_chunks, struct cma_msg *reply);
+static VCHIQ_STATUS_T cma_service_callback(VCHIQ_REASON_T reason,
+ VCHIQ_HEADER_T * header,
+ VCHIQ_SERVICE_HANDLE_T service,
+ void *bulk_userdata);
+static void send_vc_msg(unsigned short type,
+ unsigned short param1, unsigned short param2);
+static bool send_worker_msg(VCHIQ_HEADER_T * msg);
+
+static int early_vc_cma_mem(char *p)
+{
+ unsigned int new_size;
+ printk(KERN_NOTICE "early_vc_cma_mem(%s)", p);
+ vc_cma_size = memparse(p, &p);
+ vc_cma_initial = vc_cma_size;
+ if (*p == '/')
+ vc_cma_size = memparse(p + 1, &p);
+ if (*p == '@')
+ vc_cma_base = memparse(p + 1, &p);
+
+ new_size = (vc_cma_size - ((-vc_cma_base) & (VC_CMA_CHUNK_SIZE - 1)))
+ & ~(VC_CMA_CHUNK_SIZE - 1);
+ if (new_size > vc_cma_size)
+ vc_cma_size = 0;
+ vc_cma_initial = (vc_cma_initial + VC_CMA_CHUNK_SIZE - 1)
+ & ~(VC_CMA_CHUNK_SIZE - 1);
+ if (vc_cma_initial > vc_cma_size)
+ vc_cma_initial = vc_cma_size;
+ vc_cma_base = (vc_cma_base + VC_CMA_CHUNK_SIZE - 1)
+ & ~(VC_CMA_CHUNK_SIZE - 1);
+
+ printk(KERN_NOTICE " -> initial %x, size %x, base %x", vc_cma_initial,
+ vc_cma_size, (unsigned int)vc_cma_base);
+
+ return 0;
+}
+
+early_param("vc-cma-mem", early_vc_cma_mem);
+
+void vc_cma_early_init(void)
+{
+ LOG_DBG("vc_cma_early_init - vc_cma_chunks = %d", vc_cma_chunks);
+ if (vc_cma_size) {
+ int rc = platform_device_register(&vc_cma_device);
+ LOG_DBG("platform_device_register -> %d", rc);
+ }
+}
+
+void vc_cma_reserve(void)
+{
+ /* if vc_cma_size is set, then declare vc CMA area of the same
+ * size from the end of memory
+ */
+ if (vc_cma_size) {
+ if (dma_declare_contiguous(NULL /*&vc_cma_device.dev*/, vc_cma_size,
+ vc_cma_base, 0) == 0) {
+ } else {
+ LOG_ERR("vc_cma: dma_declare_contiguous(%x,%x) failed",
+ vc_cma_size, (unsigned int)vc_cma_base);
+ vc_cma_size = 0;
+ }
+ }
+ vc_cma_chunks = vc_cma_size / VC_CMA_CHUNK_SIZE;
+}
+
+/****************************************************************************
+*
+* vc_cma_open
+*
+***************************************************************************/
+
+static int vc_cma_open(struct inode *inode, struct file *file)
+{
+ (void)inode;
+ (void)file;
+
+ return 0;
+}
+
+/****************************************************************************
+*
+* vc_cma_release
+*
+***************************************************************************/
+
+static int vc_cma_release(struct inode *inode, struct file *file)
+{
+ (void)inode;
+ (void)file;
+
+ vc_cma_set_reserve(0, current->tgid);
+
+ return 0;
+}
+
+/****************************************************************************
+*
+* vc_cma_ioctl
+*
+***************************************************************************/
+
+static long vc_cma_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int rc = 0;
+
+ (void)cmd;
+ (void)arg;
+
+ switch (cmd) {
+ case VC_CMA_IOC_RESERVE:
+ rc = vc_cma_set_reserve((unsigned int)arg, current->tgid);
+ if (rc >= 0)
+ rc = 0;
+ break;
+ default:
+ LOG_ERR("vc-cma: Unknown ioctl %x", cmd);
+ return -ENOTTY;
+ }
+
+ return rc;
+}
+
+/****************************************************************************
+*
+* File Operations for the driver.
+*
+***************************************************************************/
+
+static const struct file_operations vc_cma_fops = {
+ .owner = THIS_MODULE,
+ .open = vc_cma_open,
+ .release = vc_cma_release,
+ .unlocked_ioctl = vc_cma_ioctl,
+};
+
+/****************************************************************************
+*
+* vc_cma_proc_open
+*
+***************************************************************************/
+
+static int vc_cma_show_info(struct seq_file *m, void *v)
+{
+ int i;
+
+ seq_printf(m, "Videocore CMA:\n");
+ seq_printf(m, " Base : %08x\n", (unsigned int)vc_cma_base);
+ seq_printf(m, " Length : %08x\n", vc_cma_size);
+ seq_printf(m, " Initial : %08x\n", vc_cma_initial);
+ seq_printf(m, " Chunk size : %08x\n", VC_CMA_CHUNK_SIZE);
+ seq_printf(m, " Chunks : %4d (%d bytes)\n",
+ (int)vc_cma_chunks,
+ (int)(vc_cma_chunks * VC_CMA_CHUNK_SIZE));
+ seq_printf(m, " Used : %4d (%d bytes)\n",
+ (int)vc_cma_chunks_used,
+ (int)(vc_cma_chunks_used * VC_CMA_CHUNK_SIZE));
+ seq_printf(m, " Reserved : %4d (%d bytes)\n",
+ (unsigned int)vc_cma_chunks_reserved,
+ (int)(vc_cma_chunks_reserved * VC_CMA_CHUNK_SIZE));
+
+ for (i = 0; i < vc_cma_reserve_count; i++) {
+ struct vc_cma_reserve_user *user = &vc_cma_reserve_users[i];
+ seq_printf(m, " PID %5d: %d bytes\n", user->pid,
+ user->reserve);
+ }
+
+ seq_printf(m, "\n");
+
+ return 0;
+}
+
+static int vc_cma_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, vc_cma_show_info, NULL);
+}
+
+/****************************************************************************
+*
+* vc_cma_proc_write
+*
+***************************************************************************/
+
+static int vc_cma_proc_write(struct file *file,
+ const char __user *buffer,
+ size_t size, loff_t *ppos)
+{
+ int rc = -EFAULT;
+ char input_str[20];
+
+ memset(input_str, 0, sizeof(input_str));
+
+ if (size > sizeof(input_str)) {
+ LOG_ERR("%s: input string length too long", __func__);
+ goto out;
+ }
+
+ if (copy_from_user(input_str, buffer, size - 1)) {
+ LOG_ERR("%s: failed to get input string", __func__);
+ goto out;
+ }
+#define ALLOC_STR "alloc"
+#define FREE_STR "free"
+#define DEBUG_STR "debug"
+#define RESERVE_STR "reserve"
+ if (strncmp(input_str, ALLOC_STR, strlen(ALLOC_STR)) == 0) {
+ int size;
+ char *p = input_str + strlen(ALLOC_STR);
+
+ while (*p == ' ')
+ p++;
+ size = memparse(p, NULL);
+ LOG_ERR("/proc/vc-cma: alloc %d", size);
+ if (size)
+ send_vc_msg(VC_CMA_MSG_REQUEST_FREE,
+ size / VC_CMA_CHUNK_SIZE, 0);
+ else
+ LOG_ERR("invalid size '%s'", p);
+ rc = size;
+ } else if (strncmp(input_str, FREE_STR, strlen(FREE_STR)) == 0) {
+ int size;
+ char *p = input_str + strlen(FREE_STR);
+
+ while (*p == ' ')
+ p++;
+ size = memparse(p, NULL);
+ LOG_ERR("/proc/vc-cma: free %d", size);
+ if (size)
+ send_vc_msg(VC_CMA_MSG_REQUEST_ALLOC,
+ size / VC_CMA_CHUNK_SIZE, 0);
+ else
+ LOG_ERR("invalid size '%s'", p);
+ rc = size;
+ } else if (strncmp(input_str, DEBUG_STR, strlen(DEBUG_STR)) == 0) {
+ char *p = input_str + strlen(DEBUG_STR);
+ while (*p == ' ')
+ p++;
+ if ((strcmp(p, "on") == 0) || (strcmp(p, "1") == 0))
+ vc_cma_debug = 1;
+ else if ((strcmp(p, "off") == 0) || (strcmp(p, "0") == 0))
+ vc_cma_debug = 0;
+ LOG_ERR("/proc/vc-cma: debug %s", vc_cma_debug ? "on" : "off");
+ rc = size;
+ } else if (strncmp(input_str, RESERVE_STR, strlen(RESERVE_STR)) == 0) {
+ int size;
+ int reserved;
+ char *p = input_str + strlen(RESERVE_STR);
+ while (*p == ' ')
+ p++;
+ size = memparse(p, NULL);
+
+ reserved = vc_cma_set_reserve(size, current->tgid);
+ rc = (reserved >= 0) ? size : reserved;
+ }
+
+out:
+ return rc;
+}
+
+/****************************************************************************
+*
+* File Operations for /proc interface.
+*
+***************************************************************************/
+
+static const struct file_operations vc_cma_proc_fops = {
+ .open = vc_cma_proc_open,
+ .read = seq_read,
+ .write = vc_cma_proc_write,
+ .llseek = seq_lseek,
+ .release = single_release
+};
+
+static int vc_cma_set_reserve(unsigned int reserve, unsigned int pid)
+{
+ struct vc_cma_reserve_user *user = NULL;
+ int delta = 0;
+ int i;
+
+ if (down_interruptible(&vc_cma_reserve_mutex))
+ return -ERESTARTSYS;
+
+ for (i = 0; i < vc_cma_reserve_count; i++) {
+ if (pid == vc_cma_reserve_users[i].pid) {
+ user = &vc_cma_reserve_users[i];
+ delta = reserve - user->reserve;
+ if (reserve)
+ user->reserve = reserve;
+ else {
+ /* Remove this entry by copying downwards */
+ while ((i + 1) < vc_cma_reserve_count) {
+ user[0].pid = user[1].pid;
+ user[0].reserve = user[1].reserve;
+ user++;
+ i++;
+ }
+ vc_cma_reserve_count--;
+ user = NULL;
+ }
+ break;
+ }
+ }
+
+ if (reserve && !user) {
+ if (vc_cma_reserve_count == VC_CMA_RESERVE_COUNT_MAX) {
+ LOG_ERR("vc-cma: Too many reservations - "
+ "increase CMA_RESERVE_COUNT_MAX");
+ up(&vc_cma_reserve_mutex);
+ return -EBUSY;
+ }
+ user = &vc_cma_reserve_users[vc_cma_reserve_count];
+ user->pid = pid;
+ user->reserve = reserve;
+ delta = reserve;
+ vc_cma_reserve_count++;
+ }
+
+ vc_cma_reserve_total += delta;
+
+ send_vc_msg(VC_CMA_MSG_RESERVE,
+ vc_cma_reserve_total & 0xffff, vc_cma_reserve_total >> 16);
+
+ send_worker_msg((VCHIQ_HEADER_T *) VC_CMA_MSG_UPDATE_RESERVE);
+
+ LOG_DBG("/proc/vc-cma: reserve %d (PID %d) - total %u",
+ reserve, pid, vc_cma_reserve_total);
+
+ up(&vc_cma_reserve_mutex);
+
+ return vc_cma_reserve_total;
+}
+
+static VCHIQ_STATUS_T cma_service_callback(VCHIQ_REASON_T reason,
+ VCHIQ_HEADER_T * header,
+ VCHIQ_SERVICE_HANDLE_T service,
+ void *bulk_userdata)
+{
+ switch (reason) {
+ case VCHIQ_MESSAGE_AVAILABLE:
+ if (!send_worker_msg(header))
+ return VCHIQ_RETRY;
+ break;
+ case VCHIQ_SERVICE_CLOSED:
+ LOG_DBG("CMA service closed");
+ break;
+ default:
+ LOG_ERR("Unexpected CMA callback reason %d", reason);
+ break;
+ }
+ return VCHIQ_SUCCESS;
+}
+
+static void send_vc_msg(unsigned short type,
+ unsigned short param1, unsigned short param2)
+{
+ unsigned short msg[] = { type, param1, param2 };
+ VCHIQ_ELEMENT_T elem = { &msg, sizeof(msg) };
+ VCHIQ_STATUS_T ret;
+ vchiq_use_service(cma_service);
+ ret = vchiq_queue_message(cma_service, &elem, 1);
+ vchiq_release_service(cma_service);
+ if (ret != VCHIQ_SUCCESS)
+ LOG_ERR("vchiq_queue_message returned %x", ret);
+}
+
+static bool send_worker_msg(VCHIQ_HEADER_T * msg)
+{
+ if (down_interruptible(&vc_cma_worker_queue_push_mutex))
+ return false;
+ vchiu_queue_push(&cma_msg_queue, msg);
+ up(&vc_cma_worker_queue_push_mutex);
+ return true;
+}
+
+static int vc_cma_alloc_chunks(int num_chunks, struct cma_msg *reply)
+{
+ int i;
+ for (i = 0; i < num_chunks; i++) {
+ struct page *chunk;
+ unsigned int chunk_num;
+ uint8_t *chunk_addr;
+ size_t chunk_size = PAGES_PER_CHUNK << PAGE_SHIFT;
+
+ chunk = dma_alloc_from_contiguous(NULL /*&vc_cma_device.dev*/,
+ PAGES_PER_CHUNK,
+ VC_CMA_CHUNK_ORDER);
+ if (!chunk)
+ break;
+
+ chunk_addr = page_address(chunk);
+ dmac_flush_range(chunk_addr, chunk_addr + chunk_size);
+ outer_inv_range(__pa(chunk_addr), __pa(chunk_addr) +
+ chunk_size);
+
+ chunk_num =
+ (page_to_phys(chunk) - vc_cma_base) / VC_CMA_CHUNK_SIZE;
+ BUG_ON(((page_to_phys(chunk) - vc_cma_base) %
+ VC_CMA_CHUNK_SIZE) != 0);
+ if (chunk_num >= vc_cma_chunks) {
+ LOG_ERR("%s: ===============================",
+ __func__);
+ LOG_ERR("%s: chunk phys %x, vc_cma %x-%x - "
+ "bad SPARSEMEM configuration?",
+ __func__, (unsigned int)page_to_phys(chunk),
+ vc_cma_base, vc_cma_base + vc_cma_size - 1);
+ LOG_ERR("%s: dev->cma_area = %p\n", __func__,
+ (void*)0/*vc_cma_device.dev.cma_area*/);
+ LOG_ERR("%s: ===============================",
+ __func__);
+ break;
+ }
+ reply->params[i] = chunk_num;
+ vc_cma_chunks_used++;
+ }
+
+ if (i < num_chunks) {
+ LOG_ERR("%s: dma_alloc_from_contiguous failed "
+ "for %x bytes (alloc %d of %d, %d free)",
+ __func__, VC_CMA_CHUNK_SIZE, i,
+ num_chunks, vc_cma_chunks - vc_cma_chunks_used);
+ num_chunks = i;
+ }
+
+ LOG_DBG("CMA allocated %d chunks -> %d used",
+ num_chunks, vc_cma_chunks_used);
+ reply->type = VC_CMA_MSG_ALLOCATED;
+
+ {
+ VCHIQ_ELEMENT_T elem = {
+ reply,
+ offsetof(struct cma_msg, params[0]) +
+ num_chunks * sizeof(reply->params[0])
+ };
+ VCHIQ_STATUS_T ret;
+ vchiq_use_service(cma_service);
+ ret = vchiq_queue_message(cma_service, &elem, 1);
+ vchiq_release_service(cma_service);
+ if (ret != VCHIQ_SUCCESS)
+ LOG_ERR("vchiq_queue_message return " "%x", ret);
+ }
+
+ return num_chunks;
+}
+
+static int cma_worker_proc(void *param)
+{
+ static struct cma_msg reply;
+ (void)param;
+
+ while (1) {
+ VCHIQ_HEADER_T *msg;
+ static struct cma_msg msg_copy;
+ struct cma_msg *cma_msg = &msg_copy;
+ int type, msg_size;
+
+ msg = vchiu_queue_pop(&cma_msg_queue);
+ if ((unsigned int)msg >= VC_CMA_MSG_MAX) {
+ msg_size = msg->size;
+ memcpy(&msg_copy, msg->data, msg_size);
+ type = cma_msg->type;
+ vchiq_release_message(cma_service, msg);
+ } else {
+ msg_size = 0;
+ type = (int)msg;
+ if (type == VC_CMA_MSG_QUIT)
+ break;
+ else if (type == VC_CMA_MSG_UPDATE_RESERVE) {
+ msg = NULL;
+ cma_msg = NULL;
+ } else {
+ BUG();
+ continue;
+ }
+ }
+
+ switch (type) {
+ case VC_CMA_MSG_ALLOC:{
+ int num_chunks, free_chunks;
+ num_chunks = cma_msg->params[0];
+ free_chunks =
+ vc_cma_chunks - vc_cma_chunks_used;
+ LOG_DBG("CMA_MSG_ALLOC(%d chunks)", num_chunks);
+ if (num_chunks > VC_CMA_MAX_PARAMS_PER_MSG) {
+ LOG_ERR
+ ("CMA_MSG_ALLOC - chunk count (%d) "
+ "exceeds VC_CMA_MAX_PARAMS_PER_MSG (%d)",
+ num_chunks,
+ VC_CMA_MAX_PARAMS_PER_MSG);
+ num_chunks = VC_CMA_MAX_PARAMS_PER_MSG;
+ }
+
+ if (num_chunks > free_chunks) {
+ LOG_ERR
+ ("CMA_MSG_ALLOC - chunk count (%d) "
+ "exceeds free chunks (%d)",
+ num_chunks, free_chunks);
+ num_chunks = free_chunks;
+ }
+
+ vc_cma_alloc_chunks(num_chunks, &reply);
+ }
+ break;
+
+ case VC_CMA_MSG_FREE:{
+ int chunk_count =
+ (msg_size -
+ offsetof(struct cma_msg,
+ params)) /
+ sizeof(cma_msg->params[0]);
+ int i;
+ BUG_ON(chunk_count <= 0);
+
+ LOG_DBG("CMA_MSG_FREE(%d chunks - %x, ...)",
+ chunk_count, cma_msg->params[0]);
+ for (i = 0; i < chunk_count; i++) {
+ int chunk_num = cma_msg->params[i];
+ struct page *page = vc_cma_base_page +
+ chunk_num * PAGES_PER_CHUNK;
+ if (chunk_num >= vc_cma_chunks) {
+ LOG_ERR
+ ("CMA_MSG_FREE - chunk %d of %d"
+ " (value %x) exceeds maximum "
+ "(%x)", i, chunk_count,
+ chunk_num,
+ vc_cma_chunks - 1);
+ break;
+ }
+
+ if (!dma_release_from_contiguous
+ (NULL /*&vc_cma_device.dev*/, page,
+ PAGES_PER_CHUNK)) {
+ LOG_ERR
+ ("CMA_MSG_FREE - failed to "
+ "release chunk %d (phys %x, "
+ "page %x)", chunk_num,
+ page_to_phys(page),
+ (unsigned int)page);
+ }
+ vc_cma_chunks_used--;
+ }
+ LOG_DBG("CMA released %d chunks -> %d used",
+ i, vc_cma_chunks_used);
+ }
+ break;
+
+ case VC_CMA_MSG_UPDATE_RESERVE:{
+ int chunks_needed =
+ ((vc_cma_reserve_total + VC_CMA_CHUNK_SIZE -
+ 1)
+ / VC_CMA_CHUNK_SIZE) -
+ vc_cma_chunks_reserved;
+
+ LOG_DBG
+ ("CMA_MSG_UPDATE_RESERVE(%d chunks needed)",
+ chunks_needed);
+
+ /* Cap the reservations to what is available */
+ if (chunks_needed > 0) {
+ if (chunks_needed >
+ (vc_cma_chunks -
+ vc_cma_chunks_used))
+ chunks_needed =
+ (vc_cma_chunks -
+ vc_cma_chunks_used);
+
+ chunks_needed =
+ vc_cma_alloc_chunks(chunks_needed,
+ &reply);
+ }
+
+ LOG_DBG
+ ("CMA_MSG_UPDATE_RESERVE(%d chunks allocated)",
+ chunks_needed);
+ vc_cma_chunks_reserved += chunks_needed;
+ }
+ break;
+
+ default:
+ LOG_ERR("unexpected msg type %d", type);
+ break;
+ }
+ }
+
+ LOG_DBG("quitting...");
+ return 0;
+}
+
+/****************************************************************************
+*
+* vc_cma_connected_init
+*
+* This function is called once the videocore has been connected.
+*
+***************************************************************************/
+
+static void vc_cma_connected_init(void)
+{
+ VCHIQ_SERVICE_PARAMS_T service_params;
+
+ LOG_DBG("vc_cma_connected_init");
+
+ if (!vchiu_queue_init(&cma_msg_queue, 16)) {
+ LOG_ERR("could not create CMA msg queue");
+ goto fail_queue;
+ }
+
+ if (vchiq_initialise(&cma_instance) != VCHIQ_SUCCESS)
+ goto fail_vchiq_init;
+
+ vchiq_connect(cma_instance);
+
+ service_params.fourcc = VC_CMA_FOURCC;
+ service_params.callback = cma_service_callback;
+ service_params.userdata = NULL;
+ service_params.version = VC_CMA_VERSION;
+ service_params.version_min = VC_CMA_VERSION;
+
+ if (vchiq_open_service(cma_instance, &service_params,
+ &cma_service) != VCHIQ_SUCCESS) {
+ LOG_ERR("failed to open service - already in use?");
+ goto fail_vchiq_open;
+ }
+
+ vchiq_release_service(cma_service);
+
+ cma_worker = kthread_create(cma_worker_proc, NULL, "cma_worker");
+ if (!cma_worker) {
+ LOG_ERR("could not create CMA worker thread");
+ goto fail_worker;
+ }
+ set_user_nice(cma_worker, -20);
+ wake_up_process(cma_worker);
+
+ return;
+
+fail_worker:
+ vchiq_close_service(cma_service);
+fail_vchiq_open:
+ vchiq_shutdown(cma_instance);
+fail_vchiq_init:
+ vchiu_queue_delete(&cma_msg_queue);
+fail_queue:
+ return;
+}
+
+void
+loud_error_header(void)
+{
+ if (in_loud_error)
+ return;
+
+ LOG_ERR("============================================================"
+ "================");
+ LOG_ERR("============================================================"
+ "================");
+ LOG_ERR("=====");
+
+ in_loud_error = 1;
+}
+
+void
+loud_error_footer(void)
+{
+ if (!in_loud_error)
+ return;
+
+ LOG_ERR("=====");
+ LOG_ERR("============================================================"
+ "================");
+ LOG_ERR("============================================================"
+ "================");
+
+ in_loud_error = 0;
+}
+
+#if 1
+static int check_cma_config(void) { return 1; }
+#else
+static int
+read_vc_debug_var(VC_MEM_ACCESS_HANDLE_T handle,
+ const char *symbol,
+ void *buf, size_t bufsize)
+{
+ VC_MEM_ADDR_T vcMemAddr;
+ size_t vcMemSize;
+ uint8_t *mapAddr;
+ off_t vcMapAddr;
+
+ if (!LookupVideoCoreSymbol(handle, symbol,
+ &vcMemAddr,
+ &vcMemSize)) {
+ loud_error_header();
+ loud_error(
+ "failed to find VC symbol \"%s\".",
+ symbol);
+ loud_error_footer();
+ return 0;
+ }
+
+ if (vcMemSize != bufsize) {
+ loud_error_header();
+ loud_error(
+ "VC symbol \"%s\" is the wrong size.",
+ symbol);
+ loud_error_footer();
+ return 0;
+ }
+
+ vcMapAddr = (off_t)vcMemAddr & VC_MEM_TO_ARM_ADDR_MASK;
+ vcMapAddr += mm_vc_mem_phys_addr;
+ mapAddr = ioremap_nocache(vcMapAddr, vcMemSize);
+ if (mapAddr == 0) {
+ loud_error_header();
+ loud_error(
+ "failed to ioremap \"%s\" @ 0x%x "
+ "(phys: 0x%x, size: %u).",
+ symbol,
+ (unsigned int)vcMapAddr,
+ (unsigned int)vcMemAddr,
+ (unsigned int)vcMemSize);
+ loud_error_footer();
+ return 0;
+ }
+
+ memcpy(buf, mapAddr, bufsize);
+ iounmap(mapAddr);
+
+ return 1;
+}
+
+
+static int
+check_cma_config(void)
+{
+ VC_MEM_ACCESS_HANDLE_T mem_hndl;
+ VC_MEM_ADDR_T mempool_start;
+ VC_MEM_ADDR_T mempool_end;
+ VC_MEM_ADDR_T mempool_offline_start;
+ VC_MEM_ADDR_T mempool_offline_end;
+ VC_MEM_ADDR_T cam_alloc_base;
+ VC_MEM_ADDR_T cam_alloc_size;
+ VC_MEM_ADDR_T cam_alloc_end;
+ int success = 0;
+
+ if (OpenVideoCoreMemory(&mem_hndl) != 0)
+ goto out;
+
+ /* Read the relevant VideoCore variables */
+ if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_START",
+ &mempool_start,
+ sizeof(mempool_start)))
+ goto close;
+
+ if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_END",
+ &mempool_end,
+ sizeof(mempool_end)))
+ goto close;
+
+ if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_OFFLINE_START",
+ &mempool_offline_start,
+ sizeof(mempool_offline_start)))
+ goto close;
+
+ if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_OFFLINE_END",
+ &mempool_offline_end,
+ sizeof(mempool_offline_end)))
+ goto close;
+
+ if (!read_vc_debug_var(mem_hndl, "cam_alloc_base",
+ &cam_alloc_base,
+ sizeof(cam_alloc_base)))
+ goto close;
+
+ if (!read_vc_debug_var(mem_hndl, "cam_alloc_size",
+ &cam_alloc_size,
+ sizeof(cam_alloc_size)))
+ goto close;
+
+ cam_alloc_end = cam_alloc_base + cam_alloc_size;
+
+ success = 1;
+
+ /* Now the sanity checks */
+ if (!mempool_offline_start)
+ mempool_offline_start = mempool_start;
+ if (!mempool_offline_end)
+ mempool_offline_end = mempool_end;
+
+ if (VCADDR_TO_PHYSADDR(mempool_offline_start) != vc_cma_base) {
+ loud_error_header();
+ loud_error(
+ "__MEMPOOL_OFFLINE_START(%x -> %lx) doesn't match "
+ "vc_cma_base(%x)",
+ mempool_offline_start,
+ VCADDR_TO_PHYSADDR(mempool_offline_start),
+ vc_cma_base);
+ success = 0;
+ }
+
+ if (VCADDR_TO_PHYSADDR(mempool_offline_end) !=
+ (vc_cma_base + vc_cma_size)) {
+ loud_error_header();
+ loud_error(
+ "__MEMPOOL_OFFLINE_END(%x -> %lx) doesn't match "
+ "vc_cma_base(%x) + vc_cma_size(%x) = %x",
+ mempool_offline_start,
+ VCADDR_TO_PHYSADDR(mempool_offline_end),
+ vc_cma_base, vc_cma_size, vc_cma_base + vc_cma_size);
+ success = 0;
+ }
+
+ if (mempool_end < mempool_start) {
+ loud_error_header();
+ loud_error(
+ "__MEMPOOL_END(%x) must not be before "
+ "__MEMPOOL_START(%x)",
+ mempool_end,
+ mempool_start);
+ success = 0;
+ }
+
+ if (mempool_offline_end < mempool_offline_start) {
+ loud_error_header();
+ loud_error(
+ "__MEMPOOL_OFFLINE_END(%x) must not be before "
+ "__MEMPOOL_OFFLINE_START(%x)",
+ mempool_offline_end,
+ mempool_offline_start);
+ success = 0;
+ }
+
+ if (mempool_offline_start < mempool_start) {
+ loud_error_header();
+ loud_error(
+ "__MEMPOOL_OFFLINE_START(%x) must not be before "
+ "__MEMPOOL_START(%x)",
+ mempool_offline_start,
+ mempool_start);
+ success = 0;
+ }
+
+ if (mempool_offline_end > mempool_end) {
+ loud_error_header();
+ loud_error(
+ "__MEMPOOL_OFFLINE_END(%x) must not be after "
+ "__MEMPOOL_END(%x)",
+ mempool_offline_end,
+ mempool_end);
+ success = 0;
+ }
+
+ if ((cam_alloc_base < mempool_end) &&
+ (cam_alloc_end > mempool_start)) {
+ loud_error_header();
+ loud_error(
+ "cam_alloc pool(%x-%x) overlaps "
+ "mempool(%x-%x)",
+ cam_alloc_base, cam_alloc_end,
+ mempool_start, mempool_end);
+ success = 0;
+ }
+
+ loud_error_footer();
+
+close:
+ CloseVideoCoreMemory(mem_hndl);
+
+out:
+ return success;
+}
+#endif
+
+static int vc_cma_init(void)
+{
+ int rc = -EFAULT;
+ struct device *dev;
+
+ if (!check_cma_config())
+ goto out_release;
+
+ printk(KERN_INFO "vc-cma: Videocore CMA driver\n");
+ printk(KERN_INFO "vc-cma: vc_cma_base = 0x%08x\n", vc_cma_base);
+ printk(KERN_INFO "vc-cma: vc_cma_size = 0x%08x (%u MiB)\n",
+ vc_cma_size, vc_cma_size / (1024 * 1024));
+ printk(KERN_INFO "vc-cma: vc_cma_initial = 0x%08x (%u MiB)\n",
+ vc_cma_initial, vc_cma_initial / (1024 * 1024));
+
+ vc_cma_base_page = phys_to_page(vc_cma_base);
+
+ if (vc_cma_chunks) {
+ int chunks_needed = vc_cma_initial / VC_CMA_CHUNK_SIZE;
+
+ for (vc_cma_chunks_used = 0;
+ vc_cma_chunks_used < chunks_needed; vc_cma_chunks_used++) {
+ struct page *chunk;
+ chunk = dma_alloc_from_contiguous(NULL /*&vc_cma_device.dev*/,
+ PAGES_PER_CHUNK,
+ VC_CMA_CHUNK_ORDER);
+ if (!chunk)
+ break;
+ BUG_ON(((page_to_phys(chunk) - vc_cma_base) %
+ VC_CMA_CHUNK_SIZE) != 0);
+ }
+ if (vc_cma_chunks_used != chunks_needed) {
+ LOG_ERR("%s: dma_alloc_from_contiguous failed (%d "
+ "bytes, allocation %d of %d)",
+ __func__, VC_CMA_CHUNK_SIZE,
+ vc_cma_chunks_used, chunks_needed);
+ goto out_release;
+ }
+
+ vchiq_add_connected_callback(vc_cma_connected_init);
+ }
+
+ rc = alloc_chrdev_region(&vc_cma_devnum, 0, 1, DRIVER_NAME);
+ if (rc < 0) {
+ LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc);
+ goto out_release;
+ }
+
+ cdev_init(&vc_cma_cdev, &vc_cma_fops);
+ rc = cdev_add(&vc_cma_cdev, vc_cma_devnum, 1);
+ if (rc != 0) {
+ LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc);
+ goto out_unregister;
+ }
+
+ vc_cma_class = class_create(THIS_MODULE, DRIVER_NAME);
+ if (IS_ERR(vc_cma_class)) {
+ rc = PTR_ERR(vc_cma_class);
+ LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc);
+ goto out_cdev_del;
+ }
+
+ dev = device_create(vc_cma_class, NULL, vc_cma_devnum, NULL,
+ DRIVER_NAME);
+ if (IS_ERR(dev)) {
+ rc = PTR_ERR(dev);
+ LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc);
+ goto out_class_destroy;
+ }
+
+ vc_cma_proc_entry = proc_create(DRIVER_NAME, 0444, NULL, &vc_cma_proc_fops);
+ if (vc_cma_proc_entry == NULL) {
+ rc = -EFAULT;
+ LOG_ERR("%s: proc_create failed", __func__);
+ goto out_device_destroy;
+ }
+
+ vc_cma_inited = 1;
+ return 0;
+
+out_device_destroy:
+ device_destroy(vc_cma_class, vc_cma_devnum);
+
+out_class_destroy:
+ class_destroy(vc_cma_class);
+ vc_cma_class = NULL;
+
+out_cdev_del:
+ cdev_del(&vc_cma_cdev);
+
+out_unregister:
+ unregister_chrdev_region(vc_cma_devnum, 1);
+
+out_release:
+ /* It is tempting to try to clean up by calling
+ dma_release_from_contiguous for all allocated chunks, but it isn't
+ a very safe thing to do. If vc_cma_initial is non-zero it is because
+ VideoCore is already using that memory, so giving it back to Linux
+ is likely to be fatal.
+ */
+ return -1;
+}
+
+/****************************************************************************
+*
+* vc_cma_exit
+*
+***************************************************************************/
+
+static void __exit vc_cma_exit(void)
+{
+ LOG_DBG("%s: called", __func__);
+
+ if (vc_cma_inited) {
+ remove_proc_entry(DRIVER_NAME, NULL);
+ device_destroy(vc_cma_class, vc_cma_devnum);
+ class_destroy(vc_cma_class);
+ cdev_del(&vc_cma_cdev);
+ unregister_chrdev_region(vc_cma_devnum, 1);
+ }
+}
+
+module_init(vc_cma_init);
+module_exit(vc_cma_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Broadcom Corporation");
diff -Nur linux/drivers/char/hw_random/bcm2708-rng.c rpi/drivers/char/hw_random/bcm2708-rng.c
--- linux/drivers/char/hw_random/bcm2708-rng.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/char/hw_random/bcm2708-rng.c 2014-05-29 11:49:12.971891576 +0900
@@ -0,0 +1,117 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the above-listed copyright holders may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2, as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/hw_random.h>
+#include <linux/printk.h>
+
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+#define RNG_CTRL (0x0)
+#define RNG_STATUS (0x4)
+#define RNG_DATA (0x8)
+#define RNG_FF_THRESHOLD (0xc)
+
+/* enable rng */
+#define RNG_RBGEN 0x1
+/* double speed, less random mode */
+#define RNG_RBG2X 0x2
+
+/* the initial numbers generated are "less random" so will be discarded */
+#define RNG_WARMUP_COUNT 0x40000
+
+static int bcm2708_rng_data_read(struct hwrng *rng, u32 *buffer)
+{
+ void __iomem *rng_base = (void __iomem *)rng->priv;
+ unsigned words;
+ /* wait for a random number to be in fifo */
+ do {
+ words = __raw_readl(rng_base + RNG_STATUS)>>24;
+ }
+ while (words == 0);
+ /* read the random number */
+ *buffer = __raw_readl(rng_base + RNG_DATA);
+ return 4;
+}
+
+static struct hwrng bcm2708_rng_ops = {
+ .name = "bcm2708",
+ .data_read = bcm2708_rng_data_read,
+};
+
+static int __init bcm2708_rng_init(void)
+{
+ void __iomem *rng_base;
+ int err;
+
+ /* map peripheral */
+ rng_base = ioremap(RNG_BASE, 0x10);
+ pr_info("bcm2708_rng_init=%p\n", rng_base);
+ if (!rng_base) {
+ pr_err("bcm2708_rng_init failed to ioremap\n");
+ return -ENOMEM;
+ }
+ bcm2708_rng_ops.priv = (unsigned long)rng_base;
+ /* register driver */
+ err = hwrng_register(&bcm2708_rng_ops);
+ if (err) {
+ pr_err("bcm2708_rng_init hwrng_register()=%d\n", err);
+ iounmap(rng_base);
+ } else {
+ /* set warm-up count & enable */
+ __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
+ __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
+ }
+ return err;
+}
+
+static void __exit bcm2708_rng_exit(void)
+{
+ void __iomem *rng_base = (void __iomem *)bcm2708_rng_ops.priv;
+ pr_info("bcm2708_rng_exit\n");
+ /* disable rng hardware */
+ __raw_writel(0, rng_base + RNG_CTRL);
+ /* unregister driver */
+ hwrng_unregister(&bcm2708_rng_ops);
+ iounmap(rng_base);
+}
+
+module_init(bcm2708_rng_init);
+module_exit(bcm2708_rng_exit);
+
+MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL and additional rights");
diff -Nur linux/drivers/char/hw_random/Kconfig rpi/drivers/char/hw_random/Kconfig
--- linux/drivers/char/hw_random/Kconfig 2014-05-29 12:18:19.112549506 +0900
+++ rpi/drivers/char/hw_random/Kconfig 2014-05-29 11:49:12.971891576 +0900
@@ -314,3 +314,14 @@
module will be called tpm-rng.
If unsure, say Y.
+
+config HW_RANDOM_BCM2708
+ tristate "BCM2708 generic true random number generator support"
+ depends on HW_RANDOM && ARCH_BCM2708
+ ---help---
+ This driver provides the kernel-side support for the BCM2708 hardware.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bcm2708-rng.
+
+ If unsure, say N.
diff -Nur linux/drivers/char/hw_random/Makefile rpi/drivers/char/hw_random/Makefile
--- linux/drivers/char/hw_random/Makefile 2014-05-29 12:18:19.112549506 +0900
+++ rpi/drivers/char/hw_random/Makefile 2014-05-29 11:49:12.971891576 +0900
@@ -27,3 +27,4 @@
obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
+obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.o
diff -Nur linux/drivers/char/i8k.c rpi/drivers/char/i8k.c
--- linux/drivers/char/i8k.c 2014-05-29 12:18:19.117549475 +0900
+++ rpi/drivers/char/i8k.c 2014-05-29 11:49:12.977891526 +0900
@@ -664,6 +664,13 @@
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
},
},
+ {
+ .ident = "Dell XPS421",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
+ },
+ },
{ }
};
diff -Nur linux/drivers/char/ipmi/ipmi_bt_sm.c rpi/drivers/char/ipmi/ipmi_bt_sm.c
--- linux/drivers/char/ipmi/ipmi_bt_sm.c 2014-05-29 12:18:19.118549469 +0900
+++ rpi/drivers/char/ipmi/ipmi_bt_sm.c 2014-05-29 11:49:12.978891517 +0900
@@ -352,7 +352,7 @@
static inline int read_all_bytes(struct si_sm_data *bt)
{
- unsigned char i;
+ unsigned int i;
/*
* length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode.
diff -Nur linux/drivers/char/ipmi/ipmi_si_intf.c rpi/drivers/char/ipmi/ipmi_si_intf.c
--- linux/drivers/char/ipmi/ipmi_si_intf.c 2014-05-29 12:18:19.122549444 +0900
+++ rpi/drivers/char/ipmi/ipmi_si_intf.c 2014-05-29 11:49:12.982891484 +0900
@@ -249,6 +249,9 @@
/* The timer for this si. */
struct timer_list si_timer;
+ /* This flag is set, if the timer is running (timer_pending() isn't enough) */
+ bool timer_running;
+
/* The time (in jiffies) the last timeout occurred at. */
unsigned long last_timeout_jiffies;
@@ -435,6 +438,13 @@
smi_info->si_state = SI_CLEARING_FLAGS;
}
+static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
+{
+ smi_info->last_timeout_jiffies = jiffies;
+ mod_timer(&smi_info->si_timer, new_val);
+ smi_info->timer_running = true;
+}
+
/*
* When we have a situtaion where we run out of memory and cannot
* allocate messages, we just leave them in the BMC and run the system
@@ -447,8 +457,7 @@
start_disable_irq(smi_info);
smi_info->interrupt_disabled = 1;
if (!atomic_read(&smi_info->stop_operation))
- mod_timer(&smi_info->si_timer,
- jiffies + SI_TIMEOUT_JIFFIES);
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
}
}
@@ -908,15 +917,7 @@
list_add_tail(&msg->link, &smi_info->xmit_msgs);
if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) {
- /*
- * last_timeout_jiffies is updated here to avoid
- * smi_timeout() handler passing very large time_diff
- * value to smi_event_handler() that causes
- * the send command to abort.
- */
- smi_info->last_timeout_jiffies = jiffies;
-
- mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
if (smi_info->thread)
wake_up_process(smi_info->thread);
@@ -1005,6 +1006,17 @@
spin_lock_irqsave(&(smi_info->si_lock), flags);
smi_result = smi_event_handler(smi_info, 0);
+
+ /*
+ * If the driver is doing something, there is a possible
+ * race with the timer. If the timer handler see idle,
+ * and the thread here sees something else, the timer
+ * handler won't restart the timer even though it is
+ * required. So start it here if necessary.
+ */
+ if (smi_result != SI_SM_IDLE && !smi_info->timer_running)
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
+
spin_unlock_irqrestore(&(smi_info->si_lock), flags);
busy_wait = ipmi_thread_busy_wait(smi_result, smi_info,
&busy_until);
@@ -1074,10 +1086,6 @@
* SI_USEC_PER_JIFFY);
smi_result = smi_event_handler(smi_info, time_diff);
- spin_unlock_irqrestore(&(smi_info->si_lock), flags);
-
- smi_info->last_timeout_jiffies = jiffies_now;
-
if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
/* Running with interrupts, only do long timeouts. */
timeout = jiffies + SI_TIMEOUT_JIFFIES;
@@ -1099,7 +1107,10 @@
do_mod_timer:
if (smi_result != SI_SM_IDLE)
- mod_timer(&(smi_info->si_timer), timeout);
+ smi_mod_timer(smi_info, timeout);
+ else
+ smi_info->timer_running = false;
+ spin_unlock_irqrestore(&(smi_info->si_lock), flags);
}
static irqreturn_t si_irq_handler(int irq, void *data)
@@ -1147,8 +1158,7 @@
/* Set up the timer that drives the interface. */
setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
- new_smi->last_timeout_jiffies = jiffies;
- mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
+ smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
/*
* Check if the user forcefully enabled the daemon.
diff -Nur linux/drivers/char/Kconfig rpi/drivers/char/Kconfig
--- linux/drivers/char/Kconfig 2014-05-29 12:18:19.100549581 +0900
+++ rpi/drivers/char/Kconfig 2014-05-29 11:49:12.955891710 +0900
@@ -574,6 +574,8 @@
source "drivers/s390/char/Kconfig"
+source "drivers/char/broadcom/Kconfig"
+
config MSM_SMD_PKT
bool "Enable device interface for some SMD packet ports"
default n
diff -Nur linux/drivers/char/Makefile rpi/drivers/char/Makefile
--- linux/drivers/char/Makefile 2014-05-29 12:18:19.100549581 +0900
+++ rpi/drivers/char/Makefile 2014-05-29 11:49:12.955891710 +0900
@@ -62,3 +62,5 @@
js-rtc-y = rtc.o
obj-$(CONFIG_TILE_SROM) += tile-srom.o
+
+obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/
diff -Nur linux/drivers/char/mem.c rpi/drivers/char/mem.c
--- linux/drivers/char/mem.c 2014-05-29 12:18:19.124549431 +0900
+++ rpi/drivers/char/mem.c 2014-05-29 11:49:12.985891459 +0900
@@ -100,6 +100,9 @@
ssize_t read, sz;
char *ptr;
+ if (p != *ppos)
+ return 0;
+
if (!valid_phys_addr_range(p, count))
return -EFAULT;
read = 0;
@@ -158,6 +161,9 @@
unsigned long copied;
void *ptr;
+ if (p != *ppos)
+ return -EFBIG;
+
if (!valid_phys_addr_range(p, count))
return -EFAULT;
diff -Nur linux/drivers/char/raw.c rpi/drivers/char/raw.c
--- linux/drivers/char/raw.c 2014-05-29 12:18:19.130549393 +0900
+++ rpi/drivers/char/raw.c 2014-05-29 11:49:12.998891350 +0900
@@ -190,7 +190,7 @@
struct raw_device_data *rawdev;
struct block_device *bdev;
- if (number <= 0 || number >= MAX_RAW_MINORS)
+ if (number <= 0 || number >= max_raw_minors)
return -EINVAL;
rawdev = &raw_devices[number];
diff -Nur linux/drivers/char/tpm/tpm_i2c_stm_st33.c rpi/drivers/char/tpm/tpm_i2c_stm_st33.c
--- linux/drivers/char/tpm/tpm_i2c_stm_st33.c 2014-05-29 12:18:19.136549356 +0900
+++ rpi/drivers/char/tpm/tpm_i2c_stm_st33.c 2014-05-29 11:49:13.005891291 +0900
@@ -410,6 +410,8 @@
&chip->vendor.read_queue)
== 0) {
burstcnt = get_burstcount(chip);
+ if (burstcnt < 0)
+ return burstcnt;
len = min_t(int, burstcnt, count - size);
I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len);
size += len;
@@ -451,7 +453,8 @@
static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
size_t len)
{
- u32 status, burstcnt = 0, i, size;
+ u32 status, i, size;
+ int burstcnt = 0;
int ret;
u8 data;
struct i2c_client *client;
@@ -482,6 +485,8 @@
for (i = 0; i < len - 1;) {
burstcnt = get_burstcount(chip);
+ if (burstcnt < 0)
+ return burstcnt;
size = min_t(int, len - i - 1, burstcnt);
ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size);
if (ret < 0)
diff -Nur linux/drivers/char/tpm/tpm_ppi.c rpi/drivers/char/tpm/tpm_ppi.c
--- linux/drivers/char/tpm/tpm_ppi.c 2014-05-29 12:18:19.138549343 +0900
+++ rpi/drivers/char/tpm/tpm_ppi.c 2014-05-29 11:49:13.007891274 +0900
@@ -27,15 +27,18 @@
static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
void **return_value)
{
- acpi_status status;
+ acpi_status status = AE_OK;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
- if (strstr(buffer.pointer, context) != NULL) {
- *return_value = handle;
+
+ if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) {
+ if (strstr(buffer.pointer, context) != NULL) {
+ *return_value = handle;
+ status = AE_CTRL_TERMINATE;
+ }
kfree(buffer.pointer);
- return AE_CTRL_TERMINATE;
}
- return AE_OK;
+
+ return status;
}
static inline void ppi_assign_params(union acpi_object params[4],
@@ -169,7 +172,7 @@
* is updated with function index from SUBREQ to SUBREQ2 since PPI
* version 1.1
*/
- if (strcmp(version, "1.1") == -1)
+ if (strcmp(version, "1.1") < 0)
params[2].integer.value = TPM_PPI_FN_SUBREQ;
else
params[2].integer.value = TPM_PPI_FN_SUBREQ2;
@@ -179,7 +182,7 @@
* string/package type. For PPI version 1.0 and 1.1, use buffer type
* for compatibility, and use package type since 1.2 according to spec.
*/
- if (strcmp(version, "1.2") == -1) {
+ if (strcmp(version, "1.2") < 0) {
params[3].type = ACPI_TYPE_BUFFER;
params[3].buffer.length = sizeof(req);
sscanf(buf, "%d", &req);
@@ -245,7 +248,7 @@
* (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
* compatibility, define params[3].type as buffer, if PPI version < 1.2
*/
- if (strcmp(version, "1.2") == -1) {
+ if (strcmp(version, "1.2") < 0) {
params[3].type = ACPI_TYPE_BUFFER;
params[3].buffer.length = 0;
params[3].buffer.pointer = NULL;
@@ -387,7 +390,7 @@
kfree(output.pointer);
output.length = ACPI_ALLOCATE_BUFFER;
output.pointer = NULL;
- if (strcmp(version, "1.2") == -1)
+ if (strcmp(version, "1.2") < 0)
return -EPERM;
params[2].integer.value = TPM_PPI_FN_GETOPR;
diff -Nur linux/drivers/char/tpm/xen-tpmfront.c rpi/drivers/char/tpm/xen-tpmfront.c
--- linux/drivers/char/tpm/xen-tpmfront.c 2014-05-29 12:18:19.139549337 +0900
+++ rpi/drivers/char/tpm/xen-tpmfront.c 2014-05-29 11:49:13.008891266 +0900
@@ -17,6 +17,7 @@
#include <xen/xenbus.h>
#include <xen/page.h>
#include "tpm.h"
+#include <xen/platform_pci.h>
struct tpm_private {
struct tpm_chip *chip;
@@ -423,6 +424,9 @@
if (!xen_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
return xenbus_register_frontend(&tpmfront_driver);
}
module_init(xen_tpmfront_init);
diff -Nur linux/drivers/clk/clk-divider.c rpi/drivers/clk/clk-divider.c
--- linux/drivers/clk/clk-divider.c 2014-05-29 12:18:19.143549312 +0900
+++ rpi/drivers/clk/clk-divider.c 2014-05-29 11:49:13.012891232 +0900
@@ -87,7 +87,7 @@
return 0;
}
-static unsigned int _get_val(struct clk_divider *divider, u8 div)
+static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
{
if (divider->flags & CLK_DIVIDER_ONE_BASED)
return div;
diff -Nur linux/drivers/clk/clk-s2mps11.c rpi/drivers/clk/clk-s2mps11.c
--- linux/drivers/clk/clk-s2mps11.c 2014-05-29 12:18:19.146549293 +0900
+++ rpi/drivers/clk/clk-s2mps11.c 2014-05-29 11:49:13.015891207 +0900
@@ -130,7 +130,7 @@
int i;
if (!iodev->dev->of_node)
- return NULL;
+ return ERR_PTR(-EINVAL);
clk_np = of_find_node_by_name(iodev->dev->of_node, "clocks");
if (!clk_np) {
diff -Nur linux/drivers/clk/samsung/clk-exynos4.c rpi/drivers/clk/samsung/clk-exynos4.c
--- linux/drivers/clk/samsung/clk-exynos4.c 2014-05-29 12:18:19.155549237 +0900
+++ rpi/drivers/clk/samsung/clk-exynos4.c 2014-05-29 11:49:13.026891115 +0900
@@ -39,7 +39,7 @@
#define SRC_TOP1 0xc214
#define SRC_CAM 0xc220
#define SRC_TV 0xc224
-#define SRC_MFC 0xcc28
+#define SRC_MFC 0xc228
#define SRC_G3D 0xc22c
#define E4210_SRC_IMAGE 0xc230
#define SRC_LCD0 0xc234
diff -Nur linux/drivers/clk/samsung/clk-exynos5250.c rpi/drivers/clk/samsung/clk-exynos5250.c
--- linux/drivers/clk/samsung/clk-exynos5250.c 2014-05-29 12:18:19.156549231 +0900
+++ rpi/drivers/clk/samsung/clk-exynos5250.c 2014-05-29 11:49:13.027891107 +0900
@@ -25,6 +25,7 @@
#define MPLL_LOCK 0x4000
#define MPLL_CON0 0x4100
#define SRC_CORE1 0x4204
+#define GATE_IP_ACP 0x8800
#define CPLL_LOCK 0x10020
#define EPLL_LOCK 0x10030
#define VPLL_LOCK 0x10040
@@ -75,7 +76,6 @@
#define SRC_CDREX 0x20200
#define PLL_DIV2_SEL 0x20a24
#define GATE_IP_DISP1 0x10928
-#define GATE_IP_ACP 0x10000
/* list of PLLs to be registered */
enum exynos5250_plls {
@@ -120,7 +120,8 @@
spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
- wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d,
+ wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, g2d, mdma0,
+ smmu_mdma0,
/* mux clocks */
mout_hdmi = 1024,
@@ -354,8 +355,8 @@
GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
- GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
- GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
+ GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 2, 0, 0),
+ GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 1, 0, 0),
GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0),
GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0),
GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
@@ -406,7 +407,8 @@
GATE(hsi2c2, "hsi2c2", "aclk66", GATE_IP_PERIC, 30, 0, 0),
GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0),
GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0),
- GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0),
+ GATE(sysreg, "sysreg", "aclk66",
+ GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0),
GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED, 0),
GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0),
GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0),
@@ -492,6 +494,8 @@
GATE(mixer, "mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
GATE(hdmi, "hdmi", "mout_aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
GATE(g2d, "g2d", "aclk200", GATE_IP_ACP, 3, 0, 0),
+ GATE(mdma0, "mdma0", "aclk266", GATE_IP_ACP, 1, 0, 0),
+ GATE(smmu_mdma0, "smmu_mdma0", "aclk266", GATE_IP_ACP, 5, 0, 0),
};
static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
diff -Nur linux/drivers/clocksource/dw_apb_timer_of.c rpi/drivers/clocksource/dw_apb_timer_of.c
--- linux/drivers/clocksource/dw_apb_timer_of.c 2014-05-29 12:18:19.175549112 +0900
+++ rpi/drivers/clocksource/dw_apb_timer_of.c 2014-05-29 11:49:13.048890931 +0900
@@ -108,12 +108,11 @@
static u32 read_sched_clock(void)
{
- return __raw_readl(sched_io_base);
+ return ~__raw_readl(sched_io_base);
}
static const struct of_device_id sptimer_ids[] __initconst = {
{ .compatible = "picochip,pc3x2-rtc" },
- { .compatible = "snps,dw-apb-timer-sp" },
{ /* Sentinel */ },
};
@@ -153,4 +152,6 @@
num_called++;
}
CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
diff -Nur linux/drivers/clocksource/vf_pit_timer.c rpi/drivers/clocksource/vf_pit_timer.c
--- linux/drivers/clocksource/vf_pit_timer.c 2014-05-29 12:18:19.182549068 +0900
+++ rpi/drivers/clocksource/vf_pit_timer.c 2014-05-29 11:49:13.053890889 +0900
@@ -54,7 +54,7 @@
static unsigned int pit_read_sched_clock(void)
{
- return __raw_readl(clksrc_base + PITCVAL);
+ return ~__raw_readl(clksrc_base + PITCVAL);
}
static int __init pit_clocksource_init(unsigned long rate)
diff -Nur linux/drivers/connector/cn_proc.c rpi/drivers/connector/cn_proc.c
--- linux/drivers/connector/cn_proc.c 2014-05-29 12:18:19.183549062 +0900
+++ rpi/drivers/connector/cn_proc.c 2014-05-29 11:49:13.054890881 +0900
@@ -32,11 +32,23 @@
#include <linux/atomic.h>
#include <linux/pid_namespace.h>
-#include <asm/unaligned.h>
-
#include <linux/cn_proc.h>
-#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event))
+/*
+ * Size of a cn_msg followed by a proc_event structure. Since the
+ * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we
+ * add one 4-byte word to the size here, and then start the actual
+ * cn_msg structure 4 bytes into the stack buffer. The result is that
+ * the immediately following proc_event structure is aligned to 8 bytes.
+ */
+#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4)
+
+/* See comment above; we test our assumption about sizeof struct cn_msg here. */
+static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer)
+{
+ BUILD_BUG_ON(sizeof(struct cn_msg) != 20);
+ return (struct cn_msg *)(buffer + 4);
+}
static atomic_t proc_event_num_listeners = ATOMIC_INIT(0);
static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC };
@@ -56,19 +68,19 @@
{
struct cn_msg *msg;
struct proc_event *ev;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
struct timespec ts;
struct task_struct *parent;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_FORK;
rcu_read_lock();
parent = rcu_dereference(task->real_parent);
@@ -91,17 +103,17 @@
struct cn_msg *msg;
struct proc_event *ev;
struct timespec ts;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_EXEC;
ev->event_data.exec.process_pid = task->pid;
ev->event_data.exec.process_tgid = task->tgid;
@@ -117,14 +129,14 @@
{
struct cn_msg *msg;
struct proc_event *ev;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
struct timespec ts;
const struct cred *cred;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
ev->what = which_id;
@@ -145,7 +157,7 @@
rcu_read_unlock();
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
msg->ack = 0; /* not used */
@@ -159,17 +171,17 @@
struct cn_msg *msg;
struct proc_event *ev;
struct timespec ts;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_SID;
ev->event_data.sid.process_pid = task->pid;
ev->event_data.sid.process_tgid = task->tgid;
@@ -186,17 +198,17 @@
struct cn_msg *msg;
struct proc_event *ev;
struct timespec ts;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_PTRACE;
ev->event_data.ptrace.process_pid = task->pid;
ev->event_data.ptrace.process_tgid = task->tgid;
@@ -221,17 +233,17 @@
struct cn_msg *msg;
struct proc_event *ev;
struct timespec ts;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_COMM;
ev->event_data.comm.process_pid = task->pid;
ev->event_data.comm.process_tgid = task->tgid;
@@ -248,18 +260,18 @@
{
struct cn_msg *msg;
struct proc_event *ev;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_COREDUMP;
ev->event_data.coredump.process_pid = task->pid;
ev->event_data.coredump.process_tgid = task->tgid;
@@ -275,18 +287,18 @@
{
struct cn_msg *msg;
struct proc_event *ev;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->what = PROC_EVENT_EXIT;
ev->event_data.exit.process_pid = task->pid;
ev->event_data.exit.process_tgid = task->tgid;
@@ -312,18 +324,18 @@
{
struct cn_msg *msg;
struct proc_event *ev;
- __u8 buffer[CN_PROC_MSG_SIZE];
+ __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
struct timespec ts;
if (atomic_read(&proc_event_num_listeners) < 1)
return;
- msg = (struct cn_msg *)buffer;
+ msg = buffer_to_cn_msg(buffer);
ev = (struct proc_event *)msg->data;
memset(&ev->event_data, 0, sizeof(ev->event_data));
msg->seq = rcvd_seq;
ktime_get_ts(&ts); /* get high res monotonic timestamp */
- put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
+ ev->timestamp_ns = timespec_to_ns(&ts);
ev->cpu = -1;
ev->what = PROC_EVENT_NONE;
ev->event_data.ack.err = err;
diff -Nur linux/drivers/cpufreq/bcm2835-cpufreq.c rpi/drivers/cpufreq/bcm2835-cpufreq.c
--- linux/drivers/cpufreq/bcm2835-cpufreq.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/cpufreq/bcm2835-cpufreq.c 2014-05-29 11:49:13.058890847 +0900
@@ -0,0 +1,239 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/*****************************************************************************
+* FILENAME: bcm2835-cpufreq.h
+* DESCRIPTION: This driver dynamically manages the CPU Frequency of the ARM
+* processor. Messages are sent to Videocore either setting or requesting the
+* frequency of the ARM in order to match an appropiate frequency to the current
+* usage of the processor. The policy which selects the frequency to use is
+* defined in the kernel .config file, but can be changed during runtime.
+*****************************************************************************/
+
+/* ---------- INCLUDES ---------- */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <mach/vcio.h>
+
+/* ---------- DEFINES ---------- */
+/*#define CPUFREQ_DEBUG_ENABLE*/ /* enable debugging */
+#define MODULE_NAME "bcm2835-cpufreq"
+
+#define VCMSG_ID_ARM_CLOCK 0x000000003 /* Clock/Voltage ID's */
+
+/* debug printk macros */
+#ifdef CPUFREQ_DEBUG_ENABLE
+#define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
+#else
+#define print_debug(fmt,...)
+#endif
+#define print_err(fmt,...) pr_err("%s:%s:%d: "fmt, MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__)
+#define print_info(fmt,...) pr_info("%s: "fmt, MODULE_NAME, ##__VA_ARGS__)
+
+/* tag part of the message */
+struct vc_msg_tag {
+ uint32_t tag_id; /* the message id */
+ uint32_t buffer_size; /* size of the buffer (which in this case is always 8 bytes) */
+ uint32_t data_size; /* amount of data being sent or received */
+ uint32_t dev_id; /* the ID of the clock/voltage to get or set */
+ uint32_t val; /* the value (e.g. rate (in Hz)) to set */
+};
+
+/* message structure to be sent to videocore */
+struct vc_msg {
+ uint32_t msg_size; /* simply, sizeof(struct vc_msg) */
+ uint32_t request_code; /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */
+ struct vc_msg_tag tag; /* the tag structure above to make */
+ uint32_t end_tag; /* an end identifier, should be set to NULL */
+};
+
+/* ---------- GLOBALS ---------- */
+static struct cpufreq_driver bcm2835_cpufreq_driver; /* the cpufreq driver global */
+
+/*
+ ===============================================
+ clk_rate either gets or sets the clock rates.
+ ===============================================
+*/
+static uint32_t bcm2835_cpufreq_set_clock(int cur_rate, int arm_rate)
+{
+ int s, actual_rate=0;
+ struct vc_msg msg;
+
+ /* wipe all previous message data */
+ memset(&msg, 0, sizeof msg);
+
+ msg.msg_size = sizeof msg;
+
+ msg.tag.tag_id = VCMSG_SET_CLOCK_RATE;
+ msg.tag.buffer_size = 8;
+ msg.tag.data_size = 8; /* we're sending the clock ID and the new rates which is a total of 2 words */
+ msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;
+ msg.tag.val = arm_rate * 1000;
+
+ /* send the message */
+ s = bcm_mailbox_property(&msg, sizeof msg);
+
+ /* check if it was all ok and return the rate in KHz */
+ if (s == 0 && (msg.request_code & 0x80000000))
+ actual_rate = msg.tag.val/1000;
+
+ print_debug("Setting new frequency = %d -> %d (actual %d)\n", cur_rate, arm_rate, actual_rate);
+ return actual_rate;
+}
+
+static uint32_t bcm2835_cpufreq_get_clock(int tag)
+{
+ int s;
+ int arm_rate = 0;
+ struct vc_msg msg;
+
+ /* wipe all previous message data */
+ memset(&msg, 0, sizeof msg);
+
+ msg.msg_size = sizeof msg;
+ msg.tag.tag_id = tag;
+ msg.tag.buffer_size = 8;
+ msg.tag.data_size = 4; /* we're just sending the clock ID which is one word long */
+ msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;
+
+ /* send the message */
+ s = bcm_mailbox_property(&msg, sizeof msg);
+
+ /* check if it was all ok and return the rate in KHz */
+ if (s == 0 && (msg.request_code & 0x80000000))
+ arm_rate = msg.tag.val/1000;
+
+ print_debug("%s frequency = %d\n",
+ tag == VCMSG_GET_CLOCK_RATE ? "Current":
+ tag == VCMSG_GET_MIN_CLOCK ? "Min":
+ tag == VCMSG_GET_MAX_CLOCK ? "Max":
+ "Unexpected", arm_rate);
+
+ return arm_rate;
+}
+
+/*
+ ====================================================
+ Module Initialisation registers the cpufreq driver
+ ====================================================
+*/
+static int __init bcm2835_cpufreq_module_init(void)
+{
+ print_debug("IN\n");
+ return cpufreq_register_driver(&bcm2835_cpufreq_driver);
+}
+
+/*
+ =============
+ Module exit
+ =============
+*/
+static void __exit bcm2835_cpufreq_module_exit(void)
+{
+ print_debug("IN\n");
+ cpufreq_unregister_driver(&bcm2835_cpufreq_driver);
+ return;
+}
+
+/*
+ ==============================================================
+ Initialisation function sets up the CPU policy for first use
+ ==============================================================
+*/
+static int bcm2835_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+ /* measured value of how long it takes to change frequency */
+ policy->cpuinfo.transition_latency = 355000; /* ns */
+
+ /* now find out what the maximum and minimum frequencies are */
+ policy->min = policy->cpuinfo.min_freq = bcm2835_cpufreq_get_clock(VCMSG_GET_MIN_CLOCK);
+ policy->max = policy->cpuinfo.max_freq = bcm2835_cpufreq_get_clock(VCMSG_GET_MAX_CLOCK);
+ policy->cur = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);
+
+ print_info("min=%d max=%d cur=%d\n", policy->min, policy->max, policy->cur);
+ return 0;
+}
+
+/*
+ =================================================================================
+ Target function chooses the most appropriate frequency from the table to enable
+ =================================================================================
+*/
+
+static int bcm2835_cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation)
+{
+ unsigned int target = target_freq;
+#ifdef CPUFREQ_DEBUG_ENABLE
+ unsigned int cur = policy->cur;
+#endif
+ print_debug("%s: min=%d max=%d cur=%d target=%d\n",policy->governor->name,policy->min,policy->max,policy->cur,target_freq);
+
+ /* if we are above min and using ondemand, then just use max */
+ if (strcmp("ondemand", policy->governor->name)==0 && target > policy->min)
+ target = policy->max;
+ /* if the frequency is the same, just quit */
+ if (target == policy->cur)
+ return 0;
+
+ /* otherwise were good to set the clock frequency */
+ policy->cur = bcm2835_cpufreq_set_clock(policy->cur, target);
+
+ if (!policy->cur)
+ {
+ print_err("Error occurred setting a new frequency (%d)!\n", target);
+ policy->cur = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);
+ return -EINVAL;
+ }
+ print_debug("Freq %d->%d (min=%d max=%d target=%d request=%d)\n", cur, policy->cur, policy->min, policy->max, target_freq, target);
+ return 0;
+}
+
+static unsigned int bcm2835_cpufreq_driver_get(unsigned int cpu)
+{
+ unsigned int actual_rate = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);
+ print_debug("cpu=%d\n", actual_rate);
+ return actual_rate;
+}
+
+/*
+ =================================================================================
+ Verify ensures that when a policy is changed, it is suitable for the CPU to use
+ =================================================================================
+*/
+
+static int bcm2835_cpufreq_driver_verify(struct cpufreq_policy *policy)
+{
+ print_info("switching to governor %s\n", policy->governor->name);
+ return 0;
+}
+
+
+/* the CPUFreq driver */
+static struct cpufreq_driver bcm2835_cpufreq_driver = {
+ .name = "BCM2835 CPUFreq",
+ .init = bcm2835_cpufreq_driver_init,
+ .verify = bcm2835_cpufreq_driver_verify,
+ .target = bcm2835_cpufreq_driver_target,
+ .get = bcm2835_cpufreq_driver_get
+};
+
+MODULE_AUTHOR("Dorian Peake and Dom Cobley");
+MODULE_DESCRIPTION("CPU frequency driver for BCM2835 chip");
+MODULE_LICENSE("GPL");
+
+module_init(bcm2835_cpufreq_module_init);
+module_exit(bcm2835_cpufreq_module_exit);
diff -Nur linux/drivers/cpufreq/highbank-cpufreq.c rpi/drivers/cpufreq/highbank-cpufreq.c
--- linux/drivers/cpufreq/highbank-cpufreq.c 2014-05-29 12:18:19.199548962 +0900
+++ rpi/drivers/cpufreq/highbank-cpufreq.c 2014-05-29 11:49:13.067890772 +0900
@@ -66,7 +66,8 @@
struct device_node *np;
int ret;
- if (!of_machine_is_compatible("calxeda,highbank"))
+ if ((!of_machine_is_compatible("calxeda,highbank")) &&
+ (!of_machine_is_compatible("calxeda,ecx-2000")))
return -ENODEV;
cpu_dev = get_cpu_device(0);
diff -Nur linux/drivers/cpufreq/intel_pstate.c rpi/drivers/cpufreq/intel_pstate.c
--- linux/drivers/cpufreq/intel_pstate.c 2014-05-29 12:18:19.201548949 +0900
+++ rpi/drivers/cpufreq/intel_pstate.c 2014-05-29 11:49:13.068890763 +0900
@@ -518,7 +518,8 @@
}
#define ICPU(model, policy) \
- { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&policy }
+ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\
+ (unsigned long)&policy }
static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
ICPU(0x2a, default_policy),
@@ -550,6 +551,11 @@
cpu = all_cpu_data[cpunum];
intel_pstate_get_cpu_pstates(cpu);
+ if (!cpu->pstate.current_pstate) {
+ all_cpu_data[cpunum] = NULL;
+ kfree(cpu);
+ return -ENODATA;
+ }
cpu->cpu = cpunum;
cpu->pstate_policy =
diff -Nur linux/drivers/cpufreq/Kconfig.arm rpi/drivers/cpufreq/Kconfig.arm
--- linux/drivers/cpufreq/Kconfig.arm 2014-05-29 12:18:19.184549056 +0900
+++ rpi/drivers/cpufreq/Kconfig.arm 2014-05-29 11:49:13.056890864 +0900
@@ -228,6 +228,14 @@
help
This adds the CPUFreq driver support for SPEAr SOCs.
+config ARM_BCM2835_CPUFREQ
+ bool "BCM2835 Driver"
+ default y
+ help
+ This adds the CPUFreq driver for BCM2835
+
+ If in doubt, say N.
+
config ARM_TEGRA_CPUFREQ
bool "TEGRA CPUFreq support"
depends on ARCH_TEGRA
diff -Nur linux/drivers/cpufreq/Makefile rpi/drivers/cpufreq/Makefile
--- linux/drivers/cpufreq/Makefile 2014-05-29 12:18:19.185549049 +0900
+++ rpi/drivers/cpufreq/Makefile 2014-05-29 11:49:13.056890864 +0900
@@ -76,6 +76,7 @@
obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
+obj-$(CONFIG_ARM_BCM2835_CPUFREQ) += bcm2835-cpufreq.o
obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o
##################################################################################
diff -Nur linux/drivers/cpufreq/powernow-k6.c rpi/drivers/cpufreq/powernow-k6.c
--- linux/drivers/cpufreq/powernow-k6.c 2014-05-29 12:18:19.207548912 +0900
+++ rpi/drivers/cpufreq/powernow-k6.c 2014-05-29 11:49:13.073890721 +0900
@@ -26,41 +26,108 @@
static unsigned int busfreq; /* FSB, in 10 kHz */
static unsigned int max_multiplier;
+static unsigned int param_busfreq = 0;
+static unsigned int param_max_multiplier = 0;
+
+module_param_named(max_multiplier, param_max_multiplier, uint, S_IRUGO);
+MODULE_PARM_DESC(max_multiplier, "Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)");
+
+module_param_named(bus_frequency, param_busfreq, uint, S_IRUGO);
+MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz");
/* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
static struct cpufreq_frequency_table clock_ratio[] = {
- {45, /* 000 -> 4.5x */ 0},
+ {60, /* 110 -> 6.0x */ 0},
+ {55, /* 011 -> 5.5x */ 0},
{50, /* 001 -> 5.0x */ 0},
+ {45, /* 000 -> 4.5x */ 0},
{40, /* 010 -> 4.0x */ 0},
- {55, /* 011 -> 5.5x */ 0},
- {20, /* 100 -> 2.0x */ 0},
- {30, /* 101 -> 3.0x */ 0},
- {60, /* 110 -> 6.0x */ 0},
{35, /* 111 -> 3.5x */ 0},
+ {30, /* 101 -> 3.0x */ 0},
+ {20, /* 100 -> 2.0x */ 0},
{0, CPUFREQ_TABLE_END}
};
+static const u8 index_to_register[8] = { 6, 3, 1, 0, 2, 7, 5, 4 };
+static const u8 register_to_index[8] = { 3, 2, 4, 1, 7, 6, 0, 5 };
+
+static const struct {
+ unsigned freq;
+ unsigned mult;
+} usual_frequency_table[] = {
+ { 400000, 40 }, // 100 * 4
+ { 450000, 45 }, // 100 * 4.5
+ { 475000, 50 }, // 95 * 5
+ { 500000, 50 }, // 100 * 5
+ { 506250, 45 }, // 112.5 * 4.5
+ { 533500, 55 }, // 97 * 5.5
+ { 550000, 55 }, // 100 * 5.5
+ { 562500, 50 }, // 112.5 * 5
+ { 570000, 60 }, // 95 * 6
+ { 600000, 60 }, // 100 * 6
+ { 618750, 55 }, // 112.5 * 5.5
+ { 660000, 55 }, // 120 * 5.5
+ { 675000, 60 }, // 112.5 * 6
+ { 720000, 60 }, // 120 * 6
+};
+
+#define FREQ_RANGE 3000
/**
* powernow_k6_get_cpu_multiplier - returns the current FSB multiplier
*
- * Returns the current setting of the frequency multiplier. Core clock
+ * Returns the current setting of the frequency multiplier. Core clock
* speed is frequency of the Front-Side Bus multiplied with this value.
*/
static int powernow_k6_get_cpu_multiplier(void)
{
- u64 invalue = 0;
+ unsigned long invalue = 0;
u32 msrval;
+ local_irq_disable();
+
msrval = POWERNOW_IOPORT + 0x1;
wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
invalue = inl(POWERNOW_IOPORT + 0x8);
msrval = POWERNOW_IOPORT + 0x0;
wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
- return clock_ratio[(invalue >> 5)&7].driver_data;
+ local_irq_enable();
+
+ return clock_ratio[register_to_index[(invalue >> 5)&7]].driver_data;
}
+static void powernow_k6_set_cpu_multiplier(unsigned int best_i)
+{
+ unsigned long outvalue, invalue;
+ unsigned long msrval;
+ unsigned long cr0;
+
+ /* we now need to transform best_i to the BVC format, see AMD#23446 */
+
+ /*
+ * The processor doesn't respond to inquiry cycles while changing the
+ * frequency, so we must disable cache.
+ */
+ local_irq_disable();
+ cr0 = read_cr0();
+ write_cr0(cr0 | X86_CR0_CD);
+ wbinvd();
+
+ outvalue = (1<<12) | (1<<10) | (1<<9) | (index_to_register[best_i]<<5);
+
+ msrval = POWERNOW_IOPORT + 0x1;
+ wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
+ invalue = inl(POWERNOW_IOPORT + 0x8);
+ invalue = invalue & 0x1f;
+ outvalue = outvalue | invalue;
+ outl(outvalue, (POWERNOW_IOPORT + 0x8));
+ msrval = POWERNOW_IOPORT + 0x0;
+ wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
+
+ write_cr0(cr0);
+ local_irq_enable();
+}
/**
* powernow_k6_set_state - set the PowerNow! multiplier
@@ -71,8 +138,6 @@
static void powernow_k6_set_state(struct cpufreq_policy *policy,
unsigned int best_i)
{
- unsigned long outvalue = 0, invalue = 0;
- unsigned long msrval;
struct cpufreq_freqs freqs;
if (clock_ratio[best_i].driver_data > max_multiplier) {
@@ -85,18 +150,7 @@
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
- /* we now need to transform best_i to the BVC format, see AMD#23446 */
-
- outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5);
-
- msrval = POWERNOW_IOPORT + 0x1;
- wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
- invalue = inl(POWERNOW_IOPORT + 0x8);
- invalue = invalue & 0xf;
- outvalue = outvalue | invalue;
- outl(outvalue , (POWERNOW_IOPORT + 0x8));
- msrval = POWERNOW_IOPORT + 0x0;
- wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
+ powernow_k6_set_cpu_multiplier(best_i);
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
@@ -141,18 +195,57 @@
return 0;
}
-
static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
{
unsigned int i, f;
int result;
+ unsigned khz;
if (policy->cpu != 0)
return -ENODEV;
- /* get frequencies */
- max_multiplier = powernow_k6_get_cpu_multiplier();
- busfreq = cpu_khz / max_multiplier;
+ max_multiplier = 0;
+ khz = cpu_khz;
+ for (i = 0; i < ARRAY_SIZE(usual_frequency_table); i++) {
+ if (khz >= usual_frequency_table[i].freq - FREQ_RANGE &&
+ khz <= usual_frequency_table[i].freq + FREQ_RANGE) {
+ khz = usual_frequency_table[i].freq;
+ max_multiplier = usual_frequency_table[i].mult;
+ break;
+ }
+ }
+ if (param_max_multiplier) {
+ for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+ if (clock_ratio[i].driver_data == param_max_multiplier) {
+ max_multiplier = param_max_multiplier;
+ goto have_max_multiplier;
+ }
+ }
+ printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n");
+ return -EINVAL;
+ }
+
+ if (!max_multiplier) {
+ printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz);
+ printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n");
+ return -EOPNOTSUPP;
+ }
+
+have_max_multiplier:
+ param_max_multiplier = max_multiplier;
+
+ if (param_busfreq) {
+ if (param_busfreq >= 50000 && param_busfreq <= 150000) {
+ busfreq = param_busfreq / 10;
+ goto have_busfreq;
+ }
+ printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n");
+ return -EINVAL;
+ }
+
+ busfreq = khz / max_multiplier;
+have_busfreq:
+ param_busfreq = busfreq * 10;
/* table init */
for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
@@ -164,7 +257,7 @@
}
/* cpuinfo and default policy values */
- policy->cpuinfo.transition_latency = 200000;
+ policy->cpuinfo.transition_latency = 500000;
policy->cur = busfreq * max_multiplier;
result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
diff -Nur linux/drivers/cpufreq/powernow-k8.c rpi/drivers/cpufreq/powernow-k8.c
--- linux/drivers/cpufreq/powernow-k8.c 2014-05-29 12:18:19.208548905 +0900
+++ rpi/drivers/cpufreq/powernow-k8.c 2014-05-29 11:49:13.074890713 +0900
@@ -1100,7 +1100,7 @@
{
struct powernow_k8_data *data;
struct init_on_cpu init_on_cpu;
- int rc;
+ int rc, cpu;
smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1);
if (rc)
@@ -1169,7 +1169,9 @@
pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
- per_cpu(powernow_data, pol->cpu) = data;
+ /* Point all the CPUs in this policy to the same data */
+ for_each_cpu(cpu, pol->cpus)
+ per_cpu(powernow_data, cpu) = data;
return 0;
@@ -1184,6 +1186,7 @@
static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
+ int cpu;
if (!data)
return -EINVAL;
@@ -1194,7 +1197,8 @@
kfree(data->powernow_table);
kfree(data);
- per_cpu(powernow_data, pol->cpu) = NULL;
+ for_each_cpu(cpu, pol->cpus)
+ per_cpu(powernow_data, cpu) = NULL;
return 0;
}
diff -Nur linux/drivers/cpuidle/cpuidle.c rpi/drivers/cpuidle/cpuidle.c
--- linux/drivers/cpuidle/cpuidle.c 2014-05-29 12:18:19.219548837 +0900
+++ rpi/drivers/cpuidle/cpuidle.c 2014-05-29 11:49:13.084890629 +0900
@@ -448,7 +448,7 @@
*/
void cpuidle_unregister_device(struct cpuidle_device *dev)
{
- if (dev->registered == 0)
+ if (!dev || dev->registered == 0)
return;
cpuidle_pause_and_lock();
diff -Nur linux/drivers/dma/bcm2708-dmaengine.c rpi/drivers/dma/bcm2708-dmaengine.c
--- linux/drivers/dma/bcm2708-dmaengine.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/dma/bcm2708-dmaengine.c 2014-05-29 11:49:13.155890034 +0900
@@ -0,0 +1,588 @@
+/*
+ * BCM2708 DMA engine support
+ *
+ * This driver only supports cyclic DMA transfers
+ * as needed for the I2S module.
+ *
+ * Author: Florian Meier <florian.meier@koalo.de>
+ * Copyright 2013
+ *
+ * Based on
+ * OMAP DMAengine support by Russell King
+ *
+ * BCM2708 DMA Driver
+ * Copyright (C) 2010 Broadcom
+ *
+ * Raspberry Pi PCM I2S ALSA Driver
+ * Copyright (c) by Phil Poole 2013
+ *
+ * MARVELL MMP Peripheral DMA Driver
+ * Copyright 2012 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/irq.h>
+
+#include "virt-dma.h"
+
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+struct bcm2708_dmadev {
+ struct dma_device ddev;
+ spinlock_t lock;
+ void __iomem *base;
+ struct device_dma_parameters dma_parms;
+};
+
+struct bcm2708_chan {
+ struct virt_dma_chan vc;
+ struct list_head node;
+
+ struct dma_slave_config cfg;
+ bool cyclic;
+
+ int ch;
+ struct bcm2708_desc *desc;
+
+ void __iomem *chan_base;
+ int irq_number;
+};
+
+struct bcm2708_desc {
+ struct virt_dma_desc vd;
+ enum dma_transfer_direction dir;
+
+ unsigned int control_block_size;
+ struct bcm2708_dma_cb *control_block_base;
+ dma_addr_t control_block_base_phys;
+
+ unsigned frames;
+ size_t size;
+};
+
+#define BCM2708_DMA_DATA_TYPE_S8 1
+#define BCM2708_DMA_DATA_TYPE_S16 2
+#define BCM2708_DMA_DATA_TYPE_S32 4
+#define BCM2708_DMA_DATA_TYPE_S128 16
+
+static inline struct bcm2708_dmadev *to_bcm2708_dma_dev(struct dma_device *d)
+{
+ return container_of(d, struct bcm2708_dmadev, ddev);
+}
+
+static inline struct bcm2708_chan *to_bcm2708_dma_chan(struct dma_chan *c)
+{
+ return container_of(c, struct bcm2708_chan, vc.chan);
+}
+
+static inline struct bcm2708_desc *to_bcm2708_dma_desc(
+ struct dma_async_tx_descriptor *t)
+{
+ return container_of(t, struct bcm2708_desc, vd.tx);
+}
+
+static void bcm2708_dma_desc_free(struct virt_dma_desc *vd)
+{
+ struct bcm2708_desc *desc = container_of(vd, struct bcm2708_desc, vd);
+ dma_free_coherent(desc->vd.tx.chan->device->dev,
+ desc->control_block_size,
+ desc->control_block_base,
+ desc->control_block_base_phys);
+ kfree(desc);
+}
+
+static void bcm2708_dma_start_desc(struct bcm2708_chan *c)
+{
+ struct virt_dma_desc *vd = vchan_next_desc(&c->vc);
+ struct bcm2708_desc *d;
+
+ if (!vd) {
+ c->desc = NULL;
+ return;
+ }
+
+ list_del(&vd->node);
+
+ c->desc = d = to_bcm2708_dma_desc(&vd->tx);
+
+ bcm_dma_start(c->chan_base, d->control_block_base_phys);
+}
+
+static irqreturn_t bcm2708_dma_callback(int irq, void *data)
+{
+ struct bcm2708_chan *c = data;
+ struct bcm2708_desc *d;
+ unsigned long flags;
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+
+ /* Acknowledge interrupt */
+ writel(BCM2708_DMA_INT, c->chan_base + BCM2708_DMA_CS);
+
+ d = c->desc;
+
+ if (d) {
+ /* TODO Only works for cyclic DMA */
+ vchan_cyclic_callback(&d->vd);
+ }
+
+ /* Keep the DMA engine running */
+ dsb(); /* ARM synchronization barrier */
+ writel(BCM2708_DMA_ACTIVE, c->chan_base + BCM2708_DMA_CS);
+
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int bcm2708_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
+
+ return request_irq(c->irq_number,
+ bcm2708_dma_callback, 0, "DMA IRQ", c);
+}
+
+static void bcm2708_dma_free_chan_resources(struct dma_chan *chan)
+{
+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
+
+ vchan_free_chan_resources(&c->vc);
+ free_irq(c->irq_number, c);
+
+ dev_dbg(c->vc.chan.device->dev, "Freeing DMA channel %u\n", c->ch);
+}
+
+static size_t bcm2708_dma_desc_size(struct bcm2708_desc *d)
+{
+ return d->size;
+}
+
+static size_t bcm2708_dma_desc_size_pos(struct bcm2708_desc *d, dma_addr_t addr)
+{
+ unsigned i;
+ size_t size;
+
+ for (size = i = 0; i < d->frames; i++) {
+ struct bcm2708_dma_cb *control_block =
+ &d->control_block_base[i];
+ size_t this_size = control_block->length;
+ dma_addr_t dma;
+
+ if (d->dir == DMA_DEV_TO_MEM)
+ dma = control_block->dst;
+ else
+ dma = control_block->src;
+
+ if (size)
+ size += this_size;
+ else if (addr >= dma && addr < dma + this_size)
+ size += dma + this_size - addr;
+ }
+
+ return size;
+}
+
+static enum dma_status bcm2708_dma_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
+ struct virt_dma_desc *vd;
+ enum dma_status ret;
+ unsigned long flags;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_SUCCESS || !txstate)
+ return ret;
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+ vd = vchan_find_desc(&c->vc, cookie);
+ if (vd) {
+ txstate->residue =
+ bcm2708_dma_desc_size(to_bcm2708_dma_desc(&vd->tx));
+ } else if (c->desc && c->desc->vd.tx.cookie == cookie) {
+ struct bcm2708_desc *d = c->desc;
+ dma_addr_t pos;
+
+ if (d->dir == DMA_MEM_TO_DEV)
+ pos = readl(c->chan_base + BCM2708_DMA_SOURCE_AD);
+ else if (d->dir == DMA_DEV_TO_MEM)
+ pos = readl(c->chan_base + BCM2708_DMA_DEST_AD);
+ else
+ pos = 0;
+
+ txstate->residue = bcm2708_dma_desc_size_pos(d, pos);
+ } else {
+ txstate->residue = 0;
+ }
+
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+
+ return ret;
+}
+
+static void bcm2708_dma_issue_pending(struct dma_chan *chan)
+{
+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
+ unsigned long flags;
+
+ c->cyclic = true; /* Nothing else is implemented */
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+ if (vchan_issue_pending(&c->vc) && !c->desc)
+ bcm2708_dma_start_desc(c);
+
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+}
+
+static struct dma_async_tx_descriptor *bcm2708_dma_prep_dma_cyclic(
+ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+ size_t period_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
+ enum dma_slave_buswidth dev_width;
+ struct bcm2708_desc *d;
+ dma_addr_t dev_addr;
+ unsigned es, sync_type;
+ unsigned frame;
+
+ /* Grab configuration */
+ if (direction == DMA_DEV_TO_MEM) {
+ dev_addr = c->cfg.src_addr;
+ dev_width = c->cfg.src_addr_width;
+ sync_type = BCM2708_DMA_S_DREQ;
+ } else if (direction == DMA_MEM_TO_DEV) {
+ dev_addr = c->cfg.dst_addr;
+ dev_width = c->cfg.dst_addr_width;
+ sync_type = BCM2708_DMA_D_DREQ;
+ } else {
+ dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
+ return NULL;
+ }
+
+ /* Bus width translates to the element size (ES) */
+ switch (dev_width) {
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
+ es = BCM2708_DMA_DATA_TYPE_S32;
+ break;
+ default:
+ return NULL;
+ }
+
+ /* Now allocate and setup the descriptor. */
+ d = kzalloc(sizeof(*d), GFP_NOWAIT);
+ if (!d)
+ return NULL;
+
+ d->dir = direction;
+ d->frames = buf_len / period_len;
+
+ /* Allocate memory for control blocks */
+ d->control_block_size = d->frames * sizeof(struct bcm2708_dma_cb);
+ d->control_block_base = dma_zalloc_coherent(chan->device->dev,
+ d->control_block_size, &d->control_block_base_phys,
+ GFP_NOWAIT);
+
+ if (!d->control_block_base) {
+ kfree(d);
+ return NULL;
+ }
+
+ /*
+ * Iterate over all frames, create a control block
+ * for each frame and link them together.
+ */
+ for (frame = 0; frame < d->frames; frame++) {
+ struct bcm2708_dma_cb *control_block =
+ &d->control_block_base[frame];
+
+ /* Setup adresses */
+ if (d->dir == DMA_DEV_TO_MEM) {
+ control_block->info = BCM2708_DMA_D_INC;
+ control_block->src = dev_addr;
+ control_block->dst = buf_addr + frame * period_len;
+ } else {
+ control_block->info = BCM2708_DMA_S_INC;
+ control_block->src = buf_addr + frame * period_len;
+ control_block->dst = dev_addr;
+ }
+
+ /* Enable interrupt */
+ control_block->info |= BCM2708_DMA_INT_EN;
+
+ /* Setup synchronization */
+ if (sync_type != 0)
+ control_block->info |= sync_type;
+
+ /* Setup DREQ channel */
+ if (c->cfg.slave_id != 0)
+ control_block->info |=
+ BCM2708_DMA_PER_MAP(c->cfg.slave_id);
+
+ /* Length of a frame */
+ control_block->length = period_len;
+ d->size += control_block->length;
+
+ /*
+ * Next block is the next frame.
+ * This DMA engine driver currently only supports cyclic DMA.
+ * Therefore, wrap around at number of frames.
+ */
+ control_block->next = d->control_block_base_phys +
+ sizeof(struct bcm2708_dma_cb)
+ * ((frame + 1) % d->frames);
+ }
+
+ return vchan_tx_prep(&c->vc, &d->vd, flags);
+}
+
+static int bcm2708_dma_slave_config(struct bcm2708_chan *c,
+ struct dma_slave_config *cfg)
+{
+ if ((cfg->direction == DMA_DEV_TO_MEM &&
+ cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) ||
+ (cfg->direction == DMA_MEM_TO_DEV &&
+ cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) ||
+ !is_slave_direction(cfg->direction)) {
+ return -EINVAL;
+ }
+
+ c->cfg = *cfg;
+
+ return 0;
+}
+
+static int bcm2708_dma_terminate_all(struct bcm2708_chan *c)
+{
+ struct bcm2708_dmadev *d = to_bcm2708_dma_dev(c->vc.chan.device);
+ unsigned long flags;
+ int timeout = 10000;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&c->vc.lock, flags);
+
+ /* Prevent this channel being scheduled */
+ spin_lock(&d->lock);
+ list_del_init(&c->node);
+ spin_unlock(&d->lock);
+
+ /*
+ * Stop DMA activity: we assume the callback will not be called
+ * after bcm_dma_abort() returns (even if it does, it will see
+ * c->desc is NULL and exit.)
+ */
+ if (c->desc) {
+ c->desc = NULL;
+ bcm_dma_abort(c->chan_base);
+
+ /* Wait for stopping */
+ while (timeout > 0) {
+ timeout--;
+ if (!(readl(c->chan_base + BCM2708_DMA_CS) &
+ BCM2708_DMA_ACTIVE))
+ break;
+
+ cpu_relax();
+ }
+
+ if (timeout <= 0)
+ dev_err(d->ddev.dev, "DMA transfer could not be terminated\n");
+ }
+
+ vchan_get_all_descriptors(&c->vc, &head);
+ spin_unlock_irqrestore(&c->vc.lock, flags);
+ vchan_dma_desc_free_list(&c->vc, &head);
+
+ return 0;
+}
+
+static int bcm2708_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan);
+
+ switch (cmd) {
+ case DMA_SLAVE_CONFIG:
+ return bcm2708_dma_slave_config(c,
+ (struct dma_slave_config *)arg);
+
+ case DMA_TERMINATE_ALL:
+ return bcm2708_dma_terminate_all(c);
+
+ default:
+ return -ENXIO;
+ }
+}
+
+static int bcm2708_dma_chan_init(struct bcm2708_dmadev *d, void __iomem* chan_base,
+ int chan_id, int irq)
+{
+ struct bcm2708_chan *c;
+
+ c = devm_kzalloc(d->ddev.dev, sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return -ENOMEM;
+
+ c->vc.desc_free = bcm2708_dma_desc_free;
+ vchan_init(&c->vc, &d->ddev);
+ INIT_LIST_HEAD(&c->node);
+
+ d->ddev.chancnt++;
+
+ c->chan_base = chan_base;
+ c->ch = chan_id;
+ c->irq_number = irq;
+
+ return 0;
+}
+
+static void bcm2708_dma_free(struct bcm2708_dmadev *od)
+{
+ while (!list_empty(&od->ddev.channels)) {
+ struct bcm2708_chan *c = list_first_entry(&od->ddev.channels,
+ struct bcm2708_chan, vc.chan.device_node);
+
+ list_del(&c->vc.chan.device_node);
+ tasklet_kill(&c->vc.task);
+ }
+}
+
+static int bcm2708_dma_probe(struct platform_device *pdev)
+{
+ struct bcm2708_dmadev *od;
+ int rc, i;
+
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+ rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+ if (rc)
+ return rc;
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+ od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
+ if (!od)
+ return -ENOMEM;
+
+ pdev->dev.dma_parms = &od->dma_parms;
+ dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF);
+
+ dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
+ dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
+ od->ddev.device_alloc_chan_resources = bcm2708_dma_alloc_chan_resources;
+ od->ddev.device_free_chan_resources = bcm2708_dma_free_chan_resources;
+ od->ddev.device_tx_status = bcm2708_dma_tx_status;
+ od->ddev.device_issue_pending = bcm2708_dma_issue_pending;
+ od->ddev.device_prep_dma_cyclic = bcm2708_dma_prep_dma_cyclic;
+ od->ddev.device_control = bcm2708_dma_control;
+ od->ddev.dev = &pdev->dev;
+ INIT_LIST_HEAD(&od->ddev.channels);
+ spin_lock_init(&od->lock);
+
+ platform_set_drvdata(pdev, od);
+
+ for (i = 0; i < 16; i++) {
+ void __iomem* chan_base;
+ int chan_id, irq;
+
+ chan_id = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST,
+ &chan_base,
+ &irq);
+
+ if (chan_id < 0)
+ break;
+
+ rc = bcm2708_dma_chan_init(od, chan_base, chan_id, irq);
+ if (rc) {
+ bcm2708_dma_free(od);
+ return rc;
+ }
+ }
+
+ rc = dma_async_device_register(&od->ddev);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "Failed to register slave DMA engine device: %d\n", rc);
+ bcm2708_dma_free(od);
+ return rc;
+ }
+
+ dev_dbg(&pdev->dev, "Load BCM2708 DMA engine driver\n");
+
+ return rc;
+}
+
+static int bcm2708_dma_remove(struct platform_device *pdev)
+{
+ struct bcm2708_dmadev *od = platform_get_drvdata(pdev);
+
+ dma_async_device_unregister(&od->ddev);
+ bcm2708_dma_free(od);
+
+ return 0;
+}
+
+static struct platform_driver bcm2708_dma_driver = {
+ .probe = bcm2708_dma_probe,
+ .remove = bcm2708_dma_remove,
+ .driver = {
+ .name = "bcm2708-dmaengine",
+ .owner = THIS_MODULE,
+ },
+};
+
+static struct platform_device *pdev;
+
+static const struct platform_device_info bcm2708_dma_dev_info = {
+ .name = "bcm2708-dmaengine",
+ .id = -1,
+};
+
+static int bcm2708_dma_init(void)
+{
+ int rc = platform_driver_register(&bcm2708_dma_driver);
+
+ if (rc == 0) {
+ pdev = platform_device_register_full(&bcm2708_dma_dev_info);
+ if (IS_ERR(pdev)) {
+ platform_driver_unregister(&bcm2708_dma_driver);
+ rc = PTR_ERR(pdev);
+ }
+ }
+
+ return rc;
+}
+subsys_initcall(bcm2708_dma_init);
+
+static void __exit bcm2708_dma_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&bcm2708_dma_driver);
+}
+module_exit(bcm2708_dma_exit);
+
+MODULE_ALIAS("platform:bcm2708-dma");
+MODULE_DESCRIPTION("BCM2708 DMA engine driver");
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_LICENSE("GPL v2");
diff -Nur linux/drivers/dma/edma.c rpi/drivers/dma/edma.c
--- linux/drivers/dma/edma.c 2014-05-29 12:18:19.257548599 +0900
+++ rpi/drivers/dma/edma.c 2014-05-29 11:49:13.166889942 +0900
@@ -170,11 +170,13 @@
if (edesc->processed == edesc->pset_nr)
edma_link(echan->slot[nslots-1], echan->ecc->dummy_slot);
- edma_resume(echan->ch_num);
-
if (edesc->processed <= MAX_NR_SG) {
dev_dbg(dev, "first transfer starting %d\n", echan->ch_num);
edma_start(echan->ch_num);
+ } else {
+ dev_dbg(dev, "chan: %d: completed %d elements, resuming\n",
+ echan->ch_num, edesc->processed);
+ edma_resume(echan->ch_num);
}
/*
diff -Nur linux/drivers/dma/ioat/dma.c rpi/drivers/dma/ioat/dma.c
--- linux/drivers/dma/ioat/dma.c 2014-05-29 12:18:19.263548561 +0900
+++ rpi/drivers/dma/ioat/dma.c 2014-05-29 11:49:13.173889884 +0900
@@ -77,7 +77,8 @@
attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) {
chan = ioat_chan_by_index(instance, bit);
- tasklet_schedule(&chan->cleanup_task);
+ if (test_bit(IOAT_RUN, &chan->state))
+ tasklet_schedule(&chan->cleanup_task);
}
writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
@@ -93,7 +94,8 @@
{
struct ioat_chan_common *chan = data;
- tasklet_schedule(&chan->cleanup_task);
+ if (test_bit(IOAT_RUN, &chan->state))
+ tasklet_schedule(&chan->cleanup_task);
return IRQ_HANDLED;
}
@@ -116,7 +118,6 @@
chan->timer.function = device->timer_fn;
chan->timer.data = data;
tasklet_init(&chan->cleanup_task, device->cleanup_fn, data);
- tasklet_disable(&chan->cleanup_task);
}
/**
@@ -354,13 +355,49 @@
writel(((u64) chan->completion_dma) >> 32,
chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
- tasklet_enable(&chan->cleanup_task);
+ set_bit(IOAT_RUN, &chan->state);
ioat1_dma_start_null_desc(ioat); /* give chain to dma device */
dev_dbg(to_dev(chan), "%s: allocated %d descriptors\n",
__func__, ioat->desccount);
return ioat->desccount;
}
+void ioat_stop(struct ioat_chan_common *chan)
+{
+ struct ioatdma_device *device = chan->device;
+ struct pci_dev *pdev = device->pdev;
+ int chan_id = chan_num(chan);
+ struct msix_entry *msix;
+
+ /* 1/ stop irq from firing tasklets
+ * 2/ stop the tasklet from re-arming irqs
+ */
+ clear_bit(IOAT_RUN, &chan->state);
+
+ /* flush inflight interrupts */
+ switch (device->irq_mode) {
+ case IOAT_MSIX:
+ msix = &device->msix_entries[chan_id];
+ synchronize_irq(msix->vector);
+ break;
+ case IOAT_MSI:
+ case IOAT_INTX:
+ synchronize_irq(pdev->irq);
+ break;
+ default:
+ break;
+ }
+
+ /* flush inflight timers */
+ del_timer_sync(&chan->timer);
+
+ /* flush inflight tasklet runs */
+ tasklet_kill(&chan->cleanup_task);
+
+ /* final cleanup now that everything is quiesced and can't re-arm */
+ device->cleanup_fn((unsigned long) &chan->common);
+}
+
/**
* ioat1_dma_free_chan_resources - release all the descriptors
* @chan: the channel to be cleaned
@@ -379,9 +416,7 @@
if (ioat->desccount == 0)
return;
- tasklet_disable(&chan->cleanup_task);
- del_timer_sync(&chan->timer);
- ioat1_cleanup(ioat);
+ ioat_stop(chan);
/* Delay 100ms after reset to allow internal DMA logic to quiesce
* before removing DMA descriptor resources.
@@ -526,8 +561,11 @@
static void ioat1_cleanup_event(unsigned long data)
{
struct ioat_dma_chan *ioat = to_ioat_chan((void *) data);
+ struct ioat_chan_common *chan = &ioat->base;
ioat1_cleanup(ioat);
+ if (!test_bit(IOAT_RUN, &chan->state))
+ return;
writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
}
diff -Nur linux/drivers/dma/ioat/dma.h rpi/drivers/dma/ioat/dma.h
--- linux/drivers/dma/ioat/dma.h 2014-05-29 12:18:19.263548561 +0900
+++ rpi/drivers/dma/ioat/dma.h 2014-05-29 11:49:13.173889884 +0900
@@ -370,6 +370,7 @@
void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
void ioat_kobject_del(struct ioatdma_device *device);
int ioat_dma_setup_interrupts(struct ioatdma_device *device);
+void ioat_stop(struct ioat_chan_common *chan);
extern const struct sysfs_ops ioat_sysfs_ops;
extern struct ioat_sysfs_entry ioat_version_attr;
extern struct ioat_sysfs_entry ioat_cap_attr;
diff -Nur linux/drivers/dma/ioat/dma_v2.c rpi/drivers/dma/ioat/dma_v2.c
--- linux/drivers/dma/ioat/dma_v2.c 2014-05-29 12:18:19.265548549 +0900
+++ rpi/drivers/dma/ioat/dma_v2.c 2014-05-29 11:49:13.174889875 +0900
@@ -190,8 +190,11 @@
void ioat2_cleanup_event(unsigned long data)
{
struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+ struct ioat_chan_common *chan = &ioat->base;
ioat2_cleanup(ioat);
+ if (!test_bit(IOAT_RUN, &chan->state))
+ return;
writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
}
@@ -553,10 +556,10 @@
ioat->issued = 0;
ioat->tail = 0;
ioat->alloc_order = order;
+ set_bit(IOAT_RUN, &chan->state);
spin_unlock_bh(&ioat->prep_lock);
spin_unlock_bh(&chan->cleanup_lock);
- tasklet_enable(&chan->cleanup_task);
ioat2_start_null_desc(ioat);
/* check that we got off the ground */
@@ -566,7 +569,6 @@
} while (i++ < 20 && !is_ioat_active(status) && !is_ioat_idle(status));
if (is_ioat_active(status) || is_ioat_idle(status)) {
- set_bit(IOAT_RUN, &chan->state);
return 1 << ioat->alloc_order;
} else {
u32 chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET);
@@ -809,11 +811,8 @@
if (!ioat->ring)
return;
- tasklet_disable(&chan->cleanup_task);
- del_timer_sync(&chan->timer);
- device->cleanup_fn((unsigned long) c);
+ ioat_stop(chan);
device->reset_hw(chan);
- clear_bit(IOAT_RUN, &chan->state);
spin_lock_bh(&chan->cleanup_lock);
spin_lock_bh(&ioat->prep_lock);
diff -Nur linux/drivers/dma/ioat/dma_v3.c rpi/drivers/dma/ioat/dma_v3.c
--- linux/drivers/dma/ioat/dma_v3.c 2014-05-29 12:18:19.266548543 +0900
+++ rpi/drivers/dma/ioat/dma_v3.c 2014-05-29 11:49:13.175889867 +0900
@@ -87,13 +87,6 @@
static const u8 pq16_idx_to_field[] = { 1, 4, 1, 2, 3, 4, 5, 6, 7,
0, 1, 2, 3, 4, 5, 6 };
-/*
- * technically sources 1 and 2 do not require SED, but the op will have
- * at least 9 descriptors so that's irrelevant.
- */
-static const u8 pq16_idx_to_sed[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1 };
-
static void ioat3_eh(struct ioat2_dma_chan *ioat);
static dma_addr_t xor_get_src(struct ioat_raw_descriptor *descs[2], int idx)
@@ -135,12 +128,6 @@
pq->coef[idx] = coef;
}
-static int sed_get_pq16_pool_idx(int src_cnt)
-{
-
- return pq16_idx_to_sed[src_cnt];
-}
-
static bool is_jf_ioat(struct pci_dev *pdev)
{
switch (pdev->device) {
@@ -640,8 +627,11 @@
static void ioat3_cleanup_event(unsigned long data)
{
struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+ struct ioat_chan_common *chan = &ioat->base;
ioat3_cleanup(ioat);
+ if (!test_bit(IOAT_RUN, &chan->state))
+ return;
writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
}
@@ -1129,9 +1119,6 @@
u8 op;
int i, s, idx, num_descs;
- /* this function only handles src_cnt 9 - 16 */
- BUG_ON(src_cnt < 9);
-
/* this function is only called with 9-16 sources */
op = result ? IOAT_OP_PQ_VAL_16S : IOAT_OP_PQ_16S;
@@ -1159,8 +1146,7 @@
descs[0] = (struct ioat_raw_descriptor *) pq;
- desc->sed = ioat3_alloc_sed(device,
- sed_get_pq16_pool_idx(src_cnt));
+ desc->sed = ioat3_alloc_sed(device, (src_cnt-2) >> 3);
if (!desc->sed) {
dev_err(to_dev(chan),
"%s: no free sed entries\n", __func__);
@@ -1218,13 +1204,21 @@
return &desc->txd;
}
+static int src_cnt_flags(unsigned int src_cnt, unsigned long flags)
+{
+ if (dmaf_p_disabled_continue(flags))
+ return src_cnt + 1;
+ else if (dmaf_continue(flags))
+ return src_cnt + 3;
+ else
+ return src_cnt;
+}
+
static struct dma_async_tx_descriptor *
ioat3_prep_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
unsigned int src_cnt, const unsigned char *scf, size_t len,
unsigned long flags)
{
- struct dma_device *dma = chan->device;
-
/* specify valid address for disabled result */
if (flags & DMA_PREP_PQ_DISABLE_P)
dst[0] = dst[1];
@@ -1244,7 +1238,7 @@
single_source_coef[0] = scf[0];
single_source_coef[1] = 0;
- return (src_cnt > 8) && (dma->max_pq > 8) ?
+ return src_cnt_flags(src_cnt, flags) > 8 ?
__ioat3_prep_pq16_lock(chan, NULL, dst, single_source,
2, single_source_coef, len,
flags) :
@@ -1252,7 +1246,7 @@
single_source_coef, len, flags);
} else {
- return (src_cnt > 8) && (dma->max_pq > 8) ?
+ return src_cnt_flags(src_cnt, flags) > 8 ?
__ioat3_prep_pq16_lock(chan, NULL, dst, src, src_cnt,
scf, len, flags) :
__ioat3_prep_pq_lock(chan, NULL, dst, src, src_cnt,
@@ -1265,8 +1259,6 @@
unsigned int src_cnt, const unsigned char *scf, size_t len,
enum sum_check_flags *pqres, unsigned long flags)
{
- struct dma_device *dma = chan->device;
-
/* specify valid address for disabled result */
if (flags & DMA_PREP_PQ_DISABLE_P)
pq[0] = pq[1];
@@ -1278,7 +1270,7 @@
*/
*pqres = 0;
- return (src_cnt > 8) && (dma->max_pq > 8) ?
+ return src_cnt_flags(src_cnt, flags) > 8 ?
__ioat3_prep_pq16_lock(chan, pqres, pq, src, src_cnt, scf, len,
flags) :
__ioat3_prep_pq_lock(chan, pqres, pq, src, src_cnt, scf, len,
@@ -1289,7 +1281,6 @@
ioat3_prep_pqxor(struct dma_chan *chan, dma_addr_t dst, dma_addr_t *src,
unsigned int src_cnt, size_t len, unsigned long flags)
{
- struct dma_device *dma = chan->device;
unsigned char scf[src_cnt];
dma_addr_t pq[2];
@@ -1298,7 +1289,7 @@
flags |= DMA_PREP_PQ_DISABLE_Q;
pq[1] = dst; /* specify valid address for disabled result */
- return (src_cnt > 8) && (dma->max_pq > 8) ?
+ return src_cnt_flags(src_cnt, flags) > 8 ?
__ioat3_prep_pq16_lock(chan, NULL, pq, src, src_cnt, scf, len,
flags) :
__ioat3_prep_pq_lock(chan, NULL, pq, src, src_cnt, scf, len,
@@ -1310,7 +1301,6 @@
unsigned int src_cnt, size_t len,
enum sum_check_flags *result, unsigned long flags)
{
- struct dma_device *dma = chan->device;
unsigned char scf[src_cnt];
dma_addr_t pq[2];
@@ -1324,8 +1314,7 @@
flags |= DMA_PREP_PQ_DISABLE_Q;
pq[1] = pq[0]; /* specify valid address for disabled result */
-
- return (src_cnt > 8) && (dma->max_pq > 8) ?
+ return src_cnt_flags(src_cnt, flags) > 8 ?
__ioat3_prep_pq16_lock(chan, result, pq, &src[1], src_cnt - 1,
scf, len, flags) :
__ioat3_prep_pq_lock(chan, result, pq, &src[1], src_cnt - 1,
@@ -1545,6 +1534,8 @@
goto free_resources;
}
+ memset(page_address(dest), 0, PAGE_SIZE);
+
/* test for non-zero parity sum */
op = IOAT_OP_XOR_VAL;
diff -Nur linux/drivers/dma/Kconfig rpi/drivers/dma/Kconfig
--- linux/drivers/dma/Kconfig 2014-05-29 12:18:19.246548668 +0900
+++ rpi/drivers/dma/Kconfig 2014-05-29 11:49:13.123890303 +0900
@@ -288,6 +288,12 @@
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
+config DMA_BCM2708
+ tristate "BCM2708 DMA engine support"
+ depends on MACH_BCM2708
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+
config TI_CPPI41
tristate "AM33xx CPPI41 DMA support"
depends on ARCH_OMAP
@@ -339,6 +345,7 @@
bool "Network: TCP receive copy offload"
depends on DMA_ENGINE && NET
default (INTEL_IOATDMA || FSL_DMA)
+ depends on BROKEN
help
This enables the use of DMA engines in the network stack to
offload receive copy-to-user operations, freeing CPU cycles.
diff -Nur linux/drivers/dma/Makefile rpi/drivers/dma/Makefile
--- linux/drivers/dma/Makefile 2014-05-29 12:18:19.246548668 +0900
+++ rpi/drivers/dma/Makefile 2014-05-29 11:49:13.123890303 +0900
@@ -37,6 +37,7 @@
obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
obj-$(CONFIG_DMA_OMAP) += omap-dma.o
+obj-$(CONFIG_DMA_BCM2708) += bcm2708-dmaengine.o
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
obj-$(CONFIG_TI_CPPI41) += cppi41.o
diff -Nur linux/drivers/dma/ste_dma40.c rpi/drivers/dma/ste_dma40.c
--- linux/drivers/dma/ste_dma40.c 2014-05-29 12:18:19.283548436 +0900
+++ rpi/drivers/dma/ste_dma40.c 2014-05-29 11:49:13.191889733 +0900
@@ -1640,6 +1640,7 @@
struct d40_chan *d40c = (struct d40_chan *) data;
struct d40_desc *d40d;
unsigned long flags;
+ bool callback_active;
dma_async_tx_callback callback;
void *callback_param;
@@ -1667,6 +1668,7 @@
}
/* Callback to client */
+ callback_active = !!(d40d->txd.flags & DMA_PREP_INTERRUPT);
callback = d40d->txd.callback;
callback_param = d40d->txd.callback_param;
@@ -1689,7 +1691,7 @@
spin_unlock_irqrestore(&d40c->lock, flags);
- if (callback && (d40d->txd.flags & DMA_PREP_INTERRUPT))
+ if (callback_active && callback)
callback(callback_param);
return;
diff -Nur linux/drivers/edac/amd64_edac.c rpi/drivers/edac/amd64_edac.c
--- linux/drivers/edac/amd64_edac.c 2014-05-29 12:18:19.287548411 +0900
+++ rpi/drivers/edac/amd64_edac.c 2014-05-29 11:49:13.196889691 +0900
@@ -1238,9 +1238,17 @@
if (num_dcts_intlv == 2) {
select = (sys_addr >> 8) & 0x3;
channel = select ? 0x3 : 0;
- } else if (num_dcts_intlv == 4)
- channel = (sys_addr >> 8) & 0x7;
-
+ } else if (num_dcts_intlv == 4) {
+ u8 intlv_addr = dct_sel_interleave_addr(pvt);
+ switch (intlv_addr) {
+ case 0x4:
+ channel = (sys_addr >> 8) & 0x3;
+ break;
+ case 0x5:
+ channel = (sys_addr >> 9) & 0x3;
+ break;
+ }
+ }
return channel;
}
diff -Nur linux/drivers/edac/e752x_edac.c rpi/drivers/edac/e752x_edac.c
--- linux/drivers/edac/e752x_edac.c 2014-05-29 12:18:19.290548393 +0900
+++ rpi/drivers/edac/e752x_edac.c 2014-05-29 11:49:13.199889666 +0900
@@ -1182,9 +1182,11 @@
pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
pvt->dev_info->err_dev, pvt->bridge_ck);
- if (pvt->bridge_ck == NULL)
+ if (pvt->bridge_ck == NULL) {
pvt->bridge_ck = pci_scan_single_device(pdev->bus,
PCI_DEVFN(0, 1));
+ pci_dev_get(pvt->bridge_ck);
+ }
if (pvt->bridge_ck == NULL) {
e752x_printk(KERN_ERR, "error reporting device not found:"
diff -Nur linux/drivers/edac/edac_mc.c rpi/drivers/edac/edac_mc.c
--- linux/drivers/edac/edac_mc.c 2014-05-29 12:18:19.291548386 +0900
+++ rpi/drivers/edac/edac_mc.c 2014-05-29 11:49:13.202889641 +0900
@@ -559,7 +559,8 @@
*
* called with the mem_ctls_mutex held
*/
-static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
+static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
+ bool init)
{
edac_dbg(0, "\n");
@@ -567,7 +568,9 @@
if (mci->op_state != OP_RUNNING_POLL)
return;
- INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
+ if (init)
+ INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
+
mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
}
@@ -601,7 +604,7 @@
* user space has updated our poll period value, need to
* reset our workq delays
*/
-void edac_mc_reset_delay_period(int value)
+void edac_mc_reset_delay_period(unsigned long value)
{
struct mem_ctl_info *mci;
struct list_head *item;
@@ -611,7 +614,7 @@
list_for_each(item, &mc_devices) {
mci = list_entry(item, struct mem_ctl_info, link);
- edac_mc_workq_setup(mci, (unsigned long) value);
+ edac_mc_workq_setup(mci, value, false);
}
mutex_unlock(&mem_ctls_mutex);
@@ -782,7 +785,7 @@
/* This instance is NOW RUNNING */
mci->op_state = OP_RUNNING_POLL;
- edac_mc_workq_setup(mci, edac_mc_get_poll_msec());
+ edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true);
} else {
mci->op_state = OP_RUNNING_INTERRUPT;
}
diff -Nur linux/drivers/edac/edac_mc_sysfs.c rpi/drivers/edac/edac_mc_sysfs.c
--- linux/drivers/edac/edac_mc_sysfs.c 2014-05-29 12:18:19.292548380 +0900
+++ rpi/drivers/edac/edac_mc_sysfs.c 2014-05-29 11:49:13.203889632 +0900
@@ -52,18 +52,20 @@
static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
{
- long l;
+ unsigned long l;
int ret;
if (!val)
return -EINVAL;
- ret = kstrtol(val, 0, &l);
+ ret = kstrtoul(val, 0, &l);
if (ret)
return ret;
- if ((int)l != l)
+
+ if (l < 1000)
return -EINVAL;
- *((int *)kp->arg) = l;
+
+ *((unsigned long *)kp->arg) = l;
/* notify edac_mc engine to reset the poll period */
edac_mc_reset_delay_period(l);
diff -Nur linux/drivers/edac/edac_module.h rpi/drivers/edac/edac_module.h
--- linux/drivers/edac/edac_module.h 2014-05-29 12:18:19.292548380 +0900
+++ rpi/drivers/edac/edac_module.h 2014-05-29 11:49:13.203889632 +0900
@@ -52,7 +52,7 @@
extern void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev);
extern void edac_device_reset_delay_period(struct edac_device_ctl_info
*edac_dev, unsigned long value);
-extern void edac_mc_reset_delay_period(int value);
+extern void edac_mc_reset_delay_period(unsigned long value);
extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
diff -Nur linux/drivers/edac/highbank_l2_edac.c rpi/drivers/edac/highbank_l2_edac.c
--- linux/drivers/edac/highbank_l2_edac.c 2014-05-29 12:18:19.294548367 +0900
+++ rpi/drivers/edac/highbank_l2_edac.c 2014-05-29 11:49:13.205889616 +0900
@@ -90,28 +90,30 @@
goto err;
}
+ dci->mod_name = dev_name(&pdev->dev);
+ dci->dev_name = dev_name(&pdev->dev);
+
+ if (edac_device_add_device(dci))
+ goto err;
+
drvdata->db_irq = platform_get_irq(pdev, 0);
res = devm_request_irq(&pdev->dev, drvdata->db_irq,
highbank_l2_err_handler,
0, dev_name(&pdev->dev), dci);
if (res < 0)
- goto err;
+ goto err2;
drvdata->sb_irq = platform_get_irq(pdev, 1);
res = devm_request_irq(&pdev->dev, drvdata->sb_irq,
highbank_l2_err_handler,
0, dev_name(&pdev->dev), dci);
if (res < 0)
- goto err;
-
- dci->mod_name = dev_name(&pdev->dev);
- dci->dev_name = dev_name(&pdev->dev);
-
- if (edac_device_add_device(dci))
- goto err;
+ goto err2;
devres_close_group(&pdev->dev, NULL);
return 0;
+err2:
+ edac_device_del_device(&pdev->dev);
err:
devres_release_group(&pdev->dev, NULL);
edac_device_free_ctl_info(dci);
diff -Nur linux/drivers/edac/highbank_mc_edac.c rpi/drivers/edac/highbank_mc_edac.c
--- linux/drivers/edac/highbank_mc_edac.c 2014-05-29 12:18:19.294548367 +0900
+++ rpi/drivers/edac/highbank_mc_edac.c 2014-05-29 11:49:13.205889616 +0900
@@ -189,14 +189,6 @@
goto err;
}
- irq = platform_get_irq(pdev, 0);
- res = devm_request_irq(&pdev->dev, irq, highbank_mc_err_handler,
- 0, dev_name(&pdev->dev), mci);
- if (res < 0) {
- dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
- goto err;
- }
-
mci->mtype_cap = MEM_FLAG_DDR3;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_SECDED;
@@ -217,10 +209,20 @@
if (res < 0)
goto err;
+ irq = platform_get_irq(pdev, 0);
+ res = devm_request_irq(&pdev->dev, irq, highbank_mc_err_handler,
+ 0, dev_name(&pdev->dev), mci);
+ if (res < 0) {
+ dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
+ goto err2;
+ }
+
highbank_mc_create_debugfs_nodes(mci);
devres_close_group(&pdev->dev, NULL);
return 0;
+err2:
+ edac_mc_del_mc(&pdev->dev);
err:
devres_release_group(&pdev->dev, NULL);
edac_mc_free(mci);
diff -Nur linux/drivers/edac/i7300_edac.c rpi/drivers/edac/i7300_edac.c
--- linux/drivers/edac/i7300_edac.c 2014-05-29 12:18:19.298548342 +0900
+++ rpi/drivers/edac/i7300_edac.c 2014-05-29 11:49:13.208889591 +0900
@@ -943,33 +943,35 @@
/* Attempt to 'get' the MCH register we want */
pdev = NULL;
- while (!pvt->pci_dev_16_1_fsb_addr_map ||
- !pvt->pci_dev_16_2_fsb_err_regs) {
- pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev);
- if (!pdev) {
- /* End of list, leave */
- i7300_printk(KERN_ERR,
- "'system address,Process Bus' "
- "device not found:"
- "vendor 0x%x device 0x%x ERR funcs "
- "(broken BIOS?)\n",
- PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
- goto error;
- }
-
+ while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_I7300_MCH_ERR,
+ pdev))) {
/* Store device 16 funcs 1 and 2 */
switch (PCI_FUNC(pdev->devfn)) {
case 1:
- pvt->pci_dev_16_1_fsb_addr_map = pdev;
+ if (!pvt->pci_dev_16_1_fsb_addr_map)
+ pvt->pci_dev_16_1_fsb_addr_map =
+ pci_dev_get(pdev);
break;
case 2:
- pvt->pci_dev_16_2_fsb_err_regs = pdev;
+ if (!pvt->pci_dev_16_2_fsb_err_regs)
+ pvt->pci_dev_16_2_fsb_err_regs =
+ pci_dev_get(pdev);
break;
}
}
+ if (!pvt->pci_dev_16_1_fsb_addr_map ||
+ !pvt->pci_dev_16_2_fsb_err_regs) {
+ /* At least one device was not found */
+ i7300_printk(KERN_ERR,
+ "'system address,Process Bus' device not found:"
+ "vendor 0x%x device 0x%x ERR funcs (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_I7300_MCH_ERR);
+ goto error;
+ }
+
edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n",
pci_name(pvt->pci_dev_16_0_fsb_ctlr),
pvt->pci_dev_16_0_fsb_ctlr->vendor,
diff -Nur linux/drivers/edac/i7core_edac.c rpi/drivers/edac/i7core_edac.c
--- linux/drivers/edac/i7core_edac.c 2014-05-29 12:18:19.299548336 +0900
+++ rpi/drivers/edac/i7core_edac.c 2014-05-29 11:49:13.209889582 +0900
@@ -1334,14 +1334,19 @@
* is at addr 8086:2c40, instead of 8086:2c41. So, we need
* to probe for the alternate address in case of failure
*/
- if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
+ if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) {
+ pci_dev_get(*prev); /* pci_get_device will put it */
pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
+ }
- if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
+ if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE &&
+ !pdev) {
+ pci_dev_get(*prev); /* pci_get_device will put it */
pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
*prev);
+ }
if (!pdev) {
if (*prev) {
diff -Nur linux/drivers/eisa/eisa-bus.c rpi/drivers/eisa/eisa-bus.c
--- linux/drivers/eisa/eisa-bus.c 2014-05-29 12:18:19.306548292 +0900
+++ rpi/drivers/eisa/eisa-bus.c 2014-05-29 11:49:13.218889507 +0900
@@ -275,11 +275,13 @@
}
if (slot) {
+ edev->res[i].name = NULL;
edev->res[i].start = SLOT_ADDRESS(root, slot)
+ (i * 0x400);
edev->res[i].end = edev->res[i].start + 0xff;
edev->res[i].flags = IORESOURCE_IO;
} else {
+ edev->res[i].name = NULL;
edev->res[i].start = SLOT_ADDRESS(root, slot)
+ EISA_VENDOR_ID_OFFSET;
edev->res[i].end = edev->res[i].start + 3;
@@ -326,19 +328,20 @@
return -ENOMEM;
}
- if (eisa_init_device(root, edev, 0)) {
+ if (eisa_request_resources(root, edev, 0)) {
+ dev_warn(root->dev,
+ "EISA: Cannot allocate resource for mainboard\n");
kfree(edev);
if (!root->force_probe)
- return -ENODEV;
+ return -EBUSY;
goto force_probe;
}
- if (eisa_request_resources(root, edev, 0)) {
- dev_warn(root->dev,
- "EISA: Cannot allocate resource for mainboard\n");
+ if (eisa_init_device(root, edev, 0)) {
+ eisa_release_resources(edev);
kfree(edev);
if (!root->force_probe)
- return -EBUSY;
+ return -ENODEV;
goto force_probe;
}
@@ -361,11 +364,6 @@
continue;
}
- if (eisa_init_device(root, edev, i)) {
- kfree(edev);
- continue;
- }
-
if (eisa_request_resources(root, edev, i)) {
dev_warn(root->dev,
"Cannot allocate resource for EISA slot %d\n",
@@ -373,6 +371,12 @@
kfree(edev);
continue;
}
+
+ if (eisa_init_device(root, edev, i)) {
+ eisa_release_resources(edev);
+ kfree(edev);
+ continue;
+ }
if (edev->state == (EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED))
enabled_str = " (forced enabled)";
diff -Nur linux/drivers/firewire/core-device.c rpi/drivers/firewire/core-device.c
--- linux/drivers/firewire/core-device.c 2014-05-29 12:18:19.311548261 +0900
+++ rpi/drivers/firewire/core-device.c 2014-05-29 11:49:13.225889448 +0900
@@ -916,7 +916,7 @@
old->config_rom_retries = 0;
fw_notice(card, "rediscovered device %s\n", dev_name(dev));
- PREPARE_DELAYED_WORK(&old->work, fw_device_update);
+ old->workfn = fw_device_update;
fw_schedule_device_work(old, 0);
if (current_node == card->root_node)
@@ -1075,7 +1075,7 @@
if (atomic_cmpxchg(&device->state,
FW_DEVICE_INITIALIZING,
FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
- PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+ device->workfn = fw_device_shutdown;
fw_schedule_device_work(device, SHUTDOWN_DELAY);
} else {
fw_notice(card, "created device %s: GUID %08x%08x, S%d00\n",
@@ -1196,13 +1196,20 @@
dev_name(&device->device), fw_rcode_string(ret));
gone:
atomic_set(&device->state, FW_DEVICE_GONE);
- PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+ device->workfn = fw_device_shutdown;
fw_schedule_device_work(device, SHUTDOWN_DELAY);
out:
if (node_id == card->root_node->node_id)
fw_schedule_bm_work(card, 0);
}
+static void fw_device_workfn(struct work_struct *work)
+{
+ struct fw_device *device = container_of(to_delayed_work(work),
+ struct fw_device, work);
+ device->workfn(work);
+}
+
void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
{
struct fw_device *device;
@@ -1252,7 +1259,8 @@
* power-up after getting plugged in. We schedule the
* first config rom scan half a second after bus reset.
*/
- INIT_DELAYED_WORK(&device->work, fw_device_init);
+ device->workfn = fw_device_init;
+ INIT_DELAYED_WORK(&device->work, fw_device_workfn);
fw_schedule_device_work(device, INITIAL_DELAY);
break;
@@ -1268,7 +1276,7 @@
if (atomic_cmpxchg(&device->state,
FW_DEVICE_RUNNING,
FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
- PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
+ device->workfn = fw_device_refresh;
fw_schedule_device_work(device,
device->is_local ? 0 : INITIAL_DELAY);
}
@@ -1283,7 +1291,7 @@
smp_wmb(); /* update node_id before generation */
device->generation = card->generation;
if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
- PREPARE_DELAYED_WORK(&device->work, fw_device_update);
+ device->workfn = fw_device_update;
fw_schedule_device_work(device, 0);
}
break;
@@ -1308,7 +1316,7 @@
device = node->data;
if (atomic_xchg(&device->state,
FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
- PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+ device->workfn = fw_device_shutdown;
fw_schedule_device_work(device,
list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
}
diff -Nur linux/drivers/firewire/net.c rpi/drivers/firewire/net.c
--- linux/drivers/firewire/net.c 2014-05-29 12:18:19.314548242 +0900
+++ rpi/drivers/firewire/net.c 2014-05-29 11:49:13.228889423 +0900
@@ -929,8 +929,6 @@
if (rcode == RCODE_COMPLETE) {
fwnet_transmit_packet_done(ptask);
} else {
- fwnet_transmit_packet_failed(ptask);
-
if (printk_timed_ratelimit(&j, 1000) || rcode != last_rcode) {
dev_err(&ptask->dev->netdev->dev,
"fwnet_write_complete failed: %x (skipped %d)\n",
@@ -938,8 +936,10 @@
errors_skipped = 0;
last_rcode = rcode;
- } else
+ } else {
errors_skipped++;
+ }
+ fwnet_transmit_packet_failed(ptask);
}
}
diff -Nur linux/drivers/firewire/ohci.c rpi/drivers/firewire/ohci.c
--- linux/drivers/firewire/ohci.c 2014-05-29 12:18:19.316548230 +0900
+++ rpi/drivers/firewire/ohci.c 2014-05-29 11:49:13.230889406 +0900
@@ -290,7 +290,6 @@
#define QUIRK_NO_MSI 0x10
#define QUIRK_TI_SLLZ059 0x20
#define QUIRK_IR_WAKE 0x40
-#define QUIRK_PHY_LCTRL_TIMEOUT 0x80
/* In case of multiple matches in ohci_quirks[], only the first one is used. */
static const struct {
@@ -303,10 +302,7 @@
QUIRK_BE_HEADERS},
{PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
- QUIRK_PHY_LCTRL_TIMEOUT | QUIRK_NO_MSI},
-
- {PCI_VENDOR_ID_ATT, PCI_ANY_ID, PCI_ANY_ID,
- QUIRK_PHY_LCTRL_TIMEOUT},
+ QUIRK_NO_MSI},
{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
QUIRK_RESET_PACKET},
@@ -353,7 +349,6 @@
", disable MSI = " __stringify(QUIRK_NO_MSI)
", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059)
", IR wake unreliable = " __stringify(QUIRK_IR_WAKE)
- ", phy LCtrl timeout = " __stringify(QUIRK_PHY_LCTRL_TIMEOUT)
")");
#define OHCI_PARAM_DEBUG_AT_AR 1
@@ -2295,9 +2290,6 @@
* TI TSB82AA2 + TSB81BA3(A) cards signal LPS enabled early but
* cannot actually use the phy at that time. These need tens of
* millisecods pause between LPS write and first phy access too.
- *
- * But do not wait for 50msec on Agere/LSI cards. Their phy
- * arbitration state machine may time out during such a long wait.
*/
reg_write(ohci, OHCI1394_HCControlSet,
@@ -2305,11 +2297,8 @@
OHCI1394_HCControl_postedWriteEnable);
flush_writes(ohci);
- if (!(ohci->quirks & QUIRK_PHY_LCTRL_TIMEOUT))
+ for (lps = 0, i = 0; !lps && i < 3; i++) {
msleep(50);
-
- for (lps = 0, i = 0; !lps && i < 150; i++) {
- msleep(1);
lps = reg_read(ohci, OHCI1394_HCControlSet) &
OHCI1394_HCControl_LPS;
}
diff -Nur linux/drivers/firewire/sbp2.c rpi/drivers/firewire/sbp2.c
--- linux/drivers/firewire/sbp2.c 2014-05-29 12:18:19.317548224 +0900
+++ rpi/drivers/firewire/sbp2.c 2014-05-29 11:49:13.232889389 +0900
@@ -146,6 +146,7 @@
*/
int generation;
int retries;
+ work_func_t workfn;
struct delayed_work work;
bool has_sdev;
bool blocked;
@@ -864,7 +865,7 @@
/* set appropriate retry limit(s) in BUSY_TIMEOUT register */
sbp2_set_busy_timeout(lu);
- PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
+ lu->workfn = sbp2_reconnect;
sbp2_agent_reset(lu);
/* This was a re-login. */
@@ -918,7 +919,7 @@
* If a bus reset happened, sbp2_update will have requeued
* lu->work already. Reset the work from reconnect to login.
*/
- PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+ lu->workfn = sbp2_login;
}
static void sbp2_reconnect(struct work_struct *work)
@@ -952,7 +953,7 @@
lu->retries++ >= 5) {
dev_err(tgt_dev(tgt), "failed to reconnect\n");
lu->retries = 0;
- PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+ lu->workfn = sbp2_login;
}
sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
@@ -972,6 +973,13 @@
sbp2_conditionally_unblock(lu);
}
+static void sbp2_lu_workfn(struct work_struct *work)
+{
+ struct sbp2_logical_unit *lu = container_of(to_delayed_work(work),
+ struct sbp2_logical_unit, work);
+ lu->workfn(work);
+}
+
static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
{
struct sbp2_logical_unit *lu;
@@ -998,7 +1006,8 @@
lu->blocked = false;
++tgt->dont_block;
INIT_LIST_HEAD(&lu->orb_list);
- INIT_DELAYED_WORK(&lu->work, sbp2_login);
+ lu->workfn = sbp2_login;
+ INIT_DELAYED_WORK(&lu->work, sbp2_lu_workfn);
list_add_tail(&lu->link, &tgt->lu_list);
return 0;
diff -Nur linux/drivers/firmware/efi/efi-pstore.c rpi/drivers/firmware/efi/efi-pstore.c
--- linux/drivers/firmware/efi/efi-pstore.c 2014-05-29 12:18:19.321548199 +0900
+++ rpi/drivers/firmware/efi/efi-pstore.c 2014-05-29 11:49:13.235889364 +0900
@@ -18,14 +18,12 @@
static int efi_pstore_open(struct pstore_info *psi)
{
- efivar_entry_iter_begin();
psi->data = NULL;
return 0;
}
static int efi_pstore_close(struct pstore_info *psi)
{
- efivar_entry_iter_end();
psi->data = NULL;
return 0;
}
@@ -39,6 +37,12 @@
char **buf;
};
+static inline u64 generic_id(unsigned long timestamp,
+ unsigned int part, int count)
+{
+ return (timestamp * 100 + part) * 1000 + count;
+}
+
static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
{
efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
@@ -57,7 +61,7 @@
if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
cb_data->type, &part, &cnt, &time, &data_type) == 5) {
- *cb_data->id = part;
+ *cb_data->id = generic_id(time, part, cnt);
*cb_data->count = cnt;
cb_data->timespec->tv_sec = time;
cb_data->timespec->tv_nsec = 0;
@@ -67,7 +71,7 @@
*cb_data->compressed = false;
} else if (sscanf(name, "dump-type%u-%u-%d-%lu",
cb_data->type, &part, &cnt, &time) == 4) {
- *cb_data->id = part;
+ *cb_data->id = generic_id(time, part, cnt);
*cb_data->count = cnt;
cb_data->timespec->tv_sec = time;
cb_data->timespec->tv_nsec = 0;
@@ -79,7 +83,7 @@
* which doesn't support holding
* multiple logs, remains.
*/
- *cb_data->id = part;
+ *cb_data->id = generic_id(time, part, 0);
*cb_data->count = 0;
cb_data->timespec->tv_sec = time;
cb_data->timespec->tv_nsec = 0;
@@ -91,19 +95,125 @@
__efivar_entry_get(entry, &entry->var.Attributes,
&entry->var.DataSize, entry->var.Data);
size = entry->var.DataSize;
+ memcpy(*cb_data->buf, entry->var.Data,
+ (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size));
- *cb_data->buf = kmemdup(entry->var.Data, size, GFP_KERNEL);
- if (*cb_data->buf == NULL)
- return -ENOMEM;
return size;
}
+/**
+ * efi_pstore_scan_sysfs_enter
+ * @entry: scanning entry
+ * @next: next entry
+ * @head: list head
+ */
+static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos,
+ struct efivar_entry *next,
+ struct list_head *head)
+{
+ pos->scanning = true;
+ if (&next->list != head)
+ next->scanning = true;
+}
+
+/**
+ * __efi_pstore_scan_sysfs_exit
+ * @entry: deleting entry
+ * @turn_off_scanning: Check if a scanning flag should be turned off
+ */
+static inline void __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry,
+ bool turn_off_scanning)
+{
+ if (entry->deleting) {
+ list_del(&entry->list);
+ efivar_entry_iter_end();
+ efivar_unregister(entry);
+ efivar_entry_iter_begin();
+ } else if (turn_off_scanning)
+ entry->scanning = false;
+}
+
+/**
+ * efi_pstore_scan_sysfs_exit
+ * @pos: scanning entry
+ * @next: next entry
+ * @head: list head
+ * @stop: a flag checking if scanning will stop
+ */
+static void efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
+ struct efivar_entry *next,
+ struct list_head *head, bool stop)
+{
+ __efi_pstore_scan_sysfs_exit(pos, true);
+ if (stop)
+ __efi_pstore_scan_sysfs_exit(next, &next->list != head);
+}
+
+/**
+ * efi_pstore_sysfs_entry_iter
+ *
+ * @data: function-specific data to pass to callback
+ * @pos: entry to begin iterating from
+ *
+ * You MUST call efivar_enter_iter_begin() before this function, and
+ * efivar_entry_iter_end() afterwards.
+ *
+ * It is possible to begin iteration from an arbitrary entry within
+ * the list by passing @pos. @pos is updated on return to point to
+ * the next entry of the last one passed to efi_pstore_read_func().
+ * To begin iterating from the beginning of the list @pos must be %NULL.
+ */
+static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos)
+{
+ struct efivar_entry *entry, *n;
+ struct list_head *head = &efivar_sysfs_list;
+ int size = 0;
+
+ if (!*pos) {
+ list_for_each_entry_safe(entry, n, head, list) {
+ efi_pstore_scan_sysfs_enter(entry, n, head);
+
+ size = efi_pstore_read_func(entry, data);
+ efi_pstore_scan_sysfs_exit(entry, n, head, size < 0);
+ if (size)
+ break;
+ }
+ *pos = n;
+ return size;
+ }
+
+ list_for_each_entry_safe_from((*pos), n, head, list) {
+ efi_pstore_scan_sysfs_enter((*pos), n, head);
+
+ size = efi_pstore_read_func((*pos), data);
+ efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0);
+ if (size)
+ break;
+ }
+ *pos = n;
+ return size;
+}
+
+/**
+ * efi_pstore_read
+ *
+ * This function returns a size of NVRAM entry logged via efi_pstore_write().
+ * The meaning and behavior of efi_pstore/pstore are as below.
+ *
+ * size > 0: Got data of an entry logged via efi_pstore_write() successfully,
+ * and pstore filesystem will continue reading subsequent entries.
+ * size == 0: Entry was not logged via efi_pstore_write(),
+ * and efi_pstore driver will continue reading subsequent entries.
+ * size < 0: Failed to get data of entry logging via efi_pstore_write(),
+ * and pstore will stop reading entry.
+ */
static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
int *count, struct timespec *timespec,
char **buf, bool *compressed,
struct pstore_info *psi)
{
struct pstore_read_data data;
+ ssize_t size;
data.id = id;
data.type = type;
@@ -112,8 +222,17 @@
data.compressed = compressed;
data.buf = buf;
- return __efivar_entry_iter(efi_pstore_read_func, &efivar_sysfs_list, &data,
- (struct efivar_entry **)&psi->data);
+ *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
+ if (!*data.buf)
+ return -ENOMEM;
+
+ efivar_entry_iter_begin();
+ size = efi_pstore_sysfs_entry_iter(&data,
+ (struct efivar_entry **)&psi->data);
+ efivar_entry_iter_end();
+ if (size <= 0)
+ kfree(*data.buf);
+ return size;
}
static int efi_pstore_write(enum pstore_type_id type,
@@ -184,9 +303,17 @@
return 0;
}
+ if (entry->scanning) {
+ /*
+ * Skip deletion because this entry will be deleted
+ * after scanning is completed.
+ */
+ entry->deleting = true;
+ } else
+ list_del(&entry->list);
+
/* found */
__efivar_entry_delete(entry);
- list_del(&entry->list);
return 1;
}
@@ -199,14 +326,16 @@
char name[DUMP_NAME_LEN];
efi_char16_t efi_name[DUMP_NAME_LEN];
int found, i;
+ unsigned int part;
- sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
- time.tv_sec);
+ do_div(id, 1000);
+ part = do_div(id, 100);
+ sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, time.tv_sec);
for (i = 0; i < DUMP_NAME_LEN; i++)
efi_name[i] = name[i];
- edata.id = id;
+ edata.id = part;
edata.type = type;
edata.count = count;
edata.time = time;
@@ -214,10 +343,12 @@
efivar_entry_iter_begin();
found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry);
- efivar_entry_iter_end();
- if (found)
+ if (found && !entry->scanning) {
+ efivar_entry_iter_end();
efivar_unregister(entry);
+ } else
+ efivar_entry_iter_end();
return 0;
}
diff -Nur linux/drivers/firmware/efi/efivars.c rpi/drivers/firmware/efi/efivars.c
--- linux/drivers/firmware/efi/efivars.c 2014-05-29 12:18:19.321548199 +0900
+++ rpi/drivers/firmware/efi/efivars.c 2014-05-29 11:49:13.236889356 +0900
@@ -383,12 +383,16 @@
else if (__efivar_entry_delete(entry))
err = -EIO;
- efivar_entry_iter_end();
-
- if (err)
+ if (err) {
+ efivar_entry_iter_end();
return err;
+ }
- efivar_unregister(entry);
+ if (!entry->scanning) {
+ efivar_entry_iter_end();
+ efivar_unregister(entry);
+ } else
+ efivar_entry_iter_end();
/* It's dead Jim.... */
return count;
diff -Nur linux/drivers/firmware/efi/vars.c rpi/drivers/firmware/efi/vars.c
--- linux/drivers/firmware/efi/vars.c 2014-05-29 12:18:19.322548192 +0900
+++ rpi/drivers/firmware/efi/vars.c 2014-05-29 11:49:13.236889356 +0900
@@ -683,8 +683,16 @@
if (!found)
return NULL;
- if (remove)
- list_del(&entry->list);
+ if (remove) {
+ if (entry->scanning) {
+ /*
+ * The entry will be deleted
+ * after scanning is completed.
+ */
+ entry->deleting = true;
+ } else
+ list_del(&entry->list);
+ }
return entry;
}
diff -Nur linux/drivers/gpio/gpio-mpc8xxx.c rpi/drivers/gpio/gpio-mpc8xxx.c
--- linux/drivers/gpio/gpio-mpc8xxx.c 2014-05-29 12:18:19.339548086 +0900
+++ rpi/drivers/gpio/gpio-mpc8xxx.c 2014-05-29 11:49:13.253889214 +0900
@@ -69,10 +69,14 @@
u32 val;
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+ u32 out_mask, out_shadow;
- val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
+ out_mask = in_be32(mm->regs + GPIO_DIR);
- return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
+ val = in_be32(mm->regs + GPIO_DAT) & ~out_mask;
+ out_shadow = mpc8xxx_gc->data & out_mask;
+
+ return (val | out_shadow) & mpc8xxx_gpio2mask(gpio);
}
static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
diff -Nur linux/drivers/gpio/gpio-msm-v2.c rpi/drivers/gpio/gpio-msm-v2.c
--- linux/drivers/gpio/gpio-msm-v2.c 2014-05-29 12:18:19.339548086 +0900
+++ rpi/drivers/gpio/gpio-msm-v2.c 2014-05-29 11:49:13.254889205 +0900
@@ -102,7 +102,7 @@
DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
struct irq_domain *domain;
- unsigned int summary_irq;
+ int summary_irq;
void __iomem *msm_tlmm_base;
};
@@ -252,7 +252,7 @@
spin_lock_irqsave(&tlmm_lock, irq_flags);
writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
- clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+ clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
__clear_bit(gpio, msm_gpio.enabled_irqs);
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
}
@@ -264,7 +264,7 @@
spin_lock_irqsave(&tlmm_lock, irq_flags);
__set_bit(gpio, msm_gpio.enabled_irqs);
- set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+ set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));
writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
}
diff -Nur linux/drivers/gpio/gpio-mvebu.c rpi/drivers/gpio/gpio-mvebu.c
--- linux/drivers/gpio/gpio-mvebu.c 2014-05-29 12:18:19.340548080 +0900
+++ rpi/drivers/gpio/gpio-mvebu.c 2014-05-29 11:49:13.254889205 +0900
@@ -79,7 +79,7 @@
spinlock_t lock;
void __iomem *membase;
void __iomem *percpu_membase;
- unsigned int irqbase;
+ int irqbase;
struct irq_domain *domain;
int soc_variant;
};
diff -Nur linux/drivers/gpio/gpio-mxs.c rpi/drivers/gpio/gpio-mxs.c
--- linux/drivers/gpio/gpio-mxs.c 2014-05-29 12:18:19.341548073 +0900
+++ rpi/drivers/gpio/gpio-mxs.c 2014-05-29 11:49:13.255889197 +0900
@@ -214,7 +214,8 @@
ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
ct->regs.mask = PINCTRL_IRQEN(port);
- irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0);
+ irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
+ IRQ_NOREQUEST, 0);
}
static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
diff -Nur linux/drivers/gpio/gpio-pl061.c rpi/drivers/gpio/gpio-pl061.c
--- linux/drivers/gpio/gpio-pl061.c 2014-05-29 12:18:19.345548048 +0900
+++ rpi/drivers/gpio/gpio-pl061.c 2014-05-29 11:49:13.258889172 +0900
@@ -286,11 +286,6 @@
if (!chip->base)
return -ENOMEM;
- chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
- irq_base, &pl061_domain_ops, chip);
- if (!chip->domain)
- return -ENODEV;
-
spin_lock_init(&chip->lock);
chip->gc.request = pl061_gpio_request;
@@ -320,6 +315,11 @@
irq_set_chained_handler(irq, pl061_irq_handler);
irq_set_handler_data(irq, chip);
+ chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
+ irq_base, &pl061_domain_ops, chip);
+ if (!chip->domain)
+ return -ENODEV;
+
for (i = 0; i < PL061_GPIO_NR; i++) {
if (pdata) {
if (pdata->directions & (1 << i))
diff -Nur linux/drivers/gpio/gpio-rcar.c rpi/drivers/gpio/gpio-rcar.c
--- linux/drivers/gpio/gpio-rcar.c 2014-05-29 12:18:19.346548042 +0900
+++ rpi/drivers/gpio/gpio-rcar.c 2014-05-29 11:49:13.259889163 +0900
@@ -380,7 +380,7 @@
if (!p->irq_domain) {
ret = -ENXIO;
dev_err(&pdev->dev, "cannot initialize irq domain\n");
- goto err1;
+ goto err0;
}
if (devm_request_irq(&pdev->dev, irq->start,
diff -Nur linux/drivers/gpio/gpio-twl4030.c rpi/drivers/gpio/gpio-twl4030.c
--- linux/drivers/gpio/gpio-twl4030.c 2014-05-29 12:18:19.353547998 +0900
+++ rpi/drivers/gpio/gpio-twl4030.c 2014-05-29 11:49:13.264889121 +0900
@@ -300,7 +300,7 @@
if (offset < TWL4030_GPIO_MAX)
ret = twl4030_set_gpio_direction(offset, 1);
else
- ret = -EINVAL;
+ ret = -EINVAL; /* LED outputs can't be set as input */
if (!ret)
priv->direction &= ~BIT(offset);
@@ -354,17 +354,27 @@
static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)
{
struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);
+ int ret = 0;
mutex_lock(&priv->mutex);
- if (offset < TWL4030_GPIO_MAX)
- twl4030_set_gpio_dataout(offset, value);
+ if (offset < TWL4030_GPIO_MAX) {
+ ret = twl4030_set_gpio_direction(offset, 0);
+ if (ret) {
+ mutex_unlock(&priv->mutex);
+ return ret;
+ }
+ }
+
+ /*
+ * LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output
+ */
priv->direction |= BIT(offset);
mutex_unlock(&priv->mutex);
twl_set(chip, offset, value);
- return 0;
+ return ret;
}
static int twl_to_irq(struct gpio_chip *chip, unsigned offset)
diff -Nur linux/drivers/gpu/drm/ast/ast_fb.c rpi/drivers/gpu/drm/ast/ast_fb.c
--- linux/drivers/gpu/drm/ast/ast_fb.c 2014-05-29 12:18:19.360547955 +0900
+++ rpi/drivers/gpu/drm/ast/ast_fb.c 2014-05-29 11:49:13.271889063 +0900
@@ -65,7 +65,7 @@
* then the BO is being moved and we should
* store up the damage until later.
*/
- if (!in_interrupt())
+ if (drm_can_sleep())
ret = ast_bo_reserve(bo, true);
if (ret) {
if (ret != -EBUSY)
diff -Nur linux/drivers/gpu/drm/cirrus/cirrus_drv.c rpi/drivers/gpu/drm/cirrus/cirrus_drv.c
--- linux/drivers/gpu/drm/cirrus/cirrus_drv.c 2014-05-29 12:18:19.363547936 +0900
+++ rpi/drivers/gpu/drm/cirrus/cirrus_drv.c 2014-05-29 11:49:13.273889046 +0900
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/console.h>
#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
#include "cirrus_drv.h"
@@ -75,6 +76,41 @@
drm_put_dev(dev);
}
+static int cirrus_pm_suspend(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct cirrus_device *cdev = drm_dev->dev_private;
+
+ drm_kms_helper_poll_disable(drm_dev);
+
+ if (cdev->mode_info.gfbdev) {
+ console_lock();
+ fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1);
+ console_unlock();
+ }
+
+ return 0;
+}
+
+static int cirrus_pm_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct drm_device *drm_dev = pci_get_drvdata(pdev);
+ struct cirrus_device *cdev = drm_dev->dev_private;
+
+ drm_helper_resume_force_mode(drm_dev);
+
+ if (cdev->mode_info.gfbdev) {
+ console_lock();
+ fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0);
+ console_unlock();
+ }
+
+ drm_kms_helper_poll_enable(drm_dev);
+ return 0;
+}
+
static const struct file_operations cirrus_driver_fops = {
.owner = THIS_MODULE,
.open = drm_open,
@@ -104,11 +140,17 @@
.dumb_destroy = drm_gem_dumb_destroy,
};
+static const struct dev_pm_ops cirrus_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend,
+ cirrus_pm_resume)
+};
+
static struct pci_driver cirrus_pci_driver = {
.name = DRIVER_NAME,
.id_table = pciidlist,
.probe = cirrus_pci_probe,
.remove = cirrus_pci_remove,
+ .driver.pm = &cirrus_pm_ops,
};
static int __init cirrus_init(void)
diff -Nur linux/drivers/gpu/drm/cirrus/cirrus_fbdev.c rpi/drivers/gpu/drm/cirrus/cirrus_fbdev.c
--- linux/drivers/gpu/drm/cirrus/cirrus_fbdev.c 2014-05-29 12:18:19.363547936 +0900
+++ rpi/drivers/gpu/drm/cirrus/cirrus_fbdev.c 2014-05-29 11:49:13.274889038 +0900
@@ -39,7 +39,7 @@
* then the BO is being moved and we should
* store up the damage until later.
*/
- if (!in_interrupt())
+ if (drm_can_sleep())
ret = cirrus_bo_reserve(bo, true);
if (ret) {
if (ret != -EBUSY)
@@ -233,6 +233,9 @@
info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
info->apertures->ranges[0].size = cdev->mc.vram_size;
+ info->fix.smem_start = cdev->dev->mode_config.fb_base;
+ info->fix.smem_len = cdev->mc.vram_size;
+
info->screen_base = sysram;
info->screen_size = size;
diff -Nur linux/drivers/gpu/drm/cirrus/cirrus_mode.c rpi/drivers/gpu/drm/cirrus/cirrus_mode.c
--- linux/drivers/gpu/drm/cirrus/cirrus_mode.c 2014-05-29 12:18:19.364547929 +0900
+++ rpi/drivers/gpu/drm/cirrus/cirrus_mode.c 2014-05-29 11:49:13.275889029 +0900
@@ -273,8 +273,8 @@
sr07 |= 0x11;
break;
case 16:
- sr07 |= 0xc1;
- hdr = 0xc0;
+ sr07 |= 0x17;
+ hdr = 0xc1;
break;
case 24:
sr07 |= 0x15;
@@ -308,6 +308,9 @@
WREG_HDR(hdr);
cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
+
+ /* Unblank (needed on S3 resume, vgabios doesn't do it then) */
+ outb(0x20, 0x3c0);
return 0;
}
@@ -494,13 +497,12 @@
int cirrus_vga_get_modes(struct drm_connector *connector)
{
- /* Just add a static list of modes */
- drm_add_modes_noedid(connector, 640, 480);
- drm_add_modes_noedid(connector, 800, 600);
- drm_add_modes_noedid(connector, 1024, 768);
- drm_add_modes_noedid(connector, 1280, 1024);
+ int count;
- return 4;
+ /* Just add a static list of modes */
+ count = drm_add_modes_noedid(connector, 1280, 1024);
+ drm_set_preferred_mode(connector, 1024, 768);
+ return count;
}
static int cirrus_vga_mode_valid(struct drm_connector *connector,
diff -Nur linux/drivers/gpu/drm/drm_edid.c rpi/drivers/gpu/drm/drm_edid.c
--- linux/drivers/gpu/drm/drm_edid.c 2014-05-29 12:18:19.407547661 +0900
+++ rpi/drivers/gpu/drm/drm_edid.c 2014-05-29 11:49:13.282888971 +0900
@@ -68,6 +68,8 @@
#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
/* Force reduced-blanking timings for detailed modes */
#define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7)
+/* Force 8bpc */
+#define EDID_QUIRK_FORCE_8BPC (1 << 8)
struct detailed_mode_closure {
struct drm_connector *connector;
@@ -128,6 +130,9 @@
/* Medion MD 30217 PG */
{ "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 },
+
+ /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */
+ { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC },
};
/*
@@ -3236,6 +3241,9 @@
drm_add_display_info(edid, &connector->display_info);
+ if (quirks & EDID_QUIRK_FORCE_8BPC)
+ connector->display_info.bpc = 8;
+
return num_modes;
}
EXPORT_SYMBOL(drm_add_edid_modes);
@@ -3288,6 +3296,19 @@
}
EXPORT_SYMBOL(drm_add_modes_noedid);
+void drm_set_preferred_mode(struct drm_connector *connector,
+ int hpref, int vpref)
+{
+ struct drm_display_mode *mode;
+
+ list_for_each_entry(mode, &connector->probed_modes, head) {
+ if (drm_mode_width(mode) == hpref &&
+ drm_mode_height(mode) == vpref)
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+ }
+}
+EXPORT_SYMBOL(drm_set_preferred_mode);
+
/**
* drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with
* data from a DRM display mode
diff -Nur linux/drivers/gpu/drm/drm_fb_helper.c rpi/drivers/gpu/drm/drm_fb_helper.c
--- linux/drivers/gpu/drm/drm_fb_helper.c 2014-05-29 12:18:19.408547654 +0900
+++ rpi/drivers/gpu/drm/drm_fb_helper.c 2014-05-29 11:49:13.283888962 +0900
@@ -1163,6 +1163,7 @@
{
struct drm_cmdline_mode *cmdline_mode;
struct drm_display_mode *mode = NULL;
+ bool prefer_non_interlace;
cmdline_mode = &fb_helper_conn->cmdline_mode;
if (cmdline_mode->specified == false)
@@ -1174,6 +1175,8 @@
if (cmdline_mode->rb || cmdline_mode->margins)
goto create_mode;
+ prefer_non_interlace = !cmdline_mode->interlace;
+ again:
list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
/* check width/height */
if (mode->hdisplay != cmdline_mode->xres ||
@@ -1188,10 +1191,18 @@
if (cmdline_mode->interlace) {
if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
continue;
+ } else if (prefer_non_interlace) {
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ continue;
}
return mode;
}
+ if (prefer_non_interlace) {
+ prefer_non_interlace = false;
+ goto again;
+ }
+
create_mode:
mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
cmdline_mode);
diff -Nur linux/drivers/gpu/drm/drm_gem.c rpi/drivers/gpu/drm/drm_gem.c
--- linux/drivers/gpu/drm/drm_gem.c 2014-05-29 12:18:19.410547642 +0900
+++ rpi/drivers/gpu/drm/drm_gem.c 2014-05-29 11:49:13.284888954 +0900
@@ -129,11 +129,12 @@
{
struct file *filp;
+ drm_gem_private_object_init(dev, obj, size);
+
filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
if (IS_ERR(filp))
return PTR_ERR(filp);
- drm_gem_private_object_init(dev, obj, size);
obj->filp = filp;
return 0;
diff -Nur linux/drivers/gpu/drm/gma500/gma_display.c rpi/drivers/gpu/drm/gma500/gma_display.c
--- linux/drivers/gpu/drm/gma500/gma_display.c 2014-05-29 12:18:19.449547398 +0900
+++ rpi/drivers/gpu/drm/gma500/gma_display.c 2014-05-29 11:49:13.314888703 +0900
@@ -349,6 +349,7 @@
/* If we didn't get a handle then turn the cursor off */
if (!handle) {
temp = CURSOR_MODE_DISABLE;
+ mutex_lock(&dev->struct_mutex);
if (gma_power_begin(dev, false)) {
REG_WRITE(control, temp);
@@ -365,6 +366,7 @@
gma_crtc->cursor_obj = NULL;
}
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -374,9 +376,12 @@
return -EINVAL;
}
+ mutex_lock(&dev->struct_mutex);
obj = drm_gem_object_lookup(dev, file_priv, handle);
- if (!obj)
- return -ENOENT;
+ if (!obj) {
+ ret = -ENOENT;
+ goto unlock;
+ }
if (obj->size < width * height * 4) {
dev_dbg(dev->dev, "Buffer is too small\n");
@@ -440,10 +445,13 @@
}
gma_crtc->cursor_obj = obj;
+unlock:
+ mutex_unlock(&dev->struct_mutex);
return ret;
unref_cursor:
drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
return ret;
}
diff -Nur linux/drivers/gpu/drm/i915/i915_dma.c rpi/drivers/gpu/drm/i915/i915_dma.c
--- linux/drivers/gpu/drm/i915/i915_dma.c 2014-05-29 12:18:19.472547254 +0900
+++ rpi/drivers/gpu/drm/i915/i915_dma.c 2014-05-29 11:49:13.342888468 +0900
@@ -83,6 +83,14 @@
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv;
+ /*
+ * The dri breadcrumb update races against the drm master disappearing.
+ * Instead of trying to fix this (this is by far not the only ums issue)
+ * just don't do the update in kms mode.
+ */
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return;
+
if (dev->primary->master) {
master_priv = dev->primary->master->driver_priv;
if (master_priv->sarea_priv)
@@ -1675,6 +1683,7 @@
intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev);
+ pm_qos_remove_request(&dev_priv->pm_qos);
destroy_workqueue(dev_priv->wq);
out_mtrrfree:
arch_phys_wc_del(dev_priv->gtt.mtrr);
@@ -1848,8 +1857,10 @@
void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
{
+ mutex_lock(&dev->struct_mutex);
i915_gem_context_close(dev, file_priv);
i915_gem_release(dev, file_priv);
+ mutex_unlock(&dev->struct_mutex);
}
void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
diff -Nur linux/drivers/gpu/drm/i915/i915_drv.c rpi/drivers/gpu/drm/i915/i915_drv.c
--- linux/drivers/gpu/drm/i915/i915_drv.c 2014-05-29 12:18:19.473547248 +0900
+++ rpi/drivers/gpu/drm/i915/i915_drv.c 2014-05-29 11:49:13.342888468 +0900
@@ -376,7 +376,7 @@
void intel_detect_pch(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct pci_dev *pch;
+ struct pci_dev *pch = NULL;
/* In all current cases, num_pipes is equivalent to the PCH_NOP setting
* (which really amounts to a PCH but no South Display).
@@ -397,12 +397,9 @@
* all the ISA bridge devices and check for the first match, instead
* of only checking the first one.
*/
- pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
- while (pch) {
- struct pci_dev *curr = pch;
+ while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
if (pch->vendor == PCI_VENDOR_ID_INTEL) {
- unsigned short id;
- id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
+ unsigned short id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
dev_priv->pch_id = id;
if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
@@ -428,18 +425,16 @@
DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
WARN_ON(!IS_HASWELL(dev));
WARN_ON(!IS_ULT(dev));
- } else {
- goto check_next;
- }
- pci_dev_put(pch);
+ } else
+ continue;
+
break;
}
-check_next:
- pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, curr);
- pci_dev_put(curr);
}
if (!pch)
- DRM_DEBUG_KMS("No PCH found?\n");
+ DRM_DEBUG_KMS("No PCH found.\n");
+
+ pci_dev_put(pch);
}
bool i915_semaphore_is_enabled(struct drm_device *dev)
diff -Nur linux/drivers/gpu/drm/i915/i915_drv.h rpi/drivers/gpu/drm/i915/i915_drv.h
--- linux/drivers/gpu/drm/i915/i915_drv.h 2014-05-29 12:18:19.474547241 +0900
+++ rpi/drivers/gpu/drm/i915/i915_drv.h 2014-05-29 11:49:13.343888460 +0900
@@ -296,6 +296,7 @@
u64 fence[I915_MAX_NUM_FENCES];
struct timeval time;
struct drm_i915_error_ring {
+ bool valid;
struct drm_i915_error_object {
int page_count;
u32 gtt_offset;
diff -Nur linux/drivers/gpu/drm/i915/i915_gem.c rpi/drivers/gpu/drm/i915/i915_gem.c
--- linux/drivers/gpu/drm/i915/i915_gem.c 2014-05-29 12:18:19.478547216 +0900
+++ rpi/drivers/gpu/drm/i915/i915_gem.c 2014-05-29 11:49:13.345888443 +0900
@@ -2278,15 +2278,24 @@
kfree(request);
}
-static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
- struct intel_ring_buffer *ring)
+static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
+ struct intel_ring_buffer *ring)
{
- u32 completed_seqno;
- u32 acthd;
+ u32 completed_seqno = ring->get_seqno(ring, false);
+ u32 acthd = intel_ring_get_active_head(ring);
+ struct drm_i915_gem_request *request;
+
+ list_for_each_entry(request, &ring->request_list, list) {
+ if (i915_seqno_passed(completed_seqno, request->seqno))
+ continue;
- acthd = intel_ring_get_active_head(ring);
- completed_seqno = ring->get_seqno(ring, false);
+ i915_set_reset_status(ring, request, acthd);
+ }
+}
+static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
+ struct intel_ring_buffer *ring)
+{
while (!list_empty(&ring->request_list)) {
struct drm_i915_gem_request *request;
@@ -2294,9 +2303,6 @@
struct drm_i915_gem_request,
list);
- if (request->seqno > completed_seqno)
- i915_set_reset_status(ring, request, acthd);
-
i915_gem_free_request(request);
}
@@ -2338,8 +2344,16 @@
struct intel_ring_buffer *ring;
int i;
+ /*
+ * Before we free the objects from the requests, we need to inspect
+ * them for finding the guilty party. As the requests only borrow
+ * their reference to the objects, the inspection must be done first.
+ */
+ for_each_ring(ring, dev_priv, i)
+ i915_gem_reset_ring_status(dev_priv, ring);
+
for_each_ring(ring, dev_priv, i)
- i915_gem_reset_ring_lists(dev_priv, ring);
+ i915_gem_reset_ring_cleanup(dev_priv, ring);
i915_gem_restore_fences(dev);
}
diff -Nur linux/drivers/gpu/drm/i915/i915_gem_context.c rpi/drivers/gpu/drm/i915/i915_gem_context.c
--- linux/drivers/gpu/drm/i915/i915_gem_context.c 2014-05-29 12:18:19.479547210 +0900
+++ rpi/drivers/gpu/drm/i915/i915_gem_context.c 2014-05-29 11:49:13.346888434 +0900
@@ -328,10 +328,8 @@
{
struct drm_i915_file_private *file_priv = file->driver_priv;
- mutex_lock(&dev->struct_mutex);
idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
idr_destroy(&file_priv->context_idr);
- mutex_unlock(&dev->struct_mutex);
}
static struct i915_hw_context *
@@ -404,11 +402,21 @@
if (ret)
return ret;
- /* Clear this page out of any CPU caches for coherent swap-in/out. Note
+ /*
+ * Pin can switch back to the default context if we end up calling into
+ * evict_everything - as a last ditch gtt defrag effort that also
+ * switches to the default context. Hence we need to reload from here.
+ */
+ from = ring->last_context;
+
+ /*
+ * Clear this page out of any CPU caches for coherent swap-in/out. Note
* that thanks to write = false in this call and us not setting any gpu
* write domains when putting a context object onto the active list
* (when switching away from it), this won't block.
- * XXX: We need a real interface to do this instead of trickery. */
+ *
+ * XXX: We need a real interface to do this instead of trickery.
+ */
ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
if (ret) {
i915_gem_object_unpin(to->obj);
diff -Nur linux/drivers/gpu/drm/i915/i915_gem_gtt.c rpi/drivers/gpu/drm/i915/i915_gem_gtt.c
--- linux/drivers/gpu/drm/i915/i915_gem_gtt.c 2014-05-29 12:18:19.481547198 +0900
+++ rpi/drivers/gpu/drm/i915/i915_gem_gtt.c 2014-05-29 11:49:13.348888418 +0900
@@ -536,7 +536,7 @@
dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
dev_priv->gtt.base.start / PAGE_SIZE,
dev_priv->gtt.base.total / PAGE_SIZE,
- false);
+ true);
}
void i915_gem_restore_gtt_mappings(struct drm_device *dev)
diff -Nur linux/drivers/gpu/drm/i915/i915_gem_stolen.c rpi/drivers/gpu/drm/i915/i915_gem_stolen.c
--- linux/drivers/gpu/drm/i915/i915_gem_stolen.c 2014-05-29 12:18:19.482547191 +0900
+++ rpi/drivers/gpu/drm/i915/i915_gem_stolen.c 2014-05-29 11:49:13.349888409 +0900
@@ -201,6 +201,13 @@
struct drm_i915_private *dev_priv = dev->dev_private;
int bios_reserved = 0;
+#ifdef CONFIG_INTEL_IOMMU
+ if (intel_iommu_gfx_mapped) {
+ DRM_INFO("DMAR active, disabling use of stolen memory\n");
+ return 0;
+ }
+#endif
+
if (dev_priv->gtt.stolen_size == 0)
return 0;
@@ -250,7 +257,7 @@
}
sg = st->sgl;
- sg->offset = offset;
+ sg->offset = 0;
sg->length = size;
sg_dma_address(sg) = (dma_addr_t)dev_priv->mm.stolen_base + offset;
diff -Nur linux/drivers/gpu/drm/i915/i915_gpu_error.c rpi/drivers/gpu/drm/i915/i915_gpu_error.c
--- linux/drivers/gpu/drm/i915/i915_gpu_error.c 2014-05-29 12:18:19.483547185 +0900
+++ rpi/drivers/gpu/drm/i915/i915_gpu_error.c 2014-05-29 11:49:13.350888401 +0900
@@ -146,7 +146,10 @@
va_list tmp;
va_copy(tmp, args);
- if (!__i915_error_seek(e, vsnprintf(NULL, 0, f, tmp)))
+ len = vsnprintf(NULL, 0, f, tmp);
+ va_end(tmp);
+
+ if (!__i915_error_seek(e, len))
return;
}
@@ -221,6 +224,9 @@
unsigned ring)
{
BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
+ if (!error->ring[ring].valid)
+ return;
+
err_printf(m, "%s command stream:\n", ring_str(ring));
err_printf(m, " HEAD: 0x%08x\n", error->head[ring]);
err_printf(m, " TAIL: 0x%08x\n", error->tail[ring]);
@@ -272,7 +278,6 @@
struct drm_device *dev = error_priv->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_error_state *error = error_priv->error;
- struct intel_ring_buffer *ring;
int i, j, page, offset, elt;
if (!error) {
@@ -306,7 +311,7 @@
if (INTEL_INFO(dev)->gen == 7)
err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
- for_each_ring(ring, dev_priv, i)
+ for (i = 0; i < ARRAY_SIZE(error->ring); i++)
i915_ring_error_state(m, dev, error, i);
if (error->active_bo)
@@ -363,8 +368,7 @@
}
}
- obj = error->ring[i].ctx;
- if (obj) {
+ if ((obj = error->ring[i].ctx)) {
err_printf(m, "%s --- HW Context = 0x%08x\n",
dev_priv->ring[i].name,
obj->gtt_offset);
@@ -644,7 +648,8 @@
return NULL;
obj = ring->scratch.obj;
- if (acthd >= i915_gem_obj_ggtt_offset(obj) &&
+ if (obj != NULL &&
+ acthd >= i915_gem_obj_ggtt_offset(obj) &&
acthd < i915_gem_obj_ggtt_offset(obj) + obj->base.size)
return i915_error_object_create(dev_priv, obj);
}
@@ -747,11 +752,17 @@
struct drm_i915_error_state *error)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_ring_buffer *ring;
struct drm_i915_gem_request *request;
int i, count;
- for_each_ring(ring, dev_priv, i) {
+ for (i = 0; i < I915_NUM_RINGS; i++) {
+ struct intel_ring_buffer *ring = &dev_priv->ring[i];
+
+ if (ring->dev == NULL)
+ continue;
+
+ error->ring[i].valid = true;
+
i915_record_ring_state(dev, error, ring);
error->ring[i].batchbuffer =
diff -Nur linux/drivers/gpu/drm/i915/i915_reg.h rpi/drivers/gpu/drm/i915/i915_reg.h
--- linux/drivers/gpu/drm/i915/i915_reg.h 2014-05-29 12:18:19.489547148 +0900
+++ rpi/drivers/gpu/drm/i915/i915_reg.h 2014-05-29 11:49:13.354888367 +0900
@@ -1955,9 +1955,13 @@
* Please check the detailed lore in the commit message for for experimental
* evidence.
*/
-#define PORTD_HOTPLUG_LIVE_STATUS (1 << 29)
-#define PORTC_HOTPLUG_LIVE_STATUS (1 << 28)
-#define PORTB_HOTPLUG_LIVE_STATUS (1 << 27)
+#define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 29)
+#define PORTC_HOTPLUG_LIVE_STATUS_G4X (1 << 28)
+#define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 27)
+/* VLV DP/HDMI bits again match Bspec */
+#define PORTD_HOTPLUG_LIVE_STATUS_VLV (1 << 27)
+#define PORTC_HOTPLUG_LIVE_STATUS_VLV (1 << 28)
+#define PORTB_HOTPLUG_LIVE_STATUS_VLV (1 << 29)
#define PORTD_HOTPLUG_INT_STATUS (3 << 21)
#define PORTC_HOTPLUG_INT_STATUS (3 << 19)
#define PORTB_HOTPLUG_INT_STATUS (3 << 17)
diff -Nur linux/drivers/gpu/drm/i915/intel_crt.c rpi/drivers/gpu/drm/i915/intel_crt.c
--- linux/drivers/gpu/drm/i915/intel_crt.c 2014-05-29 12:18:19.492547129 +0900
+++ rpi/drivers/gpu/drm/i915/intel_crt.c 2014-05-29 11:49:13.358888334 +0900
@@ -758,6 +758,14 @@
DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
},
},
+ {
+ .callback = intel_no_crt_dmi_callback,
+ .ident = "DELL XPS 8700",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"),
+ },
+ },
{ }
};
diff -Nur linux/drivers/gpu/drm/i915/intel_ddi.c rpi/drivers/gpu/drm/i915/intel_ddi.c
--- linux/drivers/gpu/drm/i915/intel_ddi.c 2014-05-29 12:18:19.493547122 +0900
+++ rpi/drivers/gpu/drm/i915/intel_ddi.c 2014-05-29 11:49:13.358888334 +0900
@@ -961,12 +961,18 @@
enum pipe pipe;
struct intel_crtc *intel_crtc;
+ dev_priv->ddi_plls.spll_refcount = 0;
+ dev_priv->ddi_plls.wrpll1_refcount = 0;
+ dev_priv->ddi_plls.wrpll2_refcount = 0;
+
for_each_pipe(pipe) {
intel_crtc =
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
- if (!intel_crtc->active)
+ if (!intel_crtc->active) {
+ intel_crtc->ddi_pll_sel = PORT_CLK_SEL_NONE;
continue;
+ }
intel_crtc->ddi_pll_sel = intel_ddi_get_crtc_pll(dev_priv,
pipe);
@@ -1285,6 +1291,26 @@
default:
break;
}
+
+ if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp &&
+ pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
+ /*
+ * This is a big fat ugly hack.
+ *
+ * Some machines in UEFI boot mode provide us a VBT that has 18
+ * bpp and 1.62 GHz link bandwidth for eDP, which for reasons
+ * unknown we fail to light up. Yet the same BIOS boots up with
+ * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as
+ * max, not what it tells us to use.
+ *
+ * Note: This will still be broken if the eDP panel is not lit
+ * up by the BIOS, and thus we can't get the mode at module
+ * load.
+ */
+ DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n",
+ pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
+ dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
+ }
}
static void intel_ddi_destroy(struct drm_encoder *encoder)
diff -Nur linux/drivers/gpu/drm/i915/intel_display.c rpi/drivers/gpu/drm/i915/intel_display.c
--- linux/drivers/gpu/drm/i915/intel_display.c 2014-05-29 12:18:19.497547097 +0900
+++ rpi/drivers/gpu/drm/i915/intel_display.c 2014-05-29 11:49:13.362888300 +0900
@@ -1429,6 +1429,20 @@
POSTING_READ(DPLL(pipe));
}
+static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+ u32 val = 0;
+
+ /* Make sure the pipe isn't still relying on us */
+ assert_pipe_disabled(dev_priv, pipe);
+
+ /* Leave integrated clock source enabled */
+ if (pipe == PIPE_B)
+ val = DPLL_INTEGRATED_CRI_CLK_VLV;
+ I915_WRITE(DPLL(pipe), val);
+ POSTING_READ(DPLL(pipe));
+}
+
void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port)
{
u32 port_mask;
@@ -3824,7 +3838,10 @@
if (encoder->post_disable)
encoder->post_disable(encoder);
- i9xx_disable_pll(dev_priv, pipe);
+ if (IS_VALLEYVIEW(dev))
+ vlv_disable_pll(dev_priv, pipe);
+ else
+ i9xx_disable_pll(dev_priv, pipe);
intel_crtc->active = false;
intel_update_fbc(dev);
@@ -4553,9 +4570,9 @@
/* Enable DPIO clock input */
dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
- if (pipe)
+ /* We should never disable this, set it here for state tracking */
+ if (pipe == PIPE_B)
dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
-
dpll |= DPLL_VCO_ENABLE;
crtc->config.dpll_hw_state.dpll = dpll;
@@ -5015,6 +5032,32 @@
I915_READ(LVDS) & LVDS_BORDER_ENABLE;
}
+static void vlv_crtc_clock_get(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int pipe = pipe_config->cpu_transcoder;
+ intel_clock_t clock;
+ u32 mdiv;
+ int refclk = 100000;
+
+ mutex_lock(&dev_priv->dpio_lock);
+ mdiv = vlv_dpio_read(dev_priv, DPIO_DIV(pipe));
+ mutex_unlock(&dev_priv->dpio_lock);
+
+ clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7;
+ clock.m2 = mdiv & DPIO_M2DIV_MASK;
+ clock.n = (mdiv >> DPIO_N_SHIFT) & 0xf;
+ clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7;
+ clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f;
+
+ clock.vco = refclk * clock.m1 * clock.m2 / clock.n;
+ clock.dot = 2 * clock.vco / (clock.p1 * clock.p2);
+
+ pipe_config->adjusted_mode.clock = clock.dot / 10;
+}
+
static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config)
{
@@ -5546,7 +5589,7 @@
uint16_t postoff = 0;
if (intel_crtc->config.limited_color_range)
- postoff = (16 * (1 << 13) / 255) & 0x1fff;
+ postoff = (16 * (1 << 12) / 255) & 0x1fff;
I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
@@ -5966,7 +6009,7 @@
uint32_t val;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
- WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+ WARN(crtc->active, "CRTC for pipe %c enabled\n",
pipe_name(crtc->pipe));
WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
@@ -6062,7 +6105,7 @@
/* Make sure we're not on PC8 state before disabling PC8, otherwise
* we'll hang the machine! */
- dev_priv->uncore.funcs.force_wake_get(dev_priv);
+ gen6_gt_force_wake_get(dev_priv);
if (val & LCPLL_POWER_DOWN_ALLOW) {
val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6093,7 +6136,7 @@
DRM_ERROR("Switching back to LCPLL failed\n");
}
- dev_priv->uncore.funcs.force_wake_put(dev_priv);
+ gen6_gt_force_wake_put(dev_priv);
}
void hsw_enable_pc8_work(struct work_struct *__work)
@@ -6770,7 +6813,9 @@
intel_crtc->cursor_visible = visible;
}
/* and commit changes on next vblank */
+ POSTING_READ(CURCNTR(pipe));
I915_WRITE(CURBASE(pipe), base);
+ POSTING_READ(CURBASE(pipe));
}
static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
@@ -6799,7 +6844,9 @@
intel_crtc->cursor_visible = visible;
}
/* and commit changes on next vblank */
+ POSTING_READ(CURCNTR_IVB(pipe));
I915_WRITE(CURBASE_IVB(pipe), base);
+ POSTING_READ(CURBASE_IVB(pipe));
}
/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
@@ -7899,6 +7946,20 @@
if (ring->id == RCS)
len += 6;
+ /*
+ * BSpec MI_DISPLAY_FLIP for IVB:
+ * "The full packet must be contained within the same cache line."
+ *
+ * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
+ * cacheline, if we ever start emitting more commands before
+ * the MI_DISPLAY_FLIP we may need to first emit everything else,
+ * then do the cacheline alignment, and finally emit the
+ * MI_DISPLAY_FLIP.
+ */
+ ret = intel_ring_cacheline_align(ring);
+ if (ret)
+ goto err_unpin;
+
ret = intel_ring_begin(ring, len);
if (ret)
goto err_unpin;
@@ -9828,7 +9889,7 @@
dev_priv->display.update_plane = ironlake_update_plane;
} else if (IS_VALLEYVIEW(dev)) {
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
- dev_priv->display.get_clock = i9xx_crtc_clock_get;
+ dev_priv->display.get_clock = vlv_crtc_clock_get;
dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
dev_priv->display.crtc_enable = valleyview_crtc_enable;
dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -10012,8 +10073,7 @@
/* ThinkPad T60 needs pipe A force quirk (bug #16494) */
{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
- /* 830/845 need to leave pipe A & dpll A up */
- { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+ /* 830 needs to leave pipe A & dpll A up */
{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
/* Lenovo U160 cannot use SSC on LVDS */
@@ -10084,12 +10144,19 @@
void intel_modeset_init_hw(struct drm_device *dev)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
intel_init_power_well(dev);
intel_prepare_ddi(dev);
intel_init_clock_gating(dev);
+ /* Enable the CRI clock source so we can get at the display */
+ if (IS_VALLEYVIEW(dev))
+ I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
+ DPLL_INTEGRATED_CRI_CLK_VLV);
+
mutex_lock(&dev->struct_mutex);
intel_enable_gt_powersave(dev);
mutex_unlock(&dev->struct_mutex);
@@ -10538,7 +10605,9 @@
intel_setup_overlay(dev);
+ mutex_lock(&dev->mode_config.mutex);
intel_modeset_setup_hw_state(dev, false);
+ mutex_unlock(&dev->mode_config.mutex);
}
void intel_modeset_cleanup(struct drm_device *dev)
@@ -10612,14 +10681,15 @@
int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
u16 gmch_ctrl;
- pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
+ pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl);
if (state)
gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
else
gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
- pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
+ pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl);
return 0;
}
diff -Nur linux/drivers/gpu/drm/i915/intel_dp.c rpi/drivers/gpu/drm/i915/intel_dp.c
--- linux/drivers/gpu/drm/i915/intel_dp.c 2014-05-29 12:18:19.499547085 +0900
+++ rpi/drivers/gpu/drm/i915/intel_dp.c 2014-05-29 11:49:13.364888284 +0900
@@ -450,6 +450,7 @@
uint8_t msg[20];
int msg_bytes;
uint8_t ack;
+ int retry;
intel_dp_check_edp(intel_dp);
if (send_bytes > 16)
@@ -460,18 +461,20 @@
msg[3] = send_bytes - 1;
memcpy(&msg[4], send, send_bytes);
msg_bytes = send_bytes + 4;
- for (;;) {
+ for (retry = 0; retry < 7; retry++) {
ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes, &ack, 1);
if (ret < 0)
return ret;
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
- break;
+ return send_bytes;
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
- udelay(100);
+ usleep_range(400, 500);
else
return -EIO;
}
- return send_bytes;
+
+ DRM_ERROR("too many retries, giving up\n");
+ return -EIO;
}
/* Write a single byte to the aux channel in native mode */
@@ -493,6 +496,7 @@
int reply_bytes;
uint8_t ack;
int ret;
+ int retry;
intel_dp_check_edp(intel_dp);
msg[0] = AUX_NATIVE_READ << 4;
@@ -503,7 +507,7 @@
msg_bytes = 4;
reply_bytes = recv_bytes + 1;
- for (;;) {
+ for (retry = 0; retry < 7; retry++) {
ret = intel_dp_aux_ch(intel_dp, msg, msg_bytes,
reply, reply_bytes);
if (ret == 0)
@@ -516,10 +520,13 @@
return ret - 1;
}
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
- udelay(100);
+ usleep_range(400, 500);
else
return -EIO;
}
+
+ DRM_ERROR("too many retries, giving up\n");
+ return -EIO;
}
static int
@@ -2803,18 +2810,34 @@
return status;
}
- switch (intel_dig_port->port) {
- case PORT_B:
- bit = PORTB_HOTPLUG_LIVE_STATUS;
- break;
- case PORT_C:
- bit = PORTC_HOTPLUG_LIVE_STATUS;
- break;
- case PORT_D:
- bit = PORTD_HOTPLUG_LIVE_STATUS;
- break;
- default:
- return connector_status_unknown;
+ if (IS_VALLEYVIEW(dev)) {
+ switch (intel_dig_port->port) {
+ case PORT_B:
+ bit = PORTB_HOTPLUG_LIVE_STATUS_VLV;
+ break;
+ case PORT_C:
+ bit = PORTC_HOTPLUG_LIVE_STATUS_VLV;
+ break;
+ case PORT_D:
+ bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
+ break;
+ default:
+ return connector_status_unknown;
+ }
+ } else {
+ switch (intel_dig_port->port) {
+ case PORT_B:
+ bit = PORTB_HOTPLUG_LIVE_STATUS_G4X;
+ break;
+ case PORT_C:
+ bit = PORTC_HOTPLUG_LIVE_STATUS_G4X;
+ break;
+ case PORT_D:
+ bit = PORTD_HOTPLUG_LIVE_STATUS_G4X;
+ break;
+ default:
+ return connector_status_unknown;
+ }
}
if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0)
diff -Nur linux/drivers/gpu/drm/i915/intel_dvo.c rpi/drivers/gpu/drm/i915/intel_dvo.c
--- linux/drivers/gpu/drm/i915/intel_dvo.c 2014-05-29 12:18:19.500547079 +0900
+++ rpi/drivers/gpu/drm/i915/intel_dvo.c 2014-05-29 11:49:13.365888275 +0900
@@ -171,11 +171,16 @@
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
u32 dvo_reg = intel_dvo->dev.dvo_reg;
u32 temp = I915_READ(dvo_reg);
I915_WRITE(dvo_reg, temp | DVO_ENABLE);
I915_READ(dvo_reg);
+ intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev,
+ &crtc->config.requested_mode,
+ &crtc->config.adjusted_mode);
+
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
}
@@ -184,6 +189,7 @@
{
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
struct drm_crtc *crtc;
+ struct intel_crtc_config *config;
/* dvo supports only 2 dpms states. */
if (mode != DRM_MODE_DPMS_ON)
@@ -204,10 +210,16 @@
/* We call connector dpms manually below in case pipe dpms doesn't
* change due to cloning. */
if (mode == DRM_MODE_DPMS_ON) {
+ config = &to_intel_crtc(crtc)->config;
+
intel_dvo->base.connectors_active = true;
intel_crtc_update_dpms(crtc);
+ intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev,
+ &config->requested_mode,
+ &config->adjusted_mode);
+
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
} else {
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
@@ -299,10 +311,6 @@
break;
}
- intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev,
- &crtc->config.requested_mode,
- adjusted_mode);
-
/* Save the data order, since I don't know what it should be set to. */
dvo_val = I915_READ(dvo_reg) &
(DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
diff -Nur linux/drivers/gpu/drm/i915/intel_hdmi.c rpi/drivers/gpu/drm/i915/intel_hdmi.c
--- linux/drivers/gpu/drm/i915/intel_hdmi.c 2014-05-29 12:18:19.501547072 +0900
+++ rpi/drivers/gpu/drm/i915/intel_hdmi.c 2014-05-29 11:49:13.366888267 +0900
@@ -834,7 +834,7 @@
{
struct drm_device *dev = intel_hdmi_to_dev(hdmi);
- if (IS_G4X(dev))
+ if (!hdmi->has_hdmi_sink || IS_G4X(dev))
return 165000;
else if (IS_HASWELL(dev))
return 300000;
@@ -887,8 +887,8 @@
* outputs. We also need to check that the higher clock still fits
* within limits.
*/
- if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= portclock_limit
- && HAS_PCH_SPLIT(dev)) {
+ if (pipe_config->pipe_bpp > 8*3 && intel_hdmi->has_hdmi_sink &&
+ clock_12bpc <= portclock_limit && HAS_PCH_SPLIT(dev)) {
DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
desired_bpp = 12*3;
diff -Nur linux/drivers/gpu/drm/i915/intel_ringbuffer.c rpi/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux/drivers/gpu/drm/i915/intel_ringbuffer.c 2014-05-29 12:18:19.507547035 +0900
+++ rpi/drivers/gpu/drm/i915/intel_ringbuffer.c 2014-05-29 11:49:13.373888208 +0900
@@ -1501,8 +1501,8 @@
return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request);
}
-static int __intel_ring_begin(struct intel_ring_buffer *ring,
- int bytes)
+static int __intel_ring_prepare(struct intel_ring_buffer *ring,
+ int bytes)
{
int ret;
@@ -1518,7 +1518,6 @@
return ret;
}
- ring->space -= bytes;
return 0;
}
@@ -1533,12 +1532,38 @@
if (ret)
return ret;
+ ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t));
+ if (ret)
+ return ret;
+
/* Preallocate the olr before touching the ring */
ret = intel_ring_alloc_seqno(ring);
if (ret)
return ret;
- return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t));
+ ring->space -= num_dwords * sizeof(uint32_t);
+ return 0;
+}
+
+/* Align the ring tail to a cacheline boundary */
+int intel_ring_cacheline_align(struct intel_ring_buffer *ring)
+{
+ int num_dwords = (64 - (ring->tail & 63)) / sizeof(uint32_t);
+ int ret;
+
+ if (num_dwords == 0)
+ return 0;
+
+ ret = intel_ring_begin(ring, num_dwords);
+ if (ret)
+ return ret;
+
+ while (num_dwords--)
+ intel_ring_emit(ring, MI_NOOP);
+
+ intel_ring_advance(ring);
+
+ return 0;
}
void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
diff -Nur linux/drivers/gpu/drm/i915/intel_ringbuffer.h rpi/drivers/gpu/drm/i915/intel_ringbuffer.h
--- linux/drivers/gpu/drm/i915/intel_ringbuffer.h 2014-05-29 12:18:19.507547035 +0900
+++ rpi/drivers/gpu/drm/i915/intel_ringbuffer.h 2014-05-29 11:49:13.374888200 +0900
@@ -231,6 +231,7 @@
void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
+int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring);
static inline void intel_ring_emit(struct intel_ring_buffer *ring,
u32 data)
{
diff -Nur linux/drivers/gpu/drm/i915/intel_uncore.c rpi/drivers/gpu/drm/i915/intel_uncore.c
--- linux/drivers/gpu/drm/i915/intel_uncore.c 2014-05-29 12:18:19.512547004 +0900
+++ rpi/drivers/gpu/drm/i915/intel_uncore.c 2014-05-29 11:49:13.379888158 +0900
@@ -204,6 +204,19 @@
gen6_gt_check_fifodbg(dev_priv);
}
+static void intel_uncore_forcewake_reset(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (IS_VALLEYVIEW(dev)) {
+ vlv_force_wake_reset(dev_priv);
+ } else if (INTEL_INFO(dev)->gen >= 6) {
+ __gen6_gt_force_wake_reset(dev_priv);
+ if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+ __gen6_gt_force_wake_mt_reset(dev_priv);
+ }
+}
+
void intel_uncore_early_sanitize(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -259,19 +272,8 @@
dev_priv->uncore.funcs.force_wake_put =
__gen6_gt_force_wake_put;
}
-}
-
-static void intel_uncore_forcewake_reset(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- if (IS_VALLEYVIEW(dev)) {
- vlv_force_wake_reset(dev_priv);
- } else if (INTEL_INFO(dev)->gen >= 6) {
- __gen6_gt_force_wake_reset(dev_priv);
- if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
- __gen6_gt_force_wake_mt_reset(dev_priv);
- }
+ intel_uncore_forcewake_reset(dev);
}
void intel_uncore_sanitize(struct drm_device *dev)
diff -Nur linux/drivers/gpu/drm/mgag200/mgag200_cursor.c rpi/drivers/gpu/drm/mgag200/mgag200_cursor.c
--- linux/drivers/gpu/drm/mgag200/mgag200_cursor.c 2014-05-29 12:18:19.515546985 +0900
+++ rpi/drivers/gpu/drm/mgag200/mgag200_cursor.c 2014-05-29 11:49:13.383888124 +0900
@@ -22,8 +22,10 @@
{
WREG8(MGA_CURPOSXL, 0);
WREG8(MGA_CURPOSXH, 0);
- mgag200_bo_unpin(mdev->cursor.pixels_1);
- mgag200_bo_unpin(mdev->cursor.pixels_2);
+ if (mdev->cursor.pixels_1->pin_count)
+ mgag200_bo_unpin(mdev->cursor.pixels_1);
+ if (mdev->cursor.pixels_2->pin_count)
+ mgag200_bo_unpin(mdev->cursor.pixels_2);
}
int mga_crtc_cursor_set(struct drm_crtc *crtc,
@@ -32,7 +34,7 @@
uint32_t width,
uint32_t height)
{
- struct drm_device *dev = (struct drm_device *)file_priv->minor->dev;
+ struct drm_device *dev = crtc->dev;
struct mga_device *mdev = (struct mga_device *)dev->dev_private;
struct mgag200_bo *pixels_1 = mdev->cursor.pixels_1;
struct mgag200_bo *pixels_2 = mdev->cursor.pixels_2;
diff -Nur linux/drivers/gpu/drm/mgag200/mgag200_fb.c rpi/drivers/gpu/drm/mgag200/mgag200_fb.c
--- linux/drivers/gpu/drm/mgag200/mgag200_fb.c 2014-05-29 12:18:19.516546979 +0900
+++ rpi/drivers/gpu/drm/mgag200/mgag200_fb.c 2014-05-29 11:49:13.383888124 +0900
@@ -41,7 +41,7 @@
* then the BO is being moved and we should
* store up the damage until later.
*/
- if (!in_interrupt())
+ if (drm_can_sleep())
ret = mgag200_bo_reserve(bo, true);
if (ret) {
if (ret != -EBUSY)
diff -Nur linux/drivers/gpu/drm/mgag200/mgag200_mode.c rpi/drivers/gpu/drm/mgag200/mgag200_mode.c
--- linux/drivers/gpu/drm/mgag200/mgag200_mode.c 2014-05-29 12:18:19.517546972 +0900
+++ rpi/drivers/gpu/drm/mgag200/mgag200_mode.c 2014-05-29 11:49:13.385888108 +0900
@@ -1521,11 +1521,11 @@
(mga_vga_calculate_mode_bandwidth(mode, bpp)
> (32700 * 1024))) {
return MODE_BANDWIDTH;
- } else if (mode->type == G200_EH &&
+ } else if (mdev->type == G200_EH &&
(mga_vga_calculate_mode_bandwidth(mode, bpp)
> (37500 * 1024))) {
return MODE_BANDWIDTH;
- } else if (mode->type == G200_ER &&
+ } else if (mdev->type == G200_ER &&
(mga_vga_calculate_mode_bandwidth(mode,
bpp) > (55000 * 1024))) {
return MODE_BANDWIDTH;
diff -Nur linux/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c rpi/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
--- linux/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c 2014-05-29 12:18:19.538546841 +0900
+++ rpi/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c 2014-05-29 11:49:13.409887907 +0900
@@ -1112,7 +1112,7 @@
if (conf != ~0) {
if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) {
u32 soff = (ffs(outp.or) - 1) * 0x08;
- u32 ctrl = nv_rd32(priv, 0x610798 + soff);
+ u32 ctrl = nv_rd32(priv, 0x610794 + soff);
u32 datarate;
switch ((ctrl & 0x000f0000) >> 16) {
diff -Nur linux/drivers/gpu/drm/nouveau/core/engine/falcon.c rpi/drivers/gpu/drm/nouveau/core/engine/falcon.c
--- linux/drivers/gpu/drm/nouveau/core/engine/falcon.c 2014-05-29 12:18:19.543546810 +0900
+++ rpi/drivers/gpu/drm/nouveau/core/engine/falcon.c 2014-05-29 11:49:13.413887873 +0900
@@ -56,6 +56,16 @@
nv_wr32(falcon, falcon->addr + addr, data);
}
+static void *
+vmemdup(const void *src, size_t len)
+{
+ void *p = vmalloc(len);
+
+ if (p)
+ memcpy(p, src, len);
+ return p;
+}
+
int
_nouveau_falcon_init(struct nouveau_object *object)
{
@@ -111,7 +121,7 @@
ret = request_firmware(&fw, name, &device->pdev->dev);
if (ret == 0) {
- falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+ falcon->code.data = vmemdup(fw->data, fw->size);
falcon->code.size = fw->size;
falcon->data.data = NULL;
falcon->data.size = 0;
@@ -134,7 +144,7 @@
return ret;
}
- falcon->data.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+ falcon->data.data = vmemdup(fw->data, fw->size);
falcon->data.size = fw->size;
release_firmware(fw);
if (!falcon->data.data)
@@ -149,7 +159,7 @@
return ret;
}
- falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+ falcon->code.data = vmemdup(fw->data, fw->size);
falcon->code.size = fw->size;
release_firmware(fw);
if (!falcon->code.data)
@@ -235,8 +245,8 @@
if (!suspend) {
nouveau_gpuobj_ref(NULL, &falcon->core);
if (falcon->external) {
- kfree(falcon->data.data);
- kfree(falcon->code.data);
+ vfree(falcon->data.data);
+ vfree(falcon->code.data);
falcon->code.data = NULL;
}
}
diff -Nur linux/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c rpi/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
--- linux/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c 2014-05-29 12:18:19.547546785 +0900
+++ rpi/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c 2014-05-29 11:49:13.419887823 +0900
@@ -587,6 +587,7 @@
{ 0x405870, 4, 0x04, 0x00000001 },
{ 0x405a00, 2, 0x04, 0x00000000 },
{ 0x405a18, 1, 0x04, 0x00000000 },
+ {}
};
static struct nvc0_graph_init
@@ -598,6 +599,7 @@
{ 0x408904, 1, 0x04, 0x62000001 },
{ 0x408908, 1, 0x04, 0x00c80929 },
{ 0x408980, 1, 0x04, 0x0000011d },
+ {}
};
static struct nvc0_graph_init
@@ -671,6 +673,7 @@
{ 0x419000, 1, 0x04, 0x00000780 },
{ 0x419004, 2, 0x04, 0x00000000 },
{ 0x419014, 1, 0x04, 0x00000004 },
+ {}
};
static struct nvc0_graph_init
@@ -717,6 +720,7 @@
{ 0x419e98, 1, 0x04, 0x00000000 },
{ 0x419ee0, 1, 0x04, 0x00011110 },
{ 0x419f30, 11, 0x04, 0x00000000 },
+ {}
};
void
diff -Nur linux/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c rpi/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
--- linux/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c 2014-05-29 12:18:19.548546778 +0900
+++ rpi/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c 2014-05-29 11:49:13.420887815 +0900
@@ -258,6 +258,7 @@
nvc0_grctx_init_unk78xx,
nvc0_grctx_init_unk80xx,
nvd9_grctx_init_rop,
+ NULL
};
struct nvc0_graph_init *
diff -Nur linux/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c rpi/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
--- linux/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c 2014-05-29 12:18:19.548546778 +0900
+++ rpi/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c 2014-05-29 11:49:13.421887806 +0900
@@ -466,6 +466,7 @@
nvc0_grctx_init_unk78xx,
nvc0_grctx_init_unk80xx,
nvd9_grctx_init_rop,
+ NULL
};
struct nvc0_graph_init *
diff -Nur linux/drivers/gpu/drm/nouveau/core/subdev/bios/init.c rpi/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
--- linux/drivers/gpu/drm/nouveau/core/subdev/bios/init.c 2014-05-29 12:18:19.570546641 +0900
+++ rpi/drivers/gpu/drm/nouveau/core/subdev/bios/init.c 2014-05-29 11:49:13.449887572 +0900
@@ -365,13 +365,13 @@
init_script(struct nouveau_bios *bios, int index)
{
struct nvbios_init init = { .bios = bios };
- u16 data;
+ u16 bmp_ver = bmp_version(bios), data;
- if (bmp_version(bios) && bmp_version(bios) < 0x0510) {
- if (index > 1)
+ if (bmp_ver && bmp_ver < 0x0510) {
+ if (index > 1 || bmp_ver < 0x0100)
return 0x0000;
- data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18);
+ data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18);
return nv_ro16(bios, data + (index * 2));
}
@@ -1294,7 +1294,11 @@
u16 offset = nv_ro16(bios, init->offset + 1);
trace("JUMP\t0x%04x\n", offset);
- init->offset = offset;
+
+ if (init_exec(init))
+ init->offset = offset;
+ else
+ init->offset += 3;
}
/**
diff -Nur linux/drivers/gpu/drm/nouveau/nouveau_acpi.c rpi/drivers/gpu/drm/nouveau/nouveau_acpi.c
--- linux/drivers/gpu/drm/nouveau/nouveau_acpi.c 2014-05-29 12:18:19.617546347 +0900
+++ rpi/drivers/gpu/drm/nouveau/nouveau_acpi.c 2014-05-29 11:49:13.480887312 +0900
@@ -51,6 +51,7 @@
bool dsm_detected;
bool optimus_detected;
acpi_handle dhandle;
+ acpi_handle other_handle;
acpi_handle rom_handle;
} nouveau_dsm_priv;
@@ -65,6 +66,7 @@
#define NOUVEAU_DSM_HAS_MUX 0x1
#define NOUVEAU_DSM_HAS_OPT 0x2
+#ifdef CONFIG_VGA_SWITCHEROO
static const char nouveau_dsm_muid[] = {
0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
@@ -253,19 +255,17 @@
static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
{
- acpi_handle dhandle, nvidia_handle;
- acpi_status status;
+ acpi_handle dhandle;
int retval = 0;
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!dhandle)
return false;
- status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
- if (ACPI_FAILURE(status)) {
+ if (!acpi_has_method(dhandle, "_DSM")) {
+ nouveau_dsm_priv.other_handle = dhandle;
return false;
}
-
if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
retval |= NOUVEAU_DSM_HAS_MUX;
@@ -331,6 +331,16 @@
printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
acpi_method_name);
nouveau_dsm_priv.dsm_detected = true;
+ /*
+ * On some systems hotplug events are generated for the device
+ * being switched off when _DSM is executed. They cause ACPI
+ * hotplug to trigger and attempt to remove the device from
+ * the system, which causes it to break down. Prevent that from
+ * happening by setting the no_hotplug flag for the involved
+ * ACPI device objects.
+ */
+ acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle);
+ acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);
ret = true;
}
@@ -369,6 +379,11 @@
if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected)
vga_switcheroo_unregister_handler();
}
+#else
+void nouveau_register_dsm_handler(void) {}
+void nouveau_unregister_dsm_handler(void) {}
+void nouveau_switcheroo_optimus_dsm(void) {}
+#endif
/* retrieve the ROM in 4k blocks */
static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
diff -Nur linux/drivers/gpu/drm/nouveau/nouveau_bo.c rpi/drivers/gpu/drm/nouveau/nouveau_bo.c
--- linux/drivers/gpu/drm/nouveau/nouveau_bo.c 2014-05-29 12:18:19.624546303 +0900
+++ rpi/drivers/gpu/drm/nouveau/nouveau_bo.c 2014-05-29 11:49:13.485887270 +0900
@@ -802,25 +802,25 @@
struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
{
struct nouveau_mem *node = old_mem->mm_node;
- struct nouveau_bo *nvbo = nouveau_bo(bo);
u64 length = (new_mem->num_pages << PAGE_SHIFT);
u64 src_offset = node->vma[0].offset;
u64 dst_offset = node->vma[1].offset;
+ int src_tiled = !!node->memtype;
+ int dst_tiled = !!((struct nouveau_mem *)new_mem->mm_node)->memtype;
int ret;
while (length) {
u32 amount, stride, height;
+ ret = RING_SPACE(chan, 18 + 6 * (src_tiled + dst_tiled));
+ if (ret)
+ return ret;
+
amount = min(length, (u64)(4 * 1024 * 1024));
stride = 16 * 4;
height = amount / stride;
- if (old_mem->mem_type == TTM_PL_VRAM &&
- nouveau_bo_tile_layout(nvbo)) {
- ret = RING_SPACE(chan, 8);
- if (ret)
- return ret;
-
+ if (src_tiled) {
BEGIN_NV04(chan, NvSubCopy, 0x0200, 7);
OUT_RING (chan, 0);
OUT_RING (chan, 0);
@@ -830,19 +830,10 @@
OUT_RING (chan, 0);
OUT_RING (chan, 0);
} else {
- ret = RING_SPACE(chan, 2);
- if (ret)
- return ret;
-
BEGIN_NV04(chan, NvSubCopy, 0x0200, 1);
OUT_RING (chan, 1);
}
- if (new_mem->mem_type == TTM_PL_VRAM &&
- nouveau_bo_tile_layout(nvbo)) {
- ret = RING_SPACE(chan, 8);
- if (ret)
- return ret;
-
+ if (dst_tiled) {
BEGIN_NV04(chan, NvSubCopy, 0x021c, 7);
OUT_RING (chan, 0);
OUT_RING (chan, 0);
@@ -852,18 +843,10 @@
OUT_RING (chan, 0);
OUT_RING (chan, 0);
} else {
- ret = RING_SPACE(chan, 2);
- if (ret)
- return ret;
-
BEGIN_NV04(chan, NvSubCopy, 0x021c, 1);
OUT_RING (chan, 1);
}
- ret = RING_SPACE(chan, 14);
- if (ret)
- return ret;
-
BEGIN_NV04(chan, NvSubCopy, 0x0238, 2);
OUT_RING (chan, upper_32_bits(src_offset));
OUT_RING (chan, upper_32_bits(dst_offset));
diff -Nur linux/drivers/gpu/drm/nouveau/nouveau_drm.c rpi/drivers/gpu/drm/nouveau/nouveau_drm.c
--- linux/drivers/gpu/drm/nouveau/nouveau_drm.c 2014-05-29 12:18:19.630546265 +0900
+++ rpi/drivers/gpu/drm/nouveau/nouveau_drm.c 2014-05-29 11:49:13.489887237 +0900
@@ -382,6 +382,8 @@
if (ret)
goto fail_device;
+ dev->irq_enabled = true;
+
/* workaround an odd issue on nvc1 by disabling the device's
* nosnoop capability. hopefully won't cause issues until a
* better fix is found - assuming there is one...
@@ -481,6 +483,7 @@
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_object *device;
+ dev->irq_enabled = false;
device = drm->client.base.device;
drm_put_dev(dev);
@@ -879,6 +882,12 @@
if (nouveau_runtime_pm == 0)
return -EINVAL;
+ /* are we optimus enabled? */
+ if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
+ DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+ return -EINVAL;
+ }
+
drm_kms_helper_poll_disable(drm_dev);
vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
nouveau_switcheroo_optimus_dsm();
diff -Nur linux/drivers/gpu/drm/nouveau/nouveau_gem.c rpi/drivers/gpu/drm/nouveau/nouveau_gem.c
--- linux/drivers/gpu/drm/nouveau/nouveau_gem.c 2014-05-29 12:18:19.631546259 +0900
+++ rpi/drivers/gpu/drm/nouveau/nouveau_gem.c 2014-05-29 11:49:13.491887220 +0900
@@ -317,7 +317,8 @@
list_for_each_safe(entry, tmp, list) {
nvbo = list_entry(entry, struct nouveau_bo, entry);
- nouveau_bo_fence(nvbo, fence);
+ if (likely(fence))
+ nouveau_bo_fence(nvbo, fence);
if (unlikely(nvbo->validate_mapped)) {
ttm_bo_kunmap(&nvbo->kmap);
diff -Nur linux/drivers/gpu/drm/qxl/qxl_fb.c rpi/drivers/gpu/drm/qxl/qxl_fb.c
--- linux/drivers/gpu/drm/qxl/qxl_fb.c 2014-05-29 12:18:19.646546165 +0900
+++ rpi/drivers/gpu/drm/qxl/qxl_fb.c 2014-05-29 11:49:13.512887044 +0900
@@ -108,7 +108,7 @@
u32 x1, x2, y1, y2;
/* TODO: hard coding 32 bpp */
- int stride = qfbdev->qfb.base.pitches[0] * 4;
+ int stride = qfbdev->qfb.base.pitches[0];
x1 = qfbdev->dirty.x1;
x2 = qfbdev->dirty.x2;
diff -Nur linux/drivers/gpu/drm/qxl/qxl_release.c rpi/drivers/gpu/drm/qxl/qxl_release.c
--- linux/drivers/gpu/drm/qxl/qxl_release.c 2014-05-29 12:18:19.649546147 +0900
+++ rpi/drivers/gpu/drm/qxl/qxl_release.c 2014-05-29 11:49:13.514887027 +0900
@@ -92,6 +92,7 @@
- DRM_FILE_OFFSET);
qxl_fence_remove_release(&bo->fence, release->id);
qxl_bo_unref(&bo);
+ kfree(entry);
}
spin_lock(&qdev->release_idr_lock);
idr_remove(&qdev->release_idr, release->id);
diff -Nur linux/drivers/gpu/drm/radeon/atombios_crtc.c rpi/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux/drivers/gpu/drm/radeon/atombios_crtc.c 2014-05-29 12:18:19.659546084 +0900
+++ rpi/drivers/gpu/drm/radeon/atombios_crtc.c 2014-05-29 11:49:13.526886927 +0900
@@ -209,6 +209,16 @@
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
+static const u32 vga_control_regs[6] =
+{
+ AVIVO_D1VGA_CONTROL,
+ AVIVO_D2VGA_CONTROL,
+ EVERGREEN_D3VGA_CONTROL,
+ EVERGREEN_D4VGA_CONTROL,
+ EVERGREEN_D5VGA_CONTROL,
+ EVERGREEN_D6VGA_CONTROL,
+};
+
static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -216,13 +226,23 @@
struct radeon_device *rdev = dev->dev_private;
int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
BLANK_CRTC_PS_ALLOCATION args;
+ u32 vga_control = 0;
memset(&args, 0, sizeof(args));
+ if (ASIC_IS_DCE8(rdev)) {
+ vga_control = RREG32(vga_control_regs[radeon_crtc->crtc_id]);
+ WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control | 1);
+ }
+
args.ucCRTC = radeon_crtc->crtc_id;
args.ucBlanking = state;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+ if (ASIC_IS_DCE8(rdev)) {
+ WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control);
+ }
}
static void atombios_powergate_crtc(struct drm_crtc *crtc, int state)
@@ -938,11 +958,14 @@
radeon_atombios_get_ppll_ss_info(rdev,
&radeon_crtc->ss,
ATOM_DP_SS_ID1);
- } else
+ } else {
radeon_crtc->ss_enabled =
radeon_atombios_get_ppll_ss_info(rdev,
&radeon_crtc->ss,
ATOM_DP_SS_ID1);
+ }
+ /* disable spread spectrum on DCE3 DP */
+ radeon_crtc->ss_enabled = false;
}
break;
case ATOM_ENCODER_MODE_LVDS:
@@ -1180,23 +1203,18 @@
fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
if (rdev->family >= CHIP_BONAIRE) {
- u32 num_pipe_configs = rdev->config.cik.max_tile_pipes;
- u32 num_rb = rdev->config.cik.max_backends_per_se;
- if (num_pipe_configs > 8)
- num_pipe_configs = 8;
- if (num_pipe_configs == 8)
- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16);
- else if (num_pipe_configs == 4) {
- if (num_rb == 4)
- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16);
- else if (num_rb < 4)
- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16);
- } else if (num_pipe_configs == 2)
- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2);
+ /* Read the pipe config from the 2D TILED SCANOUT mode.
+ * It should be the same for the other modes too, but not all
+ * modes set the pipe config field. */
+ u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f;
+
+ fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config);
} else if ((rdev->family == CHIP_TAHITI) ||
(rdev->family == CHIP_PITCAIRN))
fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);
- else if (rdev->family == CHIP_VERDE)
+ else if ((rdev->family == CHIP_VERDE) ||
+ (rdev->family == CHIP_OLAND) ||
+ (rdev->family == CHIP_HAINAN)) /* for completeness. HAINAN has no display hw */
fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16);
switch (radeon_crtc->crtc_id) {
@@ -1726,6 +1744,20 @@
return ATOM_PPLL1;
DRM_ERROR("unable to allocate a PPLL\n");
return ATOM_PPLL_INVALID;
+ } else if (ASIC_IS_DCE41(rdev)) {
+ /* Don't share PLLs on DCE4.1 chips */
+ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
+ if (rdev->clock.dp_extclk)
+ /* skip PPLL programming if using ext clock */
+ return ATOM_PPLL_INVALID;
+ }
+ pll_in_use = radeon_get_pll_use_mask(crtc);
+ if (!(pll_in_use & (1 << ATOM_PPLL1)))
+ return ATOM_PPLL1;
+ if (!(pll_in_use & (1 << ATOM_PPLL2)))
+ return ATOM_PPLL2;
+ DRM_ERROR("unable to allocate a PPLL\n");
+ return ATOM_PPLL_INVALID;
} else if (ASIC_IS_DCE4(rdev)) {
/* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,
* depending on the asic:
diff -Nur linux/drivers/gpu/drm/radeon/atombios_encoders.c rpi/drivers/gpu/drm/radeon/atombios_encoders.c
--- linux/drivers/gpu/drm/radeon/atombios_encoders.c 2014-05-29 12:18:19.660546078 +0900
+++ rpi/drivers/gpu/drm/radeon/atombios_encoders.c 2014-05-29 11:49:13.528886910 +0900
@@ -1313,7 +1313,7 @@
}
if (is_dp)
args.v5.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v5.ucLaneNum = 8;
else
args.v5.ucLaneNum = 4;
diff -Nur linux/drivers/gpu/drm/radeon/atombios_i2c.c rpi/drivers/gpu/drm/radeon/atombios_i2c.c
--- linux/drivers/gpu/drm/radeon/atombios_i2c.c 2014-05-29 12:18:19.661546071 +0900
+++ rpi/drivers/gpu/drm/radeon/atombios_i2c.c 2014-05-29 11:49:13.528886910 +0900
@@ -44,7 +44,7 @@
PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
unsigned char *base;
- u16 out;
+ u16 out = cpu_to_le16(0);
memset(&args, 0, sizeof(args));
@@ -55,9 +55,14 @@
DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num);
return -EINVAL;
}
- args.ucRegIndex = buf[0];
- if (num > 1)
- memcpy(&out, &buf[1], num - 1);
+ if (buf == NULL)
+ args.ucRegIndex = 0;
+ else
+ args.ucRegIndex = buf[0];
+ if (num)
+ num--;
+ if (num)
+ memcpy(&out, &buf[1], num);
args.lpI2CDataOut = cpu_to_le16(out);
} else {
if (num > ATOM_MAX_HW_I2C_READ) {
@@ -94,14 +99,14 @@
struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
struct i2c_msg *p;
int i, remaining, current_count, buffer_offset, max_bytes, ret;
- u8 buf = 0, flags;
+ u8 flags;
/* check for bus probe */
p = &msgs[0];
if ((num == 1) && (p->len == 0)) {
ret = radeon_process_i2c_ch(i2c,
p->addr, HW_I2C_WRITE,
- &buf, 1);
+ NULL, 0);
if (ret)
return ret;
else
diff -Nur linux/drivers/gpu/drm/radeon/cik.c rpi/drivers/gpu/drm/radeon/cik.c
--- linux/drivers/gpu/drm/radeon/cik.c 2014-05-29 12:18:19.667546034 +0900
+++ rpi/drivers/gpu/drm/radeon/cik.c 2014-05-29 11:49:13.535886851 +0900
@@ -2608,7 +2608,7 @@
* Returns the disabled RB bitmask.
*/
static u32 cik_get_rb_disabled(struct radeon_device *rdev,
- u32 max_rb_num, u32 se_num,
+ u32 max_rb_num_per_se,
u32 sh_per_se)
{
u32 data, mask;
@@ -2622,7 +2622,7 @@
data >>= BACKEND_DISABLE_SHIFT;
- mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se);
+ mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se);
return data & mask;
}
@@ -2639,7 +2639,7 @@
*/
static void cik_setup_rb(struct radeon_device *rdev,
u32 se_num, u32 sh_per_se,
- u32 max_rb_num)
+ u32 max_rb_num_per_se)
{
int i, j;
u32 data, mask;
@@ -2649,19 +2649,21 @@
for (i = 0; i < se_num; i++) {
for (j = 0; j < sh_per_se; j++) {
cik_select_se_sh(rdev, i, j);
- data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+ data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
disabled_rbs |= data << ((i * sh_per_se + j) * CIK_RB_BITMAP_WIDTH_PER_SH);
}
}
cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
mask = 1;
- for (i = 0; i < max_rb_num; i++) {
+ for (i = 0; i < max_rb_num_per_se * se_num; i++) {
if (!(disabled_rbs & mask))
enabled_rbs |= mask;
mask <<= 1;
}
+ rdev->config.cik.backend_enable_mask = enabled_rbs;
+
for (i = 0; i < se_num; i++) {
cik_select_se_sh(rdev, i, 0xffffffff);
data = 0;
@@ -3515,8 +3517,11 @@
{
if (enable)
WREG32(CP_MEC_CNTL, 0);
- else
+ else {
WREG32(CP_MEC_CNTL, (MEC_ME1_HALT | MEC_ME2_HALT));
+ rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
+ rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
+ }
udelay(50);
}
@@ -6993,26 +6998,7 @@
cik_mc_program(rdev);
- if (rdev->flags & RADEON_IS_IGP) {
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
- !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) {
- r = cik_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
- } else {
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
- !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw ||
- !rdev->mc_fw) {
- r = cik_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
-
+ if (!(rdev->flags & RADEON_IS_IGP)) {
r = ci_mc_load_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load MC firmware!\n");
@@ -7325,6 +7311,27 @@
if (r)
return r;
+ if (rdev->flags & RADEON_IS_IGP) {
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+ !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw) {
+ r = cik_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+ } else {
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+ !rdev->mec_fw || !rdev->sdma_fw || !rdev->rlc_fw ||
+ !rdev->mc_fw) {
+ r = cik_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+ }
+
ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
ring->ring_obj = NULL;
r600_ring_init(rdev, ring, 1024 * 1024);
diff -Nur linux/drivers/gpu/drm/radeon/cik_sdma.c rpi/drivers/gpu/drm/radeon/cik_sdma.c
--- linux/drivers/gpu/drm/radeon/cik_sdma.c 2014-05-29 12:18:19.668546028 +0900
+++ rpi/drivers/gpu/drm/radeon/cik_sdma.c 2014-05-29 11:49:13.537886834 +0900
@@ -174,6 +174,8 @@
WREG32(SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl);
WREG32(SDMA0_GFX_IB_CNTL + reg_offset, 0);
}
+ rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false;
+ rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false;
}
/**
@@ -201,6 +203,11 @@
u32 me_cntl, reg_offset;
int i;
+ if (enable == false) {
+ cik_sdma_gfx_stop(rdev);
+ cik_sdma_rlc_stop(rdev);
+ }
+
for (i = 0; i < 2; i++) {
if (i == 0)
reg_offset = SDMA0_REGISTER_OFFSET;
@@ -328,10 +335,6 @@
if (!rdev->sdma_fw)
return -EINVAL;
- /* stop the gfx rings and rlc compute queues */
- cik_sdma_gfx_stop(rdev);
- cik_sdma_rlc_stop(rdev);
-
/* halt the MEs */
cik_sdma_enable(rdev, false);
@@ -400,9 +403,6 @@
*/
void cik_sdma_fini(struct radeon_device *rdev)
{
- /* stop the gfx rings and rlc compute queues */
- cik_sdma_gfx_stop(rdev);
- cik_sdma_rlc_stop(rdev);
/* halt the MEs */
cik_sdma_enable(rdev, false);
radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]);
@@ -468,7 +468,7 @@
radeon_ring_write(ring, 0); /* src/dst endian swap */
radeon_ring_write(ring, src_offset & 0xffffffff);
radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff);
- radeon_ring_write(ring, dst_offset & 0xfffffffc);
+ radeon_ring_write(ring, dst_offset & 0xffffffff);
radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff);
src_offset += cur_size_in_bytes;
dst_offset += cur_size_in_bytes;
diff -Nur linux/drivers/gpu/drm/radeon/dce6_afmt.c rpi/drivers/gpu/drm/radeon/dce6_afmt.c
--- linux/drivers/gpu/drm/radeon/dce6_afmt.c 2014-05-29 12:18:19.670546015 +0900
+++ rpi/drivers/gpu/drm/radeon/dce6_afmt.c 2014-05-29 11:49:13.542886793 +0900
@@ -132,7 +132,7 @@
}
sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
- if (sad_count < 0) {
+ if (sad_count <= 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
return;
}
@@ -193,7 +193,7 @@
}
sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
- if (sad_count < 0) {
+ if (sad_count <= 0) {
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
return;
}
@@ -226,13 +226,15 @@
return !ASIC_IS_NODCE(rdev);
}
-static void dce6_audio_enable(struct radeon_device *rdev,
- struct r600_audio_pin *pin,
- bool enable)
+void dce6_audio_enable(struct radeon_device *rdev,
+ struct r600_audio_pin *pin,
+ bool enable)
{
+ if (!pin)
+ return;
+
WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL,
- AUDIO_ENABLED);
- DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
+ enable ? AUDIO_ENABLED : 0);
}
static const u32 pin_offsets[7] =
@@ -269,7 +271,8 @@
rdev->audio.pin[i].connected = false;
rdev->audio.pin[i].offset = pin_offsets[i];
rdev->audio.pin[i].id = i;
- dce6_audio_enable(rdev, &rdev->audio.pin[i], true);
+ /* disable audio. it will be set up later */
+ dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
}
return 0;
diff -Nur linux/drivers/gpu/drm/radeon/evergreen.c rpi/drivers/gpu/drm/radeon/evergreen.c
--- linux/drivers/gpu/drm/radeon/evergreen.c 2014-05-29 12:18:19.673545996 +0900
+++ rpi/drivers/gpu/drm/radeon/evergreen.c 2014-05-29 11:49:13.544886776 +0900
@@ -4249,8 +4249,8 @@
WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
}
- /* only one DAC on DCE6 */
- if (!ASIC_IS_DCE6(rdev))
+ /* only one DAC on DCE5 */
+ if (!ASIC_IS_DCE5(rdev))
WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
WREG32(DACB_AUTODETECT_INT_CONTROL, 0);
@@ -5061,26 +5061,11 @@
evergreen_mc_program(rdev);
if (ASIC_IS_DCE5(rdev)) {
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
- r = ni_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
r = ni_mc_load_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load MC firmware!\n");
return r;
}
- } else {
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
- r = r600_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
}
if (rdev->flags & RADEON_IS_AGP) {
@@ -5308,6 +5293,24 @@
if (r)
return r;
+ if (ASIC_IS_DCE5(rdev)) {
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+ r = ni_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+ } else {
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+ r = r600_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+ }
+
rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
@@ -5369,9 +5372,9 @@
radeon_wb_fini(rdev);
radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev);
- evergreen_pcie_gart_fini(rdev);
uvd_v1_0_fini(rdev);
radeon_uvd_fini(rdev);
+ evergreen_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev);
diff -Nur linux/drivers/gpu/drm/radeon/evergreen_cs.c rpi/drivers/gpu/drm/radeon/evergreen_cs.c
--- linux/drivers/gpu/drm/radeon/evergreen_cs.c 2014-05-29 12:18:19.674545990 +0900
+++ rpi/drivers/gpu/drm/radeon/evergreen_cs.c 2014-05-29 11:49:13.546886759 +0900
@@ -967,7 +967,10 @@
if (track->cb_dirty) {
tmp = track->cb_target_mask;
for (i = 0; i < 8; i++) {
- if ((tmp >> (i * 4)) & 0xF) {
+ u32 format = G_028C70_FORMAT(track->cb_color_info[i]);
+
+ if (format != V_028C70_COLOR_INVALID &&
+ (tmp >> (i * 4)) & 0xF) {
/* at least one component is enabled */
if (track->cb_color_bo[i] == NULL) {
dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
diff -Nur linux/drivers/gpu/drm/radeon/evergreen_hdmi.c rpi/drivers/gpu/drm/radeon/evergreen_hdmi.c
--- linux/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-05-29 12:18:19.675545984 +0900
+++ rpi/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-05-29 11:49:13.546886759 +0900
@@ -81,7 +81,7 @@
}
sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
- if (sad_count < 0) {
+ if (sad_count <= 0) {
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
return;
}
@@ -134,7 +134,7 @@
}
sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
- if (sad_count < 0) {
+ if (sad_count <= 0) {
DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
return;
}
@@ -257,6 +257,15 @@
return;
offset = dig->afmt->offset;
+ /* disable audio prior to setting up hw */
+ if (ASIC_IS_DCE6(rdev)) {
+ dig->afmt->pin = dce6_audio_get_pin(rdev);
+ dce6_audio_enable(rdev, dig->afmt->pin, false);
+ } else {
+ dig->afmt->pin = r600_audio_get_pin(rdev);
+ r600_audio_enable(rdev, dig->afmt->pin, false);
+ }
+
evergreen_audio_set_dto(encoder, mode->clock);
WREG32(HDMI_VBI_PACKET_CONTROL + offset,
@@ -358,12 +367,16 @@
WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001);
WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001);
+
+ /* enable audio after to setting up hw */
+ if (ASIC_IS_DCE6(rdev))
+ dce6_audio_enable(rdev, dig->afmt->pin, true);
+ else
+ r600_audio_enable(rdev, dig->afmt->pin, true);
}
void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
{
- struct drm_device *dev = encoder->dev;
- struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
@@ -376,15 +389,6 @@
if (!enable && !dig->afmt->enabled)
return;
- if (enable) {
- if (ASIC_IS_DCE6(rdev))
- dig->afmt->pin = dce6_audio_get_pin(rdev);
- else
- dig->afmt->pin = r600_audio_get_pin(rdev);
- } else {
- dig->afmt->pin = NULL;
- }
-
dig->afmt->enabled = enable;
DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
diff -Nur linux/drivers/gpu/drm/radeon/evergreen_smc.h rpi/drivers/gpu/drm/radeon/evergreen_smc.h
--- linux/drivers/gpu/drm/radeon/evergreen_smc.h 2014-05-29 12:18:19.676545978 +0900
+++ rpi/drivers/gpu/drm/radeon/evergreen_smc.h 2014-05-29 11:49:13.547886751 +0900
@@ -57,7 +57,7 @@
#define EVERGREEN_SMC_FIRMWARE_HEADER_LOCATION 0x100
-#define EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters 0x0
+#define EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters 0x8
#define EVERGREEN_SMC_FIRMWARE_HEADER_stateTable 0xC
#define EVERGREEN_SMC_FIRMWARE_HEADER_mcRegisterTable 0x20
diff -Nur linux/drivers/gpu/drm/radeon/ni.c rpi/drivers/gpu/drm/radeon/ni.c
--- linux/drivers/gpu/drm/radeon/ni.c 2014-05-29 12:18:19.680545953 +0900
+++ rpi/drivers/gpu/drm/radeon/ni.c 2014-05-29 11:49:13.552886709 +0900
@@ -900,6 +900,10 @@
(rdev->pdev->device == 0x999C)) {
rdev->config.cayman.max_simds_per_se = 6;
rdev->config.cayman.max_backends_per_se = 2;
+ rdev->config.cayman.max_hw_contexts = 8;
+ rdev->config.cayman.sx_max_export_size = 256;
+ rdev->config.cayman.sx_max_export_pos_size = 64;
+ rdev->config.cayman.sx_max_export_smx_size = 192;
} else if ((rdev->pdev->device == 0x9903) ||
(rdev->pdev->device == 0x9904) ||
(rdev->pdev->device == 0x990A) ||
@@ -910,6 +914,10 @@
(rdev->pdev->device == 0x999D)) {
rdev->config.cayman.max_simds_per_se = 4;
rdev->config.cayman.max_backends_per_se = 2;
+ rdev->config.cayman.max_hw_contexts = 8;
+ rdev->config.cayman.sx_max_export_size = 256;
+ rdev->config.cayman.sx_max_export_pos_size = 64;
+ rdev->config.cayman.sx_max_export_smx_size = 192;
} else if ((rdev->pdev->device == 0x9919) ||
(rdev->pdev->device == 0x9990) ||
(rdev->pdev->device == 0x9991) ||
@@ -920,9 +928,17 @@
(rdev->pdev->device == 0x99A0)) {
rdev->config.cayman.max_simds_per_se = 3;
rdev->config.cayman.max_backends_per_se = 1;
+ rdev->config.cayman.max_hw_contexts = 4;
+ rdev->config.cayman.sx_max_export_size = 128;
+ rdev->config.cayman.sx_max_export_pos_size = 32;
+ rdev->config.cayman.sx_max_export_smx_size = 96;
} else {
rdev->config.cayman.max_simds_per_se = 2;
rdev->config.cayman.max_backends_per_se = 1;
+ rdev->config.cayman.max_hw_contexts = 4;
+ rdev->config.cayman.sx_max_export_size = 128;
+ rdev->config.cayman.sx_max_export_pos_size = 32;
+ rdev->config.cayman.sx_max_export_smx_size = 96;
}
rdev->config.cayman.max_texture_channel_caches = 2;
rdev->config.cayman.max_gprs = 256;
@@ -930,10 +946,6 @@
rdev->config.cayman.max_gs_threads = 32;
rdev->config.cayman.max_stack_entries = 512;
rdev->config.cayman.sx_num_of_sets = 8;
- rdev->config.cayman.sx_max_export_size = 256;
- rdev->config.cayman.sx_max_export_pos_size = 64;
- rdev->config.cayman.sx_max_export_smx_size = 192;
- rdev->config.cayman.max_hw_contexts = 8;
rdev->config.cayman.sq_num_cf_insts = 2;
rdev->config.cayman.sc_prim_fifo_size = 0x40;
@@ -1323,13 +1335,12 @@
{
struct radeon_ring *ring = &rdev->ring[fence->ring];
u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
+ u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
+ PACKET3_SH_ACTION_ENA;
/* flush read cache over gart for this vmid */
- radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
- radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
- radeon_ring_write(ring, 0);
radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
- radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA);
+ radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
radeon_ring_write(ring, 0xFFFFFFFF);
radeon_ring_write(ring, 0);
radeon_ring_write(ring, 10); /* poll interval */
@@ -1345,6 +1356,8 @@
void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
{
struct radeon_ring *ring = &rdev->ring[ib->ring];
+ u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
+ PACKET3_SH_ACTION_ENA;
/* set to DX10/11 mode */
radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
@@ -1369,14 +1382,11 @@
(ib->vm ? (ib->vm->id << 24) : 0));
/* flush read cache over gart for this vmid */
- radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
- radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
- radeon_ring_write(ring, ib->vm ? ib->vm->id : 0);
radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
- radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA);
+ radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
radeon_ring_write(ring, 0xFFFFFFFF);
radeon_ring_write(ring, 0);
- radeon_ring_write(ring, 10); /* poll interval */
+ radeon_ring_write(ring, ((ib->vm ? ib->vm->id : 0) << 24) | 10); /* poll interval */
}
static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
@@ -1871,23 +1881,7 @@
evergreen_mc_program(rdev);
- if (rdev->flags & RADEON_IS_IGP) {
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
- r = ni_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
- } else {
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
- r = ni_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
-
+ if (!(rdev->flags & RADEON_IS_IGP)) {
r = ni_mc_load_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load MC firmware!\n");
@@ -2138,6 +2132,24 @@
if (r)
return r;
+ if (rdev->flags & RADEON_IS_IGP) {
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+ r = ni_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+ } else {
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+ r = ni_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+ }
+
ring->ring_obj = NULL;
r600_ring_init(rdev, ring, 1024 * 1024);
diff -Nur linux/drivers/gpu/drm/radeon/nid.h rpi/drivers/gpu/drm/radeon/nid.h
--- linux/drivers/gpu/drm/radeon/nid.h 2014-05-29 12:18:19.682545940 +0900
+++ rpi/drivers/gpu/drm/radeon/nid.h 2014-05-29 11:49:13.557886667 +0900
@@ -1154,6 +1154,7 @@
# define PACKET3_DB_ACTION_ENA (1 << 26)
# define PACKET3_SH_ACTION_ENA (1 << 27)
# define PACKET3_SX_ACTION_ENA (1 << 28)
+# define PACKET3_ENGINE_ME (1 << 31)
#define PACKET3_ME_INITIALIZE 0x44
#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
#define PACKET3_COND_WRITE 0x45
diff -Nur linux/drivers/gpu/drm/radeon/ni_dpm.c rpi/drivers/gpu/drm/radeon/ni_dpm.c
--- linux/drivers/gpu/drm/radeon/ni_dpm.c 2014-05-29 12:18:19.682545940 +0900
+++ rpi/drivers/gpu/drm/radeon/ni_dpm.c 2014-05-29 11:49:13.556886675 +0900
@@ -2592,7 +2592,7 @@
if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
enable_sq_ramping = false;
- if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+ if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
enable_sq_ramping = false;
for (i = 0; i < state->performance_level_count; i++) {
diff -Nur linux/drivers/gpu/drm/radeon/r600_audio.c rpi/drivers/gpu/drm/radeon/r600_audio.c
--- linux/drivers/gpu/drm/radeon/r600_audio.c 2014-05-29 12:18:19.691545884 +0900
+++ rpi/drivers/gpu/drm/radeon/r600_audio.c 2014-05-29 11:49:13.569886566 +0900
@@ -142,12 +142,15 @@
}
/* enable the audio stream */
-static void r600_audio_enable(struct radeon_device *rdev,
- struct r600_audio_pin *pin,
- bool enable)
+void r600_audio_enable(struct radeon_device *rdev,
+ struct r600_audio_pin *pin,
+ bool enable)
{
u32 value = 0;
+ if (!pin)
+ return;
+
if (ASIC_IS_DCE4(rdev)) {
if (enable) {
value |= 0x81000000; /* Required to enable audio */
@@ -158,7 +161,6 @@
WREG32_P(R600_AUDIO_ENABLE,
enable ? 0x81000000 : 0x0, ~0x81000000);
}
- DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
}
/*
@@ -178,8 +180,8 @@
rdev->audio.pin[0].status_bits = 0;
rdev->audio.pin[0].category_code = 0;
rdev->audio.pin[0].id = 0;
-
- r600_audio_enable(rdev, &rdev->audio.pin[0], true);
+ /* disable audio. it will be set up later */
+ r600_audio_enable(rdev, &rdev->audio.pin[0], false);
return 0;
}
diff -Nur linux/drivers/gpu/drm/radeon/r600.c rpi/drivers/gpu/drm/radeon/r600.c
--- linux/drivers/gpu/drm/radeon/r600.c 2014-05-29 12:18:19.691545884 +0900
+++ rpi/drivers/gpu/drm/radeon/r600.c 2014-05-29 11:49:13.569886566 +0900
@@ -2554,14 +2554,17 @@
struct radeon_fence *fence)
{
struct radeon_ring *ring = &rdev->ring[fence->ring];
+ u32 cp_coher_cntl = PACKET3_TC_ACTION_ENA | PACKET3_VC_ACTION_ENA |
+ PACKET3_SH_ACTION_ENA;
+
+ if (rdev->family >= CHIP_RV770)
+ cp_coher_cntl |= PACKET3_FULL_CACHE_ENA;
if (rdev->wb.use_event) {
u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
/* flush read cache over gart */
radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
- radeon_ring_write(ring, PACKET3_TC_ACTION_ENA |
- PACKET3_VC_ACTION_ENA |
- PACKET3_SH_ACTION_ENA);
+ radeon_ring_write(ring, cp_coher_cntl);
radeon_ring_write(ring, 0xFFFFFFFF);
radeon_ring_write(ring, 0);
radeon_ring_write(ring, 10); /* poll interval */
@@ -2575,9 +2578,7 @@
} else {
/* flush read cache over gart */
radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
- radeon_ring_write(ring, PACKET3_TC_ACTION_ENA |
- PACKET3_VC_ACTION_ENA |
- PACKET3_SH_ACTION_ENA);
+ radeon_ring_write(ring, cp_coher_cntl);
radeon_ring_write(ring, 0xFFFFFFFF);
radeon_ring_write(ring, 0);
radeon_ring_write(ring, 10); /* poll interval */
@@ -2725,14 +2726,6 @@
r600_mc_program(rdev);
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
- r = r600_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
-
if (rdev->flags & RADEON_IS_AGP) {
r600_agp_enable(rdev);
} else {
@@ -2920,6 +2913,14 @@
if (r)
return r;
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+ r = r600_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+
rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
@@ -3853,6 +3854,10 @@
break;
}
break;
+ case 124: /* UVD */
+ DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data);
+ radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX);
+ break;
case 176: /* CP_INT in ring buffer */
case 177: /* CP_INT in IB1 */
case 178: /* CP_INT in IB2 */
diff -Nur linux/drivers/gpu/drm/radeon/r600_cs.c rpi/drivers/gpu/drm/radeon/r600_cs.c
--- linux/drivers/gpu/drm/radeon/r600_cs.c 2014-05-29 12:18:19.694545865 +0900
+++ rpi/drivers/gpu/drm/radeon/r600_cs.c 2014-05-29 11:49:13.573886533 +0900
@@ -749,7 +749,10 @@
}
for (i = 0; i < 8; i++) {
- if ((tmp >> (i * 4)) & 0xF) {
+ u32 format = G_0280A0_FORMAT(track->cb_color_info[i]);
+
+ if (format != V_0280A0_COLOR_INVALID &&
+ (tmp >> (i * 4)) & 0xF) {
/* at least one component is enabled */
if (track->cb_color_bo[i] == NULL) {
dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
diff -Nur linux/drivers/gpu/drm/radeon/r600d.h rpi/drivers/gpu/drm/radeon/r600d.h
--- linux/drivers/gpu/drm/radeon/r600d.h 2014-05-29 12:18:19.698545840 +0900
+++ rpi/drivers/gpu/drm/radeon/r600d.h 2014-05-29 11:49:13.577886499 +0900
@@ -1547,6 +1547,7 @@
# define PACKET3_CP_DMA_CMD_DAIC (1 << 29)
#define PACKET3_SURFACE_SYNC 0x43
# define PACKET3_CB0_DEST_BASE_ENA (1 << 6)
+# define PACKET3_FULL_CACHE_ENA (1 << 20) /* r7xx+ only */
# define PACKET3_TC_ACTION_ENA (1 << 23)
# define PACKET3_VC_ACTION_ENA (1 << 24)
# define PACKET3_CB_ACTION_ENA (1 << 25)
diff -Nur linux/drivers/gpu/drm/radeon/r600_hdmi.c rpi/drivers/gpu/drm/radeon/r600_hdmi.c
--- linux/drivers/gpu/drm/radeon/r600_hdmi.c 2014-05-29 12:18:19.696545853 +0900
+++ rpi/drivers/gpu/drm/radeon/r600_hdmi.c 2014-05-29 11:49:13.575886516 +0900
@@ -24,6 +24,7 @@
* Authors: Christian König
*/
#include <linux/hdmi.h>
+#include <linux/gcd.h>
#include <drm/drmP.h>
#include <drm/radeon_drm.h>
#include "radeon.h"
@@ -57,35 +58,57 @@
static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
/* 32kHz 44.1kHz 48kHz */
/* Clock N CTS N CTS N CTS */
- { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */
+ { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */
{ 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */
{ 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */
{ 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */
{ 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */
{ 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */
- { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */
+ { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */
{ 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */
- { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */
+ { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */
{ 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */
- { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */
};
+
/*
- * calculate CTS value if it's not found in the table
+ * calculate CTS and N values if they are not found in the table
*/
-static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq)
+static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq)
{
- u64 n;
- u32 d;
+ int n, cts;
+ unsigned long div, mul;
- if (*CTS == 0) {
- n = (u64)clock * (u64)N * 1000ULL;
- d = 128 * freq;
- do_div(n, d);
- *CTS = n;
- }
- DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
- N, *CTS, freq);
+ /* Safe, but overly large values */
+ n = 128 * freq;
+ cts = clock * 1000;
+
+ /* Smallest valid fraction */
+ div = gcd(n, cts);
+
+ n /= div;
+ cts /= div;
+
+ /*
+ * The optimal N is 128*freq/1000. Calculate the closest larger
+ * value that doesn't truncate any bits.
+ */
+ mul = ((128*freq/1000) + (n-1))/n;
+
+ n *= mul;
+ cts *= mul;
+
+ /* Check that we are in spec (not always possible) */
+ if (n < (128*freq/1500))
+ printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n");
+ if (n > (128*freq/300))
+ printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n");
+
+ *N = n;
+ *CTS = cts;
+
+ DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
+ *N, *CTS, freq);
}
struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
@@ -93,15 +116,16 @@
struct radeon_hdmi_acr res;
u8 i;
- for (i = 0; r600_hdmi_predefined_acr[i].clock != clock &&
- r600_hdmi_predefined_acr[i].clock != 0; i++)
- ;
- res = r600_hdmi_predefined_acr[i];
-
- /* In case some CTS are missing */
- r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000);
- r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100);
- r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000);
+ /* Precalculated values for common clocks */
+ for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) {
+ if (r600_hdmi_predefined_acr[i].clock == clock)
+ return r600_hdmi_predefined_acr[i];
+ }
+
+ /* And odd clocks get manually calculated */
+ r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
+ r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
+ r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
return res;
}
@@ -280,9 +304,9 @@
WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
}
- } else if (ASIC_IS_DCE3(rdev)) {
+ } else {
/* according to the reg specs, this should DCE3.2 only, but in
- * practice it seems to cover DCE3.0/3.1 as well.
+ * practice it seems to cover DCE2.0/3.0/3.1 as well.
*/
if (dig->dig_encoder == 0) {
WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
@@ -293,10 +317,6 @@
WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
}
- } else {
- /* according to the reg specs, this should be DCE2.0 and DCE3.0/3.1 */
- WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
- AUDIO_DTO_MODULE(clock / 10));
}
}
@@ -309,9 +329,6 @@
u8 *sadb;
int sad_count;
- /* XXX: setting this register causes hangs on some asics */
- return;
-
list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
if (connector->encoder == encoder)
radeon_connector = to_radeon_connector(connector);
@@ -426,6 +443,10 @@
return;
offset = dig->afmt->offset;
+ /* disable audio prior to setting up hw */
+ dig->afmt->pin = r600_audio_get_pin(rdev);
+ r600_audio_enable(rdev, dig->afmt->pin, false);
+
r600_audio_set_dto(encoder, mode->clock);
WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
@@ -497,6 +518,9 @@
WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
r600_hdmi_audio_workaround(encoder);
+
+ /* enable audio after to setting up hw */
+ r600_audio_enable(rdev, dig->afmt->pin, true);
}
/*
@@ -617,11 +641,6 @@
if (!enable && !dig->afmt->enabled)
return;
- if (enable)
- dig->afmt->pin = r600_audio_get_pin(rdev);
- else
- dig->afmt->pin = NULL;
-
/* Older chipsets require setting HDMI and routing manually */
if (!ASIC_IS_DCE3(rdev)) {
if (enable)
diff -Nur linux/drivers/gpu/drm/radeon/radeon_asic.c rpi/drivers/gpu/drm/radeon/radeon_asic.c
--- linux/drivers/gpu/drm/radeon/radeon_asic.c 2014-05-29 12:18:19.701545821 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_asic.c 2014-05-29 11:49:13.581886466 +0900
@@ -2019,6 +2019,8 @@
.bandwidth_update = &dce8_bandwidth_update,
.get_vblank_counter = &evergreen_get_vblank_counter,
.wait_for_vblank = &dce4_wait_for_vblank,
+ .set_backlight_level = &atombios_set_backlight_level,
+ .get_backlight_level = &atombios_get_backlight_level,
.hdmi_enable = &evergreen_hdmi_enable,
.hdmi_setmode = &evergreen_hdmi_setmode,
},
@@ -2119,6 +2121,8 @@
.bandwidth_update = &dce8_bandwidth_update,
.get_vblank_counter = &evergreen_get_vblank_counter,
.wait_for_vblank = &dce4_wait_for_vblank,
+ .set_backlight_level = &atombios_set_backlight_level,
+ .get_backlight_level = &atombios_get_backlight_level,
.hdmi_enable = &evergreen_hdmi_enable,
.hdmi_setmode = &evergreen_hdmi_setmode,
},
diff -Nur linux/drivers/gpu/drm/radeon/radeon_atombios.c rpi/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux/drivers/gpu/drm/radeon/radeon_atombios.c 2014-05-29 12:18:19.703545809 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_atombios.c 2014-05-29 11:49:13.584886441 +0900
@@ -2918,7 +2918,7 @@
mpll_param->dll_speed = args.ucDllSpeed;
mpll_param->bwcntl = args.ucBWCntl;
mpll_param->vco_mode =
- (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK) ? 1 : 0;
+ (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK);
mpll_param->yclk_sel =
(args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0;
mpll_param->qdr =
@@ -3944,6 +3944,10 @@
/* tell the bios not to handle mode switching */
bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
+ /* clear the vbios dpms state */
+ if (ASIC_IS_DCE4(rdev))
+ bios_2_scratch &= ~ATOM_S2_DEVICE_DPMS_STATE;
+
if (rdev->family >= CHIP_R600) {
WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch);
WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch);
diff -Nur linux/drivers/gpu/drm/radeon/radeon_atpx_handler.c rpi/drivers/gpu/drm/radeon/radeon_atpx_handler.c
--- linux/drivers/gpu/drm/radeon/radeon_atpx_handler.c 2014-05-29 12:18:19.704545802 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_atpx_handler.c 2014-05-29 11:49:13.584886441 +0900
@@ -34,6 +34,7 @@
bool atpx_detected;
/* handle for device - and atpx */
acpi_handle dhandle;
+ acpi_handle other_handle;
struct radeon_atpx atpx;
} radeon_atpx_priv;
@@ -215,7 +216,8 @@
memcpy(&output, info->buffer.pointer, size);
/* TODO: check version? */
- printk("ATPX version %u\n", output.version);
+ printk("ATPX version %u, functions 0x%08x\n",
+ output.version, output.function_bits);
radeon_atpx_parse_functions(&atpx->functions, output.function_bits);
@@ -448,9 +450,10 @@
return false;
status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status)) {
+ radeon_atpx_priv.other_handle = dhandle;
return false;
-
+ }
radeon_atpx_priv.dhandle = dhandle;
radeon_atpx_priv.atpx.handle = atpx_handle;
return true;
@@ -527,6 +530,16 @@
printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
acpi_method_name);
radeon_atpx_priv.atpx_detected = true;
+ /*
+ * On some systems hotplug events are generated for the device
+ * being switched off when ATPX is executed. They cause ACPI
+ * hotplug to trigger and attempt to remove the device from
+ * the system, which causes it to break down. Prevent that from
+ * happening by setting the no_hotplug flag for the involved
+ * ACPI device objects.
+ */
+ acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
+ acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
return true;
}
return false;
diff -Nur linux/drivers/gpu/drm/radeon/radeon_gart.c rpi/drivers/gpu/drm/radeon/radeon_gart.c
--- linux/drivers/gpu/drm/radeon/radeon_gart.c 2014-05-29 12:18:19.715545734 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_gart.c 2014-05-29 11:49:13.596886340 +0900
@@ -1156,6 +1156,8 @@
return -ENOMEM;
r = radeon_ib_get(rdev, ridx, &ib, NULL, ndw * 4);
+ if (r)
+ return r;
ib.length_dw = 0;
r = radeon_vm_update_pdes(rdev, vm, &ib, bo_va->soffset, bo_va->eoffset);
diff -Nur linux/drivers/gpu/drm/radeon/radeon.h rpi/drivers/gpu/drm/radeon/radeon.h
--- linux/drivers/gpu/drm/radeon/radeon.h 2014-05-29 12:18:19.699545834 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon.h 2014-05-29 11:49:13.578886491 +0900
@@ -1930,7 +1930,7 @@
unsigned sc_earlyz_tile_fifo_size;
unsigned num_tile_pipes;
- unsigned num_backends_per_se;
+ unsigned backend_enable_mask;
unsigned backend_disable_mask_per_asic;
unsigned backend_map;
unsigned num_texture_channel_caches;
@@ -1960,7 +1960,7 @@
unsigned sc_earlyz_tile_fifo_size;
unsigned num_tile_pipes;
- unsigned num_backends_per_se;
+ unsigned backend_enable_mask;
unsigned backend_disable_mask_per_asic;
unsigned backend_map;
unsigned num_texture_channel_caches;
@@ -2717,6 +2717,12 @@
void r600_audio_update_hdmi(struct work_struct *work);
struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev);
struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev);
+void r600_audio_enable(struct radeon_device *rdev,
+ struct r600_audio_pin *pin,
+ bool enable);
+void dce6_audio_enable(struct radeon_device *rdev,
+ struct r600_audio_pin *pin,
+ bool enable);
/*
* R600 vram scratch functions
diff -Nur linux/drivers/gpu/drm/radeon/radeon_i2c.c rpi/drivers/gpu/drm/radeon/radeon_i2c.c
--- linux/drivers/gpu/drm/radeon/radeon_i2c.c 2014-05-29 12:18:19.716545727 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_i2c.c 2014-05-29 11:49:13.597886332 +0900
@@ -1020,6 +1020,9 @@
/* Add the default buses */
void radeon_i2c_init(struct radeon_device *rdev)
{
+ if (radeon_hw_i2c)
+ DRM_INFO("hw_i2c forced on, you may experience display detection problems!\n");
+
if (rdev->is_atom_bios)
radeon_atombios_i2c_init(rdev);
else
diff -Nur linux/drivers/gpu/drm/radeon/radeon_kms.c rpi/drivers/gpu/drm/radeon/radeon_kms.c
--- linux/drivers/gpu/drm/radeon/radeon_kms.c 2014-05-29 12:18:19.718545715 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_kms.c 2014-05-29 11:49:13.598886323 +0900
@@ -436,6 +436,15 @@
case RADEON_INFO_SI_CP_DMA_COMPUTE:
*value = 1;
break;
+ case RADEON_INFO_SI_BACKEND_ENABLED_MASK:
+ if (rdev->family >= CHIP_BONAIRE) {
+ *value = rdev->config.cik.backend_enable_mask;
+ } else if (rdev->family >= CHIP_TAHITI) {
+ *value = rdev->config.si.backend_enable_mask;
+ } else {
+ DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
+ }
+ break;
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->request);
return -EINVAL;
@@ -491,6 +500,10 @@
radeon_vm_init(rdev, &fpriv->vm);
+ r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+ if (r)
+ return r;
+
/* map the ib pool buffer read only into
* virtual address space */
bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
@@ -498,6 +511,8 @@
r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
RADEON_VM_PAGE_READABLE |
RADEON_VM_PAGE_SNOOPED);
+
+ radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
if (r) {
radeon_vm_fini(rdev, &fpriv->vm);
kfree(fpriv);
diff -Nur linux/drivers/gpu/drm/radeon/radeon_legacy_crtc.c rpi/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
--- linux/drivers/gpu/drm/radeon/radeon_legacy_crtc.c 2014-05-29 12:18:19.719545709 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_legacy_crtc.c 2014-05-29 11:49:13.599886315 +0900
@@ -422,6 +422,7 @@
/* Pin framebuffer & get tilling informations */
obj = radeon_fb->obj;
rbo = gem_to_radeon_bo(obj);
+retry:
r = radeon_bo_reserve(rbo, false);
if (unlikely(r != 0))
return r;
@@ -430,6 +431,33 @@
&base);
if (unlikely(r != 0)) {
radeon_bo_unreserve(rbo);
+
+ /* On old GPU like RN50 with little vram pining can fails because
+ * current fb is taking all space needed. So instead of unpining
+ * the old buffer after pining the new one, first unpin old one
+ * and then retry pining new one.
+ *
+ * As only master can set mode only master can pin and it is
+ * unlikely the master client will race with itself especialy
+ * on those old gpu with single crtc.
+ *
+ * We don't shutdown the display controller because new buffer
+ * will end up in same spot.
+ */
+ if (!atomic && fb && fb != crtc->fb) {
+ struct radeon_bo *old_rbo;
+ unsigned long nsize, osize;
+
+ old_rbo = gem_to_radeon_bo(to_radeon_framebuffer(fb)->obj);
+ osize = radeon_bo_size(old_rbo);
+ nsize = radeon_bo_size(rbo);
+ if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) {
+ radeon_bo_unpin(old_rbo);
+ radeon_bo_unreserve(old_rbo);
+ fb = NULL;
+ goto retry;
+ }
+ }
return -EINVAL;
}
radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
diff -Nur linux/drivers/gpu/drm/radeon/radeon_pm.c rpi/drivers/gpu/drm/radeon/radeon_pm.c
--- linux/drivers/gpu/drm/radeon/radeon_pm.c 2014-05-29 12:18:19.724545677 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_pm.c 2014-05-29 11:49:13.602886290 +0900
@@ -1024,8 +1024,10 @@
rdev->pm.current_clock_mode_index = 0;
rdev->pm.current_sclk = rdev->pm.default_sclk;
rdev->pm.current_mclk = rdev->pm.default_mclk;
- rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
- rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
+ if (rdev->pm.power_state) {
+ rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+ rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
+ }
if (rdev->pm.pm_method == PM_METHOD_DYNPM
&& rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
diff -Nur linux/drivers/gpu/drm/radeon/radeon_ttm.c rpi/drivers/gpu/drm/radeon/radeon_ttm.c
--- linux/drivers/gpu/drm/radeon/radeon_ttm.c 2014-05-29 12:18:19.729545646 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_ttm.c 2014-05-29 11:49:13.609886231 +0900
@@ -712,6 +712,9 @@
DRM_ERROR("Failed initializing VRAM heap.\n");
return r;
}
+ /* Change the size here instead of the init above so only lpfn is affected */
+ radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+
r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true,
RADEON_GEM_DOMAIN_VRAM,
NULL, &rdev->stollen_vga_memory);
diff -Nur linux/drivers/gpu/drm/radeon/radeon_uvd.c rpi/drivers/gpu/drm/radeon/radeon_uvd.c
--- linux/drivers/gpu/drm/radeon/radeon_uvd.c 2014-05-29 12:18:19.730545640 +0900
+++ rpi/drivers/gpu/drm/radeon/radeon_uvd.c 2014-05-29 11:49:13.609886231 +0900
@@ -91,6 +91,7 @@
case CHIP_VERDE:
case CHIP_PITCAIRN:
case CHIP_ARUBA:
+ case CHIP_OLAND:
fw_name = FIRMWARE_TAHITI;
break;
@@ -169,6 +170,8 @@
radeon_bo_unref(&rdev->uvd.vcpu_bo);
+ radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX]);
+
release_firmware(rdev->uvd_fw);
}
@@ -240,6 +243,8 @@
if (handle != 0 && rdev->uvd.filp[i] == filp) {
struct radeon_fence *fence;
+ radeon_uvd_note_usage(rdev);
+
r = radeon_uvd_get_destroy_msg(rdev,
R600_RING_TYPE_UVD_INDEX, handle, &fence);
if (r) {
@@ -470,7 +475,7 @@
return -EINVAL;
}
- if ((start >> 28) != (end >> 28)) {
+ if ((start >> 28) != ((end - 1) >> 28)) {
DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
start, end);
return -EINVAL;
@@ -620,7 +625,7 @@
if (r)
goto err;
- r = radeon_ib_get(rdev, ring, &ib, NULL, 16);
+ r = radeon_ib_get(rdev, ring, &ib, NULL, 64);
if (r)
goto err;
diff -Nur linux/drivers/gpu/drm/radeon/rs690.c rpi/drivers/gpu/drm/radeon/rs690.c
--- linux/drivers/gpu/drm/radeon/rs690.c 2014-05-29 12:18:19.734545615 +0900
+++ rpi/drivers/gpu/drm/radeon/rs690.c 2014-05-29 11:49:13.614886189 +0900
@@ -162,6 +162,16 @@
base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
base = G_000100_MC_FB_START(base) << 16;
rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+ /* Some boards seem to be configured for 128MB of sideport memory,
+ * but really only have 64MB. Just skip the sideport and use
+ * UMA memory.
+ */
+ if (rdev->mc.igp_sideport_enabled &&
+ (rdev->mc.real_vram_size == (384 * 1024 * 1024))) {
+ base += 128 * 1024 * 1024;
+ rdev->mc.real_vram_size -= 128 * 1024 * 1024;
+ rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+ }
/* Use K8 direct mapping for fast fb access. */
rdev->fastfb_working = false;
diff -Nur linux/drivers/gpu/drm/radeon/rv770.c rpi/drivers/gpu/drm/radeon/rv770.c
--- linux/drivers/gpu/drm/radeon/rv770.c 2014-05-29 12:18:19.737545596 +0900
+++ rpi/drivers/gpu/drm/radeon/rv770.c 2014-05-29 11:49:13.622886122 +0900
@@ -1665,14 +1665,6 @@
rv770_mc_program(rdev);
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
- r = r600_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
-
if (rdev->flags & RADEON_IS_AGP) {
rv770_agp_enable(rdev);
} else {
@@ -1876,6 +1868,14 @@
if (r)
return r;
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+ r = r600_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+
rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
@@ -1921,9 +1921,9 @@
radeon_wb_fini(rdev);
radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev);
- rv770_pcie_gart_fini(rdev);
uvd_v1_0_fini(rdev);
radeon_uvd_fini(rdev);
+ rv770_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev);
diff -Nur linux/drivers/gpu/drm/radeon/rv770_dpm.c rpi/drivers/gpu/drm/radeon/rv770_dpm.c
--- linux/drivers/gpu/drm/radeon/rv770_dpm.c 2014-05-29 12:18:19.738545590 +0900
+++ rpi/drivers/gpu/drm/radeon/rv770_dpm.c 2014-05-29 11:49:13.622886122 +0900
@@ -2328,6 +2328,12 @@
pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
ASIC_INTERNAL_MEMORY_SS, 0);
+ /* disable ss, causes hangs on some cayman boards */
+ if (rdev->family == CHIP_CAYMAN) {
+ pi->sclk_ss = false;
+ pi->mclk_ss = false;
+ }
+
if (pi->sclk_ss || pi->mclk_ss)
pi->dynamic_ss = true;
else
@@ -2525,6 +2531,12 @@
(rdev->pdev->subsystem_device == 0x1c42))
switch_limit = 200;
+ /* RV770 */
+ /* mclk switching doesn't seem to work reliably on desktop RV770s */
+ if ((rdev->family == CHIP_RV770) &&
+ !(rdev->flags & RADEON_IS_MOBILITY))
+ switch_limit = 0xffffffff; /* disable mclk switching */
+
if (vblank_time < switch_limit)
return true;
else
diff -Nur linux/drivers/gpu/drm/radeon/si.c rpi/drivers/gpu/drm/radeon/si.c
--- linux/drivers/gpu/drm/radeon/si.c 2014-05-29 12:18:19.742545565 +0900
+++ rpi/drivers/gpu/drm/radeon/si.c 2014-05-29 11:49:13.626886089 +0900
@@ -2816,7 +2816,7 @@
}
static u32 si_get_rb_disabled(struct radeon_device *rdev,
- u32 max_rb_num, u32 se_num,
+ u32 max_rb_num_per_se,
u32 sh_per_se)
{
u32 data, mask;
@@ -2830,14 +2830,14 @@
data >>= BACKEND_DISABLE_SHIFT;
- mask = si_create_bitmask(max_rb_num / se_num / sh_per_se);
+ mask = si_create_bitmask(max_rb_num_per_se / sh_per_se);
return data & mask;
}
static void si_setup_rb(struct radeon_device *rdev,
u32 se_num, u32 sh_per_se,
- u32 max_rb_num)
+ u32 max_rb_num_per_se)
{
int i, j;
u32 data, mask;
@@ -2847,19 +2847,21 @@
for (i = 0; i < se_num; i++) {
for (j = 0; j < sh_per_se; j++) {
si_select_se_sh(rdev, i, j);
- data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
+ data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
}
}
si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
mask = 1;
- for (i = 0; i < max_rb_num; i++) {
+ for (i = 0; i < max_rb_num_per_se * se_num; i++) {
if (!(disabled_rbs & mask))
enabled_rbs |= mask;
mask <<= 1;
}
+ rdev->config.si.backend_enable_mask = enabled_rbs;
+
for (i = 0; i < se_num; i++) {
si_select_se_sh(rdev, i, 0xffffffff);
data = 0;
@@ -3887,8 +3889,15 @@
rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
/* size in MB on si */
- rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
- rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+ tmp = RREG32(CONFIG_MEMSIZE);
+ /* some boards may have garbage in the upper 16 bits */
+ if (tmp & 0xffff0000) {
+ DRM_INFO("Probable bad vram size: 0x%08x\n", tmp);
+ if (tmp & 0xffff)
+ tmp &= 0xffff;
+ }
+ rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL;
+ rdev->mc.real_vram_size = rdev->mc.mc_vram_size;
rdev->mc.visible_vram_size = rdev->mc.aper_size;
si_vram_gtt_location(rdev, &rdev->mc);
radeon_update_bandwidth_info(rdev);
@@ -5616,7 +5625,7 @@
}
if (!ASIC_IS_NODCE(rdev)) {
- WREG32(DACA_AUTODETECT_INT_CONTROL, 0);
+ WREG32(DAC_AUTODETECT_INT_CONTROL, 0);
tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY;
WREG32(DC_HPD1_INT_CONTROL, tmp);
@@ -6272,6 +6281,10 @@
break;
}
break;
+ case 124: /* UVD */
+ DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data);
+ radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX);
+ break;
case 146:
case 147:
addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR);
@@ -6374,15 +6387,6 @@
si_mc_program(rdev);
- if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
- !rdev->rlc_fw || !rdev->mc_fw) {
- r = si_init_microcode(rdev);
- if (r) {
- DRM_ERROR("Failed to load firmware!\n");
- return r;
- }
- }
-
r = si_mc_load_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load MC firmware!\n");
@@ -6650,6 +6654,15 @@
if (r)
return r;
+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
+ !rdev->rlc_fw || !rdev->mc_fw) {
+ r = si_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+
ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
ring->ring_obj = NULL;
r600_ring_init(rdev, ring, 1024 * 1024);
diff -Nur linux/drivers/gpu/drm/radeon/sid.h rpi/drivers/gpu/drm/radeon/sid.h
--- linux/drivers/gpu/drm/radeon/sid.h 2014-05-29 12:18:19.746545540 +0900
+++ rpi/drivers/gpu/drm/radeon/sid.h 2014-05-29 11:49:13.629886064 +0900
@@ -478,7 +478,7 @@
#define STATE3_MASK (0x1f << 15)
#define STATE3_SHIFT 15
-#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x2808
+#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x28e8
#define TRAIN_DONE_D0 (1 << 30)
#define TRAIN_DONE_D1 (1 << 31)
@@ -770,7 +770,7 @@
# define GRPH_PFLIP_INT_MASK (1 << 0)
# define GRPH_PFLIP_INT_TYPE (1 << 8)
-#define DACA_AUTODETECT_INT_CONTROL 0x66c8
+#define DAC_AUTODETECT_INT_CONTROL 0x67c8
#define DC_HPD1_INT_STATUS 0x601c
#define DC_HPD2_INT_STATUS 0x6028
diff -Nur linux/drivers/gpu/drm/radeon/si_dpm.c rpi/drivers/gpu/drm/radeon/si_dpm.c
--- linux/drivers/gpu/drm/radeon/si_dpm.c 2014-05-29 12:18:19.745545546 +0900
+++ rpi/drivers/gpu/drm/radeon/si_dpm.c 2014-05-29 11:49:13.627886081 +0900
@@ -2396,7 +2396,7 @@
if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
enable_sq_ramping = false;
- if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO <= (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
+ if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
enable_sq_ramping = false;
for (i = 0; i < state->performance_level_count; i++) {
@@ -5409,7 +5409,7 @@
for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) {
if (si_pi->mc_reg_table.valid_flag & (1 << j)) {
- if (i >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
+ if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
break;
mc_reg_table->address[i].s0 =
cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0);
diff -Nur linux/drivers/gpu/drm/radeon/trinity_dpm.c rpi/drivers/gpu/drm/radeon/trinity_dpm.c
--- linux/drivers/gpu/drm/radeon/trinity_dpm.c 2014-05-29 12:18:19.749545521 +0900
+++ rpi/drivers/gpu/drm/radeon/trinity_dpm.c 2014-05-29 11:49:13.632886039 +0900
@@ -1873,9 +1873,9 @@
pi->enable_sclk_ds = true;
pi->enable_gfx_power_gating = true;
pi->enable_gfx_clock_gating = true;
- pi->enable_mg_clock_gating = true;
- pi->enable_gfx_dynamic_mgpg = true; /* ??? */
- pi->override_dynamic_mgpg = true;
+ pi->enable_mg_clock_gating = false;
+ pi->enable_gfx_dynamic_mgpg = false;
+ pi->override_dynamic_mgpg = false;
pi->enable_auto_thermal_throttling = true;
pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
pi->uvd_dpm = true; /* ??? */
diff -Nur linux/drivers/gpu/drm/radeon/uvd_v2_2.c rpi/drivers/gpu/drm/radeon/uvd_v2_2.c
--- linux/drivers/gpu/drm/radeon/uvd_v2_2.c 2014-05-29 12:18:19.750545515 +0900
+++ rpi/drivers/gpu/drm/radeon/uvd_v2_2.c 2014-05-29 11:49:13.633886030 +0900
@@ -153,6 +153,7 @@
chip_id = 0x01000015;
break;
case CHIP_PITCAIRN:
+ case CHIP_OLAND:
chip_id = 0x01000016;
break;
case CHIP_ARUBA:
diff -Nur linux/drivers/gpu/drm/rcar-du/rcar_du_crtc.c rpi/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
--- linux/drivers/gpu/drm/rcar-du/rcar_du_crtc.c 2014-05-29 12:18:19.751545508 +0900
+++ rpi/drivers/gpu/drm/rcar-du/rcar_du_crtc.c 2014-05-29 11:49:13.635886014 +0900
@@ -371,7 +371,6 @@
goto error;
rcrtc->plane->format = format;
- rcrtc->plane->pitch = crtc->fb->pitches[0];
rcrtc->plane->src_x = x;
rcrtc->plane->src_y = y;
diff -Nur linux/drivers/gpu/drm/rcar-du/rcar_du_plane.c rpi/drivers/gpu/drm/rcar-du/rcar_du_plane.c
--- linux/drivers/gpu/drm/rcar-du/rcar_du_plane.c 2014-05-29 12:18:19.753545496 +0900
+++ rpi/drivers/gpu/drm/rcar-du/rcar_du_plane.c 2014-05-29 11:49:13.638885988 +0900
@@ -104,6 +104,15 @@
{
struct rcar_du_group *rgrp = plane->group;
unsigned int index = plane->hwindex;
+ u32 mwr;
+
+ /* Memory pitch (expressed in pixels) */
+ if (plane->format->planes == 2)
+ mwr = plane->pitch;
+ else
+ mwr = plane->pitch * 8 / plane->format->bpp;
+
+ rcar_du_plane_write(rgrp, index, PnMWR, mwr);
/* The Y position is expressed in raster line units and must be doubled
* for 32bpp formats, according to the R8A7790 datasheet. No mention of
@@ -133,6 +142,8 @@
{
struct drm_gem_cma_object *gem;
+ plane->pitch = fb->pitches[0];
+
gem = drm_fb_cma_get_gem_obj(fb, 0);
plane->dma[0] = gem->paddr + fb->offsets[0];
@@ -209,7 +220,6 @@
struct rcar_du_group *rgrp = plane->group;
u32 ddcr2 = PnDDCR2_CODE;
u32 ddcr4;
- u32 mwr;
/* Data format
*
@@ -240,14 +250,6 @@
rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
- /* Memory pitch (expressed in pixels) */
- if (plane->format->planes == 2)
- mwr = plane->pitch;
- else
- mwr = plane->pitch * 8 / plane->format->bpp;
-
- rcar_du_plane_write(rgrp, index, PnMWR, mwr);
-
/* Destination position and size */
rcar_du_plane_write(rgrp, index, PnDSXR, plane->width);
rcar_du_plane_write(rgrp, index, PnDSYR, plane->height);
@@ -309,7 +311,6 @@
rplane->crtc = crtc;
rplane->format = format;
- rplane->pitch = fb->pitches[0];
rplane->src_x = src_x >> 16;
rplane->src_y = src_y >> 16;
diff -Nur linux/drivers/gpu/drm/shmobile/Kconfig rpi/drivers/gpu/drm/shmobile/Kconfig
--- linux/drivers/gpu/drm/shmobile/Kconfig 2014-05-29 12:18:19.755545483 +0900
+++ rpi/drivers/gpu/drm/shmobile/Kconfig 2014-05-29 11:49:13.641885963 +0900
@@ -1,6 +1,7 @@
config DRM_SHMOBILE
tristate "DRM Support for SH Mobile"
depends on DRM && (ARM || SUPERH)
+ select BACKLIGHT_CLASS_DEVICE
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
diff -Nur linux/drivers/gpu/drm/ttm/ttm_bo.c rpi/drivers/gpu/drm/ttm/ttm_bo.c
--- linux/drivers/gpu/drm/ttm/ttm_bo.c 2014-05-29 12:18:19.760545452 +0900
+++ rpi/drivers/gpu/drm/ttm/ttm_bo.c 2014-05-29 11:49:13.650885888 +0900
@@ -351,9 +351,11 @@
moved:
if (bo->evicted) {
- ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement);
- if (ret)
- pr_err("Can not flush read caches\n");
+ if (bdev->driver->invalidate_caches) {
+ ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement);
+ if (ret)
+ pr_err("Can not flush read caches\n");
+ }
bo->evicted = false;
}
@@ -986,24 +988,32 @@
return ret;
}
-static int ttm_bo_mem_compat(struct ttm_placement *placement,
- struct ttm_mem_reg *mem)
+static bool ttm_bo_mem_compat(struct ttm_placement *placement,
+ struct ttm_mem_reg *mem,
+ uint32_t *new_flags)
{
int i;
if (mem->mm_node && placement->lpfn != 0 &&
(mem->start < placement->fpfn ||
mem->start + mem->num_pages > placement->lpfn))
- return -1;
+ return false;
for (i = 0; i < placement->num_placement; i++) {
- if ((placement->placement[i] & mem->placement &
- TTM_PL_MASK_CACHING) &&
- (placement->placement[i] & mem->placement &
- TTM_PL_MASK_MEM))
- return i;
+ *new_flags = placement->placement[i];
+ if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
+ (*new_flags & mem->placement & TTM_PL_MASK_MEM))
+ return true;
}
- return -1;
+
+ for (i = 0; i < placement->num_busy_placement; i++) {
+ *new_flags = placement->busy_placement[i];
+ if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
+ (*new_flags & mem->placement & TTM_PL_MASK_MEM))
+ return true;
+ }
+
+ return false;
}
int ttm_bo_validate(struct ttm_buffer_object *bo,
@@ -1012,6 +1022,7 @@
bool no_wait_gpu)
{
int ret;
+ uint32_t new_flags;
lockdep_assert_held(&bo->resv->lock.base);
/* Check that range is valid */
@@ -1022,8 +1033,7 @@
/*
* Check whether we need to move buffer.
*/
- ret = ttm_bo_mem_compat(placement, &bo->mem);
- if (ret < 0) {
+ if (!ttm_bo_mem_compat(placement, &bo->mem, &new_flags)) {
ret = ttm_bo_move_buffer(bo, placement, interruptible,
no_wait_gpu);
if (ret)
@@ -1033,7 +1043,7 @@
* Use the access and other non-mapping-related flag bits from
* the compatible memory placement flags to the active flags
*/
- ttm_flag_masked(&bo->mem.placement, placement->placement[ret],
+ ttm_flag_masked(&bo->mem.placement, new_flags,
~TTM_PL_MASK_MEMTYPE);
}
/*
diff -Nur linux/drivers/gpu/drm/ttm/ttm_bo_util.c rpi/drivers/gpu/drm/ttm/ttm_bo_util.c
--- linux/drivers/gpu/drm/ttm/ttm_bo_util.c 2014-05-29 12:18:19.761545446 +0900
+++ rpi/drivers/gpu/drm/ttm/ttm_bo_util.c 2014-05-29 11:49:13.651885880 +0900
@@ -343,19 +343,25 @@
if (ret)
goto out;
+ /*
+ * Single TTM move. NOP.
+ */
if (old_iomap == NULL && new_iomap == NULL)
goto out2;
+
+ /*
+ * Move nonexistent data. NOP.
+ */
if (old_iomap == NULL && ttm == NULL)
goto out2;
- if (ttm->state == tt_unpopulated) {
+ /*
+ * TTM might be null for moves within the same region.
+ */
+ if (ttm && ttm->state == tt_unpopulated) {
ret = ttm->bdev->driver->ttm_tt_populate(ttm);
- if (ret) {
- /* if we fail here don't nuke the mm node
- * as the bo still owns it */
- old_copy.mm_node = NULL;
+ if (ret)
goto out1;
- }
}
add = 0;
@@ -381,11 +387,8 @@
prot);
} else
ret = ttm_copy_io_page(new_iomap, old_iomap, page);
- if (ret) {
- /* failing here, means keep old copy as-is */
- old_copy.mm_node = NULL;
+ if (ret)
goto out1;
- }
}
mb();
out2:
@@ -403,7 +406,12 @@
ttm_mem_reg_iounmap(bdev, old_mem, new_iomap);
out:
ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap);
- ttm_bo_mem_put(bo, &old_copy);
+
+ /*
+ * On error, keep the mm node!
+ */
+ if (!ret)
+ ttm_bo_mem_put(bo, &old_copy);
return ret;
}
EXPORT_SYMBOL(ttm_bo_move_memcpy);
diff -Nur linux/drivers/gpu/drm/ttm/ttm_bo_vm.c rpi/drivers/gpu/drm/ttm/ttm_bo_vm.c
--- linux/drivers/gpu/drm/ttm/ttm_bo_vm.c 2014-05-29 12:18:19.761545446 +0900
+++ rpi/drivers/gpu/drm/ttm/ttm_bo_vm.c 2014-05-29 11:49:13.651885880 +0900
@@ -116,9 +116,9 @@
}
page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) +
- drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
- page_last = vma_pages(vma) +
- drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff;
+ vma->vm_pgoff - drm_vma_node_start(&bo->vma_node);
+ page_last = vma_pages(vma) + vma->vm_pgoff -
+ drm_vma_node_start(&bo->vma_node);
if (unlikely(page_offset >= bo->num_pages)) {
retval = VM_FAULT_SIGBUS;
diff -Nur linux/drivers/gpu/drm/udl/udl_gem.c rpi/drivers/gpu/drm/udl/udl_gem.c
--- linux/drivers/gpu/drm/udl/udl_gem.c 2014-05-29 12:18:19.765545421 +0900
+++ rpi/drivers/gpu/drm/udl/udl_gem.c 2014-05-29 11:49:13.655885846 +0900
@@ -132,6 +132,12 @@
static void udl_gem_put_pages(struct udl_gem_object *obj)
{
+ if (obj->base.import_attach) {
+ drm_free_large(obj->pages);
+ obj->pages = NULL;
+ return;
+ }
+
drm_gem_put_pages(&obj->base, obj->pages, false, false);
obj->pages = NULL;
}
diff -Nur linux/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c rpi/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
--- linux/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 2014-05-29 12:18:19.775545358 +0900
+++ rpi/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 2014-05-29 11:49:13.667885745 +0900
@@ -1483,11 +1483,11 @@
ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
command_size);
if (unlikely(ret != 0))
- goto out_err;
+ goto out_err_nores;
ret = vmw_resources_reserve(sw_context);
if (unlikely(ret != 0))
- goto out_err;
+ goto out_err_nores;
ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes);
if (unlikely(ret != 0))
@@ -1569,10 +1569,11 @@
return 0;
out_err:
- vmw_resource_relocations_free(&sw_context->res_relocations);
- vmw_free_relocations(sw_context);
ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes);
+out_err_nores:
vmw_resource_list_unreserve(&sw_context->resource_list, true);
+ vmw_resource_relocations_free(&sw_context->res_relocations);
+ vmw_free_relocations(sw_context);
vmw_clear_validations(sw_context);
if (unlikely(dev_priv->pinned_bo != NULL &&
!dev_priv->query_cid_valid))
diff -Nur linux/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c rpi/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
--- linux/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c 2014-05-29 12:18:19.780545327 +0900
+++ rpi/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c 2014-05-29 11:49:15.194872958 +0900
@@ -32,6 +32,8 @@
#include <drm/drmP.h>
#include "vmwgfx_resource_priv.h"
+#define VMW_RES_EVICT_ERR_COUNT 10
+
struct vmw_user_dma_buffer {
struct ttm_base_object base;
struct vmw_dma_buffer dma;
@@ -1091,8 +1093,9 @@
* to a backup buffer.
*
* @res: The resource to evict.
+ * @interruptible: Whether to wait interruptible.
*/
-int vmw_resource_do_evict(struct vmw_resource *res)
+int vmw_resource_do_evict(struct vmw_resource *res, bool interruptible)
{
struct ttm_validate_buffer val_buf;
const struct vmw_res_func *func = res->func;
@@ -1102,7 +1105,8 @@
BUG_ON(!func->may_evict);
val_buf.bo = NULL;
- ret = vmw_resource_check_buffer(res, &ticket, true, &val_buf);
+ ret = vmw_resource_check_buffer(res, &ticket, interruptible,
+ &val_buf);
if (unlikely(ret != 0))
return ret;
@@ -1141,6 +1145,7 @@
struct vmw_private *dev_priv = res->dev_priv;
struct list_head *lru_list = &dev_priv->res_lru[res->func->res_type];
struct ttm_validate_buffer val_buf;
+ unsigned err_count = 0;
if (likely(!res->func->may_evict))
return 0;
@@ -1155,7 +1160,7 @@
write_lock(&dev_priv->resource_lock);
if (list_empty(lru_list) || !res->func->may_evict) {
- DRM_ERROR("Out of device device id entries "
+ DRM_ERROR("Out of device device resources "
"for %s.\n", res->func->type_name);
ret = -EBUSY;
write_unlock(&dev_priv->resource_lock);
@@ -1168,7 +1173,19 @@
list_del_init(&evict_res->lru_head);
write_unlock(&dev_priv->resource_lock);
- vmw_resource_do_evict(evict_res);
+
+ ret = vmw_resource_do_evict(evict_res, true);
+ if (unlikely(ret != 0)) {
+ write_lock(&dev_priv->resource_lock);
+ list_add_tail(&evict_res->lru_head, lru_list);
+ write_unlock(&dev_priv->resource_lock);
+ if (ret == -ERESTARTSYS ||
+ ++err_count > VMW_RES_EVICT_ERR_COUNT) {
+ vmw_resource_unreference(&evict_res);
+ goto out_no_validate;
+ }
+ }
+
vmw_resource_unreference(&evict_res);
} while (1);
@@ -1253,13 +1270,15 @@
* @type: The resource type to evict
*
* To avoid thrashing starvation or as part of the hibernation sequence,
- * evict all evictable resources of a specific type.
+ * try to evict all evictable resources of a specific type.
*/
static void vmw_resource_evict_type(struct vmw_private *dev_priv,
enum vmw_res_type type)
{
struct list_head *lru_list = &dev_priv->res_lru[type];
struct vmw_resource *evict_res;
+ unsigned err_count = 0;
+ int ret;
do {
write_lock(&dev_priv->resource_lock);
@@ -1272,7 +1291,18 @@
lru_head));
list_del_init(&evict_res->lru_head);
write_unlock(&dev_priv->resource_lock);
- vmw_resource_do_evict(evict_res);
+
+ ret = vmw_resource_do_evict(evict_res, false);
+ if (unlikely(ret != 0)) {
+ write_lock(&dev_priv->resource_lock);
+ list_add_tail(&evict_res->lru_head, lru_list);
+ write_unlock(&dev_priv->resource_lock);
+ if (++err_count > VMW_RES_EVICT_ERR_COUNT) {
+ vmw_resource_unreference(&evict_res);
+ return;
+ }
+ }
+
vmw_resource_unreference(&evict_res);
} while (1);
diff -Nur linux/drivers/hid/hid-apple.c rpi/drivers/hid/hid-apple.c
--- linux/drivers/hid/hid-apple.c 2014-05-29 12:18:19.794545239 +0900
+++ rpi/drivers/hid/hid-apple.c 2014-05-29 11:49:15.246872522 +0900
@@ -46,6 +46,12 @@
MODULE_PARM_DESC(iso_layout, "Enable/Disable hardcoded ISO-layout of the keyboard. "
"(0 = disabled, [1] = enabled)");
+static unsigned int swap_opt_cmd = 0;
+module_param(swap_opt_cmd, uint, 0644);
+MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") keys. "
+ "(For people who want to keep Windows PC keyboard muscle memory. "
+ "[0] = as-is, Mac layout. 1 = swapped, Windows layout.)");
+
struct apple_sc {
unsigned long quirks;
unsigned int fn_on;
@@ -150,6 +156,14 @@
{ }
};
+static const struct apple_key_translation swapped_option_cmd_keys[] = {
+ { KEY_LEFTALT, KEY_LEFTMETA },
+ { KEY_LEFTMETA, KEY_LEFTALT },
+ { KEY_RIGHTALT, KEY_RIGHTMETA },
+ { KEY_RIGHTMETA,KEY_RIGHTALT },
+ { }
+};
+
static const struct apple_key_translation *apple_find_translation(
const struct apple_key_translation *table, u16 from)
{
@@ -242,6 +256,14 @@
}
}
+ if (swap_opt_cmd) {
+ trans = apple_find_translation(swapped_option_cmd_keys, usage->code);
+ if (trans) {
+ input_event(input, usage->type, trans->to, value);
+ return 1;
+ }
+ }
+
return 0;
}
diff -Nur linux/drivers/hid/hid-axff.c rpi/drivers/hid/hid-axff.c
--- linux/drivers/hid/hid-axff.c 2014-05-29 12:18:19.795545233 +0900
+++ rpi/drivers/hid/hid-axff.c 2014-05-29 11:49:15.247872514 +0900
@@ -95,7 +95,7 @@
}
}
- if (field_count < 4) {
+ if (field_count < 4 && hid->product != 0xf705) {
hid_err(hid, "not enough fields in the report: %d\n",
field_count);
return -ENODEV;
@@ -180,6 +180,7 @@
static const struct hid_device_id ax_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705), },
{ }
};
MODULE_DEVICE_TABLE(hid, ax_devices);
diff -Nur linux/drivers/hid/hid-core.c rpi/drivers/hid/hid-core.c
--- linux/drivers/hid/hid-core.c 2014-05-29 12:18:19.796545227 +0900
+++ rpi/drivers/hid/hid-core.c 2014-05-29 11:49:15.249872497 +0900
@@ -1605,6 +1605,7 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
@@ -1716,6 +1717,7 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
@@ -1723,6 +1725,7 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_MANTICORE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) },
@@ -1754,6 +1757,7 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
@@ -1801,12 +1805,14 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
#if IS_ENABLED(CONFIG_HID_ROCCAT)
- { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE_OPTICAL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEXTD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
@@ -1816,6 +1822,8 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) },
@@ -2376,15 +2384,6 @@
hdev->type == HID_TYPE_USBNONE)
return true;
break;
- case USB_VENDOR_ID_DWAV:
- /* These are handled by usbtouchscreen. hdev->type is probably
- * HID_TYPE_USBNONE, but we say !HID_TYPE_USBMOUSE to match
- * usbtouchscreen. */
- if ((hdev->product == USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER ||
- hdev->product == USB_DEVICE_ID_DWAV_TOUCHCONTROLLER) &&
- hdev->type != HID_TYPE_USBMOUSE)
- return true;
- break;
case USB_VENDOR_ID_VELLEMAN:
/* These are not HID devices. They are handled by comedi. */
if ((hdev->product >= USB_DEVICE_ID_VELLEMAN_K8055_FIRST &&
diff -Nur linux/drivers/hid/hid-elo.c rpi/drivers/hid/hid-elo.c
--- linux/drivers/hid/hid-elo.c 2014-05-29 12:18:19.797545221 +0900
+++ rpi/drivers/hid/hid-elo.c 2014-05-29 11:49:15.252872472 +0900
@@ -181,7 +181,40 @@
*/
static bool elo_broken_firmware(struct usb_device *dev)
{
- return use_fw_quirk && le16_to_cpu(dev->descriptor.bcdDevice) == 0x10d;
+ struct usb_device *hub = dev->parent;
+ struct usb_device *child = NULL;
+ u16 fw_lvl = le16_to_cpu(dev->descriptor.bcdDevice);
+ u16 child_vid, child_pid;
+ int i;
+
+ if (!use_fw_quirk)
+ return false;
+ if (fw_lvl != 0x10d)
+ return false;
+
+ /* iterate sibling devices of the touch controller */
+ usb_hub_for_each_child(hub, i, child) {
+ child_vid = le16_to_cpu(child->descriptor.idVendor);
+ child_pid = le16_to_cpu(child->descriptor.idProduct);
+
+ /*
+ * If one of the devices below is present attached as a sibling of
+ * the touch controller then this is a newer IBM 4820 monitor that
+ * does not need the IBM-requested workaround if fw level is
+ * 0x010d - aka 'M'.
+ * No other HW can have this combination.
+ */
+ if (child_vid==0x04b3) {
+ switch (child_pid) {
+ case 0x4676: /* 4820 21x Video */
+ case 0x4677: /* 4820 51x Video */
+ case 0x4678: /* 4820 2Lx Video */
+ case 0x4679: /* 4820 5Lx Video */
+ return false;
+ }
+ }
+ }
+ return true;
}
static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
diff -Nur linux/drivers/hid/hid-holtek-mouse.c rpi/drivers/hid/hid-holtek-mouse.c
--- linux/drivers/hid/hid-holtek-mouse.c 2014-05-29 12:18:19.798545214 +0900
+++ rpi/drivers/hid/hid-holtek-mouse.c 2014-05-29 11:49:15.253872464 +0900
@@ -28,6 +28,7 @@
* - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200
* and Zalman ZM-GM1
* - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse
+ * - USB ID 04d9:a072, sold as LEETGION Hellion Gaming Mouse
*/
static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -40,6 +41,7 @@
* 0x2fff, so they don't exceed HID_MAX_USAGES */
switch (hdev->product) {
case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067:
+ case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072:
if (*rsize >= 122 && rdesc[115] == 0xff && rdesc[116] == 0x7f
&& rdesc[120] == 0xff && rdesc[121] == 0x7f) {
hid_info(hdev, "Fixing up report descriptor\n");
@@ -66,6 +68,8 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
+ USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
{ }
};
diff -Nur linux/drivers/hid/hid-ids.h rpi/drivers/hid/hid-ids.h
--- linux/drivers/hid/hid-ids.h 2014-05-29 12:18:19.799545208 +0900
+++ rpi/drivers/hid/hid-ids.h 2014-05-29 11:49:15.255872447 +0900
@@ -332,6 +332,11 @@
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003
#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101 0x0101
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102 0x0102
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106 0x0106
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a
+#define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
@@ -448,8 +453,9 @@
#define USB_VENDOR_ID_HOLTEK_ALT 0x04d9
#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055
-#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A 0xa04a
+#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067 0xa067
+#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072 0xa072
#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081
#define USB_VENDOR_ID_IMATION 0x0718
@@ -483,6 +489,7 @@
#define USB_VENDOR_ID_KYE 0x0458
#define USB_DEVICE_ID_KYE_ERGO_525V 0x0087
#define USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE 0x0138
+#define USB_DEVICE_ID_GENIUS_MANTICORE 0x0153
#define USB_DEVICE_ID_GENIUS_GX_IMPERATOR 0x4018
#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
#define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010
@@ -571,6 +578,7 @@
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
#define USB_DEVICE_ID_DINOVO_MINI 0xc71f
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03
+#define USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL 0xca04
#define USB_VENDOR_ID_LUMIO 0x202e
#define USB_DEVICE_ID_CRYSTALTOUCH 0x0006
@@ -745,6 +753,10 @@
#define USB_VENDOR_ID_SIGMATEL 0x066F
#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780
+#define USB_VENDOR_ID_SIS2_TOUCH 0x0457
+#define USB_DEVICE_ID_SIS9200_TOUCH 0x9200
+#define USB_DEVICE_ID_SIS817_TOUCH 0x0817
+
#define USB_VENDOR_ID_SKYCABLE 0x1223
#define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07
@@ -888,6 +900,9 @@
#define USB_DEVICE_ID_SUPER_DUAL_BOX_PRO 0x8802
#define USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO 0x8804
+#define USB_VENDOR_ID_WISTRON 0x0fb8
+#define USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH 0x1109
+
#define USB_VENDOR_ID_X_TENSIONS 0x1ae7
#define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001
diff -Nur linux/drivers/hid/hid-kye.c rpi/drivers/hid/hid-kye.c
--- linux/drivers/hid/hid-kye.c 2014-05-29 12:18:19.800545202 +0900
+++ rpi/drivers/hid/hid-kye.c 2014-05-29 11:49:15.257872430 +0900
@@ -342,6 +342,10 @@
rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 83,
"Genius Gx Imperator Keyboard");
break;
+ case USB_DEVICE_ID_GENIUS_MANTICORE:
+ rdesc = kye_consumer_control_fixup(hdev, rdesc, rsize, 104,
+ "Genius Manticore Keyboard");
+ break;
}
return rdesc;
}
@@ -439,6 +443,8 @@
USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE,
USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
+ USB_DEVICE_ID_GENIUS_MANTICORE) },
{ }
};
MODULE_DEVICE_TABLE(hid, kye_devices);
diff -Nur linux/drivers/hid/hid-lg2ff.c rpi/drivers/hid/hid-lg2ff.c
--- linux/drivers/hid/hid-lg2ff.c 2014-05-29 12:18:19.802545189 +0900
+++ rpi/drivers/hid/hid-lg2ff.c 2014-05-29 11:49:15.259872413 +0900
@@ -95,7 +95,7 @@
hid_hw_request(hid, report, HID_REQ_SET_REPORT);
- hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n");
+ hid_info(hid, "Force feedback for Logitech variant 2 rumble devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
return 0;
}
diff -Nur linux/drivers/hid/hid-lg4ff.c rpi/drivers/hid/hid-lg4ff.c
--- linux/drivers/hid/hid-lg4ff.c 2014-05-29 12:18:19.802545189 +0900
+++ rpi/drivers/hid/hid-lg4ff.c 2014-05-29 11:49:15.259872413 +0900
@@ -218,12 +218,46 @@
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
__s32 *value = report->field[0]->value;
+ __u32 expand_a, expand_b;
+
+ /* De-activate Auto-Center */
+ if (magnitude == 0) {
+ value[0] = 0xf5;
+ value[1] = 0x00;
+ value[2] = 0x00;
+ value[3] = 0x00;
+ value[4] = 0x00;
+ value[5] = 0x00;
+ value[6] = 0x00;
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+ return;
+ }
+
+ if (magnitude <= 0xaaaa) {
+ expand_a = 0x0c * magnitude;
+ expand_b = 0x80 * magnitude;
+ } else {
+ expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa);
+ expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa);
+ }
value[0] = 0xfe;
value[1] = 0x0d;
- value[2] = magnitude >> 13;
- value[3] = magnitude >> 13;
- value[4] = magnitude >> 8;
+ value[2] = expand_a / 0xaaaa;
+ value[3] = expand_a / 0xaaaa;
+ value[4] = expand_b / 0xaaaa;
+ value[5] = 0x00;
+ value[6] = 0x00;
+
+ hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+
+ /* Activate Auto-Center */
+ value[0] = 0x14;
+ value[1] = 0x00;
+ value[2] = 0x00;
+ value[3] = 0x00;
+ value[4] = 0x00;
value[5] = 0x00;
value[6] = 0x00;
@@ -540,17 +574,6 @@
if (error)
return error;
- /* Check if autocentering is available and
- * set the centering force to zero by default */
- if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
- if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */
- dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
- else
- dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
-
- dev->ff->set_autocenter(dev, 0);
- }
-
/* Get private driver data */
drv_data = hid_get_drvdata(hid);
if (!drv_data) {
@@ -571,6 +594,17 @@
entry->max_range = lg4ff_devices[i].max_range;
entry->set_range = lg4ff_devices[i].set_range;
+ /* Check if autocentering is available and
+ * set the centering force to zero by default */
+ if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
+ if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */
+ dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
+ else
+ dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
+
+ dev->ff->set_autocenter(dev, 0);
+ }
+
/* Create sysfs interface */
error = device_create_file(&hid->dev, &dev_attr_range);
if (error)
diff -Nur linux/drivers/hid/hid-lg.c rpi/drivers/hid/hid-lg.c
--- linux/drivers/hid/hid-lg.c 2014-05-29 12:18:19.801545196 +0900
+++ rpi/drivers/hid/hid-lg.c 2014-05-29 11:49:15.258872422 +0900
@@ -45,7 +45,9 @@
/* Size of the original descriptors of the Driving Force (and Pro) wheels */
#define DF_RDESC_ORIG_SIZE 130
#define DFP_RDESC_ORIG_SIZE 97
+#define FV_RDESC_ORIG_SIZE 130
#define MOMO_RDESC_ORIG_SIZE 87
+#define MOMO2_RDESC_ORIG_SIZE 87
/* Fixed report descriptors for Logitech Driving Force (and Pro)
* wheel controllers
@@ -170,6 +172,73 @@
0xC0 /* End Collection */
};
+static __u8 fv_rdesc_fixed[] = {
+0x05, 0x01, /* Usage Page (Desktop), */
+0x09, 0x04, /* Usage (Joystik), */
+0xA1, 0x01, /* Collection (Application), */
+0xA1, 0x02, /* Collection (Logical), */
+0x95, 0x01, /* Report Count (1), */
+0x75, 0x0A, /* Report Size (10), */
+0x15, 0x00, /* Logical Minimum (0), */
+0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
+0x35, 0x00, /* Physical Minimum (0), */
+0x46, 0xFF, 0x03, /* Physical Maximum (1023), */
+0x09, 0x30, /* Usage (X), */
+0x81, 0x02, /* Input (Variable), */
+0x95, 0x0C, /* Report Count (12), */
+0x75, 0x01, /* Report Size (1), */
+0x25, 0x01, /* Logical Maximum (1), */
+0x45, 0x01, /* Physical Maximum (1), */
+0x05, 0x09, /* Usage Page (Button), */
+0x19, 0x01, /* Usage Minimum (01h), */
+0x29, 0x0C, /* Usage Maximum (0Ch), */
+0x81, 0x02, /* Input (Variable), */
+0x95, 0x02, /* Report Count (2), */
+0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
+0x09, 0x01, /* Usage (01h), */
+0x81, 0x02, /* Input (Variable), */
+0x09, 0x02, /* Usage (02h), */
+0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+0x46, 0xFF, 0x00, /* Physical Maximum (255), */
+0x95, 0x01, /* Report Count (1), */
+0x75, 0x08, /* Report Size (8), */
+0x81, 0x02, /* Input (Variable), */
+0x05, 0x01, /* Usage Page (Desktop), */
+0x25, 0x07, /* Logical Maximum (7), */
+0x46, 0x3B, 0x01, /* Physical Maximum (315), */
+0x75, 0x04, /* Report Size (4), */
+0x65, 0x14, /* Unit (Degrees), */
+0x09, 0x39, /* Usage (Hat Switch), */
+0x81, 0x42, /* Input (Variable, Null State), */
+0x75, 0x01, /* Report Size (1), */
+0x95, 0x04, /* Report Count (4), */
+0x65, 0x00, /* Unit, */
+0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
+0x09, 0x01, /* Usage (01h), */
+0x25, 0x01, /* Logical Maximum (1), */
+0x45, 0x01, /* Physical Maximum (1), */
+0x81, 0x02, /* Input (Variable), */
+0x05, 0x01, /* Usage Page (Desktop), */
+0x95, 0x01, /* Report Count (1), */
+0x75, 0x08, /* Report Size (8), */
+0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+0x46, 0xFF, 0x00, /* Physical Maximum (255), */
+0x09, 0x31, /* Usage (Y), */
+0x81, 0x02, /* Input (Variable), */
+0x09, 0x32, /* Usage (Z), */
+0x81, 0x02, /* Input (Variable), */
+0xC0, /* End Collection, */
+0xA1, 0x02, /* Collection (Logical), */
+0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+0x46, 0xFF, 0x00, /* Physical Maximum (255), */
+0x95, 0x07, /* Report Count (7), */
+0x75, 0x08, /* Report Size (8), */
+0x09, 0x03, /* Usage (03h), */
+0x91, 0x02, /* Output (Variable), */
+0xC0, /* End Collection, */
+0xC0 /* End Collection */
+};
+
static __u8 momo_rdesc_fixed[] = {
0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x04, /* Usage (Joystik), */
@@ -216,6 +285,54 @@
0xC0 /* End Collection */
};
+static __u8 momo2_rdesc_fixed[] = {
+0x05, 0x01, /* Usage Page (Desktop), */
+0x09, 0x04, /* Usage (Joystik), */
+0xA1, 0x01, /* Collection (Application), */
+0xA1, 0x02, /* Collection (Logical), */
+0x95, 0x01, /* Report Count (1), */
+0x75, 0x0A, /* Report Size (10), */
+0x15, 0x00, /* Logical Minimum (0), */
+0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
+0x35, 0x00, /* Physical Minimum (0), */
+0x46, 0xFF, 0x03, /* Physical Maximum (1023), */
+0x09, 0x30, /* Usage (X), */
+0x81, 0x02, /* Input (Variable), */
+0x95, 0x0A, /* Report Count (10), */
+0x75, 0x01, /* Report Size (1), */
+0x25, 0x01, /* Logical Maximum (1), */
+0x45, 0x01, /* Physical Maximum (1), */
+0x05, 0x09, /* Usage Page (Button), */
+0x19, 0x01, /* Usage Minimum (01h), */
+0x29, 0x0A, /* Usage Maximum (0Ah), */
+0x81, 0x02, /* Input (Variable), */
+0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
+0x09, 0x00, /* Usage (00h), */
+0x95, 0x04, /* Report Count (4), */
+0x81, 0x02, /* Input (Variable), */
+0x95, 0x01, /* Report Count (1), */
+0x75, 0x08, /* Report Size (8), */
+0x26, 0xFF, 0x00, /* Logical Maximum (255), */
+0x46, 0xFF, 0x00, /* Physical Maximum (255), */
+0x09, 0x01, /* Usage (01h), */
+0x81, 0x02, /* Input (Variable), */
+0x05, 0x01, /* Usage Page (Desktop), */
+0x09, 0x31, /* Usage (Y), */
+0x81, 0x02, /* Input (Variable), */
+0x09, 0x32, /* Usage (Z), */
+0x81, 0x02, /* Input (Variable), */
+0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
+0x09, 0x00, /* Usage (00h), */
+0x81, 0x02, /* Input (Variable), */
+0xC0, /* End Collection, */
+0xA1, 0x02, /* Collection (Logical), */
+0x09, 0x02, /* Usage (02h), */
+0x95, 0x07, /* Report Count (7), */
+0x91, 0x02, /* Output (Variable), */
+0xC0, /* End Collection, */
+0xC0 /* End Collection */
+};
+
/*
* Certain Logitech keyboards send in report #3 keys which are far
* above the logical maximum described in descriptor. This extends
@@ -275,6 +392,24 @@
}
break;
+ case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+ if (*rsize == MOMO2_RDESC_ORIG_SIZE) {
+ hid_info(hdev,
+ "fixing up Logitech Momo Racing Force (Black) report descriptor\n");
+ rdesc = momo2_rdesc_fixed;
+ *rsize = sizeof(momo2_rdesc_fixed);
+ }
+ break;
+
+ case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
+ if (*rsize == FV_RDESC_ORIG_SIZE) {
+ hid_info(hdev,
+ "fixing up Logitech Formula Vibration report descriptor\n");
+ rdesc = fv_rdesc_fixed;
+ *rsize = sizeof(fv_rdesc_fixed);
+ }
+ break;
+
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
if (*rsize == DFP_RDESC_ORIG_SIZE) {
hid_info(hdev,
@@ -492,6 +627,7 @@
case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+ case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
field->application = HID_GD_MULTIAXIS;
break;
default:
@@ -639,6 +775,8 @@
.driver_data = LG_NOGET | LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
.driver_data = LG_FF4 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL),
+ .driver_data = LG_FF2 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
.driver_data = LG_FF4 },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL),
diff -Nur linux/drivers/hid/hid-multitouch.c rpi/drivers/hid/hid-multitouch.c
--- linux/drivers/hid/hid-multitouch.c 2014-05-29 12:18:19.805545171 +0900
+++ rpi/drivers/hid/hid-multitouch.c 2014-05-29 11:49:15.263872380 +0900
@@ -250,12 +250,12 @@
{ .name = MT_CLS_GENERALTOUCH_TWOFINGERS,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_VALID_IS_INRANGE |
- MT_QUIRK_SLOT_IS_CONTACTNUMBER,
+ MT_QUIRK_SLOT_IS_CONTACTID,
.maxcontacts = 2
},
{ .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
- MT_QUIRK_SLOT_IS_CONTACTNUMBER
+ MT_QUIRK_SLOT_IS_CONTACTID
},
{ .name = MT_CLS_FLATFROG,
@@ -1173,6 +1173,21 @@
{ .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) },
+ { .driver_data = MT_CLS_GENERALTOUCH_TWOFINGERS,
+ MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+ USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0101) },
+ { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
+ MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+ USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0102) },
+ { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
+ MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+ USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_0106) },
+ { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
+ MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+ USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A) },
+ { .driver_data = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
+ MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
+ USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100) },
/* Gametel game controller */
{ .driver_data = MT_CLS_NSMU,
@@ -1284,6 +1299,14 @@
MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,
USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) },
+ /* SiS panels */
+ { .driver_data = MT_CLS_DEFAULT,
+ HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH,
+ USB_DEVICE_ID_SIS9200_TOUCH) },
+ { .driver_data = MT_CLS_DEFAULT,
+ HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH,
+ USB_DEVICE_ID_SIS817_TOUCH) },
+
/* Stantum panels */
{ .driver_data = MT_CLS_CONFIDENCE,
MT_USB_DEVICE(USB_VENDOR_ID_STANTUM,
@@ -1312,6 +1335,12 @@
{ .driver_data = MT_CLS_NSMU,
MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
+
+ /* Wistron panels */
+ { .driver_data = MT_CLS_NSMU,
+ MT_USB_DEVICE(USB_VENDOR_ID_WISTRON,
+ USB_DEVICE_ID_WISTRON_OPTICAL_TOUCH) },
+
/* XAT */
{ .driver_data = MT_CLS_NSMU,
MT_USB_DEVICE(USB_VENDOR_ID_XAT,
diff -Nur linux/drivers/hid/hidraw.c rpi/drivers/hid/hidraw.c
--- linux/drivers/hid/hidraw.c 2014-05-29 12:18:19.813545121 +0900
+++ rpi/drivers/hid/hidraw.c 2014-05-29 11:49:15.283872213 +0900
@@ -313,13 +313,13 @@
hid_hw_close(hidraw->hid);
wake_up_interruptible(&hidraw->wait);
}
+ device_destroy(hidraw_class,
+ MKDEV(hidraw_major, hidraw->minor));
} else {
--hidraw->open;
}
if (!hidraw->open) {
if (!hidraw->exist) {
- device_destroy(hidraw_class,
- MKDEV(hidraw_major, hidraw->minor));
hidraw_table[hidraw->minor] = NULL;
kfree(hidraw);
} else {
diff -Nur linux/drivers/hid/hid-roccat-common.c rpi/drivers/hid/hid-roccat-common.c
--- linux/drivers/hid/hid-roccat-common.c 2014-05-29 12:18:19.807545158 +0900
+++ rpi/drivers/hid/hid-roccat-common.c 2014-05-29 11:49:15.268872338 +0900
@@ -65,10 +65,11 @@
EXPORT_SYMBOL_GPL(roccat_common2_send);
enum roccat_common2_control_states {
- ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD = 0,
+ ROCCAT_COMMON_CONTROL_STATUS_CRITICAL = 0,
ROCCAT_COMMON_CONTROL_STATUS_OK = 1,
ROCCAT_COMMON_CONTROL_STATUS_INVALID = 2,
- ROCCAT_COMMON_CONTROL_STATUS_WAIT = 3,
+ ROCCAT_COMMON_CONTROL_STATUS_BUSY = 3,
+ ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW = 4,
};
static int roccat_common2_receive_control_status(struct usb_device *usb_dev)
@@ -88,13 +89,12 @@
switch (control.value) {
case ROCCAT_COMMON_CONTROL_STATUS_OK:
return 0;
- case ROCCAT_COMMON_CONTROL_STATUS_WAIT:
+ case ROCCAT_COMMON_CONTROL_STATUS_BUSY:
msleep(500);
continue;
case ROCCAT_COMMON_CONTROL_STATUS_INVALID:
-
- case ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD:
- /* seems to be critical - replug necessary */
+ case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL:
+ case ROCCAT_COMMON_CONTROL_STATUS_CRITICAL_NEW:
return -EINVAL;
default:
dev_err(&usb_dev->dev,
diff -Nur linux/drivers/hid/hid-roccat-kovaplus.c rpi/drivers/hid/hid-roccat-kovaplus.c
--- linux/drivers/hid/hid-roccat-kovaplus.c 2014-05-29 12:18:19.808545152 +0900
+++ rpi/drivers/hid/hid-roccat-kovaplus.c 2014-05-29 11:49:15.272872305 +0900
@@ -554,9 +554,13 @@
break;
case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI:
kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1);
+ break;
case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY:
kovaplus->actual_x_sensitivity = button_report->data1;
kovaplus->actual_y_sensitivity = button_report->data2;
+ break;
+ default:
+ break;
}
}
diff -Nur linux/drivers/hid/hid-sensor-hub.c rpi/drivers/hid/hid-sensor-hub.c
--- linux/drivers/hid/hid-sensor-hub.c 2014-05-29 12:18:19.809545146 +0900
+++ rpi/drivers/hid/hid-sensor-hub.c 2014-05-29 11:49:15.275872280 +0900
@@ -326,7 +326,8 @@
field->logical == attr_usage_id) {
sensor_hub_fill_attr_info(info, i, report->id,
field->unit, field->unit_exponent,
- field->report_size);
+ field->report_size *
+ field->report_count);
ret = 0;
} else {
for (j = 0; j < field->maxusage; ++j) {
@@ -338,7 +339,8 @@
i, report->id,
field->unit,
field->unit_exponent,
- field->report_size);
+ field->report_size *
+ field->report_count);
ret = 0;
break;
}
@@ -425,9 +427,10 @@
hid_dbg(hdev, "%d collection_index:%x hid:%x sz:%x\n",
i, report->field[i]->usage->collection_index,
report->field[i]->usage->hid,
- report->field[i]->report_size/8);
-
- sz = report->field[i]->report_size/8;
+ (report->field[i]->report_size *
+ report->field[i]->report_count)/8);
+ sz = (report->field[i]->report_size *
+ report->field[i]->report_count)/8;
if (pdata->pending.status && pdata->pending.attr_usage_id ==
report->field[i]->usage->hid) {
hid_dbg(hdev, "data was pending ...\n");
diff -Nur linux/drivers/hid/hid-wiimote-modules.c rpi/drivers/hid/hid-wiimote-modules.c
--- linux/drivers/hid/hid-wiimote-modules.c 2014-05-29 12:18:19.812545127 +0900
+++ rpi/drivers/hid/hid-wiimote-modules.c 2014-05-29 11:49:15.281872229 +0900
@@ -1656,9 +1656,9 @@
ry = (ext[6] & 0xff) | ((ext[7] & 0x0f) << 8);
input_report_abs(wdata->extension.input, ABS_X, lx - 0x800);
- input_report_abs(wdata->extension.input, ABS_Y, ly - 0x800);
+ input_report_abs(wdata->extension.input, ABS_Y, 0x800 - ly);
input_report_abs(wdata->extension.input, ABS_RX, rx - 0x800);
- input_report_abs(wdata->extension.input, ABS_RY, ry - 0x800);
+ input_report_abs(wdata->extension.input, ABS_RY, 0x800 - ry);
input_report_key(wdata->extension.input,
wiimod_pro_map[WIIMOD_PRO_KEY_RIGHT],
diff -Nur linux/drivers/hid/Kconfig rpi/drivers/hid/Kconfig
--- linux/drivers/hid/Kconfig 2014-05-29 12:18:19.793545246 +0900
+++ rpi/drivers/hid/Kconfig 2014-05-29 11:49:15.245872531 +0900
@@ -242,6 +242,7 @@
- Tracer Sniper TRM-503 / NOVA Gaming Slider X200 /
Zalman ZM-GM1
- SHARKOON DarkGlider Gaming mouse
+ - LEETGION Hellion Gaming Mouse
config HOLTEK_FF
bool "Holtek On Line Grip force feedback support"
@@ -369,12 +370,14 @@
force feedback.
config LOGIRUMBLEPAD2_FF
- bool "Logitech RumblePad/Rumblepad 2 force feedback support"
+ bool "Logitech force feedback support (variant 2)"
depends on HID_LOGITECH
select INPUT_FF_MEMLESS
help
- Say Y here if you want to enable force feedback support for Logitech
- RumblePad and Rumblepad 2 devices.
+ Say Y here if you want to enable force feedback support for:
+ - Logitech RumblePad
+ - Logitech Rumblepad 2
+ - Logitech Formula Vibration Feedback Wheel
config LOGIG940_FF
bool "Logitech Flight System G940 force feedback support"
@@ -453,9 +456,11 @@
- Pixcir dual touch panels
- Quanta panels
- eGalax dual-touch panels, including the Joojoo and Wetab tablets
+ - SiS multitouch panels
- Stantum multitouch panels
- Touch International Panels
- Unitec Panels
+ - Wistron optical touch panels
- XAT optical touch panels
- Xiroku optical touch panels
- Zytronic touch panels
diff -Nur linux/drivers/hid/uhid.c rpi/drivers/hid/uhid.c
--- linux/drivers/hid/uhid.c 2014-05-29 12:18:19.814545114 +0900
+++ rpi/drivers/hid/uhid.c 2014-05-29 11:49:15.284872204 +0900
@@ -287,7 +287,7 @@
*/
struct uhid_create_req_compat *compat;
- compat = kmalloc(sizeof(*compat), GFP_KERNEL);
+ compat = kzalloc(sizeof(*compat), GFP_KERNEL);
if (!compat)
return -ENOMEM;
diff -Nur linux/drivers/hid/usbhid/hid-quirks.c rpi/drivers/hid/usbhid/hid-quirks.c
--- linux/drivers/hid/usbhid/hid-quirks.c 2014-05-29 12:18:19.816545102 +0900
+++ rpi/drivers/hid/usbhid/hid-quirks.c 2014-05-29 11:49:15.287872179 +0900
@@ -84,6 +84,8 @@
{ USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
diff -Nur linux/drivers/hv/channel_mgmt.c rpi/drivers/hv/channel_mgmt.c
--- linux/drivers/hv/channel_mgmt.c 2014-05-29 12:18:19.818545089 +0900
+++ rpi/drivers/hv/channel_mgmt.c 2014-05-29 11:49:15.292872137 +0900
@@ -203,7 +203,8 @@
struct vmbus_channel *primary_channel;
struct vmbus_channel_relid_released msg;
- vmbus_device_unregister(channel->device_obj);
+ if (channel->device_obj)
+ vmbus_device_unregister(channel->device_obj);
memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
msg.child_relid = channel->offermsg.child_relid;
msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
@@ -216,7 +217,7 @@
} else {
primary_channel = channel->primary_channel;
spin_lock_irqsave(&primary_channel->sc_lock, flags);
- list_del(&channel->listentry);
+ list_del(&channel->sc_list);
spin_unlock_irqrestore(&primary_channel->sc_lock, flags);
}
free_channel(channel);
diff -Nur linux/drivers/hv/connection.c rpi/drivers/hv/connection.c
--- linux/drivers/hv/connection.c 2014-05-29 12:18:19.819545083 +0900
+++ rpi/drivers/hv/connection.c 2014-05-29 11:49:15.292872137 +0900
@@ -55,6 +55,9 @@
case (VERSION_WIN8):
return VERSION_WIN7;
+ case (VERSION_WIN8_1):
+ return VERSION_WIN8;
+
case (VERSION_WS2008):
default:
return VERSION_INVAL;
@@ -67,7 +70,6 @@
int ret = 0;
struct vmbus_channel_initiate_contact *msg;
unsigned long flags;
- int t;
init_completion(&msginfo->waitevent);
@@ -80,6 +82,8 @@
msg->monitor_page2 = virt_to_phys(
(void *)((unsigned long)vmbus_connection.monitor_pages +
PAGE_SIZE));
+ if (version == VERSION_WIN8_1)
+ msg->target_vcpu = hv_context.vp_index[smp_processor_id()];
/*
* Add to list before we send the request since we may
@@ -102,15 +106,7 @@
}
/* Wait for the connection response */
- t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
- if (t == 0) {
- spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
- flags);
- list_del(&msginfo->msglistentry);
- spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
- flags);
- return -ETIMEDOUT;
- }
+ wait_for_completion(&msginfo->waitevent);
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_del(&msginfo->msglistentry);
diff -Nur linux/drivers/hwmon/bcm2835-hwmon.c rpi/drivers/hwmon/bcm2835-hwmon.c
--- linux/drivers/hwmon/bcm2835-hwmon.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/hwmon/bcm2835-hwmon.c 2014-05-29 11:49:15.313871961 +0900
@@ -0,0 +1,219 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+#include <mach/vcio.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#define MODULE_NAME "bcm2835_hwmon"
+
+/*#define HWMON_DEBUG_ENABLE*/
+
+#ifdef HWMON_DEBUG_ENABLE
+#define print_debug(fmt,...) printk(KERN_INFO "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
+#else
+#define print_debug(fmt,...)
+#endif
+#define print_err(fmt,...) printk(KERN_ERR "%s:%s:%d: "fmt"\n", MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__)
+#define print_info(fmt,...) printk(KERN_INFO "%s: "fmt"\n", MODULE_NAME, ##__VA_ARGS__)
+
+#define VC_TAG_GET_TEMP 0x00030006
+#define VC_TAG_GET_MAX_TEMP 0x0003000A
+
+/* --- STRUCTS --- */
+struct bcm2835_hwmon_data {
+ struct device *hwmon_dev;
+};
+
+/* tag part of the message */
+struct vc_msg_tag {
+ uint32_t tag_id; /* the tag ID for the temperature */
+ uint32_t buffer_size; /* size of the buffer (should be 8) */
+ uint32_t request_code; /* identifies message as a request (should be 0) */
+ uint32_t id; /* extra ID field (should be 0) */
+ uint32_t val; /* returned value of the temperature */
+};
+
+/* message structure to be sent to videocore */
+struct vc_msg {
+ uint32_t msg_size; /* simply, sizeof(struct vc_msg) */
+ uint32_t request_code; /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */
+ struct vc_msg_tag tag; /* the tag structure above to make */
+ uint32_t end_tag; /* an end identifier, should be set to NULL */
+};
+
+typedef enum {
+ TEMP,
+ MAX_TEMP,
+} temp_type;
+
+/* --- PROTOTYPES --- */
+static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf);
+
+/* --- GLOBALS --- */
+
+static struct bcm2835_hwmon_data *bcm2835_data;
+static struct platform_driver bcm2835_hwmon_driver;
+
+static SENSOR_DEVICE_ATTR(name, S_IRUGO,bcm2835_get_name,NULL,0);
+static SENSOR_DEVICE_ATTR(temp1_input,S_IRUGO,bcm2835_get_temp,NULL,TEMP);
+static SENSOR_DEVICE_ATTR(temp1_max,S_IRUGO,bcm2835_get_temp,NULL,MAX_TEMP);
+
+static struct attribute* bcm2835_attributes[] = {
+ &sensor_dev_attr_name.dev_attr.attr,
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_max.dev_attr.attr,
+ NULL,
+};
+
+static struct attribute_group bcm2835_attr_group = {
+ .attrs = bcm2835_attributes,
+};
+
+/* --- FUNCTIONS --- */
+
+static ssize_t bcm2835_get_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf,"bcm2835_hwmon\n");
+}
+
+static ssize_t bcm2835_get_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct vc_msg msg;
+ int result;
+ uint temp = 0;
+ int index = ((struct sensor_device_attribute*)to_sensor_dev_attr(attr))->index;
+
+ print_debug("IN");
+
+ /* wipe all previous message data */
+ memset(&msg, 0, sizeof msg);
+
+ /* determine the message type */
+ if(index == TEMP)
+ msg.tag.tag_id = VC_TAG_GET_TEMP;
+ else if (index == MAX_TEMP)
+ msg.tag.tag_id = VC_TAG_GET_MAX_TEMP;
+ else
+ {
+ print_debug("Unknown temperature message!");
+ return -EINVAL;
+ }
+
+ msg.msg_size = sizeof msg;
+ msg.tag.buffer_size = 8;
+
+ /* send the message */
+ result = bcm_mailbox_property(&msg, sizeof msg);
+
+ /* check if it was all ok and return the rate in milli degrees C */
+ if (result == 0 && (msg.request_code & 0x80000000))
+ temp = (uint)msg.tag.val;
+ #ifdef HWMON_DEBUG_ENABLE
+ else
+ print_debug("Failed to get temperature!");
+ #endif
+ print_debug("Got temperature as %u",temp);
+ print_debug("OUT");
+ return sprintf(buf, "%u\n", temp);
+}
+
+
+static int bcm2835_hwmon_probe(struct platform_device *pdev)
+{
+ int err;
+
+ print_debug("IN");
+ print_debug("HWMON Driver has been probed!");
+
+ /* check that the device isn't null!*/
+ if(pdev == NULL)
+ {
+ print_debug("Platform device is empty!");
+ return -ENODEV;
+ }
+
+ /* allocate memory for neccessary data */
+ bcm2835_data = kzalloc(sizeof(struct bcm2835_hwmon_data),GFP_KERNEL);
+ if(!bcm2835_data)
+ {
+ print_debug("Unable to allocate memory for hwmon data!");
+ err = -ENOMEM;
+ goto kzalloc_error;
+ }
+
+ /* create the sysfs files */
+ if(sysfs_create_group(&pdev->dev.kobj, &bcm2835_attr_group))
+ {
+ print_debug("Unable to create sysfs files!");
+ err = -EFAULT;
+ goto sysfs_error;
+ }
+
+ /* register the hwmon device */
+ bcm2835_data->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(bcm2835_data->hwmon_dev))
+ {
+ err = PTR_ERR(bcm2835_data->hwmon_dev);
+ goto hwmon_error;
+ }
+ print_debug("OUT");
+ return 0;
+
+ /* error goto's */
+ hwmon_error:
+ sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group);
+
+ sysfs_error:
+ kfree(bcm2835_data);
+
+ kzalloc_error:
+
+ return err;
+
+}
+
+static int bcm2835_hwmon_remove(struct platform_device *pdev)
+{
+ print_debug("IN");
+ hwmon_device_unregister(bcm2835_data->hwmon_dev);
+
+ sysfs_remove_group(&pdev->dev.kobj, &bcm2835_attr_group);
+ print_debug("OUT");
+ return 0;
+}
+
+/* Hwmon Driver */
+static struct platform_driver bcm2835_hwmon_driver = {
+ .probe = bcm2835_hwmon_probe,
+ .remove = bcm2835_hwmon_remove,
+ .driver = {
+ .name = "bcm2835_hwmon",
+ .owner = THIS_MODULE,
+ },
+};
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dorian Peake");
+MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip");
+
+module_platform_driver(bcm2835_hwmon_driver);
diff -Nur linux/drivers/hwmon/coretemp.c rpi/drivers/hwmon/coretemp.c
--- linux/drivers/hwmon/coretemp.c 2014-05-29 12:18:19.836544977 +0900
+++ rpi/drivers/hwmon/coretemp.c 2014-05-29 11:49:15.313871961 +0900
@@ -52,7 +52,7 @@
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
#define NUM_REAL_CORES 32 /* Number of Real cores per cpu */
-#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */
+#define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */
#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
diff -Nur linux/drivers/hwmon/hih6130.c rpi/drivers/hwmon/hih6130.c
--- linux/drivers/hwmon/hih6130.c 2014-05-29 12:18:19.843544933 +0900
+++ rpi/drivers/hwmon/hih6130.c 2014-05-29 11:49:15.323871878 +0900
@@ -43,6 +43,7 @@
* @last_update: time of last update (jiffies)
* @temperature: cached temperature measurement value
* @humidity: cached humidity measurement value
+ * @write_length: length for I2C measurement request
*/
struct hih6130 {
struct device *hwmon_dev;
@@ -51,6 +52,7 @@
unsigned long last_update;
int temperature;
int humidity;
+ size_t write_length;
};
/**
@@ -121,8 +123,15 @@
*/
if (time_after(jiffies, hih6130->last_update + HZ) || !hih6130->valid) {
- /* write to slave address, no data, to request a measurement */
- ret = i2c_master_send(client, tmp, 0);
+ /*
+ * Write to slave address to request a measurement.
+ * According with the datasheet it should be with no data, but
+ * for systems with I2C bus drivers that do not allow zero
+ * length packets we write one dummy byte to allow sensor
+ * measurements on them.
+ */
+ tmp[0] = 0;
+ ret = i2c_master_send(client, tmp, hih6130->write_length);
if (ret < 0)
goto out;
@@ -252,6 +261,9 @@
goto fail_remove_sysfs;
}
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK))
+ hih6130->write_length = 1;
+
return 0;
fail_remove_sysfs:
diff -Nur linux/drivers/hwmon/k10temp.c rpi/drivers/hwmon/k10temp.c
--- linux/drivers/hwmon/k10temp.c 2014-05-29 12:18:19.848544902 +0900
+++ rpi/drivers/hwmon/k10temp.c 2014-05-29 11:49:15.327871844 +0900
@@ -210,6 +210,7 @@
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
{}
};
diff -Nur linux/drivers/hwmon/Kconfig rpi/drivers/hwmon/Kconfig
--- linux/drivers/hwmon/Kconfig 2014-05-29 12:18:19.824545052 +0900
+++ rpi/drivers/hwmon/Kconfig 2014-05-29 11:49:15.297872095 +0900
@@ -1553,6 +1553,16 @@
help
Support for the A/D converter on MC13783 and MC13892 PMIC.
+config SENSORS_BCM2835
+ depends on THERMAL_BCM2835=n
+ tristate "Broadcom BCM2835 HWMON Driver"
+ help
+ If you say yes here you get support for the hardware
+ monitoring features of the BCM2835 Chip
+
+ This driver can also be built as a module. If so, the module
+ will be called bcm2835-hwmon.
+
if ACPI
comment "ACPI drivers"
diff -Nur linux/drivers/hwmon/lm78.c rpi/drivers/hwmon/lm78.c
--- linux/drivers/hwmon/lm78.c 2014-05-29 12:18:19.851544883 +0900
+++ rpi/drivers/hwmon/lm78.c 2014-05-29 11:49:15.331871811 +0900
@@ -94,6 +94,8 @@
{
if (rpm <= 0)
return 255;
+ if (rpm > 1350000)
+ return 1;
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
}
diff -Nur linux/drivers/hwmon/lm90.c rpi/drivers/hwmon/lm90.c
--- linux/drivers/hwmon/lm90.c 2014-05-29 12:18:19.855544858 +0900
+++ rpi/drivers/hwmon/lm90.c 2014-05-29 11:49:15.334871786 +0900
@@ -278,7 +278,7 @@
[max6696] = {
.flags = LM90_HAVE_EMERGENCY
| LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3,
- .alert_alarms = 0x187c,
+ .alert_alarms = 0x1c7c,
.max_convrate = 6,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
},
@@ -1500,19 +1500,22 @@
if ((alarms & 0x7f) == 0 && (alarms2 & 0xfe) == 0) {
dev_info(&client->dev, "Everything OK\n");
} else {
- if (alarms & 0x61)
+ if ((alarms & 0x61) || (alarms2 & 0x80))
dev_warn(&client->dev,
"temp%d out of range, please check!\n", 1);
- if (alarms & 0x1a)
+ if ((alarms & 0x1a) || (alarms2 & 0x20))
dev_warn(&client->dev,
"temp%d out of range, please check!\n", 2);
if (alarms & 0x04)
dev_warn(&client->dev,
"temp%d diode open, please check!\n", 2);
- if (alarms2 & 0x18)
+ if (alarms2 & 0x5a)
dev_warn(&client->dev,
"temp%d out of range, please check!\n", 3);
+ if (alarms2 & 0x04)
+ dev_warn(&client->dev,
+ "temp%d diode open, please check!\n", 3);
/*
* Disable ALERT# output, because these chips don't implement
diff -Nur linux/drivers/hwmon/Makefile rpi/drivers/hwmon/Makefile
--- linux/drivers/hwmon/Makefile 2014-05-29 12:18:19.824545052 +0900
+++ rpi/drivers/hwmon/Makefile 2014-05-29 11:49:15.297872095 +0900
@@ -142,6 +142,7 @@
obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
+obj-$(CONFIG_SENSORS_BCM2835) += bcm2835-hwmon.o
obj-$(CONFIG_PMBUS) += pmbus/
diff -Nur linux/drivers/hwmon/max1668.c rpi/drivers/hwmon/max1668.c
--- linux/drivers/hwmon/max1668.c 2014-05-29 12:18:19.860544827 +0900
+++ rpi/drivers/hwmon/max1668.c 2014-05-29 11:49:15.340871735 +0900
@@ -243,7 +243,7 @@
data->temp_min[index] = clamp_val(temp/1000, -128, 127);
if (i2c_smbus_write_byte_data(client,
MAX1668_REG_LIML_WR(index),
- data->temp_max[index]))
+ data->temp_min[index]))
count = -EIO;
mutex_unlock(&data->update_lock);
diff -Nur linux/drivers/hwmon/ntc_thermistor.c rpi/drivers/hwmon/ntc_thermistor.c
--- linux/drivers/hwmon/ntc_thermistor.c 2014-05-29 12:18:19.865544795 +0900
+++ rpi/drivers/hwmon/ntc_thermistor.c 2014-05-29 11:49:15.344871702 +0900
@@ -145,7 +145,7 @@
static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
{
struct iio_channel *channel = pdata->chan;
- unsigned int result;
+ s64 result;
int val, ret;
ret = iio_read_channel_raw(channel, &val);
@@ -155,10 +155,10 @@
}
/* unit: mV */
- result = pdata->pullup_uv * val;
+ result = pdata->pullup_uv * (s64) val;
result >>= 12;
- return result;
+ return (int)result;
}
static const struct of_device_id ntc_match[] = {
diff -Nur linux/drivers/hwmon/sis5595.c rpi/drivers/hwmon/sis5595.c
--- linux/drivers/hwmon/sis5595.c 2014-05-29 12:18:19.883544683 +0900
+++ rpi/drivers/hwmon/sis5595.c 2014-05-29 11:49:15.354871618 +0900
@@ -141,6 +141,8 @@
{
if (rpm <= 0)
return 255;
+ if (rpm > 1350000)
+ return 1;
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
}
diff -Nur linux/drivers/hwmon/vt8231.c rpi/drivers/hwmon/vt8231.c
--- linux/drivers/hwmon/vt8231.c 2014-05-29 12:18:19.921544445 +0900
+++ rpi/drivers/hwmon/vt8231.c 2014-05-29 11:49:15.360871568 +0900
@@ -145,7 +145,7 @@
*/
static inline u8 FAN_TO_REG(long rpm, int div)
{
- if (rpm == 0)
+ if (rpm <= 0 || rpm > 1310720)
return 0;
return clamp_val(1310720 / (rpm * div), 1, 255);
}
diff -Nur linux/drivers/hwmon/w83l786ng.c rpi/drivers/hwmon/w83l786ng.c
--- linux/drivers/hwmon/w83l786ng.c 2014-05-29 12:18:19.930544389 +0900
+++ rpi/drivers/hwmon/w83l786ng.c 2014-05-29 11:49:15.368871501 +0900
@@ -481,9 +481,11 @@
if (err)
return err;
val = clamp_val(val, 0, 255);
+ val = DIV_ROUND_CLOSEST(val, 0x11);
mutex_lock(&data->update_lock);
- data->pwm[nr] = val;
+ data->pwm[nr] = val * 0x11;
+ val |= w83l786ng_read_value(client, W83L786NG_REG_PWM[nr]) & 0xf0;
w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val);
mutex_unlock(&data->update_lock);
return count;
@@ -510,7 +512,7 @@
mutex_lock(&data->update_lock);
reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
data->pwm_enable[nr] = val;
- reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
+ reg &= ~(0x03 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr];
w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg);
mutex_unlock(&data->update_lock);
@@ -776,9 +778,10 @@
((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
? 0 : 1;
data->pwm_enable[i] =
- ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1;
- data->pwm[i] = w83l786ng_read_value(client,
- W83L786NG_REG_PWM[i]);
+ ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1;
+ data->pwm[i] =
+ (w83l786ng_read_value(client, W83L786NG_REG_PWM[i])
+ & 0x0f) * 0x11;
}
diff -Nur linux/drivers/i2c/busses/i2c-bcm2708.c rpi/drivers/i2c/busses/i2c-bcm2708.c
--- linux/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 09:00:00.000000000 +0900
+++ rpi/drivers/i2c/busses/i2c-bcm2708.c 2014-05-29 11:49:15.376871434 +0900
@@ -0,0 +1,448 @@
+/*
+ * Driver for Broadcom BCM2708 BSC Controllers
+ *
+ * Copyright (C) 2012 Chris Boot & Frank Buss
+ *
+ * This driver is inspired by:
+ * i2c-ocores.c, by Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+/* BSC register offsets */
+#define BSC_C 0x00
+#define BSC_S 0x04
+#define BSC_DLEN 0x08
+#define BSC_A 0x0c
+#define BSC_FIFO 0x10
+#define BSC_DIV 0x14
+#define BSC_DEL 0x18
+#define BSC_CLKT 0x1c
+
+/* Bitfields in BSC_C */
+#define BSC_C_I2CEN 0x00008000
+#define BSC_C_INTR 0x00000400
+#define BSC_C_INTT 0x00000200
+#define BSC_C_INTD 0x00000100
+#define BSC_C_ST 0x00000080
+#define BSC_C_CLEAR_1 0x00000020
+#define BSC_C_CLEAR_2 0x00000010
+#define BSC_C_READ 0x00000001
+
+/* Bitfields in BSC_S */
+#define BSC_S_CLKT 0x00000200
+#define BSC_S_ERR 0x00000100
+#define BSC_S_RXF 0x00000080
+#define BSC_S_TXE 0x00000040
+#define BSC_S_RXD 0x00000020
+#define BSC_S_TXD 0x00000010
+#define BSC_S_RXR 0x00000008
+#define BSC_S_TXW 0x00000004
+#define BSC_S_DONE 0x00000002
+#define BSC_S_TA 0x00000001
+
+#define I2C_TIMEOUT_MS 150
+
+#define DRV_NAME "bcm2708_i2c"
+
+static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE;
+module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(baudrate, "The I2C baudrate");
+
+static bool combined = false;
+module_param(combined, bool, 0644);
+MODULE_PARM_DESC(combined, "Use combined transactions");
+
+struct bcm2708_i2c {
+ struct i2c_adapter adapter;
+
+ spinlock_t lock;
+ void __iomem *base;
+ int irq;
+ struct clk *clk;
+
+ struct completion done;
+
+ struct i2c_msg *msg;
+ int pos;
+ int nmsgs;
+ bool error;
+};
+
+/*
+ * This function sets the ALT mode on the I2C pins so that we can use them with
+ * the BSC hardware.
+ *
+ * FIXME: This is a hack. Use pinmux / pinctrl.
+ */
+static void bcm2708_i2c_init_pinmode(int id)
+{
+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
+
+ int pin;
+ u32 *gpio = ioremap(GPIO_BASE, SZ_16K);
+
+ BUG_ON(id != 0 && id != 1);
+ /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */
+ for (pin = id*2+0; pin <= id*2+1; pin++) {
+printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin);
+ INP_GPIO(pin); /* set mode to GPIO input first */
+ SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */
+ }
+
+ iounmap(gpio);
+
+#undef INP_GPIO
+#undef SET_GPIO_ALT
+}
+
+static inline u32 bcm2708_rd(struct bcm2708_i2c *bi, unsigned reg)
+{
+ return readl(bi->base + reg);
+}
+
+static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val)
+{
+ writel(val, bi->base + reg);
+}
+
+static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi)
+{
+ bcm2708_wr(bi, BSC_C, 0);
+ bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE);
+}
+
+static inline void bcm2708_bsc_fifo_drain(struct bcm2708_i2c *bi)
+{
+ while ((bcm2708_rd(bi, BSC_S) & BSC_S_RXD) && (bi->pos < bi->msg->len))
+ bi->msg->buf[bi->pos++] = bcm2708_rd(bi, BSC_FIFO);
+}
+
+static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)
+{
+ while ((bcm2708_rd(bi, BSC_S) & BSC_S_TXD) && (bi->pos < bi->msg->len))
+ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
+}
+
+static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
+{
+ unsigned long bus_hz;
+ u32 cdiv, s;
+ u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
+
+ bus_hz = clk_get_rate(bi->clk);
+ cdiv = bus_hz / baudrate;
+ if (cdiv > 0xffff)
+ cdiv = 0xffff;
+
+ if (bi->msg->flags & I2C_M_RD)
+ c |= BSC_C_INTR | BSC_C_READ;
+ else
+ c |= BSC_C_INTT;
+
+ bcm2708_wr(bi, BSC_DIV, cdiv);
+ bcm2708_wr(bi, BSC_A, bi->msg->addr);
+ bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
+ if (combined)
+ {
+ /* Do the next two messages meet combined transaction criteria?
+ - Current message is a write, next message is a read
+ - Both messages to same slave address
+ - Write message can fit inside FIFO (16 bytes or less) */
+ if ( (bi->nmsgs > 1) &&
+ !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) &&
+ (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) {
+ /* Fill FIFO with entire write message (16 byte FIFO) */
+ while (bi->pos < bi->msg->len)
+ bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
+ /* Start write transfer (no interrupts, don't clear FIFO) */
+ bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST);
+ /* poll for transfer start bit (should only take 1-20 polls) */
+ do {
+ s = bcm2708_rd(bi, BSC_S);
+ } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)));
+ /* Send next read message before the write transfer finishes. */
+ bi->nmsgs--;
+ bi->msg++;
+ bi->pos = 0;
+ bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
+ c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ;
+ }
+ }
+ bcm2708_wr(bi, BSC_C, c);
+}
+
+static irqreturn_t bcm2708_i2c_interrupt(int irq, void *dev_id)
+{
+ struct bcm2708_i2c *bi = dev_id;
+ bool handled = true;
+ u32 s;
+
+ spin_lock(&bi->lock);
+
+ /* we may see camera interrupts on the "other" I2C channel
+ Just return if we've not sent anything */
+ if (!bi->nmsgs || !bi->msg )
+ goto early_exit;
+
+ s = bcm2708_rd(bi, BSC_S);
+
+ if (s & (BSC_S_CLKT | BSC_S_ERR)) {
+ bcm2708_bsc_reset(bi);
+ bi->error = true;
+
+ /* wake up our bh */
+ complete(&bi->done);
+ } else if (s & BSC_S_DONE) {
+ bi->nmsgs--;
+
+ if (bi->msg->flags & I2C_M_RD)
+ bcm2708_bsc_fifo_drain(bi);
+
+ bcm2708_bsc_reset(bi);
+
+ if (bi->nmsgs) {
+ /* advance to next message */
+ bi->msg++;
+ bi->pos = 0;
+ bcm2708_bsc_setup(bi);
+ } else {
+ /* wake up our bh */
+ complete(&bi->done);
+ }
+ } else if (s & BSC_S_TXW) {
+ bcm2708_bsc_fifo_fill(bi);
+ } else if (s & BSC_S_RXR) {
+ bcm2708_bsc_fifo_drain(bi);
+ } else {
+ handled = false;
+ }
+
+early_exit:
+ spin_unlock(&bi->lock);
+
+ return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int bcm2708_i2c_master_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct bcm2708_i2c *bi = adap->algo_data;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&bi->lock, flags);
+
+ INIT_COMPLETION(bi->done);
+ bi->msg = msgs;
+ bi->pos = 0;
+ bi->nmsgs = num;
+ bi->error = false;
+
+ spin_unlock_irqrestore(&bi->lock, flags);
+
+ bcm2708_bsc_setup(bi);
+
+ ret = wait_for_completion_timeout(&bi->done,
+ msecs_to_jiffies(I2C_TIMEOUT_MS));
+ if (ret == 0) {
+ dev_err(&adap->dev, "transfer timed out\n");
+ spin_lock_irqsave(&bi->lock, flags);
+ bcm2708_bsc_reset(bi);
+ spin_unlock_irqrestore(&bi->lock, flags);
+ return -ETIMEDOUT;
+ }
+
+ return bi->error ? -EIO : num;
+}
+
+static u32 bcm2708_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | /*I2C_FUNC_10BIT_ADDR |*/ I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm bcm2708_i2c_algorithm = {
+ .master_xfer = bcm2708_i2c_master_xfer,
+ .functionality = bcm2708_i2c_functionality,
+};
+
+static int bcm2708_i2c_probe(struct platform_device *pdev)
+{
+ struct resource *regs;
+ int irq, err = -ENOMEM;
+ struct clk *clk;
+ struct bcm2708_i2c *bi;
+ struct i2c_adapter *adap;
+ unsigned long bus_hz;
+ u32 cdiv;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_err(&pdev->dev, "could not get IO memory\n");
+ return -ENXIO;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "could not get IRQ\n");
+ return irq;
+ }
+
+ clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "could not find clk: %ld\n", PTR_ERR(clk));
+ return PTR_ERR(clk);
+ }
+
+ bcm2708_i2c_init_pinmode(pdev->id);
+
+ bi = kzalloc(sizeof(*bi), GFP_KERNEL);
+ if (!bi)
+ goto out_clk_put;
+
+ platform_set_drvdata(pdev, bi);
+
+ adap = &bi->adapter;
+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_DDC;
+ adap->algo = &bcm2708_i2c_algorithm;
+ adap->algo_data = bi;
+ adap->dev.parent = &pdev->dev;
+ adap->nr = pdev->id;
+ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
+
+ switch (pdev->id) {
+ case 0:
+ adap->class = I2C_CLASS_HWMON;
+ break;
+ case 1:
+ adap->class = I2C_CLASS_DDC;
+ break;
+ default:
+ dev_err(&pdev->dev, "can only bind to BSC 0 or 1\n");
+ err = -ENXIO;
+ goto out_free_bi;
+ }
+
+ spin_lock_init(&bi->lock);
+ init_completion(&bi->done);
+
+ bi->base = ioremap(regs->start, resource_size(regs));
+ if (!bi->base) {
+ dev_err(&pdev->dev, "could not remap memory\n");
+ goto out_free_bi;
+ }
+
+ bi->irq = irq;
+ bi->clk = clk;
+
+ err = request_irq(irq, bcm2708_i2c_interrupt, IRQF_SHARED,
+ dev_name(&pdev->dev), bi);
+ if (err) {
+ dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
+ goto out_iounmap;
+ }
+
+ bcm2708_bsc_reset(bi);
+
+ err = i2c_add_numbered_adapter(adap);
+ if (err < 0) {
+ dev_err(&pdev->dev, "could not add I2C adapter: %d\n", err);
+ goto out_free_irq;
+ }
+
+ bus_hz = clk_get_rate(bi->clk);
+ cdiv = bus_hz / baudrate;
+ if (cdiv > 0xffff) {
+ cdiv = 0xffff;
+ baudrate = bus_hz / cdiv;
+ }
+
+ dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %d)\n",
+ pdev->id, (unsigned long)regs->start, irq, baudrate);
+
+ return 0;
+
+out_free_irq:
+ free_irq(bi->irq, bi);
+out_iounmap:
+ iounmap(bi->base);
+out_free_bi:
+ kfree(bi);
+out_clk_put:
+ clk_put(clk);
+ return err;
+}
+
+static int bcm2708_i2c_remove(struct platform_device *pdev)
+{
+ struct bcm2708_i2c *bi = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ i2c_del_adapter(&bi->adapter);
+ free_irq(bi->irq, bi);
+ iounmap(bi->base);
+ clk_disable(bi->clk);
+ clk_put(bi->clk);
+ kfree(bi);
+
+ return 0;
+}
+
+static struct platform_driver bcm2708_i2c_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = bcm2708_i2c_probe,
+ .remove = bcm2708_i2c_remove,
+};
+
+// module_platform_driver(bcm2708_i2c_driver);
+
+
+static int __init bcm2708_i2c_init(void)
+{
+ return platform_driver_register(&bcm2708_i2c_driver);
+}
+
+static void __exit bcm2708_i2c_exit(void)
+{
+ platform_driver_unregister(&bcm2708_i2c_driver);
+}
+
+module_init(bcm2708_i2c_init);
+module_exit(bcm2708_i2c_exit);
+
+
+
+MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708");
+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
diff -Nur linux/drivers/i2c/busses/i2c-cpm.c rpi/drivers/i2c/busses/i2c-cpm.c
--- linux/drivers/i2c/busses/i2c-cpm.c 2014-05-29 12:18:19.942544314 +0900
+++ rpi/drivers/i2c/busses/i2c-cpm.c 2014-05-29 11:49:15.378871417 +0900
@@ -40,7 +40,9 @@
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
+#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
#include <asm/cpm.h>
diff -Nur linux/drivers/i2c/busses/i2c-i801.c rpi/drivers/i2c/busses/i2c-i801.c
--- linux/drivers/i2c/busses/i2c-i801.c 2014-05-29 12:18:19.948544276 +0900
+++ rpi/drivers/i2c/busses/i2c-i801.c 2014-05-29 11:49:15.382871384 +0900
@@ -59,6 +59,8 @@
Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes
Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes
Coleto Creek (PCH) 0x23b0 32 hard yes yes yes
+ Wildcat Point-LP (PCH) 0x9ca2 32 hard yes yes yes
+ BayTrail (SOC) 0x0f12 32 hard yes yes yes
Features supported by this driver:
Software PEC no
@@ -160,6 +162,7 @@
STATUS_ERROR_FLAGS)
/* Older devices have their ID defined in <linux/pci_ids.h> */
+#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
/* Patsburg also has three 'Integrated Device Function' SMBus controllers */
@@ -177,6 +180,7 @@
#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1 0x8d7e
#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2 0x8d7f
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2
struct i801_mux_config {
char *gpio_chip;
@@ -819,6 +823,8 @@
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) },
{ 0, }
};
diff -Nur linux/drivers/i2c/busses/i2c-mv64xxx.c rpi/drivers/i2c/busses/i2c-mv64xxx.c
--- linux/drivers/i2c/busses/i2c-mv64xxx.c 2014-05-29 12:18:19.953544245 +0900
+++ rpi/drivers/i2c/busses/i2c-mv64xxx.c 2014-05-29 11:49:15.386871350 +0900
@@ -97,7 +97,6 @@
enum {
MV64XXX_I2C_ACTION_INVALID,
MV64XXX_I2C_ACTION_CONTINUE,
- MV64XXX_I2C_ACTION_OFFLOAD_SEND_START,
MV64XXX_I2C_ACTION_SEND_START,
MV64XXX_I2C_ACTION_SEND_RESTART,
MV64XXX_I2C_ACTION_OFFLOAD_RESTART,
@@ -204,6 +203,9 @@
unsigned long ctrl_reg;
struct i2c_msg *msg = drv_data->msgs;
+ if (!drv_data->offload_enabled)
+ return -EOPNOTSUPP;
+
drv_data->msg = msg;
drv_data->byte_posn = 0;
drv_data->bytes_left = msg->len;
@@ -433,8 +435,7 @@
drv_data->msgs++;
drv_data->num_msgs--;
- if (!(drv_data->offload_enabled &&
- mv64xxx_i2c_offload_msg(drv_data))) {
+ if (mv64xxx_i2c_offload_msg(drv_data) < 0) {
drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
writel(drv_data->cntl_bits,
drv_data->reg_base + drv_data->reg_offsets.control);
@@ -458,15 +459,14 @@
drv_data->reg_base + drv_data->reg_offsets.control);
break;
- case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START:
- if (!mv64xxx_i2c_offload_msg(drv_data))
- break;
- else
- drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
- /* FALLTHRU */
case MV64XXX_I2C_ACTION_SEND_START:
- writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
- drv_data->reg_base + drv_data->reg_offsets.control);
+ /* Can we offload this msg ? */
+ if (mv64xxx_i2c_offload_msg(drv_data) < 0) {
+ /* No, switch to standard path */
+ mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs);
+ writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
+ drv_data->reg_base + drv_data->reg_offsets.control);
+ }
break;
case MV64XXX_I2C_ACTION_SEND_ADDR_1:
@@ -625,15 +625,10 @@
unsigned long flags;
spin_lock_irqsave(&drv_data->lock, flags);
- if (drv_data->offload_enabled) {
- drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_START;
- drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
- } else {
- mv64xxx_i2c_prepare_for_io(drv_data, msg);
- drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
- drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
- }
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
+ drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
+
drv_data->send_stop = is_last;
drv_data->block = 1;
mv64xxx_i2c_do_action(drv_data);
@@ -692,6 +687,7 @@
{ .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i},
{ .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
{ .compatible = "marvell,mv78230-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
+ { .compatible = "marvell,mv78230-a0-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
{}
};
MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
@@ -783,6 +779,10 @@
drv_data->errata_delay = true;
}
+ if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) {
+ drv_data->offload_enabled = false;
+ drv_data->errata_delay = true;
+ }
out:
return rc;
#endif
diff -Nur linux/drivers/i2c/busses/i2c-piix4.c rpi/drivers/i2c/busses/i2c-piix4.c
--- linux/drivers/i2c/busses/i2c-piix4.c 2014-05-29 12:18:19.960544201 +0900
+++ rpi/drivers/i2c/busses/i2c-piix4.c 2014-05-29 11:49:15.392871300 +0900
@@ -22,7 +22,7 @@
Intel PIIX4, 440MX
Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800
- AMD Hudson-2, CZ
+ AMD Hudson-2, ML, CZ
SMSC Victory66
Note: we assume there can only be one device, with one or more
@@ -235,7 +235,8 @@
{
unsigned short piix4_smba;
unsigned short smba_idx = 0xcd6;
- u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en;
+ u8 smba_en_lo, smba_en_hi, smb_en, smb_en_status;
+ u8 i2ccfg, i2ccfg_offset = 0x10;
/* SB800 and later SMBus does not support forcing address */
if (force || force_addr) {
@@ -245,7 +246,15 @@
}
/* Determine the address of the SMBus areas */
- smb_en = (aux) ? 0x28 : 0x2c;
+ if ((PIIX4_dev->vendor == PCI_VENDOR_ID_AMD &&
+ PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
+ PIIX4_dev->revision >= 0x41) ||
+ (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD &&
+ PIIX4_dev->device == 0x790b &&
+ PIIX4_dev->revision >= 0x49))
+ smb_en = 0x00;
+ else
+ smb_en = (aux) ? 0x28 : 0x2c;
if (!request_region(smba_idx, 2, "smba_idx")) {
dev_err(&PIIX4_dev->dev, "SMBus base address index region "
@@ -258,13 +267,22 @@
smba_en_hi = inb_p(smba_idx + 1);
release_region(smba_idx, 2);
- if ((smba_en_lo & 1) == 0) {
+ if (!smb_en) {
+ smb_en_status = smba_en_lo & 0x10;
+ piix4_smba = smba_en_hi << 8;
+ if (aux)
+ piix4_smba |= 0x20;
+ } else {
+ smb_en_status = smba_en_lo & 0x01;
+ piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
+ }
+
+ if (!smb_en_status) {
dev_err(&PIIX4_dev->dev,
"Host SMBus controller not enabled!\n");
return -ENODEV;
}
- piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
return -ENODEV;
diff -Nur linux/drivers/i2c/busses/i2c-wmt.c rpi/drivers/i2c/busses/i2c-wmt.c
--- linux/drivers/i2c/busses/i2c-wmt.c 2014-05-29 12:18:19.971544132 +0900
+++ rpi/drivers/i2c/busses/i2c-wmt.c 2014-05-29 11:49:15.402871216 +0900
@@ -349,6 +349,7 @@
err = clk_set_rate(i2c_dev->clk, 20000000);
if (err) {
dev_err(i2c_dev->dev, "failed to set clock = 20Mhz\n");
+ clk_disable_unprepare(i2c_dev->clk);
return err;
}
diff -Nur linux/drivers/i2c/busses/Kconfig rpi/drivers/i2c/busses/Kconfig
--- linux/drivers/i2c/busses/Kconfig 2014-05-29 12:18:19.933544370 +0900
+++ rpi/drivers/i2c/busses/Kconfig 2014-05-29 11:49:15.373871459 +0900
@@ -109,6 +109,8 @@
Avoton (SOC)
Wellsburg (PCH)
Coleto Creek (PCH)
+ Wildcat Point-LP (PCH)
+ BayTrail (SOC)
This driver can also be built as a module. If so, the module
will be called i2c-i801.
@@ -151,6 +153,7 @@
ATI SB700/SP5100
ATI SB800
AMD Hudson-2
+ AMD ML
AMD CZ
Serverworks OSB4
Serverworks CSB5
@@ -345,6 +348,25 @@
This support is also available as a module. If so, the module
will be called i2c-bcm2835.
+config I2C_BCM2708
+ tristate "BCM2708 BSC"
+ depends on MACH_BCM2708
+ help
+ Enabling this option will add BSC (Broadcom Serial Controller)
+ support for the BCM2708. BSC is a Broadcom proprietary bus compatible
+ with I2C/TWI/SMBus.
+
+config I2C_BCM2708_BAUDRATE
+ prompt "BCM2708 I2C baudrate"
+ depends on I2C_BCM2708
+ int
+ default 100000
+ help
+ Set the I2C baudrate. This will alter the default value. A
+ different baudrate can be set by using a module parameter as well. If
+ no parameter is provided when loading, this is the value that will be
+ used.
+
config I2C_BLACKFIN_TWI
tristate "Blackfin TWI I2C support"
depends on BLACKFIN
@@ -375,7 +397,7 @@
config I2C_CPM
tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
- depends on (CPM1 || CPM2) && OF_I2C
+ depends on CPM1 || CPM2
help
This supports the use of the I2C interface on Freescale
processors with CPM1 or CPM2.
diff -Nur linux/drivers/i2c/busses/Makefile rpi/drivers/i2c/busses/Makefile
--- linux/drivers/i2c/busses/Makefile 2014-05-29 12:18:19.933544370 +0900
+++ rpi/drivers/i2c/busses/Makefile 2014-05-29 11:49:15.373871459 +0900
@@ -32,6 +32,7 @@
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o
+obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o
obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
diff -Nur linux/drivers/i2c/muxes/i2c-mux-gpio.c rpi/drivers/i2c/muxes/i2c-mux-gpio.c
--- linux/drivers/i2c/muxes/i2c-mux-gpio.c 2014-05-29 12:18:19.976544101 +0900
+++ rpi/drivers/i2c/muxes/i2c-mux-gpio.c 2014-05-29 11:49:15.407871175 +0900
@@ -30,15 +30,15 @@
int i;
for (i = 0; i < mux->data.n_gpios; i++)
- gpio_set_value(mux->gpio_base + mux->data.gpios[i],
- val & (1 << i));
+ gpio_set_value_cansleep(mux->gpio_base + mux->data.gpios[i],
+ val & (1 << i));
}
static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan)
{
struct gpiomux *mux = data;
- i2c_mux_gpio_set(mux, mux->data.values[chan]);
+ i2c_mux_gpio_set(mux, chan);
return 0;
}
@@ -228,7 +228,7 @@
unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
- i, class,
+ mux->data.values[i], class,
i2c_mux_gpio_select, deselect);
if (!mux->adap[i]) {
ret = -ENODEV;
diff -Nur linux/drivers/idle/intel_idle.c rpi/drivers/idle/intel_idle.c
--- linux/drivers/idle/intel_idle.c 2014-05-29 12:18:19.984544051 +0900
+++ rpi/drivers/idle/intel_idle.c 2014-05-29 11:49:15.447870840 +0900
@@ -1,7 +1,7 @@
/*
* intel_idle.c - native hardware idle loop for modern Intel processors
*
- * Copyright (c) 2010, Intel Corporation.
+ * Copyright (c) 2013, Intel Corporation.
* Len Brown <len.brown@intel.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -329,6 +329,22 @@
{
.enter = NULL }
};
+static struct cpuidle_state avn_cstates[] __initdata = {
+ {
+ .name = "C1-AVN",
+ .desc = "MWAIT 0x00",
+ .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
+ .exit_latency = 2,
+ .target_residency = 2,
+ .enter = &intel_idle },
+ {
+ .name = "C6-AVN",
+ .desc = "MWAIT 0x51",
+ .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 15,
+ .target_residency = 45,
+ .enter = &intel_idle },
+};
/**
* intel_idle
@@ -359,7 +375,10 @@
if (!(lapic_timer_reliable_states & (1 << (cstate))))
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
- if (!need_resched()) {
+ if (!current_set_polling_and_test()) {
+
+ if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
+ clflush((void *)&current_thread_info()->flags);
__monitor((void *)&current_thread_info()->flags, 0, 0);
smp_mb();
@@ -462,6 +481,11 @@
.disable_promotion_to_c1e = true,
};
+static const struct idle_cpu idle_cpu_avn = {
+ .state_table = avn_cstates,
+ .disable_promotion_to_c1e = true,
+};
+
#define ICPU(model, cpu) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
@@ -483,6 +507,7 @@
ICPU(0x3f, idle_cpu_hsw),
ICPU(0x45, idle_cpu_hsw),
ICPU(0x46, idle_cpu_hsw),
+ ICPU(0x4D, idle_cpu_avn),
{}
};
MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
diff -Nur linux/drivers/iio/accel/kxsd9.c rpi/drivers/iio/accel/kxsd9.c
--- linux/drivers/iio/accel/kxsd9.c 2014-05-29 12:18:19.986544038 +0900
+++ rpi/drivers/iio/accel/kxsd9.c 2014-05-29 11:49:15.450870815 +0900
@@ -112,9 +112,10 @@
mutex_lock(&st->buf_lock);
st->tx[0] = KXSD9_READ(address);
ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
- if (ret)
- return ret;
- return (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
+ if (!ret)
+ ret = (((u16)(st->rx[0])) << 8) | (st->rx[1] & 0xF0);
+ mutex_unlock(&st->buf_lock);
+ return ret;
}
static IIO_CONST_ATTR(accel_scale_available,
diff -Nur linux/drivers/iio/adc/ad7887.c rpi/drivers/iio/adc/ad7887.c
--- linux/drivers/iio/adc/ad7887.c 2014-05-29 12:18:19.989544019 +0900
+++ rpi/drivers/iio/adc/ad7887.c 2014-05-29 11:49:15.453870789 +0900
@@ -211,7 +211,13 @@
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.address = 1,
.scan_index = 1,
- .scan_type = IIO_ST('u', 12, 16, 0),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ .shift = 0,
+ .endianness = IIO_BE,
+ },
},
.channel[1] = {
.type = IIO_VOLTAGE,
@@ -221,7 +227,13 @@
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.address = 0,
.scan_index = 0,
- .scan_type = IIO_ST('u', 12, 16, 0),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ .shift = 0,
+ .endianness = IIO_BE,
+ },
},
.channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
.int_vref_mv = 2500,
diff -Nur linux/drivers/iio/adc/max1363.c rpi/drivers/iio/adc/max1363.c
--- linux/drivers/iio/adc/max1363.c 2014-05-29 12:18:19.992544001 +0900
+++ rpi/drivers/iio/adc/max1363.c 2014-05-29 11:49:15.456870764 +0900
@@ -1527,7 +1527,7 @@
st->client = client;
st->vref_uv = st->chip_info->int_vref_mv * 1000;
- vref = devm_regulator_get(&client->dev, "vref");
+ vref = devm_regulator_get_optional(&client->dev, "vref");
if (!IS_ERR(vref)) {
int vref_uv;
diff -Nur linux/drivers/iio/gyro/Kconfig rpi/drivers/iio/gyro/Kconfig
--- linux/drivers/iio/gyro/Kconfig 2014-05-29 12:18:20.004543926 +0900
+++ rpi/drivers/iio/gyro/Kconfig 2014-05-29 11:49:15.468870664 +0900
@@ -70,7 +70,7 @@
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
help
Say yes here to build support for STMicroelectronics gyroscopes:
- L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
+ L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330.
This driver can also be built as a module. If so, these modules
will be created:
diff -Nur linux/drivers/iio/gyro/st_gyro_core.c rpi/drivers/iio/gyro/st_gyro_core.c
--- linux/drivers/iio/gyro/st_gyro_core.c 2014-05-29 12:18:20.006543913 +0900
+++ rpi/drivers/iio/gyro/st_gyro_core.c 2014-05-29 11:49:15.471870639 +0900
@@ -167,11 +167,10 @@
.wai = ST_GYRO_2_WAI_EXP,
.sensors_supported = {
[0] = L3GD20_GYRO_DEV_NAME,
- [1] = L3GD20H_GYRO_DEV_NAME,
- [2] = LSM330D_GYRO_DEV_NAME,
- [3] = LSM330DLC_GYRO_DEV_NAME,
- [4] = L3G4IS_GYRO_DEV_NAME,
- [5] = LSM330_GYRO_DEV_NAME,
+ [1] = LSM330D_GYRO_DEV_NAME,
+ [2] = LSM330DLC_GYRO_DEV_NAME,
+ [3] = L3G4IS_GYRO_DEV_NAME,
+ [4] = LSM330_GYRO_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
.odr = {
diff -Nur linux/drivers/iio/gyro/st_gyro.h rpi/drivers/iio/gyro/st_gyro.h
--- linux/drivers/iio/gyro/st_gyro.h 2014-05-29 12:18:20.006543913 +0900
+++ rpi/drivers/iio/gyro/st_gyro.h 2014-05-29 11:49:15.470870647 +0900
@@ -19,7 +19,6 @@
#define LSM330DL_GYRO_DEV_NAME "lsm330dl_gyro"
#define LSM330DLC_GYRO_DEV_NAME "lsm330dlc_gyro"
#define L3GD20_GYRO_DEV_NAME "l3gd20"
-#define L3GD20H_GYRO_DEV_NAME "l3gd20h"
#define L3G4IS_GYRO_DEV_NAME "l3g4is_ui"
#define LSM330_GYRO_DEV_NAME "lsm330_gyro"
diff -Nur linux/drivers/iio/gyro/st_gyro_i2c.c rpi/drivers/iio/gyro/st_gyro_i2c.c
--- linux/drivers/iio/gyro/st_gyro_i2c.c 2014-05-29 12:18:20.007543907 +0900
+++ rpi/drivers/iio/gyro/st_gyro_i2c.c 2014-05-29 11:49:15.471870639 +0900
@@ -55,7 +55,6 @@
{ LSM330DL_GYRO_DEV_NAME },
{ LSM330DLC_GYRO_DEV_NAME },
{ L3GD20_GYRO_DEV_NAME },
- { L3GD20H_GYRO_DEV_NAME },
{ L3G4IS_GYRO_DEV_NAME },
{ LSM330_GYRO_DEV_NAME },
{},
diff -Nur linux/drivers/iio/gyro/st_gyro_spi.c rpi/drivers/iio/gyro/st_gyro_spi.c
--- linux/drivers/iio/gyro/st_gyro_spi.c 2014-05-29 12:18:20.007543907 +0900
+++ rpi/drivers/iio/gyro/st_gyro_spi.c 2014-05-29 11:49:15.471870639 +0900
@@ -54,7 +54,6 @@
{ LSM330DL_GYRO_DEV_NAME },
{ LSM330DLC_GYRO_DEV_NAME },
{ L3GD20_GYRO_DEV_NAME },
- { L3GD20H_GYRO_DEV_NAME },
{ L3G4IS_GYRO_DEV_NAME },
{ LSM330_GYRO_DEV_NAME },
{},
diff -Nur linux/drivers/iio/imu/adis16400_core.c rpi/drivers/iio/imu/adis16400_core.c
--- linux/drivers/iio/imu/adis16400_core.c 2014-05-29 12:18:20.009543894 +0900
+++ rpi/drivers/iio/imu/adis16400_core.c 2014-05-29 11:49:15.473870622 +0900
@@ -632,7 +632,7 @@
ADIS16400_MAGN_CHAN(Z, ADIS16400_ZMAGN_OUT, 14),
ADIS16400_TEMP_CHAN(ADIS16400_TEMP_OUT, 12),
ADIS16400_AUX_ADC_CHAN(ADIS16400_AUX_ADC, 12),
- IIO_CHAN_SOFT_TIMESTAMP(12)
+ IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
static const struct iio_chan_spec adis16448_channels[] = {
@@ -651,10 +651,15 @@
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.address = ADIS16448_BARO_OUT,
.scan_index = ADIS16400_SCAN_BARO,
- .scan_type = IIO_ST('s', 16, 16, 0),
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_BE,
+ },
},
ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
- IIO_CHAN_SOFT_TIMESTAMP(11)
+ IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
static const struct iio_chan_spec adis16350_channels[] = {
@@ -672,7 +677,7 @@
ADIS16400_MOD_TEMP_CHAN(X, ADIS16350_XTEMP_OUT, 12),
ADIS16400_MOD_TEMP_CHAN(Y, ADIS16350_YTEMP_OUT, 12),
ADIS16400_MOD_TEMP_CHAN(Z, ADIS16350_ZTEMP_OUT, 12),
- IIO_CHAN_SOFT_TIMESTAMP(11)
+ IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
static const struct iio_chan_spec adis16300_channels[] = {
@@ -685,7 +690,7 @@
ADIS16400_AUX_ADC_CHAN(ADIS16300_AUX_ADC, 12),
ADIS16400_INCLI_CHAN(X, ADIS16300_PITCH_OUT, 13),
ADIS16400_INCLI_CHAN(Y, ADIS16300_ROLL_OUT, 13),
- IIO_CHAN_SOFT_TIMESTAMP(14)
+ IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
static const struct iio_chan_spec adis16334_channels[] = {
@@ -696,7 +701,7 @@
ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 14),
ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 14),
ADIS16400_TEMP_CHAN(ADIS16350_XTEMP_OUT, 12),
- IIO_CHAN_SOFT_TIMESTAMP(8)
+ IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
static struct attribute *adis16400_attributes[] = {
diff -Nur linux/drivers/iio/imu/adis16400.h rpi/drivers/iio/imu/adis16400.h
--- linux/drivers/iio/imu/adis16400.h 2014-05-29 12:18:20.008543901 +0900
+++ rpi/drivers/iio/imu/adis16400.h 2014-05-29 11:49:15.472870630 +0900
@@ -189,6 +189,7 @@
ADIS16300_SCAN_INCLI_X,
ADIS16300_SCAN_INCLI_Y,
ADIS16400_SCAN_ADC,
+ ADIS16400_SCAN_TIMESTAMP,
};
#ifdef CONFIG_IIO_BUFFER
diff -Nur linux/drivers/iio/industrialio-buffer.c rpi/drivers/iio/industrialio-buffer.c
--- linux/drivers/iio/industrialio-buffer.c 2014-05-29 12:18:20.011543882 +0900
+++ rpi/drivers/iio/industrialio-buffer.c 2014-05-29 11:49:15.476870597 +0900
@@ -119,7 +119,8 @@
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- ret = test_bit(to_iio_dev_attr(attr)->address,
+ /* Ensure ret is 0 or 1. */
+ ret = !!test_bit(to_iio_dev_attr(attr)->address,
indio_dev->buffer->scan_mask);
return sprintf(buf, "%d\n", ret);
@@ -789,7 +790,8 @@
if (!buffer->scan_mask)
return 0;
- return test_bit(bit, buffer->scan_mask);
+ /* Ensure return value is 0 or 1. */
+ return !!test_bit(bit, buffer->scan_mask);
};
EXPORT_SYMBOL_GPL(iio_scan_mask_query);
diff -Nur linux/drivers/iio/magnetometer/ak8975.c rpi/drivers/iio/magnetometer/ak8975.c
--- linux/drivers/iio/magnetometer/ak8975.c 2014-05-29 12:18:20.017543844 +0900
+++ rpi/drivers/iio/magnetometer/ak8975.c 2014-05-29 11:49:15.482870547 +0900
@@ -85,6 +85,7 @@
#define AK8975_MAX_CONVERSION_TIMEOUT 500
#define AK8975_CONVERSION_DONE_POLL_TIME 10
#define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000)
+#define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256)
/*
* Per-instance context data for the device.
@@ -265,15 +266,15 @@
*
* Since 1uT = 100 gauss, our final scale factor becomes:
*
- * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
- * Hadj = H * ((ASA + 128) * 30 / 256
+ * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100
+ * Hadj = H * ((ASA + 128) * 0.003) / 256
*
* Since ASA doesn't change, we cache the resultant scale factor into the
* device context in ak8975_setup().
*/
- data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
- data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8;
- data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
+ data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]);
+ data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]);
+ data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]);
return 0;
}
@@ -428,8 +429,9 @@
case IIO_CHAN_INFO_RAW:
return ak8975_read_axis(indio_dev, chan->address, val);
case IIO_CHAN_INFO_SCALE:
- *val = data->raw_to_gauss[chan->address];
- return IIO_VAL_INT;
+ *val = 0;
+ *val2 = data->raw_to_gauss[chan->address];
+ return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
diff -Nur linux/drivers/infiniband/hw/ehca/ehca_cq.c rpi/drivers/infiniband/hw/ehca/ehca_cq.c
--- linux/drivers/infiniband/hw/ehca/ehca_cq.c 2014-05-29 12:18:20.046543663 +0900
+++ rpi/drivers/infiniband/hw/ehca/ehca_cq.c 2014-05-29 11:49:15.525870187 +0900
@@ -283,6 +283,7 @@
(my_cq->galpas.user.fw_handle & (PAGE_SIZE - 1));
if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
ehca_err(device, "Copy to udata failed.");
+ cq = ERR_PTR(-EFAULT);
goto create_cq_exit4;
}
}
diff -Nur linux/drivers/infiniband/hw/ipath/ipath_diag.c rpi/drivers/infiniband/hw/ipath
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment