Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 07/19] irqchip/mmp: mask off interrupts from other cores
From: Marc Zyngier @ 2019-08-09 12:18 UTC (permalink / raw)
  To: Lubomir Rintel, Olof Johansson
  Cc: Mark Rutland, devicetree, Jason Cooper, Stephen Boyd,
	linux-kernel, Michael Turquette, Russell King,
	Kishon Vijay Abraham I, Rob Herring, Andres Salomon,
	Thomas Gleixner, linux-clk, linux-arm-kernel
In-Reply-To: <20190809093158.7969-8-lkundrak@v3.sk>

On 09/08/2019 10:31, Lubomir Rintel wrote:
> From: Andres Salomon <dilinger@queued.net>
> 
> On mmp3, there's an extra set of ICU registers (ICU2) that handle
> interrupts on the extra cores.  When masking off interrupts on MP1,
> these should be masked as well.
> 
> We add a new interrupt controller via device tree to identify when we're
> looking at an mmp3 machine via compatible field of "marvell,mmp3-intc".
> 
> [lkundrak@v3.sk: Changed "mrvl,mmp3-intc" compatible strings to
> "marvell,mmp3-intc". Tidied up the subject line a bit.]
> 
> Signed-off-by: Andres Salomon <dilinger@queued.net>
> Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
> 
> ---
>  arch/arm/mach-mmp/regs-icu.h |  3 +++
>  drivers/irqchip/irq-mmp.c    | 51 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 54 insertions(+)
> 
> diff --git a/arch/arm/mach-mmp/regs-icu.h b/arch/arm/mach-mmp/regs-icu.h
> index 0375d5a7fcb2b..410743d2b4020 100644
> --- a/arch/arm/mach-mmp/regs-icu.h
> +++ b/arch/arm/mach-mmp/regs-icu.h
> @@ -11,6 +11,9 @@
>  #define ICU_VIRT_BASE	(AXI_VIRT_BASE + 0x82000)
>  #define ICU_REG(x)	(ICU_VIRT_BASE + (x))
>  
> +#define ICU2_VIRT_BASE	(AXI_VIRT_BASE + 0x84000)
> +#define ICU2_REG(x)	(ICU2_VIRT_BASE + (x))
> +
>  #define ICU_INT_CONF(n)		ICU_REG((n) << 2)
>  #define ICU_INT_CONF_MASK	(0xf)
>  
> diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c
> index cd8d2253f56d1..25497c75cc861 100644
> --- a/drivers/irqchip/irq-mmp.c
> +++ b/drivers/irqchip/irq-mmp.c
> @@ -44,6 +44,7 @@ struct icu_chip_data {
>  	unsigned int		conf_enable;
>  	unsigned int		conf_disable;
>  	unsigned int		conf_mask;
> +	unsigned int		conf2_mask;
>  	unsigned int		clr_mfp_irq_base;
>  	unsigned int		clr_mfp_hwirq;
>  	struct irq_domain	*domain;
> @@ -53,9 +54,11 @@ struct mmp_intc_conf {
>  	unsigned int	conf_enable;
>  	unsigned int	conf_disable;
>  	unsigned int	conf_mask;
> +	unsigned int	conf2_mask;
>  };
>  
>  static void __iomem *mmp_icu_base;
> +static void __iomem *mmp_icu2_base;
>  static struct icu_chip_data icu_data[MAX_ICU_NR];
>  static int max_icu_nr;
>  
> @@ -98,6 +101,16 @@ static void icu_mask_irq(struct irq_data *d)
>  		r &= ~data->conf_mask;
>  		r |= data->conf_disable;
>  		writel_relaxed(r, mmp_icu_base + (hwirq << 2));
> +
> +		if (data->conf2_mask) {
> +			/*
> +			 * ICU1 (above) only controls PJ4 MP1; if using SMP,
> +			 * we need to also mask the MP2 and MM cores via ICU2.
> +			 */
> +			r = readl_relaxed(mmp_icu2_base + (hwirq << 2));
> +			r &= ~data->conf2_mask;
> +			writel_relaxed(r, mmp_icu2_base + (hwirq << 2));
> +		}
>  	} else {
>  		r = readl_relaxed(data->reg_mask) | (1 << hwirq);
>  		writel_relaxed(r, data->reg_mask);
> @@ -201,6 +214,14 @@ static const struct mmp_intc_conf mmp2_conf = {
>  			  MMP2_ICU_INT_ROUTE_PJ4_FIQ,
>  };
>  
> +static struct mmp_intc_conf mmp3_conf = {
> +	.conf_enable	= 0x20,
> +	.conf_disable	= 0x0,
> +	.conf_mask	= MMP2_ICU_INT_ROUTE_PJ4_IRQ |
> +			  MMP2_ICU_INT_ROUTE_PJ4_FIQ,
> +	.conf2_mask	= 0xf0,
> +};
> +
>  static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
>  {
>  	int hwirq;
> @@ -364,6 +385,14 @@ static int __init mmp_init_bases(struct device_node *node)
>  		pr_err("Failed to get interrupt controller register\n");
>  		return -ENOMEM;
>  	}
> +	if (of_device_is_compatible(node, "marvell,mmp3-intc")) {

Instead of harcoding the compatible property once more, why don't you
simply pass a flag from mmpx_of_init()?

> +		mmp_icu2_base = of_iomap(node, 1);
> +		if (!mmp_icu2_base) {
> +			pr_err("Failed to get interrupt controller register #2\n");
> +			iounmap(mmp_icu_base);
> +			return -ENOMEM;
> +		}
> +	}
>  
>  	icu_data[0].virq_base = 0;
>  	icu_data[0].domain = irq_domain_add_linear(node, nr_irqs,
> @@ -386,6 +415,8 @@ static int __init mmp_init_bases(struct device_node *node)
>  			irq_dispose_mapping(icu_data[0].virq_base + i);
>  	}
>  	irq_domain_remove(icu_data[0].domain);
> +	if (of_device_is_compatible(node, "marvell,mmp3-intc"))
> +		iounmap(mmp_icu2_base);
>  	iounmap(mmp_icu_base);
>  	return -EINVAL;
>  }
> @@ -428,6 +459,26 @@ static int __init mmp2_of_init(struct device_node *node,
>  }
>  IRQCHIP_DECLARE(mmp2_intc, "mrvl,mmp2-intc", mmp2_of_init);
>  
> +static int __init mmp3_of_init(struct device_node *node,
> +			       struct device_node *parent)
> +{
> +	int ret;
> +
> +	ret = mmp_init_bases(node);
> +	if (ret < 0)
> +		return ret;
> +
> +	icu_data[0].conf_enable = mmp3_conf.conf_enable;
> +	icu_data[0].conf_disable = mmp3_conf.conf_disable;
> +	icu_data[0].conf_mask = mmp3_conf.conf_mask;
> +	icu_data[0].conf2_mask = mmp3_conf.conf2_mask;
> +	irq_set_default_host(icu_data[0].domain);

Why do you need this? On a fully DT-ified platform, there should be no
notion of a default domain.

> +	set_handle_irq(mmp2_handle_irq);
> +	max_icu_nr = 1;
> +	return 0;
> +}
> +IRQCHIP_DECLARE(mmp3_intc, "marvell,mmp3-intc", mmp3_of_init);
> +
>  static int __init mmp2_mux_of_init(struct device_node *node,
>  				   struct device_node *parent)
>  {
> 

Thanks,

	M.
-- 
Jazz is not dead, it just smells funny...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH v3 3/3] interconnect: qcom: Add tagging and wake/sleep support for sdm845
From: Georgi Djakov @ 2019-08-09 12:13 UTC (permalink / raw)
  To: linux-pm, evgreen
  Cc: seansw, linux-kernel, daidavid1, dianders, amit.kucheria,
	bjorn.andersson, linux-arm-msm, georgi.djakov, linux-arm-kernel
In-Reply-To: <20190809121325.8138-1-georgi.djakov@linaro.org>

From: David Dai <daidavid1@codeaurora.org>

Add support for wake and sleep commands by using a tag to indicate
whether or not the aggregate and set requests fall into execution
state specific bucket.

Signed-off-by: David Dai <daidavid1@codeaurora.org>
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/interconnect/qcom/sdm845.c | 134 ++++++++++++++++++++++-------
 1 file changed, 103 insertions(+), 31 deletions(-)

diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
index fb526004c82e..b2047d1c6d84 100644
--- a/drivers/interconnect/qcom/sdm845.c
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -66,6 +66,17 @@ struct bcm_db {
 #define SDM845_MAX_BCM_PER_NODE	2
 #define SDM845_MAX_VCD		10
 
+#define QCOM_ICC_BUCKET_AMC		0
+#define QCOM_ICC_BUCKET_WAKE		1
+#define QCOM_ICC_BUCKET_SLEEP		2
+#define QCOM_ICC_NUM_BUCKETS		3
+#define QCOM_ICC_TAG_AMC		BIT(QCOM_ICC_BUCKET_AMC)
+#define QCOM_ICC_TAG_WAKE		BIT(QCOM_ICC_BUCKET_WAKE)
+#define QCOM_ICC_TAG_SLEEP		BIT(QCOM_ICC_BUCKET_SLEEP)
+#define QCOM_ICC_TAG_ACTIVE_ONLY	(QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE)
+#define QCOM_ICC_TAG_ALWAYS		(QCOM_ICC_TAG_AMC | QCOM_ICC_TAG_WAKE |\
+					 QCOM_ICC_TAG_SLEEP)
+
 /**
  * struct qcom_icc_node - Qualcomm specific interconnect nodes
  * @name: the node name used in debugfs
@@ -86,8 +97,8 @@ struct qcom_icc_node {
 	u16 num_links;
 	u16 channels;
 	u16 buswidth;
-	u64 sum_avg;
-	u64 max_peak;
+	u64 sum_avg[QCOM_ICC_NUM_BUCKETS];
+	u64 max_peak[QCOM_ICC_NUM_BUCKETS];
 	struct qcom_icc_bcm *bcms[SDM845_MAX_BCM_PER_NODE];
 	size_t num_bcms;
 };
@@ -112,8 +123,8 @@ struct qcom_icc_bcm {
 	const char *name;
 	u32 type;
 	u32 addr;
-	u64 vote_x;
-	u64 vote_y;
+	u64 vote_x[QCOM_ICC_NUM_BUCKETS];
+	u64 vote_y[QCOM_ICC_NUM_BUCKETS];
 	bool dirty;
 	bool keepalive;
 	struct bcm_db aux_data;
@@ -555,7 +566,7 @@ inline void tcs_cmd_gen(struct tcs_cmd *cmd, u64 vote_x, u64 vote_y,
 		cmd->wait = true;
 }
 
-static void tcs_list_gen(struct list_head *bcm_list,
+static void tcs_list_gen(struct list_head *bcm_list, int bucket,
 			 struct tcs_cmd tcs_list[SDM845_MAX_VCD],
 			 int n[SDM845_MAX_VCD])
 {
@@ -573,8 +584,8 @@ static void tcs_list_gen(struct list_head *bcm_list,
 			commit = true;
 			cur_vcd_size = 0;
 		}
-		tcs_cmd_gen(&tcs_list[idx], bcm->vote_x, bcm->vote_y,
-			    bcm->addr, commit);
+		tcs_cmd_gen(&tcs_list[idx], bcm->vote_x[bucket],
+			    bcm->vote_y[bucket], bcm->addr, commit);
 		idx++;
 		n[batch]++;
 		/*
@@ -595,51 +606,76 @@ static void tcs_list_gen(struct list_head *bcm_list,
 
 static void bcm_aggregate(struct qcom_icc_bcm *bcm)
 {
-	size_t i;
-	u64 agg_avg = 0;
-	u64 agg_peak = 0;
+	size_t i, bucket;
+	u64 agg_avg[QCOM_ICC_NUM_BUCKETS] = {0};
+	u64 agg_peak[QCOM_ICC_NUM_BUCKETS] = {0};
 	u64 temp;
 
-	for (i = 0; i < bcm->num_nodes; i++) {
-		temp = bcm->nodes[i]->sum_avg * bcm->aux_data.width;
-		do_div(temp, bcm->nodes[i]->buswidth * bcm->nodes[i]->channels);
-		agg_avg = max(agg_avg, temp);
+	for (bucket = 0; bucket < QCOM_ICC_NUM_BUCKETS; bucket++) {
+		for (i = 0; i < bcm->num_nodes; i++) {
+			temp = bcm->nodes[i]->sum_avg[bucket] * bcm->aux_data.width;
+			do_div(temp, bcm->nodes[i]->buswidth * bcm->nodes[i]->channels);
+			agg_avg[bucket] = max(agg_avg[bucket], temp);
 
-		temp = bcm->nodes[i]->max_peak * bcm->aux_data.width;
-		do_div(temp, bcm->nodes[i]->buswidth);
-		agg_peak = max(agg_peak, temp);
-	}
+			temp = bcm->nodes[i]->max_peak[bucket] * bcm->aux_data.width;
+			do_div(temp, bcm->nodes[i]->buswidth);
+			agg_peak[bucket] = max(agg_peak[bucket], temp);
+		}
 
-	temp = agg_avg * 1000ULL;
-	do_div(temp, bcm->aux_data.unit);
-	bcm->vote_x = temp;
+		temp = agg_avg[bucket] * 1000ULL;
+		do_div(temp, bcm->aux_data.unit);
+		bcm->vote_x[bucket] = temp;
 
-	temp = agg_peak * 1000ULL;
-	do_div(temp, bcm->aux_data.unit);
-	bcm->vote_y = temp;
+		temp = agg_peak[bucket] * 1000ULL;
+		do_div(temp, bcm->aux_data.unit);
+		bcm->vote_y[bucket] = temp;
+	}
 
-	if (bcm->keepalive && bcm->vote_x == 0 && bcm->vote_y == 0) {
-		bcm->vote_x = 1;
-		bcm->vote_y = 1;
+	if (bcm->keepalive && bcm->vote_x[0] == 0 && bcm->vote_y[0] == 0) {
+		bcm->vote_x[QCOM_ICC_BUCKET_AMC] = 1;
+		bcm->vote_x[QCOM_ICC_BUCKET_WAKE] = 1;
+		bcm->vote_y[QCOM_ICC_BUCKET_AMC] = 1;
+		bcm->vote_y[QCOM_ICC_BUCKET_WAKE] = 1;
 	}
 
 	bcm->dirty = false;
 }
 
+static void qcom_icc_pre_aggregate(struct icc_node *node)
+{
+	size_t i;
+	struct qcom_icc_node *qn;
+
+	qn = node->data;
+
+	for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
+		qn->sum_avg[i] = 0;
+		qn->max_peak[i] = 0;
+	}
+}
+
 static int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
 			      u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
 {
 	size_t i;
 	struct qcom_icc_node *qn;
+	unsigned long tag_word = (unsigned long)tag;
 
 	qn = node->data;
 
+	if (!tag)
+		tag_word = QCOM_ICC_TAG_ALWAYS;
+
+	for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) {
+		if (test_bit(i, &tag_word)) {
+			qn->sum_avg[i] += avg_bw;
+			qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw);
+		}
+	}
+
 	*agg_avg += avg_bw;
 	*agg_peak = max_t(u32, *agg_peak, peak_bw);
 
-	qn->sum_avg = *agg_avg;
-	qn->max_peak = *agg_peak;
-
 	for (i = 0; i < qn->num_bcms; i++)
 		qn->bcms[i]->dirty = true;
 
@@ -675,7 +711,7 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
 	 * Construct the command list based on a pre ordered list of BCMs
 	 * based on VCD.
 	 */
-	tcs_list_gen(&commit_list, cmds, commit_idx);
+	tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_AMC, cmds, commit_idx);
 
 	if (!commit_idx[0])
 		return ret;
@@ -693,6 +729,41 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
 		return ret;
 	}
 
+	INIT_LIST_HEAD(&commit_list);
+
+	for (i = 0; i < qp->num_bcms; i++) {
+		/*
+		 * Only generate WAKE and SLEEP commands if a resource's
+		 * requirements change as the execution environment transitions
+		 * between different power states.
+		 */
+		if (qp->bcms[i]->vote_x[QCOM_ICC_BUCKET_WAKE] !=
+		    qp->bcms[i]->vote_x[QCOM_ICC_BUCKET_SLEEP] ||
+		    qp->bcms[i]->vote_y[QCOM_ICC_BUCKET_WAKE] !=
+		    qp->bcms[i]->vote_y[QCOM_ICC_BUCKET_SLEEP]) {
+			list_add_tail(&qp->bcms[i]->list, &commit_list);
+		}
+	}
+
+	if (list_empty(&commit_list))
+		return ret;
+
+	tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_WAKE, cmds, commit_idx);
+
+	ret = rpmh_write_batch(qp->dev, RPMH_WAKE_ONLY_STATE, cmds, commit_idx);
+	if (ret) {
+		pr_err("Error sending WAKE RPMH requests (%d)\n", ret);
+		return ret;
+	}
+
+	tcs_list_gen(&commit_list, QCOM_ICC_BUCKET_SLEEP, cmds, commit_idx);
+
+	ret = rpmh_write_batch(qp->dev, RPMH_SLEEP_STATE, cmds, commit_idx);
+	if (ret) {
+		pr_err("Error sending SLEEP RPMH requests (%d)\n", ret);
+		return ret;
+	}
+
 	return ret;
 }
 
@@ -738,6 +809,7 @@ static int qnoc_probe(struct platform_device *pdev)
 	provider = &qp->provider;
 	provider->dev = &pdev->dev;
 	provider->set = qcom_icc_set;
+	provider->pre_aggregate = qcom_icc_pre_aggregate;
 	provider->aggregate = qcom_icc_aggregate;
 	provider->xlate = of_icc_xlate_onecell;
 	INIT_LIST_HEAD(&provider->nodes);

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v3 2/3] interconnect: Add pre_aggregate() callback
From: Georgi Djakov @ 2019-08-09 12:13 UTC (permalink / raw)
  To: linux-pm, evgreen
  Cc: seansw, linux-kernel, daidavid1, dianders, amit.kucheria,
	bjorn.andersson, linux-arm-msm, georgi.djakov, linux-arm-kernel
In-Reply-To: <20190809121325.8138-1-georgi.djakov@linaro.org>

Introduce an optional callback in interconnect provider drivers. It can be
used for implementing actions, that need to be executed before the actual
aggregation of the bandwidth requests has started.

The benefit of this for now is that it will significantly simplify the code
in provider drivers.

Suggested-by: Evan Green <evgreen@chromium.org>
Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/interconnect/core.c           | 3 +++
 include/linux/interconnect-provider.h | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 251354bb7fdc..7b971228df38 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -205,6 +205,9 @@ static int aggregate_requests(struct icc_node *node)
 	node->avg_bw = 0;
 	node->peak_bw = 0;
 
+	if (p->pre_aggregate)
+		p->pre_aggregate(node);
+
 	hlist_for_each_entry(r, &node->req_list, req_node)
 		p->aggregate(node, r->tag, r->avg_bw, r->peak_bw,
 			     &node->avg_bw, &node->peak_bw);
diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h
index 4ee19fd41568..b16f9effa555 100644
--- a/include/linux/interconnect-provider.h
+++ b/include/linux/interconnect-provider.h
@@ -36,6 +36,8 @@ struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec,
  * @nodes: internal list of the interconnect provider nodes
  * @set: pointer to device specific set operation function
  * @aggregate: pointer to device specific aggregate operation function
+ * @pre_aggregate: pointer to device specific function that is called
+ *		   before the aggregation begins (optional)
  * @xlate: provider-specific callback for mapping nodes from phandle arguments
  * @dev: the device this interconnect provider belongs to
  * @users: count of active users
@@ -47,6 +49,7 @@ struct icc_provider {
 	int (*set)(struct icc_node *src, struct icc_node *dst);
 	int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw,
 			 u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
+	void (*pre_aggregate)(struct icc_node *node);
 	struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data);
 	struct device		*dev;
 	int			users;

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v3 1/3] interconnect: Add support for path tags
From: Georgi Djakov @ 2019-08-09 12:13 UTC (permalink / raw)
  To: linux-pm, evgreen
  Cc: seansw, linux-kernel, daidavid1, dianders, amit.kucheria,
	bjorn.andersson, linux-arm-msm, georgi.djakov, linux-arm-kernel
In-Reply-To: <20190809121325.8138-1-georgi.djakov@linaro.org>

Consumers may have use cases with different bandwidth requirements based
on the system or driver state. The consumer driver can append a specific
tag to the path and pass this information to the interconnect platform
driver to do the aggregation based on this state.

Introduce icc_set_tag() function that will allow the consumers to append
an optional tag to each path. The aggregation of these tagged paths is
platform specific.

Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org>
---
 drivers/interconnect/core.c           | 24 +++++++++++++++++++++++-
 drivers/interconnect/qcom/sdm845.c    |  2 +-
 include/linux/interconnect-provider.h |  4 ++--
 include/linux/interconnect.h          |  5 +++++
 4 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 871eb4bc4efc..251354bb7fdc 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -29,6 +29,7 @@ static struct dentry *icc_debugfs_dir;
  * @req_node: entry in list of requests for the particular @node
  * @node: the interconnect node to which this constraint applies
  * @dev: reference to the device that sets the constraints
+ * @tag: path tag (optional)
  * @avg_bw: an integer describing the average bandwidth in kBps
  * @peak_bw: an integer describing the peak bandwidth in kBps
  */
@@ -36,6 +37,7 @@ struct icc_req {
 	struct hlist_node req_node;
 	struct icc_node *node;
 	struct device *dev;
+	u32 tag;
 	u32 avg_bw;
 	u32 peak_bw;
 };
@@ -204,7 +206,7 @@ static int aggregate_requests(struct icc_node *node)
 	node->peak_bw = 0;
 
 	hlist_for_each_entry(r, &node->req_list, req_node)
-		p->aggregate(node, r->avg_bw, r->peak_bw,
+		p->aggregate(node, r->tag, r->avg_bw, r->peak_bw,
 			     &node->avg_bw, &node->peak_bw);
 
 	return 0;
@@ -385,6 +387,26 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
 }
 EXPORT_SYMBOL_GPL(of_icc_get);
 
+/**
+ * icc_set_tag() - set an optional tag on a path
+ * @path: the path we want to tag
+ * @tag: the tag value
+ *
+ * This function allows consumers to append a tag to the requests associated
+ * with a path, so that a different aggregation could be done based on this tag.
+ */
+void icc_set_tag(struct icc_path *path, u32 tag)
+{
+	int i;
+
+	if (!path)
+		return;
+
+	for (i = 0; i < path->num_nodes; i++)
+		path->reqs[i].tag = tag;
+}
+EXPORT_SYMBOL_GPL(icc_set_tag);
+
 /**
  * icc_set_bw() - set bandwidth constraints on an interconnect path
  * @path: reference to the path returned by icc_get()
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
index 4915b78da673..fb526004c82e 100644
--- a/drivers/interconnect/qcom/sdm845.c
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -626,7 +626,7 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm)
 	bcm->dirty = false;
 }
 
-static int qcom_icc_aggregate(struct icc_node *node, u32 avg_bw,
+static int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
 			      u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
 {
 	size_t i;
diff --git a/include/linux/interconnect-provider.h b/include/linux/interconnect-provider.h
index 63caccadc2db..4ee19fd41568 100644
--- a/include/linux/interconnect-provider.h
+++ b/include/linux/interconnect-provider.h
@@ -45,8 +45,8 @@ struct icc_provider {
 	struct list_head	provider_list;
 	struct list_head	nodes;
 	int (*set)(struct icc_node *src, struct icc_node *dst);
-	int (*aggregate)(struct icc_node *node, u32 avg_bw, u32 peak_bw,
-			 u32 *agg_avg, u32 *agg_peak);
+	int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw,
+			 u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
 	struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data);
 	struct device		*dev;
 	int			users;
diff --git a/include/linux/interconnect.h b/include/linux/interconnect.h
index dc25864755ba..d70a914cba11 100644
--- a/include/linux/interconnect.h
+++ b/include/linux/interconnect.h
@@ -30,6 +30,7 @@ struct icc_path *icc_get(struct device *dev, const int src_id,
 struct icc_path *of_icc_get(struct device *dev, const char *name);
 void icc_put(struct icc_path *path);
 int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw);
+void icc_set_tag(struct icc_path *path, u32 tag);
 
 #else
 
@@ -54,6 +55,10 @@ static inline int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
 	return 0;
 }
 
+static inline void icc_set_tag(struct icc_path *path, u32 tag)
+{
+}
+
 #endif /* CONFIG_INTERCONNECT */
 
 #endif /* __LINUX_INTERCONNECT_H */

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v3 0/3] interconnect: Add path tagging support
From: Georgi Djakov @ 2019-08-09 12:13 UTC (permalink / raw)
  To: linux-pm, evgreen
  Cc: seansw, linux-kernel, daidavid1, dianders, amit.kucheria,
	bjorn.andersson, linux-arm-msm, georgi.djakov, linux-arm-kernel

SoCs that have multiple coexisting CPUs and DSPs, may have shared
interconnect buses between them. In such cases, each CPU/DSP may have
different bandwidth needs, depending on whether it is active or sleeping.
This means that we have to keep different bandwidth configurations for
the CPU (active/sleep). In such systems, usually there is a way to
communicate and synchronize this information with some firmware or pass
it to another processor responsible for monitoring and switching the
interconnect configurations based on the state of each CPU/DSP.

The above problem can be solved by introducing the path tagging concept,
that allows consumers to optionally attach a tag to each path they use.
This tag is used to differentiate between the aggregated bandwidth values
for each state. The tag is generic and how it's handled is up to the
platform specific interconnect provider drivers.

v3:
- New patch to add a pre_aggregate() callback.

v2: https://lore.kernel.org/lkml/20190618091724.28232-1-georgi.djakov@linaro.org/
- Store tag with the request. (Evan)
- Reorganize the code to save bandwidth values into buckets and use the
  tag as a bitfield. (Evan)
- Clear the aggregated values after icc_set().

v1: https://lore.kernel.org/lkml/20190208172152.1807-1-georgi.djakov@linaro.org/


David Dai (1):
  interconnect: qcom: Add tagging and wake/sleep support for sdm845

Georgi Djakov (2):
  interconnect: Add support for path tags
  interconnect: Add pre_aggregate() callback

 drivers/interconnect/core.c           |  27 ++++-
 drivers/interconnect/qcom/sdm845.c    | 136 ++++++++++++++++++++------
 include/linux/interconnect-provider.h |   7 +-
 include/linux/interconnect.h          |   5 +
 4 files changed, 140 insertions(+), 35 deletions(-)


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 05/19] irqchip/mmp: do not use of_address_to_resource() to get mux regs
From: Marc Zyngier @ 2019-08-09 12:12 UTC (permalink / raw)
  To: Lubomir Rintel, Olof Johansson
  Cc: Mark Rutland, devicetree, Jason Cooper, Stephen Boyd,
	linux-kernel, Michael Turquette, Russell King,
	Kishon Vijay Abraham I, Rob Herring, Pavel Machek,
	Thomas Gleixner, linux-clk, linux-arm-kernel
In-Reply-To: <20190809093158.7969-6-lkundrak@v3.sk>

