* [PATCH 0/3] Various ARM64 Armada DT warning fixup
From: Gregory CLEMENT @ 2016-11-07 21:41 UTC (permalink / raw)
To: linux-arm-kernel
Following the series sent for Armada 370/XP, this patchset fixes up
various warning from the DT compiler when using the flag W=1 with
make.
Being a fresh new port, the arm64 we did a better job for dt than for
the arm32 so there is only a few patches needed.
Gregory
Gregory CLEMENT (3):
arm64: dts: marvell: Fixup internal-regs DT warning for Armada 37xx
arm64: dts: marvell: Fixup config-space DT warning For Armada 7K/8K
ARM64: dts: marvell: Fixup memory DT warning for Armada 37xx
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 2 +-
arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts | 2 +-
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +-
arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 2 +-
arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 2 +-
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
--
2.10.1
^ permalink raw reply
* [PATCH 1/3] arm64: dts: marvell: Fixup internal-regs DT warning for Armada 37xx
From: Gregory CLEMENT @ 2016-11-07 21:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161107214128.18401-1-gregory.clement@free-electrons.com>
internal-regs has a ranges property so the unit name should contain an
address.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index c4762538ec01..f1596daa2bc7 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -91,7 +91,7 @@
#size-cells = <2>;
ranges;
- internal-regs {
+ internal-regs at d0000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
--
2.10.1
^ permalink raw reply related
* [PATCH 2/3] arm64: dts: marvell: Fixup config-space DT warning For Armada 7K/8K
From: Gregory CLEMENT @ 2016-11-07 21:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161107214128.18401-1-gregory.clement@free-electrons.com>
config-space has a ranges property so the unit name should contain an
address.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm64/boot/dts/marvell/armada-ap806.dtsi | 2 +-
arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 2 +-
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
index 7b6136182ad0..a749ba2edec4 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
@@ -71,7 +71,7 @@
interrupt-parent = <&gic>;
ranges;
- config-space {
+ config-space at f0000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
index e5e3ed678b6f..607e9a3ef834 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
@@ -52,7 +52,7 @@
interrupt-parent = <&gic>;
ranges;
- config-space {
+ config-space at f2000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
index 842fb333285c..88e74069c666 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
@@ -52,7 +52,7 @@
interrupt-parent = <&gic>;
ranges;
- config-space {
+ config-space at f4000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
--
2.10.1
^ permalink raw reply related
* [PATCH 3/3] ARM64: dts: marvell: Fixup memory DT warning for Armada 37xx
From: Gregory CLEMENT @ 2016-11-07 21:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161107214128.18401-1-gregory.clement@free-electrons.com>
memory has a reg property so the unit name should contain an address.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm64/boot/dts/marvell/armada-3720-db.dts | 2 +-
arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
index 1372e9a6aaa4..a260ae25b658 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts
@@ -56,7 +56,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory at 0 {
device_type = "memory";
reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
};
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
index eadd5993c7bd..83178d909fc2 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
@@ -55,7 +55,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory at 0 {
device_type = "memory";
reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
};
--
2.10.1
^ permalink raw reply related
* [PATCH 2/2] ARM64: configs: Add Platform MHU in defconfig
From: Kevin Hilman @ 2016-11-07 22:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478164284-24958-3-git-send-email-narmstrong@baylibre.com>
Neil Armstrong <narmstrong@baylibre.com> writes:
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
> arch/arm64/configs/defconfig | 1 +
> 1 file changed, 1 insertion(+)
Applied.
Kevin
^ permalink raw reply
* [PATCH v4 0/2] ARM: Embedding Position Independent Executables
From: Alexandre Belloni @ 2016-11-07 22:24 UTC (permalink / raw)
To: linux-arm-kernel
This series introduces Position Independent Executables (PIEs) for the
ARM architecture.
The main goal is to avoid having to write low level code in assembly as
this is currently the case for suspend/resume. Multiple platforms will
benefit from this infrastructure: at91, rockchip, am335x.
It would also be beneficial for the LPDDR support on at91 to avoid
having the handle the DDR controller from 4 different drivers.
Russell, do you see any remaining issues with the current approach?
Changes in v4:
- rebased on v4.9-rc1
- Fixed an issue with the alignment reported by Mylene
Changes in v3:
- rebased on v4.8-rc1
Changes in v2:
- handle big endian
- handle gcov and ftrace by disabling them before compilling the PIE
- Get the alignment from the original ELF to ensure the PIE is
properly aligned in SRAM.
- stop using fncpy
- rebased on v4.7-rc1
Alexandre Belloni (2):
ARM: PIE infrastructure
ARM: at91: pm: switch to the PIE infrastructure
arch/arm/Kconfig | 2 +
arch/arm/Makefile | 1 +
arch/arm/mach-at91/Kconfig | 1 +
arch/arm/mach-at91/Makefile | 2 +-
arch/arm/mach-at91/pm.c | 31 ++--
arch/arm/mach-at91/pm/.gitignore | 2 +
arch/arm/mach-at91/pm/Makefile | 3 +
arch/arm/mach-at91/pm/atmel_pm.c | 97 +++++++++++
arch/arm/mach-at91/pm_suspend.S | 338 ---------------------------------------
arch/arm/pie/Kconfig | 8 +
arch/arm/pie/Makefile | 1 +
arch/arm/pie/Makefile.pie | 86 ++++++++++
arch/arm/pie/lib/empty.c | 15 ++
arch/arm/pie/pie.c | 97 +++++++++++
arch/arm/pie/pie.lds.S | 40 +++++
include/linux/pie.h | 146 +++++++++++++++++
16 files changed, 510 insertions(+), 360 deletions(-)
create mode 100644 arch/arm/mach-at91/pm/.gitignore
create mode 100644 arch/arm/mach-at91/pm/Makefile
create mode 100644 arch/arm/mach-at91/pm/atmel_pm.c
delete mode 100644 arch/arm/mach-at91/pm_suspend.S
create mode 100644 arch/arm/pie/Kconfig
create mode 100644 arch/arm/pie/Makefile
create mode 100644 arch/arm/pie/Makefile.pie
create mode 100644 arch/arm/pie/lib/empty.c
create mode 100644 arch/arm/pie/pie.c
create mode 100644 arch/arm/pie/pie.lds.S
create mode 100644 include/linux/pie.h
--
2.10.2
^ permalink raw reply
* [PATCH v4 1/2] ARM: PIE infrastructure
From: Alexandre Belloni @ 2016-11-07 22:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161107222458.15732-1-alexandre.belloni@free-electrons.com>
Add support for embedding position independent executables (PIE) in the
kernel. Those PIEs can then be loaded into memory allocated using genalloc.
For example, this allows running code from SRAM which is usually needed for
suspend/resume or to change the DDR timings. That code is usually written
in assembly and can now be developed in C.
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
arch/arm/Kconfig | 2 +
arch/arm/Makefile | 1 +
arch/arm/pie/Kconfig | 8 +++
arch/arm/pie/Makefile | 1 +
arch/arm/pie/Makefile.pie | 86 +++++++++++++++++++++++++++
arch/arm/pie/lib/empty.c | 15 +++++
arch/arm/pie/pie.c | 97 ++++++++++++++++++++++++++++++
arch/arm/pie/pie.lds.S | 40 +++++++++++++
include/linux/pie.h | 146 ++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 396 insertions(+)
create mode 100644 arch/arm/pie/Kconfig
create mode 100644 arch/arm/pie/Makefile
create mode 100644 arch/arm/pie/Makefile.pie
create mode 100644 arch/arm/pie/lib/empty.c
create mode 100644 arch/arm/pie/pie.c
create mode 100644 arch/arm/pie/pie.lds.S
create mode 100644 include/linux/pie.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b5d529fdffab..aba849d7a7cf 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2209,3 +2209,5 @@ endif
source "lib/Kconfig"
source "arch/arm/kvm/Kconfig"
+
+source "arch/arm/pie/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6be9ee148b78..9acb9581853a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -282,6 +282,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/
core-$(CONFIG_XEN) += arch/arm/xen/
core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/
core-$(CONFIG_VDSO) += arch/arm/vdso/
+core-$(CONFIG_PIE) += arch/arm/pie/
# If we have a machine-specific directory, then include it in the build.
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
diff --git a/arch/arm/pie/Kconfig b/arch/arm/pie/Kconfig
new file mode 100644
index 000000000000..d76122140561
--- /dev/null
+++ b/arch/arm/pie/Kconfig
@@ -0,0 +1,8 @@
+config PIE
+ bool
+ help
+ This option adds support for embedding position indepentant (PIE)
+ executables into the kernel. The PIEs can then be copied into
+ genalloc regions such as SRAM and executed. Some platforms require
+ this for suspend/resume support.
+
diff --git a/arch/arm/pie/Makefile b/arch/arm/pie/Makefile
new file mode 100644
index 000000000000..d1a6a823e431
--- /dev/null
+++ b/arch/arm/pie/Makefile
@@ -0,0 +1 @@
+obj-y += pie.o
diff --git a/arch/arm/pie/Makefile.pie b/arch/arm/pie/Makefile.pie
new file mode 100644
index 000000000000..4125da72bcaa
--- /dev/null
+++ b/arch/arm/pie/Makefile.pie
@@ -0,0 +1,86 @@
+obj-y := pie.bin.elf
+
+# Report unresolved symbol references
+ldflags-y += --no-undefined
+# Delete all temporary local symbols
+ldflags-y += -X
+
+GCOV_PROFILE := n
+
+KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
+
+ifeq ($(CONFIG_FUNCTION_TRACER),y)
+ORIG_CFLAGS := $(KBUILD_CFLAGS)
+KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
+endif
+
+# Reset objcopy flags
+OBJCOPYFLAGS =
+
+$(obj)/empty.o: arch/arm/pie/lib/empty.c FORCE
+ $(call if_changed_rule,cc_o_c)
+
+# Reference gcc builtins for use in PIE with __pie_
+$(obj)/pie_rename.syms: $(obj)/empty.o
+ @$(NM) $^ | awk '{if ($$3) print $$3,"__pie_"$(PIE_NAME)$$3}' > $@
+
+# For embedding address of the symbols copied from the PIE into the kernel
+$(obj)/pie.syms: $(obj)/pie.elf
+ @$(NM) $^ | awk '{if ($$3 && $$2 == toupper($$2)) print $$3,"=","0x"$$1";"}' > $@
+
+# Collect together the libpie objects
+LDFLAGS_libpie_stage1.o += -r
+
+$(obj)/libpie_stage1.o: $(obj)/empty.o
+ $(call if_changed,ld)
+
+# Rename the libpie gcc builtins with a __pie_ prefix
+OBJCOPYFLAGS_libpie_stage2.o += --redefine-syms=$(obj)/pie_rename.syms
+
+$(obj)/libpie_stage2.o: $(obj)/libpie_stage1.o
+ $(call if_changed,objcopy)
+
+CFLAGS_$(PIE_NAME).o += -fPIE
+
+OBJCOPYFLAGS_pie_stage1.o += --redefine-syms=$(obj)/pie_rename.syms
+$(obj)/pie_stage1.o: $(obj)/$(PIE_NAME).o $(obj)/pie_rename.syms
+ $(call if_changed,objcopy)
+
+LDFLAGS_pie_stage2.o += -r
+
+$(obj)/pie_stage2.o: $(obj)/pie_stage1.o $(obj)/libpie_stage2.o
+ $(call if_changed,ld)
+
+SEDFLAGS_lds = s/PIE_NAME/$(PIE_NAME)/
+$(obj)/pie.lds.S: arch/arm/pie/pie.lds.S
+ @sed "$(SEDFLAGS_lds)" < $< > $@
+
+# Create the position independent executable
+LDFLAGS_pie.elf += -Bstatic -T $(obj)/pie.lds
+
+$(obj)/pie.elf: $(obj)/pie_stage2.o $(obj)/pie.lds
+ $(call if_changed,ld)
+
+# Create binary data for the kernel
+OBJCOPYFLAGS_pie.bin += -O binary
+
+$(obj)/pie.bin: $(obj)/pie.elf
+ $(call if_changed,objcopy)
+
+# Import the data into the kernel
+ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+OBJCOPYFLAGS_pie.bin.o += -B $(ARCH) -I binary -O elf32-bigarm
+else
+OBJCOPYFLAGS_pie.bin.o += -B $(ARCH) -I binary -O elf32-littlearm
+endif
+
+$(obj)/pie.al.c: $(obj)/pie.elf
+ @$(OBJDUMP) -h --section .text $^ | awk '{sub(/2\*\*/,"(1 << ",$$7);if ($$2 == ".text") print "unsigned int __pie_$(PIE_NAME)_align = "$$7");"}' > $@
+
+$(obj)/pie.bin.o: $(obj)/pie.bin
+ $(call if_changed,objcopy)
+
+LDFLAGS_pie.bin.elf += --just-symbols=$(obj)/pie.syms -r
+$(obj)/pie.bin.elf: $(obj)/pie.bin.o $(obj)/pie.al.o $(obj)/pie.syms
+ $(call if_changed,ld)
+
diff --git a/arch/arm/pie/lib/empty.c b/arch/arm/pie/lib/empty.c
new file mode 100644
index 000000000000..9a6d54956379
--- /dev/null
+++ b/arch/arm/pie/lib/empty.c
@@ -0,0 +1,15 @@
+void __div0(void)
+{
+};
+
+void __aeabi_unwind_cpp_pr0(void)
+{
+};
+
+void __aeabi_unwind_cpp_pr1(void)
+{
+};
+
+void __aeabi_unwind_cpp_pr2(void)
+{
+};
diff --git a/arch/arm/pie/pie.c b/arch/arm/pie/pie.c
new file mode 100644
index 000000000000..b32aa4cb11a8
--- /dev/null
+++ b/arch/arm/pie/pie.c
@@ -0,0 +1,97 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/genalloc.h>
+#include <linux/pie.h>
+#include <asm/cacheflush.h>
+
+struct pie_chunk {
+ struct gen_pool *pool;
+ unsigned long addr;
+ unsigned int align_offset;
+ size_t sz;
+};
+
+struct pie_chunk *__pie_load_data(struct gen_pool *pool, void *code_start,
+ void *code_end, unsigned int align)
+{
+ struct pie_chunk *chunk;
+ unsigned long offset;
+ int ret;
+ size_t code_sz;
+ unsigned long base;
+ phys_addr_t pbase;
+
+ chunk = kzalloc(sizeof(*chunk), GFP_KERNEL);
+ if (!chunk) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ code_sz = code_end - code_start;
+ chunk->pool = pool;
+ chunk->sz = code_sz;
+
+ base = gen_pool_alloc(pool, chunk->sz + align);
+ if (!base) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ pbase = gen_pool_virt_to_phys(pool, base);
+ chunk->addr = (unsigned long)__arm_ioremap_exec(pbase, code_sz, false);
+ if (!chunk->addr) {
+ ret = -ENOMEM;
+ goto err_remap;
+ }
+
+ chunk->align_offset = chunk->addr % align;
+ chunk->addr += chunk->align_offset;
+
+ memcpy((char *)chunk->addr, code_start, code_sz);
+ flush_icache_range(chunk->addr, chunk->addr + code_sz);
+
+ offset = gen_pool_virt_to_phys(pool, chunk->addr);
+
+ return chunk;
+
+err_remap:
+ gen_pool_free(chunk->pool, chunk->addr, chunk->sz);
+
+err_free:
+ kfree(chunk);
+err:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(__pie_load_data);
+
+phys_addr_t pie_to_phys(struct pie_chunk *chunk, unsigned long addr)
+{
+ return gen_pool_virt_to_phys(chunk->pool, addr);
+}
+EXPORT_SYMBOL_GPL(pie_to_phys);
+
+void __iomem *__kern_to_pie(struct pie_chunk *chunk, void *ptr)
+{
+ uintptr_t offset = (uintptr_t)ptr;
+
+ if (offset >= chunk->sz)
+ return NULL;
+ else
+ return (void *)(chunk->addr + offset);
+}
+EXPORT_SYMBOL_GPL(__kern_to_pie);
+
+void pie_free(struct pie_chunk *chunk)
+{
+ gen_pool_free(chunk->pool, chunk->addr, chunk->sz);
+ kfree(chunk);
+}
+EXPORT_SYMBOL_GPL(pie_free);
diff --git a/arch/arm/pie/pie.lds.S b/arch/arm/pie/pie.lds.S
new file mode 100644
index 000000000000..e640c93f5bc8
--- /dev/null
+++ b/arch/arm/pie/pie.lds.S
@@ -0,0 +1,40 @@
+OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+#include <linux/export.h>
+
+SECTIONS
+{
+ /* Don't need unwind tables */
+ /DISCARD/ : {
+ *(.ARM.exidx*)
+ *(.ARM.extab*)
+ *(.comment)
+ }
+
+ . = 0x0;
+
+ ____pie_PIE_NAME_start : {
+ VMLINUX_SYMBOL(__pie_PIE_NAME_start) = .;
+ }
+
+ .text : {
+ . = ALIGN(4);
+ KEEP(*(.text))
+ }
+
+ .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) }
+ . = ALIGN(4);
+
+ .data : {
+ *(SORT_BY_ALIGNMENT(.data*))
+ . = ALIGN(4);
+
+ *(SORT_BY_ALIGNMENT(.bss*))
+ . = ALIGN(4);
+ }
+
+ ____pie_PIE_NAME_end : {
+ VMLINUX_SYMBOL(__pie_PIE_NAME_end) = .;
+ }
+}
diff --git a/include/linux/pie.h b/include/linux/pie.h
new file mode 100644
index 000000000000..cec58384dda2
--- /dev/null
+++ b/include/linux/pie.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2013 Texas Instruments, Inc.
+ * Russ Dill <russ.dill@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_PIE_H
+#define _LINUX_PIE_H
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+
+#include <asm/fncpy.h>
+#include <linux/bug.h>
+
+struct gen_pool;
+struct pie_chunk;
+
+#ifdef CONFIG_PIE
+
+/**
+ * __pie_load_data - load and fixup PIE code from kernel data
+ * @pool: pool to allocate memory from and copy code into
+ * @start: virtual start address in kernel of chunk specific code
+ * @end: virtual end address in kernel of chunk specific code
+ * @phys: %true to fixup to physical address of destination, %false to
+ * fixup to virtual address of destination
+ *
+ * Returns 0 on success, -EERROR otherwise
+ */
+struct pie_chunk *__pie_load_data(struct gen_pool *pool, void *start, void *end,
+ unsigned int align);
+
+/**
+ * pie_to_phys - translate a virtual PIE address into a physical one
+ * @chunk: identifier returned by pie_load_sections
+ * @addr: virtual address within pie chunk
+ *
+ * Returns physical address on success, -1 otherwise
+ */
+phys_addr_t pie_to_phys(struct pie_chunk *chunk, unsigned long addr);
+
+void __iomem *__kern_to_pie(struct pie_chunk *chunk, void *ptr);
+
+/**
+ * pie_free - free the pool space used by an pie chunk
+ * @chunk: identifier returned by pie_load_sections
+ */
+void pie_free(struct pie_chunk *chunk);
+
+#define __pie_load_sections(pool, name, folder) ({ \
+ extern char _binary_##folder##_pie_bin_start[]; \
+ extern char __pie_##name##_start[]; \
+ extern char __pie_##name##_end[]; \
+ extern unsigned int __pie_##name##_align; \
+ char *start = _binary_##folder##_pie_bin_start + \
+ (unsigned long)__pie_##name##_start; \
+ char *end = _binary_##folder##_pie_bin_start + \
+ (unsigned long)__pie_##name##_end; \
+ __pie_load_data(pool, start, end, __pie_##name##_align); \
+})
+
+/*
+ * Required for any symbol within an PIE section that is referenced by the
+ * kernel
+ */
+#define EXPORT_PIE_SYMBOL(sym) extern typeof(sym) sym __weak
+
+#else
+
+static inline struct pie_chunk *__pie_load_data(struct gen_pool *pool,
+ void *start, void *end,
+ unsigned int algin)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline phys_addr_t pie_to_phys(struct pie_chunk *chunk,
+ unsigned long addr)
+{
+ return -1;
+}
+
+static inline void __iomem *__kern_to_pie(struct pie_chunk *chunk, void *ptr)
+{
+ return NULL;
+}
+
+static inline void pie_free(struct pie_chunk *chunk)
+{
+}
+
+#define __pie_load_sections(pool, name, folder, phys) ({ ERR_PTR(-EINVAL); })
+
+#endif
+
+/**
+ * pie_load_sections - load and fixup sections associated with the given name
+ * @pool: pool to allocate memory from and copy code into
+ * fixup to virtual address of destination
+ * @name: the name given to __pie() and __pie_data() when marking
+ * data and code
+ *
+ * Returns 0 on success, -EERROR otherwise
+ */
+#define pie_load_sections(pool, name, folder) ({ \
+ __pie_load_sections(pool, name, folder); \
+})
+
+/**
+ * kern_to_pie - convert a kernel symbol to the virtual address of where
+ * that symbol is loaded into the given PIE chunk.
+ *
+ * @chunk: identifier returned by pie_load_sections
+ * @p: symbol to convert
+ *
+ * Return type is the same as type passed
+ */
+#define kern_to_pie(chunk, p) ({ \
+ void *__ptr = (void *)(p); \
+ typeof(p) __result = (typeof(p))__kern_to_pie(chunk, __ptr); \
+ __result; \
+})
+
+/**
+ * kern_to_fn - convert a kernel function symbol to the virtual address of where
+ * that symbol is loaded into the given PIE chunk
+ *
+ * @chunk: identifier returned by pie_load_sections
+ * @funcp: function to convert
+ *
+ * Return type is the same as type passed
+ */
+#define fn_to_pie(chunk, funcp) ({ \
+ uintptr_t __kern_addr, __pie_addr; \
+ \
+ __kern_addr = (uintptr_t)funcp; \
+ __pie_addr = kern_to_pie(chunk, __kern_addr); \
+ \
+ (typeof(&funcp))(__pie_addr); \
+})
+
+#endif
--
2.10.2
^ permalink raw reply related
* [PATCH v4 2/2] ARM: at91: pm: switch to the PIE infrastructure
From: Alexandre Belloni @ 2016-11-07 22:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161107222458.15732-1-alexandre.belloni@free-electrons.com>
Using the PIE infrastructure allows to write the whole suspend/resume
functions in C instead of assembly.
The only remaining assembly instruction is wfi for armv5
It makes the code shorter and clearer.
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
arch/arm/mach-at91/Kconfig | 1 +
arch/arm/mach-at91/Makefile | 2 +-
arch/arm/mach-at91/pm.c | 31 ++--
arch/arm/mach-at91/pm/.gitignore | 2 +
arch/arm/mach-at91/pm/Makefile | 3 +
arch/arm/mach-at91/pm/atmel_pm.c | 97 +++++++++++
arch/arm/mach-at91/pm_suspend.S | 338 ---------------------------------------
7 files changed, 114 insertions(+), 360 deletions(-)
create mode 100644 arch/arm/mach-at91/pm/.gitignore
create mode 100644 arch/arm/mach-at91/pm/Makefile
create mode 100644 arch/arm/mach-at91/pm/atmel_pm.c
delete mode 100644 arch/arm/mach-at91/pm_suspend.S
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 841e924143f9..cecb20efbf3c 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -5,6 +5,7 @@ menuconfig ARCH_AT91
select GPIOLIB
select PINCTRL
select SOC_BUS
+ select PIE
if ARCH_AT91
config SOC_SAMA5D2
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index c5bbf8bb8c0f..062336de4f66 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_SOC_SAMA5) += sama5.o
# Power Management
obj-$(CONFIG_PM) += pm.o
-obj-$(CONFIG_PM) += pm_suspend.o
+obj-$(CONFIG_PM) += pm/
ifeq ($(CONFIG_CPU_V7),y)
AFLAGS_pm_suspend.o := -march=armv7-a
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index b4332b727e9c..f0a3eee73b86 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
+#include <linux/pie.h>
#include <linux/platform_device.h>
#include <linux/platform_data/atmel.h>
#include <linux/io.h>
@@ -57,6 +58,8 @@ static struct {
void __iomem *at91_ramc_base[2];
+static struct pie_chunk *atmel_pm_pie;
+
static int at91_pm_valid_state(suspend_state_t state)
{
switch (state) {
@@ -134,10 +137,6 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0,
void __iomem *ramc1, int memctrl);
-extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0,
- void __iomem *ramc1, int memctrl);
-extern u32 at91_pm_suspend_in_sram_sz;
-
static void at91_pm_suspend(suspend_state_t state)
{
unsigned int pm_data = at91_pm_data.memctrl;
@@ -371,11 +370,12 @@ static void at91sam9_idle(void)
cpu_do_idle();
}
+extern void atmel_pm_suspend(void __iomem *pmc, void __iomem *ramc0,
+ void __iomem *ramc1, int memctrl);
+
static void __init at91_pm_sram_init(void)
{
struct gen_pool *sram_pool;
- phys_addr_t sram_pbase;
- unsigned long sram_base;
struct device_node *node;
struct platform_device *pdev = NULL;
@@ -398,23 +398,12 @@ static void __init at91_pm_sram_init(void)
return;
}
- sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz);
- if (!sram_base) {
- pr_warn("%s: unable to alloc sram!\n", __func__);
+ atmel_pm_pie = pie_load_sections(sram_pool, atmel_pm,
+ arch_arm_mach_at91_pm);
+ if (IS_ERR(atmel_pm_pie))
return;
- }
-
- sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base);
- at91_suspend_sram_fn = __arm_ioremap_exec(sram_pbase,
- at91_pm_suspend_in_sram_sz, false);
- if (!at91_suspend_sram_fn) {
- pr_warn("SRAM: Could not map\n");
- return;
- }
- /* Copy the pm suspend handler to SRAM */
- at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
- &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
+ at91_suspend_sram_fn = fn_to_pie(atmel_pm_pie, atmel_pm_suspend);
}
static const struct of_device_id atmel_pmc_ids[] __initconst = {
diff --git a/arch/arm/mach-at91/pm/.gitignore b/arch/arm/mach-at91/pm/.gitignore
new file mode 100644
index 000000000000..1cb8879eb0bf
--- /dev/null
+++ b/arch/arm/mach-at91/pm/.gitignore
@@ -0,0 +1,2 @@
+*.lds*
+*.syms
diff --git a/arch/arm/mach-at91/pm/Makefile b/arch/arm/mach-at91/pm/Makefile
new file mode 100644
index 000000000000..c12d54862c10
--- /dev/null
+++ b/arch/arm/mach-at91/pm/Makefile
@@ -0,0 +1,3 @@
+PIE_NAME := atmel_pm
+
+include arch/arm/pie/Makefile.pie
diff --git a/arch/arm/mach-at91/pm/atmel_pm.c b/arch/arm/mach-at91/pm/atmel_pm.c
new file mode 100644
index 000000000000..7f391addd2da
--- /dev/null
+++ b/arch/arm/mach-at91/pm/atmel_pm.c
@@ -0,0 +1,97 @@
+#include <linux/io.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/mfd/syscon/atmel-mc.h>
+#include <linux/pie.h>
+#include "../pm.h"
+
+#define SRAMC_SELF_FRESH_ACTIVE 0x01
+#define SRAMC_SELF_FRESH_EXIT 0x00
+
+static void at91_sramc_self_refresh(unsigned int is_active,
+ unsigned int memtype,
+ void __iomem *sdramc_base,
+ void __iomem *sdramc_base1)
+{
+ static unsigned int lpr, mdr, lpr1, mdr1;
+
+ switch (memtype) {
+ case AT91_MEMCTRL_MC:
+ /*
+ * at91rm9200 Memory controller
+ */
+ if (is_active)
+ __raw_writel(1, sdramc_base + AT91_MC_SDRAMC_SRR);
+ break;
+
+ case AT91_MEMCTRL_DDRSDR:
+ if (is_active) {
+ mdr = __raw_readl(sdramc_base + AT91_DDRSDRC_MDR);
+ lpr = __raw_readl(sdramc_base + AT91_DDRSDRC_LPR);
+
+ if ((mdr & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR)
+ __raw_writel((mdr & ~AT91_DDRSDRC_MD) |
+ AT91_DDRSDRC_MD_DDR2, sdramc_base +
+ AT91_DDRSDRC_MDR);
+ __raw_writel((lpr & ~AT91_DDRSDRC_LPCB) |
+ AT91_DDRSDRC_LPCB_SELF_REFRESH, sdramc_base
+ + AT91_DDRSDRC_LPR);
+
+ if (sdramc_base1) {
+ mdr1 = __raw_readl(sdramc_base1 + AT91_DDRSDRC_MDR);
+ lpr1 = __raw_readl(sdramc_base1 + AT91_DDRSDRC_LPR);
+ if ((mdr1 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR)
+ __raw_writel((mdr1 & ~AT91_DDRSDRC_MD) |
+ AT91_DDRSDRC_MD_DDR2,
+ sdramc_base1 +
+ AT91_DDRSDRC_MDR);
+ __raw_writel((lpr1 & ~AT91_DDRSDRC_LPCB) |
+ AT91_DDRSDRC_LPCB_SELF_REFRESH,
+ sdramc_base1 + AT91_DDRSDRC_LPR);
+ }
+ } else {
+ __raw_writel(mdr, sdramc_base + AT91_DDRSDRC_MDR);
+ __raw_writel(lpr, sdramc_base + AT91_DDRSDRC_LPR);
+ if (sdramc_base1) {
+ __raw_writel(mdr, sdramc_base1 + AT91_DDRSDRC_MDR);
+ __raw_writel(lpr, sdramc_base1 + AT91_DDRSDRC_LPR);
+ }
+ }
+ break;
+
+ case AT91_MEMCTRL_SDRAMC:
+ if (is_active) {
+ lpr = __raw_readl(sdramc_base + AT91_SDRAMC_LPR);
+
+ __raw_writel((lpr & ~AT91_SDRAMC_LPCB) |
+ AT91_SDRAMC_LPCB_SELF_REFRESH, sdramc_base
+ + AT91_SDRAMC_LPR);
+ } else {
+ __raw_writel(lpr, sdramc_base + AT91_SDRAMC_LPR);
+ }
+ break;
+ }
+}
+
+void atmel_pm_suspend(void __iomem *pmc, void __iomem *ramc0,
+ void __iomem *ramc1, int memctrl)
+{
+ int memtype, pm_mode;
+
+ memtype = memctrl & AT91_PM_MEMTYPE_MASK;
+ pm_mode = (memctrl >> AT91_PM_MODE_OFFSET) & AT91_PM_MODE_MASK;
+
+ dsb();
+
+ at91_sramc_self_refresh(1, memtype, ramc0, ramc1);
+
+#if defined(CONFIG_CPU_V7)
+ dsb();
+ wfi();
+#else
+ asm volatile ("mcr p15, 0, %0, c7, c0, 4" \
+ : : "r" (0) : "memory");
+#endif
+
+ at91_sramc_self_refresh(0, memtype, ramc0, ramc1);
+}
+EXPORT_PIE_SYMBOL(atmel_pm_suspend);
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
deleted file mode 100644
index a25defda3d22..000000000000
--- a/arch/arm/mach-at91/pm_suspend.S
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * arch/arm/mach-at91/pm_slow_clock.S
- *
- * Copyright (C) 2006 Savin Zlobec
- *
- * AT91SAM9 support:
- * Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
- *
- * 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/linkage.h>
-#include <linux/clk/at91_pmc.h>
-#include "pm.h"
-
-#define SRAMC_SELF_FRESH_ACTIVE 0x01
-#define SRAMC_SELF_FRESH_EXIT 0x00
-
-pmc .req r0
-tmp1 .req r4
-tmp2 .req r5
-
-/*
- * Wait until master clock is ready (after switching master clock source)
- */
- .macro wait_mckrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_MCKRDY
- beq 1b
- .endm
-
-/*
- * Wait until master oscillator has stabilized.
- */
- .macro wait_moscrdy
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_MOSCS
- beq 1b
- .endm
-
-/*
- * Wait until PLLA has locked.
- */
- .macro wait_pllalock
-1: ldr tmp1, [pmc, #AT91_PMC_SR]
- tst tmp1, #AT91_PMC_LOCKA
- beq 1b
- .endm
-
-/*
- * Put the processor to enter the idle state
- */
- .macro at91_cpu_idle
-
-#if defined(CONFIG_CPU_V7)
- mov tmp1, #AT91_PMC_PCK
- str tmp1, [pmc, #AT91_PMC_SCDR]
-
- dsb
-
- wfi @ Wait For Interrupt
-#else
- mcr p15, 0, tmp1, c7, c0, 4
-#endif
-
- .endm
-
- .text
-
- .arm
-
-/*
- * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc,
- * void __iomem *ramc1, int memctrl)
- * @input param:
- * @r0: base address of AT91_PMC
- * @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS)
- * @r2: base address of second SDRAM Controller or 0 if not present
- * @r3: pm information
- */
-/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
- .align 3
-ENTRY(at91_pm_suspend_in_sram)
- /* Save registers on stack */
- stmfd sp!, {r4 - r12, lr}
-
- /* Drain write buffer */
- mov tmp1, #0
- mcr p15, 0, tmp1, c7, c10, 4
-
- str r0, .pmc_base
- str r1, .sramc_base
- str r2, .sramc1_base
-
- and r0, r3, #AT91_PM_MEMTYPE_MASK
- str r0, .memtype
-
- lsr r0, r3, #AT91_PM_MODE_OFFSET
- and r0, r0, #AT91_PM_MODE_MASK
- str r0, .pm_mode
-
- /* Active the self-refresh mode */
- mov r0, #SRAMC_SELF_FRESH_ACTIVE
- bl at91_sramc_self_refresh
-
- ldr r0, .pm_mode
- tst r0, #AT91_PM_SLOW_CLOCK
- beq skip_disable_main_clock
-
- ldr pmc, .pmc_base
-
- /* Save Master clock setting */
- ldr tmp1, [pmc, #AT91_PMC_MCKR]
- str tmp1, .saved_mckr
-
- /*
- * Set the Master clock source to slow clock
- */
- bic tmp1, tmp1, #AT91_PMC_CSS
- str tmp1, [pmc, #AT91_PMC_MCKR]
-
- wait_mckrdy
-
- /* Save PLLA setting and disable it */
- ldr tmp1, [pmc, #AT91_CKGR_PLLAR]
- str tmp1, .saved_pllar
-
- mov tmp1, #AT91_PMC_PLLCOUNT
- orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */
- str tmp1, [pmc, #AT91_CKGR_PLLAR]
-
- /* Turn off the main oscillator */
- ldr tmp1, [pmc, #AT91_CKGR_MOR]
- bic tmp1, tmp1, #AT91_PMC_MOSCEN
- orr tmp1, tmp1, #AT91_PMC_KEY
- str tmp1, [pmc, #AT91_CKGR_MOR]
-
-skip_disable_main_clock:
- ldr pmc, .pmc_base
-
- /* Wait for interrupt */
- at91_cpu_idle
-
- ldr r0, .pm_mode
- tst r0, #AT91_PM_SLOW_CLOCK
- beq skip_enable_main_clock
-
- ldr pmc, .pmc_base
-
- /* Turn on the main oscillator */
- ldr tmp1, [pmc, #AT91_CKGR_MOR]
- orr tmp1, tmp1, #AT91_PMC_MOSCEN
- orr tmp1, tmp1, #AT91_PMC_KEY
- str tmp1, [pmc, #AT91_CKGR_MOR]
-
- wait_moscrdy
-
- /* Restore PLLA setting */
- ldr tmp1, .saved_pllar
- str tmp1, [pmc, #AT91_CKGR_PLLAR]
-
- tst tmp1, #(AT91_PMC_MUL & 0xff0000)
- bne 3f
- tst tmp1, #(AT91_PMC_MUL & ~0xff0000)
- beq 4f
-3:
- wait_pllalock
-4:
-
- /*
- * Restore master clock setting
- */
- ldr tmp1, .saved_mckr
- str tmp1, [pmc, #AT91_PMC_MCKR]
-
- wait_mckrdy
-
-skip_enable_main_clock:
- /* Exit the self-refresh mode */
- mov r0, #SRAMC_SELF_FRESH_EXIT
- bl at91_sramc_self_refresh
-
- /* Restore registers, and return */
- ldmfd sp!, {r4 - r12, pc}
-ENDPROC(at91_pm_suspend_in_sram)
-
-/*
- * void at91_sramc_self_refresh(unsigned int is_active)
- *
- * @input param:
- * @r0: 1 - active self-refresh mode
- * 0 - exit self-refresh mode
- * register usage:
- * @r1: memory type
- * @r2: base address of the sram controller
- */
-
-ENTRY(at91_sramc_self_refresh)
- ldr r1, .memtype
- ldr r2, .sramc_base
-
- cmp r1, #AT91_MEMCTRL_MC
- bne ddrc_sf
-
- /*
- * at91rm9200 Memory controller
- */
-
- /*
- * For exiting the self-refresh mode, do nothing,
- * automatically exit the self-refresh mode.
- */
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq exit_sramc_sf
-
- /* Active SDRAM self-refresh mode */
- mov r3, #1
- str r3, [r2, #AT91_MC_SDRAMC_SRR]
- b exit_sramc_sf
-
-ddrc_sf:
- cmp r1, #AT91_MEMCTRL_DDRSDR
- bne sdramc_sf
-
- /*
- * DDR Memory controller
- */
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq ddrc_exit_sf
-
- /* LPDDR1 --> force DDR2 mode during self-refresh */
- ldr r3, [r2, #AT91_DDRSDRC_MDR]
- str r3, .saved_sam9_mdr
- bic r3, r3, #~AT91_DDRSDRC_MD
- cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
- ldreq r3, [r2, #AT91_DDRSDRC_MDR]
- biceq r3, r3, #AT91_DDRSDRC_MD
- orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
- streq r3, [r2, #AT91_DDRSDRC_MDR]
-
- /* Active DDRC self-refresh mode */
- ldr r3, [r2, #AT91_DDRSDRC_LPR]
- str r3, .saved_sam9_lpr
- bic r3, r3, #AT91_DDRSDRC_LPCB
- orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
- str r3, [r2, #AT91_DDRSDRC_LPR]
-
- /* If using the 2nd ddr controller */
- ldr r2, .sramc1_base
- cmp r2, #0
- beq no_2nd_ddrc
-
- ldr r3, [r2, #AT91_DDRSDRC_MDR]
- str r3, .saved_sam9_mdr1
- bic r3, r3, #~AT91_DDRSDRC_MD
- cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
- ldreq r3, [r2, #AT91_DDRSDRC_MDR]
- biceq r3, r3, #AT91_DDRSDRC_MD
- orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
- streq r3, [r2, #AT91_DDRSDRC_MDR]
-
- /* Active DDRC self-refresh mode */
- ldr r3, [r2, #AT91_DDRSDRC_LPR]
- str r3, .saved_sam9_lpr1
- bic r3, r3, #AT91_DDRSDRC_LPCB
- orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
- str r3, [r2, #AT91_DDRSDRC_LPR]
-
-no_2nd_ddrc:
- b exit_sramc_sf
-
-ddrc_exit_sf:
- /* Restore MDR in case of LPDDR1 */
- ldr r3, .saved_sam9_mdr
- str r3, [r2, #AT91_DDRSDRC_MDR]
- /* Restore LPR on AT91 with DDRAM */
- ldr r3, .saved_sam9_lpr
- str r3, [r2, #AT91_DDRSDRC_LPR]
-
- /* If using the 2nd ddr controller */
- ldr r2, .sramc1_base
- cmp r2, #0
- ldrne r3, .saved_sam9_mdr1
- strne r3, [r2, #AT91_DDRSDRC_MDR]
- ldrne r3, .saved_sam9_lpr1
- strne r3, [r2, #AT91_DDRSDRC_LPR]
-
- b exit_sramc_sf
-
- /*
- * SDRAMC Memory controller
- */
-sdramc_sf:
- tst r0, #SRAMC_SELF_FRESH_ACTIVE
- beq sdramc_exit_sf
-
- /* Active SDRAMC self-refresh mode */
- ldr r3, [r2, #AT91_SDRAMC_LPR]
- str r3, .saved_sam9_lpr
- bic r3, r3, #AT91_SDRAMC_LPCB
- orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
- str r3, [r2, #AT91_SDRAMC_LPR]
-
-sdramc_exit_sf:
- ldr r3, .saved_sam9_lpr
- str r3, [r2, #AT91_SDRAMC_LPR]
-
-exit_sramc_sf:
- mov pc, lr
-ENDPROC(at91_sramc_self_refresh)
-
-.pmc_base:
- .word 0
-.sramc_base:
- .word 0
-.sramc1_base:
- .word 0
-.memtype:
- .word 0
-.pm_mode:
- .word 0
-.saved_mckr:
- .word 0
-.saved_pllar:
- .word 0
-.saved_sam9_lpr:
- .word 0
-.saved_sam9_lpr1:
- .word 0
-.saved_sam9_mdr:
- .word 0
-.saved_sam9_mdr1:
- .word 0
-
-ENTRY(at91_pm_suspend_in_sram_sz)
- .word .-at91_pm_suspend_in_sram
--
2.10.2
^ permalink raw reply related
* [PATCH 2/8] ARM64: dts: meson-gxl: Add pinctrl nodes
From: Kevin Hilman @ 2016-11-07 22:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477932286-27482-3-git-send-email-narmstrong@baylibre.com>
Neil Armstrong <narmstrong@baylibre.com> writes:
> Add pinctrl nodes and pin definitions for Amlogic Meson GXL.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
> arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 168 +++++++++++++++++++++++++++++
> 1 file changed, 168 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
> index 13b10ee..ce7f550 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
> @@ -42,7 +42,175 @@
> */
>
> #include "meson-gx.dtsi"
> +#include <dt-bindings/gpio/meson-gxl-gpio.h>
Oops, this has a dependency on the patch going through the pinctrl tree,
which causes probelems we like to avoid in the arm-soc tree.
For now, I've changed this to use the GXBB include since the values used
are the same, but we can fix this for good in v4.10-rc, after the GXL
pinctrl changes are merged.
Kevin
[1] [PATCH] pinctrl: meson: Add GXL pinctrl definitions
> / {
> compatible = "amlogic,meson-gxl";
> };
> +
> +&aobus {
> + pinctrl_aobus: pinctrl at 14 {
> + compatible = "amlogic,meson-gxl-aobus-pinctrl";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + gpio_ao: bank at 14 {
> + reg = <0x0 0x00014 0x0 0x8>,
> + <0x0 0x0002c 0x0 0x4>,
> + <0x0 0x00024 0x0 0x8>;
> + reg-names = "mux", "pull", "gpio";
> + gpio-controller;
> + #gpio-cells = <2>;
> + };
> +
> + uart_ao_a_pins: uart_ao_a {
> + mux {
> + groups = "uart_tx_ao_a", "uart_rx_ao_a";
> + function = "uart_ao";
> + };
> + };
> +
> + remote_input_ao_pins: remote_input_ao {
> + mux {
> + groups = "remote_input_ao";
> + function = "remote_input_ao";
> + };
> + };
> + };
> +};
> +
> +&periphs {
> + pinctrl_periphs: pinctrl at 4b0 {
> + compatible = "amlogic,meson-gxl-periphs-pinctrl";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + gpio: bank at 4b0 {
> + reg = <0x0 0x004b0 0x0 0x28>,
> + <0x0 0x004e8 0x0 0x14>,
> + <0x0 0x00120 0x0 0x14>,
> + <0x0 0x00430 0x0 0x40>;
> + reg-names = "mux", "pull", "pull-enable", "gpio";
> + gpio-controller;
> + #gpio-cells = <2>;
> + };
> +
> + emmc_pins: emmc {
> + mux {
> + groups = "emmc_nand_d07",
> + "emmc_cmd",
> + "emmc_clk",
> + "emmc_ds";
> + function = "emmc";
> + };
> + };
> +
> + sdcard_pins: sdcard {
> + mux {
> + groups = "sdcard_d0",
> + "sdcard_d1",
> + "sdcard_d2",
> + "sdcard_d3",
> + "sdcard_cmd",
> + "sdcard_clk";
> + function = "sdcard";
> + };
> + };
> +
> + sdio_pins: sdio {
> + mux {
> + groups = "sdio_d0",
> + "sdio_d1",
> + "sdio_d2",
> + "sdio_d3",
> + "sdio_cmd",
> + "sdio_clk";
> + function = "sdio";
> + };
> + };
> +
> + sdio_irq_pins: sdio_irq {
> + mux {
> + groups = "sdio_irq";
> + function = "sdio";
> + };
> + };
> +
> + uart_a_pins: uart_a {
> + mux {
> + groups = "uart_tx_a",
> + "uart_rx_a";
> + function = "uart_a";
> + };
> + };
> +
> + uart_b_pins: uart_b {
> + mux {
> + groups = "uart_tx_b",
> + "uart_rx_b";
> + function = "uart_b";
> + };
> + };
> +
> + uart_c_pins: uart_c {
> + mux {
> + groups = "uart_tx_c",
> + "uart_rx_c";
> + function = "uart_c";
> + };
> + };
> +
> + i2c_a_pins: i2c_a {
> + mux {
> + groups = "i2c_sck_a",
> + "i2c_sda_a";
> + function = "i2c_a";
> + };
> + };
> +
> + i2c_b_pins: i2c_b {
> + mux {
> + groups = "i2c_sck_b",
> + "i2c_sda_b";
> + function = "i2c_b";
> + };
> + };
> +
> + i2c_c_pins: i2c_c {
> + mux {
> + groups = "i2c_sck_c",
> + "i2c_sda_c";
> + function = "i2c_c";
> + };
> + };
> +
> + eth_pins: eth_c {
> + mux {
> + groups = "eth_mdio",
> + "eth_mdc",
> + "eth_clk_rx_clk",
> + "eth_rx_dv",
> + "eth_rxd0",
> + "eth_rxd1",
> + "eth_rxd2",
> + "eth_rxd3",
> + "eth_rgmii_tx_clk",
> + "eth_tx_en",
> + "eth_txd0",
> + "eth_txd1",
> + "eth_txd2",
> + "eth_txd3";
> + function = "eth";
> + };
> + };
> +
> + pwm_e_pins: pwm_e {
> + mux {
> + groups = "pwm_e";
> + function = "pwm_e";
> + };
> + };
> + };
> +};
^ permalink raw reply
* [PATCH v5 1/7] drm: sunxi: Add a basic DRM driver for Allwinner DE2
From: Maxime Ripard @ 2016-11-07 22:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161028193420.0f7dc67ea1042ff72b09b701@free.fr>
Hi,
On Fri, Oct 28, 2016 at 07:34:20PM +0200, Jean-Francois Moine wrote:
> On Fri, 28 Oct 2016 00:03:16 +0200
> Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
>
> > On Tue, Oct 25, 2016 at 04:14:41PM +0200, Jean-Francois Moine wrote:
> > > > > +Display controller
> > > > > +==================
> > > > > +
> > > > > +Required properties:
> > > > > +
> > > > > +- compatible: value should be one of the following
> > > > > + "allwinner,sun8i-a83t-display-engine"
> > > > > + "allwinner,sun8i-h3-display-engine"
> > > > > +
> > > > > +- clocks: must include clock specifiers corresponding to entries in the
> > > > > + clock-names property.
> > > > > +
> > > > > +- clock-names: must contain
> > > > > + "gate": for DE activation
> > > > > + "clock": DE clock
> > > >
> > > > We've been calling them bus and mod.
> > >
> > > I can understand "bus" (which is better than "apb"), but why "mod"?
> >
> > Allwinner has been calling the clocks that are supposed to generate
> > the external signals (depending on where you were looking) module or
> > mod clocks (which is also why we have mod in the clock
> > compatibles). The module 1 clocks being used for the audio and the
> > module 0 for the rest (SPI, MMC, NAND, display, etc.)
>
> I did not find any 'module' in the H3 documentation.
> So, is it really a good name?
It's true that they use it less nowadays, but they still do,
ie. https://github.com/allwinner-zh/linux-3.4-sunxi/blob/master/drivers/clk/sunxi/clk-sun8iw7.c#L513
And we have to remain consistent anyway.
> > > > > +
> > > > > +- resets: phandle to the reset of the device
> > > > > +
> > > > > +- ports: phandle's to the LCD ports
> > > >
> > > > Please use the OF graph.
> > >
> > > These ports are references to the graph of nodes. See
> > > http://www.kernelhub.org/?msg=911825&p=2
> >
> > In an OF-graph, your phandle to the LCD controller would be replaced
> > by an output endpoint.
>
> This is the DE controller. There is no endpoint link at this level.
The display engine definitely has an endpoint: the TCON.
> The Device Engine just handles the planes of the LCDs, but, indeed,
> the LCDs must know about the DE and the DE must know about the LCDs.
> There are 2 ways to realize this knowledge in the DT:
> 1) either the DE has one or two phandle's to the LCDs,
> 2) or the LCDs have a phandle to the DE.
>
> I chose the 1st way, the DE ports pointing to the endpoint of the LCDs
> which is part of the video link (OF-graph LCD <-> connector).
> It would be possible to have phandles to the LCDs themselves, but this
> asks for more code.
>
> The second way is also possible, but it also complexifies a bit the
> exchanges DE <-> LCD.
I'm still not sure how it would complexify anything, and why you can't
use the display graph to model the relation between the display engine
and the TCON (and why you want to use a generic property that refers
to the of-graph while it really isn't).
> > > > > +void de2_disable_vblank(struct drm_device *drm, unsigned crtc)
> > > > > +{
> > > > > + struct priv *priv = drm->dev_private;
> > > > > + struct lcd *lcd = priv->lcds[crtc];
> > > > > +
> > > > > + tcon_write(lcd->mmio, gint0,
> > > > > + tcon_read(lcd->mmio, gint0) &
> > > > > + ~TCON_GINT0_TCON1_Vb_Int_En);
> > > > > +}
> > > > > +
> > > > > +/* panel functions */
> > > >
> > > > Panel functions? In the CRTC driver?
> > >
> > > Yes, dumb panel.
> >
> > What do you mean by that? Using a Parallel/RGB interface?
>
> Sorry, I though this was a well-known name. The 'dump panel' was used
> in the documentation of my previous ARM machine as the video frame sent
> to the HDMI controller. 'video_frame' is OK for you?
If it's the frame sent to the encoder, then it would be the CRTC by
DRM's nomenclature.
> > > > > +static const struct {
> > > > > + char chan;
> > > > > + char layer;
> > > > > + char pipe;
> > > > > +} plane2layer[DE2_N_PLANES] = {
> > > > > + [DE2_PRIMARY_PLANE] = {0, 0, 0},
> > > > > + [DE2_CURSOR_PLANE] = {1, 0, 1},
> > > > > + [DE2_VI_PLANE] = {0, 1, 0},
> > > > > +};
> > > >
> > > > Comments?
> > >
> > > This
> > > primary plane is channel 0 (VI), layer 0, pipe 0
> > > cursor plane is channel 1 (UI), layer 0, pipe 1
> > > overlay plane is channel 0 (VI), layer 1, pipe 0
> > > or the full explanation:
> > > Constraints:
> > > The VI channels can do RGB or YUV, while UI channels can do RGB
> > > only.
> > > The LCD 0 has 1 VI channel and 4 UI channels, while
> > > LCD 1 has only 1 VI channel and 1 UI channel.
> > > The cursor must go to a channel bigger than the primary channel,
> > > otherwise it is not transparent.
> > > First try:
> > > Letting the primary plane (usually RGB) in the 2nd channel (UI),
> > > as this is done in the legacy driver, asks for the cursor to go
> > > to the next channel (UI), but this one does not exist in LCD1.
> > > Retained layout:
> > > So, we must use only 2 channels for the same behaviour on LCD0
> > > (H3) and LCD1 (A83T)
> > > The retained combination is:
> > > - primary plane in the first channel (VI),
> > > - cursor plane inthe 2nd channel (UI), and
> > > - overlay plane in the 1st channel (VI).
> > >
> > > Note that there could be 3 overlay planes (a channel has 4
> > > layers), but I am not sure that the A83T or the H3 could
> > > support 3 simultaneous video streams...
> >
> > Do you know if the pipe works in the old display engine?
> >
> > Especially about the two-steps composition that wouldn't allow you to
> > have alpha on all the planes?
> >
> > If it is similar, I think hardcoding the pipe number is pretty bad,
> > because that would restrict the combination of planes and formats,
> > while some other might have worked.
>
> From what I understood about the DE2, the pipes just define the priority
> of the overlay channels (one pipe for one channel).
> With the cursor constraint, there must be at least 2 channels in
> order (primary, cursor). Then, with these 2 channels/pipes, there can be
> 6 so-called overlay planes (3 RGB/YUV and 3 RGB only).
> Enabling the pipes 2 and 3 (LCD 0 only) would offer 8 more planes, but
> RGB only. Then, it might be useful to have dynamic pipes.
That's very valuable (and definitely should go into a comment),
thanks!
I still believe that's it should be into a (simple at first)
atomic_check. That would be easier to extend and quite easy to
document and get simply by looking at the code.
> > > > > +static int __init de2_drm_init(void)
> > > > > +{
> > > > > + int ret;
> > > > > +
> > > > > +/* uncomment to activate the drm traces at startup time */
> > > > > +/* drm_debug = DRM_UT_CORE | DRM_UT_DRIVER | DRM_UT_KMS |
> > > > > + DRM_UT_PRIME | DRM_UT_ATOMIC; */
> > > >
> > > > That's useless.
> > >
> > > Right, but it seems that some people don't know how to debug a DRM
> > > driver. This is only a reminder.
> > >
> > > > > + DRM_DEBUG_DRIVER("\n");
> > > > > +
> > > > > + ret = platform_driver_register(&de2_lcd_platform_driver);
> > > > > + if (ret < 0)
> > > > > + return ret;
> > > > > +
> > > > > + ret = platform_driver_register(&de2_drm_platform_driver);
> > > > > + if (ret < 0)
> > > > > + platform_driver_unregister(&de2_lcd_platform_driver);
> > > > > +
> > > > > + return ret;
> > > > > +}
> > > >
> > > > And that really shouldn't be done that way.
> > >
> > > May you explain?
> >
> > This goes against the whole idea of the device and driver
> > model. Drivers should only register themselves, device should be
> > created by buses (or by using some external components if the bus
> > can't: DT, ACPI, etc.). If there's a match, you get probed.
> >
> > A driver that creates its own device just to probe itself violates
> > that.
>
> In this function (module init), there is no driver yet.
> The module contains 2 drivers: the DE (planes) and the LCD (CRTC),
> and there is no macro to handle such modules.
Ah, yes, my bad. I thought you were registering a device and a
driver. Still this is a very unusual pattern. Why do you need to split
the two? Can't you just merge them?
> > > > > +int de2_plane_init(struct drm_device *drm, struct lcd *lcd)
> > > > > +{
> > > > > + int ret, possible_crtcs = 1 << lcd->crtc_idx;
> > > > > +
> > > > > + ret = de2_one_plane_init(drm, &lcd->planes[DE2_PRIMARY_PLANE],
> > > > > + DRM_PLANE_TYPE_PRIMARY, possible_crtcs,
> > > > > + ui_formats, ARRAY_SIZE(ui_formats));
> > > > > + if (ret >= 0)
> > > > > + ret = de2_one_plane_init(drm, &lcd->planes[DE2_CURSOR_PLANE],
> > > > > + DRM_PLANE_TYPE_CURSOR, possible_crtcs,
> > > > > + ui_formats, ARRAY_SIZE(ui_formats));
> > > >
> > > > Nothing looks really special about that cursor plane. Any reasion not
> > > > to make it an overlay?
> > >
> > > As explained above (channel/layer/pipe plane definitions), the cursor
> > > cannot go in a channel lower or equal to the one of the primary plane.
> > > Then, it must be known and, so, have an explicit plane.
> >
> > If you were to make it a plane, you could use atomic_check to check
> > this and make sure this doesn't happen. And you would gain a generic
> > plane that can be used for other purposes if needed.
>
> The function drm_crtc_init_with_planes() offers a cursor plane for free.
> On the other side, having 6 overlay planes is more than the SoCs can
> support.
It's not really for free, it costs you a generic plane that could
definitely be used for something else and cannot anymore because
they've been hardcoded to a cursor.
And having a camera, the VPU or even an application directly output
directly into one of these planes seems a much better use of a generic
plane than a cursor.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161107/1138769a/attachment.sig>
^ permalink raw reply
* [RFC PATCH v2 1/1] PCI/ACPI: xgene: Add ECAM quirk for X-Gene PCIe controller
From: Bjorn Helgaas @ 2016-11-07 22:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CADaLND=xjHkt1yuT+1_P8Ppbrjn+cyKrLEOb_yJNzSWFPcZZJg@mail.gmail.com>
On Wed, Nov 02, 2016 at 01:54:44PM -0700, Duc Dang wrote:
> On Wed, Nov 2, 2016 at 9:53 AM, Bjorn Helgaas <helgaas@kernel.org> wrote:
> > On Tue, Oct 25, 2016 at 06:24:32PM -0700, Duc Dang wrote:
> > > PCIe controllers in X-Gene SoCs is not ECAM compliant: software
> > > needs to configure additional controller's register to address
> > > device at bus:dev:function.
> > >
> > > This patch depends on "ECAM quirks handling for ARM64 platforms"
> > > series (http://www.spinics.net/lists/arm-kernel/msg530692.html,
> > > the series was also modified by Bjorn) to address the limitation
> > > above for X-Gene PCIe controller.
> > >
> > > The quirk will only be applied for X-Gene PCIe MCFG table with
> > > OEM revison 1, 2, 3 or 4 (PCIe controller v1 and v2 on X-Gene SoCs).
> >
> > The quirks here contain some hard-coded address space consumed by
> > ECAM. The ECAM quirk itself is not a generic description of that
> > address space in the sense of a PCI BAR or an ACPI _CRS method, i.e.,
> > the quirk description is not enough to keep other parts of the kernel
> > from treating the address space as "available".
>
> Your concern here is the controller register region that I declared as
> hard-coded array of resource (xgene_vx_csr_res) is not owned by the
> root bridge? So unlike DT case where kernel discovers and knows
> exactly who owns this resource (and we can also use
> platform_get_resource to get the resource); in ACPI case with ECAM
> quirk, kernel knows who requests this resource but does not know who
> owns it? Do I understand correctly?
I think so. MCFG tells the PCI bridge driver where the ECAM space is.
But the ACPI core itself doesn't look at MCFG, so it doesn't know that
space is occupied, and it could potentially assign that space to some
other device, which would cause a conflict.
> > Can you add a note here in the changelog about how you are describing
> > this space generically? The standard solution is a PNP0C02 device
> > with _CRS that describes it.
> >
> > It would be ideal if you could open a bugzilla at bugzilla.kernel.org
> > and attach there a dmesg log, /proc/iomem contents, and DSDT. This
> > would show both the generic PNP0C02 piece and the ECAM quirk piece.
>
> We don't have PNP0C02 device in our ACPI Table. Do you want me add a
> PNP0C02 device into our firmware and check/document the difference in
> /proc/iomem output?
Yes, you should have a PNP0C02 device and its _CRS should describe the
ECAM space. _CRS is generic (not device-specific), and it's what
tells the ACPI core that the space is already in use.
If you already had a PNP0C02 device, you could make a quirk similar to
quirk_amd_mmconfig_area() to add things to its _CRS.
But I think you have firmware in the field that does not have a
PNP0C02 device at all, and that's harder to fix because you would need
to add some sort of fake device.
Rafael, do you have any ideas about this? I can imagine something
like the following, but I don't know what cans of worms it might open:
struct pnp_protocol pnpquirk_protocol = {
.name = "Plug and Play Quirks",
};
void quirk()
{
struct pnp_dev *dev;
struct resource res;
ret = pnp_register_protocol(&pnpquirk_protocol);
if (ret)
return;
dev = pnp_alloc_dev(&pnpquirk_protocol, 0, "PNP0C02");
if (!dev)
return;
res.start = XX; /* ECAM start */
res.end = YY; /* ECAM end */
res.flags = IORESOURCE_MEM;
pnp_add_resource(dev, &res);
dev->active = 1;
pnp_add_device(dev);
dev_info(&dev->dev, "fabricated device to reserve ECAM space %pR\n", &res);
}
> > BTW, I did refresh and re-push the pci/ecam-v6 branch where I'm
> > collecting this stuff, so if you want to rebase your patch on top of
> > that and test it, that would be great.
>
> Thanks, I will definitely do that.
> >
> > > Signed-off-by: Duc Dang <dhdang@apm.com>
> > > ---
> > > v2 changes:
> > > 1. Get rid of pci-xgene-ecam.c file and fold quirk code into pci-xgene.c
> > > 2. Redefine fixup array for X-Gene
> > > 3. Use devm_ioremap_resource to map csr_base
> > >
> > > drivers/acpi/pci_mcfg.c | 30 ++++++++
> > > drivers/pci/host/pci-xgene.c | 165 ++++++++++++++++++++++++++++++++++++++++++-
> > > include/linux/pci-ecam.h | 5 ++
> > > 3 files changed, 197 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
> > > index bb2c508..9dfc937 100644
> > > --- a/drivers/acpi/pci_mcfg.c
> > > +++ b/drivers/acpi/pci_mcfg.c
> > > @@ -96,6 +96,36 @@ struct mcfg_fixup {
> > > THUNDER_ECAM_MCFG(2, 12),
> > > THUNDER_ECAM_MCFG(2, 13),
> > > #endif
> > > +#ifdef CONFIG_PCI_XGENE
> > > +#define XGENE_V1_ECAM_MCFG(rev, seg) \
> > > + {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \
> > > + &xgene_v1_pcie_ecam_ops }
> > > +#define XGENE_V2_1_ECAM_MCFG(rev, seg) \
> > > + {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \
> > > + &xgene_v2_1_pcie_ecam_ops }
> > > +#define XGENE_V2_2_ECAM_MCFG(rev, seg) \
> > > + {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \
> > > + &xgene_v2_2_pcie_ecam_ops }
> > > +
> > > + /* X-Gene SoC with v1 PCIe controller */
> > > + XGENE_V1_ECAM_MCFG(1, 0),
> > > + XGENE_V1_ECAM_MCFG(1, 1),
> > > + XGENE_V1_ECAM_MCFG(1, 2),
> > > + XGENE_V1_ECAM_MCFG(1, 3),
> > > + XGENE_V1_ECAM_MCFG(1, 4),
> > > + XGENE_V1_ECAM_MCFG(2, 0),
> > > + XGENE_V1_ECAM_MCFG(2, 1),
> > > + XGENE_V1_ECAM_MCFG(2, 2),
> > > + XGENE_V1_ECAM_MCFG(2, 3),
> > > + XGENE_V1_ECAM_MCFG(2, 4),
> > > + /* X-Gene SoC with v2.1 PCIe controller */
> > > + XGENE_V2_1_ECAM_MCFG(3, 0),
> > > + XGENE_V2_1_ECAM_MCFG(3, 1),
> > > + /* X-Gene SoC with v2.2 PCIe controller */
> > > + XGENE_V2_2_ECAM_MCFG(4, 0),
> > > + XGENE_V2_2_ECAM_MCFG(4, 1),
> > > + XGENE_V2_2_ECAM_MCFG(4, 2),
> > > +#endif
> > > };
> > >
> > > static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
> > > diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
> > > index 1de23d7..d6aa642 100644
> > > --- a/drivers/pci/host/pci-xgene.c
> > > +++ b/drivers/pci/host/pci-xgene.c
> > > @@ -27,6 +27,8 @@
> > > #include <linux/of_irq.h>
> > > #include <linux/of_pci.h>
> > > #include <linux/pci.h>
> > > +#include <linux/pci-acpi.h>
> > > +#include <linux/pci-ecam.h>
> > > #include <linux/platform_device.h>
> > > #include <linux/slab.h>
> > >
> > > @@ -64,6 +66,7 @@
> > > /* PCIe IP version */
> > > #define XGENE_PCIE_IP_VER_UNKN 0
> > > #define XGENE_PCIE_IP_VER_1 1
> > > +#define XGENE_PCIE_IP_VER_2 2
> > >
> > > struct xgene_pcie_port {
> > > struct device_node *node;
> > > @@ -97,7 +100,15 @@ static inline u32 pcie_bar_low_val(u32 addr, u32 flags)
> > > */
> > > static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus)
> > > {
> > > - struct xgene_pcie_port *port = bus->sysdata;
> > > + struct pci_config_window *cfg;
> > > + struct xgene_pcie_port *port;
> > > +
> > > + if (acpi_disabled)
> > > + port = bus->sysdata;
> > > + else {
> > > + cfg = bus->sysdata;
> > > + port = cfg->priv;
> > > + }
> > >
> > > if (bus->number >= (bus->primary + 1))
> > > return port->cfg_base + AXI_EP_CFG_ACCESS;
> > > @@ -111,10 +122,18 @@ static void __iomem *xgene_pcie_get_cfg_base(struct pci_bus *bus)
> > > */
> > > static void xgene_pcie_set_rtdid_reg(struct pci_bus *bus, uint devfn)
> > > {
> > > - struct xgene_pcie_port *port = bus->sysdata;
> > > + struct pci_config_window *cfg;
> > > + struct xgene_pcie_port *port;
> > > unsigned int b, d, f;
> > > u32 rtdid_val = 0;
> > >
> > > + if (acpi_disabled)
> > > + port = bus->sysdata;
> > > + else {
> > > + cfg = bus->sysdata;
> > > + port = cfg->priv;
> > > + }
> > > +
> > > b = bus->number;
> > > d = PCI_SLOT(devfn);
> > > f = PCI_FUNC(devfn);
> > > @@ -158,7 +177,15 @@ static void __iomem *xgene_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
> > > static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
> > > int where, int size, u32 *val)
> > > {
> > > - struct xgene_pcie_port *port = bus->sysdata;
> > > + struct pci_config_window *cfg;
> > > + struct xgene_pcie_port *port;
> > > +
> > > + if (acpi_disabled)
> > > + port = bus->sysdata;
> > > + else {
> > > + cfg = bus->sysdata;
> > > + port = cfg->priv;
> > > + }
> > >
> > > if (pci_generic_config_read32(bus, devfn, where & ~0x3, 4, val) !=
> > > PCIBIOS_SUCCESSFUL)
> > > @@ -189,6 +216,138 @@ static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
> > > .write = pci_generic_config_write32,
> > > };
> > >
> > > +#ifdef CONFIG_ACPI
> > > +static struct resource xgene_v1_csr_res[] = {
> > > + [0] = DEFINE_RES_MEM(0x1f2b0000UL, SZ_64K),
> > > + [1] = DEFINE_RES_MEM(0x1f2c0000UL, SZ_64K),
> > > + [2] = DEFINE_RES_MEM(0x1f2d0000UL, SZ_64K),
> > > + [3] = DEFINE_RES_MEM(0x1f500000UL, SZ_64K),
> > > + [4] = DEFINE_RES_MEM(0x1f510000UL, SZ_64K),
> > > +};
> > > +
> > > +static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg)
> > > +{
> > > + struct acpi_device *adev = to_acpi_device(cfg->parent);
> > > + struct acpi_pci_root *root = acpi_driver_data(adev);
> > > + struct device *dev = cfg->parent;
> > > + struct xgene_pcie_port *port;
> > > + struct resource *csr;
> > > +
> > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > + if (!port)
> > > + return -ENOMEM;
> > > +
> > > + csr = &xgene_v1_csr_res[root->segment];
> > > + port->csr_base = devm_ioremap_resource(dev, csr);
> > > + if (IS_ERR(port->csr_base)) {
> > > + kfree(port);
> > > + return -ENOMEM;
> > > + }
> > > +
> > > + port->cfg_base = cfg->win;
> > > + port->version = XGENE_PCIE_IP_VER_1;
> > > +
> > > + cfg->priv = port;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +struct pci_ecam_ops xgene_v1_pcie_ecam_ops = {
> > > + .bus_shift = 16,
> > > + .init = xgene_v1_pcie_ecam_init,
> > > + .pci_ops = {
> > > + .map_bus = xgene_pcie_map_bus,
> > > + .read = xgene_pcie_config_read32,
> > > + .write = pci_generic_config_write,
> > > + }
> > > +};
> > > +
> > > +static struct resource xgene_v2_1_csr_res[] = {
> > > + [0] = DEFINE_RES_MEM(0x1f2b0000UL, SZ_64K),
> > > + [1] = DEFINE_RES_MEM(0x1f2c0000UL, SZ_64K),
> > > +};
> > > +
> > > +static int xgene_v2_1_pcie_ecam_init(struct pci_config_window *cfg)
> > > +{
> > > + struct acpi_device *adev = to_acpi_device(cfg->parent);
> > > + struct acpi_pci_root *root = acpi_driver_data(adev);
> > > + struct device *dev = cfg->parent;
> > > + struct xgene_pcie_port *port;
> > > + struct resource *csr;
> > > +
> > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > + if (!port)
> > > + return -ENOMEM;
> > > +
> > > + csr = &xgene_v2_1_csr_res[root->segment];
> > > + port->csr_base = devm_ioremap_resource(dev, csr);
> > > + if (IS_ERR(port->csr_base)) {
> > > + kfree(port);
> > > + return -ENOMEM;
> > > + }
> > > +
> > > + port->cfg_base = cfg->win;
> > > + port->version = XGENE_PCIE_IP_VER_2;
> > > +
> > > + cfg->priv = port;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +struct pci_ecam_ops xgene_v2_1_pcie_ecam_ops = {
> > > + .bus_shift = 16,
> > > + .init = xgene_v2_1_pcie_ecam_init,
> > > + .pci_ops = {
> > > + .map_bus = xgene_pcie_map_bus,
> > > + .read = xgene_pcie_config_read32,
> > > + .write = pci_generic_config_write,
> > > + }
> > > +};
> > > +
> > > +static struct resource xgene_v2_2_csr_res[] = {
> > > + [0] = DEFINE_RES_MEM(0x1f2b0000UL, SZ_64K),
> > > + [1] = DEFINE_RES_MEM(0x1f500000UL, SZ_64K),
> > > + [2] = DEFINE_RES_MEM(0x1f2d0000UL, SZ_64K),
> > > +};
> > > +
> > > +static int xgene_v2_2_pcie_ecam_init(struct pci_config_window *cfg)
> > > +{
> > > + struct acpi_device *adev = to_acpi_device(cfg->parent);
> > > + struct acpi_pci_root *root = acpi_driver_data(adev);
> > > + struct device *dev = cfg->parent;
> > > + struct xgene_pcie_port *port;
> > > + struct resource *csr;
> > > +
> > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > + if (!port)
> > > + return -ENOMEM;
> > > +
> > > + csr = &xgene_v2_2_csr_res[root->segment];
> > > + port->csr_base = devm_ioremap_resource(dev, csr);
> > > + if (IS_ERR(port->csr_base)) {
> > > + kfree(port);
> > > + return -ENOMEM;
> > > + }
> > > +
> > > + port->cfg_base = cfg->win;
> > > + port->version = XGENE_PCIE_IP_VER_2;
> > > +
> > > + cfg->priv = port;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +struct pci_ecam_ops xgene_v2_2_pcie_ecam_ops = {
> > > + .bus_shift = 16,
> > > + .init = xgene_v2_2_pcie_ecam_init,
> > > + .pci_ops = {
> > > + .map_bus = xgene_pcie_map_bus,
> > > + .read = xgene_pcie_config_read32,
> > > + .write = pci_generic_config_write,
> > > + }
> > > +};
> > > +#endif
> > > +
> > > static u64 xgene_pcie_set_ib_mask(struct xgene_pcie_port *port, u32 addr,
> > > u32 flags, u64 size)
> > > {
> > > diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
> > > index 35f0e81..40da3e7 100644
> > > --- a/include/linux/pci-ecam.h
> > > +++ b/include/linux/pci-ecam.h
> > > @@ -65,6 +65,11 @@ void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
> > > #ifdef CONFIG_PCI_HOST_THUNDER_ECAM
> > > extern struct pci_ecam_ops pci_thunder_ecam_ops;
> > > #endif
> > > +#ifdef CONFIG_PCI_XGENE
> > > +extern struct pci_ecam_ops xgene_v1_pcie_ecam_ops;
> > > +extern struct pci_ecam_ops xgene_v2_1_pcie_ecam_ops;
> > > +extern struct pci_ecam_ops xgene_v2_2_pcie_ecam_ops;
> > > +#endif
> > >
> > > #ifdef CONFIG_PCI_HOST_GENERIC
> > > /* for DT-based PCI controllers that support ECAM */
> > > --
> > > 1.9.1
> > >
> Regards,
> Duc Dang.
^ permalink raw reply
* [PATCH 00/30] usb: dwc2: Gadget descriptor DMA and IOT
From: John Youn @ 2016-11-07 22:39 UTC (permalink / raw)
To: linux-arm-kernel
This series implements gadget-side descriptor DMA for the DWC_hsotg
controller.
It also includes support for DWC USB IOT controllers which use the
descriptor DMA mode of operation exclusively. These are two new
device-only USB controller IPs based on DWC_hsotg.
Tested on HAPS platform with:
* HSOTG IP version 3.30a
* FS/LS IOT IP version 1.00a
* HS IOT IP version 1.00a
This series should be applied on top of:
http://marc.info/?l=linux-usb&m=147822095118860&w=2
Regards,
John
John Youn (2):
usb: dwc2: Deprecate g-use-dma binding
usb: dwc2: Enable gadget DDMA by default for HAPS
Vahram Aharonyan (25):
usb: dwc2: Update DMA descriptor structure
usb: dwc2: gadget: Add descriptor DMA binding
usb: dwc2: gadget: Add DMA descriptor status quadlet fields
usb: dwc2: gadget: Enable BNA interrupt in descriptor DMA mode
usb: dwc2: gadget: Add DMA descriptor chains for EP 0
usb: dwc2: host: Rename MAX_DMA_DESC_SIZE to HOST_DMA_NBYTES_LIMIT
usb: dwc2: gadget: Transfer length limit checking for DDMA
usb: dwc2: gadget: Add DDMA chain pointers to dwc2_hsotg_ep structure
usb: dwc2: gadget: Add DDMA chain fill and parse functions
usb: dwc2: gadget: EP 0 specific DDMA programming
usb: dwc2: gadget: DDMA transfer start and complete
usb: dwc2: gadget: Fixes for StsPhseRcvd interrupt
usb: dwc2: gadget: Start DDMA IN status phase in StsPhseRcvd handler
usb: dwc2: gadget: Enable descriptor DMA mode
usb: dwc2: gadget: Add DDMA isoc related fields to dwc2_hsotg_ep
usb: dwc2: gadget: Fill isoc descriptor and start transfer in DDMA
usb: dwc2: gadget: Add completions for DDMA isoc transfers
usb: dwc2: gadget: In DDMA keep incompISOOUT and incompISOIN masked
usb: dwc2: gadget: Add start and complete calls for DDMA ISOC
usb: dwc2: gadget: Adjust ISOC OUT request's actual len for DDMA
usb: dwc2: gadget: Adjustments in debug prints
usb: dwc2: gadget: For DDMA parse setup only after SetUp interrupt
usb: dwc2: gadget: Correct dwc2_hsotg_ep_stop_xfr() function
usb: dwc2: gadget: Disable enabled HW endpoint in
dwc2_hsotg_ep_disable
usb: dwc2: Add support of dedicated full-speed PHY interface
Vardan Mikayelyan (3):
usb: dwc2: gadget: Add IOT device IDs, configure core accordingly
usb: dwc2: gadget: Program ep0_mps for LS
usb: dwc2: gadget: Add new core parameter for low speed
Documentation/devicetree/bindings/usb/dwc2.txt | 6 +-
arch/arm/boot/dts/rk3036.dtsi | 2 +-
arch/arm/boot/dts/rk3288.dtsi | 2 +-
arch/arm/boot/dts/rk3xxx.dtsi | 2 +-
arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 2 +-
arch/arm64/boot/dts/rockchip/rk3368.dtsi | 2 +-
drivers/usb/dwc2/core.h | 48 ++
drivers/usb/dwc2/gadget.c | 978 ++++++++++++++++++++++---
drivers/usb/dwc2/hcd.c | 12 +-
drivers/usb/dwc2/hcd.h | 2 +-
drivers/usb/dwc2/hcd_ddma.c | 52 +-
drivers/usb/dwc2/hw.h | 48 +-
drivers/usb/dwc2/params.c | 42 +-
drivers/usb/dwc2/pci.c | 3 +-
14 files changed, 1039 insertions(+), 162 deletions(-)
--
2.10.0
^ permalink raw reply
* [PATCH 01/30] usb: dwc2: Deprecate g-use-dma binding
From: John Youn @ 2016-11-07 22:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1478558343.git.johnyoun@synopsys.com>
Add a vendor prefix and make the name more consistent by renaming it to
"snps,gadget-dma-enable".
Signed-off-by: John Youn <johnyoun@synopsys.com>
---
Documentation/devicetree/bindings/usb/dwc2.txt | 5 ++++-
arch/arm/boot/dts/rk3036.dtsi | 2 +-
arch/arm/boot/dts/rk3288.dtsi | 2 +-
arch/arm/boot/dts/rk3xxx.dtsi | 2 +-
arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 2 +-
arch/arm64/boot/dts/rockchip/rk3368.dtsi | 2 +-
drivers/usb/dwc2/params.c | 9 ++++++++-
drivers/usb/dwc2/pci.c | 2 +-
8 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt
index 9472111..389a461 100644
--- a/Documentation/devicetree/bindings/usb/dwc2.txt
+++ b/Documentation/devicetree/bindings/usb/dwc2.txt
@@ -26,11 +26,14 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties
- dr_mode: shall be one of "host", "peripheral" and "otg"
Refer to usb/generic.txt
- snps,host-dma-disable: disable host DMA mode.
-- g-use-dma: enable dma usage in gadget driver.
+- snps,gadget-dma-enable: enable gadget DMA mode.
- g-rx-fifo-size: size of rx fifo size in gadget mode.
- g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
+Deprecated properties:
+- g-use-dma: Use "snps,gadget-dma-enable" instead.
+
Example:
usb at 101c0000 {
diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index a935523..2604d2d 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -204,7 +204,7 @@
g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <275>;
g-tx-fifo-size = <256 128 128 64 64 32>;
- g-use-dma;
+ snps,gadget-dma-enable;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 17ec2e2..c0db4ae 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -596,7 +596,7 @@
g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <275>;
g-tx-fifo-size = <256 128 128 64 64 32>;
- g-use-dma;
+ snps,gadget-dma-enable;
phys = <&usbphy0>;
phy-names = "usb2-phy";
status = "disabled";
diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi
index e15beb3..c96d622 100644
--- a/arch/arm/boot/dts/rk3xxx.dtsi
+++ b/arch/arm/boot/dts/rk3xxx.dtsi
@@ -181,7 +181,7 @@
g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <275>;
g-tx-fifo-size = <256 128 128 64 64 32>;
- g-use-dma;
+ snps,gadget-dma-enable;
phys = <&usbphy0>;
phy-names = "usb2-phy";
status = "disabled";
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
index 17839db..fe441f7 100644
--- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
@@ -747,7 +747,7 @@
clocks = <&sys_ctrl HI6220_USBOTG_HCLK>;
clock-names = "otg";
dr_mode = "otg";
- g-use-dma;
+ snps,gadget-dma-enable;
g-rx-fifo-size = <512>;
g-np-tx-fifo-size = <128>;
g-tx-fifo-size = <128 128 128 128 128 128>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
index 0fcb214..6b44544 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -537,7 +537,7 @@
g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <275>;
g-tx-fifo-size = <256 128 128 64 64 32>;
- g-use-dma;
+ snps,gadget-dma-enable;
status = "disabled";
};
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 2eb79e8..aeece91 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -1161,10 +1161,17 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
(hsotg->dr_mode == USB_DR_MODE_OTG)) {
dev_dbg(hsotg->dev, "Setting peripheral device properties\n");
- dwc2_set_param_bool(hsotg, &p->g_dma, true, "g-use-dma",
+ dwc2_set_param_bool(hsotg, &p->g_dma, true,
+ "snps,gadget-dma-enable",
false, false,
dma_capable);
+ /* Check the deprecated property. */
+ if (!p->g_dma)
+ dwc2_set_param_bool(hsotg, &p->g_dma, true, "g-use-dma",
+ false, false,
+ dma_capable);
+
/*
* The values for g_rx_fifo_size (2048) and
* g_np_tx_fifo_size (1024) come from the legacy s3c
diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c
index b3f3b58..46a9d2b 100644
--- a/drivers/usb/dwc2/pci.c
+++ b/drivers/usb/dwc2/pci.c
@@ -67,7 +67,7 @@ static int dwc2_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc2)
if (pdev->vendor == PCI_VENDOR_ID_SYNOPSYS &&
pdev->device == PCI_PRODUCT_ID_HAPS_HSOTG) {
struct property_entry properties[] = {
- PROPERTY_ENTRY_BOOL("g-use-dma"),
+ PROPERTY_ENTRY_BOOL("snps,gadget-dma-enable"),
{ },
};
--
2.10.0
^ permalink raw reply related
* [PATCH v2 1/6] pinctrl-aspeed-g5: Never set SCU90[6]
From: Andrew Jeffery @ 2016-11-07 22:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdbH8eubEHwHCsdJsmqVp3hkBW4vb5DCHvJxz+tyfFqbKQ@mail.gmail.com>
On Mon, 2016-11-07 at 10:34 +0100, Linus Walleij wrote:
> > On Thu, Nov 3, 2016 at 11:59 PM, Joel Stanley <joel@jms.id.au> wrote:
>
> > In the future I think we should send fixes separately from the rest of
> > the series, so it's clear to Linus where we expect patches to end up.
> >
> > Perhaps Linus can share his preference with us?
>
> Just make it clear to me where the patch is headed, if it is
> a fix or a new feature.
>
> Also mixing stuff in big series is of course problematic because
> all the CC:in on MFD patches and whatnot that I don't apply
> makes the picture blurry, but sometimes it is anyways needed
> for context so it is a soft requirement.
Context was my concern here and I would otherwise have split the rest
of the patches along mfd/pinctrl boundaries. I felt the situation was
odd enough to warrant presenting the full picture.
Andrew
>
> Yours,
> Linus Walleij
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161108/472a2ae8/attachment.sig>
^ permalink raw reply
* [PATCH RESEND] ARM: AM43XX: Select OMAP_INTERCONNECT in Kconfig
From: Tony Lindgren @ 2016-11-07 23:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161019204412.18607-1-d-gerlach@ti.com>
* Dave Gerlach <d-gerlach@ti.com> [161019 13:45]:
> AM437x makes use of the omap_l3_noc driver so explicitly select
> OMAP_INTERCONNECT in the Kconfig for SOC_AM43XX to ensure it gets enabled
> for AM43XX only builds.
Applying into omap-for-v4.9/fixes thanks.
Tony
^ permalink raw reply
* [PATCH] ARM: OMAP2+: PRM: initialize en_uart4_mask and grpsel_uart4_mask
From: Tony Lindgren @ 2016-11-07 23:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161024110021.10259-1-colin.king@canonical.com>
* Colin King <colin.king@canonical.com> [161024 04:01]:
> From: Colin Ian King <colin.king@canonical.com>
>
> In the case where has_uart4 is false, en_uart4_mask and grpsel_uart4_mask
> are not initialized and so any garbage value is being logically or'd into
> the write of PM_WKEN and OMAP3430_PM_MPUGRPSEL. Fix this by initializing
> these masks to zero.
Thanks applying into omap-for-v4.9/fixes.
Regards,
Tony
^ permalink raw reply
* [PATCH] ARM: OMAP2+: avoid NULL pointer dereference
From: Tony Lindgren @ 2016-11-07 23:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477993765-9980-1-git-send-email-Nicolae_Rosia@mentor.com>
* Nicolae Rosia <Nicolae_Rosia@mentor.com> [161101 02:50]:
> For OMAP4, volt_data is set in omap44xx_voltagedomains_init.
> If the SoC is neither OMAP443X or OMAP446X, we end up with a
> NULL in volt_data which causes a kernel oops.
> This is the case when booting OMAP4470.
Thanks applying into omap-for-v4.9/fixes.
Tony
^ permalink raw reply
* [PATCH v2] media: s5p-mfc include buffer size in error message
From: Shuah Khan @ 2016-11-07 23:39 UTC (permalink / raw)
To: linux-arm-kernel
Include buffer size in s5p_mfc_alloc_priv_buf() the error message when it
fails to allocate the buffer.
Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
---
Changes since v1:
- Left debug message as is. v1 removed the debug message.
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
index 1e72502..da4f52a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
@@ -45,7 +45,8 @@ int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base,
b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL);
if (!b->virt) {
- mfc_err("Allocating private buffer failed\n");
+ mfc_err("Allocating private buffer of size %zu failed\n",
+ b->size);
return -ENOMEM;
}
--
2.7.4
^ permalink raw reply related
* [PATCH] media: s5p-mfc include buffer size in error message
From: Shuah Khan @ 2016-11-07 23:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b1a9fa02-6821-7637-881c-a31719e891c9@samsung.com>
On 11/04/2016 04:05 AM, Sylwester Nawrocki wrote:
> On 10/18/2016 02:43 AM, Shuah Khan wrote:
>> Include buffer size in s5p_mfc_alloc_priv_buf() the error message when it
>> fails to allocate the buffer. Remove the debug message that does the same.
>>
>> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
>> ---
>> drivers/media/platform/s5p-mfc/s5p_mfc_opr.c | 5 ++---
>> 1 file changed, 2 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
>> index 1e72502..eee16a1 100644
>> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
>> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
>> @@ -40,12 +40,11 @@ void s5p_mfc_init_regs(struct s5p_mfc_dev *dev)
>> int s5p_mfc_alloc_priv_buf(struct device *dev, dma_addr_t base,
>> struct s5p_mfc_priv_buf *b)
>> {
>> - mfc_debug(3, "Allocating priv: %zu\n", b->size);
>
> How about keeping this debug message, I think it would be useful
> to leave that information in the debug logs.
Sent v2 with just the error message change.
thanks,
-- Shuah
>
>> b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL);
>>
>> if (!b->virt) {
>> - mfc_err("Allocating private buffer failed\n");
>> + mfc_err("Allocating private buffer of size %zu failed\n",
>> + b->size);
>> return -ENOMEM;
>> }
>
> --
> Thanks,
> Sylwester
>
^ permalink raw reply
* [PATCH] fpga zynq: Check the bitstream for validity
From: Jason Gunthorpe @ 2016-11-08 0:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4e2c7e1c-7c33-a552-5b91-dbdefac58e37@xilinx.com>
On Tue, Nov 01, 2016 at 06:48:42PM +0100, Michal Simek wrote:
> On 1.11.2016 16:33, Jason Gunthorpe wrote:
> > On Tue, Nov 01, 2016 at 07:39:22AM +0100, Michal Simek wrote:
> >
> >> Regarding BIT and BIN format. This support is in vivado for a long time
> >> and it is up2you what you want to support. We have removed that BIT
> >> support and not doing any swap by saying only BIN format is supported.
> >
> > BIN is not supported, it needs a swap as well.
> >
> > Moritz has it right, you have to use vivado to create a PROM image to be
> > compatible with the driver.
>
> hm than that's bad.
IMHO, Xilinx made an error with Zynq DevC, the DMA does not accept a
memory image that is output by the usual Xilinx tools. It should have
accepted a byte swapped input.
I think Moritz is right, the fpgamgr *should not* alter the bitstream
in any way. This is important for future work to make the DMA do
gather and avoid the really bad high-order allocation.
So users will have to provide byte swapped .bin files - the vivado
write_cfgmem command will produce them - this all needs to be
documented.
Also, I think Punnaiah (?) was telling me that bitstream encryption
does not work - DevC must be told the bitstream is encrypted.
That seems like something that needs work at the fpgamgr level - and
maybe this driver should auto-detect encryption by looking at the
bitfile (as is typical for Xilinx programming)
Jason
^ permalink raw reply
* [PATCH] ARM64: dts: amlogic: Reorder copyrights for meson-gx
From: Kevin Hilman @ 2016-11-08 0:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478460334-17644-1-git-send-email-afaerber@suse.de>
Andreas F?rber <afaerber@suse.de> writes:
> meson-gx.dtsi was directly derived from meson-gxbb.dtsi, so keep the
> copyrights in chronological order to not give a wrong impression.
>
> Fixes: c328666d58aa ("ARM64: dts: amlogic: Add Meson GX dtsi from GXBB")
> Cc: Neil Armstrong <narmstrong@baylibre.com>
> Cc: Kevin Hilman <khilman@baylibre.com>
> Signed-off-by: Andreas F?rber <afaerber@suse.de>
Applied.
Kevin
^ permalink raw reply
* [PATCH] fpga zynq: Check the bitstream for validity
From: Jason Gunthorpe @ 2016-11-08 0:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161029000926.GA30169@live.com>
On Fri, Oct 28, 2016 at 05:09:26PM -0700, Moritz Fischer wrote:
> That being said, I don't like the idea of the driver having to search
> either...
I think we are stuck with that, considering what Xilinx tools
produce..
Here is a v2, what do you think?
>From 93ffde371ca50809ba9b4cdca17051a050b0f92d Mon Sep 17 00:00:00 2001
From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Date: Wed, 26 Oct 2016 16:51:26 -0600
Subject: [PATCH v2] fpga zynq: Check the bitstream for validity
There is no sense in sending a bitstream we know will not work, and
with the variety of options for bitstream generation in Xilinx tools
it is not terribly clear or very well documented what the correct
input should be, especially since auto-detection was removed from this
driver.
All Zynq full configuration bitstreams must start with the sync word in
the correct byte order.
Zynq is also only able to DMA dword quantities, so bitstreams must be
a multiple of 4 bytes. This also fixes a DMA-past the end bug.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
---
drivers/fpga/zynq-fpga.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index c2fb4120bd62..de475a6a1882 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -175,6 +175,19 @@ static irqreturn_t zynq_fpga_isr(int irq, void *data)
return IRQ_HANDLED;
}
+/* Sanity check the proposed bitstream. It must start with the sync word in
+ * the correct byte order. The input is a Xilinx .bin file with every 32 bit
+ * quantity swapped.
+ */
+static bool zynq_fpga_has_sync(const char *buf, size_t count)
+{
+ for (; count > 4; buf += 4, --count)
+ if (buf[0] == 0x66 && buf[1] == 0x55 && buf[2] == 0x99 &&
+ buf[3] == 0xaa)
+ return true;
+ return false;
+}
+
static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
const char *buf, size_t count)
{
@@ -184,12 +197,23 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
priv = mgr->priv;
+ /* The hardware can only DMA multiples of 4 bytes, and we need at
+ * least the sync word and something else to do anything.
+ */
+ if (count <= 4 || (count % 4) != 0)
+ return -EINVAL;
+
err = clk_enable(priv->clk);
if (err)
return err;
/* don't globally reset PL if we're doing partial reconfig */
if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+ if (!zynq_fpga_has_sync(buf, count)) {
+ err = -EINVAL;
+ goto out_err;
+ }
+
/* assert AXI interface resets */
regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET,
FPGA_RST_ALL_MASK);
@@ -287,12 +311,9 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
struct zynq_fpga_priv *priv;
int err;
char *kbuf;
- size_t in_count;
dma_addr_t dma_addr;
- u32 transfer_length;
u32 intr_status;
- in_count = count;
priv = mgr->priv;
kbuf = dma_alloc_coherent(priv->dev, count, &dma_addr, GFP_KERNEL);
@@ -318,11 +339,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
*/
zynq_fpga_write(priv, DMA_SRC_ADDR_OFFSET, (u32)(dma_addr) + 1);
zynq_fpga_write(priv, DMA_DST_ADDR_OFFSET, (u32)DMA_INVALID_ADDRESS);
-
- /* convert #bytes to #words */
- transfer_length = (count + 3) / 4;
-
- zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, transfer_length);
+ zynq_fpga_write(priv, DMA_SRC_LEN_OFFSET, count / 4);
zynq_fpga_write(priv, DMA_DEST_LEN_OFFSET, 0);
wait_for_completion(&priv->dma_done);
@@ -338,7 +355,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr,
clk_disable(priv->clk);
out_free:
- dma_free_coherent(priv->dev, in_count, kbuf, dma_addr);
+ dma_free_coherent(priv->dev, count, kbuf, dma_addr);
return err;
}
--
2.1.4
^ permalink raw reply related
* [PATCH] staging: vc04_services: Add 32-bit compatibility ioctls
From: Michael Zoran @ 2016-11-08 0:48 UTC (permalink / raw)
To: linux-arm-kernel
VCHIQ/vc04_services has a userland device interface
that includes ioctls. The ioctls are very pointer
dependent, so in the case of 32-bit running on top
of a 64-bit kernel, it is necessary to deal with
the structure differences.
The solution to this is that the standard ioctl numbering
mechanism includes a data size field. Since the size of the
userland data structures change between 32-bit and 64-bit,
the length of the data can be used to easily determine the
type of application.
On 64-bit ONLY - Compatibility ioctls are defined.
Example:
Native ioctl:
_IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T)
Compatibility ioctl:
_IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE32_T)
For this particular ioctl, the two ioctls share a different
code path. For some ioctls, it is much easier to share
the same code path and only occasionally handle the differences.
This is typically done by copying the 32-bit datastructure into
the 64-bit datastructure after it has been read from userland.
Testing:
1. vchiq_test -f 10 and vchiq_test -p 1 were run from a native
64-bit OS(debian sid) to check for regressions.
2. vchiq_test -f 10 and vchiq_test -p 1 where run from a 32-bit
chroot install from the same OS to test the compatibility ioctls.
Both test cases now pass.
Signed-off-by: Michael Zoran <mzoran@crowfest.net>
---
.../vc04_services/interface/vchiq_arm/vchiq_arm.c | 269 +++++++++++++++++++++
.../vc04_services/interface/vchiq_arm/vchiq_if.h | 25 ++
.../interface/vchiq_arm/vchiq_ioctl.h | 102 ++++++++
3 files changed, 396 insertions(+)
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index 8fcd940..df343a0 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -573,12 +573,40 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
"vchiq: could not connect: %d", status);
break;
+#if defined(CONFIG_64BIT)
+ case VCHIQ_IOC_CREATE_SERVICE32:
+#endif
case VCHIQ_IOC_CREATE_SERVICE: {
VCHIQ_CREATE_SERVICE_T args;
USER_SERVICE_T *user_service = NULL;
void *userdata;
int srvstate;
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_CREATE_SERVICE32) {
+ VCHIQ_CREATE_SERVICE32_T args32;
+
+ if (copy_from_user
+ (&args32, (const void __user *)arg,
+ sizeof(args32)) != 0) {
+ ret = -EFAULT;
+ break;
+ }
+
+ args.params.fourcc = args32.params.fourcc;
+ args.params.callback =
+ (VCHIQ_CALLBACK_T)(unsigned long)
+ args32.params.callback;
+ args.params.userdata =
+ (void *)(unsigned long)
+ args32.params.userdata;
+ args.params.version = args32.params.version;
+ args.params.version_min = args32.params.version_min;
+ args.is_open = args32.is_open;
+ args.is_vchi = args32.is_vchi;
+ args.handle = args32.handle;
+ } else
+#endif
if (copy_from_user
(&args, (const void __user *)arg,
sizeof(args)) != 0) {
@@ -641,6 +669,19 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
}
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_CREATE_SERVICE32) {
+ if (copy_to_user((void __user *)
+ &(((VCHIQ_CREATE_SERVICE32_T __user *)
+ arg)->handle),
+ (const void *)&service->handle,
+ sizeof(service->handle)) != 0) {
+ ret = -EFAULT;
+ vchiq_remove_service(
+ service->handle);
+ }
+ } else
+#endif
if (copy_to_user((void __user *)
&(((VCHIQ_CREATE_SERVICE_T __user *)
arg)->handle),
@@ -736,6 +777,49 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ret = -EINVAL;
} break;
+#if defined(CONFIG_64BIT)
+ case VCHIQ_IOC_QUEUE_MESSAGE32: {
+ VCHIQ_QUEUE_MESSAGE32_T args32;
+
+ if (copy_from_user
+ (&args32, (const void __user *)arg,
+ sizeof(args32)) != 0) {
+ ret = -EFAULT;
+ break;
+ }
+
+ service = find_service_for_instance(instance, args32.handle);
+
+ if ((service) && (args32.count <= MAX_ELEMENTS)) {
+ /* Copy elements into kernel space */
+ VCHIQ_ELEMENT_T elements[MAX_ELEMENTS];
+ VCHIQ_ELEMENT32_T elements32[MAX_ELEMENTS];
+
+ if (copy_from_user(elements32,
+ (void *)(unsigned long)args32.elements,
+ args32.count * sizeof(VCHIQ_ELEMENT32_T)) == 0) {
+ unsigned int i;
+
+ for (i = 0; i < args32.count; i++) {
+ elements[i].data =
+ (const void *)(unsigned long)
+ elements32[i].data;
+ elements[i].size =
+ elements32[i].size;
+ }
+ status = vchiq_ioc_queue_message
+ (args32.handle,
+ elements, args32.count);
+ }
+ else {
+ ret = -EFAULT;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+ } break;
+#endif
+
case VCHIQ_IOC_QUEUE_MESSAGE: {
VCHIQ_QUEUE_MESSAGE_T args;
if (copy_from_user
@@ -762,6 +846,10 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
} break;
+#if defined(CONFIG_64BIT)
+ case VCHIQ_IOC_QUEUE_BULK_TRANSMIT32:
+ case VCHIQ_IOC_QUEUE_BULK_RECEIVE32:
+#endif
case VCHIQ_IOC_QUEUE_BULK_TRANSMIT:
case VCHIQ_IOC_QUEUE_BULK_RECEIVE: {
VCHIQ_QUEUE_BULK_TRANSFER_T args;
@@ -770,6 +858,28 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
(cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 ||
+ cmd == VCHIQ_IOC_QUEUE_BULK_RECEIVE32) {
+ VCHIQ_QUEUE_BULK_TRANSFER32_T args32;
+
+ if (copy_from_user
+ (&args32, (const void __user *)arg,
+ sizeof(args32)) != 0) {
+ ret = -EFAULT;
+ break;
+ }
+
+ args.handle = args32.handle;
+ args.data = (void *)(unsigned long)args32.data;
+ args.size = args32.size;
+ args.userdata = (void *)(unsigned long)args32.userdata;
+ args.mode = args32.mode;
+
+ dir = (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32) ?
+ VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
+ } else
+#endif
if (copy_from_user
(&args, (const void __user *)arg,
sizeof(args)) != 0) {
@@ -847,6 +957,18 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
"saved bulk_waiter %pK for pid %d",
waiter, current->pid);
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 ||
+ cmd == VCHIQ_IOC_QUEUE_BULK_RECEIVE32) {
+ if (copy_to_user((void __user *)
+ &(((VCHIQ_QUEUE_BULK_TRANSFER32_T __user *)
+ arg)->mode),
+ (const void *)&mode_waiting,
+ sizeof(mode_waiting)) != 0)
+ ret = -EFAULT;
+ } else
+#endif
+
if (copy_to_user((void __user *)
&(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *)
arg)->mode),
@@ -856,6 +978,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
} break;
+#if defined(CONFIG_64BIT)
+ case VCHIQ_IOC_AWAIT_COMPLETION32:
+#endif
case VCHIQ_IOC_AWAIT_COMPLETION: {
VCHIQ_AWAIT_COMPLETION_T args;
@@ -865,6 +990,25 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_AWAIT_COMPLETION32) {
+ VCHIQ_AWAIT_COMPLETION32_T args32;
+
+ if (copy_from_user(&args32, (const void __user *)arg,
+ sizeof(args32)) != 0) {
+ ret = -EFAULT;
+ break;
+ }
+
+ args.count = args32.count;
+ args.buf =
+ (VCHIQ_COMPLETION_DATA_T *)(unsigned long)
+ args32.buf;
+ args.msgbufsize = args32.msgbufsize;
+ args.msgbufcount = args32.msgbufcount;
+ args.msgbufs = (void **)(unsigned long)args32.msgbufs;
+ } else
+#endif
if (copy_from_user(&args, (const void __user *)arg,
sizeof(args)) != 0) {
ret = -EFAULT;
@@ -942,6 +1086,24 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
/* Get the pointer from user space */
msgbufcount--;
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_AWAIT_COMPLETION32) {
+ u32 msgbuf32;
+
+ if (copy_from_user(&msgbuf32,
+ (const void __user *)
+ (void *)(args.msgbufs) +
+ (sizeof(u32) * msgbufcount),
+ sizeof(msgbuf32)) != 0) {
+ if (ret == 0)
+ ret = -EFAULT;
+ break;
+ }
+
+ msgbuf = (void *)(unsigned long)
+ msgbuf32;
+ } else
+#endif
if (copy_from_user(&msgbuf,
(const void __user *)
&args.msgbufs[msgbufcount],
@@ -974,6 +1136,33 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
!instance->use_close_delivered)
unlock_service(service);
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_AWAIT_COMPLETION32) {
+ VCHIQ_COMPLETION_DATA32_T completion32;
+
+ completion32.reason =
+ completion->reason;
+ completion32.header =
+ (u32)(unsigned long)
+ completion->header;
+ completion32.service_userdata =
+ (u32)(unsigned long)
+ completion->service_userdata;
+ completion32.bulk_userdata =
+ (u32)(unsigned long)
+ completion->bulk_userdata;
+
+ if (copy_to_user((void __user *)(
+ (void *)args.buf +
+ ret * sizeof(VCHIQ_COMPLETION_DATA32_T)),
+ &completion32,
+ sizeof(VCHIQ_COMPLETION_DATA32_T)) != 0) {
+ if (ret == 0)
+ ret = -EFAULT;
+ break;
+ }
+ } else
+#endif
if (copy_to_user((void __user *)(
(size_t)args.buf +
ret * sizeof(VCHIQ_COMPLETION_DATA_T)),
@@ -988,6 +1177,17 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
if (msgbufcount != args.msgbufcount) {
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_AWAIT_COMPLETION32) {
+ if (copy_to_user((void __user *)
+ &((VCHIQ_AWAIT_COMPLETION32_T *)arg)->
+ msgbufcount,
+ &msgbufcount,
+ sizeof(msgbufcount)) != 0) {
+ ret = -EFAULT;
+ }
+ } else
+#endif
if (copy_to_user((void __user *)
&((VCHIQ_AWAIT_COMPLETION_T *)arg)->
msgbufcount,
@@ -1004,12 +1204,32 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
} break;
+#if defined(CONFIG_64BIT)
+ case VCHIQ_IOC_DEQUEUE_MESSAGE32:
+#endif
case VCHIQ_IOC_DEQUEUE_MESSAGE: {
VCHIQ_DEQUEUE_MESSAGE_T args;
USER_SERVICE_T *user_service;
VCHIQ_HEADER_T *header;
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
+#if defined(CONFIG_64BIT)
+ if (cmd == VCHIQ_IOC_DEQUEUE_MESSAGE32) {
+ VCHIQ_DEQUEUE_MESSAGE32_T args32;
+
+ if (copy_from_user(&args32,
+ (const void __user *)arg,
+ sizeof(args32)) != 0) {
+ ret = -EFAULT;
+ break;
+ }
+
+ args.handle = args32.handle;
+ args.blocking = args32.blocking;
+ args.bufsize = args32.bufsize;
+ args.buf = (void *)(unsigned long)args32.buf;
+ } else
+#endif
if (copy_from_user
(&args, (const void __user *)arg,
sizeof(args)) != 0) {
@@ -1093,6 +1313,37 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ret = vchiq_get_client_id(handle);
} break;
+#if defined(CONFIG_64BIT)
+ case VCHIQ_IOC_GET_CONFIG32: {
+ VCHIQ_GET_CONFIG32_T args32;
+ VCHIQ_CONFIG_T config;
+
+ if (copy_from_user(&args32,
+ (const void __user *)arg,
+ sizeof(args32)) != 0) {
+ ret = -EFAULT;
+ break;
+ }
+ if (args32.config_size > sizeof(config)) {
+ ret = -EINVAL;
+ break;
+ }
+ status = vchiq_get_config(instance,
+ args32.config_size,
+ &config);
+ if (status == VCHIQ_SUCCESS) {
+ if (copy_to_user((void __user *)(unsigned long)
+ args32.pconfig,
+ &config,
+ args32.config_size)
+ != 0) {
+ ret = -EFAULT;
+ break;
+ }
+ }
+ } break;
+#endif
+
case VCHIQ_IOC_GET_CONFIG: {
VCHIQ_GET_CONFIG_T args;
VCHIQ_CONFIG_T config;
@@ -1136,6 +1387,21 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
args.handle, args.option, args.value);
} break;
+#if defined(CONFIG_64BIT)
+ case VCHIQ_IOC_DUMP_PHYS_MEM32: {
+ VCHIQ_DUMP_MEM32_T args32;
+
+ if (copy_from_user(&args32,
+ (const void __user *)arg,
+ sizeof(args32)) != 0) {
+ ret = -EFAULT;
+ break;
+ }
+ dump_phys_mem((void *)(unsigned long)args32.virt_addr,
+ args32.num_bytes);
+ } break;
+#endif
+
case VCHIQ_IOC_DUMP_PHYS_MEM: {
VCHIQ_DUMP_MEM_T args;
@@ -1660,6 +1926,9 @@ static const struct file_operations
vchiq_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = vchiq_ioctl,
+#if defined(CONFIG_64BIT)
+ .compat_ioctl = vchiq_ioctl,
+#endif
.open = vchiq_open,
.release = vchiq_release,
.read = vchiq_read
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h
index 377e8e4..f4cc324 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h
@@ -93,6 +93,13 @@ typedef struct {
unsigned int size;
} VCHIQ_ELEMENT_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ u32 data;
+ unsigned int size;
+} VCHIQ_ELEMENT32_T;
+#endif
+
typedef unsigned int VCHIQ_SERVICE_HANDLE_T;
typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *,
@@ -104,6 +111,14 @@ typedef struct vchiq_service_base_struct {
void *userdata;
} VCHIQ_SERVICE_BASE_T;
+#if defined(CONFIG_64BIT)
+typedef struct vchiq_service_base_struct32 {
+ int fourcc;
+ u32 callback;
+ u32 userdata;
+} VCHIQ_SERVICE_BASE32_T;
+#endif
+
typedef struct vchiq_service_params_struct {
int fourcc;
VCHIQ_CALLBACK_T callback;
@@ -112,6 +127,16 @@ typedef struct vchiq_service_params_struct {
short version_min; /* Update for incompatible changes */
} VCHIQ_SERVICE_PARAMS_T;
+#if defined(CONFIG_64BIT)
+typedef struct vchiq_service_params_struct32 {
+ int fourcc;
+ u32 callback;
+ u32 userdata;
+ short version; /* Increment for non-trivial changes */
+ short version_min; /* Update for incompatible changes */
+} VCHIQ_SERVICE_PARAMS32_T;
+#endif
+
typedef struct vchiq_config_struct {
unsigned int max_msg_size;
unsigned int bulk_threshold; /* The message size above which it
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
index 6137ae9..001d346 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
@@ -47,12 +47,29 @@ typedef struct {
unsigned int handle; /* OUT */
} VCHIQ_CREATE_SERVICE_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ VCHIQ_SERVICE_PARAMS32_T params;
+ int is_open;
+ int is_vchi;
+ unsigned int handle; /* OUT */
+} VCHIQ_CREATE_SERVICE32_T;
+#endif
+
typedef struct {
unsigned int handle;
unsigned int count;
const VCHIQ_ELEMENT_T *elements;
} VCHIQ_QUEUE_MESSAGE_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ unsigned int handle;
+ unsigned int count;
+ u32 elements;
+} VCHIQ_QUEUE_MESSAGE32_T;
+#endif
+
typedef struct {
unsigned int handle;
void *data;
@@ -61,6 +78,16 @@ typedef struct {
VCHIQ_BULK_MODE_T mode;
} VCHIQ_QUEUE_BULK_TRANSFER_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ unsigned int handle;
+ u32 data;
+ unsigned int size;
+ u32 userdata;
+ VCHIQ_BULK_MODE_T mode;
+} VCHIQ_QUEUE_BULK_TRANSFER32_T;
+#endif
+
typedef struct {
VCHIQ_REASON_T reason;
VCHIQ_HEADER_T *header;
@@ -68,6 +95,15 @@ typedef struct {
void *bulk_userdata;
} VCHIQ_COMPLETION_DATA_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ VCHIQ_REASON_T reason;
+ u32 header;
+ u32 service_userdata;
+ u32 bulk_userdata;
+} VCHIQ_COMPLETION_DATA32_T;
+#endif
+
typedef struct {
unsigned int count;
VCHIQ_COMPLETION_DATA_T *buf;
@@ -76,6 +112,16 @@ typedef struct {
void **msgbufs;
} VCHIQ_AWAIT_COMPLETION_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ unsigned int count;
+ u32 buf;
+ unsigned int msgbufsize;
+ unsigned int msgbufcount; /* IN/OUT */
+ u32 msgbufs;
+} VCHIQ_AWAIT_COMPLETION32_T;
+#endif
+
typedef struct {
unsigned int handle;
int blocking;
@@ -83,11 +129,27 @@ typedef struct {
void *buf;
} VCHIQ_DEQUEUE_MESSAGE_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ unsigned int handle;
+ int blocking;
+ unsigned int bufsize;
+ u32 buf;
+} VCHIQ_DEQUEUE_MESSAGE32_T;
+#endif
+
typedef struct {
unsigned int config_size;
VCHIQ_CONFIG_T *pconfig;
} VCHIQ_GET_CONFIG_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ unsigned int config_size;
+ u32 pconfig;
+} VCHIQ_GET_CONFIG32_T;
+#endif
+
typedef struct {
unsigned int handle;
VCHIQ_SERVICE_OPTION_T option;
@@ -99,24 +161,60 @@ typedef struct {
size_t num_bytes;
} VCHIQ_DUMP_MEM_T;
+#if defined(CONFIG_64BIT)
+typedef struct {
+ u32 virt_addr;
+ u32 num_bytes;
+} VCHIQ_DUMP_MEM32_T;
+
+#endif
+
#define VCHIQ_IOC_CONNECT _IO(VCHIQ_IOC_MAGIC, 0)
#define VCHIQ_IOC_SHUTDOWN _IO(VCHIQ_IOC_MAGIC, 1)
#define VCHIQ_IOC_CREATE_SERVICE \
_IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T)
+#if defined(CONFIG_64BIT)
+#define VCHIQ_IOC_CREATE_SERVICE32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE32_T)
+#endif
#define VCHIQ_IOC_REMOVE_SERVICE _IO(VCHIQ_IOC_MAGIC, 3)
#define VCHIQ_IOC_QUEUE_MESSAGE \
_IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T)
+#if defined(CONFIG_64BIT)
+#define VCHIQ_IOC_QUEUE_MESSAGE32 \
+ _IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE32_T)
+#endif
#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \
_IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T)
+#if defined(CONFIG_64BIT)
+#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER32_T)
+#endif
#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \
_IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T)
+#if defined(CONFIG_64BIT)
+#define VCHIQ_IOC_QUEUE_BULK_RECEIVE32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER32_T)
+#endif
#define VCHIQ_IOC_AWAIT_COMPLETION \
_IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T)
+#if defined(CONFIG_64BIT)
+#define VCHIQ_IOC_AWAIT_COMPLETION32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION32_T)
+#endif
#define VCHIQ_IOC_DEQUEUE_MESSAGE \
_IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T)
+#if defined(CONFIG_64BIT)
+#define VCHIQ_IOC_DEQUEUE_MESSAGE32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE32_T)
+#endif
#define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9)
#define VCHIQ_IOC_GET_CONFIG \
_IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T)
+#if defined(CONFIG_64BIT)
+#define VCHIQ_IOC_GET_CONFIG32 \
+ _IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG32_T)
+#endif
#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11)
#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12)
#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13)
@@ -124,6 +222,10 @@ typedef struct {
_IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T)
#define VCHIQ_IOC_DUMP_PHYS_MEM \
_IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T)
+#if defined(CONFIG_64BIT)
+#define VCHIQ_IOC_DUMP_PHYS_MEM32 \
+ _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM32_T)
+#endif
#define VCHIQ_IOC_LIB_VERSION _IO(VCHIQ_IOC_MAGIC, 16)
#define VCHIQ_IOC_CLOSE_DELIVERED _IO(VCHIQ_IOC_MAGIC, 17)
#define VCHIQ_IOC_MAX 17
--
2.10.2
^ permalink raw reply related
* RE: [RESEND PATCH v3 1/2] PM/devfreq: add suspend frequency support
From: MyungJoo Ham @ 2016-11-08 2:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CGME20161107063403epcas5p4f8d0d95b9a997ca7bf2b2702c3e5d337@epcas5p4.samsung.com>
> Add suspend frequency support and if needed set it to
> the frequency obtained from the suspend opp (can be defined
> using opp-v2 bindings and is optional).
>
> Signed-off-by: Lin Huang <hl@rock-chips.com>
> ---
> Changes in v2:
> - use update_devfreq() instead devfreq_update_status()
> Changes in v3:
> - fix build error
>
> drivers/devfreq/devfreq.c | 18 ++++++++++++++++--
> drivers/devfreq/governor_simpleondemand.c | 9 +++++++++
> include/linux/devfreq.h | 8 ++++++++
> 3 files changed, 33 insertions(+), 2 deletions(-)
>
>
[]
> +void devfreq_opp_get_suspend_opp(struct device *dev, struct devfreq *devfreq)
> +{
> + struct dev_pm_opp *suspend_opp;
> +
> + rcu_read_lock();
> + suspend_opp = dev_pm_opp_get_suspend_opp(dev);
> + if (suspend_opp)
> + devfreq->suspend_freq = dev_pm_opp_get_freq(suspend_opp);
> + rcu_read_unlock();
> +}
> +EXPORT_SYMBOL(devfreq_opp_get_suspend_opp);
> +
Why do we need this function?
This could be done at the init time (devfreq_add_device).
Plus, when it does not have dev_pm_opp_get_suspend_opp() available,
> /**
> * devfreq_register_opp_notifier() - Helper function to get devfreq notified
> * for any changes in the OPP availability
> diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
> index ae72ba5..a3efee0 100644
> --- a/drivers/devfreq/governor_simpleondemand.c
> +++ b/drivers/devfreq/governor_simpleondemand.c
> @@ -29,6 +29,15 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
> struct devfreq_simple_ondemand_data *data = df->data;
> unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX;
>
> + /*
> + * if devfreq in suspend status and have suspend_freq,
> + * the frequency need to set to suspend_freq
> + */
> + if (df->stop_polling && df->suspend_freq) {
> + *freq = df->suspend_freq;
> + return 0;
> + }
> +
Why are you adding this? "Stop polling" does not necessarily mean that
we are doing suspend-to-RAM/disk. It may really mean just to stop at
the current frequency.
Cheers,
MyungJoo
^ permalink raw reply
* [PATCH 2/2] mm: hugetlb: support gigantic surplus pages
From: Huang Shijie @ 2016-11-08 2:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161107162504.17591806@thinkpad>
On Mon, Nov 07, 2016 at 04:25:04PM +0100, Gerald Schaefer wrote:
> On Thu, 3 Nov 2016 10:51:38 +0800
> Huang Shijie <shijie.huang@arm.com> wrote:
>
> > When testing the gigantic page whose order is too large for the buddy
> > allocator, the libhugetlbfs test case "counter.sh" will fail.
> >
> > The failure is caused by:
> > 1) kernel fails to allocate a gigantic page for the surplus case.
> > And the gather_surplus_pages() will return NULL in the end.
> >
> > 2) The condition checks for "over-commit" is wrong.
> >
> > This patch adds code to allocate the gigantic page in the
> > __alloc_huge_page(). After this patch, gather_surplus_pages()
> > can return a gigantic page for the surplus case.
> >
> > This patch also changes the condition checks for:
> > return_unused_surplus_pages()
> > nr_overcommit_hugepages_store()
> >
> > After this patch, the counter.sh can pass for the gigantic page.
> >
> > Acked-by: Steve Capper <steve.capper@arm.com>
> > Signed-off-by: Huang Shijie <shijie.huang@arm.com>
> > ---
> > mm/hugetlb.c | 15 ++++++++++-----
> > 1 file changed, 10 insertions(+), 5 deletions(-)
> >
> > diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> > index 0bf4444..2b67aff 100644
> > --- a/mm/hugetlb.c
> > +++ b/mm/hugetlb.c
> > @@ -1574,7 +1574,7 @@ static struct page *__alloc_huge_page(struct hstate *h,
> > struct page *page;
> > unsigned int r_nid;
> >
> > - if (hstate_is_gigantic(h))
> > + if (hstate_is_gigantic(h) && !gigantic_page_supported())
> > return NULL;
>
> Is it really possible to stumble over gigantic pages w/o having
> gigantic_page_supported()?
>
> Also, I've just tried this on s390 and counter.sh still fails after these
> patches, and it should fail on all archs as long as you use the gigantic
I guess the failure you met is caused by the libhugetlbfs itself, there are
several bugs in the libhugetlbfs. I have a patch set for the
libhugetlbfs too. I will send it as soon as possible.
> hugepage size as default hugepage size. This is because you only changed
> nr_overcommit_hugepages_store(), which handles nr_overcommit_hugepages
> in sysfs, and missed hugetlb_overcommit_handler() which handles
> /proc/sys/vm/nr_overcommit_hugepages for the default sized hugepages.
This is wrong. :)
I did have an extra patch to fix the hugetlb_overcommit_handler().
but the counters.sh does not use the /proc/sys/vm/nr_overcommit_hugepages.
Please grep it in the code.
Thanks
Huang Shijie
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox