Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 06/10] perf/core: Export AUX buffer helpers to modules
From: Will Deacon @ 2017-01-03 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483467027-14547-1-git-send-email-will.deacon@arm.com>

Perf PMU drivers using AUX buffers cannot be built as modules unless
the AUX helpers are exported.

This patch exports perf_aux_output_{begin,end,skip} and perf_get_aux to
modules.

Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 kernel/events/ring_buffer.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 257fa460b846..13b8a46bd517 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -397,6 +397,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
 
 	return NULL;
 }
+EXPORT_SYMBOL(perf_aux_output_begin);
 
 /*
  * Commit the data written by hardware into the ring buffer by adjusting
@@ -458,6 +459,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
 	rb_free_aux(rb);
 	ring_buffer_put(rb);
 }
+EXPORT_SYMBOL(perf_aux_output_end);
 
 /*
  * Skip over a given number of bytes in the AUX buffer, due to, for example,
@@ -486,6 +488,7 @@ int perf_aux_output_skip(struct perf_output_handle *handle, unsigned long size)
 
 	return 0;
 }
+EXPORT_SYMBOL(perf_aux_output_skip);
 
 void *perf_get_aux(struct perf_output_handle *handle)
 {
@@ -495,6 +498,7 @@ void *perf_get_aux(struct perf_output_handle *handle)
 
 	return handle->rb->aux_priv;
 }
+EXPORT_SYMBOL(perf_get_aux);
 
 #define PERF_AUX_GFP	(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY)
 
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 05/10] genirq: export irq_get_percpu_devid_partition to modules
From: Will Deacon @ 2017-01-03 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483467027-14547-1-git-send-email-will.deacon@arm.com>

Any modular driver using cluster-affine PPIs needs to be able to call
irq_get_percpu_devid_partition so that it can enable the IRQ on the
correct subset of CPUs.

This patch exports the symbol so that it can be called from within a
module.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 kernel/irq/irqdesc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 00bb0aeea1d0..1e6ae73eae59 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -856,6 +856,7 @@ int irq_get_percpu_devid_partition(unsigned int irq, struct cpumask *affinity)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(irq_get_percpu_devid_partition);
 
 void kstat_incr_irq_this_cpu(unsigned int irq)
 {
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 04/10] arm64: head.S: Enable EL1 (host) access to SPE when entered at EL2
From: Will Deacon @ 2017-01-03 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483467027-14547-1-git-send-email-will.deacon@arm.com>

The SPE architecture requires each exception level to enable access
to the SPE controls for the exception level below it, since additional
context-switch logic may be required to handle the buffer safely.

This patch allows EL1 (host) access to the SPE controls when entered at
EL2.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/kernel/head.S | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 4b1abac3485a..6a97831dcf3b 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -592,8 +592,8 @@ CPU_LE(	movk	x0, #0x30d0, lsl #16	)	// Clear EE and E0E on LE systems
 #endif
 
 	/* EL2 debug */
-	mrs	x0, id_aa64dfr0_el1		// Check ID_AA64DFR0_EL1 PMUVer
-	sbfx	x0, x0, #8, #4
+	mrs	x1, id_aa64dfr0_el1		// Check ID_AA64DFR0_EL1 PMUVer
+	sbfx	x0, x1, #8, #4
 	cmp	x0, #1
 	b.lt	4f				// Skip if no PMU present
 	mrs	x0, pmcr_el0			// Disable debug access traps
@@ -601,6 +601,16 @@ CPU_LE(	movk	x0, #0x30d0, lsl #16	)	// Clear EE and E0E on LE systems
 4:
 	csel	x0, xzr, x0, lt			// all PMU counters from EL1
 	msr	mdcr_el2, x0			// (if they exist)
+	/* Statistical profiling */
+	ubfx	x0, x1, #32, #4			// Check ID_AA64DFR0_EL1 PMSVer
+	cbz	x0, 5f				// Skip if SPE not present
+	mrs	x0, mdcr_el2			// Preserve HPMN field
+	cmp	x2, xzr				// If VHE is not enabled,
+	mov	x1, #3				// use EL1&0 translations,
+	cinc	x1, x1, ne			// otherwise use EL2 and
+	bfi	x0, x1, #12, #3			// enable/disable access
+	msr	mdcr_el2, x0			// traps accordingly.
+5:
 
 	/* Stage-2 translation */
 	msr	vttbr_el2, xzr
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 03/10] arm64: KVM: Save/restore the host SPE state when entering/leaving a VM
From: Will Deacon @ 2017-01-03 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483467027-14547-1-git-send-email-will.deacon@arm.com>

The SPE buffer is virtually addressed, using the page tables of the CPU
MMU. Unusually, this means that the EL0/1 page table may be live whilst
we're executing at EL2 on non-VHE configurations. When VHE is in use,
we can use the same property to profile the guest behind its back.

This patch adds the relevant disabling and flushing code to KVM so that
the host can make use of SPE without corrupting guest memory, and any
attempts by a guest to use SPE will result in a trap.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Alex Benn?e <alex.bennee@linaro.org>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/kvm_arm.h  |  3 ++
 arch/arm64/include/asm/kvm_host.h |  7 ++++-
 arch/arm64/kvm/debug.c            |  6 ++++
 arch/arm64/kvm/hyp/debug-sr.c     | 66 +++++++++++++++++++++++++++++++++++++--
 arch/arm64/kvm/hyp/switch.c       | 13 +++++++-
 5 files changed, 91 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 2a2752b5b6aa..6e99978e83bd 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -188,6 +188,9 @@
 #define CPTR_EL2_DEFAULT	0x000033ff
 
 /* Hyp Debug Configuration Register bits */
+#define MDCR_EL2_TPMS		(1 << 14)
+#define MDCR_EL2_E2PB_MASK	(UL(0x3))
+#define MDCR_EL2_E2PB_SHIFT	(UL(12))
 #define MDCR_EL2_TDRA		(1 << 11)
 #define MDCR_EL2_TDOSA		(1 << 10)
 #define MDCR_EL2_TDA		(1 << 9)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index e5050388e062..443b387021f2 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -229,7 +229,12 @@ struct kvm_vcpu_arch {
 
 	/* Pointer to host CPU context */
 	kvm_cpu_context_t *host_cpu_context;
-	struct kvm_guest_debug_arch host_debug_state;
+	struct {
+		/* {Break,watch}point registers */
+		struct kvm_guest_debug_arch regs;
+		/* Statistical profiling extension */
+		u64 pmscr_el1;
+	} host_debug_state;
 
 	/* VGIC state */
 	struct vgic_cpu vgic_cpu;
diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
index 47e5f0feaee8..dbadfaf850a7 100644
--- a/arch/arm64/kvm/debug.c
+++ b/arch/arm64/kvm/debug.c
@@ -95,6 +95,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
  *  - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR)
  *  - Debug ROM Address (MDCR_EL2_TDRA)
  *  - OS related registers (MDCR_EL2_TDOSA)
+ *  - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB)
  *
  * Additionally, KVM only traps guest accesses to the debug registers if
  * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY
@@ -110,8 +111,13 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
 
 	trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug);
 
+	/*
+	 * This also clears MDCR_EL2_E2PB_MASK to disable guest access
+	 * to the profiling buffer.
+	 */
 	vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
 	vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
+				MDCR_EL2_TPMS |
 				MDCR_EL2_TPMCR |
 				MDCR_EL2_TDRA |
 				MDCR_EL2_TDOSA);
diff --git a/arch/arm64/kvm/hyp/debug-sr.c b/arch/arm64/kvm/hyp/debug-sr.c
index 4ba5c9095d03..f5154ed3da6c 100644
--- a/arch/arm64/kvm/hyp/debug-sr.c
+++ b/arch/arm64/kvm/hyp/debug-sr.c
@@ -65,6 +65,66 @@
 	default:	write_debug(ptr[0], reg, 0);			\
 	}
 
+#define PMSCR_EL1		sys_reg(3, 0, 9, 9, 0)
+
+#define PMBLIMITR_EL1		sys_reg(3, 0, 9, 10, 0)
+#define PMBLIMITR_EL1_E		BIT(0)
+
+#define PMBIDR_EL1		sys_reg(3, 0, 9, 10, 7)
+#define PMBIDR_EL1_P		BIT(4)
+
+#define psb_csync()		asm volatile("hint #17")
+
+static void __hyp_text __debug_save_spe_vhe(u64 *pmscr_el1)
+{
+	/* The vcpu can run. but it can't hide. */
+}
+
+static void __hyp_text __debug_save_spe_nvhe(u64 *pmscr_el1)
+{
+	u64 reg;
+
+	/* SPE present on this CPU? */
+	if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
+						  ID_AA64DFR0_PMSVER_SHIFT))
+		return;
+
+	/* Yes; is it owned by EL3? */
+	reg = read_sysreg_s(PMBIDR_EL1);
+	if (reg & PMBIDR_EL1_P)
+		return;
+
+	/* No; is the host actually using the thing? */
+	reg = read_sysreg_s(PMBLIMITR_EL1);
+	if (!(reg & PMBLIMITR_EL1_E))
+		return;
+
+	/* Yes; save the control register and disable data generation */
+	*pmscr_el1 = read_sysreg_s(PMSCR_EL1);
+	write_sysreg_s(0, PMSCR_EL1);
+	isb();
+
+	/* Now drain all buffered data to memory */
+	psb_csync();
+	dsb(nsh);
+}
+
+static hyp_alternate_select(__debug_save_spe,
+			    __debug_save_spe_nvhe, __debug_save_spe_vhe,
+			    ARM64_HAS_VIRT_HOST_EXTN);
+
+static void __hyp_text __debug_restore_spe(u64 pmscr_el1)
+{
+	if (!pmscr_el1)
+		return;
+
+	/* The host page table is installed, but not yet synchronised */
+	isb();
+
+	/* Re-enable data generation */
+	write_sysreg_s(pmscr_el1, PMSCR_EL1);
+}
+
 void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu,
 				   struct kvm_guest_debug_arch *dbg,
 				   struct kvm_cpu_context *ctxt)
@@ -118,13 +178,15 @@ void __hyp_text __debug_cond_save_host_state(struct kvm_vcpu *vcpu)
 	    (vcpu->arch.ctxt.sys_regs[MDSCR_EL1] & DBG_MDSCR_MDE))
 		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
 
-	__debug_save_state(vcpu, &vcpu->arch.host_debug_state,
+	__debug_save_state(vcpu, &vcpu->arch.host_debug_state.regs,
 			   kern_hyp_va(vcpu->arch.host_cpu_context));
+	__debug_save_spe()(&vcpu->arch.host_debug_state.pmscr_el1);
 }
 
 void __hyp_text __debug_cond_restore_host_state(struct kvm_vcpu *vcpu)
 {
-	__debug_restore_state(vcpu, &vcpu->arch.host_debug_state,
+	__debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1);
+	__debug_restore_state(vcpu, &vcpu->arch.host_debug_state.regs,
 			      kern_hyp_va(vcpu->arch.host_cpu_context));
 
 	if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 75e83dd40d43..1ee5b06d81e5 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -103,7 +103,13 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
 static void __hyp_text __deactivate_traps_vhe(void)
 {
 	extern char vectors[];	/* kernel exception vectors */
+	u64 mdcr_el2 = read_sysreg(mdcr_el2);
 
+	mdcr_el2 &= MDCR_EL2_HPMN_MASK |
+		    MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT |
+		    MDCR_EL2_TPMS;
+
+	write_sysreg(mdcr_el2, mdcr_el2);
 	write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
 	write_sysreg(CPACR_EL1_FPEN, cpacr_el1);
 	write_sysreg(vectors, vbar_el1);
@@ -111,6 +117,12 @@ static void __hyp_text __deactivate_traps_vhe(void)
 
 static void __hyp_text __deactivate_traps_nvhe(void)
 {
+	u64 mdcr_el2 = read_sysreg(mdcr_el2);
+
+	mdcr_el2 &= MDCR_EL2_HPMN_MASK;
+	mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT;
+
+	write_sysreg(mdcr_el2, mdcr_el2);
 	write_sysreg(HCR_RW, hcr_el2);
 	write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
 }
@@ -132,7 +144,6 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
 
 	__deactivate_traps_arch()();
 	write_sysreg(0, hstr_el2);
-	write_sysreg(read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK, mdcr_el2);
 	write_sysreg(0, pmuserenr_el0);
 }
 
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 02/10] arm64: cpufeature: Don't enforce system-wide SPE capability
From: Will Deacon @ 2017-01-03 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483467027-14547-1-git-send-email-will.deacon@arm.com>

The statistical profiling extension (SPE) is an optional feature of
ARMv8.1 and is unlikely to be supported by all of the CPUs in a
heterogeneous system.

This patch updates the cpufeature checks so that such systems are not
tainted as unsupported.

Reviewed-by: Suzuki Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/sysreg.h | 1 +
 arch/arm64/kernel/cpufeature.c  | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 98ae03f8eedd..e156e7793a65 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -190,6 +190,7 @@
 #define ID_AA64MMFR2_CNP_SHIFT		0
 
 /* id_aa64dfr0 */
+#define ID_AA64DFR0_PMSVER_SHIFT	32
 #define ID_AA64DFR0_CTX_CMPS_SHIFT	28
 #define ID_AA64DFR0_WRPS_SHIFT		20
 #define ID_AA64DFR0_BRPS_SHIFT		12
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 47d0226620e8..c18eb78d3a00 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -180,7 +180,8 @@ static const struct arm64_ftr_bits ftr_id_mmfr0[] = {
 };
 
 static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
-	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
+	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 36, 28, 0),
+	ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64DFR0_PMSVER_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0),
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 01/10] arm64: cpufeature: allow for version discrepancy in PMU implementations
From: Will Deacon @ 2017-01-03 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483467027-14547-1-git-send-email-will.deacon@arm.com>

Perf already supports multiple PMU instances for heterogeneous systems,
so there's no need to be strict in the cpufeature checking, particularly
as the PMU extension is optional in the architecture.

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index fdf8f045929f..47d0226620e8 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -184,7 +184,11 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
 	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0),
-	S_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0),
+	/*
+	 * We can instantiate multiple PMU instances with different levels
+	 * of support.
+	 * */
+	S_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6),
 	ARM64_FTR_END,
-- 
2.1.4

^ permalink raw reply related

* [RFC PATCH 00/10] Add support for the ARMv8.2 Statistical Profiling Extension
From: Will Deacon @ 2017-01-03 18:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

This RFC series adds support for the ARMv8.2 Statistical Profiling
Extension (SPE) to Linux in the form of a perf PMU driver. There aren't
any userspace patches for perf tool yet, but Kim (on CC) is working on
those and I thought posting the kernel side as an RFC was still worth it
in the meantime.

The series is structured as:

  1-2: Tweak arm64 CPU feature detection to support heterogeneous
       configurations where CPUs have differ in debug and profiling
       capabilities.

  3-4: Add EL2 SPE support (KVM world switch and initialisation)

  5-6: Export some functions to modules, so this driver can be built as
       a loadable module.

  7-8: Introduce PERF_AUX_FLAG_COLLISION

  9-10: Add the actual PMU driver and devicetree binding

Like intel-pt, the interface to the PMU is via the perf AUX area and the
profiling hardware writes directly to the pages mapped by userspace. The
hardware capabilities (caps/) and config field encodings (format/) are
advertised via sysfs.

Patches based on v4.10-rc2 and tested on an ARM FastModel.

Will

--->8

Will Deacon (10):
  arm64: cpufeature: allow for version discrepancy in PMU
    implementations
  arm64: cpufeature: Don't enforce system-wide SPE capability
  arm64: KVM: Save/restore the host SPE state when entering/leaving a VM
  arm64: head.S: Enable EL1 (host) access to SPE when entered at EL2
  genirq: export irq_get_percpu_devid_partition to modules
  perf/core: Export AUX buffer helpers to modules
  perf: Directly pass PERF_AUX_* flags to perf_aux_output_end
  perf/core: Add PERF_AUX_FLAG_COLLISION to report colliding samples
  drivers/perf: Add support for ARMv8.2 Statistical Profiling Extension
  dt-bindings: Document devicetree binding for ARM SPE

 Documentation/devicetree/bindings/arm/spe-pmu.txt |   20 +
 arch/arm64/include/asm/kvm_arm.h                  |    3 +
 arch/arm64/include/asm/kvm_host.h                 |    7 +-
 arch/arm64/include/asm/sysreg.h                   |    1 +
 arch/arm64/kernel/cpufeature.c                    |    9 +-
 arch/arm64/kernel/head.S                          |   14 +-
 arch/arm64/kvm/debug.c                            |    6 +
 arch/arm64/kvm/hyp/debug-sr.c                     |   66 +-
 arch/arm64/kvm/hyp/switch.c                       |   13 +-
 arch/x86/events/intel/bts.c                       |   11 +-
 arch/x86/events/intel/pt.c                        |   11 +-
 drivers/hwtracing/coresight/coresight-etm-perf.c  |    5 +-
 drivers/perf/Kconfig                              |    8 +
 drivers/perf/Makefile                             |    1 +
 drivers/perf/arm_spe_pmu.c                        | 1247 +++++++++++++++++++++
 include/linux/perf_event.h                        |    4 +-
 include/uapi/linux/perf_event.h                   |    1 +
 kernel/events/ring_buffer.c                       |   16 +-
 kernel/irq/irqdesc.c                              |    1 +
 19 files changed, 1416 insertions(+), 28 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/spe-pmu.txt
 create mode 100644 drivers/perf/arm_spe_pmu.c

-- 
2.1.4

^ permalink raw reply

* [RFC PATCH] sched: Remove set_task_state()
From: Davidlohr Bueso @ 2017-01-03 18:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170103100453.GB5605@leverpostej>

On Tue, 03 Jan 2017, Mark Rutland wrote:

>Does the below help?

It does, yes. Performance is pretty much the same with either function
without sysreg. With arm no longer in the picture, I'll send up another
patchset with this change as well as Peter's cleanup remarks.

Thanks,
Davidlohr

^ permalink raw reply

* [PATCH 2/2] mmc: sdhci-iproc: Increase max_blk_size for bcm2835
From: Eric Anholt @ 2017-01-03 18:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483111474-29907-3-git-send-email-stefan.wahren@i2se.com>

Stefan Wahren <stefan.wahren@i2se.com> writes:

> According to the BCM2835 datasheet the maximum block size for the
> eMMC module is restricted to the internal data FIFO which is 1024 byte.
> But this is still an improvement to the default of 512 byte.

Confirmed that the internal FIFOs are 1k.

Reviewed-by: Eric Anholt <eric@anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170103/e734aeda/attachment.sig>

^ permalink raw reply

* [PATCH v3 5/6] mfd: dt: Add bindings for the Aspeed SoC Display Controller (GFX)
From: Lee Jones @ 2017-01-03 17:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161206025321.1792-6-andrew@aj.id.au>

On Tue, 06 Dec 2016, Andrew Jeffery wrote:

> The Aspeed SoC Display Controller is presented as a syscon device to
> arbitrate access by display and pinmux drivers. Video pinmux
> configuration on fifth generation SoCs depends on bits in both the
> System Control Unit and the Display Controller.
> 
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> Acked-by: Rob Herring <robh@kernel.org>

Applied with Acks, thanks.

> ---
>  .../devicetree/bindings/mfd/syscon/aspeed-gfx.txt       | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/syscon/aspeed-gfx.txt
> 
> diff --git a/Documentation/devicetree/bindings/mfd/syscon/aspeed-gfx.txt b/Documentation/devicetree/bindings/mfd/syscon/aspeed-gfx.txt
> new file mode 100644
> index 000000000000..aea5370efd97
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/syscon/aspeed-gfx.txt
> @@ -0,0 +1,17 @@
> +* Device tree bindings for Aspeed SoC Display Controller (GFX)
> +
> +The Aspeed SoC Display Controller primarily does as its name suggests, but also
> +participates in pinmux requests on the g5 SoCs. It is therefore considered a
> +syscon device.
> +
> +Required properties:
> +- compatible:		"aspeed,ast2500-gfx", "syscon"
> +- reg:			contains offset/length value of the GFX memory
> +			region.
> +
> +Example:
> +
> +gfx: display at 1e6e6000 {
> +	compatible = "aspeed,ast2500-gfx", "syscon";
> +	reg = <0x1e6e6000 0x1000>;
> +};

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH v3 1/6] mfd: dt: Fix "indicates" typo in mfd bindings document
From: Lee Jones @ 2017-01-03 17:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161206025321.1792-2-andrew@aj.id.au>

On Tue, 06 Dec 2016, Andrew Jeffery wrote:

> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>

Applied with Acks, thanks.

> ---
>  Documentation/devicetree/bindings/mfd/mfd.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/mfd.txt b/Documentation/devicetree/bindings/mfd/mfd.txt
> index af9d6931a1a2..f1fceeda12f1 100644
> --- a/Documentation/devicetree/bindings/mfd/mfd.txt
> +++ b/Documentation/devicetree/bindings/mfd/mfd.txt
> @@ -19,7 +19,7 @@ Optional properties:
>  
>  - compatible : "simple-mfd" - this signifies that the operating system should
>    consider all subnodes of the MFD device as separate devices akin to how
> -  "simple-bus" inidicates when to see subnodes as children for a simple
> +  "simple-bus" indicates when to see subnodes as children for a simple
>    memory-mapped bus. For more complex devices, when the nexus driver has to
>    probe registers to figure out what child devices exist etc, this should not
>    be used. In the latter case the child devices will be determined by the

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH v3 2/6] mfd: dt: ranges, #address-cells and #size-cells as optional properties
From: Lee Jones @ 2017-01-03 17:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161206025321.1792-3-andrew@aj.id.au>

On Tue, 06 Dec 2016, Andrew Jeffery wrote:

> Whilst describing a device and not a bus, simple-mfd is modelled on
> simple-bus where child nodes are iterated and registered as platform
> devices. Some complex devices, e.g. the Aspeed LPC controller, can
> benefit from address space mapping such that child nodes can use the
> regs property to describe their resources within the multi-function
> device.
> 
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>

Applied with Acks, thanks.

> ---
>  Documentation/devicetree/bindings/mfd/mfd.txt | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/mfd.txt b/Documentation/devicetree/bindings/mfd/mfd.txt
> index f1fceeda12f1..bcb6abb9d413 100644
> --- a/Documentation/devicetree/bindings/mfd/mfd.txt
> +++ b/Documentation/devicetree/bindings/mfd/mfd.txt
> @@ -25,6 +25,16 @@ Optional properties:
>    be used. In the latter case the child devices will be determined by the
>    operating system.
>  
> +- ranges: Describes the address mapping relationship to the parent. Should set
> +  the child's base address to 0, the physical address within parent's address
> +  space, and the length of the address map.
> +
> +- #address-cells: Specifies the number of cells used to represent physical base
> +  addresses. Must be present if ranges is used.
> +
> +- #size-cells: Specifies the number of cells used to represent the size of an
> +  address. Must be present if ranges is used.
> +
>  Example:
>  
>  foo at 1000 {

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH v3 3/6] mfd: dt: Add Aspeed Low Pin Count Controller bindings
From: Lee Jones @ 2017-01-03 17:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161206025321.1792-4-andrew@aj.id.au>

On Tue, 06 Dec 2016, Andrew Jeffery wrote:

> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>

Applied with Acks, thanks.

> ---
>  .../devicetree/bindings/mfd/aspeed-lpc.txt         | 111 +++++++++++++++++++++
>  1 file changed, 111 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> 
> diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt b/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> new file mode 100644
> index 000000000000..a97131aba446
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> @@ -0,0 +1,111 @@
> +======================================================================
> +Device tree bindings for the Aspeed Low Pin Count (LPC) Bus Controller
> +======================================================================
> +
> +The LPC bus is a means to bridge a host CPU to a number of low-bandwidth
> +peripheral devices, replacing the use of the ISA bus in the age of PCI[0]. The
> +primary use case of the Aspeed LPC controller is as a slave on the bus
> +(typically in a Baseboard Management Controller SoC), but under certain
> +conditions it can also take the role of bus master.
> +
> +The LPC controller is represented as a multi-function device to account for the
> +mix of functionality it provides. The principle split is between the register
> +layout at the start of the I/O space which is, to quote the Aspeed datasheet,
> +"basically compatible with the [LPC registers from the] popular BMC controller
> +H8S/2168[1]", and everything else, where everything else is an eclectic
> +collection of functions with a esoteric register layout. "Everything else",
> +here labeled the "host" portion of the controller, includes, but is not limited
> +to:
> +
> +* An IPMI Block Transfer[2] Controller
> +
> +* An LPC Host Controller: Manages LPC functions such as host vs slave mode, the
> +  physical properties of some LPC pins, configuration of serial IRQs, and
> +  APB-to-LPC bridging amonst other functions.
> +
> +* An LPC Host Interface Controller: Manages functions exposed to the host such
> +  as LPC firmware hub cycles, configuration of the LPC-to-AHB mapping, UART
> +  management and bus snoop configuration.
> +
> +* A set of SuperIO[3] scratch registers: Enables implementation of e.g. custom
> +  hardware management protocols for handover between the host and baseboard
> +  management controller.
> +
> +Additionally the state of the LPC controller influences the pinmux
> +configuration, therefore the host portion of the controller is exposed as a
> +syscon as a means to arbitrate access.
> +
> +[0] http://www.intel.com/design/chipsets/industry/25128901.pdf
> +[1] https://www.renesas.com/en-sg/doc/products/mpumcu/001/rej09b0078_h8s2168.pdf?key=7c88837454702128622bee53acbda8f4
> +[2] http://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf
> +[3] https://en.wikipedia.org/wiki/Super_I/O
> +
> +Required properties
> +===================
> +
> +- compatible:	One of:
> +		"aspeed,ast2400-lpc", "simple-mfd"
> +		"aspeed,ast2500-lpc", "simple-mfd"
> +
> +- reg:		contains the physical address and length values of the Aspeed
> +                LPC memory region.
> +
> +- #address-cells: <1>
> +- #size-cells:	<1>
> +- ranges: 	Maps 0 to the physical address and length of the LPC memory
> +                region
> +
> +Required LPC Child nodes
> +========================
> +
> +BMC Node
> +--------
> +
> +- compatible:	One of:
> +		"aspeed,ast2400-lpc-bmc"
> +		"aspeed,ast2500-lpc-bmc"
> +
> +- reg:		contains the physical address and length values of the
> +                H8S/2168-compatible LPC controller memory region
> +
> +Host Node
> +---------
> +
> +- compatible:   One of:
> +		"aspeed,ast2400-lpc-host", "simple-mfd", "syscon"
> +		"aspeed,ast2500-lpc-host", "simple-mfd", "syscon"
> +
> +- reg:		contains the address and length values of the host-related
> +                register space for the Aspeed LPC controller
> +
> +- #address-cells: <1>
> +- #size-cells:	<1>
> +- ranges: 	Maps 0 to the address and length of the host-related LPC memory
> +                region
> +
> +Example:
> +
> +lpc: lpc at 1e789000 {
> +	compatible = "aspeed,ast2500-lpc", "simple-mfd";
> +	reg = <0x1e789000 0x1000>;
> +
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +	ranges = <0x0 0x1e789000 0x1000>;
> +
> +	lpc_bmc: lpc-bmc at 0 {
> +		compatible = "aspeed,ast2500-lpc-bmc";
> +		reg = <0x0 0x80>;
> +	};
> +
> +	lpc_host: lpc-host at 80 {
> +		compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
> +		reg = <0x80 0x1e0>;
> +		reg-io-width = <4>;
> +
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		ranges = <0x0 0x80 0x1e0>;
> +	};
> +};
> +

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH v2 04/12] driver: clk: imx: Add clock driver for imx6sll
From: Rob Herring @ 2017-01-03 17:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482832070-22668-5-git-send-email-ping.bai@nxp.com>

On Tue, Dec 27, 2016 at 05:47:42PM +0800, Bai Ping wrote:
> Add clk driver support for imx6sll.
> 
> Signed-off-by: Bai Ping <ping.bai@nxp.com>
> ---
>  drivers/clk/imx/Makefile                  |   1 +
>  drivers/clk/imx/clk-imx6sll.c             | 369 ++++++++++++++++++++++++++++++

>  include/dt-bindings/clock/imx6sll-clock.h | 204 +++++++++++++++++

This should be part of the binding doc patch.

>  3 files changed, 574 insertions(+)
>  create mode 100644 drivers/clk/imx/clk-imx6sll.c
>  create mode 100644 include/dt-bindings/clock/imx6sll-clock.h

^ permalink raw reply

* [PATCH v3 4/6] mfd: dt: Add bindings for the Aspeed LPC Host Controller (LHC)
From: Lee Jones @ 2017-01-03 17:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161206025321.1792-5-andrew@aj.id.au>

On Tue, 06 Dec 2016, Andrew Jeffery wrote:

> The LPC bus pinmux configuration on fifth generation Aspeed SoCs depends
> on bits in both the System Control Unit and the LPC Host Controller.
> 
> The Aspeed LPC Host Controller is described as a child node of the
> LPC host-range syscon device for arbitration of access by the host
> controller and pinmux drivers.
> 
> Signed-off-by: Andrew Jeffery <andrew@aj.id.au>

Applied with Acks, thanks.

> ---
>  .../devicetree/bindings/mfd/aspeed-lpc.txt         | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt b/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> index a97131aba446..9de318ef72da 100644
> --- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt
> @@ -109,3 +109,25 @@ lpc: lpc at 1e789000 {
>  	};
>  };
>  
> +Host Node Children
> +==================
> +
> +LPC Host Controller
> +-------------------
> +
> +The Aspeed LPC Host Controller configures the Low Pin Count (LPC) bus behaviour
> +between the host and the baseboard management controller. The registers exist
> +in the "host" portion of the Aspeed LPC controller, which must be the parent of
> +the LPC host controller node.
> +
> +Required properties:
> +- compatible:		"aspeed,ast2500-lhc";
> +- reg:			contains offset/length value of the LHC memory
> +			region.
> +
> +Example:
> +
> +lhc: lhc at 20 {
> +	compatible = "aspeed,ast2500-lhc";
> +	reg = <0x20 0x24 0x48 0x8>;
> +};

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH v2 03/12] Document: dt: binding: imx: update clock doc for imx6sll
From: Rob Herring @ 2017-01-03 17:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482832070-22668-4-git-send-email-ping.bai@nxp.com>

On Tue, Dec 27, 2016 at 05:47:41PM +0800, Bai Ping wrote:
> Add clock binding doc uppdate for imx6sll.

s/uppdate/update/

> 
> Signed-off-by: Bai Ping <ping.bai@nxp.com>
> ---
>  .../devicetree/bindings/clock/imx6sll-clock.txt    | 37 ++++++++++++++++++++++
>  1 file changed, 37 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/imx6sll-clock.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/imx6sll-clock.txt b/Documentation/devicetree/bindings/clock/imx6sll-clock.txt
> new file mode 100644
> index 0000000..3a46787
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/imx6sll-clock.txt
> @@ -0,0 +1,37 @@
> +* Clock bindings for Freescale i.MX6 SLL
> +
> +Required properties:
> +- compatible: Should be "fsl,imx6sll-ccm"
> +- reg: Address and length of the register set
> +- #clock-cells: Should be <1>
> +- clocks: list of clock specifiers, must contain an entry for each required
> +  entry in clock-names
> +- clock-names: should include entries "ckil", "osc", "ipp_di0" and "ipp_di1"
> +
> +The clock consumer should specify the desired clock by having the clock
> +ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx6sll-clock.h
> +for the full list of i.MX6 SLL clock IDs.
> +
> +Examples:
> +
> +#include <dt-bindings/clock/imx6sll-clock.h>
> +
> +clks: ccm at 020c4000 {

Drop leading 0s.

> +		compatible = "fsl,imx6sll-ccm";
> +		reg = <0x020c4000 0x4000>;
> +		interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> +		#clock-cells = <1>;
> +		clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
> +		clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
> +};
> +
> +uart1: serial at 02020000 {

ditto.

> +		compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart", "fsl,imx21-uart";
> +		reg = <0x02020000 0x4000>;
> +		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX6SLL_CLK_UART1_IPG>,
> +			 <&clks IMX6SLL_CLK_UART1_SERIAL>;
> +		clock-names = "ipg", "per";
> +		status = "disabled";
> +};
> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 0/6] staging: vchiq_arm: Fine-tuning for some function implementations
From: Eric Anholt @ 2017-01-03 17:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5acd65e7-0b5d-0972-5e1a-6e87d71dc1a4@users.sourceforge.net>

SF Markus Elfring <elfring@users.sourceforge.net> writes:

> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Sat, 31 Dec 2016 22:42:34 +0100
>
> Some update suggestions were taken into account
> from static source code analysis.

This series is:

Reviewed-by: Eric Anholt <eric@anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170103/9f31ad45/attachment.sig>

^ permalink raw reply

* [PATCH 8/9] irqchip/ls-scfg-msi: add LS1043a v1.1 MSI support
From: Rob Herring @ 2017-01-03 17:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482829985-24421-8-git-send-email-Minghuan.Lian@nxp.com>

On Tue, Dec 27, 2016 at 05:13:04PM +0800, Minghuan Lian wrote:
> A MSI controller of LS1043a v1.0 only includes one MSIR and
> is assigned one GIC interrupt. In order to support affinity,
> LS1043a v1.1 MSI is assigned 4 MSIRs and 4 GIC interrupts.
> But the MSIR has the different offset and only supports 8 MSIs.
> The bits between variable bit_start and bit_end in structure
> ls_scfg_msir are used to show 8 MSI interrupts. msir_irqs and
> msir_base are added to describe the difference of MSI between
> LS1043a v1.1 and other SoCs.
> 
> Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
> ---
>  .../interrupt-controller/fsl,ls-scfg-msi.txt       |  1 +
>  drivers/irqchip/irq-ls-scfg-msi.c                  | 45 +++++++++++++++++++---
>  2 files changed, 40 insertions(+), 6 deletions(-)

Acked-by: Rob Herring <robh@kernel.org> 

^ permalink raw reply

* [PATCH 7/9] irqchip/ls-scfg-msi: add LS1046a MSI support
From: Rob Herring @ 2017-01-03 17:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482829985-24421-7-git-send-email-Minghuan.Lian@nxp.com>

On Tue, Dec 27, 2016 at 05:13:03PM +0800, Minghuan Lian wrote:
> LS1046a includes 4 MSIRs, each MSIR is assigned a dedicate GIC
> SPI interrupt and provides 32 MSI interrupts. Compared to previous
> MSI, LS1046a's IBS(interrupt bit select) shift is changed to 2 and
> total MSI interrupt number is changed to 128.
> 
> The patch adds structure 'ls_scfg_msir' to describe MSIR setting and
> 'ibs_shift' to store the different value between the SoCs.
> 
> Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
> ---
>  .../interrupt-controller/fsl,ls-scfg-msi.txt       |   2 +-
>  drivers/irqchip/irq-ls-scfg-msi.c                  | 161 ++++++++++++++++-----
>  2 files changed, 127 insertions(+), 36 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
> index 54597b0..dde4552 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
> @@ -6,7 +6,7 @@ Required properties:
>  	      Layerscape PCIe MSI controller block such as:
>                "fsl,ls1021a-msi"
>                "fsl,ls1043a-msi"
> -	      "fsl,ls1046a-msi"
> +              "fsl,ls1046a-msi"

This hunk goes in the previous patch...

>  - msi-controller: indicates that this is a PCIe MSI controller node
>  - reg: physical base address of the controller and length of memory mapped.
>  - interrupts: an interrupt to the parent interrupt controller.

^ permalink raw reply

* [PATCH] iommu: Drop the of_iommu_{set/get}_ops() interface
From: Lorenzo Pieralisi @ 2017-01-03 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

With the introduction of the new iommu_{register/get}_instance()
interface in commit e4f10ffe4c9b ("iommu: Make of_iommu_set/get_ops() DT
agnostic") (based on struct fwnode_handle as look-up token, so firmware
agnostic) to register IOMMU instances with the core IOMMU layer there is
no reason to keep the old OF based interface around any longer.

Convert all the IOMMU drivers (and OF IOMMU core code) that rely on the
of_iommu_{set/get}_ops() to the new kernel interface to register/retrieve
IOMMU instances and remove the of_iommu_{set/get}_ops() remaining glue
code in order to complete the interface rework.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
---
Exynos, msm and mtk code compile tested only owing to lack of
test platforms, I would appreciate some help in testing this
patch on those platforms before merging it even if it is just
a simple interface conversion.

Thanks,
Lorenzo

 drivers/iommu/exynos-iommu.c |  2 +-
 drivers/iommu/msm_iommu.c    |  2 +-
 drivers/iommu/mtk_iommu.c    |  2 +-
 drivers/iommu/of_iommu.c     |  4 ++--
 include/linux/of_iommu.h     | 11 -----------
 5 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 57ba0d3..b79e4c4 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -628,7 +628,7 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(dev);
 
-	of_iommu_set_ops(dev->of_node, &exynos_iommu_ops);
+	iommu_register_instance(dev->fwnode, &exynos_iommu_ops);
 
 	return 0;
 }
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index b09692b..9cd3cee 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -737,7 +737,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
 	}
 
 	list_add(&iommu->dev_node, &qcom_iommu_devices);
-	of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops);
+	iommu_register_instance(pdev->dev.fwnode, &msm_iommu_ops);
 
 	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
 		iommu->base, iommu->irq, iommu->ncb);
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 1479c76..0596ab2 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -655,7 +655,7 @@ static int mtk_iommu_init_fn(struct device_node *np)
 		return ret;
 	}
 
-	of_iommu_set_ops(np, &mtk_iommu_ops);
+	iommu_register_instance(&np->fwnode, &mtk_iommu_ops);
 	return 0;
 }
 
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 0f57ddc..d7f480a 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -127,7 +127,7 @@ static const struct iommu_ops
 			   "iommu-map-mask", &iommu_spec.np, iommu_spec.args))
 		return NULL;
 
-	ops = of_iommu_get_ops(iommu_spec.np);
+	ops = iommu_get_instance(&iommu_spec.np->fwnode);
 	if (!ops || !ops->of_xlate ||
 	    iommu_fwspec_init(&pdev->dev, &iommu_spec.np->fwnode, ops) ||
 	    ops->of_xlate(&pdev->dev, &iommu_spec))
