Devicetree
 help / color / mirror / Atom feed
* [PATCH v8 08/21] clk: tegra: periph: Add restore_context support
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm
In-Reply-To: <1565308020-31952-1-git-send-email-skomatineni@nvidia.com>

This patch implements restore_context support for clk-periph and
clk-sdmmc-mux clock operations to restore clock parent and rates
on system resume.

During system suspend, core power goes off and looses the context
of the Tegra clock controller registers.

So on system resume, clocks parent and rate are restored back to
the context before suspend based on cached data.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-periph.c    | 18 ++++++++++++++++++
 drivers/clk/tegra/clk-sdmmc-mux.c | 12 ++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 58437da25156..c9d28cbadccc 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
  */
 
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/export.h>
 #include <linux/slab.h>
@@ -99,6 +100,20 @@ static void clk_periph_disable(struct clk_hw *hw)
 	gate_ops->disable(gate_hw);
 }
 
+static void clk_periph_restore_context(struct clk_hw *hw)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *div_ops = periph->div_ops;
+	struct clk_hw *div_hw = &periph->divider.hw;
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	int parent_id = clk_hw_get_parent_index(hw, parent);
+
+	if (!(periph->gate.flags & TEGRA_PERIPH_NO_DIV))
+		div_ops->restore_context(div_hw);
+
+	clk_periph_set_parent(hw, parent_id);
+}
+
 const struct clk_ops tegra_clk_periph_ops = {
 	.get_parent = clk_periph_get_parent,
 	.set_parent = clk_periph_set_parent,
@@ -108,6 +123,7 @@ const struct clk_ops tegra_clk_periph_ops = {
 	.is_enabled = clk_periph_is_enabled,
 	.enable = clk_periph_enable,
 	.disable = clk_periph_disable,
+	.restore_context = clk_periph_restore_context,
 };
 
 static const struct clk_ops tegra_clk_periph_nodiv_ops = {
@@ -116,6 +132,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = {
 	.is_enabled = clk_periph_is_enabled,
 	.enable = clk_periph_enable,
 	.disable = clk_periph_disable,
+	.restore_context = clk_periph_restore_context,
 };
 
 static const struct clk_ops tegra_clk_periph_no_gate_ops = {
@@ -124,6 +141,7 @@ static const struct clk_ops tegra_clk_periph_no_gate_ops = {
 	.recalc_rate = clk_periph_recalc_rate,
 	.round_rate = clk_periph_round_rate,
 	.set_rate = clk_periph_set_rate,
+	.restore_context = clk_periph_restore_context,
 };
 
 static struct clk *_tegra_clk_register_periph(const char *name,
diff --git a/drivers/clk/tegra/clk-sdmmc-mux.c b/drivers/clk/tegra/clk-sdmmc-mux.c
index a5cd3e31dbae..8db48966b100 100644
--- a/drivers/clk/tegra/clk-sdmmc-mux.c
+++ b/drivers/clk/tegra/clk-sdmmc-mux.c
@@ -194,6 +194,17 @@ static void clk_sdmmc_mux_disable(struct clk_hw *hw)
 	gate_ops->disable(gate_hw);
 }
 
+static void clk_sdmmc_mux_restore_context(struct clk_hw *hw)
+{
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	unsigned long parent_rate = clk_hw_get_rate(parent);
+	unsigned long rate = clk_hw_get_rate(hw);
+	int parent_id = clk_hw_get_parent_index(hw, parent);
+
+	clk_sdmmc_mux_set_parent(hw, parent_id);
+	clk_sdmmc_mux_set_rate(hw, rate, parent_rate);
+}
+
 static const struct clk_ops tegra_clk_sdmmc_mux_ops = {
 	.get_parent = clk_sdmmc_mux_get_parent,
 	.set_parent = clk_sdmmc_mux_set_parent,
@@ -203,6 +214,7 @@ static const struct clk_ops tegra_clk_sdmmc_mux_ops = {
 	.is_enabled = clk_sdmmc_mux_is_enabled,
 	.enable = clk_sdmmc_mux_enable,
 	.disable = clk_sdmmc_mux_disable,
+	.restore_context = clk_sdmmc_mux_restore_context,
 };
 
 struct clk *tegra_clk_register_sdmmc_mux_div(const char *name,
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 07/21] clk: Add API to get index of the clock parent
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm
In-Reply-To: <1565308020-31952-1-git-send-email-skomatineni@nvidia.com>

This patch adds an API clk_hw_get_parent_index to get index of the
clock parent to use during the clock restore operations on system
resume.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/clk.c            | 17 +++++++++++++++++
 include/linux/clk-provider.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c0990703ce54..f26252e48f73 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1643,6 +1643,23 @@ static int clk_fetch_parent_index(struct clk_core *core,
 	return i;
 }
 
+/**
+ * clk_hw_get_parent_index - return the index of parent clock
+ * @hw: clk_hw associated with the clk being consumed
+ * @parent_hw: clk_hw associated with the parent of clk
+ *
+ * Fetches and returns the index of parent clock.
+ * if hw or parent_hw is NULL, returns -EINVAL.
+ */
+int clk_hw_get_parent_index(struct clk_hw *hw, struct clk_hw *parent_hw)
+{
+	if (!hw || !parent_hw)
+		return -EINVAL;
+
+	return clk_fetch_parent_index(hw->core, parent_hw->core);
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_parent_index);
+
 /*
  * Update the orphan status of @core and all its children.
  */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 2ae7604783dd..477112946dd2 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -817,6 +817,7 @@ unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
 struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
 struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
 					  unsigned int index);
+int clk_hw_get_parent_index(struct clk_hw *hw, struct clk_hw *parent_hw);
 unsigned int __clk_get_enable_count(struct clk *clk);
 unsigned long clk_hw_get_rate(const struct clk_hw *hw);
 unsigned long __clk_get_flags(struct clk *clk);
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 06/21] clk: tegra: Support for OSC context save and restore
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm
In-Reply-To: <1565308020-31952-1-git-send-email-skomatineni@nvidia.com>

This patch adds support for saving OSC clock frequency and the
drive-strength during OSC clock init and creates an API to restore
OSC control register value from the saved context.

This API is invoked by Tegra210 clock driver during system resume
to restore the  OSC clock settings.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-tegra-fixed.c | 15 +++++++++++++++
 drivers/clk/tegra/clk.h             |  1 +
 2 files changed, 16 insertions(+)

diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c
index 8d91b2b191cf..7c6c8abfcde6 100644
--- a/drivers/clk/tegra/clk-tegra-fixed.c
+++ b/drivers/clk/tegra/clk-tegra-fixed.c
@@ -17,6 +17,10 @@
 #define OSC_CTRL			0x50
 #define OSC_CTRL_OSC_FREQ_SHIFT		28
 #define OSC_CTRL_PLL_REF_DIV_SHIFT	26
+#define OSC_CTRL_MASK			(0x3f2 |	\
+					(0xf << OSC_CTRL_OSC_FREQ_SHIFT))
+
+static u32 osc_ctrl_ctx;
 
 int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
 			      unsigned long *input_freqs, unsigned int num,
@@ -29,6 +33,7 @@ int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
 	unsigned osc_idx;
 
 	val = readl_relaxed(clk_base + OSC_CTRL);
+	osc_ctrl_ctx = val & OSC_CTRL_MASK;
 	osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;
 
 	if (osc_idx < num)
@@ -96,3 +101,13 @@ void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
 		*dt_clk = clk;
 	}
 }
+
+void tegra_clk_osc_resume(void __iomem *clk_base)
+{
+	u32 val;
+
+	val = readl_relaxed(clk_base + OSC_CTRL) & ~OSC_CTRL_MASK;
+	val |= osc_ctrl_ctx;
+	writel_relaxed(val, clk_base + OSC_CTRL);
+	fence_udelay(2, clk_base);
+}
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index dc546292e030..8a9af45b6084 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -837,6 +837,7 @@ u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate);
 int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div);
 int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
 		 u8 frac_width, u8 flags);
+void tegra_clk_osc_resume(void __iomem *clk_base);
 
 
 /* Combined read fence with delay */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 05/21] clk: tegra: pll: Save and restore pll context
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm
In-Reply-To: <1565308020-31952-1-git-send-email-skomatineni@nvidia.com>

This patch implements save and restore of PLL context.

During system suspend, core power goes off and looses the settings
of the Tegra CAR controller registers.

So during suspend entry pll context is stored and on resume it is
restored back along with its state.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-pll.c | 88 ++++++++++++++++++++++++++++-----------------
 drivers/clk/tegra/clk.h     |  2 ++
 2 files changed, 58 insertions(+), 32 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 1583f5fc992f..e52add2bbdbb 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -1008,6 +1008,28 @@ static unsigned long clk_plle_recalc_rate(struct clk_hw *hw,
 	return rate;
 }
 
+static void tegra_clk_pll_restore_context(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	unsigned long parent_rate = clk_hw_get_rate(parent);
+	unsigned long rate = clk_hw_get_rate(hw);
+	u32 val;
+
+	if (clk_pll_is_enabled(hw))
+		return;
+
+	if (pll->params->set_defaults)
+		pll->params->set_defaults(pll);
+
+	clk_pll_set_rate(hw, rate, parent_rate);
+
+	if (!__clk_get_enable_count(hw->clk))
+		clk_pll_disable(hw);
+	else
+		clk_pll_enable(hw);
+}
+
 const struct clk_ops tegra_clk_pll_ops = {
 	.is_enabled = clk_pll_is_enabled,
 	.enable = clk_pll_enable,
@@ -1015,6 +1037,7 @@ const struct clk_ops tegra_clk_pll_ops = {
 	.recalc_rate = clk_pll_recalc_rate,
 	.round_rate = clk_pll_round_rate,
 	.set_rate = clk_pll_set_rate,
+	.restore_context = tegra_clk_pll_restore_context,
 };
 
 const struct clk_ops tegra_clk_plle_ops = {
@@ -1802,6 +1825,27 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw)
 
 	return ret;
 }
+
+static void _clk_plle_tegra_init_parent(struct tegra_clk_pll *pll)
+{
+	u32 val, val_aux;
+
+	/* ensure parent is set to pll_ref */
+	val = pll_readl_base(pll);
+	val_aux = pll_readl(pll->params->aux_reg, pll);
+
+	if (val & PLL_BASE_ENABLE) {
+		if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
+		    (val_aux & PLLE_AUX_PLLP_SEL))
+			WARN(1, "pll_e enabled with unsupported parent %s\n",
+			     (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
+			     "pll_re_vco");
+	} else {
+		val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
+		pll_writel(val_aux, pll->params->aux_reg, pll);
+		fence_udelay(1, pll->clk_base);
+	}
+}
 #endif
 
 static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
@@ -2214,27 +2258,12 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
 {
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
-	u32 val, val_aux;
 
 	pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
 
-	/* ensure parent is set to pll_re_vco */
-
-	val = pll_readl_base(pll);
-	val_aux = pll_readl(pll_params->aux_reg, pll);
-
-	if (val & PLL_BASE_ENABLE) {
-		if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
-			(val_aux & PLLE_AUX_PLLP_SEL))
-			WARN(1, "pll_e enabled with unsupported parent %s\n",
-			  (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
-					"pll_re_vco");
-	} else {
-		val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
-		pll_writel(val_aux, pll_params->aux_reg, pll);
-	}
+	_clk_plle_tegra_init_parent(pll);
 
 	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
 				      &tegra_clk_plle_tegra114_ops);
@@ -2276,6 +2305,7 @@ static const struct clk_ops tegra_clk_pllss_ops = {
 	.recalc_rate = clk_pll_recalc_rate,
 	.round_rate = clk_pll_ramp_round_rate,
 	.set_rate = clk_pllxc_set_rate,
+	.restore_context = tegra_clk_pll_restore_context,
 };
 
 struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
@@ -2375,6 +2405,7 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name,
 		pll_params->vco_min = pll_params->adjust_vco(pll_params,
 							     parent_rate);
 
+	pll_params->flags |= TEGRA_PLLRE;
 	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
@@ -2520,11 +2551,19 @@ static void clk_plle_tegra210_disable(struct clk_hw *hw)
 		spin_unlock_irqrestore(pll->lock, flags);
 }
 
+static void tegra_clk_plle_t210_restore_context(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+
+	_clk_plle_tegra_init_parent(pll);
+}
+
 static const struct clk_ops tegra_clk_plle_tegra210_ops = {
 	.is_enabled =  clk_plle_tegra210_is_enabled,
 	.enable = clk_plle_tegra210_enable,
 	.disable = clk_plle_tegra210_disable,
 	.recalc_rate = clk_pll_recalc_rate,
+	.restore_context = tegra_clk_plle_t210_restore_context,
 };
 
 struct clk *tegra_clk_register_plle_tegra210(const char *name,
@@ -2535,27 +2574,12 @@ struct clk *tegra_clk_register_plle_tegra210(const char *name,
 {
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
-	u32 val, val_aux;
 
 	pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
 	if (IS_ERR(pll))
 		return ERR_CAST(pll);
 
-	/* ensure parent is set to pll_re_vco */
-
-	val = pll_readl_base(pll);
-	val_aux = pll_readl(pll_params->aux_reg, pll);
-
-	if (val & PLLE_BASE_ENABLE) {
-		if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
-			(val_aux & PLLE_AUX_PLLP_SEL))
-			WARN(1, "pll_e enabled with unsupported parent %s\n",
-			  (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
-					"pll_re_vco");
-	} else {
-		val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
-		pll_writel(val_aux, pll_params->aux_reg, pll);
-	}
+	_clk_plle_tegra_init_parent(pll);
 
 	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
 				      &tegra_clk_plle_tegra210_ops);
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index a464524fbc90..dc546292e030 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -233,6 +233,7 @@ struct tegra_clk_pll;
  * TEGRA_PLLMB - PLLMB has should be treated similar to PLLM. This
  *     flag indicated that it is PLLMB.
  * TEGRA_PLL_VCO_OUT - Used to indicate that the PLL has a VCO output
+ * TEGRA_PLLRE - Used to indicate that it is PLLRE
  */
 struct tegra_clk_pll_params {
 	unsigned long	input_min;
@@ -299,6 +300,7 @@ struct tegra_clk_pll_params {
 #define TEGRA_MDIV_NEW BIT(11)
 #define TEGRA_PLLMB BIT(12)
 #define TEGRA_PLL_VCO_OUT BIT(13)
+#define TEGRA_PLLRE BIT(14)
 
 /**
  * struct tegra_clk_pll - Tegra PLL clock
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 04/21] clk: tegra: pllout: Save and restore pllout context
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm
In-Reply-To: <1565308020-31952-1-git-send-email-skomatineni@nvidia.com>

This patch implements save and restore of pllout context.

During system suspend, core power goes off and looses the settings
of the Tegra CAR controller registers.

So during suspend entry the state of pllout is saved and on resume
it is restored back to have pllout in same state as before suspend.

pllout rate is saved and restore in clock divider so it will be at
same rate as before suspend when pllout state is restored.

Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-pll-out.c  | 9 +++++++++
 drivers/clk/tegra/clk-tegra210.c | 3 ++-
 drivers/clk/tegra/clk.h          | 6 ++++++
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-pll-out.c b/drivers/clk/tegra/clk-pll-out.c
index 35f2bf00e1e6..d8bf89a81e6d 100644
--- a/drivers/clk/tegra/clk-pll-out.c
+++ b/drivers/clk/tegra/clk-pll-out.c
@@ -69,10 +69,19 @@ static void clk_pll_out_disable(struct clk_hw *hw)
 		spin_unlock_irqrestore(pll_out->lock, flags);
 }
 
+static void tegra_clk_pll_out_restore_context(struct clk_hw *hw)
+{
+	if (!__clk_get_enable_count(hw->clk))
+		clk_pll_out_disable(hw);
+	else
+		clk_pll_out_enable(hw);
+}
+
 const struct clk_ops tegra_clk_pll_out_ops = {
 	.is_enabled = clk_pll_out_is_enabled,
 	.enable = clk_pll_out_enable,
 	.disable = clk_pll_out_disable,
+	.restore_context = tegra_clk_pll_out_restore_context,
 };
 
 struct clk *tegra_clk_register_pll_out(const char *name,
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index df172d5772d7..4721ee030d1c 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -3200,7 +3200,8 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
 					 8, 8, 1, NULL);
 	clk = tegra_clk_register_pll_out("pll_re_out1", "pll_re_out1_div",
 					 clk_base + PLLRE_OUT1, 1, 0,
-					 CLK_SET_RATE_PARENT, 0, NULL);
+					 CLK_SET_RATE_PARENT, TEGRA_PLLRE_OUT,
+					 NULL);
 	clks[TEGRA210_CLK_PLL_RE_OUT1] = clk;
 
 	/* PLLE */
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 905bf1096558..a464524fbc90 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -437,6 +437,10 @@ struct clk *tegra_clk_register_pllu_tegra210(const char *name,
  * @rst_bit_idx:	bit to reset PLL divider
  * @lock:		register lock
  * @flags:		hardware-specific flags
+ *
+ * Flags:
+ * TEGRA_PLLRE_OUT - This flag indicates that it is PLLRE_OUT and is used to
+ *		     identify PLLRE_OUT during clk_pll_out save and restore.
  */
 struct tegra_clk_pll_out {
 	struct clk_hw	hw;
@@ -447,6 +451,8 @@ struct tegra_clk_pll_out {
 	u8		flags;
 };
 
+#define TEGRA_PLLRE_OUT BIT(0)
+
 #define to_clk_pll_out(_hw) container_of(_hw, struct tegra_clk_pll_out, hw)
 
 extern const struct clk_ops tegra_clk_pll_out_ops;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 03/21] clk: tegra: divider: Save and restore divider rate
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm
In-Reply-To: <1565308020-31952-1-git-send-email-skomatineni@nvidia.com>

This patch implements context restore for clock divider.

During system suspend, core power goes off and looses the settings
of the Tegra CAR controller registers.

So on resume, clock dividers are restored back for normal operation.

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-divider.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
index e76731fb7d69..ca0de5f11f84 100644
--- a/drivers/clk/tegra/clk-divider.c
+++ b/drivers/clk/tegra/clk-divider.c
@@ -109,10 +109,21 @@ static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate,
 	return 0;
 }
 
+static void clk_divider_restore_context(struct clk_hw *hw)
+{
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	unsigned long parent_rate = clk_hw_get_rate(parent);
+	unsigned long rate = clk_hw_get_rate(hw);
+
+	if (clk_frac_div_set_rate(hw, rate, parent_rate) < 0)
+		WARN_ON(1);
+}
+
 const struct clk_ops tegra_clk_frac_div_ops = {
 	.recalc_rate = clk_frac_div_recalc_rate,
 	.set_rate = clk_frac_div_set_rate,
 	.round_rate = clk_frac_div_round_rate,
+	.restore_context = clk_divider_restore_context,
 };
 
 struct clk *tegra_clk_register_divider(const char *name,
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 02/21] pinctrl: tegra: Add write barrier after all pinctrl register writes
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm
In-Reply-To: <1565308020-31952-1-git-send-email-skomatineni@nvidia.com>

This patch adds write barrier after all pinctrl register writes
during resume to make sure all pinctrl changes are complete.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/pinctrl/tegra/pinctrl-tegra.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index 982ee634b3b1..f49fe29fb6df 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -677,6 +677,8 @@ static int tegra_pinctrl_resume(struct device *dev)
 			writel_relaxed(*backup_regs++, regs++);
 	}
 
+	/* make sure all the pinmux register writes are complete */
+	wmb();
 	return 0;
 }
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 01/21] pinctrl: tegra: Fix write barrier placement in pmx_writel
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm
In-Reply-To: <1565308020-31952-1-git-send-email-skomatineni@nvidia.com>

pmx_writel uses writel which inserts write barrier before the
register write rather.

This patch has fix to replace writel with writel_relaxed followed
by a write barrier to ensure write operation before the barrier
is completed for successful pinctrl change.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/pinctrl/tegra/pinctrl-tegra.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index e3a237534281..982ee634b3b1 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -32,7 +32,9 @@ static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg)
 
 static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
 {
-	writel(val, pmx->regs[bank] + reg);
+	writel_relaxed(val, pmx->regs[bank] + reg);
+	/* make sure pinmux register write completed */
+	wmb();
 }
 
 static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
-- 
2.7.4

^ permalink raw reply related

* [PATCH v8 00/21] SC7 entry and exit support for Tegra210
From: Sowjanya Komatineni @ 2019-08-08 23:46 UTC (permalink / raw)
  To: thierry.reding, jonathanh, tglx, jason, marc.zyngier,
	linus.walleij, stefan, mark.rutland
  Cc: pdeschrijver, pgaikwad, sboyd, linux-clk, linux-gpio, jckuo,
	josephl, talho, skomatineni, linux-tegra, linux-kernel,
	mperttunen, spatra, robh+dt, digetx, devicetree, rjw,
	viresh.kumar, linux-pm

This patch series includes Tegra210 deepsleep (SC7) support with RTC alarm
wake event.

This series also includes save and restore of PLLs, clocks, OSC contexts
for deepsleep exit to normal operation.

This patch series doesn't support 100% suspend/resume to allow fully
functional state upon resume and we are working on some more drivers suspend
and resume implementations.

[v8]: Changes between v7 & v8 are
	- v7 feedback fixes
	- moved clock enable/disable state and reset enable/disable state
	  restore from clk_save/restore_context back to clk-tegra210 driver
	  to do complete register value store/restore.
	- Removed manual store/restore of peripheral parent context and added
	  API in clk core to retrieve clock parent index to use during
	  restoring parent on resume.
	- Implemented Tegra recommended clock source programming sequence
	  during restore (CLK ENB ON followed by divider/source programming
	  followed by restoring CLK ENB ON/OFF state followed by restoring
	  RST state).
	- Removed pinctrl suspend/resume patch from this series as pinctrl
	  suspend/resume patch from v7 got acked and merged.
	- Added pinctrl patch-0001 to update pmx_writel for proper placement
	  of write barrier.
	- Added pinctrl patch-0002 to insert write barrier after all pinctrl
	  register writes during pinctrl resume.

	Note:
	  Below patch is also needed for SC7 support as GPIO restore need
	  to happen prior to pinctrl.
	  https://patchwork.kernel.org/patch/11012077/

[v7]: Changes between V6 & v7 are
	- V6 feedback fixes
	- Removed patch-0001 from V6 which keeps COP IRQ enabled. Looking
	  more into ATF FW, it loads SC7 entry FW into IRAM and sets the
	  COP reset vector to SC7 FW load address and resets COP. So, COP
	  IRQ can be cleared during suspend.

	Note:
	  Below patch is also needed for SC7 support as GPIO restore need
	  to happen prior to pinctrl.
	  https://patchwork.kernel.org/patch/11012077/

[V6]: Changes between V5 & V6 are
	- V5 feedback fixes
	- DFLL suspend and resume moved to DFLL clock driver
	- Add suspend and resume support for CPUFreq driver to explicitly
	  switch source to safe source of PLLP and disable DFLL clock.
	- Fix to super clock driver to enable PLLP branch to CPU before
	  source switch to PLLP.
	- Added save and restore support for super clock driver.

[V5]: Changes between V4 & V5 are
	- V4 feedback fixes

[V4]: Changes between V3 & V4 are
	- V3 feedback fixes
	- Removed park bits clear for EMMC pads in pinctrl-tegra driver
	  function tegra_pinctrl_clear_parked_bits as based on V3 feedback
	  parked_bit is updated to parked_bitmask to use with DRV_PINGROUP
	  as well and thierry posted patch series for this.
	- Implemented all peripheral clocks save and restore through their
	  corresponding clk_ops save_context and restore_context and removed
	  all direct registers store and restore in clk-tegra210 driver.
	- Created separate patch for fence_delay update during PLLU init based
	  on V3 feedback.
	- Added more comments in tegra210_clk_resume regarding dfll restore
	  sequence and its dependency on peripheral clocks restore.

[V3]: Changes between V2 & V3 are
	- V2 feedback fixes
	- GPIO restore should happen prior to Pinctrl restore to prevent
	  glitch on GPIO lines. So using resume_noirq for gpio tegra to allow
	  gpio resume prior to pinctrl resume.
	- Implemented save_context and restore_context callbacks for clock
	  plls, pll outs and dividers in corresponding drivers.
	  Note: Peripheral clocks and clock enable and reset need to be in
	  Tegra210 clock suspend/resume as they need to be in proper sequence
	  w.r.t DFLL resume for restoring CPU clock.
	- Removed gpio-tegra changes for hierarchical support to have PMC as
	  parent to GPIOs for GPIO wake event support. Thierry is working on
	  gpiolib for some cleanup before adding hierarchical support. So
	  holding on to GPIO wake support for now.

[V2] : V1 feedback fixes
	Patch 0002: This version still using syscore. Thierry suggest not to
	use syscore and waiting on suggestion from Linux Walleij for any better
	way of storing current state of pins before suspend entry and restoring
	them on resume at very early stage. So left this the same way as V1 and
	will address once I get more feedback on this.
	Also need to findout and implement proper way of forcing resume order
	between pinctrl and gpio driver.

[V1]:	Tegra210 SC7 entry and exit thru RTC wake and Power button GPIO wake
	using hierarchical IRQ with PMC as parent to GPIO.


Sowjanya Komatineni (21):
  pinctrl: tegra: Fix write barrier placement in pmx_writel
  pinctrl: tegra: Add write barrier after all pinctrl register writes
  clk: tegra: divider: Save and restore divider rate
  clk: tegra: pllout: Save and restore pllout context
  clk: tegra: pll: Save and restore pll context
  clk: tegra: Support for OSC context save and restore
  clk: Add API to get index of the clock parent
  clk: tegra: periph: Add restore_context support
  clk: tegra: clk-super: Fix to enable PLLP branches to CPU
  clk: tegra: clk-super: Add restore-context support
  clk: tegra: clk-dfll: Add suspend and resume support
  cpufreq: tegra124: Add suspend and resume support
  clk: tegra210: Use fence_udelay during PLLU init
  clk: tegra210: Add suspend and resume support
  soc/tegra: pmc: Allow to support more tegras wake
  soc/tegra: pmc: Add pmc wake support for tegra210
  arm64: tegra: Enable wake from deep sleep on RTC alarm
  soc/tegra: pmc: Configure core power request polarity
  soc/tegra: pmc: Configure deep sleep control settings
  arm64: dts: tegra210-p2180: Jetson TX1 SC7 timings
  arm64: dts: tegra210-p3450: Jetson Nano SC7 timings

 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi     |   7 ++
 arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts |   7 ++
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |   5 +-
 drivers/clk/clk.c                                  |  17 +++
 drivers/clk/tegra/clk-dfll.c                       |  56 +++++++++
 drivers/clk/tegra/clk-dfll.h                       |   2 +
 drivers/clk/tegra/clk-divider.c                    |  11 ++
 drivers/clk/tegra/clk-periph.c                     |  18 +++
 drivers/clk/tegra/clk-pll-out.c                    |   9 ++
 drivers/clk/tegra/clk-pll.c                        |  88 +++++++++-----
 drivers/clk/tegra/clk-sdmmc-mux.c                  |  12 ++
 drivers/clk/tegra/clk-super.c                      |  35 ++++++
 drivers/clk/tegra/clk-tegra-fixed.c                |  15 +++
 drivers/clk/tegra/clk-tegra-super-gen4.c           |   7 +-
 drivers/clk/tegra/clk-tegra124-dfll-fcpu.c         |   1 +
 drivers/clk/tegra/clk-tegra210.c                   | 114 ++++++++++++++++--
 drivers/clk/tegra/clk.c                            |  78 +++++++++++++
 drivers/clk/tegra/clk.h                            |  17 +++
 drivers/cpufreq/tegra124-cpufreq.c                 |  60 ++++++++++
 drivers/pinctrl/tegra/pinctrl-tegra.c              |   6 +-
 drivers/soc/tegra/pmc.c                            | 129 ++++++++++++++++++++-
 include/linux/clk-provider.h                       |   1 +
 22 files changed, 646 insertions(+), 49 deletions(-)

-- 
2.7.4

^ permalink raw reply

* Re: [PATCH 0/3] Add basic support for RTC on Allwinner H6 SoC
From: Alexandre Belloni @ 2019-08-08 23:39 UTC (permalink / raw)
  To: Chen-Yu Tsai, Mark Rutland, Alessandro Zummo, devicetree,
	Maxime Ripard, linux-kernel, linux-sunxi, Rob Herring,
	linux-arm-kernel, linux-rtc-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20190808121237.g6twq2nh3sayu3vx-9v8tmBix7cb9zxVx7UNMDg@public.gmane.org>

On 08/08/2019 14:12:37+0200, Ondřej Jirman wrote:
> On Wed, Aug 07, 2019 at 12:55:02PM +0200, Alexandre Belloni wrote:
> > Hi,
> > 
> > On 06/08/2019 20:30:45+0200, Ondřej Jirman wrote:
> > > Maybe whether XO or DCXO is used also matters if you want to do some fine
> > > tunning of DCXO (control register has pletny of options), but that's probably
> > > better done in u-boot. And there's still no need to read HOSC source from DT.
> > > The driver can just check compatible, and if it is H6 and OSC_CLK_SRC_SEL is 1,
> > > it can do it's DCXO tunning, or whatever. But neither OS nor bootloader will
> > > be using this info to gate/disable the osciallator.
> > > 
> > 
> > It is actually useful to be able to tweak the crystal tuning at
> > runtime to be able to reduce clock drift and compare with a reliable
> > source (e.g. NTP).
> 
> I don't think there's a Linux kernel API that you can use to achieve that, so
> that's a rather theoretical concern at the moment.
> 

There is /sys/class/rtc/rtcX/offset which is even properly documented.

The reason I asked is that some RTCs have both analog (changing the
oscillator capacitance) and digital (changing the RTC counter) so I'm
wondering whether this interface should be extended.

> Also there are multiple clocks, that can drive the RTC, and you usually don't
> drive it from 24MHz DCXO oscillator. The reason is that you'd have to deal with
> the fact that the clock for RTC then becomes 24000000/750 (750 is fixed
> divider), which is 32000.
> 
> So if you want to get 32768Hz for RTC by tuning the DCXO, it would have to have
> 24 576 000 Hz. And even if you could achieve that (doubtful), it would throw off
> timings in the rest of the system (say UART, USB, CPU, display ctl) in a major way.
> 
> I guess you can try tuning 24MHz oscillator so that it's closer to the
> real-world 24MHz via NTP reference for other reasons. But it would be
> complicated, and require precise interaction with other components, like using
> HW timers sourced from 24MHz HOSC clock, because you can't use CPU's timers,
> because of inaccuracies introduced during DVFS, for example.
> 
> regards,
> 	o.
> 
> > I'm curious, what kind of options does this RTC have?
> > 
> > -- 
> > Alexandre Belloni, Bootlin
> > Embedded Linux and Kernel engineering
> > https://bootlin.com
> > 
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20190808233930.GM3600%40piout.net.

^ permalink raw reply

* Re: [PATCH v2 15/15] dt-bindings: net: add bindings for ADIN PHY driver
From: Rob Herring @ 2019-08-08 23:03 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: netdev, devicetree, linux-kernel@vger.kernel.org, David Miller,
	Mark Rutland, Florian Fainelli, Heiner Kallweit, Andrew Lunn
In-Reply-To: <20190808123026.17382-16-alexandru.ardelean@analog.com>

On Thu, Aug 8, 2019 at 6:31 AM Alexandru Ardelean
<alexandru.ardelean@analog.com> wrote:
>
> This change adds bindings for the Analog Devices ADIN PHY driver, detailing
> all the properties implemented by the driver.
>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
> ---
>  .../devicetree/bindings/net/adi,adin.yaml     | 76 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 77 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/adi,adin.yaml
>
> diff --git a/Documentation/devicetree/bindings/net/adi,adin.yaml b/Documentation/devicetree/bindings/net/adi,adin.yaml
> new file mode 100644
> index 000000000000..86177c8fe23a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/adi,adin.yaml
> @@ -0,0 +1,76 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/adi,adin.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Analog Devices ADIN1200/ADIN1300 PHY
> +
> +maintainers:
> +  - Alexandru Ardelean <alexandru.ardelean@analog.com>
> +
> +description: |
> +  Bindings for Analog Devices Industrial Ethernet PHYs
> +
> +allOf:
> +  - $ref: ethernet-phy.yaml#
> +
> +properties:
> +  adi,rx-internal-delay-ps:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      RGMII RX Clock Delay used only when PHY operates in RGMII mode with
> +      internal delay (phy-mode is 'rgmii-id' or 'rgmii-rxid') in pico-seconds.
> +    enum: [ 1600, 1800, 2000, 2200, 2400 ]
> +    default: 2000

This doesn't actually do what you think. The '$ref' has to be under an
'allOf' to work. It's an oddity of json-schema. However, anything with
a standard unit suffix already has a schema to define the type, so you
don't need to here and can just drop $ref.

> +
> +  adi,tx-internal-delay-ps:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      RGMII TX Clock Delay used only when PHY operates in RGMII mode with
> +      internal delay (phy-mode is 'rgmii-id' or 'rgmii-txid') in pico-seconds.
> +    enum: [ 1600, 1800, 2000, 2200, 2400 ]
> +    default: 2000
> +
> +  adi,fifo-depth-bits:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      When operating in RMII mode, this option configures the FIFO depth.
> +    enum: [ 4, 8, 12, 16, 20, 24 ]
> +    default: 8
> +
> +  adi,disable-energy-detect:
> +    description: |
> +      Disables Energy Detect Powerdown Mode (default disabled, i.e energy detect
> +      is enabled if this property is unspecified)
> +    type: boolean
> +
> +examples:
> +  - |
> +    ethernet {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        phy-mode = "rgmii-id";
> +
> +        ethernet-phy@0 {
> +            reg = <0>;
> +
> +            adi,rx-internal-delay-ps = <1800>;
> +            adi,tx-internal-delay-ps = <2200>;
> +        };
> +    };
> +  - |
> +    ethernet {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        phy-mode = "rmii";
> +
> +        ethernet-phy@1 {
> +            reg = <1>;
> +
> +            adi,fifo-depth-bits = <16>;
> +            adi,disable-energy-detect;
> +        };
> +    };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e8aa8a667864..fd9ab61c2670 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -944,6 +944,7 @@ L:  netdev@vger.kernel.org
>  W:     http://ez.analog.com/community/linux-device-drivers
>  S:     Supported
>  F:     drivers/net/phy/adin.c
> +F:     Documentation/devicetree/bindings/net/adi,adin.yaml
>
>  ANALOG DEVICES INC ADIS DRIVER LIBRARY
>  M:     Alexandru Ardelean <alexandru.ardelean@analog.com>
> --
> 2.20.1
>

^ permalink raw reply

* Re: [PATCH v15 00/13] TCU patchset v15
From: Paul Burton @ 2019-08-08 23:02 UTC (permalink / raw)
  To: Paul Cercueil
  Cc: Ralf Baechle, Paul Burton, James Hogan, Jonathan Corbet,
	Lee Jones, Arnd Bergmann, Daniel Lezcano, Thomas Gleixner,
	Michael Turquette, Stephen Boyd, Jason Cooper, Marc Zyngier,
	Rob Herring, Mark Rutland, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-mips@vger.kernel.org
In-Reply-To: <20190724171615.20774-1-paul@crapouillou.net>

Hello,

Paul Cercueil wrote:
> Hi,
> 
> This is the V15 of my Ingenic TCU patchet.
> 
> The big change since V14 is that the custom MFD driver
> (ex patch 04/13) was dropped in favor of a small patch to syscon
> and a "simple-mfd" compatible.
> 
> The patchset was based on mips/mips-next, but all of them minus
> the last one will apply cleanly on v5.3-rc1.
> 
> Changelog:
> 
> * [02/13]: Remove info about MFD driver
> * [03/13]: Add "simple-mfd" compatible string
> * [04/13]: New patch
> * [05/13]: - Use CLK_OF_DECLARE_DRIVER since we use "simple-mfd"
>            - Use device_node_to_regmap()
> * [06/13]: Use device_node_to_regmap()
> * [07/13]: Use device_node_to_regmap()
> * [09/13]: Add "simple-mfd" compatible string
> 
> Cheers,

Series applied to mips-next.

> dt-bindings: ingenic: Add DT bindings for TCU clocks
>   commit 4bc3c420246e
>   https://git.kernel.org/mips/c/4bc3c420246e
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Reviewed-by: Rob Herring <robh@kernel.org>
>   Acked-by: Stephen Boyd <sboyd@kernel.org>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> doc: Add doc for the Ingenic TCU hardware
>   commit 97689a1a3fda
>   https://git.kernel.org/mips/c/97689a1a3fda
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> dt-bindings: Add doc for the Ingenic TCU drivers
>   commit 2e8722a5255e
>   https://git.kernel.org/mips/c/2e8722a5255e
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Reviewed-by: Rob Herring <robh@kernel.org>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> mfd/syscon: Add device_node_to_regmap()
>   commit 39233b7c6112
>   https://git.kernel.org/mips/c/39233b7c6112
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Acked-by: Arnd Bergmann <arnd@arndb.de>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> clk: ingenic: Add driver for the TCU clocks
>   commit 4f89e4b8f121
>   https://git.kernel.org/mips/c/4f89e4b8f121
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Acked-by: Stephen Boyd <sboyd@kernel.org>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> irqchip: Add irq-ingenic-tcu driver
>   commit 9536eba03ec7
>   https://git.kernel.org/mips/c/9536eba03ec7
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
>   Acked-by: Marc Zyngier <maz@kernel.org>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> clocksource: Add a new timer-ingenic driver
>   commit 34e9368301d5
>   https://git.kernel.org/mips/c/34e9368301d5
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> clk: jz4740: Add TCU clock
>   commit 73dd11dc1a88
>   https://git.kernel.org/mips/c/73dd11dc1a88
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Acked-by: Stephen Boyd <sboyd@kernel.org>
>   Acked-by: Rob Herring <robh@kernel.org>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> MIPS: jz4740: Add DTS nodes for the TCU drivers
>   commit 36aafdbd5288
>   https://git.kernel.org/mips/c/36aafdbd5288
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> MIPS: qi_lb60: Reduce system timer and clocksource to 750 kHz
>   commit a68d3b052b57
>   https://git.kernel.org/mips/c/a68d3b052b57
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> MIPS: CI20: Reduce system timer and clocksource to 3 MHz
>   commit 157c887aff52
>   https://git.kernel.org/mips/c/157c887aff52
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> MIPS: GCW0: Reduce system timer and clocksource to 750 kHz
>   commit 967a7100400a
>   https://git.kernel.org/mips/c/967a7100400a
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>
> 
> MIPS: jz4740: Drop obsolete code
>   commit abc552284f6b
>   https://git.kernel.org/mips/c/abc552284f6b
>   
>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>   Tested-by: Mathieu Malaterre <malat@debian.org>
>   Tested-by: Artur Rojek <contact@artur-rojek.eu>
>   Signed-off-by: Paul Burton <paul.burton@mips.com>

Thanks,
    Paul

[ This message was auto-generated; if you believe anything is incorrect
  then please email paul.burton@mips.com to report it. ]

^ permalink raw reply

* Re: [PATCH] dt-bindings: riscv: remove obsolete cpus.txt
From: Rob Herring @ 2019-08-08 22:56 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: devicetree, Mark Rutland, linux-riscv,
	linux-kernel@vger.kernel.org
In-Reply-To: <alpine.DEB.2.21.9999.1908081520100.6414@viisi.sifive.com>

On Thu, Aug 8, 2019 at 4:22 PM Paul Walmsley <paul.walmsley@sifive.com> wrote:
>
>
> Remove the now-obsolete riscv/cpus.txt DT binding document, since we
> are using YAML binding documentation instead.
>
> While doing so, transfer the explanatory text about 'harts' (with some
> edits) into the YAML file, at Rob's request.
>
> Link: https://lore.kernel.org/linux-riscv/CAL_JsqJs6MtvmuyAknsUxQymbmoV=G+=JfS1PQj9kNHV7fjC9g@mail.gmail.com/
> Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com>
> Cc: Rob Herring <robh@kernel.org>
> ---
>  .../devicetree/bindings/riscv/cpus.txt        | 162 ------------------
>  .../devicetree/bindings/riscv/cpus.yaml       |  12 ++
>  2 files changed, 12 insertions(+), 162 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/riscv/cpus.txt

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

^ permalink raw reply

* Re: [PATCH] dt-bindings: riscv: fix the schema compatible string for the HiFive Unleashed board
From: Rob Herring @ 2019-08-08 22:52 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Mark Rutland, devicetree, linux-riscv,
	linux-kernel@vger.kernel.org
In-Reply-To: <alpine.DEB.2.21.9999.1908081545190.15649@viisi.sifive.com>

On Thu, Aug 8, 2019 at 4:46 PM Paul Walmsley <paul.walmsley@sifive.com> wrote:
>
>
> The YAML binding document for SiFive boards has an incorrect
> compatible string for the HiFive Unleashed board.  Change it to match
> the name of the board on the SiFive web site:
>
>    https://www.sifive.com/boards/hifive-unleashed
>
> which also matches the contents of the board DT data file:
>
>    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts#n13
>
> Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com>
> ---
>  Documentation/devicetree/bindings/riscv/sifive.yaml | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

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

^ permalink raw reply

* [PATCH] dt-bindings: riscv: fix the schema compatible string for the HiFive Unleashed board
From: Paul Walmsley @ 2019-08-08 22:46 UTC (permalink / raw)
  To: robh+dt, mark.rutland, devicetree; +Cc: linux-riscv, linux-kernel


The YAML binding document for SiFive boards has an incorrect
compatible string for the HiFive Unleashed board.  Change it to match
the name of the board on the SiFive web site:

   https://www.sifive.com/boards/hifive-unleashed

which also matches the contents of the board DT data file:

   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts#n13

Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com>
---
 Documentation/devicetree/bindings/riscv/sifive.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/riscv/sifive.yaml b/Documentation/devicetree/bindings/riscv/sifive.yaml
index 9d17dc2f3f84..3ab532713dc1 100644
--- a/Documentation/devicetree/bindings/riscv/sifive.yaml
+++ b/Documentation/devicetree/bindings/riscv/sifive.yaml
@@ -19,7 +19,7 @@ properties:
   compatible:
     items:
       - enum:
-          - sifive,freedom-unleashed-a00
+          - sifive,hifive-unleashed-a00
       - const: sifive,fu540-c000
       - const: sifive,fu540
 ...
-- 
2.22.0

^ permalink raw reply related

* [PATCH] dt-bindings: riscv: remove obsolete cpus.txt
From: Paul Walmsley @ 2019-08-08 22:21 UTC (permalink / raw)
  To: devicetree, robh+dt, mark.rutland; +Cc: linux-riscv, linux-kernel


Remove the now-obsolete riscv/cpus.txt DT binding document, since we
are using YAML binding documentation instead.

While doing so, transfer the explanatory text about 'harts' (with some
edits) into the YAML file, at Rob's request.

Link: https://lore.kernel.org/linux-riscv/CAL_JsqJs6MtvmuyAknsUxQymbmoV=G+=JfS1PQj9kNHV7fjC9g@mail.gmail.com/
Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/riscv/cpus.txt        | 162 ------------------
 .../devicetree/bindings/riscv/cpus.yaml       |  12 ++
 2 files changed, 12 insertions(+), 162 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/riscv/cpus.txt

diff --git a/Documentation/devicetree/bindings/riscv/cpus.txt b/Documentation/devicetree/bindings/riscv/cpus.txt
deleted file mode 100644
index adf7b7af5dc3..000000000000
--- a/Documentation/devicetree/bindings/riscv/cpus.txt
+++ /dev/null
@@ -1,162 +0,0 @@
-===================
-RISC-V CPU Bindings
-===================
-
-The device tree allows to describe the layout of CPUs in a system through
-the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
-defining properties for every cpu.
-
-Bindings for CPU nodes follow the Devicetree Specification, available from:
-
-https://www.devicetree.org/specifications/
-
-with updates for 32-bit and 64-bit RISC-V systems provided in this document.
-
-===========
-Terminology
-===========
-
-This document uses some terminology common to the RISC-V community that is not
-widely used, the definitions of which are listed here:
-
-* hart: A hardware execution context, which contains all the state mandated by
-  the RISC-V ISA: a PC and some registers.  This terminology is designed to
-  disambiguate software's view of execution contexts from any particular
-  microarchitectural implementation strategy.  For example, my Intel laptop is
-  described as having one socket with two cores, each of which has two hyper
-  threads.  Therefore this system has four harts.
-
-=====================================
-cpus and cpu node bindings definition
-=====================================
-
-The RISC-V architecture, in accordance with the Devicetree Specification,
-requires the cpus and cpu nodes to be present and contain the properties
-described below.
-
-- cpus node
-
-        Description: Container of cpu nodes
-
-        The node name must be "cpus".
-
-        A cpus node must define the following properties:
-
-        - #address-cells
-                Usage: required
-                Value type: <u32>
-                Definition: must be set to 1
-        - #size-cells
-                Usage: required
-                Value type: <u32>
-                Definition: must be set to 0
-
-- cpu node
-
-        Description: Describes a hart context
-
-        PROPERTIES
-
-        - device_type
-                Usage: required
-                Value type: <string>
-                Definition: must be "cpu"
-        - reg
-                Usage: required
-                Value type: <u32>
-                Definition: The hart ID of this CPU node
-        - compatible:
-                Usage: required
-                Value type: <stringlist>
-                Definition: must contain "riscv", may contain one of
-                            "sifive,rocket0"
-        - mmu-type:
-                Usage: optional
-                Value type: <string>
-                Definition: Specifies the CPU's MMU type.  Possible values are
-                            "riscv,sv32"
-                            "riscv,sv39"
-                            "riscv,sv48"
-        - riscv,isa:
-                Usage: required
-                Value type: <string>
-                Definition: Contains the RISC-V ISA string of this hart.  These
-                            ISA strings are defined by the RISC-V ISA manual.
-
-Example: SiFive Freedom U540G Development Kit
----------------------------------------------
-
-This system contains two harts: a hart marked as disabled that's used for
-low-level system tasks and should be ignored by Linux, and a second hart that
-Linux is allowed to run on.
-
-        cpus {
-                #address-cells = <1>;
-                #size-cells = <0>;
-                timebase-frequency = <1000000>;
-                cpu@0 {
-                        clock-frequency = <1600000000>;
-                        compatible = "sifive,rocket0", "riscv";
-                        device_type = "cpu";
-                        i-cache-block-size = <64>;
-                        i-cache-sets = <128>;
-                        i-cache-size = <16384>;
-                        next-level-cache = <&L15 &L0>;
-                        reg = <0>;
-                        riscv,isa = "rv64imac";
-                        status = "disabled";
-                        L10: interrupt-controller {
-                                #interrupt-cells = <1>;
-                                compatible = "riscv,cpu-intc";
-                                interrupt-controller;
-                        };
-                };
-                cpu@1 {
-                        clock-frequency = <1600000000>;
-                        compatible = "sifive,rocket0", "riscv";
-                        d-cache-block-size = <64>;
-                        d-cache-sets = <64>;
-                        d-cache-size = <32768>;
-                        d-tlb-sets = <1>;
-                        d-tlb-size = <32>;
-                        device_type = "cpu";
-                        i-cache-block-size = <64>;
-                        i-cache-sets = <64>;
-                        i-cache-size = <32768>;
-                        i-tlb-sets = <1>;
-                        i-tlb-size = <32>;
-                        mmu-type = "riscv,sv39";
-                        next-level-cache = <&L15 &L0>;
-                        reg = <1>;
-                        riscv,isa = "rv64imafdc";
-                        status = "okay";
-                        tlb-split;
-                        L13: interrupt-controller {
-                                #interrupt-cells = <1>;
-                                compatible = "riscv,cpu-intc";
-                                interrupt-controller;
-                        };
-                };
-        };
-
-Example: Spike ISA Simulator with 1 Hart
-----------------------------------------
-
-This device tree matches the Spike ISA golden model as run with `spike -p1`.
-
-        cpus {
-                cpu@0 {
-                        device_type = "cpu";
-                        reg = <0x00000000>;
-                        status = "okay";
-                        compatible = "riscv";
-                        riscv,isa = "rv64imafdc";
-                        mmu-type = "riscv,sv48";
-                        clock-frequency = <0x3b9aca00>;
-                        interrupt-controller {
-                                #interrupt-cells = <0x00000001>;
-                                interrupt-controller;
-                                compatible = "riscv,cpu-intc";
-                        }
-                }
-        }
diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml
index c899111aa5e3..5963af8c0c11 100644
--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
+++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
@@ -10,6 +10,18 @@ maintainers:
   - Paul Walmsley <paul.walmsley@sifive.com>
   - Palmer Dabbelt <palmer@sifive.com>
 
+description: |
+  This document uses some terminology common to the RISC-V community
+  that is not widely used, the definitions of which are listed here:
+
+  hart: A hardware execution context, which contains all the state
+  mandated by the RISC-V ISA: a PC and some registers.  This
+  terminology is designed to disambiguate software's view of execution
+  contexts from any particular microarchitectural implementation
+  strategy.  For example, an Intel laptop containing one socket with
+  two cores, each of which has two hyperthreads, could be described as
+  having four harts.
+
 properties:
   compatible:
     items:
-- 
2.22.0

^ permalink raw reply related

* Re: [PATCH v8 09/14] media: rkisp1: add rockchip isp1 core driver
From: Helen Koike @ 2019-08-08 21:59 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-rockchip, devicetree, eddie.cai.linux, mchehab, heiko,
	jacob2.chen, jeffy.chen, zyc, linux-kernel, tfiga, hans.verkuil,
	laurent.pinchart, kernel, ezequiel, linux-media, linux-arm-kernel,
	zhengsq, Jacob Chen, Allon Huang
In-Reply-To: <20190807152727.GN21370@paasikivi.fi.intel.com>

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).

> 
>> +
>> +/**************************** 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

> 
> 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())

> 
>> +
>> +		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?

> 
>> +{
>> +	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?

> 
>> +	}
>> +
>> +	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.

> 
>> +
>> +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.

> 
>> 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.

Thanks a lot for your review
Helen

> 
>> +
>> +/*
>> + * struct rkisp1_device - ISP platform device
>> + * @base_addr: base register address
>> + * @active_sensor: sensor in-use, set when streaming on
>> + * @isp_sdev: ISP sub-device
>> + * @rkisp1_stream: capture video device
>> + * @stats_vdev: ISP statistics output device
>> + * @params_vdev: ISP input parameters device
>> + */
>> +struct rkisp1_device {
>> +	void __iomem *base_addr;
>> +	int irq;
>> +	struct device *dev;
>> +	unsigned int clk_size;
>> +	struct clk_bulk_data clks[RKISP1_MAX_BUS_CLK];
>> +	struct v4l2_device v4l2_dev;
>> +	struct v4l2_ctrl_handler ctrl_handler;
>> +	struct media_device media_dev;
>> +	struct v4l2_async_notifier notifier;
>> +	struct v4l2_subdev *subdevs[RKISP1_SD_MAX];
>> +	struct rkisp1_sensor *active_sensor;
>> +	struct list_head sensors;
>> +	struct rkisp1_isp_subdev isp_sdev;
>> +	struct rkisp1_stream stream[RKISP1_MAX_STREAM];
>> +	struct rkisp1_isp_stats_vdev stats_vdev;
>> +	struct rkisp1_isp_params_vdev params_vdev;
>> +	struct rkisp1_pipeline pipe;
>> +	struct vb2_alloc_ctx *alloc_ctx;
>> +};
>> +
>> +#endif
> 

^ permalink raw reply

* Re: 21871a99b3 ("of/platform: Pause/resume sync state during init .."): WARNING: CPU: 0 PID: 1 at drivers/base/core.c:691 device_links_supplier_sync_state_resume
From: Saravana Kannan @ 2019-08-08 20:55 UTC (permalink / raw)
  To: kernel test robot
  Cc: LKP, LKML,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Frank Rowand, Greg Kroah-Hartman, philip.li
In-Reply-To: <5d4bce76.Bu8zZv8tcbDqokLR%lkp@intel.com>

On Thu, Aug 8, 2019 at 12:25 AM kernel test robot <lkp@intel.com> wrote:
>
> Greetings,
>
> 0day kernel testing robot got the below dmesg and the first bad commit is
>
> https://kernel.googlesource.com/pub/scm/linux/kernel/git/gregkh/driver-core.git driver-core-testing
>
> commit 21871a99b34c65c56a24193c277a4981529c306f
> Author:     Saravana Kannan <saravanak@google.com>
> AuthorDate: Wed Jul 31 15:17:18 2019 -0700
> Commit:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> CommitDate: Thu Aug 1 16:04:14 2019 +0200
>
>     of/platform: Pause/resume sync state during init and of_platform_populate()
>
>     When all the top level devices are populated from DT during kernel
>     init, the supplier devices could be added and probed before the
>     consumer devices are added and linked to the suppliers. To avoid the
>     sync_state() callback from being called prematurely, pause the
>     sync_state() callbacks before populating the devices and resume them
>     at late_initcall_sync().
>
>     Similarly, when children devices are populated after kernel init using
>     of_platform_populate(), there could be supplier-consumer dependencies
>     between the children devices that are populated. To avoid the same
>     problem with sync_state() being called prematurely, pause and resume
>     sync_state() callbacks across of_platform_populate().
>
>     Signed-off-by: Saravana Kannan <saravanak@google.com>
>     Link: https://lore.kernel.org/r/20190731221721.187713-6-saravanak@google.com
>     Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> 8f8184d6bf  driver core: Add sync_state driver/bus callback
> 21871a99b3  of/platform: Pause/resume sync state during init and of_platform_populate()
> 5adf578101  of/platform: Fix device_links_supplier_sync_state_resume() warning
> 3880be629e  Add linux-next specific files for 20190807
> +-------------------------------------------------------------------------+------------+------------+------------+---------------+
> |                                                                         | 8f8184d6bf | 21871a99b3 | 5adf578101 | next-20190807 |
> +-------------------------------------------------------------------------+------------+------------+------------+---------------+
> | boot_successes                                                          | 27         | 0          | 0          | 0             |
> | boot_failures                                                           | 2          | 11         | 11         | 11            |
> | WARNING:at_mm/usercopy.c:#usercopy_warn                                 | 1          |            |            |               |
> | RIP:usercopy_warn                                                       | 1          |            |            |               |
> | invoked_oom-killer:gfp_mask=0x                                          | 1          |            |            |               |
> | Mem-Info                                                                | 1          |            |            |               |
> | WARNING:at_drivers/base/core.c:#device_links_supplier_sync_state_resume | 0          | 11         | 11         | 11            |
> | RIP:device_links_supplier_sync_state_resume                             | 0          | 11         | 11         | 11            |
> +-------------------------------------------------------------------------+------------+------------+------------+---------------+
>
> If you fix the issue, kindly add following tag
> Reported-by: kernel test robot <lkp@intel.com>
>
> [   26.905004] i2c i2c-1: Added multiplexed i2c bus 3
> [   26.917068] ### dt-test ### FAIL of_unittest_overlay_high_level():2380 overlay_base_root not initialized
> [   26.920311] ### dt-test ### end of unittest - 219 passed, 1 failed
> [   26.922504] ------------[ cut here ]------------
> [   26.924102] Unmatched sync_state pause/resume!
> [   26.924192] WARNING: CPU: 0 PID: 1 at drivers/base/core.c:691 device_links_supplier_sync_state_resume+0x140/0x160
> [   26.929493] Modules linked in:
> [   26.930681] CPU: 0 PID: 1 Comm: swapper Tainted: G                T 5.3.0-rc1-00025-g21871a99b34c6 #1
> [   26.933665] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
> [   26.936451] RIP: 0010:device_links_supplier_sync_state_resume+0x140/0x160
> [   26.938611] Code: 84 c0 49 8d 84 24 c8 00 00 00 0f 85 48 ff ff ff 49 8d 94 24 d0 00 00 00 48 89 55 d0 eb 86 48 c7 c7 c0 30 be 83 e8 10 c0 e5 fe <0f> 0b 48 c7 c7 80 33 c4 84 e8 12 19 d0 00 48 83 c4 10 5b 41 5c 41
> [   26.944420] RSP: 0018:ffff88801a397da8 EFLAGS: 00010286
> [   26.946213] RAX: 0000000000000022 RBX: b05332a62e1f2e76 RCX: 0000000000000000
> [   26.948487] RDX: 0000000000000022 RSI: ffffffff81276c83 RDI: 0000000000000246
> [   26.950858] RBP: ffff88801a397de0 R08: fffffbfff0aa192d R09: fffffbfff0aa192d
> [   26.953192] R10: ffff88801a397df0 R11: 0000000000000001 R12: 0000000000000000
> [   26.955411] R13: 00000000ffffffff R14: 1ffff11003472fc3 R15: ffff88801a397eb8
> [   26.957678] FS:  0000000000000000(0000) GS:ffffffff846b3000(0000) knlGS:0000000000000000
> [   26.960398] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   26.962374] CR2: 00007fb42acb9480 CR3: 000000000462a006 CR4: 00000000001606f0
> [   26.964683] Call Trace:
> [   26.965713]  of_platform_sync_state_init+0x17/0x3a
> [   26.967381]  ? of_core_init+0x16a/0x16a
> [   26.968769]  do_one_initcall+0x103/0x295
> [   26.970179]  ? trace_event_raw_event_initcall_finish+0x150/0x150
> [   26.972130]  ? down_write+0xbe/0x100
> [   26.973467]  ? __down_killable+0x260/0x260
> [   26.974933]  ? __kasan_check_write+0x1f/0x30
> [   26.976433]  kernel_init_freeable+0x232/0x349
> [   26.978003]  ? rest_init+0xd0/0xd0
> [   26.979274]  kernel_init+0xe/0x120
> [   26.980580]  ? rest_init+0xd0/0xd0
> [   26.981870]  ret_from_fork+0x24/0x30
> [   26.983168] ---[ end trace fa753e8363323d3d ]---
> [   26.991111] Freeing unused decrypted memory: 2040K

This looks like the same issue fixed by:
https://lore.kernel.org/lkml/20190807020559.74458-1-saravanak@google.com/

If anyone thinks otherwise, please let me know.

-Saravana

^ permalink raw reply

* Re: [PATCH 12/15] arm64: dts: msm8974: thermal: Add interrupt support
From: Brian Masney @ 2019-08-08 20:49 UTC (permalink / raw)
  To: Amit Kucheria
  Cc: linux-kernel, linux-arm-msm, bjorn.andersson, edubezval,
	andy.gross, Andy Gross, Daniel Lezcano, Mark Rutland, Rob Herring,
	Zhang Rui, devicetree
In-Reply-To: <ec8205566eb9c015ad51fbb88f0da7ca60b414fd.1564091601.git.amit.kucheria@linaro.org>

On Fri, Jul 26, 2019 at 03:48:47AM +0530, Amit Kucheria wrote:
> Register upper-lower interrupt for the tsens controller.
> 
> Signed-off-by: Amit Kucheria <amit.kucheria@linaro.org>

Tested-by: Brian Masney <masneyb@onstation.org>

^ permalink raw reply

* Re: [PATCH 05/15] arm: dts: msm8974: thermal: Add thermal zones for each sensor
From: Brian Masney @ 2019-08-08 20:49 UTC (permalink / raw)
  To: Amit Kucheria
  Cc: linux-kernel, linux-arm-msm, bjorn.andersson, edubezval,
	andy.gross, Andy Gross, Daniel Lezcano, Mark Rutland, Rob Herring,
	Zhang Rui, devicetree
In-Reply-To: <9e2948528c789225bf8a6ef458b83a5350a7ea26.1564091601.git.amit.kucheria@linaro.org>

On Fri, Jul 26, 2019 at 03:48:40AM +0530, Amit Kucheria wrote:
> msm8974 has 11 sensors connected to a single TSENS IP. Define a thermal
> zone for each of those sensors to expose the temperature of each zone.
> 
> Signed-off-by: Amit Kucheria <amit.kucheria@linaro.org>

Tested-by: Brian Masney <masneyb@onstation.org> # msm8974

^ permalink raw reply

* [PATCH v4 2/2] leds: add LED driver for EL15203000 board
From: Oleh Kravchenko @ 2019-08-08 20:32 UTC (permalink / raw)
  To: devicetree, linux-leds; +Cc: Oleh Kravchenko
In-Reply-To: <20190808203204.8614-1-oleg@kaa.org.ua>

This patch adds a LED class driver for the RGB LEDs found on
the Crane Merchandising System EL15203000 LEDs board
(aka RED LEDs board).

Signed-off-by: Oleh Kravchenko <oleg@kaa.org.ua>
---
 .../testing/sysfs-class-led-driver-el15203000 |  22 +
 drivers/leds/Kconfig                          |  13 +
 drivers/leds/Makefile                         |   1 +
 drivers/leds/leds-el15203000.c                | 478 ++++++++++++++++++
 4 files changed, 514 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-driver-el15203000
 create mode 100644 drivers/leds/leds-el15203000.c

diff --git a/Documentation/ABI/testing/sysfs-class-led-driver-el15203000 b/Documentation/ABI/testing/sysfs-class-led-driver-el15203000
new file mode 100644
index 000000000000..91a483e493d9
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-driver-el15203000
@@ -0,0 +1,22 @@
+What:		/sys/class/leds/<led>/hw_pattern
+Date:		August 2019
+KernelVersion:	5.3
+Description:
+		Specify a hardware pattern for the EL15203000 LED.
+		The LEDs board supports only predefined patterns by firmware
+		for specific LEDs.
+
+		Breathing mode for Screen frame light tube:
+		"0 4000 1 4000"
+
+		Cascade mode for Pipe LED:
+		"1 800 2 800 4 800 8 800 16 800 1 800 2 800 4 800 8 800 16 800"
+
+		Inverted cascade mode for Pipe LED:
+		"30 800 29 800 27 800 23 800 15 800 30 800 29 800 27 800 23 800 15 800"
+
+		Bounce mode for Pipe LED:
+		"1 800 2 800 4 800 8 800 16 800 16 800 8 800 4 800 2 800 1 800"
+
+		Inverted bounce mode for Pipe LED:
+		"30 800 29 800 27 800 23 800 15 800 15 800 23 800 27 800 29 800 30 800"
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 760f73a49c9f..0cbdb9ba5213 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -129,6 +129,19 @@ config LEDS_CR0014114
 	  To compile this driver as a module, choose M here: the module
 	  will be called leds-cr0014114.
 
+config LEDS_EL15203000
+	tristate "LED Support for Crane EL15203000"
+	depends on LEDS_CLASS
+	depends on SPI
+	depends on OF
+	help
+	  This option enables support for EL15203000 LED Board
+	  (aka RED LED board) which is widely used in coffee vending
+	  machines produced by Crane Merchandising Systems.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called leds-el15203000.
+
 config LEDS_LM3530
 	tristate "LCD Backlight driver for LM3530"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 1e9702ebffee..1f193ffc2feb 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_LEDS_LM3601X)		+= leds-lm3601x.o
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_CR0014114)		+= leds-cr0014114.o
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
+obj-$(CONFIG_LEDS_EL15203000)		+= leds-el15203000.o
 
 # LED Userspace Drivers
 obj-$(CONFIG_LEDS_USER)			+= uleds.o
diff --git a/drivers/leds/leds-el15203000.c b/drivers/leds/leds-el15203000.c
new file mode 100644
index 000000000000..c62da5ec6630
--- /dev/null
+++ b/drivers/leds/leds-el15203000.c
@@ -0,0 +1,478 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2019 Crane Merchandising Systems. All rights reserved.
+// Copyright (C) 2019 Oleh Kravchenko <oleg@kaa.org.ua>
+
+#include <linux/delay.h>
+#include <linux/leds.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+#include <uapi/linux/uleds.h>
+
+/*
+ * EL15203000 SPI protocol description:
+ * +-----+------------+
+ * | LED | BRIGHTNESS |
+ * +-----+------------+
+ * |  1  |      1     |
+ * +-----+------------+
+ * (*) LEDs MCU board expects 20 msec delay per byte.
+ *
+ * LEDs:
+ * +----------+--------------+-------------------------------------------+
+ * |    ID    |     NAME     |         DESCRIPTION                       |
+ * +----------+--------------+-------------------------------------------+
+ * | 'P' 0x50 |     Pipe     | Consists from 5 LEDs, controlled by board |
+ * +----------+--------------+-------------------------------------------+
+ * | 'S' 0x53 | Screen frame | Light tube around the screen              |
+ * +----------+--------------+-------------------------------------------+
+ * | 'V' 0x56 | Vending area | Highlights a cup of coffee                |
+ * +----------+--------------+-------------------------------------------+
+ *
+ * BRIGHTNESS:
+ * +----------+-----------------+--------------+--------------+
+ * |  VALUES  |       PIPE      | SCREEN FRAME | VENDING AREA |
+ * +----------+-----------------+--------------+--------------+
+ * | '0' 0x30 |                      Off                      |
+ * +----------+-----------------------------------------------+
+ * | '1' 0x31 |                      On                       |
+ * +----------+-----------------+--------------+--------------+
+ * | '2' 0x32 |     Cascade     |   Breathing  |
+ * +----------+-----------------+--------------+
+ * | '3' 0x33 | Inverse cascade |
+ * +----------+-----------------+
+ * | '4' 0x34 |     Bounce      |
+ * +----------+-----------------+
+ * | '5' 0x35 | Inverse bounce  |
+ * +----------+-----------------+
+ */
+
+/* EL15203000 default settings */
+#define EL_FW_DELAY_USEC	20000
+
+enum el15203000_brightness {
+	/* for all LEDs */
+	EL_OFF			= '0',
+	EL_ON			= '1',
+
+	/* for Screen LED */
+	EL_SCREEN_BREATHING	= '2',
+
+	/* for Pipe LED */
+	EL_PIPE_CASCADE		= '2',
+	EL_PIPE_INV_CASCADE	= '3',
+	EL_PIPE_BOUNCE		= '4',
+	EL_PIPE_INV_BOUNCE	= '5',
+};
+
+struct el15203000_led {
+	struct el15203000	*priv;
+	struct led_classdev	ldev;
+	char			name[LED_MAX_NAME_SIZE];
+	u8			reg;
+};
+
+struct el15203000 {
+	struct device		*dev;
+	struct mutex		lock;
+	struct spi_device	*spi;
+	unsigned long		delay;
+	size_t			count;
+	struct el15203000_led	leds[];
+};
+
+static int el15203000_cmd(struct el15203000_led *led, u8 brightness)
+{
+	int		ret;
+	u8		cmd[2];
+	size_t		i;
+	unsigned long	jdelay, udelay, now;
+
+	mutex_lock(&led->priv->lock);
+
+	dev_dbg(led->priv->dev, "Set brightness of %s to %d",
+		led->name, brightness);
+
+	/* to avoid SPI mistiming with firmware we should wait some time */
+	now = jiffies;
+	if (time_after(led->priv->delay, now)) {
+		jdelay = led->priv->delay - now;
+		udelay = jiffies_to_usecs(jdelay);
+
+		dev_dbg(led->priv->dev, "Wait %luus (%lu jiffies) to sync",
+			udelay, jdelay);
+
+		usleep_range(udelay, udelay + 1);
+	}
+
+	cmd[0] = led->reg;
+	cmd[1] = brightness;
+
+	for (i = 0; i < ARRAY_SIZE(cmd); i++) {
+		if (i)
+			usleep_range(EL_FW_DELAY_USEC,
+				     EL_FW_DELAY_USEC + 1);
+
+		ret = spi_write(led->priv->spi, &cmd[i], sizeof(cmd[i]));
+		if (ret) {
+			dev_err(led->priv->dev,
+				"spi_write() error %d", ret);
+			break;
+		}
+	}
+
+	led->priv->delay = jiffies + usecs_to_jiffies(EL_FW_DELAY_USEC);
+
+	mutex_unlock(&led->priv->lock);
+
+	return ret;
+}
+
+static int el15203000_set_blocking(struct led_classdev *ldev,
+				   enum led_brightness brightness)
+{
+	struct el15203000_led	*led = container_of(ldev,
+						    struct el15203000_led,
+						    ldev);
+
+	return el15203000_cmd(led, brightness == LED_OFF ? EL_OFF : EL_ON);
+}
+
+static int led_pattern_cmp(const struct led_pattern *p1, u32 p1_len,
+			   const struct led_pattern *p2, u32 p2_len)
+{
+	u32 i;
+
+	if (p1_len != p2_len)
+		return -1;
+
+	for (i = 0; i < p1_len; i ++)
+		if (p1[i].delta_t != p2[i].delta_t ||
+		    p1[i].brightness != p2[i].brightness)
+			return -1;
+
+	return 0;
+}
+
+int el15203000_pattern_set_S(struct led_classdev *ldev,
+			     struct led_pattern *pattern,
+			     u32 len, int repeat)
+{
+	struct el15203000_led	*led = container_of(ldev,
+						    struct el15203000_led,
+						    ldev);
+	struct led_pattern	scr_pattern[] = {{
+		.delta_t	= 4000,
+		.brightness	= 0,
+	}, {
+		.delta_t	= 4000,
+		.brightness	= 1,
+	}};
+
+	if (repeat > 0)
+		return -EINVAL;
+
+	if (led_pattern_cmp(scr_pattern, ARRAY_SIZE(scr_pattern), pattern, len))
+		return -EINVAL;
+
+	dev_dbg(led->priv->dev, "Breathing mode for '%s'", led->name);
+
+	return el15203000_cmd(led, EL_SCREEN_BREATHING);
+}
+
+int el15203000_pattern_set_P(struct led_classdev *ldev,
+			   struct led_pattern *pattern,
+			   u32 len, int repeat)
+{
+	struct el15203000_led	*led = container_of(ldev,
+						    struct el15203000_led,
+						    ldev);
+
+	struct led_pattern cascade[] = {{
+		.delta_t	= 800,
+		.brightness	= 1,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 2,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 4,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 8,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 16,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 1,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 2,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 4,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 8,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 16,
+	}};
+
+	struct led_pattern inv_cascade[] = {{
+		.delta_t	= 800,
+		.brightness	= 30,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 29,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 27,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 23,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 15,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 30,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 29,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 27,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 23,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 15,
+	}};
+
+	struct led_pattern	bounce[] = {{
+		.delta_t	= 800,
+		.brightness	= 1,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 2,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 4,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 8,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 16,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 16,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 8,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 4,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 2,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 1,
+	}};
+
+	struct led_pattern	inv_bounce[] = {{
+		.delta_t	= 800,
+		.brightness	= 30,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 29,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 27,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 23,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 15,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 15,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 23,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 27,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 29,
+	}, {
+		.delta_t	= 800,
+		.brightness	= 30,
+	}};
+
+	if (repeat > 0)
+		return -EINVAL;
+
+	if (!led_pattern_cmp(cascade, ARRAY_SIZE(cascade), pattern, len)) {
+		dev_dbg(led->priv->dev, "Cascade mode for '%s'", led->name);
+		return el15203000_cmd(led, EL_PIPE_CASCADE);
+	} else if (!led_pattern_cmp(inv_cascade, ARRAY_SIZE(inv_cascade), pattern, len)) {
+		dev_dbg(led->priv->dev, "Inverse cascade mode for '%s'", led->name);
+		return el15203000_cmd(led, EL_PIPE_INV_CASCADE);
+	} else if (!led_pattern_cmp(bounce, ARRAY_SIZE(bounce), pattern, len)) {
+		dev_dbg(led->priv->dev, "Bounce mode for '%s'", led->name);
+		return el15203000_cmd(led, EL_PIPE_BOUNCE);
+	} else if (!led_pattern_cmp(inv_bounce, ARRAY_SIZE(inv_bounce), pattern, len)) {
+		dev_dbg(led->priv->dev, "Inverse bounce mode for '%s'", led->name);
+		return el15203000_cmd(led, EL_PIPE_INV_BOUNCE);
+	}
+
+	return -EINVAL;
+}
+
+int el15203000_pattern_clear(struct led_classdev *ldev)
+{
+	struct el15203000_led	*led = container_of(ldev,
+						    struct el15203000_led,
+						    ldev);
+
+	return el15203000_cmd(led, EL_OFF);
+}
+
+static int el15203000_probe_dt(struct el15203000 *priv)
+{
+	size_t			i = 0;
+	struct el15203000_led	*led;
+	struct fwnode_handle	*child;
+	int			ret;
+	const char		*str;
+	u32			reg;
+
+	device_for_each_child_node(priv->dev, child) {
+		led = &priv->leds[i];
+
+		ret = fwnode_property_read_u32(child, "reg", &reg);
+		if (ret) {
+			dev_err(priv->dev, "LED without ID number");
+			fwnode_handle_put(child);
+
+			return ret;
+		}
+
+		if (reg > U8_MAX) {
+			dev_err(priv->dev, "LED value %d is invalid", reg);
+			fwnode_handle_put(child);
+
+			return -EINVAL;
+		}
+
+		led->reg = reg;
+
+		ret = fwnode_property_read_string(child, "label", &str);
+		if (ret)
+			str = ":";
+		snprintf(led->name, sizeof(led->name), "el15203000:%s", str);
+
+		fwnode_property_read_string(child, "linux,default-trigger",
+					    &led->ldev.default_trigger);
+
+		led->ldev.max_brightness	  = LED_ON;
+		led->priv			  = priv;
+		led->ldev.name			  = led->name;
+		led->ldev.brightness_set_blocking = el15203000_set_blocking;
+
+		if (reg == 'S') {
+			led->ldev.pattern_set	= el15203000_pattern_set_S;
+			led->ldev.pattern_clear	= el15203000_pattern_clear;
+		} else if (reg == 'P') {
+			led->ldev.pattern_set	= el15203000_pattern_set_P;
+			led->ldev.pattern_clear	= el15203000_pattern_clear;
+		}
+
+		ret = devm_led_classdev_register(priv->dev, &led->ldev);
+		if (ret) {
+			dev_err(priv->dev,
+				"failed to register LED device %s, err %d",
+				led->name, ret);
+			fwnode_handle_put(child);
+			return ret;
+		}
+
+		i++;
+	}
+
+	return ret;
+}
+
+static int el15203000_probe(struct spi_device *spi)
+{
+	struct el15203000	*priv;
+	size_t			count;
+	int			ret;
+
+	count = device_get_child_node_count(&spi->dev);
+	if (!count) {
+		dev_err(&spi->dev, "LEDs are not defined in device tree!");
+		return -ENODEV;
+	}
+
+	priv = devm_kzalloc(&spi->dev, struct_size(priv, leds, count),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	mutex_init(&priv->lock);
+	priv->count	= count;
+	priv->dev	= &spi->dev;
+	priv->spi	= spi;
+	priv->delay	= jiffies -
+			  usecs_to_jiffies(EL_FW_DELAY_USEC);
+
+	ret = el15203000_probe_dt(priv);
+	if (ret)
+		return ret;
+
+	spi_set_drvdata(spi, priv);
+	dev_dbg(priv->dev, "%zd LEDs registered", priv->count);
+
+	return 0;
+}
+
+static int el15203000_remove(struct spi_device *spi)
+{
+	struct el15203000 *priv = spi_get_drvdata(spi);
+
+	mutex_destroy(&priv->lock);
+
+	return 0;
+}
+
+static const struct of_device_id el15203000_dt_ids[] = {
+	{ .compatible = "crane,el15203000", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, el15203000_dt_ids);
+
+static struct spi_driver el15203000_driver = {
+	.probe		= el15203000_probe,
+	.remove		= el15203000_remove,
+	.driver = {
+		.name		= KBUILD_MODNAME,
+		.of_match_table	= el15203000_dt_ids,
+	},
+};
+
+module_spi_driver(el15203000_driver);
+
+MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>");
+MODULE_DESCRIPTION("el15203000 LED driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:el15203000");
-- 
2.21.0

^ permalink raw reply related

* Re: [PATCH v2 13/15] net: phy: adin: configure downshift on config_init
From: Andrew Lunn @ 2019-08-08 20:39 UTC (permalink / raw)
  To: Heiner Kallweit
  Cc: Alexandru Ardelean, netdev, devicetree, linux-kernel, davem,
	robh+dt, mark.rutland, f.fainelli
In-Reply-To: <420c8e15-3361-a722-4ad1-3c448b1d3bc1@gmail.com>

On Thu, Aug 08, 2019 at 09:38:40PM +0200, Heiner Kallweit wrote:
> On 08.08.2019 14:30, Alexandru Ardelean wrote:
> > Down-speed auto-negotiation may not always be enabled, in which case the
> > PHY won't down-shift to 100 or 10 during auto-negotiation.
> > 
> > This change enables downshift and configures the number of retries to
> > default 8 (maximum supported value).
> > 
> > The change has been adapted from the Marvell PHY driver.
> > 
> Instead of a fixed downshift setting (like in the Marvell driver) you
> may consider to implement the ethtool phy-tunable ETHTOOL_PHY_DOWNSHIFT.

Hi Alexandru

Upps, sorry, my bad.

I looked at marvell_set_downshift(), and assumed it was connected to
the phy-tunable. I have patches somewhere which does that. But they
have not made it into mainline yet.

> See the Aquantia PHY driver for an example.

Yes, that does have all the tunable stuff.

     Andrew

^ permalink raw reply

* [PATCH v4 1/2] dt-bindings: Add docs for EL15203000
From: Oleh Kravchenko @ 2019-08-08 20:32 UTC (permalink / raw)
  To: devicetree, linux-leds; +Cc: Oleh Kravchenko

Add documentation and example for dt-bindings EL15203000.
LED board (aka RED LED board) from Crane Merchandising Systems.

Signed-off-by: Oleh Kravchenko <oleg@kaa.org.ua>
---
 .../bindings/leds/leds-el15203000.txt         | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-el15203000.txt

diff --git a/Documentation/devicetree/bindings/leds/leds-el15203000.txt b/Documentation/devicetree/bindings/leds/leds-el15203000.txt
new file mode 100644
index 000000000000..4c2245babfdc
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-el15203000.txt
@@ -0,0 +1,47 @@
+Crane Merchandising System - el15203000 LED driver
+--------------------------------------------------
+
+This LED Board (aka RED LEDs board) is widely used in
+coffee vending machines produced by Crane Merchandising Systems.
+
+Required properties:
+- compatible : "crane,el15203000"
+- reg :
+	see Documentation/devicetree/bindings/spi/spi-bus.txt
+- spi-max-frequency : (optional)
+	see Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Optional LED sub-node properties:
+- label :
+	see Documentation/devicetree/bindings/leds/common.txt
+- linux,default-trigger :
+	see Documentation/devicetree/bindings/leds/common.txt
+
+Example
+-------
+
+led-controller@0 {
+	compatible = "crane,el15203000";
+	reg = <0>;
+	spi-max-frequency = <50000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* water pipe */
+	pipe@50 {
+		reg = <0x50>;
+		label = "red:pipe";
+	};
+
+	/* screen frame */
+	screen@53 {
+		reg = <0x53>;
+		label = "red:screen";
+	};
+
+	/* vending area */
+	vend@56 {
+		reg = <0x56>;
+		label = "red:vend";
+	};
+};
-- 
2.21.0

^ permalink raw reply related

* Applied "regulator: qcom-rpmh: Add support for SM8150" to the regulator tree
From: Mark Brown @ 2019-08-08 20:33 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Andy Gross, Bjorn Andersson, devicetree, Liam Girdwood,
	linux-arm-msm, linux-kernel, Mark Brown, Mark Rutland,
	Rob Herring
In-Reply-To: <20190808093343.5600-2-vkoul@kernel.org>

The patch

   regulator: qcom-rpmh: Add support for SM8150

has been applied to the regulator tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-5.4

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 06369bcc15a1620930a17fb35e26477504cd2255 Mon Sep 17 00:00:00 2001
From: Vinod Koul <vkoul@kernel.org>
Date: Thu, 8 Aug 2019 15:03:43 +0530
Subject: [PATCH] regulator: qcom-rpmh: Add support for SM8150

Add support from RPMH regulators found in SM8150 platform

Signed-off-by: Vinod Koul <vkoul@kernel.org>
Link: https://lore.kernel.org/r/20190808093343.5600-2-vkoul@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 drivers/regulator/qcom-rpmh-regulator.c | 147 ++++++++++++++++++++++++
 1 file changed, 147 insertions(+)

diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index b2c2d01d1637..693ffec62f3e 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -637,6 +637,72 @@ static const struct rpmh_vreg_hw_data pmic4_lvs = {
 	/* LVS hardware does not support voltage or mode configuration. */
 };
 
+static const struct rpmh_vreg_hw_data pmic5_pldo = {
+	.regulator_type = VRM,
+	.ops = &rpmh_regulator_vrm_drms_ops,
+	.voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 255, 8000),
+	.n_voltages = 256,
+	.hpm_min_load_uA = 10000,
+	.pmic_mode_map = pmic_mode_map_pmic4_ldo,
+	.of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_pldo_lv = {
+	.regulator_type = VRM,
+	.ops = &rpmh_regulator_vrm_drms_ops,
+	.voltage_range = REGULATOR_LINEAR_RANGE(1504000, 0, 62, 8000),
+	.n_voltages = 63,
+	.hpm_min_load_uA = 10000,
+	.pmic_mode_map = pmic_mode_map_pmic4_ldo,
+	.of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_nldo = {
+	.regulator_type = VRM,
+	.ops = &rpmh_regulator_vrm_drms_ops,
+	.voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000),
+	.n_voltages = 124,
+	.hpm_min_load_uA = 30000,
+	.pmic_mode_map = pmic_mode_map_pmic4_ldo,
+	.of_map_mode = rpmh_regulator_pmic4_ldo_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_hfsmps510 = {
+	.regulator_type = VRM,
+	.ops = &rpmh_regulator_vrm_ops,
+	.voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000),
+	.n_voltages = 216,
+	.pmic_mode_map = pmic_mode_map_pmic4_smps,
+	.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = {
+	.regulator_type = VRM,
+	.ops = &rpmh_regulator_vrm_ops,
+	.voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 263, 4000),
+	.n_voltages = 264,
+	.pmic_mode_map = pmic_mode_map_pmic4_smps,
+	.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = {
+	.regulator_type = VRM,
+	.ops = &rpmh_regulator_vrm_ops,
+	.voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 1600),
+	.n_voltages = 5,
+	.pmic_mode_map = pmic_mode_map_pmic4_smps,
+	.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
+};
+
+static const struct rpmh_vreg_hw_data pmic5_bob = {
+	.regulator_type = VRM,
+	.ops = &rpmh_regulator_vrm_bypass_ops,
+	.voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 135, 32000),
+	.n_voltages = 135,
+	.pmic_mode_map = pmic_mode_map_pmic4_bob,
+	.of_map_mode = rpmh_regulator_pmic4_bob_of_map_mode,
+};
+
 #define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \
 { \
 	.name		= _name, \
@@ -705,6 +771,75 @@ static const struct rpmh_vreg_init_data pm8005_vreg_data[] = {
 	{},
 };
 
+static const struct rpmh_vreg_init_data pm8150_vreg_data[] = {
+	RPMH_VREG("smps1",  "smp%s1",  &pmic5_ftsmps510, "vdd-s1"),
+	RPMH_VREG("smps2",  "smp%s2",  &pmic5_ftsmps510, "vdd-s2"),
+	RPMH_VREG("smps3",  "smp%s3",  &pmic5_ftsmps510, "vdd-s3"),
+	RPMH_VREG("smps4",  "smp%s4",  &pmic5_hfsmps510,   "vdd-s4"),
+	RPMH_VREG("smps5",  "smp%s5",  &pmic5_hfsmps510,   "vdd-s5"),
+	RPMH_VREG("smps6",  "smp%s6",  &pmic5_ftsmps510, "vdd-s6"),
+	RPMH_VREG("smps7",  "smp%s7",  &pmic5_ftsmps510, "vdd-s7"),
+	RPMH_VREG("smps8",  "smp%s8",  &pmic5_ftsmps510, "vdd-s8"),
+	RPMH_VREG("smps9",  "smp%s9",  &pmic5_ftsmps510, "vdd-s9"),
+	RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps510, "vdd-s10"),
+	RPMH_VREG("ldo1",   "ldo%s1",  &pmic5_nldo,      "vdd-l1-l8-l11"),
+	RPMH_VREG("ldo2",   "ldo%s2",  &pmic5_pldo,      "vdd-l2-l10"),
+	RPMH_VREG("ldo3",   "ldo%s3",  &pmic5_nldo,      "vdd-l3-l4-l5-l18"),
+	RPMH_VREG("ldo4",   "ldo%s4",  &pmic5_nldo,      "vdd-l3-l4-l5-l18"),
+	RPMH_VREG("ldo5",   "ldo%s5",  &pmic5_nldo,      "vdd-l3-l4-l5-l18"),
+	RPMH_VREG("ldo6",   "ldo%s6",  &pmic5_nldo,      "vdd-l6-l9"),
+	RPMH_VREG("ldo7",   "ldo%s7",  &pmic5_pldo,      "vdd-l7-l12-l14-l15"),
+	RPMH_VREG("ldo8",   "ldo%s8",  &pmic5_nldo,      "vdd-l1-l8-l11"),
+	RPMH_VREG("ldo9",   "ldo%s9",  &pmic5_nldo,      "vdd-l6-l9"),
+	RPMH_VREG("ldo10",  "ldo%s10", &pmic5_pldo,      "vdd-l2-l10"),
+	RPMH_VREG("ldo11",  "ldo%s11", &pmic5_nldo,      "vdd-l1-l8-l11"),
+	RPMH_VREG("ldo12",  "ldo%s12", &pmic5_pldo_lv,   "vdd-l7-l12-l14-l15"),
+	RPMH_VREG("ldo13",  "ldo%s13", &pmic5_pldo,      "vdd-l13-l6-l17"),
+	RPMH_VREG("ldo14",  "ldo%s14", &pmic5_pldo_lv,   "vdd-l7-l12-l14-l15"),
+	RPMH_VREG("ldo15",  "ldo%s15", &pmic5_pldo_lv,   "vdd-l7-l12-l14-l15"),
+	RPMH_VREG("ldo16",  "ldo%s16", &pmic5_pldo,      "vdd-l13-l6-l17"),
+	RPMH_VREG("ldo17",  "ldo%s17", &pmic5_pldo,      "vdd-l13-l6-l17"),
+	RPMH_VREG("ldo18",  "ldo%s18", &pmic5_nldo,      "vdd-l3-l4-l5-l18"),
+	{},
+};
+
+static const struct rpmh_vreg_init_data pm8150l_vreg_data[] = {
+	RPMH_VREG("smps1",  "smp%s1",  &pmic5_ftsmps510, "vdd-s1"),
+	RPMH_VREG("smps2",  "smp%s2",  &pmic5_ftsmps510, "vdd-s2"),
+	RPMH_VREG("smps3",  "smp%s3",  &pmic5_ftsmps510, "vdd-s3"),
+	RPMH_VREG("smps4",  "smp%s4",  &pmic5_ftsmps510, "vdd-s4"),
+	RPMH_VREG("smps5",  "smp%s5",  &pmic5_ftsmps510, "vdd-s5"),
+	RPMH_VREG("smps6",  "smp%s6",  &pmic5_ftsmps510, "vdd-s6"),
+	RPMH_VREG("smps7",  "smp%s7",  &pmic5_ftsmps510, "vdd-s7"),
+	RPMH_VREG("smps8",  "smp%s8",  &pmic5_hfsmps510, "vdd-s8"),
+	RPMH_VREG("ldo1",   "ldo%s1",  &pmic5_pldo_lv,   "vdd-l1-l8"),
+	RPMH_VREG("ldo2",   "ldo%s2",  &pmic5_nldo,      "vdd-l2-l3"),
+	RPMH_VREG("ldo3",   "ldo%s3",  &pmic5_nldo,      "vdd-l2-l3"),
+	RPMH_VREG("ldo4",   "ldo%s4",  &pmic5_pldo,      "vdd-l4-l5-l6"),
+	RPMH_VREG("ldo5",   "ldo%s5",  &pmic5_pldo,      "vdd-l4-l5-l6"),
+	RPMH_VREG("ldo6",   "ldo%s6",  &pmic5_pldo,      "vdd-l4-l5-l6"),
+	RPMH_VREG("ldo7",   "ldo%s7",  &pmic5_pldo,      "vdd-l7-l11"),
+	RPMH_VREG("ldo8",   "ldo%s8",  &pmic5_pldo_lv,   "vdd-l1-l8-l11"),
+	RPMH_VREG("ldo9",   "ldo%s9",  &pmic5_pldo,      "vdd-l9-l10"),
+	RPMH_VREG("ldo10",  "ldo%s10", &pmic5_pldo,      "vdd-l9-l10"),
+	RPMH_VREG("ldo11",  "ldo%s11", &pmic5_pldo,      "vdd-l7-l11"),
+	RPMH_VREG("bob",    "bob%s1",  &pmic5_bob,       "vdd-bob"),
+	{},
+};
+
+static const struct rpmh_vreg_init_data pm8009_vreg_data[] = {
+	RPMH_VREG("smps1",  "smp%s1",  &pmic5_hfsmps510, "vdd-s1"),
+	RPMH_VREG("smps2",  "smp%s2",  &pmic5_hfsmps515, "vdd-s2"),
+	RPMH_VREG("ldo1",   "ldo%s1",  &pmic5_nldo,      "vdd-l1"),
+	RPMH_VREG("ldo2",   "ldo%s2",  &pmic5_nldo,      "vdd-l2"),
+	RPMH_VREG("ldo3",   "ldo%s3",  &pmic5_nldo,      "vdd-l3"),
+	RPMH_VREG("ldo4",   "ldo%s4",  &pmic5_nldo,      "vdd-l4"),
+	RPMH_VREG("ldo5",   "ldo%s5",  &pmic5_pldo,      "vdd-l5-l6"),
+	RPMH_VREG("ldo6",   "ldo%s6",  &pmic5_pldo,      "vdd-l5-l6"),
+	RPMH_VREG("ldo7",   "ldo%s6",  &pmic5_pldo_lv,   "vdd-l7"),
+	{},
+};
+
 static int rpmh_regulator_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -755,6 +890,18 @@ static const struct of_device_id rpmh_regulator_match_table[] = {
 		.compatible = "qcom,pm8005-rpmh-regulators",
 		.data = pm8005_vreg_data,
 	},
+	{
+		.compatible = "qcom,pm8150-rpmh-regulators",
+		.data = pm8150_vreg_data,
+	},
+	{
+		.compatible = "qcom,pm8150l-rpmh-regulators",
+		.data = pm8150l_vreg_data,
+	},
+	{
+		.compatible = "qcom,pm8009-rpmh-regulators",
+		.data = pm8009_vreg_data,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table);
-- 
2.20.1

^ permalink raw reply related

* Applied "regulator: dt-bindings: Add PM8150x compatibles" to the regulator tree
From: Mark Brown @ 2019-08-08 20:33 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Andy Gross, Bjorn Andersson, devicetree, Liam Girdwood,
	linux-arm-msm, linux-kernel, Mark Brown, Mark Rutland,
	Rob Herring
In-Reply-To: <20190808093343.5600-1-vkoul@kernel.org>

The patch

   regulator: dt-bindings: Add PM8150x compatibles

has been applied to the regulator tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-5.4

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From d566aae1c80d9be2276057b3236c68bdcc5b3254 Mon Sep 17 00:00:00 2001
From: Vinod Koul <vkoul@kernel.org>
Date: Thu, 8 Aug 2019 15:03:42 +0530
Subject: [PATCH] regulator: dt-bindings: Add PM8150x compatibles

Add PM8150, PM8150L and PM8009 compatibles for these PMICs found
in some Qualcomm platforms.

Signed-off-by: Vinod Koul <vkoul@kernel.org>
Link: https://lore.kernel.org/r/20190808093343.5600-1-vkoul@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 .../devicetree/bindings/regulator/qcom,rpmh-regulator.txt | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt
index 14d2eee96b3d..1a9cab50503a 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt
@@ -25,6 +25,9 @@ Supported regulator node names:
 	PM8998:		smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2
 	PMI8998:	bob
 	PM8005:		smps1 - smps4
+	PM8150:		smps1 - smps10, ldo1 - ldo18
+	PM8150L:	smps1 - smps8, ldo1 - ldo11, bob, flash, rgb
+	PM8009:		smps1 - smps2, ld01 - ldo7
 
 ========================
 First Level Nodes - PMIC
@@ -35,7 +38,10 @@ First Level Nodes - PMIC
 	Value type: <string>
 	Definition: Must be one of: "qcom,pm8998-rpmh-regulators",
 		    "qcom,pmi8998-rpmh-regulators" or
-		    "qcom,pm8005-rpmh-regulators".
+		    "qcom,pm8005-rpmh-regulators" or
+		    "qcom,pm8150-rpmh-regulators" or
+		    "qcom,pm8150l-rpmh-regulators" or
+		    "qcom,pm8009-rpmh-regulators".
 
 - qcom,pmic-id
 	Usage:      required
-- 
2.20.1

^ 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