Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 2/4] dt-bindings: misc: Aspeed coprocessor interrupt controller
From: Benjamin Herrenschmidt @ 2018-06-18  4:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618045902.11453-1-benh@kernel.crashing.org>

Add the device-tree binding definition for the AST2400
and AST2500 coprocessor interrupt controller

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 .../devicetree/bindings/misc/aspeed,cvic.txt  | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/aspeed,cvic.txt

diff --git a/Documentation/devicetree/bindings/misc/aspeed,cvic.txt b/Documentation/devicetree/bindings/misc/aspeed,cvic.txt
new file mode 100644
index 000000000000..2562e2991e4d
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/aspeed,cvic.txt
@@ -0,0 +1,35 @@
+* Aspeed AST2400 and AST2500 coprocessor interrupt controller
+
+This file describes the bindings for the interrupt controller present
+in the AST2400 and AST2500 BMC SoCs which provides interrupt to the
+ColdFire coprocessor.
+
+It is not a normal interrupt controller and it would be rather
+inconvenient to create an interrupt tree for it as it somewhat shares
+some of the same sources as the main ARM interrupt controller but with
+different numbers.
+
+The AST2500 supports a SW generated interrupt
+
+Required properties:
+- reg: address and length of the register for the device.
+- compatible: "aspeed,cvic" and one of:
+		"aspeed,ast2400-cvic"
+	      or
+		"aspeed,ast2500-cvic"
+
+- valid-sources: One cell, bitmap of supported sources for the implementation
+
+Optional properties;
+- copro-sw-interrupts: List of interrupt numbers that can be used as
+		       SW interrupts from the ARM to the coprocessor.
+		       (AST2500 only)
+
+Example:
+
+	cvic: copro-interrupt-controller at 1e6c2000 {
+		compatible = "aspeed,ast2500-cvic";
+		valid-sources = <0xffffffff>;
+		copro-sw-interrupts = <1>;
+		reg = <0x1e6c2000 0x80>;
+	};
-- 
2.17.1

^ permalink raw reply related

* [PATCH v2 3/4] arm: dts: Update AST2500 device-tree
From: Benjamin Herrenschmidt @ 2018-06-18  4:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618045902.11453-1-benh@kernel.crashing.org>

Add the missing node for the CVIC (the coprocessor interrupt
controller) and add a label to the SRAM node so it can be
referenced from the board device-tree file.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/arm/boot/dts/aspeed-g5.dtsi | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index 17f2714d18a7..21141ca1bfa4 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -127,6 +127,13 @@
 			reg = <0x1e6c0080 0x80>;
 		};
 
+		cvic: copro-interrupt-controller at 1e6c2000 {
+			compatible = "aspeed,ast2500-cvic", "aspeed-cvic";
+			valid-sources = <0xffffffff>;
+			copro-sw-interrupts = <1>;
+			reg = <0x1e6c2000 0x80>;
+		};
+
 		mac0: ethernet at 1e660000 {
 			compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
 			reg = <0x1e660000 0x180>;
@@ -211,7 +218,7 @@
 				status = "disabled";
 			};
 
-			sram at 1e720000 {
+			sram: sram at 1e720000 {
 				compatible = "mmio-sram";
 				reg = <0x1e720000 0x9000>;	// 36K
 			};
-- 
2.17.1

^ permalink raw reply related

* [PATCH v2 4/4] arm: dts: Update AST2400 device-tree
From: Benjamin Herrenschmidt @ 2018-06-18  4:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618045902.11453-1-benh@kernel.crashing.org>

Add the missing node for the CVIC (the coprocessor interrupt
controller) and add a label to the SRAM node so it can be
referenced from the board device-tree file.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/arm/boot/dts/aspeed-g4.dtsi | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
index 75df1573380e..b1a19f99a4c9 100644
--- a/arch/arm/boot/dts/aspeed-g4.dtsi
+++ b/arch/arm/boot/dts/aspeed-g4.dtsi
@@ -92,6 +92,12 @@
 			reg = <0x1e6c0080 0x80>;
 		};
 
+		cvic: copro-interrupt-controller at 1e6c2000 {
+			compatible = "aspeed,ast2400-cvic", "aspeed-cvic";
+			valid-sources = <0x7fffffff>;
+			reg = <0x1e6c2000 0x80>;
+		};
+
 		mac0: ethernet at 1e660000 {
 			compatible = "aspeed,ast2400-mac", "faraday,ftgmac100";
 			reg = <0x1e660000 0x180>;
@@ -161,7 +167,7 @@
 				status = "disabled";
 			};
 
-			sram at 1e720000 {
+			sram: sram at 1e720000 {
 				compatible = "mmio-sram";
 				reg = <0x1e720000 0x8000>;	// 32K
 			};
-- 
2.17.1

^ permalink raw reply related

* [PATCH v1 0/6] perf cs-etm: Fix tracing packet handling and minor refactoring
From: Leo Yan @ 2018-06-18  5:09 UTC (permalink / raw)
  To: linux-arm-kernel

Due the current code is missing to handle cs-etm start tracing packet
and CS_ETM_TRACE_ON packet, we fail to generate branch sample for them.

This patch series is to fix cs-etm tracing packet handling:

Patch 0001 is to add invalid address macro for readable coding;

Patch 0002 is one minor fixing to return error code for instruction
sample failure;

Patches 0003~0006 are fixing patches for start tracing packet
and CS_ETM_TRACE_ON packet.

This patch series is applied on acme tree [1] on branch perf/core with
latest commit: e238cf2e3d2e ("perf intel-pt: Fix packet decoding of CYC
packets").  Also applied successfully this patch series on Linus tree
on 4.18-rc1.

This patch series has been verified on Hikey620 platform with below two
commands:
perf script --itrace=i10000il128 -F cpu,event,ip,addr,sym -k ./vmlinux
perf script -F cpu,event,ip,addr,sym -k ./vmlinux

[1] https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git


Leo Yan (6):
  perf cs-etm: Introduce invalid address macro
  perf cs-etm: Bail out immediately for instruction sample failure
  perf cs-etm: Fix start tracing packet handling
  perf cs-etm: Support dummy address value for CS_ETM_TRACE_ON packet
  perf cs-etm: Generate branch sample when receiving a CS_ETM_TRACE_ON
    packet
  perf cs-etm: Generate branch sample for CS_ETM_TRACE_ON packet

 tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 10 ++--
 tools/perf/util/cs-etm-decoder/cs-etm-decoder.h |  1 +
 tools/perf/util/cs-etm.c                        | 71 +++++++++++++++++++++----
 3 files changed, 68 insertions(+), 14 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v1 1/6] perf cs-etm: Introduce invalid address macro
From: Leo Yan @ 2018-06-18  5:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529298599-3876-1-git-send-email-leo.yan@linaro.org>

This patch introduces invalid address macro and uses it to replace dummy
value '0xdeadbeefdeadbeefUL'.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index 4d5fc37..938def6 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -31,6 +31,8 @@
 #endif
 #endif
 
+#define CS_ETM_INVAL_ADDR	0xdeadbeefdeadbeefUL
+
 struct cs_etm_decoder {
 	void *data;
 	void (*packet_printer)(const char *msg);
@@ -261,8 +263,8 @@ static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
 	decoder->tail = 0;
 	decoder->packet_count = 0;
 	for (i = 0; i < MAX_BUFFER; i++) {
-		decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL;
-		decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL;
+		decoder->packet_buffer[i].start_addr = CS_ETM_INVAL_ADDR;
+		decoder->packet_buffer[i].end_addr = CS_ETM_INVAL_ADDR;
 		decoder->packet_buffer[i].last_instr_taken_branch = false;
 		decoder->packet_buffer[i].exc = false;
 		decoder->packet_buffer[i].exc_ret = false;
@@ -295,8 +297,8 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
 	decoder->packet_buffer[et].exc = false;
 	decoder->packet_buffer[et].exc_ret = false;
 	decoder->packet_buffer[et].cpu = *((int *)inode->priv);
-	decoder->packet_buffer[et].start_addr = 0xdeadbeefdeadbeefUL;
-	decoder->packet_buffer[et].end_addr = 0xdeadbeefdeadbeefUL;
+	decoder->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR;
+	decoder->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR;
 
 	if (decoder->packet_count == MAX_BUFFER - 1)
 		return OCSD_RESP_WAIT;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v1 2/6] perf cs-etm: Bail out immediately for instruction sample failure
From: Leo Yan @ 2018-06-18  5:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529298599-3876-1-git-send-email-leo.yan@linaro.org>

If the instruction sample failure has happened, it isn't necessary to
execute to the end of the function cs_etm__flush().  This commit is to
bail out immediately and return the error code.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 822ba91..8b2c099 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -939,6 +939,9 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
 		err = cs_etm__synth_instruction_sample(
 			etmq, addr,
 			etmq->period_instructions);
+		if (err)
+			return err;
+
 		etmq->period_instructions = 0;
 
 		/*
-- 
2.7.4

^ permalink raw reply related

* [PATCH v1 3/6] perf cs-etm: Fix start tracing packet handling
From: Leo Yan @ 2018-06-18  5:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529298599-3876-1-git-send-email-leo.yan@linaro.org>

Usually the start tracing packet is a CS_ETM_TRACE_ON packet, this
packet is passed to cs_etm__flush();  cs_etm__flush() will check the
condition 'prev_packet->sample_type == CS_ETM_RANGE' but 'prev_packet'
is allocated by zalloc() so 'prev_packet->sample_type' is zero in
initialization and this condition is false.  So cs_etm__flush() will
directly bail out without handling the start tracing packet.

This patch is to introduce a new sample type CS_ETM_EMPTY, which is used
to indicate the packet is an empty packet.  cs_etm__flush() will swap
packets when it finds the previous packet is empty, so this can record
the start tracing packet into 'etmq->prev_packet'.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm-decoder/cs-etm-decoder.h |  1 +
 tools/perf/util/cs-etm.c                        | 19 ++++++++++++++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
index 743f5f4..612b575 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
@@ -23,6 +23,7 @@ struct cs_etm_buffer {
 };
 
 enum cs_etm_sample_type {
+	CS_ETM_EMPTY = 0,
 	CS_ETM_RANGE = 1 << 0,
 	CS_ETM_TRACE_ON = 1 << 1,
 };
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 8b2c099..ae7c9c88 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -924,8 +924,14 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
 	int err = 0;
 	struct cs_etm_packet *tmp;
 
+	if (!etmq->prev_packet)
+		return 0;
+
+	/* Handle start tracing packet */
+	if (etmq->prev_packet->sample_type == CS_ETM_EMPTY)
+		goto swap_packet;
+
 	if (etmq->etm->synth_opts.last_branch &&
-	    etmq->prev_packet &&
 	    etmq->prev_packet->sample_type == CS_ETM_RANGE) {
 		/*
 		 * Generate a last branch event for the branches left in the
@@ -944,6 +950,10 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
 
 		etmq->period_instructions = 0;
 
+	}
+
+swap_packet:
+	if (etmq->etm->synth_opts.last_branch) {
 		/*
 		 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
 		 * the next incoming packet.
@@ -1023,6 +1033,13 @@ static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
 					 */
 					cs_etm__flush(etmq);
 					break;
+				case CS_ETM_EMPTY:
+					/*
+					 * Should not receive empty packet,
+					 * report error.
+					 */
+					pr_err("CS ETM Trace: empty packet\n");
+					return -EINVAL;
 				default:
 					break;
 				}
-- 
2.7.4

^ permalink raw reply related

* [PATCH v1 4/6] perf cs-etm: Support dummy address value for CS_ETM_TRACE_ON packet
From: Leo Yan @ 2018-06-18  5:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529298599-3876-1-git-send-email-leo.yan@linaro.org>

For CS_ETM_TRACE_ON packet, its fields 'packet->start_addr' and
'packet->end_addr' equal to 0xdeadbeefdeadbeefUL which are emitted in
the decoder layer as dummy value, but the dummy value is pointless for
branch sample when we use 'perf script' command to check program flow.

This patch is a preparation to support CS_ETM_TRACE_ON packet for
branch sample, it converts the dummy address value to zero for more
readable; this is accomplished by cs_etm__last_executed_instr() and
cs_etm__first_executed_instr().  The later one is a new function
introduced by this patch.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index ae7c9c88..976db84 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -494,6 +494,10 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
 
 static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
 {
+	/* Returns 0 for the CS_ETM_TRACE_ON packet */
+	if (packet->sample_type == CS_ETM_TRACE_ON)
+		return 0;
+
 	/*
 	 * The packet records the execution range with an exclusive end address
 	 *
@@ -505,6 +509,15 @@ static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
 	return packet->end_addr - A64_INSTR_SIZE;
 }
 
+static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet)
+{
+	/* Returns 0 for the CS_ETM_TRACE_ON packet */
+	if (packet->sample_type == CS_ETM_TRACE_ON)
+		return 0;
+
+	return packet->start_addr;
+}
+
 static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
 {
 	/*
@@ -546,7 +559,7 @@ static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
 
 	be       = &bs->entries[etmq->last_branch_pos];
 	be->from = cs_etm__last_executed_instr(etmq->prev_packet);
-	be->to	 = etmq->packet->start_addr;
+	be->to	 = cs_etm__first_executed_instr(etmq->packet);
 	/* No support for mispredict */
 	be->flags.mispred = 0;
 	be->flags.predicted = 1;
@@ -701,7 +714,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
 	sample.ip = cs_etm__last_executed_instr(etmq->prev_packet);
 	sample.pid = etmq->pid;
 	sample.tid = etmq->tid;
-	sample.addr = etmq->packet->start_addr;
+	sample.addr = cs_etm__first_executed_instr(etmq->packet);
 	sample.id = etmq->etm->branches_id;
 	sample.stream_id = etmq->etm->branches_id;
 	sample.period = 1;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v1 5/6] perf cs-etm: Generate branch sample when receiving a CS_ETM_TRACE_ON packet
From: Leo Yan @ 2018-06-18  5:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529298599-3876-1-git-send-email-leo.yan@linaro.org>

If one CS_ETM_TRACE_ON packet is inserted, we miss to generate branch
sample for the previous CS_ETM_RANGE packet.

This patch is to generate branch sample when receiving a CS_ETM_TRACE_ON
packet, so this can save complete info for the previous CS_ETM_RANGE
packet just before CS_ETM_TRACE_ON packet.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 976db84..d3b7942 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -935,6 +935,7 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
 static int cs_etm__flush(struct cs_etm_queue *etmq)
 {
 	int err = 0;
+	struct cs_etm_auxtrace *etm = etmq->etm;
 	struct cs_etm_packet *tmp;
 
 	if (!etmq->prev_packet)
@@ -965,6 +966,13 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
 
 	}
 
+	if (etm->sample_branches &&
+	    etmq->prev_packet->sample_type == CS_ETM_RANGE) {
+		err = cs_etm__synth_branch_sample(etmq);
+		if (err)
+			return err;
+	}
+
 swap_packet:
 	if (etmq->etm->synth_opts.last_branch) {
 		/*
-- 
2.7.4

^ permalink raw reply related

* [PATCH v1 6/6] perf cs-etm: Generate branch sample for CS_ETM_TRACE_ON packet
From: Leo Yan @ 2018-06-18  5:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529298599-3876-1-git-send-email-leo.yan@linaro.org>

CS_ETM_TRACE_ON packet itself can give the info that there have a
discontinuity in the trace, this patch is to add branch sample for
CS_ETM_TRACE_ON packet if it is inserted in the middle of CS_ETM_RANGE
packets; as result we can have hint for the trace discontinuity.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
---
 tools/perf/util/cs-etm.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index d3b7942..2ae6402 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -910,13 +910,23 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
 		etmq->period_instructions = instrs_over;
 	}
 
-	if (etm->sample_branches &&
-	    etmq->prev_packet &&
-	    etmq->prev_packet->sample_type == CS_ETM_RANGE &&
-	    etmq->prev_packet->last_instr_taken_branch) {
-		ret = cs_etm__synth_branch_sample(etmq);
-		if (ret)
-			return ret;
+	if (etm->sample_branches && etmq->prev_packet) {
+		bool generate_sample = false;
+
+		/* Generate sample for tracing on packet */
+		if (etmq->prev_packet->sample_type == CS_ETM_TRACE_ON)
+			generate_sample = true;
+
+		/* Generate sample for branch taken packet */
+		if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
+		    etmq->prev_packet->last_instr_taken_branch)
+			generate_sample = true;
+
+		if (generate_sample) {
+			ret = cs_etm__synth_branch_sample(etmq);
+			if (ret)
+				return ret;
+		}
 	}
 
 	if (etm->sample_branches || etm->synth_opts.last_branch) {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 1/4] arm: dts: Fix error in Aspeed OpenPower Romulus device-tree
From: Benjamin Herrenschmidt @ 2018-06-18  5:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618045902.11453-2-benh@kernel.crashing.org>

On Mon, 2018-06-18 at 14:58 +1000, Benjamin Herrenschmidt wrote:
> The reserved memory for the VGA frame buffer is at the wrong address
> for this system.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Note: These are pre-reqs for subsequent work, so if they are accepted,
I will put them in the fsi tree that I send to Greg (though it can also
be in an ARM soc tree).

Let me know if you prefer that I create a topic branch to pull on both
sides on k.org

> ---
>  arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts b/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
> index 0b9b37d4d6ef..7d28c03a9e0b 100644
> --- a/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
> +++ b/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
> @@ -21,9 +21,9 @@
>  		#size-cells = <1>;
>  		ranges;
>  
> -		vga_memory: framebuffer at bf000000 {
> +		vga_memory: framebuffer at 9f000000 {
>  			no-map;
> -			reg = <0xbf000000 0x01000000>; /* 16M */
> +			reg = <0x9f000000 0x01000000>; /* 16M */
>  		};
>  
>  		flash_memory: region at 98000000 {

^ permalink raw reply

* [PATCH v4 23/26] devicetree: fix a series of wrong file references
From: Lee Jones @ 2018-06-18  5:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <266e5f874b36aa83f3327879d85921fab52d5461.1529079120.git.mchehab+samsung@kernel.org>

On Fri, 15 Jun 2018, Mauro Carvalho Chehab wrote:

> As files got renamed, their references broke.
> 
> Manually fix a series of broken refs at the DT bindings.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> ---
>  .../devicetree/bindings/input/rmi4/rmi_2d_sensor.txt |  2 +-
>  Documentation/devicetree/bindings/mfd/sun6i-prcm.txt |  2 +-

Acked-by: Lee Jones <lee.jones@linaro.org>

>  .../devicetree/bindings/pci/hisilicon-pcie.txt       |  2 +-
>  Documentation/devicetree/bindings/pci/kirin-pcie.txt |  2 +-
>  .../devicetree/bindings/pci/pci-keystone.txt         |  4 ++--
>  .../devicetree/bindings/sound/st,stm32-i2s.txt       |  2 +-
>  .../devicetree/bindings/sound/st,stm32-sai.txt       |  2 +-
>  MAINTAINERS                                          | 12 ++++++------
>  8 files changed, 14 insertions(+), 14 deletions(-)

-- 
Lee Jones [???]
Linaro Services Technical Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH 0/3] arm64: kexec,kdump: fix boot failures on acpi-only system
From: AKASHI Takahiro @ 2018-06-18  5:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <81a9a385-3b9f-113d-96f0-379be74c19f0@arm.com>

James,

Thank you for follow-up explanation.
I have nothing to add :)

-Takahiro AKASHI

On Fri, Jun 15, 2018 at 05:29:32PM +0100, James Morse wrote:
> Hi Akashi,
> 
> Thanks for putting this together,
> 
> On 15/06/18 08:56, AKASHI Takahiro wrote:
> > This patch series is a set of bug fixes to address kexec/kdump
> > failures which are sometimes observed on ACPI-only system and reported
> > in LAK-ML before.
> > 
> > In short, the phenomena are:
> > 1. kexec'ed kernel can fail to boot because some ACPI table is corrupted
> >    by a new kernel (or other data) being loaded into System RAM. Currently
> >    kexec may possibly allocate space ignoring such "reserved" regions.
> >    We will see no messages after "Bye!"
> > 
> > 2. crash dump (kdump) kernel can fail to boot and get into panic due to
> >    an alignment fault when accessing ACPI tables. This can happen because
> >    those tables are not always properly aligned while they are mapped
> >    non-cacheable (ioremap'ed) as they are not recognized as part of System
> >    RAM under the current implementation.
> > 
> > After discussing several possibilities to address those issues,
> > the agreed approach, in my understanding, is
> > * to add resource entries for every "reserved", i.e. memblock_reserve(),
> >   regions to /proc/iomem.
> >   (NOMAP regions, also marked as "reserved," remains at top-level for
> >   backward compatibility.)
> 
> This means user-space can tell the difference between reserved-system-ram and
> reserved-address-space.
> 
> 
> > * For case (1), user space (kexec-tools) should rule out such regions
> >   in searching for free space for loaded data.
> 
> ... but doesn't today, because it fails to account for second-level entries.
> We've always had second-level entries, so this is a user-space bug. We need both
> fixed to fix the issue.
> 
> Our attempts to fix this just in the kernel reached a dead end, because Kdump
> needs to include reserved-system-ram, whereas kexec has to avoid it. User-space
> needs to be able to tell reserved-system-ram and reserved-address-space apart.
> Hence we need to expose that information, and pick it up in user-space.
> 
> Patched-kernel and unpatch-user-space will work the same way it does today, as
> the additional reserved regions are ignored by user-space.
> 
> Unpatched-kernel and patched-user-space will also work the same way it does
> today as the additional reserved regions are missing.
> 
> I think this is the only way forwards on this issue...
> 
> 
> > * For case (2), the kernel should access ACPI tables by mapping
> >   them with appropriate memory attributes described in UEFI memory map.
> >   (This means that it doesn't require any changes in /proc/iomem, and
> >   hence user space.)
> 
> (this one is handled entirely in the kernel)
> 
> 
> Thanks,
> 
> James

^ permalink raw reply

* [PATCH 2/3] arm64: acpi,efi: fix alignment fault in accessing ACPI tables at kdump
From: AKASHI Takahiro @ 2018-06-18  6:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <026a4d23-ac91-ed35-d711-c55882242037@arm.com>

James,

On Fri, Jun 15, 2018 at 05:30:08PM +0100, James Morse wrote:
> Hi Akashi,
> 
> On 15/06/18 08:56, AKASHI Takahiro wrote:
> > This is a fix against the issue that crash dump kernel may hang up
> > during booting, which can happen on any ACPI-based system with "ACPI
> > Reclaim Memory."
> > 
> > (kernel messages after panic kicked off kdump)
> > 	   (snip...)
> > 	Bye!
> > 	   (snip...)
> > 	ACPI: Core revision 20170728
> > 	pud=000000002e7d0003, *pmd=000000002e7c0003, *pte=00e8000039710707
> > 	Internal error: Oops: 96000021 [#1] SMP
> > 	Modules linked in:
> > 	CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.14.0-rc6 #1
> > 	task: ffff000008d05180 task.stack: ffff000008cc0000
> > 	PC is at acpi_ns_lookup+0x25c/0x3c0
> > 	LR is at acpi_ds_load1_begin_op+0xa4/0x294
> > 	   (snip...)
> > 	Process swapper/0 (pid: 0, stack limit = 0xffff000008cc0000)
> > 	Call trace:
> > 	   (snip...)
> > 	[<ffff0000084a6764>] acpi_ns_lookup+0x25c/0x3c0
> > 	[<ffff00000849b4f8>] acpi_ds_load1_begin_op+0xa4/0x294
> > 	[<ffff0000084ad4ac>] acpi_ps_build_named_op+0xc4/0x198
> > 	[<ffff0000084ad6cc>] acpi_ps_create_op+0x14c/0x270
> > 	[<ffff0000084acfa8>] acpi_ps_parse_loop+0x188/0x5c8
> > 	[<ffff0000084ae048>] acpi_ps_parse_aml+0xb0/0x2b8
> > 	[<ffff0000084a8e10>] acpi_ns_one_complete_parse+0x144/0x184
> > 	[<ffff0000084a8e98>] acpi_ns_parse_table+0x48/0x68
> > 	[<ffff0000084a82cc>] acpi_ns_load_table+0x4c/0xdc
> > 	[<ffff0000084b32f8>] acpi_tb_load_namespace+0xe4/0x264
> > 	[<ffff000008baf9b4>] acpi_load_tables+0x48/0xc0
> > 	[<ffff000008badc20>] acpi_early_init+0x9c/0xd0
> > 	[<ffff000008b70d50>] start_kernel+0x3b4/0x43c
> > 	Code: b9008fb9 2a000318 36380054 32190318 (b94002c0)
> > 	---[ end trace c46ed37f9651c58e ]---
> > 	Kernel panic - not syncing: Fatal exception
> > 	Rebooting in 10 seconds..
> > 
> > (diagnosis)
> > * This fault is a data abort, alignment fault (ESR=0x96000021)
> >   during reading out ACPI table.
> > * Initial ACPI tables are normally stored in system ram and marked as
> >   "ACPI Reclaim memory" by the firmware.
> > * After the commit f56ab9a5b73c ("efi/arm: Don't mark ACPI reclaim
> >   memory as MEMBLOCK_NOMAP"), those regions are differently handled
> >   as they are "memblock-reserved", without NOMAP bit.
> > * So they are now excluded from device tree's "usable-memory-range"
> >   which kexec-tools determines based on a current view of /proc/iomem.
> > * When crash dump kernel boots up, it tries to accesses ACPI tables by
> >   mapping them with ioremap(), not ioremap_cache(), in acpi_os_ioremap()
> >   since they are no longer part of mapped system ram.
> > * Given that ACPI accessor/helper functions are compiled in without
> >   unaligned access support (ACPI_MISALIGNMENT_NOT_SUPPORTED),
> >   any unaligned access to ACPI tables can cause a fatal panic.
> > 
> > With this patch, acpi_os_ioremap() always honors memory attribute
> > information provided by the firmware (EFI) and retaining cacheability
> > allows the kernel safe access to ACPI tables.
> 
> 
> > Please note that arm_enable_runtime_services() is now renamed to
> > efi_enter_virtual_mode() due to the similarity to x86's.
> 
> Just a rename?:

and maps EFI memory map whether or not runtime service is enabled.

> >  drivers/firmware/efi/arm-runtime.c | 27 ++++++++++++---------------
> 
> 
> 
> > diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> > index 32f465a80e4e..d53c95f4e1a9 100644
> > --- a/arch/arm64/include/asm/acpi.h
> > +++ b/arch/arm64/include/asm/acpi.h
> > @@ -29,18 +31,22 @@
> >  
> >  /* Basic configuration for ACPI */
> >  #ifdef	CONFIG_ACPI
> > +pgprot_t __acpi_get_mem_attribute(phys_addr_t addr);
> > +
> >  /* ACPI table mapping after acpi_permanent_mmap is set */
> >  static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
> >  					    acpi_size size)
> >  {
> > +	/* For normal memory we already have a cacheable mapping. */
> > +	if (memblock_is_map_memory(phys))
> > +		return (void __iomem *)__phys_to_virt(phys);
> 
> >  	/*
> > -	 * EFI's reserve_regions() call adds memory with the WB attribute
> > -	 * to memblock via early_init_dt_add_memory_arch().
> > +	 * We should still honor the memory's attribute here because
> > +	 * crash dump kernel possibly excludes some ACPI (reclaim)
> > +	 * regions from memblock list.
> >  	 */
> 
> (Even without kdump we would still need this. Regions ACPI wants mapped may not
> be covered by the linear map. In this case we need to use the attributes
> firmware described in the UEFI memory map. Kdump exacerbates this by
> artificially reducing the range of the linear map.)
> 
> 
> > -	if (!memblock_is_memory(phys))
> > -		return ioremap(phys, size);
> > -
> > -	return ioremap_cache(phys, size);
> > +	return __ioremap(phys, size, __acpi_get_mem_attribute(phys));
> >  }
> 
> 
> 
> > diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
> > index 5889cbea60b8..566ef0a9edb5 100644
> > --- a/drivers/firmware/efi/arm-runtime.c
> > +++ b/drivers/firmware/efi/arm-runtime.c
> > @@ -106,46 +106,43 @@ static bool __init efi_virtmap_init(void)
> >   * non-early mapping of the UEFI system table and virtual mappings for all
> >   * EFI_MEMORY_RUNTIME regions.
> >   */
> > -static int __init arm_enable_runtime_services(void)
> > +void __init efi_enter_virtual_mode(void)
> >  {
> >  	u64 mapsize;
> >  
> >  	if (!efi_enabled(EFI_BOOT)) {
> >  		pr_info("EFI services will not be available.\n");
> > -		return 0;
> > +		return;
> > +	}
> > +
> > +	mapsize = efi.memmap.desc_size * efi.memmap.nr_map;
> > +
> > +	if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) {
> > +		pr_err("Failed to remap EFI memory map\n");
> > +		return;
> >  	}
> >  
> >  	if (efi_runtime_disabled()) {
> >  		pr_info("EFI runtime services will be disabled.\n");
> > -		return 0;
> > +		return;
> >  	}
> >  
> >  	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
> >  		pr_info("EFI runtime services access via paravirt.\n");
> > -		return 0;
> > +		return;
> >  	}
> >  
> >  	pr_info("Remapping and enabling EFI services.\n");
> >  
> > -	mapsize = efi.memmap.desc_size * efi.memmap.nr_map;
> > -
> > -	if (efi_memmap_init_late(efi.memmap.phys_map, mapsize)) {
> > -		pr_err("Failed to remap EFI memory map\n");
> > -		return -ENOMEM;
> > -	}
> > -
> >  	if (!efi_virtmap_init()) {
> >  		pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n");
> > -		return -ENOMEM;
> > +		return;
> >  	}
> >  
> >  	/* Set up runtime services function pointers */
> >  	efi_native_runtime_setup();
> >  	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
> > -
> > -	return 0;
> >  }
> 
> Please have the drivers/firmware/efi/arm-runtime.c changes in a separate patch
> (maybe combine it with patch 3). The 'efi/arm: ' prefix is more likely to catch
> the maintainers attention.
>
> I think this is what Ard meant by:
> | Could you please move the changes to this file and init/main.c into a
> | separate patch?
> 
> https://patchwork.kernel.org/patch/10361761/
> 
> 
> > -early_initcall(arm_enable_runtime_services);
> 
> With just this patch, surely nothing ever calls arm_enable_runtime_services(),
> and now acpi_os_ioremap() will return device memory for anything that isn't part
> of the linear region. (This breaks RAS).

Actually I noticed the issue.

> This will make it difficult to bisect through for any RAS or
> efi-runtime-services issue. Its easily fixed: please put the efi+init changes in
> a patch before the acpi_os_ioremap() changes.

I was reluctant to put different part of code changes into one.
But if nobody cares, I will do so in three patches.
  * change arm_enable_runtime_services() with renaming
  * move this function earlier in start_kernel()
  * modify acpi_os_ioremap()

Thanks,
-Takahiro AKASHI


> Otherwise, looks good to me!
> 
> 
> Thanks,
> 
> James

^ permalink raw reply

* Charge counter on droid 4
From: Tony Lindgren @ 2018-06-18  6:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180615083156.GA32102@amd>

* Pavel Machek <pavel@ucw.cz> [180615 08:34]:
> On Fri 2018-06-15 10:00:14, Pavel Machek wrote:
> > Hi!
> > 
> > Droid 4 has non-removable battery, yet the charge counter is reset to
> > near zero on each boot of linux.

Not sure if we actively do anything to reset it. I'm guessing
it's the Motorola bootloader that resets everything on boot.

> > Unfortunately, that makes charge counter pretty much useless on d4, as
> > the "battery full" and "battery empty" limits will be different during
> > each boot.

>From what I've seen also the stock kernel starts only with
voltage based estimate initially after a reboot?

> Hmm, and could we refrain from providing "power" values?
> 
> I was thinking great, we have hardware that does proper power
> measuerement for us. No.... it is driver providing synthetic
> values. As userland has enough information to do that itself, I
> believe we should not do this in kernel.

Hmm I don't follow you, why would we want to remove these as
they implement a standard sysfs interface?

I use the sysfs interface all the time to monitor the power
consumption and the output seems to match what I was seeing
with my power supply.

Note that we also have the IIO raw data also available if that
might help.

Regards,

Tony

^ permalink raw reply

* [PATCH] dt-bindings: Fix unbalanced quotation marks
From: Krzysztof Kozlowski @ 2018-06-18  7:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180617143127.11421-1-j.neuschaefer@gmx.net>

On Sun, Jun 17, 2018 at 4:31 PM, Jonathan Neusch?fer
<j.neuschaefer@gmx.net> wrote:
> Multiple binding documents have various forms of unbalanced quotation
> marks. Fix them.
>
> Signed-off-by: Jonathan Neusch?fer <j.neuschaefer@gmx.net>
> ---
>
> Should I split this patch so that different parts can go through different trees?
> ---
>  .../devicetree/bindings/arm/samsung/samsung-boards.txt          | 2 +-
>  .../devicetree/bindings/gpio/nintendo,hollywood-gpio.txt        | 2 +-
>  Documentation/devicetree/bindings/input/touchscreen/hideep.txt  | 2 +-
>  .../bindings/interrupt-controller/nvidia,tegra20-ictlr.txt      | 2 +-
>  .../devicetree/bindings/interrupt-controller/st,stm32-exti.txt  | 2 +-
>  Documentation/devicetree/bindings/mips/brcm/soc.txt             | 2 +-
>  Documentation/devicetree/bindings/net/fsl-fman.txt              | 2 +-
>  Documentation/devicetree/bindings/power/power_domain.txt        | 2 +-
>  Documentation/devicetree/bindings/regulator/tps65090.txt        | 2 +-
>  Documentation/devicetree/bindings/reset/st,sti-softreset.txt    | 2 +-
>  Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt    | 2 +-
>  Documentation/devicetree/bindings/sound/qcom,apq8096.txt        | 2 +-
>  12 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
> index bdadc3da9556..6970f30a3770 100644
> --- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
> +++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
> @@ -66,7 +66,7 @@ Required root node properties:
>         - "insignal,arndale-octa" - for Exynos5420-based Insignal Arndale
>                                     Octa board.
>         - "insignal,origen"       - for Exynos4210-based Insignal Origen board.
> -       - "insignal,origen4412    - for Exynos4412-based Insignal Origen board.
> +       - "insignal,origen4412"   - for Exynos4412-based Insignal Origen board.
>

Acked-by: Krzysztof Kozlowski <krzk@kernel.org>

Best regards,
Krzysztof

^ permalink raw reply

* [PATCH v3 0/4] allwinner: a64: add SRAM controller / system control
From: Maxime Ripard @ 2018-06-18  7:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGb2v64Ar+rOgiXbjtRrQojHUZteLa9N7OwM3XY7ZcpS87Qpmw@mail.gmail.com>

On Mon, Jun 18, 2018 at 10:11:20AM +0800, Chen-Yu Tsai wrote:
> On Fri, Jun 15, 2018 at 5:14 PM, Maxime Ripard
> <maxime.ripard@bootlin.com> wrote:
> > On Thu, Jun 14, 2018 at 11:35:44PM +0800, Chen-Yu Tsai wrote:
> >> Hi,
> >>
> >> This series is the remaining A64 syscon changes from the R40 DWMAC
> >> series. The series aligns how the A64 system control exports a regmap
> >> for the sun8i DWMAC driver to access with what we've done for the R40.
> >>
> >> Originally the A64 used the generic syscon for this bit of hardware.
> >> But this block also contains mapping bits for the onboard SRAM, used
> >> by various peripherals, and other vendor specific bits we may use in
> >> the future. It is by no means generic. And we already have a device
> >> tree binding and driver for the SRAM part.
> >>
> >> The first patch make the SRAM control device export a regmap, exposing
> >> a single EMAC control register, for the DWMAC driver to consume.
> >>
> >> The second and third patches rename the A64 compatible string to read
> >> "system control", which is what the block is named in the user manual.
> >>
> >> The last patch fixes up the device node, and also adds the lone mappable
> >> SRAM block, which is needed by the Display Engine.
> >
> > For the serie:
> > Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
> 
> Cool. I'll apply them once you've rebased and pushed out any patches you
> queued up during the merge window.

All should be pushed now, feel free to apply them :)

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180618/4398cd96/attachment-0001.sig>

^ permalink raw reply

* Charge counter on droid 4
From: Pavel Machek @ 2018-06-18  7:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618065827.GN112168@atomide.com>

Hi!

> > > Droid 4 has non-removable battery, yet the charge counter is reset to
> > > near zero on each boot of linux.
> 
> Not sure if we actively do anything to reset it. I'm guessing
> it's the Motorola bootloader that resets everything on boot.

Too bad if that's the case :-(.

> > > Unfortunately, that makes charge counter pretty much useless on d4, as
> > > the "battery full" and "battery empty" limits will be different during
> > > each boot.
> 
> From what I've seen also the stock kernel starts only with
> voltage based estimate initially after a reboot?
> 
> > Hmm, and could we refrain from providing "power" values?
> > 
> > I was thinking great, we have hardware that does proper power
> > measuerement for us. No.... it is driver providing synthetic
> > values. As userland has enough information to do that itself, I
> > believe we should not do this in kernel.
> 
> Hmm I don't follow you, why would we want to remove these as
> they implement a standard sysfs interface?
> 
> I use the sysfs interface all the time to monitor the power
> consumption and the output seems to match what I was seeing
> with my power supply.

So... there are mA, mAh values. Those come from hardware, and I
believe we should keep them.

But there are also mW, mWh values, which are synthetic. Userland can
compute them from mV, mA values... and it is confusing that kernel
provides them. (My tendency was to start computing these synthetic
values in userland, to compare them with "real hardware" values from
kernel. But then I looked at kernel implementation, and realized they
are synthetic, tooo...)

Best regards,
								Pavel
								
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180618/14095185/attachment.sig>

^ permalink raw reply

* [PATCH] efi/arm: preserve early mapping of UEFI memory map longer for BGRT
From: Ard Biesheuvel @ 2018-06-18  7:41 UTC (permalink / raw)
  To: linux-arm-kernel

The BGRT code validates the contents of the table against the UEFI
memory map, and so it expects it to be mapped when the code runs.

On ARM, this is currently not the case, since we tear down the early
mapping after efi_init() completes, and only create the permanent
mapping in arm_enable_runtime_services(), which executes as an early
initcall, but still leaves a window where the UEFI memory map is not
mapped.

So move the call to efi_memmap_unmap() from efi_init() to
arm_enable_runtime_services().

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 drivers/firmware/efi/arm-init.c    | 1 -
 drivers/firmware/efi/arm-runtime.c | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 80d1a885def5..a7c522eac640 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -259,7 +259,6 @@ void __init efi_init(void)
 
 	reserve_regions();
 	efi_esrt_init();
-	efi_memmap_unmap();
 
 	memblock_reserve(params.mmap & PAGE_MASK,
 			 PAGE_ALIGN(params.mmap_size +
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 5889cbea60b8..59a8c0ec94d5 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -115,6 +115,8 @@ static int __init arm_enable_runtime_services(void)
 		return 0;
 	}
 
+	efi_memmap_unmap();
+
 	if (efi_runtime_disabled()) {
 		pr_info("EFI runtime services will be disabled.\n");
 		return 0;
-- 
2.17.1

^ permalink raw reply related

* [PATCH 1/3] drm: mxsfb: Change driver.name to mxsfb-drm
From: Daniel Vetter @ 2018-06-18  7:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <6995fa4b-47a9-887b-5e4f-4284ca6a2c79@gmail.com>

On Sat, Jun 16, 2018 at 01:32:44AM +0200, Marek Vasut wrote:
> On 06/16/2018 12:42 AM, Leonard Crestez wrote:
> > On Fri, 2018-06-15 at 23:36 +0200, Marek Vasut wrote:
> >> On 06/15/2018 10:58 PM, Leonard Crestez wrote:
> >>> On Fri, 2018-06-15 at 16:47 -0300, Fabio Estevam wrote:
> >>>> On Fri, Jun 15, 2018 at 4:43 PM, Leonard Crestez
> >>>> <leonard.crestez@nxp.com> wrote:
> > 
> >>>>> The FBDEV driver uses the same name and both can't be registered at the
> >>>>> same time. Fix this by renaming the drm driver to mxsfb-drm
> >>>>
> >>>> Stefan sent the same patch a few days ago:
> >>>
> >>> In that thread there is a proposal for removing the old fbdev/mxsfb
> >>> driver entirely.
> >>>
> >>> That would break old DTBs, isn't this generally considered bad? Also,
> >>> are we sure the removal of fbdev/mxsfb wouldn't lose any features?
> >>>
> >>> What my series does is make both drivers work with the same kernel
> >>> image and turns the choice into a board-level dtb decision. Supporting
> >>> everything at once seems desirable to me and it allows for a very
> >>> smooth upgrade path.
> >>
> >> Having two drivers in the kernel with different set of bugs is always bad.
> >>
> >>> The old driver could be removed later, after all users are converted.
> >>
> >> Both drivers were in for long enough already. And let's be realistic,
> >> how many MX23/MX28 users of old DTs with new kernels are there who
> >> cannot update the DT as well ?
> > 
> > Grepping for "display =" in arch/arm/boot/dts/imx* I see that old
> > bindings are also used by 3rd-party boards for imx6/7:
> >  * imx6sx-nitrogen6sx
> >  * imx6ul-geam
> >  * imx6ul-isiot
> >  * imx6ul-opos6uldev
> >  * imx6ul-pico-hobbit
> >  * imx6ul-tx6ul
> >  * imx7d-nitrogen7
> 
> Er, yes, a handful of boards which could be updated :)
> 
> > Converting everything might be quite a bit of work, and explicitly
> > supporting old bindings is also work.
> 
> Does adding support for old bindings justify the effort invested ? I
> doubt so, it only adds more code to maintain.
> 
> > It is very confusing that there is a whole set of displays for imx6/7
> > which are supported by upstream but only with a non-default config.
> > While it is extremely common in the embedded field to have custom
> > configs the default one in the kernel should try to "just work".
> > 
> > Couldn't this patch series be considered a bugfix? It was also
> > surprisingly small.
> 
> I think it's just a workaround which allows you to postpone the real
> fix, and I don't like that.

Yeah agreed, imo the proper fix here would be to either update the dts for
the affected boards and/or make mxsfb accept the old dt bindings for
backwards compat. Artificially extending the life of the fbdev drivers
seems silly.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply

* [PATCH 0/5] RFC: Mezzanine handling for 96boards
From: Linus Walleij @ 2018-06-18  7:45 UTC (permalink / raw)
  To: linux-arm-kernel

This is a proposal for how to handle the non-discoverable
96boards plug-in expansion boards called "mezzanines" in the
Linux kernel. It is a working RFC series meant for discussion
at the moment.

The RFC was done on the brand new Ultra96 board from Xilinx
with a Secure96 mezzanine expansion board. The main part
is in patch 4, the rest is enabling and examples.

The code can be obtained from here:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96

You can for example probably augment the DTS file for any
upstream-supported 96board and get the Secure96 going with
it with minor efforts.

TODO:

- Proper device tree bindings for the connector, for now
  look at the example.

- Discuss whether to actually do this or just take it all and
  flush it down the drain because the community doesn't like
  it. I'm not one of those especially infatuated with my own code,
  I always stay by the old programming project management mantra
  to calculate to make one version and throw it away as stepping
  stone to a good final design.

- Placement: putting this in drivers/bus is just an example.
  drivers/platform/96boards-mezzanines is fine too, maybe better?

- I am especially curious about input from Andy and Mika from
  the Intel/ACPI camp on what they have seen for non-discoverable
  plug-in boards. Does this problem even exist in the Intel
  world, or not...

Background:

- These boards connect on a custom connector on this family
  of boards. The relationship is many-to-many with the connector
  as nexus. The electronic standard for the connector is specified:
  https://github.com/96boards/documentation/blob/master/Specifications/96Boards-CE-Specification.pdf
  Example mezzanines:
  https://www.96boards.org/documentation/mezzanine/

- These boards have siblings on other platforms, the problem
  scope is similar with BeagleBone "capes":
  https://beagleboard.org/capes
  Raspberry Pi expansion boards:
  https://www.abelectronics.co.uk/products/18/raspberry-pi-expansion-boards
  Intel Edison, Galileo, Joule also have expansion boards.

Idea: add a driver for the connector itself and tie it in to
the device tree with a compatible string. Since the boards
are non-discoverable two mechanisms are provided to discover
them:

- Add a very simple device tree node with just a compatible
  string for the board in the node. This will be simple to
  add from e.g. a boot loader or as an overlay from userspace.

  board {
        compatible = "96boards,secure96";
  };


- Echo 1 > boardname into a sysfs file to populate the
  board and echo 0 > boardname to depopulate it. This
  makes it easy to even switch out expansion boards at
  runtime, if allowed by the electronics.

  > cd /sys/devices/platform/connector
  > echo 1 > secure96
  lscon connector: called mezzanine_store on secure96
  lscon connector: populate secure96
  at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write
  atmel-ecc 1-0060: configuration zone is unlocked
  tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16)
  (...)

What this patch set does not do:

- It does not use device tree or ACPI DSDT or any other
  hardware decription language to model the contents of the
  board per se. Instead the boards buses are populated
  directly with platform devices.

Predictable complaints about this design:

Q: This is not device tree overlays. Why is it not device
   tree overlays?

A1: Right tool for the job, overlays are complex and the
    plan to get it in place seems to be spanning years, this
    is a few devices on simple busses and it works today.
    Using this approach I can already work on shaping up
    drivers for the mezzanine board devices as proved by:
    https://marc.info/?l=linux-crypto-vger&m=152820660120590&w=2
    https://marc.info/?l=linux-crypto-vger&m=152820662820595&w=2
    (...)

    I can work on drivers for the chips on the
    Secure96 mezzanine board. It's just an example of
    what the mezzanine community can do.
    Now they are hacking around in userspace instead of
    doing/reusing kernel drivers for their stuff:
    https://github.com/jbech-linaro/secure96

    This way we can bring developers for these components
    into the kernel community instead of telling them to
    wait for some big infrastructure that comes later
    before they can contribute their stuff.

A2: Overlays does not solve the problem if the system runs
    ACPI, and what about if the same connector[s] appear
    on a server board, servers use ACPI. Also notice
    that Intel have development boards with non-discoverable
    expansion boards as well. They just will not use
    device tree.

A3: Overlays is Big Upfront Design.
    https://en.wikipedia.org/wiki/Big_Design_Up_Front
    This way of designing things is associated with the
    (pejorative term) "waterfall model" which is out of
    fashion as a way of doing development. I think I am not
    the only one slightly annoyed by the fact that device
    tree overlays is now starting to look like a very
    big very upfront design. It's just not possible to get
    something up and running in small iterative steps with
    device tree overlays. Instead huge efforts are
    required and it involves major possible showstoppers
    and uncertain outcome as indicated by Frank's TODO:
    https://elinux.org/Frank's_Evolving_Overlay_Thoughts

    This appears also in our work process documents:
    Documentation/process/4.Coding.rst
    "experience has shown that excessive or premature
     abstraction can be just as harmful as premature
     optimization.  Abstraction should be used to the level
     required and no further."

So for that reason, or other predictable statements such
as "you're reinventing board files", I'd like to have an
open discussion on how to actually support these boards
with the mainline kernel and work on device drivers common
with other systems now, and not in 2020 when they are already
obsolete.

Yeah it is a bit controversial, but what we are doing right
now for non-discoverable expansion boards isn't working
in my opinion, so I have to throw something out there,
and this is it.

Linus Walleij (5):
  RFC: gpio: Add API to explicitly name a consumer
  RFC: eeprom: at24: Allow passing gpiodesc from pdata
  RFC: spi: Make of_find_spi_device_by_node() available
  RFC: bus: 96boards Low-Speed Connector
  RFC: ARM64: dts: Add Low-Speed Connector to ZCU100

 .../boot/dts/xilinx/zynqmp-zcu100-revC.dts    |  27 +-
 .../96boards-ls-connector.c                   | 307 ++++++++++++++++++
 .../96boards-mezzanines/96boards-mezzanines.h |  46 +++
 .../96boards-mezzanines/96boards-secure96.c   | 249 ++++++++++++++
 drivers/bus/96boards-mezzanines/Kconfig       |  36 ++
 drivers/bus/96boards-mezzanines/Makefile      |   6 +
 drivers/bus/Kconfig                           |   2 +
 drivers/bus/Makefile                          |   4 +-
 drivers/gpio/gpiolib.c                        |  13 +
 drivers/misc/eeprom/at24.c                    |   6 +-
 drivers/spi/spi.c                             |  33 +-
 include/linux/gpio/consumer.h                 |   7 +
 include/linux/platform_data/at24.h            |   2 +
 include/linux/spi/spi.h                       |   4 +
 14 files changed, 723 insertions(+), 19 deletions(-)
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-ls-connector.c
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-mezzanines.h
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-secure96.c
 create mode 100644 drivers/bus/96boards-mezzanines/Kconfig
 create mode 100644 drivers/bus/96boards-mezzanines/Makefile

-- 
2.17.0

^ permalink raw reply

* [PATCH 1/5] RFC: gpio: Add API to explicitly name a consumer
From: Linus Walleij @ 2018-06-18  7:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074556.6944-1-linus.walleij@linaro.org>

The GPIO (descriptor) API registers a "label" naming what is
currently using the GPIO line. Typically this is taken from
things like the device tree node, so "reset-gpios" will result
in he line being labeled "reset".

The technical effect is pretty much zero: the use is for
debug and introspection, such as "lsgpio" and debugfs files.

However sometimes the user want this cuddly feeling of
listing all GPIO lines and seeing exactly what they are for
and it gives a very fulfilling sense of control. Especially
in the cases when the device tree node doesn't provide a
good name, or anonymous GPIO lines assigned just to
"gpios" in the device tree because the usage is implicit.

For these cases it may be nice to be able to label the
line directly and explicitly.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/gpio/gpiolib.c        | 13 +++++++++++++
 include/linux/gpio/consumer.h |  7 +++++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index e11a3bb03820..c6f77e806cb8 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3193,6 +3193,19 @@ int gpiod_cansleep(const struct gpio_desc *desc)
 }
 EXPORT_SYMBOL_GPL(gpiod_cansleep);
 
+/**
+ * gpiod_set_consumer_name() - set the consumer name for the descriptor
+ * @desc: gpio to set the consumer name on
+ * @name: the new consumer name
+ */
+void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
+{
+	VALIDATE_DESC_VOID(desc);
+	/* Just overwrite whatever the previous name was */
+	desc->label = name;
+}
+EXPORT_SYMBOL_GPL(gpiod_set_consumer_name);
+
 /**
  * gpiod_to_irq() - return the IRQ corresponding to a GPIO
  * @desc: gpio whose IRQ will be returned (already requested)
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 243112c7fa7d..e8aaf34dd65d 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -145,6 +145,7 @@ int gpiod_is_active_low(const struct gpio_desc *desc);
 int gpiod_cansleep(const struct gpio_desc *desc);
 
 int gpiod_to_irq(const struct gpio_desc *desc);
+void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name);
 
 /* Convert between the old gpio_ and new gpiod_ interfaces */
 struct gpio_desc *gpio_to_desc(unsigned gpio);
@@ -467,6 +468,12 @@ static inline int gpiod_to_irq(const struct gpio_desc *desc)
 	return -EINVAL;
 }
 
+static inline void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+}
+
 static inline struct gpio_desc *gpio_to_desc(unsigned gpio)
 {
 	return ERR_PTR(-EINVAL);
-- 
2.17.0

^ permalink raw reply related

* [PATCH 2/5] RFC: eeprom: at24: Allow passing gpiodesc from pdata
From: Linus Walleij @ 2018-06-18  7:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074556.6944-1-linus.walleij@linaro.org>

This makes it possible to pass an initialized GPIO descriptor
to the driver through platform data.

This is useful when we are dealing with EEPROMs on expansion
boards where the GPIO has to be looked up indirectly using a
connector abstraction (several systems using the same
connector) so the machine descriptor tables cannot be used
to associate the descriptor with the device and we then want
to pass this descriptor on to the EEPROM driver this way
instead.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/misc/eeprom/at24.c         | 6 +++++-
 include/linux/platform_data/at24.h | 2 ++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index f5cc517d1131..d577cdbe221e 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -662,7 +662,11 @@ static int at24_probe(struct i2c_client *client)
 	at24->client[0].client = client;
 	at24->client[0].regmap = regmap;
 
-	at24->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH);
+	if (pdata.wp_gpiod)
+		at24->wp_gpio = pdata.wp_gpiod;
+	else
+		at24->wp_gpio =
+			devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH);
 	if (IS_ERR(at24->wp_gpio))
 		return PTR_ERR(at24->wp_gpio);
 
diff --git a/include/linux/platform_data/at24.h b/include/linux/platform_data/at24.h
index 63507ff464ee..5606fb2ef76c 100644
--- a/include/linux/platform_data/at24.h
+++ b/include/linux/platform_data/at24.h
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/bitops.h>
+#include <linux/gpio/consumer.h>
 
 /**
  * struct at24_platform_data - data to set up at24 (generic eeprom) driver
@@ -55,6 +56,7 @@ struct at24_platform_data {
 
 	void		(*setup)(struct nvmem_device *nvmem, void *context);
 	void		*context;
+	struct gpio_desc *wp_gpiod;
 };
 
 #endif /* _LINUX_AT24_H */
-- 
2.17.0

^ permalink raw reply related

* [PATCH 3/5] RFC: spi: Make of_find_spi_device_by_node() available
From: Linus Walleij @ 2018-06-18  7:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074556.6944-1-linus.walleij@linaro.org>

This externalizes and exports the symbol
of_find_spi_device_by_node() from the SPI core akin to how
of_find_i2c_adapter_by_node() is already available. As we will
need this also for non-dynamic OF setups, we move it under a
CONFIG_OF check.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/spi/spi.c       | 33 ++++++++++++++++++---------------
 include/linux/spi/spi.h |  4 ++++
 2 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index ec395a6baf9c..6a1085077317 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3314,27 +3314,14 @@ EXPORT_SYMBOL_GPL(spi_write_then_read);
 
 /*-------------------------------------------------------------------------*/
 
-#if IS_ENABLED(CONFIG_OF_DYNAMIC)
-static int __spi_of_device_match(struct device *dev, void *data)
-{
-	return dev->of_node == data;
-}
-
-/* must call put_device() when done with returned spi_device device */
-static struct spi_device *of_find_spi_device_by_node(struct device_node *node)
-{
-	struct device *dev = bus_find_device(&spi_bus_type, NULL, node,
-						__spi_of_device_match);
-	return dev ? to_spi_device(dev) : NULL;
-}
-
+#if IS_ENABLED(CONFIG_OF)
 static int __spi_of_controller_match(struct device *dev, const void *data)
 {
 	return dev->of_node == data;
 }
 
 /* the spi controllers are not using spi_bus, so we find it with another way */
-static struct spi_controller *of_find_spi_controller_by_node(struct device_node *node)
+struct spi_controller *of_find_spi_controller_by_node(struct device_node *node)
 {
 	struct device *dev;
 
@@ -3349,6 +3336,22 @@ static struct spi_controller *of_find_spi_controller_by_node(struct device_node
 	/* reference got in class_find_device */
 	return container_of(dev, struct spi_controller, dev);
 }
+EXPORT_SYMBOL_GPL(of_find_spi_controller_by_node);
+#endif
+
+#if IS_ENABLED(CONFIG_OF_DYNAMIC)
+static int __spi_of_device_match(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+/* must call put_device() when done with returned spi_device device */
+static struct spi_device *of_find_spi_device_by_node(struct device_node *node)
+{
+	struct device *dev = bus_find_device(&spi_bus_type, NULL, node,
+						__spi_of_device_match);
+	return dev ? to_spi_device(dev) : NULL;
+}
 
 static int of_spi_notify(struct notifier_block *nb, unsigned long action,
 			 void *arg)
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index a64235e05321..c2be93224bd1 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -639,6 +639,10 @@ extern int devm_spi_register_controller(struct device *dev,
 					struct spi_controller *ctlr);
 extern void spi_unregister_controller(struct spi_controller *ctlr);
 
+#if IS_ENABLED(CONFIG_OF)
+struct spi_controller *of_find_spi_controller_by_node(struct device_node *node);
+#endif
+
 extern struct spi_controller *spi_busnum_to_master(u16 busnum);
 
 /*
-- 
2.17.0

^ permalink raw reply related

* [PATCH 4/5] RFC: bus: 96boards Low-Speed Connector
From: Linus Walleij @ 2018-06-18  7:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074556.6944-1-linus.walleij@linaro.org>

This illustrates my idea for using a small connector driver to
plug in "mezzanine boards" on the 96boards low-speed connector.

These "mezzanine boards" are no different than "capes", "logic
modules", etc. This thing, a non-discoverable connector where
a user can plug in a few peripherals has been reinvented a few
times.

As a proof-of-concept we add the Secure96, a quite minimal
mezzanine board.

Users can register their boards in a simple way. Either just
add their compatible-string in the device tree:

board {
        compatible = "96boards,secure96";
};

And if they can't even change three lines in their device tree,
or if they at runtime decide to plug in some board and test it,
they can use sysfs, as exemplified by plugging in the secure96
security board at runtime:

> cd /sys/devices/platform/connector
> echo 1 > secure96
[   61.014629] lscon connector: called mezzanine_store on secure96
[   61.020530] lscon connector: populate secure96
[   61.027081] at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write
[   61.053569] atmel-ecc 1-0060: configuration zone is unlocked
[   61.502535] tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16)
(...)

The plug-in board can be removed from sysfs and added back
again multiple times like this with the devices being runtime
added and removed by two writes to sysfs.

> echo 0 > secure96
> echo 1 > secure96
> echo 0 > secure96
(...)

I certainly see some scalability problems with this particular
code for example, but the fact is: it pretty much works. The
devices need hooks in I2C and SPI, and need to be able to accept
initialized GPIO descriptors passed in as platform data.

Any discussions related to the concept compared to doing
device tree overlays/fragments etc: please discuss in patch
0 (the cover letter).

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 .../96boards-ls-connector.c                   | 307 ++++++++++++++++++
 .../96boards-mezzanines/96boards-mezzanines.h |  46 +++
 .../96boards-mezzanines/96boards-secure96.c   | 249 ++++++++++++++
 drivers/bus/96boards-mezzanines/Kconfig       |  36 ++
 drivers/bus/96boards-mezzanines/Makefile      |   6 +
 drivers/bus/Kconfig                           |   2 +
 drivers/bus/Makefile                          |   4 +-
 7 files changed, 649 insertions(+), 1 deletion(-)
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-ls-connector.c
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-mezzanines.h
 create mode 100644 drivers/bus/96boards-mezzanines/96boards-secure96.c
 create mode 100644 drivers/bus/96boards-mezzanines/Kconfig
 create mode 100644 drivers/bus/96boards-mezzanines/Makefile

diff --git a/drivers/bus/96boards-mezzanines/96boards-ls-connector.c b/drivers/bus/96boards-mezzanines/96boards-ls-connector.c
new file mode 100644
index 000000000000..1a012b0cd457
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/96boards-ls-connector.c
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * 96boards Low-speed Connector driver
+ * (C) 2018 Linus Walleij <linus.walleij@linaro.org>
+ */
+
+#include <linux/init.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include "96boards-mezzanines.h"
+
+/**
+ * struct mezzanine - daughter boards (mezzanines) data
+ * Having dynamic data here means that we can only plug ONE board
+ * of each type. Stacking two different boards is fine. This
+ * should be fixed using a linked list of mezzanines if we
+ * go for this solution.
+ */
+struct mezzanine {
+	const char *compatible;
+	const char *sysfs_name;
+	struct dev_ext_attribute ext_attr;
+	void * (*populate) (struct lscon *ls);
+	void (*depopulate) (void *data);
+	void *data;
+};
+
+static struct mezzanine mezzanines[] = {
+#if IS_ENABLED(96BOARDS_SECURE96)
+	{
+		.compatible = "96boards,secure96",
+		.sysfs_name = "secure96",
+		.populate = secure96_populate,
+		.depopulate = secure96_depopulate,
+	},
+#endif
+	/* Add any other mezzanines here */
+};
+
+struct gpio_desc *mezzanine_ls_get_gpiod(struct lscon *ls,
+					 enum mezzanine_ls_gpio pin,
+					 const char *consumer_name,
+					 enum gpiod_flags flags)
+{
+	struct gpio_desc *retdesc;
+
+	/*
+	 * TODO: get all the LS GPIOs as an array on probe() then
+	 * the consumers can skip error handling of IS_ERR() descriptors
+	 * and this need only set the consumer name.
+	 */
+	retdesc = devm_gpiod_get_index(ls->dev, NULL, pin, flags);
+	if (!IS_ERR(retdesc) && consumer_name)
+		gpiod_set_consumer_name(retdesc, consumer_name);
+
+	return retdesc;
+}
+EXPORT_SYMBOL_GPL(mezzanine_ls_get_gpiod);
+
+/*
+ * Mezzanine boards will call this to orderly remove their claimed
+ * gpio descriptors, since we acquired them all with devm_gpiod_get()
+ * they will eventually be released once this connector device
+ * disappears if the board do not release them in order.
+ */
+void mezzanine_ls_put_gpiod(struct lscon *ls, struct gpio_desc *gpiod)
+{
+	devm_gpiod_put(ls->dev, gpiod);
+}
+EXPORT_SYMBOL_GPL(mezzanine_ls_put_gpiod);
+
+static ssize_t mezzanine_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct lscon *ls = dev_get_drvdata(dev);
+	struct dev_ext_attribute *d = container_of(attr,
+						   struct dev_ext_attribute,
+						   attr);
+	struct mezzanine *mez = d->var;
+
+	dev_info(ls->dev, "called %s on %s\n", __func__, mez->sysfs_name);
+	return 0;
+}
+
+static ssize_t mezzanine_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct lscon *ls = dev_get_drvdata(dev);
+	struct dev_ext_attribute *d = container_of(attr,
+						   struct dev_ext_attribute,
+						   attr);
+	struct mezzanine *mez = d->var;
+	unsigned long state;
+	int ret;
+
+	dev_info(ls->dev, "called %s on %s\n", __func__, mez->sysfs_name);
+
+	ret = kstrtoul(buf, 0, &state);
+	if (ret)
+		return ret;
+
+	if (state == 1) {
+		void *data;
+
+		/* Already populated */
+		if (mez->data)
+			return count;
+
+		data = mez->populate(ls);
+		if (IS_ERR(data))
+			return PTR_ERR(data);
+		mez->data = data;
+		return count;
+	}
+
+	if (state == 0) {
+		/* Not populated so nothing to do here */
+		if (!mez->data)
+			return count;
+		mez->depopulate(mez->data);
+		mez->data = NULL;
+		return count;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * This adds one sysfs file per mezzanine board that we support, so they
+ * can be probed and added from userspace.
+ */
+static int lscon_add_sysfs_mezzanines(struct lscon *ls)
+{
+	struct mezzanine *mez;
+	struct dev_ext_attribute *ext_attr;
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		ext_attr = &mez->ext_attr;
+
+		ext_attr->var = mez;
+		ext_attr->attr.attr.name = mez->sysfs_name;
+		ext_attr->attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(0644);
+		ext_attr->attr.show = mezzanine_show;
+		ext_attr->attr.store = mezzanine_store;
+		ret = device_create_file(ls->dev, &ext_attr->attr);
+		if (ret)
+			dev_err(ls->dev, "unable to create sysfs entries\n");
+
+	}
+
+	return 0;
+}
+
+static int lscon_probe_of_mezzanine(struct lscon *ls, struct device_node *np)
+{
+	struct mezzanine *mez;
+	void *data;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (of_device_is_compatible(np, mez->compatible)) {
+			dev_info(ls->dev, "found %s\n", mez->compatible);
+			data = mez->populate(ls);
+			if (IS_ERR(data))
+				return PTR_ERR(data);
+			mez->data = data;
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int lscon_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *child;
+	struct spi_controller *spi;
+	struct mezzanine *mez;
+	struct lscon *ls;
+	int ret;
+	int i;
+
+	ls = devm_kzalloc(dev, sizeof(*ls), GFP_KERNEL);
+	if (!ls)
+		return -ENOMEM;
+	ls->dev = dev;
+
+	/* Bridge I2C busses */
+	child = of_parse_phandle(np, "i2c0", 0);
+	if (!child) {
+		dev_err(dev, "no i2c0 phandle\n");
+		return -ENODEV;
+	}
+	ls->i2c0 = of_get_i2c_adapter_by_node(child);
+	if (!ls->i2c0) {
+		dev_err(dev, "no i2c0 adapter, deferring\n");
+		return -EPROBE_DEFER;
+	}
+
+	child = of_parse_phandle(np, "i2c1", 0);
+	if (!child) {
+		dev_err(dev, "no i2c1 phandle\n");
+		ret = -ENODEV;
+		goto out_put_i2c0;
+	}
+	ls->i2c1 = of_get_i2c_adapter_by_node(child);
+	if (!ls->i2c1) {
+		dev_err(dev, "no i2c0 adapter, deferring\n");
+		ret = -EPROBE_DEFER;
+		goto out_put_i2c0;
+	}
+
+	/* Bride SPI bus */
+	child = of_parse_phandle(np, "spi", 0);
+	if (!child) {
+		dev_err(dev, "no spi phandle\n");
+		ret = -ENODEV;
+		goto out_put_i2c1;
+	}
+	spi = of_find_spi_controller_by_node(child);
+	if (!spi) {
+		dev_err(dev, "no spi controller, deferring\n");
+		ret = -EPROBE_DEFER;
+		goto out_put_i2c1;
+	}
+	ls->spi = spi_controller_get(spi);
+	if (!ls->spi) {
+		dev_err(dev, "no spi reference\n");
+		ret = -ENODEV;
+		goto out_put_i2c1;
+	}
+
+	platform_set_drvdata(pdev, ls);
+
+	/* Get the mezzanine boards, stacking possible */
+	for_each_available_child_of_node(np, child)
+		lscon_probe_of_mezzanine(ls, child);
+
+	ret = lscon_add_sysfs_mezzanines(ls);
+	if (ret)
+		goto out_remove_mezzanines;
+
+	return 0;
+
+out_remove_mezzanines:
+	/* Depopulate any populated boards */
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (mez->data)
+			mez->depopulate(mez->data);
+		mez->data = NULL;
+	}
+out_put_i2c1:
+	i2c_put_adapter(ls->i2c1);
+out_put_i2c0:
+	i2c_put_adapter(ls->i2c0);
+	return ret;
+}
+
+static int lscon_remove(struct platform_device *pdev)
+{
+	struct lscon *ls = platform_get_drvdata(pdev);
+	struct mezzanine *mez;
+	int i;
+
+	/* Depopulate any populated boards */
+	for (i = 0; i < ARRAY_SIZE(mezzanines); i++) {
+		mez = &mezzanines[i];
+		if (mez->data)
+			mez->depopulate(mez->data);
+		mez->data = NULL;
+	}
+
+	spi_controller_put(ls->spi);
+	i2c_put_adapter(ls->i2c1);
+	i2c_put_adapter(ls->i2c0);
+
+	return 0;
+}
+
+static const struct of_device_id lscon_of_match[] = {
+	{
+		.compatible = "96boards,low-speed-connector",
+	},
+};
+
+static struct platform_driver lscon_driver = {
+	.driver = {
+		.name = "lscon",
+		.of_match_table = of_match_ptr(lscon_of_match),
+	},
+	.probe  = lscon_probe,
+	.remove = lscon_remove,
+};
+builtin_platform_driver(lscon_driver);
diff --git a/drivers/bus/96boards-mezzanines/96boards-mezzanines.h b/drivers/bus/96boards-mezzanines/96boards-mezzanines.h
new file mode 100644
index 000000000000..f6a460766ff3
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/96boards-mezzanines.h
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+
+/**
+ * enum mezzanine_ls_gpio - the GPIO lines on the low-speed connector
+ */
+enum mezzanine_ls_gpio {
+	MEZZANINE_LS_GPIO_A = 0,
+	MEZZANINE_LS_GPIO_B,
+	MEZZANINE_LS_GPIO_C,
+	MEZZANINE_LS_GPIO_D,
+	MEZZANINE_LS_GPIO_E,
+	MEZZANINE_LS_GPIO_F,
+	MEZZANINE_LS_GPIO_G,
+	MEZZANINE_LS_GPIO_H,
+	MEZZANINE_LS_GPIO_I,
+	MEZZANINE_LS_GPIO_J,
+	MEZZANINE_LS_GPIO_K,
+	MEZZANINE_LS_GPIO_L,
+};
+
+/**
+ * struct lscon - low speed connector state container
+ * @dev: containing device for this instance
+ */
+struct lscon {
+	struct device *dev;
+	struct i2c_adapter *i2c0;
+	struct i2c_adapter *i2c1;
+	struct spi_controller *spi;
+};
+
+struct gpio_desc *mezzanine_ls_get_gpiod(struct lscon *ls,
+					 enum mezzanine_ls_gpio pin,
+					 const char *consumer_name,
+					 enum gpiod_flags flags);
+void mezzanine_ls_put_gpiod(struct lscon *ls, struct gpio_desc *gpiod);
+
+#if IS_ENABLED(96BOARDS_SECURE96)
+void *secure96_populate(struct lscon *ls);
+void secure96_depopulate(void *data);
+#endif
+/* Add any other mezzanine population calls here */
diff --git a/drivers/bus/96boards-mezzanines/96boards-secure96.c b/drivers/bus/96boards-mezzanines/96boards-secure96.c
new file mode 100644
index 000000000000..6c44a699d2e0
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/96boards-secure96.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * 96boards Secure96 mezzanine board driver
+ * (C) 2018 Linus Walleij <linus.walleij@linaro.org>
+ */
+#include <linux/gpio/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/sizes.h>
+#include <linux/platform_data/at24.h>
+#include <linux/delay.h>
+
+#include "96boards-mezzanines.h"
+
+struct secure96 {
+	struct device *dev;
+	struct lscon *ls;
+	struct platform_device *leds_device;
+	struct gpio_led *secure96_leds;
+	struct i2c_client *eeprom;
+	struct i2c_client *crypto;
+	struct i2c_client *hash;
+	struct gpio_desc *tpm_reset;
+	struct gpio_desc *tpm_irq;
+	struct spi_device *tpm;
+};
+
+struct secure96_ledinfo {
+	enum mezzanine_ls_gpio pin;
+	const char *ledname;
+};
+
+/*
+ * GPIO-F, G, H and I are connected to LEDs, two red and two green
+ */
+static const struct secure96_ledinfo ledinfos[] = {
+	{
+		.pin = MEZZANINE_LS_GPIO_F,
+		.ledname = "secure96:red:0",
+	},
+	{
+		.pin = MEZZANINE_LS_GPIO_G,
+		.ledname = "secure96:red:1",
+	},
+	{
+		.pin = MEZZANINE_LS_GPIO_H,
+		.ledname = "secure96:green:0",
+	},
+	{
+		.pin = MEZZANINE_LS_GPIO_I,
+		.ledname = "secure96:green:1",
+	},
+};
+
+/*
+ * The On Semiconductor CAT21M01 is 131072bits i.e. 16KB. This should be
+ * mostly compatible to 24c128 so we register that with special pdata so
+ * that we can fill in the GPIO descriptor for write protect.
+ */
+static struct at24_platform_data secure96_eeprom_pdata = {
+	.byte_len = SZ_16K / 8,
+	.page_size = 256,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static const struct i2c_board_info secure96_eeprom = {
+	I2C_BOARD_INFO("24c128", 0x50),
+	.platform_data  = &secure96_eeprom_pdata,
+};
+
+/* Crypto chip */
+static const struct i2c_board_info secure96_crypto = {
+	I2C_BOARD_INFO("atecc508a", 0x60),
+};
+
+/* SHA hash chip */
+static const struct i2c_board_info secure96_hash = {
+	I2C_BOARD_INFO("atsha204a", 0x64),
+};
+
+/* Infineon SLB9670 TPM 2.0 chip */
+static struct spi_board_info secure96_tpm = {
+	.modalias = "tpm_tis_spi",
+	/* The manual says 22.5MHz for 1.8V supply */
+	.max_speed_hz = 22500000,
+	.chip_select = 0,
+};
+
+void *secure96_populate(struct lscon *ls)
+{
+	struct device *dev = ls->dev;
+	struct secure96 *sec;
+	struct gpio_desc *gpiod;
+	struct gpio_led_platform_data secure96_leds_pdata;
+	int ret;
+	int i;
+
+	/* TODO: create a struct device for secure96? */
+
+	sec = devm_kzalloc(dev, sizeof(*sec), GFP_KERNEL);
+	if (!sec)
+		return ERR_PTR(-ENOMEM);
+	sec->dev = dev;
+	sec->ls = ls;
+
+	sec->secure96_leds = devm_kzalloc(dev,
+			ARRAY_SIZE(ledinfos) * sizeof(*sec->secure96_leds),
+			GFP_KERNEL);
+	if (!sec->secure96_leds)
+		return ERR_PTR(-ENOMEM);
+
+	dev_info(ls->dev, "populate secure96\n");
+
+	/* Populate the four LEDs */
+	for (i = 0; i < ARRAY_SIZE(ledinfos); i++) {
+		const struct secure96_ledinfo *linfo;
+
+		linfo = &ledinfos[i];
+
+		gpiod = mezzanine_ls_get_gpiod(ls, linfo->pin, linfo->ledname,
+					       GPIOD_OUT_LOW);
+		if (IS_ERR(gpiod)) {
+			dev_err(dev, "failed to get GPIO line %d\n",
+				linfo->pin);
+			return ERR_PTR(-ENODEV);
+		}
+		sec->secure96_leds[i].gpiod = gpiod;
+		sec->secure96_leds[i].name = linfo->ledname;
+		/* Heartbeat on first LED */
+		if (i == 0)
+			sec->secure96_leds[i].default_trigger = "heartbeat";
+	}
+
+	secure96_leds_pdata.num_leds = ARRAY_SIZE(ledinfos);
+	secure96_leds_pdata.leds = sec->secure96_leds;
+
+	sec->leds_device = platform_device_register_data(dev,
+					"leds-gpio",
+					PLATFORM_DEVID_AUTO,
+					&secure96_leds_pdata,
+					sizeof(secure96_leds_pdata));
+	if (IS_ERR(sec->leds_device)) {
+		dev_err(dev, "failed to populate LEDs device\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	/* Populate the three I2C0 devices */
+	gpiod = mezzanine_ls_get_gpiod(ls, MEZZANINE_LS_GPIO_B, "cat21m01-wp",
+				       GPIOD_OUT_HIGH);
+	if (IS_ERR(gpiod))
+		dev_err(dev, "no CAT21M01 write-protect GPIO\n");
+	else
+		secure96_eeprom_pdata.wp_gpiod = gpiod;
+	sec->eeprom = i2c_new_device(ls->i2c0, &secure96_eeprom);
+	if (!sec->eeprom) {
+		dev_err(dev, "failed to populate EEPROM\n");
+		ret = -ENODEV;
+		goto out_unreg_leds;
+	}
+
+	sec->crypto = i2c_new_device(ls->i2c0, &secure96_crypto);
+	if (!sec->eeprom) {
+		dev_err(dev, "failed to populate crypto device\n");
+		ret = -ENODEV;
+		goto out_remove_eeprom;
+	}
+
+	sec->hash = i2c_new_device(ls->i2c0, &secure96_hash);
+	if (!sec->eeprom) {
+		dev_err(dev, "failed to populate hash device\n");
+		ret = -ENODEV;
+		goto out_remove_crypto;
+	}
+
+	/* Populate the SPI TPM device */
+	gpiod = mezzanine_ls_get_gpiod(ls, MEZZANINE_LS_GPIO_D,
+				       "tpm-slb9670-rst",
+				       GPIOD_OUT_LOW);
+	if (IS_ERR(gpiod)) {
+		dev_err(dev, "failed to get TPM RESET\n");
+		ret = -ENODEV;
+		goto out_remove_hash;
+	}
+	udelay(80);
+	/* Deassert RST */
+	gpiod_set_value(gpiod, 1);
+	sec->tpm_reset = gpiod;
+
+	gpiod = mezzanine_ls_get_gpiod(ls, MEZZANINE_LS_GPIO_C,
+				       "tpm-slb9670-irq",
+				       GPIOD_IN);
+	if (IS_ERR(gpiod)) {
+		dev_err(dev, "failed to get TPM IRQ GPIO\n");
+		ret = -ENODEV;
+		goto out_remove_tpm_reset;
+	}
+	sec->tpm_irq = gpiod;
+	secure96_tpm.irq = gpiod_to_irq(gpiod);
+	sec->tpm = spi_new_device(ls->spi, &secure96_tpm);
+	if (!sec->tpm) {
+		dev_err(dev, "failed to populate TPM device\n");
+		ret = -ENODEV;
+		goto out_remove_tpm_irq;
+	}
+
+	return sec;
+
+out_remove_tpm_irq:
+	mezzanine_ls_put_gpiod(ls, sec->tpm_irq);
+out_remove_tpm_reset:
+	mezzanine_ls_put_gpiod(ls, sec->tpm_reset);
+out_remove_hash:
+	i2c_unregister_device(sec->hash);
+out_remove_crypto:
+	i2c_unregister_device(sec->crypto);
+out_remove_eeprom:
+	i2c_unregister_device(sec->eeprom);
+	if (secure96_eeprom_pdata.wp_gpiod)
+		mezzanine_ls_put_gpiod(ls, secure96_eeprom_pdata.wp_gpiod);
+out_unreg_leds:
+	platform_device_unregister(sec->leds_device);
+	for (i = 0; i < ARRAY_SIZE(ledinfos); i++) {
+		mezzanine_ls_put_gpiod(ls, sec->secure96_leds[i].gpiod);
+	};
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(secure96_populate);
+
+void secure96_depopulate(void *data)
+{
+	struct secure96 *sec = data;
+	int i;
+
+	spi_unregister_device(sec->tpm);
+	mezzanine_ls_put_gpiod(sec->ls, sec->tpm_irq);
+	mezzanine_ls_put_gpiod(sec->ls, sec->tpm_reset);
+	i2c_unregister_device(sec->hash);
+	i2c_unregister_device(sec->crypto);
+	i2c_unregister_device(sec->eeprom);
+	if (secure96_eeprom_pdata.wp_gpiod)
+		mezzanine_ls_put_gpiod(sec->ls, secure96_eeprom_pdata.wp_gpiod);
+	platform_device_unregister(sec->leds_device);
+	for (i = 0; i < ARRAY_SIZE(ledinfos); i++) {
+		mezzanine_ls_put_gpiod(sec->ls, sec->secure96_leds[i].gpiod);
+	};
+}
+EXPORT_SYMBOL_GPL(secure96_depopulate);
diff --git a/drivers/bus/96boards-mezzanines/Kconfig b/drivers/bus/96boards-mezzanines/Kconfig
new file mode 100644
index 000000000000..18f94e9ec0f8
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/Kconfig
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# 96boards mezzanine connectors and drivers
+
+menuconfig 96BOARDS_MEZZANINES
+	bool "96boards mezzanine boards"
+
+if 96BOARDS_MEZZANINES
+
+config 96BOARDS_LS_CONNECTOR
+	bool "96boards low speed connector driver"
+	depends on OF
+	depends on I2C
+	depends on SPI_MASTER
+	depends on GPIOLIB
+	help
+	 Driver for the 96boards low speed connector
+
+config 96BOARDS_SECURE96
+	bool "96boards Secure96 board driver"
+	depends on 96BOARDS_LS_CONNECTOR
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_GPIO
+	select EEPROM_AT24
+	select CRYPTO_HW
+	select CRYPTO_DEV_ATMEL_ECC
+	select HW_RANDOM
+	select TCG_TPM
+	select HW_RANDOM_TPM
+	select TCG_TIS
+	select TCG_TIS_SPI
+	help
+	 Driver for the 96boards Secure96 mezzanine
+
+endif
diff --git a/drivers/bus/96boards-mezzanines/Makefile b/drivers/bus/96boards-mezzanines/Makefile
new file mode 100644
index 000000000000..a6e1f3507672
--- /dev/null
+++ b/drivers/bus/96boards-mezzanines/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the 96boards mezzanines
+#
+obj-$(CONFIG_96BOARDS_LS_CONNECTOR)	+= 96boards-ls-connector.o
+obj-$(CONFIG_96BOARDS_SECURE96)		+= 96boards-secure96.o
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index d1c0b60e9326..46f7785f27e9 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -173,4 +173,6 @@ config DA8XX_MSTPRI
 
 source "drivers/bus/fsl-mc/Kconfig"
 
+source "drivers/bus/96boards-mezzanines/Kconfig"
+
 endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index b8f036cca7ff..f6d080a63bd7 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -29,5 +29,7 @@ obj-$(CONFIG_TI_SYSC)		+= ti-sysc.o
 obj-$(CONFIG_TS_NBUS)		+= ts-nbus.o
 obj-$(CONFIG_UNIPHIER_SYSTEM_BUS)	+= uniphier-system-bus.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o
-
 obj-$(CONFIG_DA8XX_MSTPRI)	+= da8xx-mstpri.o
+
+# 96boards mezzanines
+obj-$(CONFIG_96BOARDS_MEZZANINES)	+= 96boards-mezzanines/
-- 
2.17.0

^ 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