On 09/08/2019 10:31, Lubomir Rintel wrote:
> The "regs" property of the "mrvl,mmp2-mux-intc" devices are silly. They
> are offsets from intc's base, not addresses on the parent bus. At this
> point it probably can't be fixed.
> 
> On an OLPC XO-1.75 machine, the muxes are children of the intc, not the
> axi bus, and thus of_address_to_resource() won't work. We should treat
> the values as mere integers as opposed to bus addresses.
> 
> Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
> Acked-by: Pavel Machek <pavel@ucw.cz>
> 
> ---
>  drivers/irqchip/irq-mmp.c | 20 +++++++++++---------
>  1 file changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c
> index 14618dc0bd396..af9cba4a51c2e 100644
> --- a/drivers/irqchip/irq-mmp.c
> +++ b/drivers/irqchip/irq-mmp.c
> @@ -424,9 +424,9 @@ IRQCHIP_DECLARE(mmp2_intc, "mrvl,mmp2-intc", mmp2_of_init);
>  static int __init mmp2_mux_of_init(struct device_node *node,
>  				   struct device_node *parent)
>  {
> -	struct resource res;
>  	int i, ret, irq, j = 0;
>  	u32 nr_irqs, mfp_irq;
> +	u32 reg[4];
>  
>  	if (!parent)
>  		return -ENODEV;
> @@ -438,18 +438,20 @@ static int __init mmp2_mux_of_init(struct device_node *node,
>  		pr_err("Not found mrvl,intc-nr-irqs property\n");
>  		return -EINVAL;
>  	}
> -	ret = of_address_to_resource(node, 0, &res);
> +
> +	/*
> +	 * For historical reasonsm, the "regs" property of the
> +	 * mrvl,mmp2-mux-intc is not a regular * "regs" property containing
> +	 * addresses on the parent bus, but offsets from the intc's base.
> +	 * That is why we can't use of_address_to_resource() here.
> +	 */
> +	ret = of_property_read_u32_array(node, "reg", reg, ARRAY_SIZE(reg));

This will return 0 even if you've read less than your expected 4 u32s.
You may want to try of_property_read_variable_u32_array instead.

>  	if (ret < 0) {
>  		pr_err("Not found reg property\n");
>  		return -EINVAL;
>  	}
> -	icu_data[i].reg_status = mmp_icu_base + res.start;
> -	ret = of_address_to_resource(node, 1, &res);
> -	if (ret < 0) {
> -		pr_err("Not found reg property\n");
> -		return -EINVAL;
> -	}
> -	icu_data[i].reg_mask = mmp_icu_base + res.start;
> +	icu_data[i].reg_status = mmp_icu_base + reg[0];
> +	icu_data[i].reg_mask = mmp_icu_base + reg[2];
>  	icu_data[i].cascade_irq = irq_of_parse_and_map(node, 0);
>  	if (!icu_data[i].cascade_irq)
>  		return -EINVAL;
> 

Thanks,

	M.
-- 
Jazz is not dead, it just smells funny...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v8 09/14] media: rkisp1: add rockchip isp1 core driver
From: Sakari Ailus @ 2019-08-09 12:05 UTC (permalink / raw)
  To: Helen Koike
  Cc: devicetree, eddie.cai.linux, kernel, heiko, jacob2.chen,
	jeffy.chen, zyc, linux-kernel, tfiga, linux-rockchip, Allon Huang,
	Jacob Chen, hans.verkuil, laurent.pinchart, zhengsq, mchehab,
	ezequiel, linux-arm-kernel, linux-media
In-Reply-To: <bca5e3fe-8a37-2b91-ae96-30378fd98012@collabora.com>

Hi Helen,

On Thu, Aug 08, 2019 at 06:59:47PM -0300, Helen Koike wrote:
> Hi Sakari,
> 
> Thanks for your review, just some comments/questions below:
> 
> On 8/7/19 12:27 PM, Sakari Ailus wrote:
> > Hi Helen,
> > 
> > On Tue, Jul 30, 2019 at 03:42:51PM -0300, Helen Koike wrote:
> >> From: Jacob Chen <jacob2.chen@rock-chips.com>
> >>
> >> Add the core driver for rockchip isp1.
> >>
> >> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
> >> Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
> >> Signed-off-by: Yichong Zhong <zyc@rock-chips.com>
> >> Signed-off-by: Jacob Chen <cc@rock-chips.com>
> >> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> >> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
> >> Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
> >> Signed-off-by: Tomasz Figa <tfiga@chromium.org>
> >> [fixed compilation and run time errors regarding new v4l2 async API]
> >> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >> [Add missing module device table]
> >> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> >> [update for upstream]
> >> Signed-off-by: Helen Koike <helen.koike@collabora.com>
> >>
> >> ---
> >>
> >> Changes in v8: None
> >> Changes in v7:
> >> - VIDEO_ROCKCHIP_ISP1 selects VIDEOBUF2_VMALLOC
> >> - add PHY_ROCKCHIP_DPHY as a dependency for VIDEO_ROCKCHIP_ISP1
> >> - Fix compilation and runtime errors due to bitrotting
> >> The code has bit-rotten since March 2018, fix compilation errors.
> >> The new V4L2 async notifier API requires notifiers to be initialized by
> >> a call to v4l2_async_notifier_init() before being used, do so.
> >> - Add missing module device table
> >> - use clk_bulk framework
> >> - add missing notifiers cleanups
> >> - s/strlcpy/strscpy
> >> - normalize bus_info name
> >> - fix s_stream error path, stream_cnt wans't being decremented properly
> >> - use devm_platform_ioremap_resource() helper
> >> - s/deice/device
> >> - redesign: remove mipi/csi subdevice, sensors connect directly to the
> >> isp subdevice in the media topology now.
> >> - remove "saved_state" member from rkisp1_stream struct
> >> - Reverse the order of MIs
> >> - Simplify MI interrupt handling
> >> Rather than adding unnecessary indirection, just use stream index to
> >> handle MI interrupt enable/disable/clear, since the stream index matches
> >> the order of bits now, thanks to previous patch. While at it, remove
> >> some dead code.
> >> - code styling and checkpatch fixes
> >>
> >>  drivers/media/platform/Kconfig                |  12 +
> >>  drivers/media/platform/Makefile               |   1 +
> >>  drivers/media/platform/rockchip/isp1/Makefile |   7 +
> >>  drivers/media/platform/rockchip/isp1/common.h | 101 +++
> >>  drivers/media/platform/rockchip/isp1/dev.c    | 675 ++++++++++++++++++
> >>  drivers/media/platform/rockchip/isp1/dev.h    |  97 +++
> >>  6 files changed, 893 insertions(+)
> >>  create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
> >>  create mode 100644 drivers/media/platform/rockchip/isp1/common.h
> >>  create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
> >>  create mode 100644 drivers/media/platform/rockchip/isp1/dev.h
> >>
> >> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> >> index 89555f9a813f..e0e98937c565 100644
> >> --- a/drivers/media/platform/Kconfig
> >> +++ b/drivers/media/platform/Kconfig
> >> @@ -106,6 +106,18 @@ config VIDEO_QCOM_CAMSS
> >>  	select VIDEOBUF2_DMA_SG
> >>  	select V4L2_FWNODE
> >>  
> >> +config VIDEO_ROCKCHIP_ISP1
> >> +	tristate "Rockchip Image Signal Processing v1 Unit driver"
> >> +	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
> >> +	depends on ARCH_ROCKCHIP || COMPILE_TEST
> >> +	select VIDEOBUF2_DMA_CONTIG
> >> +	select VIDEOBUF2_VMALLOC
> >> +	select V4L2_FWNODE
> >> +	select PHY_ROCKCHIP_DPHY
> >> +	default n
> >> +	---help---
> >> +	  Support for ISP1 on the rockchip SoC.
> >> +
> >>  config VIDEO_S3C_CAMIF
> >>  	tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
> >>  	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
> >> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> >> index 7cbbd925124c..f9fcf8e7c513 100644
> >> --- a/drivers/media/platform/Makefile
> >> +++ b/drivers/media/platform/Makefile
> >> @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1)	+= rcar_fdp1.o
> >>  obj-$(CONFIG_VIDEO_RENESAS_JPU)		+= rcar_jpu.o
> >>  obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1/
> >>  
> >> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1)	+= rockchip/isp1/
> >>  obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)	+= rockchip/rga/
> >>  
> >>  obj-y	+= omap/
> >> diff --git a/drivers/media/platform/rockchip/isp1/Makefile b/drivers/media/platform/rockchip/isp1/Makefile
> >> new file mode 100644
> >> index 000000000000..72706e80fc8b
> >> --- /dev/null
> >> +++ b/drivers/media/platform/rockchip/isp1/Makefile
> >> @@ -0,0 +1,7 @@
> >> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += 	rockchip-isp1.o
> >> +rockchip-isp1-objs 	   += 	rkisp1.o \
> >> +				dev.o \
> >> +				regs.o \
> >> +				isp_stats.o \
> >> +				isp_params.o \
> >> +				capture.o
> >> diff --git a/drivers/media/platform/rockchip/isp1/common.h b/drivers/media/platform/rockchip/isp1/common.h
> >> new file mode 100644
> >> index 000000000000..606ce2793546
> >> --- /dev/null
> >> +++ b/drivers/media/platform/rockchip/isp1/common.h
> >> @@ -0,0 +1,101 @@
> >> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> >> +/*
> >> + * Rockchip isp1 driver
> >> + *
> >> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> >> + */
> >> +
> >> +#ifndef _RKISP1_COMMON_H
> >> +#define _RKISP1_COMMON_H
> >> +
> >> +#include <linux/mutex.h>
> >> +#include <media/media-device.h>
> >> +#include <media/media-entity.h>
> >> +#include <media/v4l2-ctrls.h>
> >> +#include <media/v4l2-device.h>
> >> +#include <media/videobuf2-v4l2.h>
> >> +
> >> +#define RKISP1_DEFAULT_WIDTH		800
> >> +#define RKISP1_DEFAULT_HEIGHT		600
> >> +
> >> +#define RKISP1_MAX_STREAM		2
> >> +#define RKISP1_STREAM_MP		0
> >> +#define RKISP1_STREAM_SP		1
> >> +
> >> +#define RKISP1_PLANE_Y			0
> >> +#define RKISP1_PLANE_CB			1
> >> +#define RKISP1_PLANE_CR			2
> >> +
> >> +enum rkisp1_sd_type {
> >> +	RKISP1_SD_SENSOR,
> >> +	RKISP1_SD_PHY_CSI,
> >> +	RKISP1_SD_VCM,
> >> +	RKISP1_SD_FLASH,
> >> +	RKISP1_SD_MAX,
> >> +};
> > 
> > I wonder if this is a leftover from the driver development time. Same goes
> > for the subdevs field in struct rkisp1_device.
> 
> It is a left over, I'm removing them for the next version, thanks.
> 
> > 
> >> +
> >> +/* One structure per video node */
> >> +struct rkisp1_vdev_node {
> >> +	struct vb2_queue buf_queue;
> >> +	/* vfd lock */
> >> +	struct mutex vlock;
> >> +	struct video_device vdev;
> >> +	struct media_pad pad;
> >> +};
> >> +
> >> +enum rkisp1_fmt_pix_type {
> >> +	FMT_YUV,
> >> +	FMT_RGB,
> >> +	FMT_BAYER,
> >> +	FMT_JPEG,
> >> +	FMT_MAX
> >> +};
> >> +
> >> +enum rkisp1_fmt_raw_pat_type {
> >> +	RAW_RGGB = 0,
> >> +	RAW_GRBG,
> >> +	RAW_GBRG,
> >> +	RAW_BGGR,
> >> +};
> >> +
> >> +struct rkisp1_buffer {
> >> +	struct vb2_v4l2_buffer vb;
> >> +	struct list_head queue;
> >> +	union {
> >> +		u32 buff_addr[VIDEO_MAX_PLANES];
> >> +		void *vaddr[VIDEO_MAX_PLANES];
> >> +	};
> >> +};
> >> +
> >> +struct rkisp1_dummy_buffer {
> >> +	void *vaddr;
> >> +	dma_addr_t dma_addr;
> >> +	u32 size;
> >> +};
> >> +
> >> +extern int rkisp1_debug;
> >> +
> >> +static inline
> >> +struct rkisp1_vdev_node *vdev_to_node(struct video_device *vdev)
> >> +{
> >> +	return container_of(vdev, struct rkisp1_vdev_node, vdev);
> >> +}
> >> +
> >> +static inline struct rkisp1_vdev_node *queue_to_node(struct vb2_queue *q)
> >> +{
> >> +	return container_of(q, struct rkisp1_vdev_node, buf_queue);
> >> +}
> >> +
> >> +static inline struct rkisp1_buffer *to_rkisp1_buffer(struct vb2_v4l2_buffer *vb)
> >> +{
> >> +	return container_of(vb, struct rkisp1_buffer, vb);
> >> +}
> >> +
> >> +static inline struct vb2_queue *to_vb2_queue(struct file *file)
> >> +{
> >> +	struct rkisp1_vdev_node *vnode = video_drvdata(file);
> >> +
> >> +	return &vnode->buf_queue;
> >> +}
> >> +
> >> +#endif /* _RKISP1_COMMON_H */
> >> diff --git a/drivers/media/platform/rockchip/isp1/dev.c b/drivers/media/platform/rockchip/isp1/dev.c
> >> new file mode 100644
> >> index 000000000000..2b4a67e1a3b5
> >> --- /dev/null
> >> +++ b/drivers/media/platform/rockchip/isp1/dev.c
> >> @@ -0,0 +1,675 @@
> >> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> >> +/*
> >> + * Rockchip isp1 driver
> >> + *
> >> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> >> + */
> >> +
> >> +#include <linux/clk.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/module.h>
> >> +#include <linux/of.h>
> >> +#include <linux/of_graph.h>
> >> +#include <linux/of_platform.h>
> >> +#include <linux/pm_runtime.h>
> >> +#include <linux/pinctrl/consumer.h>
> >> +#include <linux/phy/phy.h>
> >> +#include <linux/phy/phy-mipi-dphy.h>
> >> +
> >> +#include "common.h"
> >> +#include "regs.h"
> >> +
> >> +struct isp_match_data {
> >> +	const char * const *clks;
> >> +	int size;
> > 
> > unsigned int
> 
> ack
> 
> > 
> >> +};
> >> +
> >> +struct sensor_async_subdev {
> >> +	struct v4l2_async_subdev asd;
> >> +	struct v4l2_mbus_config mbus;
> >> +	unsigned int lanes;
> >> +};
> >> +
> >> +int rkisp1_debug;
> >> +module_param_named(debug, rkisp1_debug, int, 0644);
> >> +MODULE_PARM_DESC(debug, "Debug level (0-1)");
> > 
> > Have you thought of using dynamic debug instead?
> 
> right, this is being used in v4l2_dbg(), which I can replace by dev_dbg()
> that is already covered by dynamic debug iirc.
> Should I also replace v4l2_err() by dev_err() (I always get confused by
> which log function I should use).

In case you switch to the dev_*() macros, then yes. The corresponding
v4l2_*() macros are still an entirely valid interface to use. But today we
likely wouldn't add such macros; I usually ask driver developers using both
to switch to the dev_*() ones.

> 
> > 
> >> +
> >> +/**************************** pipeline operations******************************/
> >> +
> >> +static int __isp_pipeline_prepare(struct rkisp1_pipeline *p,
> >> +				  struct media_entity *me)
> >> +{
> >> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> >> +	struct v4l2_subdev *sd;
> >> +	unsigned int i;
> >> +
> >> +	p->num_subdevs = 0;
> >> +	memset(p->subdevs, 0, sizeof(p->subdevs));
> >> +
> >> +	while (1) {
> >> +		struct media_pad *pad = NULL;
> >> +
> >> +		/* Find remote source pad */
> >> +		for (i = 0; i < me->num_pads; i++) {
> >> +			struct media_pad *spad = &me->pads[i];
> >> +
> >> +			if (!(spad->flags & MEDIA_PAD_FL_SINK))
> >> +				continue;
> >> +			pad = media_entity_remote_pad(spad);
> >> +			if (pad)
> >> +				break;
> >> +		}
> >> +
> >> +		if (!pad)
> >> +			break;
> >> +
> >> +		sd = media_entity_to_v4l2_subdev(pad->entity);
> >> +		if (sd != &dev->isp_sdev.sd)
> >> +			p->subdevs[p->num_subdevs++] = sd;
> > 
> > How do you make sure you don't overrun the array?
> 
> Because the maximum path the topology can have is:
> sensor->rkisp->capture

The sensor may consist of more than one sub-device, and there may be
bridges such as parallel/CSI-2 ones in between. The latter would be an
unlikely hardware configuration for this ISP though as it supports both.

External ISPs in front of the camera sensor are another possibility.

Basically you can't make expectations of the topology outside the scope of
your own device --- the topology of which is known.

> 
> > 
> > Instead, I'd avoid maintaining the array in the first place --- the same
> > information is available from the MC framework data structures --- see e.g.
> > the omap3isp driver.
> 
> If I understand correctly, omap3isp navigates through the topology in the same way,
> but it just don't save in an array, but I reuse this information in other places,
> mostly for power up/down (see below why I don't use v4l2_pipeline_pm_use())

Correct.

> 
> > 
> >> +
> >> +		me = &sd->entity;
> >> +		if (me->num_pads == 1)
> >> +			break;
> >> +	}
> >> +	return 0;
> >> +}
> >> +
> >> +static int __subdev_set_power(struct v4l2_subdev *sd, int on)
> >> +{
> >> +	int ret;
> >> +
> >> +	if (!sd)
> >> +		return -ENXIO;
> >> +
> >> +	ret = v4l2_subdev_call(sd, core, s_power, on);
> >> +
> >> +	return ret != -ENOIOCTLCMD ? ret : 0;
> >> +}
> >> +
> >> +static int __isp_pipeline_s_power(struct rkisp1_pipeline *p, bool on)
> > 
> > Could you instead use v4l2_pipeline_pm_use()?
> 
> Unless I misunderstood this (which is very likely), v4l2_pipeline_pm_use() calls pipeline_pm_power(),
> that applies power change to all entities in a pipeline, but if I have two sensors
> connected to the ISP, one with link enabled and the other with a disabled link,
> I don't want to power both sensors on, just the one participating in that stream. And
> if I call v4l2_pipeline_pm_use() it will power on both, which is not what I want.
> 
> Does it make sense?

The v4l2_pipeline_pm_use() only follows the active links. A simplistic
implementation could power on all the subdevs in the graph but no; the
v4l2_pipeline_pm_use() exists for this very purpose.

> 
> > 
> >> +{
> >> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> >> +	int i, ret;
> >> +
> >> +	if (on) {
> >> +		__subdev_set_power(&dev->isp_sdev.sd, true);
> >> +
> >> +		for (i = p->num_subdevs - 1; i >= 0; --i) {
> >> +			ret = __subdev_set_power(p->subdevs[i], true);
> >> +			if (ret < 0 && ret != -ENXIO)
> >> +				goto err_power_off;
> >> +		}
> >> +	} else {
> >> +		for (i = 0; i < p->num_subdevs; ++i)
> >> +			__subdev_set_power(p->subdevs[i], false);
> >> +
> >> +		__subdev_set_power(&dev->isp_sdev.sd, false);
> >> +	}
> >> +
> >> +	return 0;
> >> +
> >> +err_power_off:
> >> +	for (++i; i < p->num_subdevs; ++i)
> >> +		__subdev_set_power(p->subdevs[i], false);
> >> +	__subdev_set_power(&dev->isp_sdev.sd, true);
> >> +	return ret;
> >> +}
> >> +
> >> +static int rkisp1_pipeline_open(struct rkisp1_pipeline *p,
> >> +				struct media_entity *me,
> >> +				bool prepare)
> >> +{
> >> +	int ret;
> >> +
> >> +	if (WARN_ON(!p || !me))
> >> +		return -EINVAL;
> >> +	if (atomic_inc_return(&p->power_cnt) > 1)
> >> +		return 0;
> >> +
> >> +	/* go through media graphic and get subdevs */
> >> +	if (prepare)
> >> +		__isp_pipeline_prepare(p, me);
> >> +
> >> +	if (!p->num_subdevs)
> >> +		return -EINVAL;
> >> +
> >> +	ret = __isp_pipeline_s_power(p, 1);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int rkisp1_pipeline_close(struct rkisp1_pipeline *p)
> >> +{
> >> +	int ret;
> >> +
> >> +	if (atomic_dec_return(&p->power_cnt) > 0)
> >> +		return 0;
> >> +	ret = __isp_pipeline_s_power(p, 0);
> >> +
> >> +	return ret == -ENXIO ? 0 : ret;
> >> +}
> >> +
> >> +/*
> >> + * stream-on order: isp_subdev, mipi dphy, sensor
> >> + * stream-off order: mipi dphy, sensor, isp_subdev
> >> + */
> >> +static int rkisp1_pipeline_set_stream(struct rkisp1_pipeline *p, bool on)
> >> +{
> >> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> >> +	int i, ret;
> >> +
> >> +	if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
> >> +	    (!on && atomic_dec_return(&p->stream_cnt) > 0))
> >> +		return 0;
> >> +
> >> +	if (on) {
> >> +		ret = v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream,
> >> +				       true);
> >> +		if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
> >> +			v4l2_err(&dev->v4l2_dev,
> >> +				 "s_stream failed on subdevice %s (%d)\n",
> >> +				 dev->isp_sdev.sd.name,
> >> +				 ret);
> >> +			atomic_dec(&p->stream_cnt);
> >> +			return ret;
> >> +		}
> >> +	}
> >> +
> >> +	/* phy -> sensor */
> >> +	for (i = 0; i < p->num_subdevs; ++i) {
> >> +		ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
> >> +		if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
> >> +			goto err_stream_off;
> > 
> > You should stop after the first external sub-device.
> > 
> > It seems even the omap3isp driver doesn't do that. It's not easy to spot
> > such issues indeed.
> 
> I'm not sure I understand, what do you call an external sub-device? Is the sensor
> an external subdevice?

One that is not controlled by this driver.

> 
> > 
> >> +	}
> >> +
> >> +	if (!on)
> >> +		v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
> >> +
> >> +	return 0;
> >> +
> >> +err_stream_off:
> >> +	for (--i; i >= 0; --i)
> >> +		v4l2_subdev_call(p->subdevs[i], video, s_stream, false);
> >> +	v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
> >> +	atomic_dec(&p->stream_cnt);
> >> +	return ret;
> >> +}
> >> +
> >> +/***************************** media controller *******************************/
> >> +/* See http://opensource.rock-chips.com/wiki_Rockchip-isp1 for Topology */
> > 
> > The host appears to be down, or there's a routing problem. Unless this is
> > fixed, having such a URL here doesn't do much good. :-I
> 
> This is a left over, sorry about that.
> I can access the URL now. I'll try to get some of the docs and move to the kernel docs.

I wonder if the server is only powered on during the local office hours.
;-)

More seriously, I looked into this and it seems there's a routing problem
somewhere between my ISP and that server. From a few other places the
server is reachable.

> 
> > 
> >> +
> >> +static int rkisp1_create_links(struct rkisp1_device *dev)
> >> +{
> >> +	struct media_entity *source, *sink;
> >> +	struct rkisp1_sensor *sensor;
> >> +	unsigned int flags, pad;
> >> +	int ret;
> >> +
> >> +	/* sensor links(or mipi-phy) */
> >> +	list_for_each_entry(sensor, &dev->sensors, list) {
> >> +		for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
> >> +			if (sensor->sd->entity.pads[pad].flags &
> >> +				MEDIA_PAD_FL_SOURCE)
> >> +				break;
> > 
> > Could you use media_entity_get_fwnode_pad() instead?
> 
> Yes, I didn't know about it actually, thanks for that, looks cleaner (I'll send in
> the next version).
> 
> > 
> >> +
> >> +		if (pad == sensor->sd->entity.num_pads) {
> >> +			dev_err(dev->dev,
> >> +				"failed to find src pad for %s\n",
> >> +				sensor->sd->name);
> >> +
> >> +			return -ENXIO;
> >> +		}
> >> +
> >> +		ret = media_create_pad_link(
> >> +				&sensor->sd->entity, pad,
> >> +				&dev->isp_sdev.sd.entity,
> >> +				RKISP1_ISP_PAD_SINK,
> >> +				list_is_first(&sensor->list, &dev->sensors) ?
> >> +				MEDIA_LNK_FL_ENABLED : 0);
> >> +		if (ret) {
> >> +			dev_err(dev->dev,
> >> +				"failed to create link for %s\n",
> >> +				sensor->sd->name);
> >> +			return ret;
> >> +		}
> >> +	}
> >> +
> >> +	/* params links */
> >> +	source = &dev->params_vdev.vnode.vdev.entity;
> >> +	sink = &dev->isp_sdev.sd.entity;
> >> +	flags = MEDIA_LNK_FL_ENABLED;
> >> +	ret = media_create_pad_link(source, 0, sink,
> >> +				       RKISP1_ISP_PAD_SINK_PARAMS, flags);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	/* create isp internal links */
> >> +	/* SP links */
> >> +	source = &dev->isp_sdev.sd.entity;
> >> +	sink = &dev->stream[RKISP1_STREAM_SP].vnode.vdev.entity;
> >> +	ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
> >> +				       sink, 0, flags);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	/* MP links */
> >> +	source = &dev->isp_sdev.sd.entity;
> >> +	sink = &dev->stream[RKISP1_STREAM_MP].vnode.vdev.entity;
> >> +	ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
> >> +				       sink, 0, flags);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	/* 3A stats links */
> >> +	source = &dev->isp_sdev.sd.entity;
> >> +	sink = &dev->stats_vdev.vnode.vdev.entity;
> >> +	return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS,
> >> +					sink, 0, flags);
> > 
> > Indentation. Same for the calls to the same function above.
> 
> ack
> 
> > 
> >> +}
> >> +
> >> +static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
> >> +				 struct v4l2_subdev *sd,
> >> +				 struct v4l2_async_subdev *asd)
> >> +{
> >> +	struct rkisp1_device *isp_dev = container_of(notifier,
> >> +						     struct rkisp1_device,
> >> +						     notifier);
> >> +	struct sensor_async_subdev *s_asd = container_of(asd,
> >> +					struct sensor_async_subdev, asd);
> >> +	struct rkisp1_sensor *sensor;
> >> +
> >> +	sensor = devm_kzalloc(isp_dev->dev, sizeof(*sensor), GFP_KERNEL);
> >> +	if (!sensor)
> >> +		return -ENOMEM;
> >> +
> >> +	sensor->lanes = s_asd->lanes;
> >> +	sensor->mbus = s_asd->mbus;
> >> +	sensor->sd = sd;
> >> +	sensor->dphy = devm_phy_get(isp_dev->dev, "dphy");
> >> +	if (IS_ERR(sensor->dphy)) {
> >> +		if (PTR_ERR(sensor->dphy) != -EPROBE_DEFER)
> >> +			dev_err(isp_dev->dev, "Couldn't get the MIPI D-PHY\n");
> >> +		return PTR_ERR(sensor->dphy);
> >> +	}
> >> +	phy_init(sensor->dphy);
> >> +
> >> +	list_add(&sensor->list, &isp_dev->sensors);
> > 
> > In general, maintaining the information on the external subdevs on your own
> > adds complexity to the driver. You can get the information when you need it
> > from the data structures maintained by MC (see e.g. the omap3isp driver for
> > examples).
> > 
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static struct rkisp1_sensor *sd_to_sensor(struct rkisp1_device *dev,
> >> +					  struct v4l2_subdev *sd)
> >> +{
> >> +	struct rkisp1_sensor *sensor;
> >> +
> >> +	list_for_each_entry(sensor, &dev->sensors, list)
> >> +		if (sensor->sd == sd)
> >> +			return sensor;
> >> +
> >> +	return NULL;
> >> +}
> >> +
> >> +static void subdev_notifier_unbind(struct v4l2_async_notifier *notifier,
> >> +				   struct v4l2_subdev *sd,
> >> +				   struct v4l2_async_subdev *asd)
> >> +{
> >> +	struct rkisp1_device *isp_dev = container_of(notifier,
> >> +						     struct rkisp1_device,
> >> +						     notifier);
> >> +	struct rkisp1_sensor *sensor = sd_to_sensor(isp_dev, sd);
> >> +
> >> +	/* TODO: check if a lock is required here */
> >> +	list_del(&sensor->list);
> >> +
> >> +	phy_exit(sensor->dphy);
> >> +}
> >> +
> >> +static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
> >> +{
> >> +	struct rkisp1_device *dev = container_of(notifier, struct rkisp1_device,
> >> +						 notifier);
> >> +	int ret;
> >> +
> >> +	mutex_lock(&dev->media_dev.graph_mutex);
> >> +	ret = rkisp1_create_links(dev);
> >> +	if (ret < 0)
> >> +		goto unlock;
> >> +	ret = v4l2_device_register_subdev_nodes(&dev->v4l2_dev);
> >> +	if (ret < 0)
> >> +		goto unlock;
> >> +
> >> +	v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n");
> >> +
> >> +unlock:
> >> +	mutex_unlock(&dev->media_dev.graph_mutex);
> >> +	return ret;
> >> +}
> >> +
> >> +static int rkisp1_fwnode_parse(struct device *dev,
> >> +			       struct v4l2_fwnode_endpoint *vep,
> >> +			       struct v4l2_async_subdev *asd)
> >> +{
> >> +	struct sensor_async_subdev *s_asd =
> >> +			container_of(asd, struct sensor_async_subdev, asd);
> >> +
> >> +	if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
> >> +		dev_err(dev, "Only CSI2 bus type is currently supported\n");
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	if (vep->base.port != 0) {
> >> +		dev_err(dev, "The ISP has only port 0\n");
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	s_asd->mbus.type = vep->bus_type;
> >> +	s_asd->mbus.flags = vep->bus.mipi_csi2.flags;
> >> +	s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
> >> +
> >> +	switch (vep->bus.mipi_csi2.num_data_lanes) {
> >> +	case 1:
> >> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_1_LANE;
> >> +		break;
> >> +	case 2:
> >> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_2_LANE;
> >> +		break;
> >> +	case 3:
> >> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_3_LANE;
> >> +		break;
> >> +	case 4:
> >> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_4_LANE;
> >> +		break;
> >> +	default:
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
> >> +	.bound = subdev_notifier_bound,
> >> +	.unbind = subdev_notifier_unbind,
> >> +	.complete = subdev_notifier_complete,
> >> +};
> >> +
> >> +static int isp_subdev_notifier(struct rkisp1_device *isp_dev)
> >> +{
> >> +	struct v4l2_async_notifier *ntf = &isp_dev->notifier;
> >> +	struct device *dev = isp_dev->dev;
> >> +	int ret;
> >> +
> >> +	v4l2_async_notifier_init(ntf);
> >> +
> >> +	ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> >> +		dev, ntf, sizeof(struct sensor_async_subdev), 0,
> >> +		rkisp1_fwnode_parse);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	if (list_empty(&ntf->asd_list))
> >> +		return -ENODEV;	/* no endpoint */
> >> +
> >> +	ntf->ops = &subdev_notifier_ops;
> >> +
> >> +	return v4l2_async_notifier_register(&isp_dev->v4l2_dev, ntf);
> >> +}
> >> +
> >> +/***************************** platform device *******************************/
> >> +
> >> +static int rkisp1_register_platform_subdevs(struct rkisp1_device *dev)
> >> +{
> >> +	int ret;
> >> +
> >> +	ret = rkisp1_register_isp_subdev(dev, &dev->v4l2_dev);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	ret = rkisp1_register_stream_vdevs(dev);
> >> +	if (ret < 0)
> >> +		goto err_unreg_isp_subdev;
> >> +
> >> +	ret = rkisp1_register_stats_vdev(&dev->stats_vdev, &dev->v4l2_dev, dev);
> >> +	if (ret < 0)
> >> +		goto err_unreg_stream_vdev;
> >> +
> >> +	ret = rkisp1_register_params_vdev(&dev->params_vdev, &dev->v4l2_dev,
> >> +					  dev);
> >> +	if (ret < 0)
> >> +		goto err_unreg_stats_vdev;
> >> +
> >> +	ret = isp_subdev_notifier(dev);
> >> +	if (ret < 0) {
> >> +		v4l2_err(&dev->v4l2_dev,
> >> +			 "Failed to register subdev notifier(%d)\n", ret);
> >> +		goto err_unreg_params_vdev;
> >> +	}
> >> +
> >> +	return 0;
> >> +err_unreg_params_vdev:
> >> +	rkisp1_unregister_params_vdev(&dev->params_vdev);
> >> +err_unreg_stats_vdev:
> >> +	rkisp1_unregister_stats_vdev(&dev->stats_vdev);
> >> +err_unreg_stream_vdev:
> >> +	rkisp1_unregister_stream_vdevs(dev);
> >> +err_unreg_isp_subdev:
> >> +	rkisp1_unregister_isp_subdev(dev);
> >> +	return ret;
> >> +}
> >> +
> >> +static const char * const rk3399_isp_clks[] = {
> >> +	"clk_isp",
> >> +	"aclk_isp",
> >> +	"hclk_isp",
> >> +	"aclk_isp_wrap",
> >> +	"hclk_isp_wrap",
> >> +};
> >> +
> >> +static const char * const rk3288_isp_clks[] = {
> >> +	"clk_isp",
> >> +	"aclk_isp",
> >> +	"hclk_isp",
> >> +	"pclk_isp_in",
> >> +	"sclk_isp_jpe",
> >> +};
> >> +
> >> +static const struct isp_match_data rk3288_isp_clk_data = {
> >> +	.clks = rk3288_isp_clks,
> >> +	.size = ARRAY_SIZE(rk3288_isp_clks),
> >> +};
> >> +
> >> +static const struct isp_match_data rk3399_isp_clk_data = {
> >> +	.clks = rk3399_isp_clks,
> >> +	.size = ARRAY_SIZE(rk3399_isp_clks),
> >> +};
> >> +
> >> +static const struct of_device_id rkisp1_plat_of_match[] = {
> >> +	{
> >> +		.compatible = "rockchip,rk3288-cif-isp",
> >> +		.data = &rk3288_isp_clk_data,
> >> +	}, {
> >> +		.compatible = "rockchip,rk3399-cif-isp",
> >> +		.data = &rk3399_isp_clk_data,
> >> +	},
> >> +	{},
> >> +};
> >> +MODULE_DEVICE_TABLE(of, rkisp1_plat_of_match);
> >> +
> >> +static irqreturn_t rkisp1_irq_handler(int irq, void *ctx)
> >> +{
> >> +	struct device *dev = ctx;
> >> +	struct rkisp1_device *rkisp1_dev = dev_get_drvdata(dev);
> >> +	unsigned int mis_val;
> >> +
> >> +	mis_val = readl(rkisp1_dev->base_addr + CIF_ISP_MIS);
> >> +	if (mis_val)
> >> +		rkisp1_isp_isr(mis_val, rkisp1_dev);
> >> +
> >> +	mis_val = readl(rkisp1_dev->base_addr + CIF_MIPI_MIS);
> >> +	if (mis_val)
> >> +		rkisp1_mipi_isr(mis_val, rkisp1_dev);
> >> +
> >> +	mis_val = readl(rkisp1_dev->base_addr + CIF_MI_MIS);
> >> +	if (mis_val)
> >> +		rkisp1_mi_isr(mis_val, rkisp1_dev);
> >> +
> >> +	return IRQ_HANDLED;
> >> +}
> >> +
> >> +static int rkisp1_plat_probe(struct platform_device *pdev)
> >> +{
> >> +	struct device_node *node = pdev->dev.of_node;
> >> +	const struct isp_match_data *clk_data;
> >> +	const struct of_device_id *match;
> >> +	struct device *dev = &pdev->dev;
> >> +	struct rkisp1_device *isp_dev;
> >> +	struct v4l2_device *v4l2_dev;
> >> +	unsigned int i;
> >> +	int ret, irq;
> >> +
> >> +	match = of_match_node(rkisp1_plat_of_match, node);
> >> +	isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
> >> +	if (!isp_dev)
> >> +		return -ENOMEM;
> >> +
> >> +	INIT_LIST_HEAD(&isp_dev->sensors);
> >> +
> >> +	dev_set_drvdata(dev, isp_dev);
> >> +	isp_dev->dev = dev;
> >> +
> >> +	isp_dev->base_addr = devm_platform_ioremap_resource(pdev, 0);
> >> +	if (IS_ERR(isp_dev->base_addr))
> >> +		return PTR_ERR(isp_dev->base_addr);
> >> +
> >> +	irq = platform_get_irq(pdev, 0);
> >> +	if (irq < 0)
> >> +		return irq;
> >> +
> >> +	ret = devm_request_irq(dev, irq, rkisp1_irq_handler, IRQF_SHARED,
> >> +			       dev_driver_string(dev), dev);
> >> +	if (ret < 0) {
> >> +		dev_err(dev, "request irq failed: %d\n", ret);
> >> +		return ret;
> >> +	}
> >> +
> >> +	isp_dev->irq = irq;
> >> +	clk_data = match->data;
> >> +
> >> +	for (i = 0; i < clk_data->size; i++)
> >> +		isp_dev->clks[i].id = clk_data->clks[i];
> >> +	ret = devm_clk_bulk_get(dev, clk_data->size, isp_dev->clks);
> >> +	if (ret)
> >> +		return ret;
> >> +	isp_dev->clk_size = clk_data->size;
> >> +
> >> +	atomic_set(&isp_dev->pipe.power_cnt, 0);
> >> +	atomic_set(&isp_dev->pipe.stream_cnt, 0);
> >> +	isp_dev->pipe.open = rkisp1_pipeline_open;
> >> +	isp_dev->pipe.close = rkisp1_pipeline_close;
> >> +	isp_dev->pipe.set_stream = rkisp1_pipeline_set_stream;
> >> +
> >> +	rkisp1_stream_init(isp_dev, RKISP1_STREAM_SP);
> >> +	rkisp1_stream_init(isp_dev, RKISP1_STREAM_MP);
> >> +
> >> +	strscpy(isp_dev->media_dev.model, "rkisp1",
> >> +		sizeof(isp_dev->media_dev.model));
> >> +	isp_dev->media_dev.dev = &pdev->dev;
> >> +	strscpy(isp_dev->media_dev.bus_info,
> >> +		"platform: " DRIVER_NAME, sizeof(isp_dev->media_dev.bus_info));
> >> +	media_device_init(&isp_dev->media_dev);
> >> +
> >> +	v4l2_dev = &isp_dev->v4l2_dev;
> >> +	v4l2_dev->mdev = &isp_dev->media_dev;
> >> +	strscpy(v4l2_dev->name, "rkisp1", sizeof(v4l2_dev->name));
> >> +	v4l2_ctrl_handler_init(&isp_dev->ctrl_handler, 5);
> >> +	v4l2_dev->ctrl_handler = &isp_dev->ctrl_handler;
> >> +
> >> +	ret = v4l2_device_register(isp_dev->dev, &isp_dev->v4l2_dev);
> >> +	if (ret < 0)
> > 
> > Once you've initialised the control handler, you'll need to free it in case
> > of an error. I.e. add one more label for that purpose near the end.
> 
> control handler is not required, I'll remove it for the next version.
> 
> > 
> >> +		return ret;
> >> +
> >> +	ret = media_device_register(&isp_dev->media_dev);
> >> +	if (ret < 0) {
> >> +		v4l2_err(v4l2_dev, "Failed to register media device: %d\n",
> >> +			 ret);
> >> +		goto err_unreg_v4l2_dev;
> >> +	}
> >> +
> >> +	/* create & register platefom subdev (from of_node) */
> >> +	ret = rkisp1_register_platform_subdevs(isp_dev);
> >> +	if (ret < 0)
> >> +		goto err_unreg_media_dev;
> >> +
> >> +	pm_runtime_enable(&pdev->dev);
> >> +
> >> +	return 0;
> >> +
> >> +err_unreg_media_dev:
> >> +	media_device_unregister(&isp_dev->media_dev);
> >> +err_unreg_v4l2_dev:
> >> +	v4l2_device_unregister(&isp_dev->v4l2_dev);
> >> +	return ret;
> >> +}
> >> +
> >> +static int rkisp1_plat_remove(struct platform_device *pdev)
> >> +{
> >> +	struct rkisp1_device *isp_dev = platform_get_drvdata(pdev);
> >> +
> >> +	pm_runtime_disable(&pdev->dev);
> >> +	media_device_unregister(&isp_dev->media_dev);
> >> +	v4l2_async_notifier_unregister(&isp_dev->notifier);
> >> +	v4l2_async_notifier_cleanup(&isp_dev->notifier);
> >> +	v4l2_device_unregister(&isp_dev->v4l2_dev);
> >> +	rkisp1_unregister_params_vdev(&isp_dev->params_vdev);
> >> +	rkisp1_unregister_stats_vdev(&isp_dev->stats_vdev);
> >> +	rkisp1_unregister_stream_vdevs(isp_dev);
> >> +	rkisp1_unregister_isp_subdev(isp_dev);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
> >> +{
> >> +	struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
> >> +
> >> +	clk_bulk_disable_unprepare(isp_dev->clk_size, isp_dev->clks);
> >> +	return pinctrl_pm_select_sleep_state(dev);
> >> +}
> >> +
> >> +static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
> >> +{
> >> +	struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
> >> +	int ret;
> >> +
> >> +	ret = pinctrl_pm_select_default_state(dev);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +	ret = clk_bulk_prepare_enable(isp_dev->clk_size, isp_dev->clks);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static const struct dev_pm_ops rkisp1_plat_pm_ops = {
> >> +	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> >> +				pm_runtime_force_resume)
> >> +	SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL)
> >> +};
> >> +
> >> +static struct platform_driver rkisp1_plat_drv = {
> >> +	.driver = {
> >> +		.name = DRIVER_NAME,
> >> +		.of_match_table = of_match_ptr(rkisp1_plat_of_match),
> >> +		.pm = &rkisp1_plat_pm_ops,
> >> +	},
> >> +	.probe = rkisp1_plat_probe,
> >> +	.remove = rkisp1_plat_remove,
> >> +};
> >> +
> >> +module_platform_driver(rkisp1_plat_drv);
> >> +MODULE_AUTHOR("Rockchip Camera/ISP team");
> >> +MODULE_DESCRIPTION("Rockchip ISP1 platform driver");
> >> +MODULE_LICENSE("Dual BSD/GPL");
> > 
> > BSD or MIT?
> 
> Thanks for spotting this, I'll verify.

I think this was the only place where the BSD license was present. The file
header has MIT.

> 
> > 
> >> diff --git a/drivers/media/platform/rockchip/isp1/dev.h b/drivers/media/platform/rockchip/isp1/dev.h
> >> new file mode 100644
> >> index 000000000000..f7cbee316523
> >> --- /dev/null
> >> +++ b/drivers/media/platform/rockchip/isp1/dev.h
> >> @@ -0,0 +1,97 @@
> >> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> >> +/*
> >> + * Rockchip isp1 driver
> >> + *
> >> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> >> + */
> >> +
> >> +#ifndef _RKISP1_DEV_H
> >> +#define _RKISP1_DEV_H
> >> +
> >> +#include <linux/clk.h>
> >> +
> >> +#include "capture.h"
> >> +#include "rkisp1.h"
> >> +#include "isp_params.h"
> >> +#include "isp_stats.h"
> >> +
> >> +#define DRIVER_NAME "rkisp1"
> >> +#define ISP_VDEV_NAME DRIVER_NAME  "_ispdev"
> >> +#define SP_VDEV_NAME DRIVER_NAME   "_selfpath"
> >> +#define MP_VDEV_NAME DRIVER_NAME   "_mainpath"
> >> +#define DMA_VDEV_NAME DRIVER_NAME  "_dmapath"
> >> +
> >> +#define GRP_ID_SENSOR			BIT(0)
> >> +#define GRP_ID_MIPIPHY			BIT(1)
> >> +#define GRP_ID_ISP			BIT(2)
> >> +#define GRP_ID_ISP_MP			BIT(3)
> >> +#define GRP_ID_ISP_SP			BIT(4)
> >> +
> >> +#define RKISP1_MAX_BUS_CLK	8
> >> +#define RKISP1_MAX_SENSOR	2
> >> +#define RKISP1_MAX_PIPELINE	4
> >> +
> >> +/*
> >> + * struct rkisp1_pipeline - An ISP hardware pipeline
> >> + *
> >> + * Capture device call other devices via pipeline
> >> + *
> >> + * @num_subdevs: number of linked subdevs
> >> + * @power_cnt: pipeline power count
> >> + * @stream_cnt: stream power count
> >> + */
> >> +struct rkisp1_pipeline {
> >> +	struct media_pipeline pipe;
> >> +	int num_subdevs;
> >> +	atomic_t power_cnt;
> >> +	atomic_t stream_cnt;
> >> +	struct v4l2_subdev *subdevs[RKISP1_MAX_PIPELINE];
> >> +	int (*open)(struct rkisp1_pipeline *p,
> >> +		    struct media_entity *me, bool prepare);
> >> +	int (*close)(struct rkisp1_pipeline *p);
> >> +	int (*set_stream)(struct rkisp1_pipeline *p, bool on);
> >> +};
> >> +
> >> +/*
> >> + * struct rkisp1_sensor - Sensor information
> >> + * @mbus: media bus configuration
> >> + */
> >> +struct rkisp1_sensor {
> >> +	struct v4l2_subdev *sd;
> >> +	struct v4l2_mbus_config mbus;
> >> +	unsigned int lanes;
> >> +	struct phy *dphy;
> >> +	struct list_head list;
> >> +};
> > 
> > You seem to also have struct sensor_async_subdev that appears to contain
> > similar information. Would it be possible to unify the two?
> > 
> > This would appear to allow you getting rid of functions such as
> > sd_to_sensor, for instance.
> 
> ack, I managed to get rid of this, and I don't even need to keep them
> on a list, I'll submit in the next version.

Nice!

> 
> Thanks a lot for your review

You're welcome!

-- 
Kind regards,

Sakari Ailus
sakari.ailus@linux.intel.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 07/22] ARM: omap1: move perseus spi pinconf to board file
From: Mark Brown @ 2019-08-09 12:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Aaro Koskinen, Tony Lindgren, Greg Kroah-Hartman, Linus Walleij,
	Bartlomiej Zolnierkiewicz, Linux Kernel Mailing List, linux-spi,
	Tomi Valkeinen, linux-omap, Linux ARM, Boris Brezillon
In-Reply-To: <CAK8P3a0qTvDFMj4GrKfD=2mkPpKN=eRJ--mp0r7mqAH+b2r=kg@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 749 bytes --]

On Fri, Aug 09, 2019 at 01:29:13PM +0200, Arnd Bergmann wrote:
> On Fri, Aug 9, 2019 at 12:24 AM Mark Brown <broonie@kernel.org> wrote:

> > On Thu, Aug 08, 2019 at 11:22:16PM +0200, Arnd Bergmann wrote:
> > > The driver has always had a FIXME about this, and it seems
> > > like this trivial code move avoids a mach header inclusion,
> > > so just do it.

> > This appears to be part of a series but I've no cover letter or anything
> > else from it.  What's the story for dependencies and merging?

> Sorry for missing you on the cover letter. The patch is part of a series
> to make omap1 part of ARCH_MULTIPLATFORM. I'd like to merge the entire
> series through the arm-soc tree to avoid dependencies:

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 00/59] KVM: arm64: ARMv8.3 Nested Virtualization support
From: Alexandru Elisei @ 2019-08-09 12:00 UTC (permalink / raw)
  To: Andrew Jones
  Cc: kvm@vger.kernel.org, Marc Zyngier, Andre Przywara,
	kvmarm@lists.cs.columbia.edu, Dave P Martin,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190809114455.w4jes6z2442vu3py@kamzik.brq.redhat.com>

Hi Andrew,

On 8/9/19 12:44 PM, Andrew Jones wrote:
> On Fri, Aug 09, 2019 at 11:01:51AM +0100, Alexandru Elisei wrote:
>> On 8/2/19 11:11 AM, Alexandru Elisei wrote:
>>> Hi,
>>>
>>> On 6/21/19 10:37 AM, Marc Zyngier wrote:
>>>> I've taken over the maintenance of this series originally written by
>>>> Jintack and Christoffer. Since then, the series has been substantially
>>>> reworked, new features (and most probably bugs) have been added, and
>>>> the whole thing rebased multiple times. If anything breaks, please
>>>> blame me, and nobody else.
>>>>
>>>> As you can tell, this is quite big. It is also remarkably incomplete
>>>> (we're missing many critical bits for fully emulate EL2), but the idea
>>>> is to start merging things early in order to reduce the maintenance
>>>> headache. What we want to achieve is that with NV disabled, there is
>>>> no performance overhead and no regression. The only thing I intend to
>>>> merge ASAP is the first patch in the series, because it should have
>>>> zero effect and is a reasonable cleanup.
>>>>
>>>> The series is roughly divided in 4 parts: exception handling, memory
>>>> virtualization, interrupts and timers. There are of course some
>>>> dependencies, but you'll hopefully get the gist of it.
>>>>
>>>> For the most courageous of you, I've put out a branch[1] containing this
>>>> and a bit more. Of course, you'll need some userspace. Andre maintains
>>>> a hacked version of kvmtool[1] that takes a --nested option, allowing
>>>> the guest to be started at EL2. You can run the whole stack in the
>>>> Foundation model. Don't be in a hurry ;-).
>>>>
>>>> [1] git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git kvm-arm64/nv-wip-5.2-rc5
>>>> [2] git://linux-arm.org/kvmtool.git nv/nv-wip-5.2-rc5
>>>>
>>>> Andre Przywara (4):
>>>>   KVM: arm64: nv: Handle virtual EL2 registers in
>>>>     vcpu_read/write_sys_reg()
>>>>   KVM: arm64: nv: Save/Restore vEL2 sysregs
>>>>   KVM: arm64: nv: Handle traps for timer _EL02 and _EL2 sysregs
>>>>     accessors
>>>>   KVM: arm64: nv: vgic: Allow userland to set VGIC maintenance IRQ
>>>>
>>>> Christoffer Dall (16):
>>>>   KVM: arm64: nv: Introduce nested virtualization VCPU feature
>>>>   KVM: arm64: nv: Reset VCPU to EL2 registers if VCPU nested virt is set
>>>>   KVM: arm64: nv: Allow userspace to set PSR_MODE_EL2x
>>>>   KVM: arm64: nv: Add nested virt VCPU primitives for vEL2 VCPU state
>>>>   KVM: arm64: nv: Handle trapped ERET from virtual EL2
>>>>   KVM: arm64: nv: Emulate PSTATE.M for a guest hypervisor
>>>>   KVM: arm64: nv: Trap EL1 VM register accesses in virtual EL2
>>>>   KVM: arm64: nv: Only toggle cache for virtual EL2 when SCTLR_EL2
>>>>     changes
>>>>   KVM: arm/arm64: nv: Support multiple nested stage 2 mmu structures
>>>>   KVM: arm64: nv: Implement nested Stage-2 page table walk logic
>>>>   KVM: arm64: nv: Handle shadow stage 2 page faults
>>>>   KVM: arm64: nv: Unmap/flush shadow stage 2 page tables
>>>>   KVM: arm64: nv: arch_timer: Support hyp timer emulation
>>>>   KVM: arm64: nv: vgic-v3: Take cpu_if pointer directly instead of vcpu
>>>>   KVM: arm64: nv: vgic: Emulate the HW bit in software
>>>>   KVM: arm64: nv: Add nested GICv3 tracepoints
>>>>
>>>> Dave Martin (1):
>>>>   KVM: arm64: Migrate _elx sysreg accessors to msr_s/mrs_s
>>>>
>>>> Jintack Lim (21):
>>>>   arm64: Add ARM64_HAS_NESTED_VIRT cpufeature
>>>>   KVM: arm64: nv: Add EL2 system registers to vcpu context
>>>>   KVM: arm64: nv: Support virtual EL2 exceptions
>>>>   KVM: arm64: nv: Inject HVC exceptions to the virtual EL2
>>>>   KVM: arm64: nv: Trap SPSR_EL1, ELR_EL1 and VBAR_EL1 from virtual EL2
>>>>   KVM: arm64: nv: Trap CPACR_EL1 access in virtual EL2
>>>>   KVM: arm64: nv: Set a handler for the system instruction traps
>>>>   KVM: arm64: nv: Handle PSCI call via smc from the guest
>>>>   KVM: arm64: nv: Respect virtual HCR_EL2.TWX setting
>>>>   KVM: arm64: nv: Respect virtual CPTR_EL2.TFP setting
>>>>   KVM: arm64: nv: Respect the virtual HCR_EL2.NV bit setting
>>>>   KVM: arm64: nv: Respect virtual HCR_EL2.TVM and TRVM settings
>>>>   KVM: arm64: nv: Respect the virtual HCR_EL2.NV1 bit setting
>>>>   KVM: arm64: nv: Emulate EL12 register accesses from the virtual EL2
>>>>   KVM: arm64: nv: Configure HCR_EL2 for nested virtualization
>>>>   KVM: arm64: nv: Pretend we only support larger-than-host page sizes
>>>>   KVM: arm64: nv: Introduce sys_reg_desc.forward_trap
>>>>   KVM: arm64: nv: Rework the system instruction emulation framework
>>>>   KVM: arm64: nv: Trap and emulate AT instructions from virtual EL2
>>>>   KVM: arm64: nv: Trap and emulate TLBI instructions from virtual EL2
>>>>   KVM: arm64: nv: Nested GICv3 Support
>>>>
>>>> Marc Zyngier (17):
>>>>   KVM: arm64: Move __load_guest_stage2 to kvm_mmu.h
>>>>   KVM: arm64: nv: Reset VMPIDR_EL2 and VPIDR_EL2 to sane values
>>>>   KVM: arm64: nv: Handle SPSR_EL2 specially
>>>>   KVM: arm64: nv: Refactor vcpu_{read,write}_sys_reg
>>>>   KVM: arm64: nv: Don't expose SVE to nested guests
>>>>   KVM: arm64: nv: Hide RAS from nested guests
>>>>   KVM: arm/arm64: nv: Factor out stage 2 page table data from struct kvm
>>>>   KVM: arm64: nv: Move last_vcpu_ran to be per s2 mmu
>>>>   KVM: arm64: nv: Don't always start an S2 MMU search from the beginning
>>>>   KVM: arm64: nv: Propagate CNTVOFF_EL2 to the virtual EL1 timer
>>>>   KVM: arm64: nv: Load timer before the GIC
>>>>   KVM: arm64: nv: Implement maintenance interrupt forwarding
>>>>   arm64: KVM: nv: Add handling of EL2-specific timer registers
>>>>   arm64: KVM: nv: Honor SCTLR_EL2.SPAN on entering vEL2
>>>>   arm64: KVM: nv: Handle SCTLR_EL2 RES0/RES1 bits
>>>>   arm64: KVM: nv: Restrict S2 RD/WR permissions to match the guest's
>>>>   arm64: KVM: nv: Allow userspace to request KVM_ARM_VCPU_NESTED_VIRT
>>>>
>>>>  .../admin-guide/kernel-parameters.txt         |    4 +
>>>>  .../virtual/kvm/devices/arm-vgic-v3.txt       |    9 +
>>>>  arch/arm/include/asm/kvm_asm.h                |    5 +-
>>>>  arch/arm/include/asm/kvm_emulate.h            |    3 +
>>>>  arch/arm/include/asm/kvm_host.h               |   31 +-
>>>>  arch/arm/include/asm/kvm_hyp.h                |   25 +-
>>>>  arch/arm/include/asm/kvm_mmu.h                |   83 +-
>>>>  arch/arm/include/asm/kvm_nested.h             |    9 +
>>>>  arch/arm/include/uapi/asm/kvm.h               |    1 +
>>>>  arch/arm/kvm/hyp/switch.c                     |   11 +-
>>>>  arch/arm/kvm/hyp/tlb.c                        |   13 +-
>>>>  arch/arm64/include/asm/cpucaps.h              |    3 +-
>>>>  arch/arm64/include/asm/esr.h                  |    4 +-
>>>>  arch/arm64/include/asm/kvm_arm.h              |   28 +-
>>>>  arch/arm64/include/asm/kvm_asm.h              |    9 +-
>>>>  arch/arm64/include/asm/kvm_coproc.h           |    2 +-
>>>>  arch/arm64/include/asm/kvm_emulate.h          |  157 +-
>>>>  arch/arm64/include/asm/kvm_host.h             |  105 +-
>>>>  arch/arm64/include/asm/kvm_hyp.h              |   82 +-
>>>>  arch/arm64/include/asm/kvm_mmu.h              |   62 +-
>>>>  arch/arm64/include/asm/kvm_nested.h           |   68 +
>>>>  arch/arm64/include/asm/sysreg.h               |  143 +-
>>>>  arch/arm64/include/uapi/asm/kvm.h             |    2 +
>>>>  arch/arm64/kernel/cpufeature.c                |   26 +
>>>>  arch/arm64/kvm/Makefile                       |    4 +
>>>>  arch/arm64/kvm/emulate-nested.c               |  223 +++
>>>>  arch/arm64/kvm/guest.c                        |    6 +
>>>>  arch/arm64/kvm/handle_exit.c                  |   76 +-
>>>>  arch/arm64/kvm/hyp/Makefile                   |    1 +
>>>>  arch/arm64/kvm/hyp/at.c                       |  217 +++
>>>>  arch/arm64/kvm/hyp/switch.c                   |   86 +-
>>>>  arch/arm64/kvm/hyp/sysreg-sr.c                |  267 ++-
>>>>  arch/arm64/kvm/hyp/tlb.c                      |  129 +-
>>>>  arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c      |    2 +-
>>>>  arch/arm64/kvm/inject_fault.c                 |   12 -
>>>>  arch/arm64/kvm/nested.c                       |  551 +++++++
>>>>  arch/arm64/kvm/regmap.c                       |    4 +-
>>>>  arch/arm64/kvm/reset.c                        |    7 +
>>>>  arch/arm64/kvm/sys_regs.c                     | 1460 +++++++++++++++--
>>>>  arch/arm64/kvm/sys_regs.h                     |    6 +
>>>>  arch/arm64/kvm/trace.h                        |   58 +-
>>>>  include/kvm/arm_arch_timer.h                  |    6 +
>>>>  include/kvm/arm_vgic.h                        |   28 +-
>>>>  virt/kvm/arm/arch_timer.c                     |  158 +-
>>>>  virt/kvm/arm/arm.c                            |   62 +-
>>>>  virt/kvm/arm/hyp/vgic-v3-sr.c                 |   35 +-
>>>>  virt/kvm/arm/mmio.c                           |   12 +-
>>>>  virt/kvm/arm/mmu.c                            |  445 +++--
>>>>  virt/kvm/arm/trace.h                          |    6 +-
>>>>  virt/kvm/arm/vgic/vgic-init.c                 |   30 +
>>>>  virt/kvm/arm/vgic/vgic-kvm-device.c           |   22 +
>>>>  virt/kvm/arm/vgic/vgic-nested-trace.h         |  137 ++
>>>>  virt/kvm/arm/vgic/vgic-v2.c                   |   10 +-
>>>>  virt/kvm/arm/vgic/vgic-v3-nested.c            |  236 +++
>>>>  virt/kvm/arm/vgic/vgic-v3.c                   |   40 +-
>>>>  virt/kvm/arm/vgic/vgic.c                      |   74 +-
>>>>  56 files changed, 4683 insertions(+), 612 deletions(-)
>>>>  create mode 100644 arch/arm/include/asm/kvm_nested.h
>>>>  create mode 100644 arch/arm64/include/asm/kvm_nested.h
>>>>  create mode 100644 arch/arm64/kvm/emulate-nested.c
>>>>  create mode 100644 arch/arm64/kvm/hyp/at.c
>>>>  create mode 100644 arch/arm64/kvm/nested.c
>>>>  create mode 100644 virt/kvm/arm/vgic/vgic-nested-trace.h
>>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v3-nested.c
>>>>
>>> When working on adding support for EL2 to kvm-unit-tests I was able to trigger
>>> the following warning:
>>>
>>> # ./lkvm run -f psci.flat -m 128 -c 8 --console serial --irqchip gicv3 --nested
>>>   # lkvm run --firmware psci.flat -m 128 -c 8 --name guest-151
>>>   Info: Placing fdt at 0x80200000 - 0x80210000
>>>   # Warning: The maximum recommended amount of VCPUs is 4
>>> chr_testdev_init: chr-testdev: can't find a virtio-console
>>> INFO: PSCI version 1.0
>>> PASS: invalid-function
>>> PASS: affinity-info-on
>>> PASS: affinity-info-off
>>> [   24.381266] WARNING: CPU: 3 PID: 160 at
>>> arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:170
>>> kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.381366] Modules linked in:
>>> [   24.381466] CPU: 3 PID: 160 Comm: kvm-vcpu-1 Not tainted
>>> 5.2.0-rc5-00060-g7dbce63bd1c7 #145
>>> [   24.381566] Hardware name: Foundation-v8A (DT)
>>> [   24.381566] pstate: 40400009 (nZcv daif +PAN -UAO)
>>> [   24.381666] pc : kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.381766] lr : timer_emulate+0x24/0x98
>>> [   24.381766] sp : ffff000013d8b780
>>> [   24.381866] x29: ffff000013d8b780 x28: ffff80087a639b80
>>> [   24.381966] x27: ffff000010ba8648 x26: ffff000010b71b40
>>> [   24.382066] x25: ffff80087a63a100 x24: 0000000000000000
>>> [   24.382111] x23: 000080086ca54000 x22: ffff0000100ce260
>>> [   24.382166] x21: ffff800875e7c918 x20: ffff800875e7a800
>>> [   24.382275] x19: ffff800875e7ca08 x18: 0000000000000000
>>> [   24.382366] x17: 0000000000000000 x16: 0000000000000000
>>> [   24.382466] x15: 0000000000000000 x14: 0000000000002118
>>> [   24.382566] x13: 0000000000002190 x12: 0000000000002280
>>> [   24.382566] x11: 0000000000002208 x10: 0000000000000040
>>> [   24.382666] x9 : ffff000012dc3b38 x8 : 0000000000000000
>>> [   24.382766] x7 : 0000000000000000 x6 : ffff80087ac00248
>>> [   24.382866] x5 : 000080086ca54000 x4 : 0000000000002118
>>> [   24.382966] x3 : eeeeeeeeeeeeeeef x2 : ffff800875e7c918
>>> [   24.383066] x1 : 0000000000000001 x0 : ffff800875e7ca08
>>> [   24.383066] Call trace:
>>> [   24.383166]  kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.383266]  kvm_timer_vcpu_load+0x9c/0x1a0
>>> [   24.383366]  kvm_arch_vcpu_load+0xb0/0x1f0
>>> [   24.383366]  kvm_sched_in+0x1c/0x28
>>> [   24.383466]  finish_task_switch+0xd8/0x1d8
>>> [   24.383566]  __schedule+0x248/0x4a0
>>> [   24.383666]  preempt_schedule_irq+0x60/0x90
>>> [   24.383666]  el1_irq+0xd0/0x180
>>> [   24.383766]  kvm_handle_guest_abort+0x0/0x3a0
>>> [   24.383866]  kvm_arch_vcpu_ioctl_run+0x41c/0x688
>>> [   24.383866]  kvm_vcpu_ioctl+0x4c0/0x838
>>> [   24.383966]  do_vfs_ioctl+0xb8/0x878
>>> [   24.384077]  ksys_ioctl+0x84/0x90
>>> [   24.384166]  __arm64_sys_ioctl+0x18/0x28
>>> [   24.384166]  el0_svc_common.constprop.0+0xb0/0x168
>>> [   24.384266]  el0_svc_handler+0x28/0x78
>>> [   24.384366]  el0_svc+0x8/0xc
>>> [   24.384366] ---[ end trace 37a32293e43ac12c ]---
>>> [   24.384666] WARNING: CPU: 3 PID: 160 at
>>> arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:170
>>> kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.384766] Modules linked in:
>>> [   24.384866] CPU: 3 PID: 160 Comm: kvm-vcpu-1 Tainted: G        W
>>> 5.2.0-rc5-00060-g7dbce63bd1c7 #145
>>> [   24.384966] Hardware name: Foundation-v8A (DT)
>>> [   24.384966] pstate: 40400009 (nZcv daif +PAN -UAO)
>>> [   24.385066] pc : kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.385166] lr : timer_emulate+0x24/0x98
>>> [   24.385166] sp : ffff000013d8b780
>>> [   24.385266] x29: ffff000013d8b780 x28: ffff80087a639b80
>>> [   24.385366] x27: ffff000010ba8648 x26: ffff000010b71b40
>>> [   24.385466] x25: ffff80087a63a100 x24: 0000000000000000
>>> [   24.385466] x23: 000080086ca54000 x22: ffff0000100ce260
>>> [   24.385566] x21: ffff800875e7c918 x20: ffff800875e7a800
>>> [   24.385666] x19: ffff800875e7ca80 x18: 0000000000000000
>>> [   24.385766] x17: 0000000000000000 x16: 0000000000000000
>>> [   24.385866] x15: 0000000000000000 x14: 0000000000002118
>>> [   24.385966] x13: 0000000000002190 x12: 0000000000002280
>>> [   24.385966] x11: 0000000000002208 x10: 0000000000000040
>>> [   24.386066] x9 : ffff000012dc3b38 x8 : 0000000000000000
>>> [   24.386166] x7 : 0000000000000000 x6 : ffff80087ac00248
>>> [   24.386266] x5 : 000080086ca54000 x4 : 0000000000002118
>>> [   24.386366] x3 : eeeeeeeeeeeeeeef x2 : ffff800875e7c918
>>> [   24.386466] x1 : 0000000000000001 x0 : ffff800875e7ca80
>>> [   24.386466] Call trace:
>>> [   24.386566]  kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.386666]  kvm_timer_vcpu_load+0xa8/0x1a0
>>> [   24.386666]  kvm_arch_vcpu_load+0xb0/0x1f0
>>> [   24.386898]  kvm_sched_in+0x1c/0x28
>>> [   24.386966]  finish_task_switch+0xd8/0x1d8
>>> [   24.387166]  __schedule+0x248/0x4a0
>>> [   24.387354]  preempt_schedule_irq+0x60/0x90
>>> [   24.387366]  el1_irq+0xd0/0x180
>>> [   24.387466]  kvm_handle_guest_abort+0x0/0x3a0
>>> [   24.387566]  kvm_arch_vcpu_ioctl_run+0x41c/0x688
>>> [   24.387566]  kvm_vcpu_ioctl+0x4c0/0x838
>>> [   24.387666]  do_vfs_ioctl+0xb8/0x878
>>> [   24.387766]  ksys_ioctl+0x84/0x90
>>> [   24.387866]  __arm64_sys_ioctl+0x18/0x28
>>> [   24.387866]  el0_svc_common.constprop.0+0xb0/0x168
>>> [   24.387966]  el0_svc_handler+0x28/0x78
>>> [   24.388066]  el0_svc+0x8/0xc
>>> [   24.388066] ---[ end trace 37a32293e43ac12d ]---
>>> PASS: cpu-on
>>> SUMMARY: 4 te[   24.390266] WARNING: CPU: 3 PID: 160 at
>>> arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:170
>>> kvm_timer_irq_can_fire+0xc/0x30
>>> s[   24.390366] Modules linked in:
>>> ts[   24.390366] CPU: 3 PID: 160 Comm: kvm-vcpu-1 Tainted: G        W
>>> 5.2.0-rc5-00060-g7dbce63bd1c7 #145
>>> [   24.390566] Hardware name: Foundation-v8A (DT)
>>>
>>> [   24.390795] pstate: 40400009 (nZcv daif +PAN -UAO)
>>> [   24.390866] pc : kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.390966] lr : timer_emulate+0x24/0x98
>>> [   24.391066] sp : ffff000013d8b780
>>> [   24.391066] x29: ffff000013d8b780 x28: ffff80087a639b80
>>> [   24.391166] x27: ffff000010ba8648 x26: ffff000010b71b40
>>> [   24.391266] x25: ffff80087a63a100 x24: 0000000000000000
>>> [   24.391366] x23: 000080086ca54000 x22: 0000000000000003
>>> [   24.391466] x21: ffff800875e7c918 x20: ffff800875e7a800
>>> [   24.391466] x19: ffff800875e7ca08 x18: 0000000000000000
>>> [   24.391566] x17: 0000000000000000 x16: 0000000000000000
>>> [   24.391666] x15: 0000000000000000 x14: 0000000000002118
>>> [   24.391766] x13: 0000000000002190 x12: 0000000000002280
>>> [   24.391866] x11: 0000000000002208 x10: 0000000000000040
>>> [   24.391942] x9 : ffff000012dc3b38 x8 : 0000000000000000
>>> [   24.391966] x7 : 0000000000000000 x6 : ffff80087ac00248
>>> [   24.392066] x5 : 000080086ca54000 x4 : 0000000000002118
>>> [   24.392166] x3 : eeeeeeeeeeeeeeef x2 : ffff800875e7c918
>>> [   24.392269] x1 : 0000000000000001 x0 : ffff800875e7ca08
>>> [   24.392366] Call trace:
>>> [   24.392433]  kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.392466]  kvm_timer_vcpu_load+0x9c/0x1a0
>>> [   24.392597]  kvm_arch_vcpu_load+0xb0/0x1f0
>>> [   24.392666]  kvm_sched_in+0x1c/0x28
>>> [   24.392766]  finish_task_switch+0xd8/0x1d8
>>> [   24.392766]  __schedule+0x248/0x4a0
>>> [   24.392866]  preempt_schedule_irq+0x60/0x90
>>> [   24.392966]  el1_irq+0xd0/0x180
>>> [   24.392966]  kvm_handle_guest_abort+0x0/0x3a0
>>> [   24.393066]  kvm_arch_vcpu_ioctl_run+0x41c/0x688
>>> [   24.393166]  kvm_vcpu_ioctl+0x4c0/0x838
>>> [   24.393266]  do_vfs_ioctl+0xb8/0x878
>>> [   24.393266]  ksys_ioctl+0x84/0x90
>>> [   24.393366]  __arm64_sys_ioctl+0x18/0x28
>>> [   24.393466]  el0_svc_common.constprop.0+0xb0/0x168
>>> [   24.393566]  el0_svc_handler+0x28/0x78
>>> [   24.393566]  el0_svc+0x8/0xc
>>> [   24.393666] ---[ end trace 37a32293e43ac12e ]---
>>> [   24.393866] WARNING: CPU: 3 PID: 160 at
>>> arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:170
>>> kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.394066] Modules linked in:
>>> [   24.394266] CPU: 3 PID: 160 Comm: kvm-vcpu-1 Tainted: G        W
>>> 5.2.0-rc5-00060-g7dbce63bd1c7 #145
>>> [   24.394366] Hardware name: Foundation-v8A (DT)
>>> [   24.394466] pstate: 40400009 (nZcv daif +PAN -UAO)
>>> [   24.394466] pc : kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.394566] lr : timer_emulate+0x24/0x98
>>> [   24.394666] sp : ffff000013d8b780
>>> [   24.394727] x29: ffff000013d8b780 x28: ffff80087a639b80
>>> [   24.394766] x27: ffff000010ba8648 x26: ffff000010b71b40
>>> [   24.394866] x25: ffff80087a63a100 x24: 0000000000000000
>>> [   24.394966] x23: 000080086ca54000 x22: 0000000000000003
>>> [   24.394966] x21: ffff800875e7c918 x20: ffff800875e7a800
>>> [   24.395066] x19: ffff800875e7ca80 x18: 0000000000000000
>>> [   24.395166] x17: 0000000000000000 x16: 0000000000000000
>>> [   24.395266] x15: 0000000000000000 x14: 0000000000002118
>>> [   24.395383] x13: 0000000000002190 x12: 0000000000002280
>>> [   24.395466] x11: 0000000000002208 x10: 0000000000000040
>>> [   24.395547] x9 : ffff000012dc3b38 x8 : 0000000000000000
>>> [   24.395666] x7 : 0000000000000000 x6 : ffff80087ac00248
>>> [   24.395866] x5 : 000080086ca54000 x4 : 0000000000002118
>>> [   24.395966] x3 : eeeeeeeeeeeeeeef x2 : ffff800875e7c918
>>> [   24.396066] x1 : 0000000000000001 x0 : ffff800875e7ca80
>>> [   24.396066] Call trace:
>>> [   24.396166]  kvm_timer_irq_can_fire+0xc/0x30
>>> [   24.396266]  kvm_timer_vcpu_load+0xa8/0x1a0
>>> [   24.396366]  kvm_arch_vcpu_load+0xb0/0x1f0
>>> [   24.396366]  kvm_sched_in+0x1c/0x28
>>> [   24.396466]  finish_task_switch+0xd8/0x1d8
>>> [   24.396566]  __schedule+0x248/0x4a0
>>> [   24.396666]  preempt_schedule_irq+0x60/0x90
>>> [   24.396666]  el1_irq+0xd0/0x180
>>> [   24.396766]  kvm_handle_guest_abort+0x0/0x3a0
>>> [   24.396866]  kvm_arch_vcpu_ioctl_run+0x41c/0x688
>>> [   24.396866]  kvm_vcpu_ioctl+0x4c0/0x838
>>> [   24.397021]  do_vfs_ioctl+0xb8/0x878
>>> [   24.397066]  ksys_ioctl+0x84/0x90
>>> [   24.397166]  __arm64_sys_ioctl+0x18/0x28
>>> [   24.397348]  el0_svc_common.constprop.0+0xb0/0x168
>>> [   24.397366]  el0_svc_handler+0x28/0x78
>>> [   24.397566]  el0_svc+0x8/0xc
>>> [   24.397676] ---[ end trace 37a32293e43ac12f ]---
>>>
>>>   # KVM compatibility warning.
>>>     virtio-9p device was not detected.
>>>     While you have requested a virtio-9p device, the guest kernel did not
>>> initialize it.
>>>     Please make sure that the guest kernel was compiled with
>>> CONFIG_NET_9P_VIRTIO=y enabled in .config.
>>>
>>>   # KVM compatibility warning.
>>>     virtio-net device was not detected.
>>>     While you have requested a virtio-net device, the guest kernel did not
>>> initialize it.
>>>     Please make sure that the guest kernel was compiled with CONFIG_VIRTIO_NET=y
>>> enabled in .config.
>>>
>>> [..]
>> Did some investigating and this was caused by a bug in kvm-unit-tests (the fix
>> for it will be part of the EL2 patches for kvm-unit-tests). The guest was trying
>> to fetch an instruction from address 0x200, which KVM interprets as a prefetch
>> abort on an I/O address and ends up calling kvm_inject_pabt. The code from
>> arch/arm64/kvm/inject_fault.c doesn't know anything about nested virtualization,
>> and it sets the VCPU mode directly to PSR_MODE_EL1h. This makes_hyp_ctxt return
>> false, and get_timer_map will return an incorrect mapping.
>>
>> On next kvm_timer_vcpu_put, the direct timers will be {p,v}timer, and
>> h{p,v}timer->loaded will not be set to false. In the corresponding call to
>> kvm_timer_vcpu_load, KVM will try to emulate the hptimer and hvtimer, which
>> still have loaded = true. And this causes the warning I saw.
>>
> Hi Alexandru,
>
> While a unit test in kvm-unit-tests may not do what it should in order to
> exercise the code it's targeting appropriately, and therefore need to be
> fixed in order to do that, I'd argue that if a guest can induce a host
> warning then that's a host bug. Indeed now that you've analyzed the
> issue you could write a kvm-unit-tests test to specifically reproduce the
> warning and then use that test to test any host fix candidates.
>
> Thanks,
> drew
>
It was a host bug triggered by a bug in kvm-unit-tests. The kvm-unit-tests bug
is a real bug because it goes against the intent of the psci test. It wasn't
discovered until now because with the upstream version of Linux we don't get any
messages about it. I'll post a patch for it as soon as I can and we can discuss
how we want to fix it :)

Thanks,
Alex

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 00/59] KVM: arm64: ARMv8.3 Nested Virtualization support
From: Andrew Jones @ 2019-08-09 11:44 UTC (permalink / raw)
  To: Alexandru Elisei
  Cc: kvm@vger.kernel.org, Marc Zyngier, Andre Przywara,
	kvmarm@lists.cs.columbia.edu, Dave P Martin,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <0d9aa552-fa01-c482-41d7-587acf308259@arm.com>

On Fri, Aug 09, 2019 at 11:01:51AM +0100, Alexandru Elisei wrote:
> On 8/2/19 11:11 AM, Alexandru Elisei wrote:
> > Hi,
> >
> > On 6/21/19 10:37 AM, Marc Zyngier wrote:
> >> I've taken over the maintenance of this series originally written by
> >> Jintack and Christoffer. Since then, the series has been substantially
> >> reworked, new features (and most probably bugs) have been added, and
> >> the whole thing rebased multiple times. If anything breaks, please
> >> blame me, and nobody else.
> >>
> >> As you can tell, this is quite big. It is also remarkably incomplete
> >> (we're missing many critical bits for fully emulate EL2), but the idea
> >> is to start merging things early in order to reduce the maintenance
> >> headache. What we want to achieve is that with NV disabled, there is
> >> no performance overhead and no regression. The only thing I intend to
> >> merge ASAP is the first patch in the series, because it should have
> >> zero effect and is a reasonable cleanup.
> >>
> >> The series is roughly divided in 4 parts: exception handling, memory
> >> virtualization, interrupts and timers. There are of course some
> >> dependencies, but you'll hopefully get the gist of it.
> >>
> >> For the most courageous of you, I've put out a branch[1] containing this
> >> and a bit more. Of course, you'll need some userspace. Andre maintains
> >> a hacked version of kvmtool[1] that takes a --nested option, allowing
> >> the guest to be started at EL2. You can run the whole stack in the
> >> Foundation model. Don't be in a hurry ;-).
> >>
> >> [1] git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git kvm-arm64/nv-wip-5.2-rc5
> >> [2] git://linux-arm.org/kvmtool.git nv/nv-wip-5.2-rc5
> >>
> >> Andre Przywara (4):
> >>   KVM: arm64: nv: Handle virtual EL2 registers in
> >>     vcpu_read/write_sys_reg()
> >>   KVM: arm64: nv: Save/Restore vEL2 sysregs
> >>   KVM: arm64: nv: Handle traps for timer _EL02 and _EL2 sysregs
> >>     accessors
> >>   KVM: arm64: nv: vgic: Allow userland to set VGIC maintenance IRQ
> >>
> >> Christoffer Dall (16):
> >>   KVM: arm64: nv: Introduce nested virtualization VCPU feature
> >>   KVM: arm64: nv: Reset VCPU to EL2 registers if VCPU nested virt is set
> >>   KVM: arm64: nv: Allow userspace to set PSR_MODE_EL2x
> >>   KVM: arm64: nv: Add nested virt VCPU primitives for vEL2 VCPU state
> >>   KVM: arm64: nv: Handle trapped ERET from virtual EL2
> >>   KVM: arm64: nv: Emulate PSTATE.M for a guest hypervisor
> >>   KVM: arm64: nv: Trap EL1 VM register accesses in virtual EL2
> >>   KVM: arm64: nv: Only toggle cache for virtual EL2 when SCTLR_EL2
> >>     changes
> >>   KVM: arm/arm64: nv: Support multiple nested stage 2 mmu structures
> >>   KVM: arm64: nv: Implement nested Stage-2 page table walk logic
> >>   KVM: arm64: nv: Handle shadow stage 2 page faults
> >>   KVM: arm64: nv: Unmap/flush shadow stage 2 page tables
> >>   KVM: arm64: nv: arch_timer: Support hyp timer emulation
> >>   KVM: arm64: nv: vgic-v3: Take cpu_if pointer directly instead of vcpu
> >>   KVM: arm64: nv: vgic: Emulate the HW bit in software
> >>   KVM: arm64: nv: Add nested GICv3 tracepoints
> >>
> >> Dave Martin (1):
> >>   KVM: arm64: Migrate _elx sysreg accessors to msr_s/mrs_s
> >>
> >> Jintack Lim (21):
> >>   arm64: Add ARM64_HAS_NESTED_VIRT cpufeature
> >>   KVM: arm64: nv: Add EL2 system registers to vcpu context
> >>   KVM: arm64: nv: Support virtual EL2 exceptions
> >>   KVM: arm64: nv: Inject HVC exceptions to the virtual EL2
> >>   KVM: arm64: nv: Trap SPSR_EL1, ELR_EL1 and VBAR_EL1 from virtual EL2
> >>   KVM: arm64: nv: Trap CPACR_EL1 access in virtual EL2
> >>   KVM: arm64: nv: Set a handler for the system instruction traps
> >>   KVM: arm64: nv: Handle PSCI call via smc from the guest
> >>   KVM: arm64: nv: Respect virtual HCR_EL2.TWX setting
> >>   KVM: arm64: nv: Respect virtual CPTR_EL2.TFP setting
> >>   KVM: arm64: nv: Respect the virtual HCR_EL2.NV bit setting
> >>   KVM: arm64: nv: Respect virtual HCR_EL2.TVM and TRVM settings
> >>   KVM: arm64: nv: Respect the virtual HCR_EL2.NV1 bit setting
> >>   KVM: arm64: nv: Emulate EL12 register accesses from the virtual EL2
> >>   KVM: arm64: nv: Configure HCR_EL2 for nested virtualization
> >>   KVM: arm64: nv: Pretend we only support larger-than-host page sizes
> >>   KVM: arm64: nv: Introduce sys_reg_desc.forward_trap
> >>   KVM: arm64: nv: Rework the system instruction emulation framework
> >>   KVM: arm64: nv: Trap and emulate AT instructions from virtual EL2
> >>   KVM: arm64: nv: Trap and emulate TLBI instructions from virtual EL2
> >>   KVM: arm64: nv: Nested GICv3 Support
> >>
> >> Marc Zyngier (17):
> >>   KVM: arm64: Move __load_guest_stage2 to kvm_mmu.h
> >>   KVM: arm64: nv: Reset VMPIDR_EL2 and VPIDR_EL2 to sane values
> >>   KVM: arm64: nv: Handle SPSR_EL2 specially
> >>   KVM: arm64: nv: Refactor vcpu_{read,write}_sys_reg
> >>   KVM: arm64: nv: Don't expose SVE to nested guests
> >>   KVM: arm64: nv: Hide RAS from nested guests
> >>   KVM: arm/arm64: nv: Factor out stage 2 page table data from struct kvm
> >>   KVM: arm64: nv: Move last_vcpu_ran to be per s2 mmu
> >>   KVM: arm64: nv: Don't always start an S2 MMU search from the beginning
> >>   KVM: arm64: nv: Propagate CNTVOFF_EL2 to the virtual EL1 timer
> >>   KVM: arm64: nv: Load timer before the GIC
> >>   KVM: arm64: nv: Implement maintenance interrupt forwarding
> >>   arm64: KVM: nv: Add handling of EL2-specific timer registers
> >>   arm64: KVM: nv: Honor SCTLR_EL2.SPAN on entering vEL2
> >>   arm64: KVM: nv: Handle SCTLR_EL2 RES0/RES1 bits
> >>   arm64: KVM: nv: Restrict S2 RD/WR permissions to match the guest's
> >>   arm64: KVM: nv: Allow userspace to request KVM_ARM_VCPU_NESTED_VIRT
> >>
> >>  .../admin-guide/kernel-parameters.txt         |    4 +
> >>  .../virtual/kvm/devices/arm-vgic-v3.txt       |    9 +
> >>  arch/arm/include/asm/kvm_asm.h                |    5 +-
> >>  arch/arm/include/asm/kvm_emulate.h            |    3 +
> >>  arch/arm/include/asm/kvm_host.h               |   31 +-
> >>  arch/arm/include/asm/kvm_hyp.h                |   25 +-
> >>  arch/arm/include/asm/kvm_mmu.h                |   83 +-
> >>  arch/arm/include/asm/kvm_nested.h             |    9 +
> >>  arch/arm/include/uapi/asm/kvm.h               |    1 +
> >>  arch/arm/kvm/hyp/switch.c                     |   11 +-
> >>  arch/arm/kvm/hyp/tlb.c                        |   13 +-
> >>  arch/arm64/include/asm/cpucaps.h              |    3 +-
> >>  arch/arm64/include/asm/esr.h                  |    4 +-
> >>  arch/arm64/include/asm/kvm_arm.h              |   28 +-
> >>  arch/arm64/include/asm/kvm_asm.h              |    9 +-
> >>  arch/arm64/include/asm/kvm_coproc.h           |    2 +-
> >>  arch/arm64/include/asm/kvm_emulate.h          |  157 +-
> >>  arch/arm64/include/asm/kvm_host.h             |  105 +-
> >>  arch/arm64/include/asm/kvm_hyp.h              |   82 +-
> >>  arch/arm64/include/asm/kvm_mmu.h              |   62 +-
> >>  arch/arm64/include/asm/kvm_nested.h           |   68 +
> >>  arch/arm64/include/asm/sysreg.h               |  143 +-
> >>  arch/arm64/include/uapi/asm/kvm.h             |    2 +
> >>  arch/arm64/kernel/cpufeature.c                |   26 +
> >>  arch/arm64/kvm/Makefile                       |    4 +
> >>  arch/arm64/kvm/emulate-nested.c               |  223 +++
> >>  arch/arm64/kvm/guest.c                        |    6 +
> >>  arch/arm64/kvm/handle_exit.c                  |   76 +-
> >>  arch/arm64/kvm/hyp/Makefile                   |    1 +
> >>  arch/arm64/kvm/hyp/at.c                       |  217 +++
> >>  arch/arm64/kvm/hyp/switch.c                   |   86 +-
> >>  arch/arm64/kvm/hyp/sysreg-sr.c                |  267 ++-
> >>  arch/arm64/kvm/hyp/tlb.c                      |  129 +-
> >>  arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c      |    2 +-
> >>  arch/arm64/kvm/inject_fault.c                 |   12 -
> >>  arch/arm64/kvm/nested.c                       |  551 +++++++
> >>  arch/arm64/kvm/regmap.c                       |    4 +-
> >>  arch/arm64/kvm/reset.c                        |    7 +
> >>  arch/arm64/kvm/sys_regs.c                     | 1460 +++++++++++++++--
> >>  arch/arm64/kvm/sys_regs.h                     |    6 +
> >>  arch/arm64/kvm/trace.h                        |   58 +-
> >>  include/kvm/arm_arch_timer.h                  |    6 +
> >>  include/kvm/arm_vgic.h                        |   28 +-
> >>  virt/kvm/arm/arch_timer.c                     |  158 +-
> >>  virt/kvm/arm/arm.c                            |   62 +-
> >>  virt/kvm/arm/hyp/vgic-v3-sr.c                 |   35 +-
> >>  virt/kvm/arm/mmio.c                           |   12 +-
> >>  virt/kvm/arm/mmu.c                            |  445 +++--
> >>  virt/kvm/arm/trace.h                          |    6 +-
> >>  virt/kvm/arm/vgic/vgic-init.c                 |   30 +
> >>  virt/kvm/arm/vgic/vgic-kvm-device.c           |   22 +
> >>  virt/kvm/arm/vgic/vgic-nested-trace.h         |  137 ++
> >>  virt/kvm/arm/vgic/vgic-v2.c                   |   10 +-
> >>  virt/kvm/arm/vgic/vgic-v3-nested.c            |  236 +++
> >>  virt/kvm/arm/vgic/vgic-v3.c                   |   40 +-
> >>  virt/kvm/arm/vgic/vgic.c                      |   74 +-
> >>  56 files changed, 4683 insertions(+), 612 deletions(-)
> >>  create mode 100644 arch/arm/include/asm/kvm_nested.h
> >>  create mode 100644 arch/arm64/include/asm/kvm_nested.h
> >>  create mode 100644 arch/arm64/kvm/emulate-nested.c
> >>  create mode 100644 arch/arm64/kvm/hyp/at.c
> >>  create mode 100644 arch/arm64/kvm/nested.c
> >>  create mode 100644 virt/kvm/arm/vgic/vgic-nested-trace.h
> >>  create mode 100644 virt/kvm/arm/vgic/vgic-v3-nested.c
> >>
> > When working on adding support for EL2 to kvm-unit-tests I was able to trigger
> > the following warning:
> >
> > # ./lkvm run -f psci.flat -m 128 -c 8 --console serial --irqchip gicv3 --nested
> >   # lkvm run --firmware psci.flat -m 128 -c 8 --name guest-151
> >   Info: Placing fdt at 0x80200000 - 0x80210000
> >   # Warning: The maximum recommended amount of VCPUs is 4
> > chr_testdev_init: chr-testdev: can't find a virtio-console
> > INFO: PSCI version 1.0
> > PASS: invalid-function
> > PASS: affinity-info-on
> > PASS: affinity-info-off
> > [   24.381266] WARNING: CPU: 3 PID: 160 at
> > arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:170
> > kvm_timer_irq_can_fire+0xc/0x30
> > [   24.381366] Modules linked in:
> > [   24.381466] CPU: 3 PID: 160 Comm: kvm-vcpu-1 Not tainted
> > 5.2.0-rc5-00060-g7dbce63bd1c7 #145
> > [   24.381566] Hardware name: Foundation-v8A (DT)
> > [   24.381566] pstate: 40400009 (nZcv daif +PAN -UAO)
> > [   24.381666] pc : kvm_timer_irq_can_fire+0xc/0x30
> > [   24.381766] lr : timer_emulate+0x24/0x98
> > [   24.381766] sp : ffff000013d8b780
> > [   24.381866] x29: ffff000013d8b780 x28: ffff80087a639b80
> > [   24.381966] x27: ffff000010ba8648 x26: ffff000010b71b40
> > [   24.382066] x25: ffff80087a63a100 x24: 0000000000000000
> > [   24.382111] x23: 000080086ca54000 x22: ffff0000100ce260
> > [   24.382166] x21: ffff800875e7c918 x20: ffff800875e7a800
> > [   24.382275] x19: ffff800875e7ca08 x18: 0000000000000000
> > [   24.382366] x17: 0000000000000000 x16: 0000000000000000
> > [   24.382466] x15: 0000000000000000 x14: 0000000000002118
> > [   24.382566] x13: 0000000000002190 x12: 0000000000002280
> > [   24.382566] x11: 0000000000002208 x10: 0000000000000040
> > [   24.382666] x9 : ffff000012dc3b38 x8 : 0000000000000000
> > [   24.382766] x7 : 0000000000000000 x6 : ffff80087ac00248
> > [   24.382866] x5 : 000080086ca54000 x4 : 0000000000002118
> > [   24.382966] x3 : eeeeeeeeeeeeeeef x2 : ffff800875e7c918
> > [   24.383066] x1 : 0000000000000001 x0 : ffff800875e7ca08
> > [   24.383066] Call trace:
> > [   24.383166]  kvm_timer_irq_can_fire+0xc/0x30
> > [   24.383266]  kvm_timer_vcpu_load+0x9c/0x1a0
> > [   24.383366]  kvm_arch_vcpu_load+0xb0/0x1f0
> > [   24.383366]  kvm_sched_in+0x1c/0x28
> > [   24.383466]  finish_task_switch+0xd8/0x1d8
> > [   24.383566]  __schedule+0x248/0x4a0
> > [   24.383666]  preempt_schedule_irq+0x60/0x90
> > [   24.383666]  el1_irq+0xd0/0x180
> > [   24.383766]  kvm_handle_guest_abort+0x0/0x3a0
> > [   24.383866]  kvm_arch_vcpu_ioctl_run+0x41c/0x688
> > [   24.383866]  kvm_vcpu_ioctl+0x4c0/0x838
> > [   24.383966]  do_vfs_ioctl+0xb8/0x878
> > [   24.384077]  ksys_ioctl+0x84/0x90
> > [   24.384166]  __arm64_sys_ioctl+0x18/0x28
> > [   24.384166]  el0_svc_common.constprop.0+0xb0/0x168
> > [   24.384266]  el0_svc_handler+0x28/0x78
> > [   24.384366]  el0_svc+0x8/0xc
> > [   24.384366] ---[ end trace 37a32293e43ac12c ]---
> > [   24.384666] WARNING: CPU: 3 PID: 160 at
> > arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:170
> > kvm_timer_irq_can_fire+0xc/0x30
> > [   24.384766] Modules linked in:
> > [   24.384866] CPU: 3 PID: 160 Comm: kvm-vcpu-1 Tainted: G        W
> > 5.2.0-rc5-00060-g7dbce63bd1c7 #145
> > [   24.384966] Hardware name: Foundation-v8A (DT)
> > [   24.384966] pstate: 40400009 (nZcv daif +PAN -UAO)
> > [   24.385066] pc : kvm_timer_irq_can_fire+0xc/0x30
> > [   24.385166] lr : timer_emulate+0x24/0x98
> > [   24.385166] sp : ffff000013d8b780
> > [   24.385266] x29: ffff000013d8b780 x28: ffff80087a639b80
> > [   24.385366] x27: ffff000010ba8648 x26: ffff000010b71b40
> > [   24.385466] x25: ffff80087a63a100 x24: 0000000000000000
> > [   24.385466] x23: 000080086ca54000 x22: ffff0000100ce260
> > [   24.385566] x21: ffff800875e7c918 x20: ffff800875e7a800
> > [   24.385666] x19: ffff800875e7ca80 x18: 0000000000000000
> > [   24.385766] x17: 0000000000000000 x16: 0000000000000000
> > [   24.385866] x15: 0000000000000000 x14: 0000000000002118
> > [   24.385966] x13: 0000000000002190 x12: 0000000000002280
> > [   24.385966] x11: 0000000000002208 x10: 0000000000000040
> > [   24.386066] x9 : ffff000012dc3b38 x8 : 0000000000000000
> > [   24.386166] x7 : 0000000000000000 x6 : ffff80087ac00248
> > [   24.386266] x5 : 000080086ca54000 x4 : 0000000000002118
> > [   24.386366] x3 : eeeeeeeeeeeeeeef x2 : ffff800875e7c918
> > [   24.386466] x1 : 0000000000000001 x0 : ffff800875e7ca80
> > [   24.386466] Call trace:
> > [   24.386566]  kvm_timer_irq_can_fire+0xc/0x30
> > [   24.386666]  kvm_timer_vcpu_load+0xa8/0x1a0
> > [   24.386666]  kvm_arch_vcpu_load+0xb0/0x1f0
> > [   24.386898]  kvm_sched_in+0x1c/0x28
> > [   24.386966]  finish_task_switch+0xd8/0x1d8
> > [   24.387166]  __schedule+0x248/0x4a0
> > [   24.387354]  preempt_schedule_irq+0x60/0x90
> > [   24.387366]  el1_irq+0xd0/0x180
> > [   24.387466]  kvm_handle_guest_abort+0x0/0x3a0
> > [   24.387566]  kvm_arch_vcpu_ioctl_run+0x41c/0x688
> > [   24.387566]  kvm_vcpu_ioctl+0x4c0/0x838
> > [   24.387666]  do_vfs_ioctl+0xb8/0x878
> > [   24.387766]  ksys_ioctl+0x84/0x90
> > [   24.387866]  __arm64_sys_ioctl+0x18/0x28
> > [   24.387866]  el0_svc_common.constprop.0+0xb0/0x168
> > [   24.387966]  el0_svc_handler+0x28/0x78
> > [   24.388066]  el0_svc+0x8/0xc
> > [   24.388066] ---[ end trace 37a32293e43ac12d ]---
> > PASS: cpu-on
> > SUMMARY: 4 te[   24.390266] WARNING: CPU: 3 PID: 160 at
> > arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:170
> > kvm_timer_irq_can_fire+0xc/0x30
> > s[   24.390366] Modules linked in:
> > ts[   24.390366] CPU: 3 PID: 160 Comm: kvm-vcpu-1 Tainted: G        W
> > 5.2.0-rc5-00060-g7dbce63bd1c7 #145
> > [   24.390566] Hardware name: Foundation-v8A (DT)
> >
> > [   24.390795] pstate: 40400009 (nZcv daif +PAN -UAO)
> > [   24.390866] pc : kvm_timer_irq_can_fire+0xc/0x30
> > [   24.390966] lr : timer_emulate+0x24/0x98
> > [   24.391066] sp : ffff000013d8b780
> > [   24.391066] x29: ffff000013d8b780 x28: ffff80087a639b80
> > [   24.391166] x27: ffff000010ba8648 x26: ffff000010b71b40
> > [   24.391266] x25: ffff80087a63a100 x24: 0000000000000000
> > [   24.391366] x23: 000080086ca54000 x22: 0000000000000003
> > [   24.391466] x21: ffff800875e7c918 x20: ffff800875e7a800
> > [   24.391466] x19: ffff800875e7ca08 x18: 0000000000000000
> > [   24.391566] x17: 0000000000000000 x16: 0000000000000000
> > [   24.391666] x15: 0000000000000000 x14: 0000000000002118
> > [   24.391766] x13: 0000000000002190 x12: 0000000000002280
> > [   24.391866] x11: 0000000000002208 x10: 0000000000000040
> > [   24.391942] x9 : ffff000012dc3b38 x8 : 0000000000000000
> > [   24.391966] x7 : 0000000000000000 x6 : ffff80087ac00248
> > [   24.392066] x5 : 000080086ca54000 x4 : 0000000000002118
> > [   24.392166] x3 : eeeeeeeeeeeeeeef x2 : ffff800875e7c918
> > [   24.392269] x1 : 0000000000000001 x0 : ffff800875e7ca08
> > [   24.392366] Call trace:
> > [   24.392433]  kvm_timer_irq_can_fire+0xc/0x30
> > [   24.392466]  kvm_timer_vcpu_load+0x9c/0x1a0
> > [   24.392597]  kvm_arch_vcpu_load+0xb0/0x1f0
> > [   24.392666]  kvm_sched_in+0x1c/0x28
> > [   24.392766]  finish_task_switch+0xd8/0x1d8
> > [   24.392766]  __schedule+0x248/0x4a0
> > [   24.392866]  preempt_schedule_irq+0x60/0x90
> > [   24.392966]  el1_irq+0xd0/0x180
> > [   24.392966]  kvm_handle_guest_abort+0x0/0x3a0
> > [   24.393066]  kvm_arch_vcpu_ioctl_run+0x41c/0x688
> > [   24.393166]  kvm_vcpu_ioctl+0x4c0/0x838
> > [   24.393266]  do_vfs_ioctl+0xb8/0x878
> > [   24.393266]  ksys_ioctl+0x84/0x90
> > [   24.393366]  __arm64_sys_ioctl+0x18/0x28
> > [   24.393466]  el0_svc_common.constprop.0+0xb0/0x168
> > [   24.393566]  el0_svc_handler+0x28/0x78
> > [   24.393566]  el0_svc+0x8/0xc
> > [   24.393666] ---[ end trace 37a32293e43ac12e ]---
> > [   24.393866] WARNING: CPU: 3 PID: 160 at
> > arch/arm64/kvm/../../../virt/kvm/arm/arch_timer.c:170
> > kvm_timer_irq_can_fire+0xc/0x30
> > [   24.394066] Modules linked in:
> > [   24.394266] CPU: 3 PID: 160 Comm: kvm-vcpu-1 Tainted: G        W
> > 5.2.0-rc5-00060-g7dbce63bd1c7 #145
> > [   24.394366] Hardware name: Foundation-v8A (DT)
> > [   24.394466] pstate: 40400009 (nZcv daif +PAN -UAO)
> > [   24.394466] pc : kvm_timer_irq_can_fire+0xc/0x30
> > [   24.394566] lr : timer_emulate+0x24/0x98
> > [   24.394666] sp : ffff000013d8b780
> > [   24.394727] x29: ffff000013d8b780 x28: ffff80087a639b80
> > [   24.394766] x27: ffff000010ba8648 x26: ffff000010b71b40
> > [   24.394866] x25: ffff80087a63a100 x24: 0000000000000000
> > [   24.394966] x23: 000080086ca54000 x22: 0000000000000003
> > [   24.394966] x21: ffff800875e7c918 x20: ffff800875e7a800
> > [   24.395066] x19: ffff800875e7ca80 x18: 0000000000000000
> > [   24.395166] x17: 0000000000000000 x16: 0000000000000000
> > [   24.395266] x15: 0000000000000000 x14: 0000000000002118
> > [   24.395383] x13: 0000000000002190 x12: 0000000000002280
> > [   24.395466] x11: 0000000000002208 x10: 0000000000000040
> > [   24.395547] x9 : ffff000012dc3b38 x8 : 0000000000000000
> > [   24.395666] x7 : 0000000000000000 x6 : ffff80087ac00248
> > [   24.395866] x5 : 000080086ca54000 x4 : 0000000000002118
> > [   24.395966] x3 : eeeeeeeeeeeeeeef x2 : ffff800875e7c918
> > [   24.396066] x1 : 0000000000000001 x0 : ffff800875e7ca80
> > [   24.396066] Call trace:
> > [   24.396166]  kvm_timer_irq_can_fire+0xc/0x30
> > [   24.396266]  kvm_timer_vcpu_load+0xa8/0x1a0
> > [   24.396366]  kvm_arch_vcpu_load+0xb0/0x1f0
> > [   24.396366]  kvm_sched_in+0x1c/0x28
> > [   24.396466]  finish_task_switch+0xd8/0x1d8
> > [   24.396566]  __schedule+0x248/0x4a0
> > [   24.396666]  preempt_schedule_irq+0x60/0x90
> > [   24.396666]  el1_irq+0xd0/0x180
> > [   24.396766]  kvm_handle_guest_abort+0x0/0x3a0
> > [   24.396866]  kvm_arch_vcpu_ioctl_run+0x41c/0x688
> > [   24.396866]  kvm_vcpu_ioctl+0x4c0/0x838
> > [   24.397021]  do_vfs_ioctl+0xb8/0x878
> > [   24.397066]  ksys_ioctl+0x84/0x90
> > [   24.397166]  __arm64_sys_ioctl+0x18/0x28
> > [   24.397348]  el0_svc_common.constprop.0+0xb0/0x168
> > [   24.397366]  el0_svc_handler+0x28/0x78
> > [   24.397566]  el0_svc+0x8/0xc
> > [   24.397676] ---[ end trace 37a32293e43ac12f ]---
> >
> >   # KVM compatibility warning.
> >     virtio-9p device was not detected.
> >     While you have requested a virtio-9p device, the guest kernel did not
> > initialize it.
> >     Please make sure that the guest kernel was compiled with
> > CONFIG_NET_9P_VIRTIO=y enabled in .config.
> >
> >   # KVM compatibility warning.
> >     virtio-net device was not detected.
> >     While you have requested a virtio-net device, the guest kernel did not
> > initialize it.
> >     Please make sure that the guest kernel was compiled with CONFIG_VIRTIO_NET=y
> > enabled in .config.
> >
> > [..]
> 
> Did some investigating and this was caused by a bug in kvm-unit-tests (the fix
> for it will be part of the EL2 patches for kvm-unit-tests). The guest was trying
> to fetch an instruction from address 0x200, which KVM interprets as a prefetch
> abort on an I/O address and ends up calling kvm_inject_pabt. The code from
> arch/arm64/kvm/inject_fault.c doesn't know anything about nested virtualization,
> and it sets the VCPU mode directly to PSR_MODE_EL1h. This makes_hyp_ctxt return
> false, and get_timer_map will return an incorrect mapping.
> 
> On next kvm_timer_vcpu_put, the direct timers will be {p,v}timer, and
> h{p,v}timer->loaded will not be set to false. In the corresponding call to
> kvm_timer_vcpu_load, KVM will try to emulate the hptimer and hvtimer, which
> still have loaded = true. And this causes the warning I saw.
>

Hi Alexandru,

While a unit test in kvm-unit-tests may not do what it should in order to
exercise the code it's targeting appropriately, and therefore need to be
fixed in order to do that, I'd argue that if a guest can induce a host
warning then that's a host bug. Indeed now that you've analyzed the
issue you could write a kvm-unit-tests test to specifically reproduce the
warning and then use that test to test any host fix candidates.

Thanks,
drew


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [RFC V2 0/1] mm/debug: Add tests for architecture exported page table helpers
From: Mark Rutland @ 2019-08-09 11:44 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: linux-ia64, linux-sh, Tetsuo Handa, James Hogan, Heiko Carstens,
	Michal Hocko, linux-mm, Paul Mackerras, sparclinux,
	Thomas Gleixner, linux-s390, Michael Ellerman, x86,
	Russell King - ARM Linux, Steven Price, Jason Gunthorpe,
	linux-arm-kernel, linux-snps-arc, Kees Cook, Anshuman Khandual,
	Masahiro Yamada, Mark Brown, Dan Williams, Vlastimil Babka,
	Sri Krishna chowdary, Ard Biesheuvel, Greg Kroah-Hartman,
	Dave Hansen, linux-mips, Ralf Baechle, linux-kernel,
	Peter Zijlstra, Mike Rapoport, Paul Burton, Vineet Gupta,
	Martin Schwidefsky, Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20190809101632.GM5482@bombadil.infradead.org>

On Fri, Aug 09, 2019 at 03:16:33AM -0700, Matthew Wilcox wrote:
> On Fri, Aug 09, 2019 at 01:03:17PM +0530, Anshuman Khandual wrote:
> > Should alloc_gigantic_page() be made available as an interface for general
> > use in the kernel. The test module here uses very similar implementation from
> > HugeTLB to allocate a PUD aligned memory block. Similar for mm_alloc() which
> > needs to be exported through a header.
> 
> Why are you allocating memory at all instead of just using some
> known-to-exist PFNs like I suggested?

IIUC the issue is that there aren't necessarily known-to-exist PFNs that
are sufficiently aligned -- they may not even exist.

For example, with 64K pages, a PMD covers 512M. The kernel image is
(generally) smaller than 512M, and will be mapped at page granularity.
In that case, any PMD entry for a kernel symbol address will point to
the PTE level table, and that will only necessarily be page-aligned, as
any P?D level table is only necessarily page-aligned.

In the same configuration, you could have less than 512M of total
memory, and none of this memory is necessarily aligned to 512M. So
beyond the PTE level, I don't think you can guarantee a known-to-exist
valid PFN.

I also believe that synthetic PFNs could fail pfn_valid(), so that might
cause us pain too...

Thanks,
Mark.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 02/22] ARM: omap1: make omapfb standalone compilable
From: Arnd Bergmann @ 2019-08-09 11:43 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: Aaro Koskinen, Tony Lindgren, Greg Kroah-Hartman, Linus Walleij,
	Linux Kernel Mailing List, dri-devel, Tomi Valkeinen, linux-omap,
	Linux ARM
In-Reply-To: <55c9608d-68c4-17f6-2682-7668d5d7720a@samsung.com>

On Fri, Aug 9, 2019 at 1:32 PM Bartlomiej Zolnierkiewicz
<b.zolnierkie@samsung.com> wrote:
> On 8/8/19 11:22 PM, Arnd Bergmann wrote:
> > The omapfb driver is split into platform specific code for omap1, and
> > driver code that is also specific to omap1.
> >
> > Moving both parts into the driver directory simplifies the structure
> > and avoids the dependency on certain omap machine header files.
> >
> > The interrupt numbers in particular however must not be referenced
> > directly from the driver to allow building in a multiplatform
> > configuration, so these have to be passed through resources, is
> > done for all other omap drivers.
> >
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>
> For fbdev part:
>
> Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Thanks for taking a look.

> [ It seems that adding of static inline for omap_set_dma_priority()
>   when ARCH_OMAP=n should be in patch #9 but this is a minor issue. ]

That would have been ok as well, but having the addition here was
intentional and seems more logical to me as this is where the headers
get moved around.

      Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v3 20/41] fbdev/pvr2fb: convert put_page() to put_user_page*()
From: Bartlomiej Zolnierkiewicz @ 2019-08-09 11:38 UTC (permalink / raw)
  To: john.hubbard
  Cc: linux-fbdev, Jan Kara, kvm, Dave Hansen, Dave Chinner, dri-devel,
	linux-mm, sparclinux, Ira Weiny, Dan Williams, devel, rds-devel,
	linux-rdma, x86, amd-gfx, Christoph Hellwig, Jason Gunthorpe,
	xen-devel, devel, linux-media, Kees Cook, John Hubbard, intel-gfx,
	linux-block, Jérôme Glisse, linux-rpi-kernel,
	Arvind Yadav, ceph-devel, linux-arm-kernel, linux-nfs, netdev,
	LKML, linux-xfs, linux-crypto, linux-fsdevel, Andrew Morton,
	Bhumika Goyal, Al Viro
In-Reply-To: <20190807013340.9706-21-jhubbard@nvidia.com>


On 8/7/19 3:33 AM, john.hubbard@gmail.com wrote:
> From: John Hubbard <jhubbard@nvidia.com>
> 
> For pages that were retained via get_user_pages*(), release those pages
> via the new put_user_page*() routines, instead of via put_page() or
> release_pages().
> 
> This is part a tree-wide conversion, as described in commit fc1d8e7cca2d
> ("mm: introduce put_user_page*(), placeholder versions").
> 
> Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Al Viro <viro@zeniv.linux.org.uk>
> Cc: Bhumika Goyal <bhumirks@gmail.com>
> Cc: Arvind Yadav <arvind.yadav.cs@gmail.com>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-fbdev@vger.kernel.org
> Signed-off-by: John Hubbard <jhubbard@nvidia.com>

Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> ---
>  drivers/video/fbdev/pvr2fb.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
> index 7ff4b6b84282..0e4f9aa6444d 100644
> --- a/drivers/video/fbdev/pvr2fb.c
> +++ b/drivers/video/fbdev/pvr2fb.c
> @@ -700,8 +700,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
>  	ret = count;
>  
>  out_unmap:
> -	for (i = 0; i < nr_pages; i++)
> -		put_page(pages[i]);
> +	put_user_pages(pages, nr_pages);
>  
>  	kfree(pages);

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 09/22] fbdev: omap: avoid using mach/*.h files
From: Bartlomiej Zolnierkiewicz @ 2019-08-09 11:34 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Daniel Thompson, Aaro Koskinen, Tony Lindgren, Jingoo Han,
	Linus Walleij, linux-fbdev, dri-devel, linux-kernel,
	Tomi Valkeinen, Greg Kroah-Hartman, linux-omap, Lee Jones,
	linux-arm-kernel
In-Reply-To: <20190808212234.2213262-10-arnd@arndb.de>


On 8/8/19 11:22 PM, Arnd Bergmann wrote:
> All the headers we actually need are now in include/linux/soc,
> so use those versions instead and allow compile-testing on
> other architectures.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

For fbdev part:

Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> ---
>  drivers/video/backlight/Kconfig          | 4 ++--
>  drivers/video/backlight/omap1_bl.c       | 4 ++--
>  drivers/video/fbdev/omap/Kconfig         | 4 ++--
>  drivers/video/fbdev/omap/lcd_ams_delta.c | 2 +-
>  drivers/video/fbdev/omap/lcd_dma.c       | 3 ++-
>  drivers/video/fbdev/omap/lcd_inn1510.c   | 2 +-
>  drivers/video/fbdev/omap/lcd_osk.c       | 4 ++--
>  drivers/video/fbdev/omap/lcdc.c          | 2 ++
>  drivers/video/fbdev/omap/omapfb_main.c   | 3 +--
>  drivers/video/fbdev/omap/sossi.c         | 1 +
>  10 files changed, 16 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
> index 8b081d61773e..195c71130827 100644
> --- a/drivers/video/backlight/Kconfig
> +++ b/drivers/video/backlight/Kconfig
> @@ -213,8 +213,8 @@ config BACKLIGHT_LOCOMO
>  
>  config BACKLIGHT_OMAP1
>  	tristate "OMAP1 PWL-based LCD Backlight"
> -	depends on ARCH_OMAP1
> -	default y
> +	depends on ARCH_OMAP1 || COMPILE_TEST
> +	default ARCH_OMAP1
>  	help
>  	  This driver controls the LCD backlight level and power for
>  	  the PWL module of OMAP1 processors.  Say Y if your board
> diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
> index 74263021b1b3..69a49384b3de 100644
> --- a/drivers/video/backlight/omap1_bl.c
> +++ b/drivers/video/backlight/omap1_bl.c
> @@ -14,8 +14,8 @@
>  #include <linux/slab.h>
>  #include <linux/platform_data/omap1_bl.h>
>  
> -#include <mach/hardware.h>
> -#include <mach/mux.h>
> +#include <linux/soc/ti/omap1-io.h>
> +#include <linux/soc/ti/omap1-mux.h>
>  
>  #define OMAPBL_MAX_INTENSITY		0xff
>  
> diff --git a/drivers/video/fbdev/omap/Kconfig b/drivers/video/fbdev/omap/Kconfig
> index df2a5d0d4aa2..b1786cf1b486 100644
> --- a/drivers/video/fbdev/omap/Kconfig
> +++ b/drivers/video/fbdev/omap/Kconfig
> @@ -2,7 +2,7 @@
>  config FB_OMAP
>  	tristate "OMAP frame buffer support"
>  	depends on FB
> -	depends on ARCH_OMAP1
> +	depends on ARCH_OMAP1 || (ARM && COMPILE_TEST)
>  	select FB_CFB_FILLRECT
>  	select FB_CFB_COPYAREA
>  	select FB_CFB_IMAGEBLIT
> @@ -42,7 +42,7 @@ config FB_OMAP_LCD_MIPID
>  
>  config FB_OMAP_LCD_H3
>  	bool "TPS65010 LCD controller on OMAP-H3"
> -	depends on MACH_OMAP_H3
> +	depends on MACH_OMAP_H3 || COMPILE_TEST
>  	depends on TPS65010=y
>  	default y
>  	help
> diff --git a/drivers/video/fbdev/omap/lcd_ams_delta.c b/drivers/video/fbdev/omap/lcd_ams_delta.c
> index 8e54aae544a0..da2e32615abe 100644
> --- a/drivers/video/fbdev/omap/lcd_ams_delta.c
> +++ b/drivers/video/fbdev/omap/lcd_ams_delta.c
> @@ -14,7 +14,7 @@
>  #include <linux/gpio/consumer.h>
>  #include <linux/lcd.h>
>  
> -#include <mach/hardware.h>
> +#include <linux/soc/ti/omap1-io.h>
>  
>  #include "omapfb.h"
>  
> diff --git a/drivers/video/fbdev/omap/lcd_dma.c b/drivers/video/fbdev/omap/lcd_dma.c
> index 867a63c06f42..f85817635a8c 100644
> --- a/drivers/video/fbdev/omap/lcd_dma.c
> +++ b/drivers/video/fbdev/omap/lcd_dma.c
> @@ -25,7 +25,8 @@
>  
>  #include <linux/omap-dma.h>
>  
> -#include <mach/hardware.h>
> +#include <linux/soc/ti/omap1-soc.h>
> +#include <linux/soc/ti/omap1-io.h>
>  
>  #include "lcdc.h"
>  #include "lcd_dma.h"
> diff --git a/drivers/video/fbdev/omap/lcd_inn1510.c b/drivers/video/fbdev/omap/lcd_inn1510.c
> index 37ed0c14aa5a..bb915637e9b6 100644
> --- a/drivers/video/fbdev/omap/lcd_inn1510.c
> +++ b/drivers/video/fbdev/omap/lcd_inn1510.c
> @@ -10,7 +10,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/io.h>
>  
> -#include <mach/hardware.h>
> +#include <linux/soc/ti/omap1-soc.h>
>  
>  #include "omapfb.h"
>  
> diff --git a/drivers/video/fbdev/omap/lcd_osk.c b/drivers/video/fbdev/omap/lcd_osk.c
> index 5d5762128c8d..8168ba0d47fd 100644
> --- a/drivers/video/fbdev/omap/lcd_osk.c
> +++ b/drivers/video/fbdev/omap/lcd_osk.c
> @@ -11,8 +11,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/gpio.h>
>  
> -#include <mach/hardware.h>
> -#include <mach/mux.h>
> +#include <linux/soc/ti/omap1-io.h>
> +#include <linux/soc/ti/omap1-mux.h>
>  
>  #include "omapfb.h"
>  
> diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c
> index 65953b7fbdb9..3af758f12afd 100644
> --- a/drivers/video/fbdev/omap/lcdc.c
> +++ b/drivers/video/fbdev/omap/lcdc.c
> @@ -17,6 +17,8 @@
>  #include <linux/clk.h>
>  #include <linux/gfp.h>
>  
> +#include <linux/soc/ti/omap1-io.h>
> +#include <linux/soc/ti/omap1-soc.h>
>  #include <linux/omap-dma.h>
>  
>  #include <asm/mach-types.h>
> diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
> index dc06057de91d..af73a3f9ac53 100644
> --- a/drivers/video/fbdev/omap/omapfb_main.c
> +++ b/drivers/video/fbdev/omap/omapfb_main.c
> @@ -19,8 +19,7 @@
>  
>  #include <linux/omap-dma.h>
>  
> -#include <mach/hardware.h>
> -
> +#include <linux/soc/ti/omap1-soc.h>
>  #include "omapfb.h"
>  #include "lcdc.h"
>  
> diff --git a/drivers/video/fbdev/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c
> index ade9d452254c..6b99d89fbe6e 100644
> --- a/drivers/video/fbdev/omap/sossi.c
> +++ b/drivers/video/fbdev/omap/sossi.c
> @@ -13,6 +13,7 @@
>  #include <linux/interrupt.h>
>  
>  #include <linux/omap-dma.h>
> +#include <linux/soc/ti/omap1-io.h>
>  
>  #include "omapfb.h"
>  #include "lcd_dma.h"

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 02/22] ARM: omap1: make omapfb standalone compilable
From: Bartlomiej Zolnierkiewicz @ 2019-08-09 11:32 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Aaro Koskinen, Tony Lindgren, Greg Kroah-Hartman, Linus Walleij,
	linux-kernel, dri-devel, Tomi Valkeinen, linux-omap,
	linux-arm-kernel
In-Reply-To: <20190808212234.2213262-3-arnd@arndb.de>


On 8/8/19 11:22 PM, Arnd Bergmann wrote:
> The omapfb driver is split into platform specific code for omap1, and
> driver code that is also specific to omap1.
> 
> Moving both parts into the driver directory simplifies the structure
> and avoids the dependency on certain omap machine header files.
> 
> The interrupt numbers in particular however must not be referenced
> directly from the driver to allow building in a multiplatform
> configuration, so these have to be passed through resources, is
> done for all other omap drivers.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

For fbdev part:

Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

[ It seems that adding of static inline for omap_set_dma_priority()
  when ARCH_OMAP=n should be in patch #9 but this is a minor issue. ]

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> ---
>  arch/arm/mach-omap1/Makefile                  |  4 --
>  arch/arm/mach-omap1/fb.c                      | 19 +++++++-
>  arch/arm/mach-omap1/include/mach/lcdc.h       | 44 -------------------
>  drivers/video/fbdev/Makefile                  |  2 +-
>  drivers/video/fbdev/omap/Makefile             |  5 +++
>  .../video/fbdev/omap}/lcd_dma.c               |  4 +-
>  .../video/fbdev/omap}/lcd_dma.h               |  2 -
>  drivers/video/fbdev/omap/lcdc.c               |  8 ++--
>  drivers/video/fbdev/omap/lcdc.h               | 35 +++++++++++++++
>  drivers/video/fbdev/omap/omapfb.h             |  2 +
>  drivers/video/fbdev/omap/omapfb_main.c        | 16 ++++++-
>  drivers/video/fbdev/omap/sossi.c              |  3 +-
>  include/linux/omap-dma.h                      |  7 ++-
>  13 files changed, 90 insertions(+), 61 deletions(-)
>  delete mode 100644 arch/arm/mach-omap1/include/mach/lcdc.h
>  rename {arch/arm/mach-omap1 => drivers/video/fbdev/omap}/lcd_dma.c (99%)
>  rename {arch/arm/mach-omap1/include/mach => drivers/video/fbdev/omap}/lcd_dma.h (98%)
> 
> diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
> index c757a52d0801..450bbf552b57 100644
> --- a/arch/arm/mach-omap1/Makefile
> +++ b/arch/arm/mach-omap1/Makefile
> @@ -57,7 +57,3 @@ obj-$(CONFIG_ARCH_OMAP730)		+= gpio7xx.o
>  obj-$(CONFIG_ARCH_OMAP850)		+= gpio7xx.o
>  obj-$(CONFIG_ARCH_OMAP15XX)		+= gpio15xx.o
>  obj-$(CONFIG_ARCH_OMAP16XX)		+= gpio16xx.o
> -
> -ifneq ($(CONFIG_FB_OMAP),)
> -obj-y += lcd_dma.o
> -endif
> diff --git a/arch/arm/mach-omap1/fb.c b/arch/arm/mach-omap1/fb.c
> index 0e32a959f254..b093375afc27 100644
> --- a/arch/arm/mach-omap1/fb.c
> +++ b/arch/arm/mach-omap1/fb.c
> @@ -17,9 +17,12 @@
>  #include <linux/io.h>
>  #include <linux/omapfb.h>
>  #include <linux/dma-mapping.h>
> +#include <linux/irq.h>
>  
>  #include <asm/mach/map.h>
>  
> +#include <mach/irqs.h>
> +
>  #if IS_ENABLED(CONFIG_FB_OMAP)
>  
>  static bool omapfb_lcd_configured;
> @@ -27,6 +30,19 @@ static struct omapfb_platform_data omapfb_config;
>  
>  static u64 omap_fb_dma_mask = ~(u32)0;
>  
> +struct resource omap_fb_resources[] = {
> +	{
> +		.name  = "irq",
> +		.start = INT_LCD_CTRL,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +	{
> +		.name  = "irq",
> +		.start = INT_SOSSI_MATCH,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
>  static struct platform_device omap_fb_device = {
>  	.name		= "omapfb",
>  	.id		= -1,
> @@ -35,7 +51,8 @@ static struct platform_device omap_fb_device = {
>  		.coherent_dma_mask	= DMA_BIT_MASK(32),
>  		.platform_data		= &omapfb_config,
>  	},
> -	.num_resources = 0,
> +	.num_resources = ARRAY_SIZE(omap_fb_resources),
> +	.resource = omap_fb_resources,
>  };
>  
>  void __init omapfb_set_lcd_config(const struct omap_lcd_config *config)
> diff --git a/arch/arm/mach-omap1/include/mach/lcdc.h b/arch/arm/mach-omap1/include/mach/lcdc.h
> deleted file mode 100644
> index 7152db1f5361..000000000000
> --- a/arch/arm/mach-omap1/include/mach/lcdc.h
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-or-later */
> -/*
> - * arch/arm/mach-omap1/include/mach/lcdc.h
> - *
> - * Extracted from drivers/video/omap/lcdc.c
> - * Copyright (C) 2004 Nokia Corporation
> - * Author: Imre Deak <imre.deak@nokia.com>
> - */
> -#ifndef __MACH_LCDC_H__
> -#define __MACH_LCDC_H__
> -
> -#define OMAP_LCDC_BASE			0xfffec000
> -#define OMAP_LCDC_SIZE			256
> -#define OMAP_LCDC_IRQ			INT_LCD_CTRL
> -
> -#define OMAP_LCDC_CONTROL		(OMAP_LCDC_BASE + 0x00)
> -#define OMAP_LCDC_TIMING0		(OMAP_LCDC_BASE + 0x04)
> -#define OMAP_LCDC_TIMING1		(OMAP_LCDC_BASE + 0x08)
> -#define OMAP_LCDC_TIMING2		(OMAP_LCDC_BASE + 0x0c)
> -#define OMAP_LCDC_STATUS		(OMAP_LCDC_BASE + 0x10)
> -#define OMAP_LCDC_SUBPANEL		(OMAP_LCDC_BASE + 0x14)
> -#define OMAP_LCDC_LINE_INT		(OMAP_LCDC_BASE + 0x18)
> -#define OMAP_LCDC_DISPLAY_STATUS	(OMAP_LCDC_BASE + 0x1c)
> -
> -#define OMAP_LCDC_STAT_DONE		(1 << 0)
> -#define OMAP_LCDC_STAT_VSYNC		(1 << 1)
> -#define OMAP_LCDC_STAT_SYNC_LOST	(1 << 2)
> -#define OMAP_LCDC_STAT_ABC		(1 << 3)
> -#define OMAP_LCDC_STAT_LINE_INT		(1 << 4)
> -#define OMAP_LCDC_STAT_FUF		(1 << 5)
> -#define OMAP_LCDC_STAT_LOADED_PALETTE	(1 << 6)
> -
> -#define OMAP_LCDC_CTRL_LCD_EN		(1 << 0)
> -#define OMAP_LCDC_CTRL_LCD_TFT		(1 << 7)
> -#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL	(1 << 10)
> -
> -#define OMAP_LCDC_IRQ_VSYNC		(1 << 2)
> -#define OMAP_LCDC_IRQ_DONE		(1 << 3)
> -#define OMAP_LCDC_IRQ_LOADED_PALETTE	(1 << 4)
> -#define OMAP_LCDC_IRQ_LINE_NIRQ		(1 << 5)
> -#define OMAP_LCDC_IRQ_LINE		(1 << 6)
> -#define OMAP_LCDC_IRQ_MASK		(((1 << 5) - 1) << 2)
> -
> -#endif /* __MACH_LCDC_H__ */
> diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
> index aab7155884ea..3324301e4c36 100644
> --- a/drivers/video/fbdev/Makefile
> +++ b/drivers/video/fbdev/Makefile
> @@ -111,7 +111,7 @@ obj-$(CONFIG_FB_UDL)		  += udlfb.o
>  obj-$(CONFIG_FB_SMSCUFX)	  += smscufx.o
>  obj-$(CONFIG_FB_XILINX)           += xilinxfb.o
>  obj-$(CONFIG_FB_SH_MOBILE_LCDC)	  += sh_mobile_lcdcfb.o
> -obj-$(CONFIG_FB_OMAP)             += omap/
> +obj-y				  += omap/
>  obj-y                             += omap2/
>  obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
>  obj-$(CONFIG_FB_CARMINE)          += carminefb.o
> diff --git a/drivers/video/fbdev/omap/Makefile b/drivers/video/fbdev/omap/Makefile
> index daaa73a94e7f..b88e02f5cb1f 100644
> --- a/drivers/video/fbdev/omap/Makefile
> +++ b/drivers/video/fbdev/omap/Makefile
> @@ -5,6 +5,11 @@
>  
>  obj-$(CONFIG_FB_OMAP) += omapfb.o
>  
> +ifdef CONFIG_FB_OMAP
> +# must be built-in
> +obj-y += lcd_dma.o
> +endif
> +
>  objs-yy := omapfb_main.o lcdc.o
>  
>  objs-y$(CONFIG_FB_OMAP_LCDC_EXTERNAL) += sossi.o
> diff --git a/arch/arm/mach-omap1/lcd_dma.c b/drivers/video/fbdev/omap/lcd_dma.c
> similarity index 99%
> rename from arch/arm/mach-omap1/lcd_dma.c
> rename to drivers/video/fbdev/omap/lcd_dma.c
> index a72ac0c02b4f..867a63c06f42 100644
> --- a/arch/arm/mach-omap1/lcd_dma.c
> +++ b/drivers/video/fbdev/omap/lcd_dma.c
> @@ -26,7 +26,9 @@
>  #include <linux/omap-dma.h>
>  
>  #include <mach/hardware.h>
> -#include <mach/lcdc.h>
> +
> +#include "lcdc.h"
> +#include "lcd_dma.h"
>  
>  int omap_lcd_dma_running(void)
>  {
> diff --git a/arch/arm/mach-omap1/include/mach/lcd_dma.h b/drivers/video/fbdev/omap/lcd_dma.h
> similarity index 98%
> rename from arch/arm/mach-omap1/include/mach/lcd_dma.h
> rename to drivers/video/fbdev/omap/lcd_dma.h
> index 1a3c0cf17899..1b4780197381 100644
> --- a/arch/arm/mach-omap1/include/mach/lcd_dma.h
> +++ b/drivers/video/fbdev/omap/lcd_dma.h
> @@ -60,6 +60,4 @@ extern void omap_set_lcd_dma_b1_vxres(unsigned long vxres);
>  extern void omap_set_lcd_dma_b1_mirror(int mirror);
>  extern void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale);
>  
> -extern int omap_lcd_dma_running(void);
> -
>  #endif /* __MACH_OMAP1_LCD_DMA_H__ */
> diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c
> index fa73acfc1371..65953b7fbdb9 100644
> --- a/drivers/video/fbdev/omap/lcdc.c
> +++ b/drivers/video/fbdev/omap/lcdc.c
> @@ -17,7 +17,6 @@
>  #include <linux/clk.h>
>  #include <linux/gfp.h>
>  
> -#include <mach/lcdc.h>
>  #include <linux/omap-dma.h>
>  
>  #include <asm/mach-types.h>
> @@ -25,6 +24,7 @@
>  #include "omapfb.h"
>  
>  #include "lcdc.h"
> +#include "lcd_dma.h"
>  
>  #define MODULE_NAME			"lcdc"
>  
> @@ -713,7 +713,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
>  	}
>  	clk_enable(lcdc.lcd_ck);
>  
> -	r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
> +	r = request_irq(fbdev->int_irq, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
>  	if (r) {
>  		dev_err(fbdev->dev, "unable to get IRQ\n");
>  		goto fail2;
> @@ -744,7 +744,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
>  fail4:
>  	omap_free_lcd_dma();
>  fail3:
> -	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
> +	free_irq(fbdev->int_irq, lcdc.fbdev);
>  fail2:
>  	clk_disable(lcdc.lcd_ck);
>  fail1:
> @@ -759,7 +759,7 @@ static void omap_lcdc_cleanup(void)
>  		free_palette_ram();
>  	free_fbmem();
>  	omap_free_lcd_dma();
> -	free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
> +	free_irq(lcdc.fbdev->int_irq, lcdc.fbdev);
>  	clk_disable(lcdc.lcd_ck);
>  	clk_put(lcdc.lcd_ck);
>  }
> diff --git a/drivers/video/fbdev/omap/lcdc.h b/drivers/video/fbdev/omap/lcdc.h
> index 8a7607d861c1..cbbfd9b9e949 100644
> --- a/drivers/video/fbdev/omap/lcdc.h
> +++ b/drivers/video/fbdev/omap/lcdc.h
> @@ -1,6 +1,41 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  #ifndef LCDC_H
>  #define LCDC_H
> +/*
> + * Copyright (C) 2004 Nokia Corporation
> + * Author: Imre Deak <imre.deak@nokia.com>
> + */
> +#define OMAP_LCDC_BASE			0xfffec000
> +#define OMAP_LCDC_SIZE			256
> +#define OMAP_LCDC_IRQ			INT_LCD_CTRL
> +
> +#define OMAP_LCDC_CONTROL		(OMAP_LCDC_BASE + 0x00)
> +#define OMAP_LCDC_TIMING0		(OMAP_LCDC_BASE + 0x04)
> +#define OMAP_LCDC_TIMING1		(OMAP_LCDC_BASE + 0x08)
> +#define OMAP_LCDC_TIMING2		(OMAP_LCDC_BASE + 0x0c)
> +#define OMAP_LCDC_STATUS		(OMAP_LCDC_BASE + 0x10)
> +#define OMAP_LCDC_SUBPANEL		(OMAP_LCDC_BASE + 0x14)
> +#define OMAP_LCDC_LINE_INT		(OMAP_LCDC_BASE + 0x18)
> +#define OMAP_LCDC_DISPLAY_STATUS	(OMAP_LCDC_BASE + 0x1c)
> +
> +#define OMAP_LCDC_STAT_DONE		(1 << 0)
> +#define OMAP_LCDC_STAT_VSYNC		(1 << 1)
> +#define OMAP_LCDC_STAT_SYNC_LOST	(1 << 2)
> +#define OMAP_LCDC_STAT_ABC		(1 << 3)
> +#define OMAP_LCDC_STAT_LINE_INT		(1 << 4)
> +#define OMAP_LCDC_STAT_FUF		(1 << 5)
> +#define OMAP_LCDC_STAT_LOADED_PALETTE	(1 << 6)
> +
> +#define OMAP_LCDC_CTRL_LCD_EN		(1 << 0)
> +#define OMAP_LCDC_CTRL_LCD_TFT		(1 << 7)
> +#define OMAP_LCDC_CTRL_LINE_IRQ_CLR_SEL	(1 << 10)
> +
> +#define OMAP_LCDC_IRQ_VSYNC		(1 << 2)
> +#define OMAP_LCDC_IRQ_DONE		(1 << 3)
> +#define OMAP_LCDC_IRQ_LOADED_PALETTE	(1 << 4)
> +#define OMAP_LCDC_IRQ_LINE_NIRQ		(1 << 5)
> +#define OMAP_LCDC_IRQ_LINE		(1 << 6)
> +#define OMAP_LCDC_IRQ_MASK		(((1 << 5) - 1) << 2)
>  
>  int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data);
>  void omap_lcdc_free_dma_callback(void);
> diff --git a/drivers/video/fbdev/omap/omapfb.h b/drivers/video/fbdev/omap/omapfb.h
> index d930152c289c..313a051fe7a4 100644
> --- a/drivers/video/fbdev/omap/omapfb.h
> +++ b/drivers/video/fbdev/omap/omapfb.h
> @@ -204,6 +204,8 @@ struct omapfb_device {
>  	struct lcd_panel	*panel;			/* LCD panel */
>  	const struct lcd_ctrl	*ctrl;			/* LCD controller */
>  	const struct lcd_ctrl	*int_ctrl;		/* internal LCD ctrl */
> +	int			ext_irq;
> +	int			int_irq;
>  	struct lcd_ctrl_extif	*ext_if;		/* LCD ctrl external
>  							   interface */
>  	struct device		*dev;
> diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
> index 90eca64e3144..dc06057de91d 100644
> --- a/drivers/video/fbdev/omap/omapfb_main.c
> +++ b/drivers/video/fbdev/omap/omapfb_main.c
> @@ -1618,7 +1618,7 @@ static int omapfb_do_probe(struct platform_device *pdev,
>  
>  	init_state = 0;
>  
> -	if (pdev->num_resources != 0) {
> +	if (pdev->num_resources != 1) {
>  		dev_err(&pdev->dev, "probed for an unknown device\n");
>  		r = -ENODEV;
>  		goto cleanup;
> @@ -1637,6 +1637,20 @@ static int omapfb_do_probe(struct platform_device *pdev,
>  		r = -ENOMEM;
>  		goto cleanup;
>  	}
> +	fbdev->int_irq = platform_get_irq(pdev, 0);
> +	if (!fbdev->int_irq) {
> +		dev_err(&pdev->dev, "unable to get irq\n");
> +		r = ENXIO;
> +		goto cleanup;
> +	}
> +
> +	fbdev->ext_irq = platform_get_irq(pdev, 1);
> +	if (!fbdev->ext_irq) {
> +		dev_err(&pdev->dev, "unable to get irq\n");
> +		r = ENXIO;
> +		goto cleanup;
> +	}
> +
>  	init_state++;
>  
>  	fbdev->dev = &pdev->dev;
> diff --git a/drivers/video/fbdev/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c
> index 80ac67f27f0d..ade9d452254c 100644
> --- a/drivers/video/fbdev/omap/sossi.c
> +++ b/drivers/video/fbdev/omap/sossi.c
> @@ -15,6 +15,7 @@
>  #include <linux/omap-dma.h>
>  
>  #include "omapfb.h"
> +#include "lcd_dma.h"
>  #include "lcdc.h"
>  
>  #define MODULE_NAME		"omapfb-sossi"
> @@ -638,7 +639,7 @@ static int sossi_init(struct omapfb_device *fbdev)
>  	l &= ~(1 << 31); /* REORDERING */
>  	sossi_write_reg(SOSSI_INIT1_REG, l);
>  
> -	if ((r = request_irq(INT_1610_SoSSI_MATCH, sossi_match_irq,
> +	if ((r = request_irq(fbdev->ext_irq, sossi_match_irq,
>  			     IRQ_TYPE_EDGE_FALLING,
>  	     "sossi_match", sossi.fbdev->dev)) < 0) {
>  		dev_err(sossi.fbdev->dev, "can't get SoSSI match IRQ\n");
> diff --git a/include/linux/omap-dma.h b/include/linux/omap-dma.h
> index ba3cfbb52312..e9d76ac6321d 100644
> --- a/include/linux/omap-dma.h
> +++ b/include/linux/omap-dma.h
> @@ -346,8 +346,8 @@ extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth,
>  void omap_dma_global_context_save(void);
>  void omap_dma_global_context_restore(void);
>  
> -#if defined(CONFIG_ARCH_OMAP1) && IS_ENABLED(CONFIG_FB_OMAP)
> -#include <mach/lcd_dma.h>
> +#if IS_ENABLED(CONFIG_FB_OMAP)
> +extern int omap_lcd_dma_running(void);
>  #else
>  static inline int omap_lcd_dma_running(void)
>  {
> @@ -356,6 +356,9 @@ static inline int omap_lcd_dma_running(void)
>  #endif
>  
>  #else /* CONFIG_ARCH_OMAP */
> +static inline void omap_set_dma_priority(int lch, int dst_port, int priority)
> +{
> +}
>  
>  static inline struct omap_system_dma_plat_info *omap_get_plat_info(void)
>  {

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: Explicitly marking initializer overrides (was "Re: [PATCH] arm64/cache: silence -Woverride-init warnings")
From: Robin Murphy @ 2019-08-09 11:31 UTC (permalink / raw)
  To: Mark Rutland, Nathan Chancellor
  Cc: catalin.marinas, linux-kernel, clang-built-linux, Qian Cai, will,
	linux-arm-kernel
In-Reply-To: <20190809083251.GA48423@lakrids.cambridge.arm.com>

On 09/08/2019 09:32, Mark Rutland wrote:
> On Thu, Aug 08, 2019 at 10:09:16AM -0700, Nathan Chancellor wrote:
>> On Thu, Aug 08, 2019 at 11:38:08AM +0100, Mark Rutland wrote:
>>> On Wed, Aug 07, 2019 at 11:29:16PM -0400, Qian Cai wrote:
>>>> The commit 155433cb365e ("arm64: cache: Remove support for ASID-tagged
>>>> VIVT I-caches") introduced some compiation warnings from GCC (and
>>>> Clang) with -Winitializer-overrides),
>>>>
>>>> arch/arm64/kernel/cpuinfo.c:38:26: warning: initialized field
>>>> overwritten [-Woverride-init]
>>>> [ICACHE_POLICY_VIPT]  = "VIPT",
>>>>                          ^~~~~~
>>>> arch/arm64/kernel/cpuinfo.c:38:26: note: (near initialization for
>>>> 'icache_policy_str[2]')
>>>> arch/arm64/kernel/cpuinfo.c:39:26: warning: initialized field
>>>> overwritten [-Woverride-init]
>>>> [ICACHE_POLICY_PIPT]  = "PIPT",
>>>>                          ^~~~~~
>>>> arch/arm64/kernel/cpuinfo.c:39:26: note: (near initialization for
>>>> 'icache_policy_str[3]')
>>>> arch/arm64/kernel/cpuinfo.c:40:27: warning: initialized field
>>>> overwritten [-Woverride-init]
>>>> [ICACHE_POLICY_VPIPT]  = "VPIPT",
>>>>                           ^~~~~~~
>>>> arch/arm64/kernel/cpuinfo.c:40:27: note: (near initialization for
>>>> 'icache_policy_str[0]')
>>>>
>>>> because it initializes icache_policy_str[0 ... 3] twice. Since
>>>> arm64 developers are keen to keep the style of initializing a static
>>>> array with a non-zero pattern first, just disable those warnings for
>>>> both GCC and Clang of this file.
>>>>
>>>> Fixes: 155433cb365e ("arm64: cache: Remove support for ASID-tagged VIVT I-caches")
>>>> Signed-off-by: Qian Cai <cai@lca.pw>
>>>
>>> This is _not_ a fix, and should not require backporting to stable trees.
>>>
>>> What about all the other instances that we have in mainline?
>>>
>>> I really don't think that we need to go down this road; we're just going
>>> to end up adding this to every file that happens to include a header
>>> using this scheme...
>>>
>>> Please just turn this off by default for clang.
>>>
>>> If we want to enable this, we need a mechanism to permit overridable
>>> assignments as we use range initializers for.
>>>
>>> Thanks,
>>> Mark.
>>>
>>
>> For what it's worth, this is disabled by default for clang in the
>> kernel:
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/scripts/Makefile.extrawarn?h=v5.3-rc3#n69
>>
>> It only becomes visible with clang at W=1 because that section doesn't
>> get applied. It becomes visible with GCC at W=1 because of -Wextra.
> 
> Thanks for clarifying that!
> 
> Do you know if there's any existing mechanism that we can use to silence
> the warning on a per-assignment basis? Either to say that an assignment
> can be overridden, or that the assignment is expected to override an
> existing assignment?
> 
> If not, who would be able to look at adding a mechanism to clang for
> this?
> 
> If we could have some attribute or intrinsic that we could wrap like:
> 
> struct foo f = {
> 	.bar __defaultval = <default>,
> 	.bar = <newval>,		// no warning
> 	.bar = <anotherval>,		// warning
> };
> 
> ... or:
> 
> struct foo f = {
> 	.bar = <default>,
> 	.bar __override = <newval>,	// no warning
> 	.bar = <anotherval>,		// warning
> };
> 
> ... or:
> 	
> 	.bar = OVERRIDE(<newval>),	// no warning
> 
> ... or:
> 	OVERRIDE(.bar) = <newval>,	// no warning
> 
> ... then I think it would be possible to make use of the warning
> effectively, as we could distinguish intentional overrides from
> unintentional ones, and annotating assignments in this way doesn't seem
> onerous to me.

Tangentially, there might also be value in some kind of "must be 
explicitly initialised" attribute that would warn if any element was not 
covered by (at least one) initialiser. For cases like our 
icache_policy_str one, where using the "default + overrides" pattern for 
the sake of one reserved entry is more about robustness against the 
array growing in future than simpler code today, that could arguably be 
a more appropriate option.

Robin.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 01/22] ARM: omap1: innovator: pass lcd control address as pdata
From: Bartlomiej Zolnierkiewicz @ 2019-08-09 11:29 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-fbdev, Aaro Koskinen, Tony Lindgren, Greg Kroah-Hartman,
	Linus Walleij, linux-kernel, dri-devel, Tomi Valkeinen,
	linux-omap, linux-arm-kernel
In-Reply-To: <20190808212234.2213262-2-arnd@arndb.de>


On 8/8/19 11:22 PM, Arnd Bergmann wrote:
> To avoid using the mach/omap1510.h header file, pass the correct
> address as platform data.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

For fbdev part:

Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> ---
>  arch/arm/mach-omap1/board-innovator.c  | 3 +++
>  drivers/video/fbdev/omap/lcd_inn1510.c | 7 +++++--
>  2 files changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
> index cbe093f969d5..2425f1bacb33 100644
> --- a/arch/arm/mach-omap1/board-innovator.c
> +++ b/arch/arm/mach-omap1/board-innovator.c
> @@ -194,6 +194,9 @@ static struct platform_device innovator1510_smc91x_device = {
>  static struct platform_device innovator1510_lcd_device = {
>  	.name		= "lcd_inn1510",
>  	.id		= -1,
> +	.dev	= {
> +		.platform_data = (void __force *)OMAP1510_FPGA_LCD_PANEL_CONTROL,
> +	}
>  };
>  
>  static struct platform_device innovator1510_spi_device = {
> diff --git a/drivers/video/fbdev/omap/lcd_inn1510.c b/drivers/video/fbdev/omap/lcd_inn1510.c
> index 776e7f8d656e..37ed0c14aa5a 100644
> --- a/drivers/video/fbdev/omap/lcd_inn1510.c
> +++ b/drivers/video/fbdev/omap/lcd_inn1510.c
> @@ -14,15 +14,17 @@
>  
>  #include "omapfb.h"
>  
> +static void __iomem *omap1510_fpga_lcd_panel_control;
> +
>  static int innovator1510_panel_enable(struct lcd_panel *panel)
>  {
> -	__raw_writeb(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
> +	__raw_writeb(0x7, omap1510_fpga_lcd_panel_control);
>  	return 0;
>  }
>  
>  static void innovator1510_panel_disable(struct lcd_panel *panel)
>  {
> -	__raw_writeb(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
> +	__raw_writeb(0x0, omap1510_fpga_lcd_panel_control);
>  }
>  
>  static struct lcd_panel innovator1510_panel = {
> @@ -48,6 +50,7 @@ static struct lcd_panel innovator1510_panel = {
>  
>  static int innovator1510_panel_probe(struct platform_device *pdev)
>  {
> +	omap1510_fpga_lcd_panel_control = (void __iomem *)pdev->dev.platform_data;
>  	omapfb_register_panel(&innovator1510_panel);
>  	return 0;
>  }

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH] ARM: dts: imx7d: cl-som-imx7: add compatible for phy
From: André Draszik @ 2019-08-09 11:29 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mark Rutland, devicetree, Fabio Estevam, linux-arm-kernel,
	André Draszik, Sascha Hauer, Rob Herring, Igor Grinberg,
	Pengutronix Kernel Team, Shawn Guo, Ilya Ledvich, NXP Linux Team

While not strictly needed as "ethernet-phy-ieee802.3-c22"
is assumed by default if not given explicitly, having
the compatible string here makes it more clear what
this is and which driver handles this - an Ethernet
phy attached to mdio, handled by of_mdio.c

Signed-off-by: André Draszik <git@andred.net>
CC: Ilya Ledvich <ilya@compulab.co.il>
CC: Igor Grinberg <grinberg@compulab.co.il>
CC: Rob Herring <robh+dt@kernel.org>
CC: Mark Rutland <mark.rutland@arm.com>
CC: Shawn Guo <shawnguo@kernel.org>
CC: Sascha Hauer <s.hauer@pengutronix.de>
CC: Pengutronix Kernel Team <kernel@pengutronix.de>
CC: Fabio Estevam <festevam@gmail.com>
CC: NXP Linux Team <linux-imx@nxp.com>
CC: devicetree@vger.kernel.org
CC: linux-arm-kernel@lists.infradead.org
---
 arch/arm/boot/dts/imx7d-cl-som-imx7.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
index 62d5e9a4a781..7646284e13a7 100644
--- a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
+++ b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
@@ -54,10 +54,12 @@
 		#size-cells = <0>;
 
 		ethphy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-ieee802.3-c22";
 			reg = <0>;
 		};
 
 		ethphy1: ethernet-phy@1 {
+			compatible = "ethernet-phy-ieee802.3-c22";
 			reg = <1>;
 		};
 	};
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* Re: [PATCH 07/22] ARM: omap1: move perseus spi pinconf to board file
From: Arnd Bergmann @ 2019-08-09 11:29 UTC (permalink / raw)
  To: Mark Brown
  Cc: Aaro Koskinen, Tony Lindgren, Greg Kroah-Hartman, Linus Walleij,
	Bartlomiej Zolnierkiewicz, Linux Kernel Mailing List, linux-spi,
	Tomi Valkeinen, linux-omap, Linux ARM, Boris Brezillon
In-Reply-To: <20190808222408.GS3795@sirena.co.uk>

On Fri, Aug 9, 2019 at 12:24 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Thu, Aug 08, 2019 at 11:22:16PM +0200, Arnd Bergmann wrote:
> > The driver has always had a FIXME about this, and it seems
> > like this trivial code move avoids a mach header inclusion,
> > so just do it.
>
> This appears to be part of a series but I've no cover letter or anything
> else from it.  What's the story for dependencies and merging?

Sorry for missing you on the cover letter. The patch is part of a series
to make omap1 part of ARCH_MULTIPLATFORM. I'd like to merge the entire
series through the arm-soc tree to avoid dependencies:

https://lore.kernel.org/linux-arm-kernel/20190808212234.2213262-1-arnd@arndb.de/T

      Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH v2 6/6] arm64: defconfig: Enable configs for S32V234
From: Stefan-gabriel Mirea @ 2019-08-09 11:29 UTC (permalink / raw)
  To: corbet@lwn.net, robh+dt@kernel.org, mark.rutland@arm.com,
	gregkh@linuxfoundation.org, catalin.marinas@arm.com,
	will@kernel.org, shawnguo@kernel.org, Leo Li
  Cc: devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
	jslaby@suse.com, Cosmin Stefan Stoica,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190809112853.15846-1-stefan-gabriel.mirea@nxp.com>

From: Mihaela Martinas <Mihaela.Martinas@freescale.com>

Enable support for the S32V234 SoC, including the previously added UART
driver.

Signed-off-by: Mihaela Martinas <Mihaela.Martinas@freescale.com>
Signed-off-by: Adrian.Nitu <adrian.nitu@freescale.com>
Signed-off-by: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>
Signed-off-by: Stefan-Gabriel Mirea <stefan-gabriel.mirea@nxp.com>
---
 arch/arm64/configs/defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 0e58ef02880c..bb5aa95a8455 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -48,6 +48,7 @@ CONFIG_ARCH_MXC=y
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_RENESAS=y
 CONFIG_ARCH_ROCKCHIP=y
+CONFIG_ARCH_S32=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_STRATIX10=y
 CONFIG_ARCH_SYNQUACER=y
@@ -347,6 +348,8 @@ CONFIG_SERIAL_XILINX_PS_UART=y
 CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
 CONFIG_SERIAL_FSL_LPUART=y
 CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+CONFIG_SERIAL_FSL_LINFLEXUART=y
+CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y
 CONFIG_SERIAL_MVEBU_UART=y
 CONFIG_SERIAL_DEV_BUS=y
 CONFIG_VIRTIO_CONSOLE=y
-- 
2.22.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v2 5/6] tty: serial: Add linflexuart driver for S32V234
From: Stefan-gabriel Mirea @ 2019-08-09 11:29 UTC (permalink / raw)
  To: corbet@lwn.net, robh+dt@kernel.org, mark.rutland@arm.com,
	gregkh@linuxfoundation.org, catalin.marinas@arm.com,
	will@kernel.org, shawnguo@kernel.org, Leo Li
  Cc: devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
	Larisa Ileana Grigore, linux-kernel@vger.kernel.org,
	linux-serial@vger.kernel.org, jslaby@suse.com,
	Cosmin Stefan Stoica, linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190809112853.15846-1-stefan-gabriel.mirea@nxp.com>

Introduce support for LINFlex driver, based on:
- the version of Freescale LPUART driver after commit b3e3bf2ef2c7 ("Merge
  4.0-rc7 into tty-next");
- commit abf1e0a98083 ("tty: serial: fsl_lpuart: lock port on console
  write").
In this basic version, the driver can be tested using initramfs and relies
on the clocks and pin muxing set up by U-Boot.

Remarks concerning the earlycon support:

- LinFlexD does not allow character transmissions in the INIT mode (see
  section 47.4.2.1 in the reference manual[1]). Therefore, a mutual
  exclusion between the first linflex_setup_watermark/linflex_set_termios
  executions and linflex_earlycon_putchar was employed and the characters
  normally sent to earlycon during initialization are kept in a buffer and
  sent afterwards.

- Empirically, character transmission is also forbidden within the last 1-2
  ms before entering the INIT mode, so we use an explicit timeout
  (PREINIT_DELAY) between linflex_earlycon_putchar and the first call to
  linflex_setup_watermark.

- U-Boot currently uses the UART FIFO mode, while this driver makes the
  transition to the buffer mode. Therefore, the earlycon putchar function
  matches the U-Boot behavior before initializations and the Linux behavior
  after.

[1] https://www.nxp.com/webapp/Download?colCode=S32V234RM

Signed-off-by: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>
Signed-off-by: Adrian.Nitu <adrian.nitu@freescale.com>
Signed-off-by: Larisa Grigore <Larisa.Grigore@nxp.com>
Signed-off-by: Ana Nedelcu <B56683@freescale.com>
Signed-off-by: Mihaela Martinas <Mihaela.Martinas@freescale.com>
Signed-off-by: Matthew Nunez <matthew.nunez@nxp.com>
[stefan-gabriel.mirea@nxp.com: Reduced for upstreaming and implemented
                               earlycon support]
Signed-off-by: Stefan-Gabriel Mirea <stefan-gabriel.mirea@nxp.com>
---
 .../admin-guide/kernel-parameters.txt         |   6 +
 drivers/tty/serial/Kconfig                    |  15 +
 drivers/tty/serial/Makefile                   |   1 +
 drivers/tty/serial/fsl_linflexuart.c          | 942 ++++++++++++++++++
 include/uapi/linux/serial_core.h              |   3 +
 5 files changed, 967 insertions(+)
 create mode 100644 drivers/tty/serial/fsl_linflexuart.c

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 46b826fcb5ad..4d545732aadc 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1090,6 +1090,12 @@
 			the framebuffer, pass the 'ram' option so that it is
 			mapped with the correct attributes.
 
+		linflex,<addr>
+			Use early console provided by Freescale LinFlex UART
+			serial driver for NXP S32V234 SoCs. A valid base
+			address must be provided, and the serial port must
+			already be setup and configured.
+
 	earlyprintk=	[X86,SH,ARM,M68k,S390]
 			earlyprintk=vga
 			earlyprintk=sclp
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index fd385c8c53a5..b4fa2f7c96bd 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1452,6 +1452,21 @@ config SERIAL_FSL_LPUART_CONSOLE
 	  If you have enabled the lpuart serial port on the Freescale SoCs,
 	  you can make it the console by answering Y to this option.
 
+config SERIAL_FSL_LINFLEXUART
+	tristate "Freescale linflexuart serial port support"
+	select SERIAL_CORE
+	help
+	  Support for the on-chip linflexuart on some Freescale SOCs.
+
+config SERIAL_FSL_LINFLEXUART_CONSOLE
+	bool "Console on Freescale linflexuart serial port"
+	depends on SERIAL_FSL_LINFLEXUART=y
+	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON
+	help
+	  If you have enabled the linflexuart serial port on the Freescale
+	  SoCs, you can make it the console by answering Y to this option.
+
 config SERIAL_CONEXANT_DIGICOLOR
 	tristate "Conexant Digicolor CX92xxx USART serial port support"
 	depends on OF
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 7cd7cabfa6c4..7a3d52a453b7 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
 obj-$(CONFIG_SERIAL_ARC)	+= arc_uart.o
 obj-$(CONFIG_SERIAL_RP2)	+= rp2.o
 obj-$(CONFIG_SERIAL_FSL_LPUART)	+= fsl_lpuart.o
+obj-$(CONFIG_SERIAL_FSL_LINFLEXUART)	+= fsl_linflexuart.o
 obj-$(CONFIG_SERIAL_CONEXANT_DIGICOLOR)	+= digicolor-usart.o
 obj-$(CONFIG_SERIAL_MEN_Z135)	+= men_z135_uart.o
 obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c
new file mode 100644
index 000000000000..26b9601a0952
--- /dev/null
+++ b/drivers/tty/serial/fsl_linflexuart.c
@@ -0,0 +1,942 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Freescale linflexuart serial port driver
+ *
+ * Copyright 2012-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP
+ */
+
+#if defined(CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE) && \
+	defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+
+/* All registers are 32-bit width */
+
+#define LINCR1	0x0000	/* LIN control register				*/
+#define LINIER	0x0004	/* LIN interrupt enable register		*/
+#define LINSR	0x0008	/* LIN status register				*/
+#define LINESR	0x000C	/* LIN error status register			*/
+#define UARTCR	0x0010	/* UART mode control register			*/
+#define UARTSR	0x0014	/* UART mode status register			*/
+#define LINTCSR	0x0018	/* LIN timeout control status register		*/
+#define LINOCR	0x001C	/* LIN output compare register			*/
+#define LINTOCR	0x0020	/* LIN timeout control register			*/
+#define LINFBRR	0x0024	/* LIN fractional baud rate register		*/
+#define LINIBRR	0x0028	/* LIN integer baud rate register		*/
+#define LINCFR	0x002C	/* LIN checksum field register			*/
+#define LINCR2	0x0030	/* LIN control register 2			*/
+#define BIDR	0x0034	/* Buffer identifier register			*/
+#define BDRL	0x0038	/* Buffer data register least significant	*/
+#define BDRM	0x003C	/* Buffer data register most significant	*/
+#define IFER	0x0040	/* Identifier filter enable register		*/
+#define IFMI	0x0044	/* Identifier filter match index		*/
+#define IFMR	0x0048	/* Identifier filter mode register		*/
+#define GCR	0x004C	/* Global control register			*/
+#define UARTPTO	0x0050	/* UART preset timeout register			*/
+#define UARTCTO	0x0054	/* UART current timeout register		*/
+
+/*
+ * Register field definitions
+ */
+
+#define LINFLEXD_LINCR1_INIT		BIT(0)
+#define LINFLEXD_LINCR1_MME		BIT(4)
+#define LINFLEXD_LINCR1_BF		BIT(7)
+
+#define LINFLEXD_LINSR_LINS_INITMODE	BIT(12)
+#define LINFLEXD_LINSR_LINS_MASK	(0xF << 12)
+
+#define LINFLEXD_LINIER_SZIE		BIT(15)
+#define LINFLEXD_LINIER_OCIE		BIT(14)
+#define LINFLEXD_LINIER_BEIE		BIT(13)
+#define LINFLEXD_LINIER_CEIE		BIT(12)
+#define LINFLEXD_LINIER_HEIE		BIT(11)
+#define LINFLEXD_LINIER_FEIE		BIT(8)
+#define LINFLEXD_LINIER_BOIE		BIT(7)
+#define LINFLEXD_LINIER_LSIE		BIT(6)
+#define LINFLEXD_LINIER_WUIE		BIT(5)
+#define LINFLEXD_LINIER_DBFIE		BIT(4)
+#define LINFLEXD_LINIER_DBEIETOIE	BIT(3)
+#define LINFLEXD_LINIER_DRIE		BIT(2)
+#define LINFLEXD_LINIER_DTIE		BIT(1)
+#define LINFLEXD_LINIER_HRIE		BIT(0)
+
+#define LINFLEXD_UARTCR_OSR_MASK	(0xF << 24)
+#define LINFLEXD_UARTCR_OSR(uartcr)	(((uartcr) \
+					& LINFLEXD_UARTCR_OSR_MASK) >> 24)
+
+#define LINFLEXD_UARTCR_ROSE		BIT(23)
+
+#define LINFLEXD_UARTCR_RFBM		BIT(9)
+#define LINFLEXD_UARTCR_TFBM		BIT(8)
+#define LINFLEXD_UARTCR_WL1		BIT(7)
+#define LINFLEXD_UARTCR_PC1		BIT(6)
+
+#define LINFLEXD_UARTCR_RXEN		BIT(5)
+#define LINFLEXD_UARTCR_TXEN		BIT(4)
+#define LINFLEXD_UARTCR_PC0		BIT(3)
+
+#define LINFLEXD_UARTCR_PCE		BIT(2)
+#define LINFLEXD_UARTCR_WL0		BIT(1)
+#define LINFLEXD_UARTCR_UART		BIT(0)
+
+#define LINFLEXD_UARTSR_SZF		BIT(15)
+#define LINFLEXD_UARTSR_OCF		BIT(14)
+#define LINFLEXD_UARTSR_PE3		BIT(13)
+#define LINFLEXD_UARTSR_PE2		BIT(12)
+#define LINFLEXD_UARTSR_PE1		BIT(11)
+#define LINFLEXD_UARTSR_PE0		BIT(10)
+#define LINFLEXD_UARTSR_RMB		BIT(9)
+#define LINFLEXD_UARTSR_FEF		BIT(8)
+#define LINFLEXD_UARTSR_BOF		BIT(7)
+#define LINFLEXD_UARTSR_RPS		BIT(6)
+#define LINFLEXD_UARTSR_WUF		BIT(5)
+#define LINFLEXD_UARTSR_4		BIT(4)
+
+#define LINFLEXD_UARTSR_TO		BIT(3)
+
+#define LINFLEXD_UARTSR_DRFRFE		BIT(2)
+#define LINFLEXD_UARTSR_DTFTFF		BIT(1)
+#define LINFLEXD_UARTSR_NF		BIT(0)
+#define LINFLEXD_UARTSR_PE		(LINFLEXD_UARTSR_PE0 |\
+					 LINFLEXD_UARTSR_PE1 |\
+					 LINFLEXD_UARTSR_PE2 |\
+					 LINFLEXD_UARTSR_PE3)
+
+#define LINFLEX_LDIV_MULTIPLIER		(16)
+
+#define DRIVER_NAME	"fsl-linflexuart"
+#define DEV_NAME	"ttyLF"
+#define UART_NR		4
+
+#define EARLYCON_BUFFER_INITIAL_CAP	8
+
+#define PREINIT_DELAY			2000 /* us */
+
+static const struct of_device_id linflex_dt_ids[] = {
+	{
+		.compatible = "fsl,s32-linflexuart",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, linflex_dt_ids);
+
+#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE
+static struct uart_port *earlycon_port;
+static bool linflex_earlycon_same_instance;
+static spinlock_t init_lock;
+static bool during_init;
+
+static struct {
+	char *content;
+	unsigned int len, cap;
+} earlycon_buf;
+#endif
+
+static void linflex_stop_tx(struct uart_port *port)
+{
+	unsigned long ier;
+
+	ier = readl(port->membase + LINIER);
+	ier &= ~(LINFLEXD_LINIER_DTIE);
+	writel(ier, port->membase + LINIER);
+}
+
+static void linflex_stop_rx(struct uart_port *port)
+{
+	unsigned long ier;
+
+	ier = readl(port->membase + LINIER);
+	writel(ier & ~LINFLEXD_LINIER_DRIE, port->membase + LINIER);
+}
+
+static inline void linflex_transmit_buffer(struct uart_port *sport)
+{
+	struct circ_buf *xmit = &sport->state->xmit;
+	unsigned char c;
+	unsigned long status;
+
+	while (!uart_circ_empty(xmit)) {
+		c = xmit->buf[xmit->tail];
+		writeb(c, sport->membase + BDRL);
+
+		/* Waiting for data transmission completed. */
+		while (((status = readl(sport->membase + UARTSR)) &
+					LINFLEXD_UARTSR_DTFTFF) !=
+					LINFLEXD_UARTSR_DTFTFF)
+			;
+
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		sport->icount.tx++;
+
+		writel(status | LINFLEXD_UARTSR_DTFTFF,
+		       sport->membase + UARTSR);
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(sport);
+
+	if (uart_circ_empty(xmit))
+		linflex_stop_tx(sport);
+}
+
+static void linflex_start_tx(struct uart_port *port)
+{
+	unsigned long ier;
+
+	linflex_transmit_buffer(port);
+	ier = readl(port->membase + LINIER);
+	writel(ier | LINFLEXD_LINIER_DTIE, port->membase + LINIER);
+}
+
+static irqreturn_t linflex_txint(int irq, void *dev_id)
+{
+	struct uart_port *sport = dev_id;
+	struct circ_buf *xmit = &sport->state->xmit;
+	unsigned long flags;
+	unsigned long status;
+
+	spin_lock_irqsave(&sport->lock, flags);
+
+	if (sport->x_char) {
+		writeb(sport->x_char, sport->membase + BDRL);
+
+		/* waiting for data transmission completed */
+		while (((status = readl(sport->membase + UARTSR)) &
+			LINFLEXD_UARTSR_DTFTFF) != LINFLEXD_UARTSR_DTFTFF)
+			;
+
+		writel(status | LINFLEXD_UARTSR_DTFTFF,
+		       sport->membase + UARTSR);
+
+		goto out;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(sport)) {
+		linflex_stop_tx(sport);
+		goto out;
+	}
+
+	linflex_transmit_buffer(sport);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(sport);
+
+out:
+	spin_unlock_irqrestore(&sport->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t linflex_rxint(int irq, void *dev_id)
+{
+	struct uart_port *sport = dev_id;
+	unsigned int flg;
+	struct tty_port *port = &sport->state->port;
+	unsigned long flags, status;
+	unsigned char rx;
+
+	spin_lock_irqsave(&sport->lock, flags);
+
+	status = readl(sport->membase + UARTSR);
+	while (status & LINFLEXD_UARTSR_RMB) {
+		rx = readb(sport->membase + BDRM);
+		flg = TTY_NORMAL;
+		sport->icount.rx++;
+
+		if (status & (LINFLEXD_UARTSR_BOF | LINFLEXD_UARTSR_SZF |
+			      LINFLEXD_UARTSR_FEF | LINFLEXD_UARTSR_PE)) {
+			if (status & LINFLEXD_UARTSR_SZF)
+				status |= LINFLEXD_UARTSR_SZF;
+			if (status & LINFLEXD_UARTSR_BOF)
+				status |= LINFLEXD_UARTSR_BOF;
+			if (status & LINFLEXD_UARTSR_FEF)
+				status |= LINFLEXD_UARTSR_FEF;
+			if (status & LINFLEXD_UARTSR_PE)
+				status |=  LINFLEXD_UARTSR_PE;
+		}
+
+		writel(status | LINFLEXD_UARTSR_RMB | LINFLEXD_UARTSR_DRFRFE,
+		       sport->membase + UARTSR);
+		status = readl(sport->membase + UARTSR);
+
+		if (uart_handle_sysrq_char(sport, (unsigned char)rx))
+			continue;
+
+#ifdef SUPPORT_SYSRQ
+			sport->sysrq = 0;
+#endif
+		tty_insert_flip_char(port, rx, flg);
+	}
+
+	spin_unlock_irqrestore(&sport->lock, flags);
+
+	tty_flip_buffer_push(port);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t linflex_int(int irq, void *dev_id)
+{
+	struct uart_port *sport = dev_id;
+	unsigned long status;
+
+	status = readl(sport->membase + UARTSR);
+
+	if (status & LINFLEXD_UARTSR_DRFRFE)
+		linflex_rxint(irq, dev_id);
+	if (status & LINFLEXD_UARTSR_DTFTFF)
+		linflex_txint(irq, dev_id);
+
+	return IRQ_HANDLED;
+}
+
+/* return TIOCSER_TEMT when transmitter is not busy */
+static unsigned int linflex_tx_empty(struct uart_port *port)
+{
+	unsigned long status;
+
+	status = readl(port->membase + UARTSR) & LINFLEXD_UARTSR_DTFTFF;
+
+	return status ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int linflex_get_mctrl(struct uart_port *port)
+{
+	return 0;
+}
+
+static void linflex_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static void linflex_break_ctl(struct uart_port *port, int break_state)
+{
+}
+
+static void linflex_setup_watermark(struct uart_port *sport)
+{
+	unsigned long cr, ier, cr1;
+
+	/* Disable transmission/reception */
+	ier = readl(sport->membase + LINIER);
+	ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE);
+	writel(ier, sport->membase + LINIER);
+
+	cr = readl(sport->membase + UARTCR);
+	cr &= ~(LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN);
+	writel(cr, sport->membase + UARTCR);
+
+	/* Enter initialization mode by setting INIT bit */
+
+	/* set the Linflex in master mode and activate by-pass filter */
+	cr1 = LINFLEXD_LINCR1_BF | LINFLEXD_LINCR1_MME
+	      | LINFLEXD_LINCR1_INIT;
+	writel(cr1, sport->membase + LINCR1);
+
+	/* wait for init mode entry */
+	while ((readl(sport->membase + LINSR)
+		& LINFLEXD_LINSR_LINS_MASK)
+		!= LINFLEXD_LINSR_LINS_INITMODE)
+		;
+
+	/*
+	 *	UART = 0x1;		- Linflex working in UART mode
+	 *	TXEN = 0x1;		- Enable transmission of data now
+	 *	RXEn = 0x1;		- Receiver enabled
+	 *	WL0 = 0x1;		- 8 bit data
+	 *	PCE = 0x0;		- No parity
+	 */
+
+	/* set UART bit to allow writing other bits */
+	writel(LINFLEXD_UARTCR_UART, sport->membase + UARTCR);
+
+	cr = (LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN |
+	      LINFLEXD_UARTCR_WL0 | LINFLEXD_UARTCR_UART);
+
+	writel(cr, sport->membase + UARTCR);
+
+	cr1 &= ~(LINFLEXD_LINCR1_INIT);
+
+	writel(cr1, sport->membase + LINCR1);
+
+	ier = readl(sport->membase + LINIER);
+	ier |= LINFLEXD_LINIER_DRIE;
+	ier |= LINFLEXD_LINIER_DTIE;
+
+	writel(ier, sport->membase + LINIER);
+}
+
+static int linflex_startup(struct uart_port *port)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	linflex_setup_watermark(port);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	ret = devm_request_irq(port->dev, port->irq, linflex_int, 0,
+			       DRIVER_NAME, port);
+
+	return ret;
+}
+
+static void linflex_shutdown(struct uart_port *port)
+{
+	unsigned long ier;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* disable interrupts */
+	ier = readl(port->membase + LINIER);
+	ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE);
+	writel(ier, port->membase + LINIER);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	devm_free_irq(port->dev, port->irq, port);
+}
+
+static void
+linflex_set_termios(struct uart_port *port, struct ktermios *termios,
+		    struct ktermios *old)
+{
+	unsigned long flags;
+	unsigned long cr, old_cr, cr1;
+	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
+
+	cr = readl(port->membase + UARTCR);
+	old_cr = cr;
+
+	/* Enter initialization mode by setting INIT bit */
+	cr1 = readl(port->membase + LINCR1);
+	cr1 |= LINFLEXD_LINCR1_INIT;
+	writel(cr1, port->membase + LINCR1);
+
+	/* wait for init mode entry */
+	while ((readl(port->membase + LINSR)
+		& LINFLEXD_LINSR_LINS_MASK)
+		!= LINFLEXD_LINSR_LINS_INITMODE)
+		;
+
+	/*
+	 * only support CS8 and CS7, and for CS7 must enable PE.
+	 * supported mode:
+	 *	- (7,e/o,1)
+	 *	- (8,n,1)
+	 *	- (8,e/o,1)
+	 */
+	/* enter the UART into configuration mode */
+
+	while ((termios->c_cflag & CSIZE) != CS8 &&
+	       (termios->c_cflag & CSIZE) != CS7) {
+		termios->c_cflag &= ~CSIZE;
+		termios->c_cflag |= old_csize;
+		old_csize = CS8;
+	}
+
+	if ((termios->c_cflag & CSIZE) == CS7) {
+		/* Word length: WL1WL0:00 */
+		cr = old_cr & ~LINFLEXD_UARTCR_WL1 & ~LINFLEXD_UARTCR_WL0;
+	}
+
+	if ((termios->c_cflag & CSIZE) == CS8) {
+		/* Word length: WL1WL0:01 */
+		cr = (old_cr | LINFLEXD_UARTCR_WL0) & ~LINFLEXD_UARTCR_WL1;
+	}
+
+	if (termios->c_cflag & CMSPAR) {
+		if ((termios->c_cflag & CSIZE) != CS8) {
+			termios->c_cflag &= ~CSIZE;
+			termios->c_cflag |= CS8;
+		}
+		/* has a space/sticky bit */
+		cr |= LINFLEXD_UARTCR_WL0;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		termios->c_cflag &= ~CSTOPB;
+
+	/* parity must be enabled when CS7 to match 8-bits format */
+	if ((termios->c_cflag & CSIZE) == CS7)
+		termios->c_cflag |= PARENB;
+
+	if ((termios->c_cflag & PARENB)) {
+		cr |= LINFLEXD_UARTCR_PCE;
+		if (termios->c_cflag & PARODD)
+			cr = (cr | LINFLEXD_UARTCR_PC0) &
+			     (~LINFLEXD_UARTCR_PC1);
+		else
+			cr = cr & (~LINFLEXD_UARTCR_PC1 &
+				   ~LINFLEXD_UARTCR_PC0);
+	} else {
+		cr &= ~LINFLEXD_UARTCR_PCE;
+	}
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	port->read_status_mask = 0;
+
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |=	(LINFLEXD_UARTSR_FEF |
+						 LINFLEXD_UARTSR_PE0 |
+						 LINFLEXD_UARTSR_PE1 |
+						 LINFLEXD_UARTSR_PE2 |
+						 LINFLEXD_UARTSR_PE3);
+	if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+		port->read_status_mask |= LINFLEXD_UARTSR_FEF;
+
+	/* characters to ignore */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= LINFLEXD_UARTSR_PE;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= LINFLEXD_UARTSR_PE;
+		/*
+		 * if we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= LINFLEXD_UARTSR_BOF;
+	}
+
+	writel(cr, port->membase + UARTCR);
+
+	cr1 &= ~(LINFLEXD_LINCR1_INIT);
+
+	writel(cr1, port->membase + LINCR1);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *linflex_type(struct uart_port *port)
+{
+	return "FSL_LINFLEX";
+}
+
+static void linflex_release_port(struct uart_port *port)
+{
+	/* nothing to do */
+}
+
+static int linflex_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+/* configure/auto-configure the port */
+static void linflex_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		port->type = PORT_LINFLEXUART;
+}
+
+static const struct uart_ops linflex_pops = {
+	.tx_empty	= linflex_tx_empty,
+	.set_mctrl	= linflex_set_mctrl,
+	.get_mctrl	= linflex_get_mctrl,
+	.stop_tx	= linflex_stop_tx,
+	.start_tx	= linflex_start_tx,
+	.stop_rx	= linflex_stop_rx,
+	.break_ctl	= linflex_break_ctl,
+	.startup	= linflex_startup,
+	.shutdown	= linflex_shutdown,
+	.set_termios	= linflex_set_termios,
+	.type		= linflex_type,
+	.request_port	= linflex_request_port,
+	.release_port	= linflex_release_port,
+	.config_port	= linflex_config_port,
+};
+
+static struct uart_port *linflex_ports[UART_NR];
+
+#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE
+static void linflex_console_putchar(struct uart_port *port, int ch)
+{
+	unsigned long cr;
+
+	cr = readl(port->membase + UARTCR);
+
+	writeb(ch, port->membase + BDRL);
+
+	if (!(cr & LINFLEXD_UARTCR_TFBM))
+		while ((readl(port->membase + UARTSR) &
+					LINFLEXD_UARTSR_DTFTFF)
+				!= LINFLEXD_UARTSR_DTFTFF)
+			;
+	else
+		while (readl(port->membase + UARTSR) &
+					LINFLEXD_UARTSR_DTFTFF)
+			;
+
+	if (!(cr & LINFLEXD_UARTCR_TFBM)) {
+		writel((readl(port->membase + UARTSR) |
+					LINFLEXD_UARTSR_DTFTFF),
+					port->membase + UARTSR);
+	}
+}
+
+static void linflex_earlycon_putchar(struct uart_port *port, int ch)
+{
+	unsigned long flags;
+	char *ret;
+
+	if (!linflex_earlycon_same_instance) {
+		linflex_console_putchar(port, ch);
+		return;
+	}
+
+	spin_lock_irqsave(&init_lock, flags);
+	if (!during_init)
+		goto outside_init;
+
+	if (earlycon_buf.len >= 1 << CONFIG_LOG_BUF_SHIFT)
+		goto init_release;
+
+	if (!earlycon_buf.cap) {
+		earlycon_buf.content = kmalloc(EARLYCON_BUFFER_INITIAL_CAP,
+					       GFP_ATOMIC);
+		earlycon_buf.cap = earlycon_buf.content ?
+				   EARLYCON_BUFFER_INITIAL_CAP : 0;
+	} else if (earlycon_buf.len == earlycon_buf.cap) {
+		ret = krealloc(earlycon_buf.content, earlycon_buf.cap << 1,
+			       GFP_ATOMIC);
+		if (ret) {
+			earlycon_buf.content = ret;
+			earlycon_buf.cap <<= 1;
+		}
+	}
+
+	if (earlycon_buf.len < earlycon_buf.cap)
+		earlycon_buf.content[earlycon_buf.len++] = ch;
+
+	goto init_release;
+
+outside_init:
+	linflex_console_putchar(port, ch);
+init_release:
+	spin_unlock_irqrestore(&init_lock, flags);
+}
+
+static void linflex_string_write(struct uart_port *sport, const char *s,
+				 unsigned int count)
+{
+	unsigned long cr, ier = 0;
+
+	ier = readl(sport->membase + LINIER);
+	linflex_stop_tx(sport);
+
+	cr = readl(sport->membase + UARTCR);
+	cr |= (LINFLEXD_UARTCR_TXEN);
+	writel(cr, sport->membase + UARTCR);
+
+	uart_console_write(sport, s, count, linflex_console_putchar);
+
+	writel(ier, sport->membase + LINIER);
+}
+
+static void
+linflex_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct uart_port *sport = linflex_ports[co->index];
+	unsigned long flags;
+	int locked = 1;
+
+	if (sport->sysrq)
+		locked = 0;
+	else if (oops_in_progress)
+		locked = spin_trylock_irqsave(&sport->lock, flags);
+	else
+		spin_lock_irqsave(&sport->lock, flags);
+
+	linflex_string_write(sport, s, count);
+
+	if (locked)
+		spin_unlock_irqrestore(&sport->lock, flags);
+}
+
+/*
+ * if the port was already initialised (eg, by a boot loader),
+ * try to determine the current setup.
+ */
+static void __init
+linflex_console_get_options(struct uart_port *sport, int *parity, int *bits)
+{
+	unsigned long cr;
+
+	cr = readl(sport->membase + UARTCR);
+	cr &= LINFLEXD_UARTCR_RXEN | LINFLEXD_UARTCR_TXEN;
+
+	if (!cr)
+		return;
+
+	/* ok, the port was enabled */
+
+	*parity = 'n';
+	if (cr & LINFLEXD_UARTCR_PCE) {
+		if (cr & LINFLEXD_UARTCR_PC0)
+			*parity = 'o';
+		else
+			*parity = 'e';
+	}
+
+	if ((cr & LINFLEXD_UARTCR_WL0) && ((cr & LINFLEXD_UARTCR_WL1) == 0)) {
+		if (cr & LINFLEXD_UARTCR_PCE)
+			*bits = 9;
+		else
+			*bits = 8;
+	}
+}
+
+static int __init linflex_console_setup(struct console *co, char *options)
+{
+	struct uart_port *sport;
+	int baud = 115200;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+	int ret;
+	int i;
+	unsigned long flags;
+	/*
+	 * check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	if (co->index == -1 || co->index >= ARRAY_SIZE(linflex_ports))
+		co->index = 0;
+
+	sport = linflex_ports[co->index];
+	if (!sport)
+		return -ENODEV;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	else
+		linflex_console_get_options(sport, &parity, &bits);
+
+	if (earlycon_port && sport->mapbase == earlycon_port->mapbase) {
+		linflex_earlycon_same_instance = true;
+
+		spin_lock_irqsave(&init_lock, flags);
+		during_init = true;
+		spin_unlock_irqrestore(&init_lock, flags);
+
+		/* Workaround for character loss or output of many invalid
+		 * characters, when INIT mode is entered shortly after a
+		 * character has just been printed.
+		 */
+		udelay(PREINIT_DELAY);
+	}
+
+	linflex_setup_watermark(sport);
+
+	ret = uart_set_options(sport, co, baud, parity, bits, flow);
+
+	if (!linflex_earlycon_same_instance)
+		goto done;
+
+	spin_lock_irqsave(&init_lock, flags);
+
+	/* Emptying buffer */
+	if (earlycon_buf.len) {
+		for (i = 0; i < earlycon_buf.len; i++)
+			linflex_console_putchar(earlycon_port,
+				earlycon_buf.content[i]);
+
+		kfree(earlycon_buf.content);
+		earlycon_buf.len = 0;
+	}
+
+	during_init = false;
+	spin_unlock_irqrestore(&init_lock, flags);
+
+done:
+	return ret;
+}
+
+static struct uart_driver linflex_reg;
+static struct console linflex_console = {
+	.name		= DEV_NAME,
+	.write		= linflex_console_write,
+	.device		= uart_console_device,
+	.setup		= linflex_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &linflex_reg,
+};
+
+static void linflex_earlycon_write(struct console *con, const char *s,
+				   unsigned int n)
+{
+	struct earlycon_device *dev = con->data;
+
+	uart_console_write(&dev->port, s, n, linflex_earlycon_putchar);
+}
+
+static int __init linflex_early_console_setup(struct earlycon_device *device,
+					      const char *options)
+{
+	if (!device->port.membase)
+		return -ENODEV;
+
+	device->con->write = linflex_earlycon_write;
+	earlycon_port = &device->port;
+
+	return 0;
+}
+
+OF_EARLYCON_DECLARE(linflex, "fsl,s32-linflexuart",
+		    linflex_early_console_setup);
+
+#define LINFLEX_CONSOLE	(&linflex_console)
+#else
+#define LINFLEX_CONSOLE	NULL
+#endif
+
+static struct uart_driver linflex_reg = {
+	.owner		= THIS_MODULE,
+	.driver_name	= DRIVER_NAME,
+	.dev_name	= DEV_NAME,
+	.nr		= ARRAY_SIZE(linflex_ports),
+	.cons		= LINFLEX_CONSOLE,
+};
+
+static int linflex_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct uart_port *sport;
+	struct resource *res;
+	int ret;
+
+	sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
+	if (!sport)
+		return -ENOMEM;
+
+	ret = of_alias_get_id(np, "serial");
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
+		return ret;
+	}
+	if (ret >= UART_NR) {
+		dev_err(&pdev->dev, "driver limited to %d serial ports\n",
+			UART_NR);
+		return -ENOMEM;
+	}
+
+	sport->line = ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	sport->mapbase = res->start;
+	sport->membase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sport->membase))
+		return PTR_ERR(sport->membase);
+
+	sport->dev = &pdev->dev;
+	sport->type = PORT_LINFLEXUART;
+	sport->iotype = UPIO_MEM;
+	sport->irq = platform_get_irq(pdev, 0);
+	sport->ops = &linflex_pops;
+	sport->flags = UPF_BOOT_AUTOCONF;
+
+	linflex_ports[sport->line] = sport;
+
+	platform_set_drvdata(pdev, sport);
+
+	ret = uart_add_one_port(&linflex_reg, sport);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int linflex_remove(struct platform_device *pdev)
+{
+	struct uart_port *sport = platform_get_drvdata(pdev);
+
+	uart_remove_one_port(&linflex_reg, sport);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int linflex_suspend(struct device *dev)
+{
+	struct uart_port *sport = dev_get_drvdata(dev);
+
+	uart_suspend_port(&linflex_reg, sport);
+
+	return 0;
+}
+
+static int linflex_resume(struct device *dev)
+{
+	struct uart_port *sport = dev_get_drvdata(dev);
+
+	uart_resume_port(&linflex_reg, sport);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(linflex_pm_ops, linflex_suspend, linflex_resume);
+
+static struct platform_driver linflex_driver = {
+	.probe		= linflex_probe,
+	.remove		= linflex_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table	= linflex_dt_ids,
+		.pm	= &linflex_pm_ops,
+	},
+};
+
+static int __init linflex_serial_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&linflex_reg);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&linflex_driver);
+	if (ret)
+		uart_unregister_driver(&linflex_reg);
+
+#ifdef CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE
+	spin_lock_init(&init_lock);
+#endif
+
+	return ret;
+}
+
+static void __exit linflex_serial_exit(void)
+{
+	platform_driver_unregister(&linflex_driver);
+	uart_unregister_driver(&linflex_reg);
+}
+
+module_init(linflex_serial_init);
+module_exit(linflex_serial_exit);
+
+MODULE_DESCRIPTION("Freescale linflex serial port driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 5642c05e0da0..25a3dead4473 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -293,4 +293,7 @@
 /* SiFive UART */
 #define PORT_SIFIVE_V0	120
 
+/* Freescale Linflex UART */
+#define PORT_LINFLEXUART	121
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
-- 
2.22.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v2 4/6] dt-bindings: serial: Document Freescale LINFlex UART
From: Stefan-gabriel Mirea @ 2019-08-09 11:29 UTC (permalink / raw)
  To: corbet@lwn.net, robh+dt@kernel.org, mark.rutland@arm.com,
	gregkh@linuxfoundation.org, catalin.marinas@arm.com,
	will@kernel.org, shawnguo@kernel.org, Leo Li
  Cc: devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
	Larisa Ileana Grigore, linux-kernel@vger.kernel.org,
	linux-serial@vger.kernel.org, jslaby@suse.com,
	Cosmin Stefan Stoica, linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190809112853.15846-1-stefan-gabriel.mirea@nxp.com>

From: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>

Add documentation for the serial communication interface module (LINFlex),
found in two instances on S32V234.

Signed-off-by: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>
Signed-off-by: Larisa Grigore <Larisa.Grigore@nxp.com>
Signed-off-by: Stefan-Gabriel Mirea <stefan-gabriel.mirea@nxp.com>
---
 .../bindings/serial/fsl,s32-linflexuart.txt   | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.txt

diff --git a/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.txt b/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.txt
new file mode 100644
index 000000000000..957ffeaca9f1
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/fsl,s32-linflexuart.txt
@@ -0,0 +1,24 @@
+* Freescale Linflex UART
+
+The LINFlexD controller implements several LIN protocol versions, as well as
+support for full-duplex UART communication through 8-bit and 9-bit frames. The
+Linflex UART driver enables operation only in UART mode.
+
+See chapter 47 ("LINFlexD") in the reference manual[1].
+
+Required properties:
+- compatible :
+  - "fsl,s32-linflexuart" for linflex configured in uart mode which
+  is compatible with the one integrated on S32V234 SoC
+- reg : Address and length of the register set for the device
+- interrupts : Should contain uart interrupt
+
+Example:
+uart0:serial@40053000 {
+	compatible = "fsl,s32-linflexuart";
+	reg = <0x0 0x40053000 0x0 0x1000>;
+	interrupts = <0 59 4>;
+	status = "disabled";
+};
+
+[1] https://www.nxp.com/webapp/Download?colCode=S32V234RM
-- 
2.22.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v2 3/6] arm64: dts: fsl: Add device tree for S32V234-EVB
From: Stefan-gabriel Mirea @ 2019-08-09 11:29 UTC (permalink / raw)
  To: corbet@lwn.net, robh+dt@kernel.org, mark.rutland@arm.com,
	gregkh@linuxfoundation.org, catalin.marinas@arm.com,
	will@kernel.org, shawnguo@kernel.org, Leo Li
  Cc: devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
	Larisa Ileana Grigore, linux-kernel@vger.kernel.org, Dan Nica,
	linux-serial@vger.kernel.org, jslaby@suse.com,
	Cosmin Stefan Stoica, linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190809112853.15846-1-stefan-gabriel.mirea@nxp.com>

From: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>

Add initial version of device tree for S32V234-EVB, including nodes for the
4 Cortex-A53 cores, AIPS bus with UART modules, ARM architected timer and
Generic Interrupt Controller (GIC).

Keep SoC level separate from board level to let future boards with this SoC
share common properties, while the dts files will keep board-dependent
properties.

Signed-off-by: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>
Signed-off-by: Mihaela Martinas <Mihaela.Martinas@freescale.com>
Signed-off-by: Dan Nica <dan.nica@nxp.com>
Signed-off-by: Larisa Grigore <Larisa.Grigore@nxp.com>
Signed-off-by: Phu Luu An <phu.luuan@nxp.com>
Signed-off-by: Stefan-Gabriel Mirea <stefan-gabriel.mirea@nxp.com>
---
 arch/arm64/boot/dts/freescale/Makefile        |   2 +
 .../boot/dts/freescale/fsl-s32v234-evb.dts    |  24 ++++
 .../arm64/boot/dts/freescale/fsl-s32v234.dtsi | 130 ++++++++++++++++++
 3 files changed, 156 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/fsl-s32v234-evb.dts
 create mode 100644 arch/arm64/boot/dts/freescale/fsl-s32v234.dtsi

diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index c043aca66572..3af29b58a833 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -26,3 +26,5 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mq-librem5-devkit.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-rmb3.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8mq-zii-ultra-zest.dtb
 dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb
+
+dtb-$(CONFIG_ARCH_S32) += fsl-s32v234-evb.dtb
diff --git a/arch/arm64/boot/dts/freescale/fsl-s32v234-evb.dts b/arch/arm64/boot/dts/freescale/fsl-s32v234-evb.dts
new file mode 100644
index 000000000000..92bf6c5563a3
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-s32v234-evb.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ */
+
+/dts-v1/;
+#include "fsl-s32v234.dtsi"
+
+/ {
+	compatible = "fsl,s32v234-evb", "fsl,s32v234";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-s32v234.dtsi b/arch/arm64/boot/dts/freescale/fsl-s32v234.dtsi
new file mode 100644
index 000000000000..6d686d3ba997
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/fsl-s32v234.dtsi
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2016-2018 NXP
+ */
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+	model = "Freescale S32V234";
+	compatible = "fsl,s32v234";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x0 0x0>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x80000000>;
+			next-level-cache = <&cluster0_l2_cache>;
+		};
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x0 0x1>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x80000000>;
+			next-level-cache = <&cluster0_l2_cache>;
+		};
+		cpu2: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x0 0x100>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x80000000>;
+			next-level-cache = <&cluster1_l2_cache>;
+		};
+		cpu3: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x0 0x101>;
+			enable-method = "spin-table";
+			cpu-release-addr = <0x0 0x80000000>;
+			next-level-cache = <&cluster1_l2_cache>;
+		};
+
+		cluster0_l2_cache: l2-cache0 {
+			compatible = "cache";
+		};
+
+		cluster1_l2_cache: l2-cache1 {
+			compatible = "cache";
+		};
+	};
+
+	soc {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		aips0: aips-bus@40000000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			interrupt-parent = <&gic>;
+			reg = <0x0 0x40000000 0x0 0x7D000>;
+			ranges;
+
+			uart0: serial@40053000 {
+				compatible = "fsl,s32-linflexuart";
+				reg = <0x0 0x40053000 0x0 0x1000>;
+				interrupts = <0 59 1>;
+				status = "disabled";
+			};
+		};
+
+		aips1: aips-bus@40080000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			interrupt-parent = <&gic>;
+			reg = <0x0 0x40080000 0x0 0x70000>;
+			ranges;
+
+			uart1: serial@400bc000 {
+				compatible = "fsl,s32-linflexuart";
+				reg = <0x0 0x400bc000 0x0 0x1000>;
+				interrupts = <0 60 1>;
+				status = "disabled";
+			};
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
+		/* clock-frequency might be modified by u-boot, depending on the
+		 * chip version.
+		 */
+		clock-frequency = <10000000>;
+	};
+
+	gic: interrupt-controller@7d001000 {
+		compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg = <0 0x7d001000 0 0x1000>,
+		      <0 0x7d002000 0 0x2000>,
+		      <0 0x7d004000 0 0x2000>,
+		      <0 0x7d006000 0 0x2000>;
+		interrupts = <1 9 0xf04>;
+	};
+};
-- 
2.22.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v2 1/6] dt-bindings: arm: fsl: Add the S32V234-EVB board
From: Stefan-gabriel Mirea @ 2019-08-09 11:29 UTC (permalink / raw)
  To: corbet@lwn.net, robh+dt@kernel.org, mark.rutland@arm.com,
	gregkh@linuxfoundation.org, catalin.marinas@arm.com,
	will@kernel.org, shawnguo@kernel.org, Leo Li
  Cc: devicetree@vger.kernel.org, Eddy Petrisor,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-serial@vger.kernel.org, jslaby@suse.com,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190809112853.15846-1-stefan-gabriel.mirea@nxp.com>

From: Eddy Petrișor <eddy.petrisor@nxp.com>

Add entry for the NXP S32V234 Customer Evaluation Board to the board/SoC
bindings.

Signed-off-by: Eddy Petrișor <eddy.petrisor@nxp.com>
Signed-off-by: Stefan-Gabriel Mirea <stefan-gabriel.mirea@nxp.com>
---
 Documentation/devicetree/bindings/arm/fsl.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index 7294ac36f4c0..597c563bdec9 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -309,4 +309,10 @@ properties:
               - fsl,ls2088a-rdb
           - const: fsl,ls2088a
 
+      - description: S32V234 based Boards
+        items:
+          - enum:
+              - fsl,s32v234-evb           # S32V234-EVB2 Customer Evaluation Board
+          - const: fsl,s32v234
+
 ...
-- 
2.22.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v2 2/6] arm64: Introduce config for S32
From: Stefan-gabriel Mirea @ 2019-08-09 11:29 UTC (permalink / raw)
  To: corbet@lwn.net, robh+dt@kernel.org, mark.rutland@arm.com,
	gregkh@linuxfoundation.org, catalin.marinas@arm.com,
	will@kernel.org, shawnguo@kernel.org, Leo Li
  Cc: devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
	jslaby@suse.com, Cosmin Stefan Stoica,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190809112853.15846-1-stefan-gabriel.mirea@nxp.com>

From: Mihaela Martinas <Mihaela.Martinas@freescale.com>

Add configuration option for the Freescale S32 platform family in
Kconfig.platforms. For starters, the only SoC supported will be Treerunner
(S32V234), with a single execution target: the S32V234-EVB (rev 29288)
board.

Signed-off-by: Mihaela Martinas <Mihaela.Martinas@freescale.com>
Signed-off-by: Stoica Cosmin-Stefan <cosmin.stoica@nxp.com>
Signed-off-by: Stefan-Gabriel Mirea <stefan-gabriel.mirea@nxp.com>
---
 arch/arm64/Kconfig.platforms | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 4778c775de1b..a9a6152d37eb 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -210,6 +210,11 @@ config ARCH_ROCKCHIP
 	  This enables support for the ARMv8 based Rockchip chipsets,
 	  like the RK3368.
 
+config ARCH_S32
+	bool "Freescale S32 SoC Family"
+	help
+	  This enables support for the Freescale S32 family of processors.
+
 config ARCH_SEATTLE
 	bool "AMD Seattle SoC Family"
 	help
-- 
2.22.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ 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