@@ -157,7 +157,7 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
 					   "#iommu-cells", idx,
 					   &iommu_spec)) {
 		np = iommu_spec.np;
-		ops = of_iommu_get_ops(np);
+		ops = iommu_get_instance(&np->fwnode);
 
 		if (!ops || !ops->of_xlate ||
 		    iommu_fwspec_init(dev, &np->fwnode, ops) ||
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 6a7fc50..13394ac 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -31,17 +31,6 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 
 #endif	/* CONFIG_OF_IOMMU */
 
-static inline void of_iommu_set_ops(struct device_node *np,
-				    const struct iommu_ops *ops)
-{
-	iommu_register_instance(&np->fwnode, ops);
-}
-
-static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
-{
-	return iommu_get_instance(&np->fwnode);
-}
-
 extern struct of_device_id __iommu_of_table;
 
 typedef int (*of_iommu_init_fn)(struct device_node *);
-- 
2.10.0

^ permalink raw reply related

* [PATCH v3 0/5] boot-wrapper: arm64: Xen support
From: Mark Rutland @ 2017-01-03 17:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161215122718.21422-1-andre.przywara@arm.com>

On Thu, Dec 15, 2016 at 12:27:13PM +0000, Andre Przywara wrote:
> These patches allow to include a Xen hypervisor binary into a boot-wrapper
> ELF file, so that a Foundation Platform or a Fast Model can boot a Xen
> system (including a Dom0 kernel).

Thanks!

I've applied the series and pushed it out to git.kernel.org.

I made minor tweaks to patches 1 and 3 for consistency, as noted in the
commit logs, but neither of these should have a functional impact.

Thanks,
Mark.

^ permalink raw reply

* [PATCH v3 4/5] Xen: Select correct dom0 console
From: Mark Rutland @ 2017-01-03 17:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161215122718.21422-5-andre.przywara@arm.com>

On Thu, Dec 15, 2016 at 12:27:17PM +0000, Andre Przywara wrote:
> From: Ian Campbell <ian.campbell@citrix.com>
> 
> If Xen is enabled, tell Dom0 to use the 'hvc0' console, and fall back to
> the usual ttyAMA0 otherwise.
> 
> Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reviewed-by: Julien Grall <julien.grall@arm.com>
> Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
>  configure.ac | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/configure.ac b/configure.ac
> index ea02dca..d23cced 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -105,7 +105,8 @@ AC_ARG_WITH([initrd],
>  AC_SUBST([FILESYSTEM], [$USE_INITRD])
>  AM_CONDITIONAL([INITRD], [test "x$USE_INITRD" != "x"])
>  
> -C_CMDLINE="console=ttyAMA0 earlyprintk=pl011,0x1c090000"
> +AS_IF([test "x$X_IMAGE" = "x"],[C_CONSOLE="ttyAMA0"],[C_CONSOLE="hvc0"])
> +C_CMDLINE="console=$C_CONSOLE earlyprintk=pl011,0x1c090000"

Just to check: what happesns if Dom0 tries to write to 0x1c090000?

Shouldn't we override/delete earlyprintk/earlycon here too?

I've applied this as-is, so if we do need to, I'll need a fixup patch.

Thanks,
Mark.

^ permalink raw reply

* [PATCH v6 6/8] IIO: add STM32 timer trigger driver
From: Jonathan Cameron @ 2017-01-03 17:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CA+M3ks4RuhUiBTu=GS9_9S8i2y53-Lc_r9rCZ1piPPuooZ4+Eg@mail.gmail.com>



On 3 January 2017 12:59:20 GMT+00:00, Benjamin Gaignard <benjamin.gaignard@linaro.org> wrote:
>2017-01-03 10:23 GMT+01:00 Benjamin Gaignard
><benjamin.gaignard@linaro.org>:
>> 2017-01-02 19:22 GMT+01:00 Jonathan Cameron <jic23@kernel.org>:
>>> On 02/01/17 08:46, Benjamin Gaignard wrote:
>>>> 2016-12-30 22:12 GMT+01:00 Jonathan Cameron <jic23@kernel.org>:
>>>>> On 09/12/16 14:15, Benjamin Gaignard wrote:
>>>>>> Timers IPs can be used to generate triggers for other IPs like
>>>>>> DAC, ADC or other timers.
>>>>>> Each trigger may result of timer internals signals like counter
>enable,
>>>>>> reset or edge, this configuration could be done through
>"master_mode"
>>>>>> device attribute.
>>>>>>
>>>>>> A timer device could be triggered by other timers, we use the
>trigger
>>>>>> name and is_stm32_iio_timer_trigger() function to distinguish
>them
>>>>>> and configure IP input switch.
>>>>>>
>>>>>> Timer may also decide on which event (edge, level) they could
>>>>>> be activated by a trigger, this configuration is done by writing
>in
>>>>>> "slave_mode" device attribute.
>>>>>>
>>>>>> Since triggers could also be used by DAC or ADC their names are
>defined
>>>>>> in include/ nux/iio/timer/stm32-timer-trigger.h so those IPs will
>be able
>>>>>> to configure themselves in valid_trigger function
>>>>>>
>>>>>> Trigger have a "sampling_frequency" attribute which allow to
>configure
>>>>>> timer sampling frequency without using PWM interface
>>>>>>
>>>>>> version 5:
>>>>>> - simplify tables of triggers
>>>>>> - only create an IIO device when needed
>>>>>>
>>>>>> version 4:
>>>>>> - get triggers configuration from "reg" in DT
>>>>>> - add tables of triggers
>>>>>> - sampling frequency is enable/disable when writing in trigger
>>>>>>   sampling_frequency attribute
>>>>>> - no more use of interruptions
>>>>>>
>>>>>> version 3:
>>>>>> - change compatible to "st,stm32-timer-trigger"
>>>>>> - fix attributes access right
>>>>>> - use string instead of int for master_mode and slave_mode
>>>>>> - document device attributes in sysfs-bus-iio-timer-stm32
>>>>>>
>>>>>> version 2:
>>>>>> - keep only one compatible
>>>>>> - use st,input-triggers-names and st,output-triggers-names
>>>>>>   to know which triggers are accepted and/or create by the device
>>>>> Firstly, sorry it has taken me so long to get back to this.
>>>>>
>>>>> I'm still not keen on this use of iio_device elements just to act
>as
>>>>> glue between triggers.  I think we need to work out a more light
>weight
>>>>> way to do this.  As you are only using them for validation and to
>provide
>>>>> somewhere to hang the control attibutes off, there is nothing
>stopping us
>>>>> moving that over to the iio_trigger instead which would avoid the
>messy
>>>>> duality going on here.
>>>>
>>>> I have add an iio_device because each hardware can generate
>multiple
>>>> triggers (up to 5: trgo, ch 1...4) and slave_mode attribute will
>impact all the
>>>> triggers of a device. For me it was making sense to centralize that
>in an
>>>> iio_device rather than having an attribute "shared" (from hardware
>>>> point of view)
>>>> on multiple triggers.
>>>> Since master_mode attribute is only used by trgo and not impact
>ch1...4
>>>> triggers I will move it to trigger instead of the iio_device.
>>>>
>>>> I also wanted to be able to connect triggers on a iio_device as I
>>>> could do for an
>>>> ADC with a command like 'echo "tim1_trgo" >
>iio_deviceX/trigger/current_trigger'
>>> This is interesting, but with a bit of refactoring I would think it
>would
>>> be possible to share some of that code thus allowing non IIO devices
>to
>>> bind to triggers.  Ultimately I want to be able to bind a trigger to
>>> a trigger - I appreciate here the topology is more limited than that
>>> so some complexity comes in.
>>>
>>> My gut feeling is that representing that topology explicitly is hard
>>> to do in a remotely general way, but lets try it and see.
>>> We run into this sort of interdependency issue between different
>bits of
>>> the hardware all the time.  Setting a value somewhere effects the
>configuration
>>> elsewhere - often the best plan is to just let that happen and leave
>it up to
>>> userspace to check for changes if it cares.
>>
>> okay
>>
>>>> If I change that to parent_trigger attribute it change this
>behavior
>>>> and I will have to
>>>> duplicated what is done in iio_trigger_write_current() to find and
>>>> validate triggers.
>>> I get the reasoning, but we still end up with something represented
>>> by an IIO device that isn't providing any channels at all. It's
>simply
>>> using some of the infrastructure.  To my mind it is 'something else'
>>> and should be represented as such.  I have no problem at all with
>>> you registering additional elements in /sysfs/bus/iio/ to represent
>>> these shared elements - we already have drivers that do that to
>>> provide some centralized infrastructure (e.g. the sysfs-trigger)
>>
>> My hardware block are timers maybe I can add a channel type
>"IIO_TIMER"
>> and declare a channel with info_mask_separate =
>BIT(IIO_CHAN_INFO_SAMP_FREQ)
>> so I will be able to write/read sampling frequency on IIO device.
>>
>
>If it isn't possible to implement IIO_TIMER I will simply drop device
>part of
>my driver until we find a solution because I would like to upstream at
>least what is
>need to ADC/DAC.

Agreed. Let's move forward with the easy stuff.
I might get a chance to look at trigger trees later
this week depending on how some tedious time in a pharma clean room and on planes goes.

I think we can mock most of this up with software triggers and the dummy driver.

Perhaps a sysfs trigger driving a timer trigger will get us moving in the right direction API wise.
Might let us figure out something generic without needing hardware.

A few other bits of hardware can do similar to yours but I don't think I have any in my pile of boards.

J
>
>>> I'm worried about the scope spread we get for an IIO device
>otherwise.
>>> They serve a well defined purpose at the moment, and that isn't what
>>> is happening here.
>>>
>>> So my gut feeling is we are better deliberately not representing the
>>> inter dependence and claiming all triggers we are creating are
>>> independent.  That way we can have a nice generic infrastructure
>>> that will work in all cases (be it pushing the sanity checking to
>>> userspace).
>>>
>>> So each trigger has direct access to what controls it.  Changing
>anything
>>> can effect other triggers in weird ways.
>>>
>>> I'm finding it hard to see anything else generalizing sufficiently
>>> as we'll always get cases where we can't represent the topology
>without
>>> diving into the complexity of something like the media controller
>>> framework.
>>>
>>> Jonathan
>>>>
>>>>> I might still be missing something though!
>>>>>
>>>>> You would only I think need 3 attributes
>>>>>
>>>>> parrent_trigger
>>>>> and something like your master_mode and slave_mode attributes.
>>>>>
>>>>> The parrent_trigger would need some validation etc, but if we keep
>it
>>>>> within this driver initially that won't be hard to do. Checking
>the device
>>>>> parent matches will do most of it.
>>>>>
>>>>> Jonathan
>>>>>>
>>>>>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
>>>>>> ---
>>>>>>  .../ABI/testing/sysfs-bus-iio-timer-stm32          |  55 +++
>>>>>>  drivers/iio/Kconfig                                |   2 +-
>>>>>>  drivers/iio/Makefile                               |   1 +
>>>>>>  drivers/iio/timer/Kconfig                          |  13 +
>>>>>>  drivers/iio/timer/Makefile                         |   1 +
>>>>>>  drivers/iio/timer/stm32-timer-trigger.c            | 466
>+++++++++++++++++++++
>>>>>>  drivers/iio/trigger/Kconfig                        |   1 -
>>>>>>  include/linux/iio/timer/stm32-timer-trigger.h      |  62 +++
>>>>>>  8 files changed, 599 insertions(+), 2 deletions(-)
>>>>>>  create mode 100644
>Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>>>>>>  create mode 100644 drivers/iio/timer/Kconfig
>>>>>>  create mode 100644 drivers/iio/timer/Makefile
>>>>>>  create mode 100644 drivers/iio/timer/stm32-timer-trigger.c
>>>>>>  create mode 100644 include/linux/iio/timer/stm32-timer-trigger.h
>>>>>>
>>>>>> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>>>>>> new file mode 100644
>>>>>> index 0000000..26583dd
>>>>>> --- /dev/null
>>>>>> +++ b/Documentation/ABI/testing/sysfs-bus-iio-timer-stm32
>>>>>> @@ -0,0 +1,55 @@
>>>>>> +What:               
>/sys/bus/iio/devices/iio:deviceX/master_mode_available
>>>>>> +KernelVersion:       4.10
>>>>>> +Contact:     benjamin.gaignard at st.com
>>>>>> +Description:
>>>>>> +             Reading returns the list possible master modes
>which are:
>>>>>> +             - "reset"     : The UG bit from the TIMx_EGR
>register is used as trigger output (TRGO).
>>>>>> +             - "enable"    : The Counter Enable signal CNT_EN is
>used as trigger output.
>>>>>> +             - "update"    : The update event is selected as
>trigger output.
>>>>>> +                             For instance a master timer can
>then be used as a prescaler for a slave timer.
>>>>>> +             - "compare_pulse" : The trigger output send a
>positive pulse when the CC1IF flag is to be set.
>>>>>> +             - "OC1REF"    : OC1REF signal is used as trigger
>output.
>>>>>> +             - "OC2REF"    : OC2REF signal is used as trigger
>output.
>>>>>> +             - "OC3REF"    : OC3REF signal is used as trigger
>output.
>>>>>> +             - "OC4REF"    : OC4REF signal is used as trigger
>output.
>>>>>> +
>>>>>> +What:               
>/sys/bus/iio/devices/iio:deviceX/master_mode
>>>>>> +KernelVersion:       4.10
>>>>>> +Contact:     benjamin.gaignard at st.com
>>>>>> +Description:
>>>>>> +             Reading returns the current master modes.
>>>>>> +             Writing set the master mode
>>>>>> +
>>>>>> +What:               
>/sys/bus/iio/devices/iio:deviceX/slave_mode_available
>>>>>> +KernelVersion:       4.10
>>>>>> +Contact:     benjamin.gaignard at st.com
>>>>>> +Description:
>>>>>> +             Reading returns the list possible slave modes which
>are:
>>>>>> +             - "disabled"  : The prescaler is clocked directly
>by the internal clock.
>>>>>> +             - "encoder_1" : Counter counts up/down on TI2FP1
>edge depending on TI1FP2 level.
>>>>>> +             - "encoder_2" : Counter counts up/down on TI1FP2
>edge depending on TI2FP1 level.
>>>>>> +             - "encoder_3" : Counter counts up/down on both
>TI1FP1 and TI2FP2 edges depending
>>>>>> +                             on the level of the other input.
>>>>>> +             - "reset"     : Rising edge of the selected trigger
>input reinitializes the counter
>>>>>> +                             and generates an update of the
>registers.
>>>>>> +             - "gated"     : The counter clock is enabled when
>the trigger input is high.
>>>>>> +                             The counter stops (but is not
>reset) as soon as the trigger becomes low.
>>>>>> +                             Both start and stop of the counter
>are controlled.
>>>>>> +             - "trigger"   : The counter starts at a rising edge
>of the trigger TRGI (but it is not
>>>>>> +                             reset). Only the start of the
>counter is controlled.
>>>>>> +             - "external_clock": Rising edges of the selected
>trigger (TRGI) clock the counter.
>>>>>> +
>>>>>> +What:                /sys/bus/iio/devices/iio:deviceX/slave_mode
>>>>>> +KernelVersion:       4.10
>>>>>> +Contact:     benjamin.gaignard at st.com
>>>>>> +Description:
>>>>>> +             Reading returns the current slave mode.
>>>>>> +             Writing set the slave mode
>>>>>> +
>>>>>> +What:               
>/sys/bus/iio/devices/triggerX/sampling_frequency
>>>>>> +KernelVersion:       4.10
>>>>>> +Contact:     benjamin.gaignard at st.com
>>>>>> +Description:
>>>>>> +             Reading returns the current sampling frequency.
>>>>>> +             Writing an value different of 0 set and start
>sampling.
>>>>>> +             Writing 0 stop sampling.
>>>>>> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
>>>>>> index 6743b18..2de2a80 100644
>>>>>> --- a/drivers/iio/Kconfig
>>>>>> +++ b/drivers/iio/Kconfig
>>>>>> @@ -90,5 +90,5 @@ source "drivers/iio/potentiometer/Kconfig"
>>>>>>  source "drivers/iio/pressure/Kconfig"
>>>>>>  source "drivers/iio/proximity/Kconfig"
>>>>>>  source "drivers/iio/temperature/Kconfig"
>>>>>> -
>>>>>> +source "drivers/iio/timer/Kconfig"
>>>>>>  endif # IIO
>>>>>> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
>>>>>> index 87e4c43..b797c08 100644
>>>>>> --- a/drivers/iio/Makefile
>>>>>> +++ b/drivers/iio/Makefile
>>>>>> @@ -32,4 +32,5 @@ obj-y += potentiometer/
>>>>>>  obj-y += pressure/
>>>>>>  obj-y += proximity/
>>>>>>  obj-y += temperature/
>>>>>> +obj-y += timer/
>>>>>>  obj-y += trigger/
>>>>>> diff --git a/drivers/iio/timer/Kconfig
>b/drivers/iio/timer/Kconfig
>>>>>> new file mode 100644
>>>>>> index 0000000..e3c21f2
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/iio/timer/Kconfig
>>>>>> @@ -0,0 +1,13 @@
>>>>>> +#
>>>>>> +# Timers drivers
>>>>>> +
>>>>>> +menu "Timers"
>>>>>> +
>>>>>> +config IIO_STM32_TIMER_TRIGGER
>>>>>> +     tristate "STM32 Timer Trigger"
>>>>>> +     depends on (ARCH_STM32 && OF && MFD_STM32_TIMERS) ||
>COMPILE_TEST
>>>>>> +     select IIO_TRIGGERED_EVENT
>>>>>> +     help
>>>>>> +       Select this option to enable STM32 Timer Trigger
>>>>>> +
>>>>>> +endmenu
>>>>>> diff --git a/drivers/iio/timer/Makefile
>b/drivers/iio/timer/Makefile
>>>>>> new file mode 100644
>>>>>> index 0000000..4ad95ec9
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/iio/timer/Makefile
>>>>>> @@ -0,0 +1 @@
>>>>>> +obj-$(CONFIG_IIO_STM32_TIMER_TRIGGER) += stm32-timer-trigger.o
>>>>>> diff --git a/drivers/iio/timer/stm32-timer-trigger.c
>b/drivers/iio/timer/stm32-timer-trigger.c
>>>>>> new file mode 100644
>>>>>> index 0000000..8d16e8f
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/iio/timer/stm32-timer-trigger.c
>>>>>> @@ -0,0 +1,466 @@
>>>>>> +/*
>>>>>> + * Copyright (C) STMicroelectronics 2016
>>>>>> + *
>>>>>> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
>>>>>> + *
>>>>>> + * License terms:  GNU General Public License (GPL), version 2
>>>>>> + */
>>>>>> +
>>>>>> +#include <linux/iio/iio.h>
>>>>>> +#include <linux/iio/sysfs.h>
>>>>>> +#include <linux/iio/timer/stm32-timer-trigger.h>
>>>>>> +#include <linux/iio/trigger.h>
>>>>>> +#include <linux/iio/triggered_event.h>
>>>>>> +#include <linux/interrupt.h>
>>>>>> +#include <linux/mfd/stm32-timers.h>
>>>>>> +#include <linux/module.h>
>>>>>> +#include <linux/platform_device.h>
>>>>>> +
>>>>>> +#define MAX_TRIGGERS 6
>>>>>> +#define MAX_VALIDS 5
>>>>>> +
>>>>>> +/* List the triggers created by each timer */
>>>>>> +static const void *triggers_table[][MAX_TRIGGERS] = {
>>>>>> +     { TIM1_TRGO, TIM1_CH1, TIM1_CH2, TIM1_CH3, TIM1_CH4,},
>>>>>> +     { TIM2_TRGO, TIM2_CH1, TIM2_CH2, TIM2_CH3, TIM2_CH4,},
>>>>>> +     { TIM3_TRGO, TIM3_CH1, TIM3_CH2, TIM3_CH3, TIM3_CH4,},
>>>>>> +     { TIM4_TRGO, TIM4_CH1, TIM4_CH2, TIM4_CH3, TIM4_CH4,},
>>>>>> +     { TIM5_TRGO, TIM5_CH1, TIM5_CH2, TIM5_CH3, TIM5_CH4,},
>>>>>> +     { TIM6_TRGO,},
>>>>>> +     { TIM7_TRGO,},
>>>>>> +     { TIM8_TRGO, TIM8_CH1, TIM8_CH2, TIM8_CH3, TIM8_CH4,},
>>>>>> +     { TIM9_TRGO, TIM9_CH1, TIM9_CH2,},
>>>>>> +     { TIM12_TRGO, TIM12_CH1, TIM12_CH2,},
>>>>>> +};
>>>>>> +
>>>>>> +/* List the triggers accepted by each timer */
>>>>>> +static const void *valids_table[][MAX_VALIDS] = {
>>>>>> +     { TIM5_TRGO, TIM2_TRGO, TIM4_TRGO, TIM3_TRGO,},
>>>>>> +     { TIM1_TRGO, TIM8_TRGO, TIM3_TRGO, TIM4_TRGO,},
>>>>>> +     { TIM1_TRGO, TIM8_TRGO, TIM5_TRGO, TIM4_TRGO,},
>>>>>> +     { TIM1_TRGO, TIM2_TRGO, TIM3_TRGO, TIM8_TRGO,},
>>>>>> +     { TIM2_TRGO, TIM3_TRGO, TIM4_TRGO, TIM8_TRGO,},
>>>>>> +     { }, /* timer 6 */
>>>>>> +     { }, /* timer 7 */
>>>>>> +     { TIM1_TRGO, TIM2_TRGO, TIM4_TRGO, TIM5_TRGO,},
>>>>>> +     { TIM2_TRGO, TIM3_TRGO,},
>>>>>> +     { TIM4_TRGO, TIM5_TRGO,},
>>>>>> +};
>>>>>> +
>>>>>> +struct stm32_timer_trigger {
>>>>>> +     struct device *dev;
>>>>>> +     struct regmap *regmap;
>>>>>> +     struct clk *clk;
>>>>>> +     u32 max_arr;
>>>>>> +     const void *triggers;
>>>>>> +     const void *valids;
>>>>>> +};
>>>>>> +
>>>>>> +static int stm32_timer_start(struct stm32_timer_trigger *priv,
>>>>>> +                          unsigned int frequency)
>>>>>> +{
>>>>>> +     unsigned long long prd, div;
>>>>>> +     int prescaler = 0;
>>>>>> +     u32 ccer, cr1;
>>>>>> +
>>>>>> +     /* Period and prescaler values depends of clock rate */
>>>>>> +     div = (unsigned long long)clk_get_rate(priv->clk);
>>>>>> +
>>>>>> +     do_div(div, frequency);
>>>>>> +
>>>>>> +     prd = div;
>>>>>> +
>>>>>> +     /*
>>>>>> +      * Increase prescaler value until we get a result that fit
>>>>>> +      * with auto reload register maximum value.
>>>>>> +      */
>>>>>> +     while (div > priv->max_arr) {
>>>>>> +             prescaler++;
>>>>>> +             div = prd;
>>>>>> +             do_div(div, (prescaler + 1));
>>>>>> +     }
>>>>>> +     prd = div;
>>>>>> +
>>>>>> +     if (prescaler > MAX_TIM_PSC) {
>>>>>> +             dev_err(priv->dev, "prescaler exceeds the maximum
>value\n");
>>>>>> +             return -EINVAL;
>>>>>> +     }
>>>>>> +
>>>>>> +     /* Check if nobody else use the timer */
>>>>>> +     regmap_read(priv->regmap, TIM_CCER, &ccer);
>>>>>> +     if (ccer & TIM_CCER_CCXE)
>>>>>> +             return -EBUSY;
>>>>>> +
>>>>>> +     regmap_read(priv->regmap, TIM_CR1, &cr1);
>>>>>> +     if (!(cr1 & TIM_CR1_CEN))
>>>>>> +             clk_enable(priv->clk);
>>>>>> +
>>>>>> +     regmap_write(priv->regmap, TIM_PSC, prescaler);
>>>>>> +     regmap_write(priv->regmap, TIM_ARR, prd - 1);
>>>>>> +     regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE,
>TIM_CR1_ARPE);
>>>>>> +
>>>>>> +     /* Force master mode to update mode */
>>>>>> +     regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS,
>0x20);
>>>>>> +
>>>>>> +     /* Make sure that registers are updated */
>>>>>> +     regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG,
>TIM_EGR_UG);
>>>>>> +
>>>>>> +     /* Enable controller */
>>>>>> +     regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
>TIM_CR1_CEN);
>>>>>> +
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static void stm32_timer_stop(struct stm32_timer_trigger *priv)
>>>>>> +{
>>>>>> +     u32 ccer, cr1;
>>>>>> +
>>>>>> +     regmap_read(priv->regmap, TIM_CCER, &ccer);
>>>>>> +     if (ccer & TIM_CCER_CCXE)
>>>>>> +             return;
>>>>>> +
>>>>>> +     regmap_read(priv->regmap, TIM_CR1, &cr1);
>>>>>> +     if (cr1 & TIM_CR1_CEN)
>>>>>> +             clk_disable(priv->clk);
>>>>>> +
>>>>>> +     /* Stop timer */
>>>>>> +     regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
>>>>>> +     regmap_write(priv->regmap, TIM_PSC, 0);
>>>>>> +     regmap_write(priv->regmap, TIM_ARR, 0);
>>>>>> +}
>>>>>> +
>>>>>> +static ssize_t stm32_tt_store_frequency(struct device *dev,
>>>>>> +                                     struct device_attribute
>*attr,
>>>>>> +                                     const char *buf, size_t
>len)
>>>>>> +{
>>>>>> +     struct iio_trigger *trig = to_iio_trigger(dev);
>>>>>> +     struct stm32_timer_trigger *priv =
>iio_trigger_get_drvdata(trig);
>>>>>> +     unsigned int freq;
>>>>>> +     int ret;
>>>>>> +
>>>>>> +     ret = kstrtouint(buf, 10, &freq);
>>>>>> +     if (ret)
>>>>>> +             return ret;
>>>>>> +
>>>>>> +     if (freq == 0) {
>>>>>> +             stm32_timer_stop(priv);
>>>>>> +     } else {
>>>>>> +             ret = stm32_timer_start(priv, freq);
>>>>>> +             if (ret)
>>>>>> +                     return ret;
>>>>>> +     }
>>>>>> +
>>>>>> +     return len;
>>>>>> +}
>>>>>> +
>>>>>> +static ssize_t stm32_tt_read_frequency(struct device *dev,
>>>>>> +                                    struct device_attribute
>*attr, char *buf)
>>>>>> +{
>>>>>> +     struct iio_trigger *trig = to_iio_trigger(dev);
>>>>>> +     struct stm32_timer_trigger *priv =
>iio_trigger_get_drvdata(trig);
>>>>>> +     u32 psc, arr, cr1;
>>>>>> +     unsigned long long freq = 0;
>>>>>> +
>>>>>> +     regmap_read(priv->regmap, TIM_CR1, &cr1);
>>>>>> +     regmap_read(priv->regmap, TIM_PSC, &psc);
>>>>>> +     regmap_read(priv->regmap, TIM_ARR, &arr);
>>>>>> +
>>>>>> +     if (psc && arr && (cr1 & TIM_CR1_CEN)) {
>>>>>> +             freq = (unsigned long long)clk_get_rate(priv->clk);
>>>>>> +             do_div(freq, psc);
>>>>>> +             do_div(freq, arr);
>>>>>> +     }
>>>>>> +
>>>>>> +     return sprintf(buf, "%d\n", (unsigned int)freq);
>>>>>> +}
>>>>>> +
>>>>>> +static IIO_DEV_ATTR_SAMP_FREQ(0660,
>>>>>> +                           stm32_tt_read_frequency,
>>>>>> +                           stm32_tt_store_frequency);
>>>>>> +
>>>>>> +static struct attribute *stm32_trigger_attrs[] = {
>>>>>> +     &iio_dev_attr_sampling_frequency.dev_attr.attr,
>>>>>> +     NULL,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct attribute_group stm32_trigger_attr_group = {
>>>>>> +     .attrs = stm32_trigger_attrs,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct attribute_group *stm32_trigger_attr_groups[]
>= {
>>>>>> +     &stm32_trigger_attr_group,
>>>>>> +     NULL,
>>>>>> +};
>>>>>> +
>>>>>> +static char *master_mode_table[] = {
>>>>>> +     "reset",
>>>>>> +     "enable",
>>>>>> +     "update",
>>>>>> +     "compare_pulse",
>>>>>> +     "OC1REF",
>>>>>> +     "OC2REF",
>>>>>> +     "OC3REF",
>>>>>> +     "OC4REF"
>>>>>> +};
>>>>>> +
>>>>>> +static ssize_t stm32_tt_show_master_mode(struct device *dev,
>>>>>> +                                      struct device_attribute
>*attr,
>>>>>> +                                      char *buf)
>>>>>> +{
>>>>>> +     struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>>>>> +     struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>>> +     u32 cr2;
>>>>>> +
>>>>>> +     regmap_read(priv->regmap, TIM_CR2, &cr2);
>>>>>> +     cr2 = (cr2 & TIM_CR2_MMS) >> TIM_CR2_MMS_SHIFT;
>>>>>> +
>>>>>> +     return snprintf(buf, PAGE_SIZE, "%s\n",
>master_mode_table[cr2]);
>>>>>> +}
>>>>>> +
>>>>>> +static ssize_t stm32_tt_store_master_mode(struct device *dev,
>>>>>> +                                       struct device_attribute
>*attr,
>>>>>> +                                       const char *buf, size_t
>len)
>>>>>> +{
>>>>>> +     struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>>>>> +     struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>>> +     int i;
>>>>>> +
>>>>>> +     for (i = 0; i < ARRAY_SIZE(master_mode_table); i++) {
>>>>>> +             if (!strncmp(master_mode_table[i], buf,
>>>>>> +                          strlen(master_mode_table[i]))) {
>>>>>> +                     regmap_update_bits(priv->regmap, TIM_CR2,
>>>>>> +                                        TIM_CR2_MMS, i <<
>TIM_CR2_MMS_SHIFT);
>>>>>> +                     return len;
>>>>>> +             }
>>>>>> +     }
>>>>>> +
>>>>>> +     return -EINVAL;
>>>>>> +}
>>>>>> +
>>>>>> +static IIO_CONST_ATTR(master_mode_available,
>>>>>> +     "reset enable update compare_pulse OC1REF OC2REF OC3REF
>OC4REF");
>>>>>> +
>>>>>> +static IIO_DEVICE_ATTR(master_mode, 0660,
>>>>>> +                    stm32_tt_show_master_mode,
>>>>>> +                    stm32_tt_store_master_mode,
>>>>>> +                    0);
>>>>>> +
>>>>>> +static char *slave_mode_table[] = {
>>>>>> +     "disabled",
>>>>>> +     "encoder_1",
>>>>>> +     "encoder_2",
>>>>>> +     "encoder_3",
>>>>>> +     "reset",
>>>>>> +     "gated",
>>>>>> +     "trigger",
>>>>>> +     "external_clock",
>>>>>> +};
>>>>>> +
>>>>>> +static ssize_t stm32_tt_show_slave_mode(struct device *dev,
>>>>>> +                                     struct device_attribute
>*attr,
>>>>>> +                                     char *buf)
>>>>>> +{
>>>>>> +     struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>>>>> +     struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>>> +     u32 smcr;
>>>>>> +
>>>>>> +     regmap_read(priv->regmap, TIM_SMCR, &smcr);
>>>>>> +     smcr &= TIM_SMCR_SMS;
>>>>>> +
>>>>>> +     return snprintf(buf, PAGE_SIZE, "%s\n",
>slave_mode_table[smcr]);
>>>>>> +}
>>>>>> +
>>>>>> +static ssize_t stm32_tt_store_slave_mode(struct device *dev,
>>>>>> +                                      struct device_attribute
>*attr,
>>>>>> +                                      const char *buf, size_t
>len)
>>>>>> +{
>>>>>> +     struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>>>>>> +     struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>>> +     int i;
>>>>>> +
>>>>>> +     for (i = 0; i < ARRAY_SIZE(slave_mode_table); i++) {
>>>>>> +             if (!strncmp(slave_mode_table[i], buf,
>>>>>> +                          strlen(slave_mode_table[i]))) {
>>>>>> +                     regmap_update_bits(priv->regmap,
>>>>>> +                                        TIM_SMCR, TIM_SMCR_SMS,
>i);
>>>>>> +                     return len;
>>>>>> +             }
>>>>>> +     }
>>>>>> +
>>>>>> +     return -EINVAL;
>>>>>> +}
>>>>>> +
>>>>>> +static IIO_CONST_ATTR(slave_mode_available,
>>>>>> +"disabled encoder_1 encoder_2 encoder_3 reset gated trigger
>external_clock");
>>>>>> +
>>>>>> +static IIO_DEVICE_ATTR(slave_mode, 0660,
>>>>>> +                    stm32_tt_show_slave_mode,
>>>>>> +                    stm32_tt_store_slave_mode,
>>>>>> +                    0);
>>>>>> +
>>>>>> +static struct attribute *stm32_timer_attrs[] = {
>>>>>> +     &iio_dev_attr_master_mode.dev_attr.attr,
>>>>>> +     &iio_const_attr_master_mode_available.dev_attr.attr,
>>>>>> +     &iio_dev_attr_slave_mode.dev_attr.attr,
>>>>>> +     &iio_const_attr_slave_mode_available.dev_attr.attr,
>>>>>> +     NULL,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct attribute_group stm32_timer_attr_group = {
>>>>>> +     .attrs = stm32_timer_attrs,
>>>>>> +};
>>>>>> +
>>>>>> +static const struct iio_trigger_ops timer_trigger_ops = {
>>>>>> +     .owner = THIS_MODULE,
>>>>>> +};
>>>>>> +
>>>>>> +static int stm32_setup_iio_triggers(struct stm32_timer_trigger
>*priv)
>>>>>> +{
>>>>>> +     int ret;
>>>>>> +     const char * const *cur = priv->triggers;
>>>>>> +
>>>>>> +     while (cur && *cur) {
>>>>>> +             struct iio_trigger *trig;
>>>>>> +
>>>>>> +             trig = devm_iio_trigger_alloc(priv->dev, "%s",
>*cur);
>>>>>> +             if  (!trig)
>>>>>> +                     return -ENOMEM;
>>>>>> +
>>>>>> +             trig->dev.parent = priv->dev->parent;
>>>>>> +             trig->ops = &timer_trigger_ops;
>>>>>> +             trig->dev.groups = stm32_trigger_attr_groups;
>>>>>> +             iio_trigger_set_drvdata(trig, priv);
>>>>>> +
>>>>>> +             ret = devm_iio_trigger_register(priv->dev, trig);
>>>>>> +             if (ret)
>>>>>> +                     return ret;
>>>>>> +             cur++;
>>>>>> +     }
>>>>>> +
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +/**
>>>>>> + * is_stm32_timer_trigger
>>>>>> + * @trig: trigger to be checked
>>>>>> + *
>>>>>> + * return true if the trigger is a valid stm32 iio timer trigger
>>>>>> + * either return false
>>>>>> + */
>>>>>> +bool is_stm32_timer_trigger(struct iio_trigger *trig)
>>>>>> +{
>>>>>> +     return (trig->ops == &timer_trigger_ops);
>>>>>> +}
>>>>>> +EXPORT_SYMBOL(is_stm32_timer_trigger);
>>>>>> +
>>>>>> +static int stm32_validate_trigger(struct iio_dev *indio_dev,
>>>>>> +                               struct iio_trigger *trig)
>>>>>> +{
>>>>>> +     struct stm32_timer_trigger *priv = iio_priv(indio_dev);
>>>>>> +     const char * const *cur = priv->valids;
>>>>>> +     unsigned int i = 0;
>>>>>> +
>>>>>> +     if (!is_stm32_timer_trigger(trig))
>>>>>> +             return -EINVAL;
>>>>>> +
>>>>>> +     while (cur && *cur) {
>>>>>> +             if (!strncmp(trig->name, *cur, strlen(trig->name)))
>{
>>>>>> +                     regmap_update_bits(priv->regmap,
>>>>>> +                                        TIM_SMCR, TIM_SMCR_TS,
>>>>>> +                                        i << TIM_SMCR_TS_SHIFT);
>>>>>> +                     return 0;
>>>>>> +             }
>>>>>> +             cur++;
>>>>>> +             i++;
>>>>>> +     }
>>>>>> +
>>>>>> +     return -EINVAL;
>>>>>> +}
>>>>>> +
>>>>>> +static const struct iio_info stm32_trigger_info = {
>>>>>> +     .driver_module = THIS_MODULE,
>>>>>> +     .validate_trigger = stm32_validate_trigger,
>>>>>> +     .attrs = &stm32_timer_attr_group,
>>>>>> +};
>>>>>> +
>>>>>> +static struct stm32_timer_trigger *stm32_setup_iio_device(struct
>device *dev)
>>>>>> +{
>>>>>> +     struct iio_dev *indio_dev;
>>>>>> +     int ret;
>>>>>> +
>>>>>> +     indio_dev = devm_iio_device_alloc(dev,
>>>>>> +                                       sizeof(struct
>stm32_timer_trigger));
>>>>>> +     if (!indio_dev)
>>>>>> +             return NULL;
>>>>>> +
>>>>>> +     indio_dev->name = dev_name(dev);
>>>>>> +     indio_dev->dev.parent = dev;
>>>>>> +     indio_dev->info = &stm32_trigger_info;
>>>>>> +     indio_dev->modes = INDIO_EVENT_TRIGGERED;
>>>>>> +     indio_dev->num_channels = 0;
>>>>>> +     indio_dev->dev.of_node = dev->of_node;
>>>>>> +
>>>>>> +     ret = devm_iio_device_register(dev, indio_dev);
>>>>>> +     if (ret)
>>>>>> +             return NULL;
>>>>>> +
>>>>>> +     return iio_priv(indio_dev);
>>>>>> +}
>>>>>> +
>>>>>> +static int stm32_timer_trigger_probe(struct platform_device
>*pdev)
>>>>>> +{
>>>>>> +     struct device *dev = &pdev->dev;
>>>>>> +     struct stm32_timer_trigger *priv;
>>>>>> +     struct stm32_timers *ddata =
>dev_get_drvdata(pdev->dev.parent);
>>>>>> +     unsigned int index;
>>>>>> +     int ret;
>>>>>> +
>>>>>> +     if (of_property_read_u32(dev->of_node, "reg", &index))
>>>>>> +             return -EINVAL;
>>>>>> +
>>>>>> +     if (index >= ARRAY_SIZE(triggers_table))
>>>>>> +             return -EINVAL;
>>>>>> +
>>>>>> +     /* Create an IIO device only if we have triggers to be
>validated */
>>>>>> +     if (*valids_table[index])
>>>>>> +             priv = stm32_setup_iio_device(dev);
>>>>>
>>>>> I still don't like this. Really feels like we shouldn't be
>creating an
>>>>> iio device with all the bagage that carries just to allow us to do
>the
>>>>> trigger trees.  We ought to have a much more light weight solution
>for this
>>>>> functionality - we aren't typically even using the interrupt tree
>stuff
>>>>> that the triggers for devices are all really about.
>>>>>
>>>>> A simpler approach of allowing each trigger the option of a parent
>seems like
>>>>> it would be cleaner.  Could be done entirely within this driver in
>the first
>>>>> instance.  Basically it would just look like your master and slave
>attributes
>>>>> but have those under triggerX not iio:deviceX.
>>>>>
>>>>> We can work out how to make it more generic later - including
>perhaps the
>>>>> option to trigger from triggers outside this driver, using some
>parallel
>>>>> infrastructure to the device triggering.
>>>>>
>>>>>
>>>>>> +     else
>>>>>> +             priv = devm_kzalloc(dev, sizeof(*priv),
>GFP_KERNEL);
>>>>>> +
>>>>>> +     if (!priv)
>>>>>> +             return -ENOMEM;
>>>>>> +
>>>>>> +     priv->dev = dev;
>>>>>> +     priv->regmap = ddata->regmap;
>>>>>> +     priv->clk = ddata->clk;
>>>>>> +     priv->max_arr = ddata->max_arr;
>>>>>> +     priv->triggers = triggers_table[index];
>>>>>> +     priv->valids = valids_table[index];
>>>>>> +
>>>>>> +     ret = stm32_setup_iio_triggers(priv);
>>>>>> +     if (ret)
>>>>>> +             return ret;
>>>>>> +
>>>>>> +     platform_set_drvdata(pdev, priv);
>>>>>> +
>>>>>> +     return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static const struct of_device_id stm32_trig_of_match[] = {
>>>>>> +     { .compatible = "st,stm32-timer-trigger", },
>>>>>> +     { /* end node */ },
>>>>>> +};
>>>>>> +MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
>>>>>> +
>>>>>> +static struct platform_driver stm32_timer_trigger_driver = {
>>>>>> +     .probe = stm32_timer_trigger_probe,
>>>>>> +     .driver = {
>>>>>> +             .name = "stm32-timer-trigger",
>>>>>> +             .of_match_table = stm32_trig_of_match,
>>>>>> +     },
>>>>>> +};
>>>>>> +module_platform_driver(stm32_timer_trigger_driver);
>>>>>> +
>>>>>> +MODULE_ALIAS("platform: stm32-timer-trigger");
>>>>>> +MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger
>driver");
>>>>>> +MODULE_LICENSE("GPL v2");
>>>>>> diff --git a/drivers/iio/trigger/Kconfig
>b/drivers/iio/trigger/Kconfig
>>>>>> index 809b2e7..f2af4fe 100644
>>>>>> --- a/drivers/iio/trigger/Kconfig
>>>>>> +++ b/drivers/iio/trigger/Kconfig
>>>>>> @@ -46,5 +46,4 @@ config IIO_SYSFS_TRIGGER
>>>>>>
>>>>>>         To compile this driver as a module, choose M here: the
>>>>>>         module will be called iio-trig-sysfs.
>>>>>> -
>>>>> Clean this up.
>>>>
>>>> ok
>>>>
>>>>>>  endmenu
>>>>>> diff --git a/include/linux/iio/timer/stm32-timer-trigger.h
>b/include/linux/iio/timer/stm32-timer-trigger.h
>>>>>> new file mode 100644
>>>>>> index 0000000..55535ae
>>>>>> --- /dev/null
>>>>>> +++ b/include/linux/iio/timer/stm32-timer-trigger.h
>>>>>> @@ -0,0 +1,62 @@
>>>>>> +/*
>>>>>> + * Copyright (C) STMicroelectronics 2016
>>>>>> + *
>>>>>> + * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
>>>>>> + *
>>>>>> + * License terms:  GNU General Public License (GPL), version 2
>>>>>> + */
>>>>>> +
>>>>>> +#ifndef _STM32_TIMER_TRIGGER_H_
>>>>>> +#define _STM32_TIMER_TRIGGER_H_
>>>>>> +
>>>>>> +#define TIM1_TRGO    "tim1_trgo"
>>>>>> +#define TIM1_CH1     "tim1_ch1"
>>>>>> +#define TIM1_CH2     "tim1_ch2"
>>>>>> +#define TIM1_CH3     "tim1_ch3"
>>>>>> +#define TIM1_CH4     "tim1_ch4"
>>>>>> +
>>>>>> +#define TIM2_TRGO    "tim2_trgo"
>>>>>> +#define TIM2_CH1     "tim2_ch1"
>>>>>> +#define TIM2_CH2     "tim2_ch2"
>>>>>> +#define TIM2_CH3     "tim2_ch3"
>>>>>> +#define TIM2_CH4     "tim2_ch4"
>>>>>> +
>>>>>> +#define TIM3_TRGO    "tim3_trgo"
>>>>>> +#define TIM3_CH1     "tim3_ch1"
>>>>>> +#define TIM3_CH2     "tim3_ch2"
>>>>>> +#define TIM3_CH3     "tim3_ch3"
>>>>>> +#define TIM3_CH4     "tim3_ch4"
>>>>>> +
>>>>>> +#define TIM4_TRGO    "tim4_trgo"
>>>>>> +#define TIM4_CH1     "tim4_ch1"
>>>>>> +#define TIM4_CH2     "tim4_ch2"
>>>>>> +#define TIM4_CH3     "tim4_ch3"
>>>>>> +#define TIM4_CH4     "tim4_ch4"
>>>>>> +
>>>>>> +#define TIM5_TRGO    "tim5_trgo"
>>>>>> +#define TIM5_CH1     "tim5_ch1"
>>>>>> +#define TIM5_CH2     "tim5_ch2"
>>>>>> +#define TIM5_CH3     "tim5_ch3"
>>>>>> +#define TIM5_CH4     "tim5_ch4"
>>>>>> +
>>>>>> +#define TIM6_TRGO    "tim6_trgo"
>>>>>> +
>>>>>> +#define TIM7_TRGO    "tim7_trgo"
>>>>>> +
>>>>>> +#define TIM8_TRGO    "tim8_trgo"
>>>>>> +#define TIM8_CH1     "tim8_ch1"
>>>>>> +#define TIM8_CH2     "tim8_ch2"
>>>>>> +#define TIM8_CH3     "tim8_ch3"
>>>>>> +#define TIM8_CH4     "tim8_ch4"
>>>>>> +
>>>>>> +#define TIM9_TRGO    "tim9_trgo"
>>>>>> +#define TIM9_CH1     "tim9_ch1"
>>>>>> +#define TIM9_CH2     "tim9_ch2"
>>>>>> +
>>>>>> +#define TIM12_TRGO   "tim12_trgo"
>>>>>> +#define TIM12_CH1    "tim12_ch1"
>>>>>> +#define TIM12_CH2    "tim12_ch2"
>>>>>> +
>>>>>> +bool is_stm32_timer_trigger(struct iio_trigger *trig);
>>>>>> +
>>>>>> +#endif
>>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>
>>
>>
>>
>> --
>> Benjamin Gaignard
>>
>> Graphic Study Group
>>
>> Linaro.org ? Open source software for ARM SoCs
>>
>> Follow Linaro: Facebook | Twitter | Blog

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply

* [PATCHv6 11/11] arm64: Add support for CONFIG_DEBUG_VIRTUAL
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>


x86 has an option CONFIG_DEBUG_VIRTUAL to do additional checks
on virt_to_phys calls. The goal is to catch users who are calling
virt_to_phys on non-linear addresses immediately. This inclues callers
using virt_to_phys on image addresses instead of __pa_symbol. As features
such as CONFIG_VMAP_STACK get enabled for arm64, this becomes increasingly
important. Add checks to catch bad virt_to_phys usage.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 arch/arm64/Kconfig              |  1 +
 arch/arm64/include/asm/memory.h | 31 ++++++++++++++++++++++++++++---
 arch/arm64/mm/Makefile          |  2 ++
 arch/arm64/mm/physaddr.c        | 30 ++++++++++++++++++++++++++++++
 4 files changed, 61 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm64/mm/physaddr.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1117421..359bca2 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -6,6 +6,7 @@ config ARM64
 	select ACPI_MCFG if ACPI
 	select ACPI_SPCR_TABLE if ACPI
 	select ARCH_CLOCKSOURCE_DATA
+	select ARCH_HAS_DEBUG_VIRTUAL
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
 	select ARCH_HAS_ELF_RANDOMIZE
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 0ff237a..7011f08 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -172,10 +172,33 @@ static inline unsigned long kaslr_offset(void)
  * private definitions which should NOT be used outside memory.h
  * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
  */
-#define __virt_to_phys(x) ({						\
+
+
+/*
+ * The linear kernel range starts in the middle of the virtual adddress
+ * space. Testing the top bit for the start of the region is a
+ * sufficient check.
+ */
+#define __is_lm_address(addr)	(!!((addr) & BIT(VA_BITS - 1)))
+
+#define __lm_to_phys(addr)	(((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
+#define __kimg_to_phys(addr)	((addr) - kimage_voffset)
+
+#define __virt_to_phys_nodebug(x) ({					\
 	phys_addr_t __x = (phys_addr_t)(x);				\
-	__x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET :	\
-				 (__x - kimage_voffset); })
+	__is_lm_address(__x) ? __lm_to_phys(__x) :			\
+			       __kimg_to_phys(__x);			\
+})
+
+#define __pa_symbol_nodebug(x)	__kimg_to_phys((phys_addr_t)(x))
+
+#ifdef CONFIG_DEBUG_VIRTUAL
+extern phys_addr_t __virt_to_phys(unsigned long x);
+extern phys_addr_t __phys_addr_symbol(unsigned long x);
+#else
+#define __virt_to_phys(x)	__virt_to_phys_nodebug(x)
+#define __phys_addr_symbol(x)	__pa_symbol_nodebug(x)
+#endif
 
 #define __phys_to_virt(x)	((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
 #define __phys_to_kimg(x)	((unsigned long)((x) + kimage_voffset))
@@ -207,6 +230,8 @@ static inline void *phys_to_virt(phys_addr_t x)
  * Drivers should NOT use these either.
  */
 #define __pa(x)			__virt_to_phys((unsigned long)(x))
+#define __pa_symbol(x)		__phys_addr_symbol(RELOC_HIDE((unsigned long)(x), 0))
+#define __pa_nodebug(x)		__virt_to_phys_nodebug((unsigned long)(x))
 #define __va(x)			((void *)__phys_to_virt((phys_addr_t)(x)))
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 #define virt_to_pfn(x)      __phys_to_pfn(__virt_to_phys((unsigned long)(x)))
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
index e703fb9..9b0ba19 100644
--- a/arch/arm64/mm/Makefile
+++ b/arch/arm64/mm/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 obj-$(CONFIG_ARM64_PTDUMP_CORE)	+= dump.o
 obj-$(CONFIG_ARM64_PTDUMP_DEBUGFS)	+= ptdump_debugfs.o
 obj-$(CONFIG_NUMA)		+= numa.o
+obj-$(CONFIG_DEBUG_VIRTUAL)	+= physaddr.o
+KASAN_SANITIZE_physaddr.o	+= n
 
 obj-$(CONFIG_KASAN)		+= kasan_init.o
 KASAN_SANITIZE_kasan_init.o	:= n
diff --git a/arch/arm64/mm/physaddr.c b/arch/arm64/mm/physaddr.c
new file mode 100644
index 0000000..91371da
--- /dev/null
+++ b/arch/arm64/mm/physaddr.c
@@ -0,0 +1,30 @@
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/mmdebug.h>
+#include <linux/mm.h>
+
+#include <asm/memory.h>
+
+phys_addr_t __virt_to_phys(unsigned long x)
+{
+	WARN(!__is_lm_address(x),
+	     "virt_to_phys used for non-linear address: %pK (%pS)\n",
+	      (void *)x,
+	      (void *)x);
+
+	return __virt_to_phys_nodebug(x);
+}
+EXPORT_SYMBOL(__virt_to_phys);
+
+phys_addr_t __phys_addr_symbol(unsigned long x)
+{
+	/*
+	 * This is bounds checking against the kernel image only.
+	 * __pa_symbol should only be used on kernel symbol addresses.
+	 */
+	VIRTUAL_BUG_ON(x < (unsigned long) KERNEL_START ||
+		       x > (unsigned long) KERNEL_END);
+	return __pa_symbol_nodebug(x);
+}
+EXPORT_SYMBOL(__phys_addr_symbol);
-- 
2.7.4

^ permalink raw reply related

* [PATCHv6 10/11] mm/usercopy: Switch to using lm_alias
From: Laura Abbott @ 2017-01-03 17:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483464113-1587-1-git-send-email-labbott@redhat.com>

The usercopy checking code currently calls __va(__pa(...)) to check for
aliases on symbols. Switch to using lm_alias instead.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Laura Abbott <labbott@redhat.com>
---
 mm/usercopy.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/usercopy.c b/mm/usercopy.c
index 3c8da0a..8345299 100644
--- a/mm/usercopy.c
+++ b/mm/usercopy.c
@@ -108,13 +108,13 @@ static inline const char *check_kernel_text_object(const void *ptr,
 	 * __pa() is not just the reverse of __va(). This can be detected
 	 * and checked:
 	 */
-	textlow_linear = (unsigned long)__va(__pa(textlow));
+	textlow_linear = (unsigned long)lm_alias(textlow);
 	/* No different mapping: we're done. */
 	if (textlow_linear == textlow)
 		return NULL;
 
 	/* Check the secondary mapping... */
-	texthigh_linear = (unsigned long)__va(__pa(texthigh));
+	texthigh_linear = (unsigned long)lm_alias(texthigh);
 	if (overlaps(ptr, n, textlow_linear, texthigh_linear))
 		return "<linear kernel text>";
 
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox