Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v9 02/15] clk: mux: Split out register accessors for reuse
From: Bjorn Andersson @ 2018-05-24 16:50 UTC (permalink / raw)
  To: Sricharan R
  Cc: robh, viresh.kumar, mark.rutland, mturquette, sboyd, linux,
	andy.gross, david.brown, rjw, linux-arm-kernel, devicetree,
	linux-kernel, linux-clk, linux-arm-msm, linux-soc, linux-pm,
	linux
In-Reply-To: <1520347148-27852-3-git-send-email-sricharan@codeaurora.org>

On Tue 06 Mar 06:38 PST 2018, Sricharan R wrote:

> From: Stephen Boyd <sboyd@codeaurora.org>
> 
> We want to reuse the logic in clk-mux.c for other clock drivers
> that don't use readl as register accessors. Fortunately, there
> really isn't much to the mux code besides the table indirection
> and quirk flags if you assume any bit shifting and masking has
> been done already. Pull that logic out into reusable functions
> that operate on an optional table and some flags so that other
> drivers can use the same logic.
> 
> [Sricharan: Rebased for mainline]
> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

This should read as a log, where the first entry is Stephen stating that
he acquired or wrote the code and can release it according to the
license requirements. Then you state that you acquired it, changed it
and are releasing it according to the license requirements.


PS. Please expand your last name.

Regards,
Bjorn

> ---
>  drivers/clk/clk-mux.c         | 74 +++++++++++++++++++++++++++----------------
>  drivers/clk/nxp/clk-lpc32xx.c | 21 +++---------
>  include/linux/clk-provider.h  |  6 ++++
>  3 files changed, 57 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
> index 39cabe1..28223fa 100644
> --- a/drivers/clk/clk-mux.c
> +++ b/drivers/clk/clk-mux.c
> @@ -26,35 +26,25 @@
>   * parent - parent is adjustable through clk_set_parent
>   */
>  
> -static u8 clk_mux_get_parent(struct clk_hw *hw)
> +unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val,
> +				unsigned int *table,
> +				unsigned long flags)
>  {
> -	struct clk_mux *mux = to_clk_mux(hw);
>  	int num_parents = clk_hw_get_num_parents(hw);
> -	u32 val;
> -
> -	/*
> -	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
> -	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
> -	 * to 0x7 (index starts at one)
> -	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
> -	 * val = 0x4 really means "bit 2, index starts at bit 0"
> -	 */
> -	val = clk_readl(mux->reg) >> mux->shift;
> -	val &= mux->mask;
>  
> -	if (mux->table) {
> +	if (table) {
>  		int i;
>  
>  		for (i = 0; i < num_parents; i++)
> -			if (mux->table[i] == val)
> +			if (table[i] == val)
>  				return i;
>  		return -EINVAL;
>  	}
>  
> -	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
> +	if (val && (flags & CLK_MUX_INDEX_BIT))
>  		val = ffs(val) - 1;
>  
> -	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
> +	if (val && (flags & CLK_MUX_INDEX_ONE))
>  		val--;
>  
>  	if (val >= num_parents)
> @@ -62,23 +52,53 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
>  
>  	return val;
>  }
> +EXPORT_SYMBOL_GPL(clk_mux_get_parent);
>  
> -static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
> +static u8 _clk_mux_get_parent(struct clk_hw *hw)
>  {
>  	struct clk_mux *mux = to_clk_mux(hw);
>  	u32 val;
> -	unsigned long flags = 0;
>  
> -	if (mux->table) {
> -		index = mux->table[index];
> +	/*
> +	 * FIXME need a mux-specific flag to determine if val is bitwise or
> +	 * numeric e.g. sys_clkin_ck's clksel field is 3 bits wide,
> +	 * but ranges from 0x1 to 0x7 (index starts at one)
> +	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
> +	 * val = 0x4 really means "bit 2, index starts at bit 0"
> +	 */
> +	val = clk_readl(mux->reg) >> mux->shift;
> +	val &= mux->mask;
> +
> +	return clk_mux_get_parent(hw, val, mux->table, mux->flags);
> +}
> +
> +unsigned int clk_mux_reindex(u8 index, unsigned int *table,
> +			     unsigned long flags)
> +{
> +	unsigned int val = index;
> +
> +	if (table) {
> +		val = table[val];
>  	} else {
> -		if (mux->flags & CLK_MUX_INDEX_BIT)
> -			index = 1 << index;
> +		if (flags & CLK_MUX_INDEX_BIT)
> +			val = 1 << index;
>  
> -		if (mux->flags & CLK_MUX_INDEX_ONE)
> -			index++;
> +		if (flags & CLK_MUX_INDEX_ONE)
> +			val++;
>  	}
>  
> +	return val;
> +}
> +EXPORT_SYMBOL_GPL(clk_mux_reindex);
> +
> +static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct clk_mux *mux = to_clk_mux(hw);
> +	u32 val;
> +	unsigned long flags = 0;
> +
> +	index = clk_mux_reindex(index, mux->table, mux->flags);
> +
>  	if (mux->lock)
>  		spin_lock_irqsave(mux->lock, flags);
>  	else
> @@ -102,14 +122,14 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
>  }
>  
>  const struct clk_ops clk_mux_ops = {
> -	.get_parent = clk_mux_get_parent,
> +	.get_parent = _clk_mux_get_parent,
>  	.set_parent = clk_mux_set_parent,
>  	.determine_rate = __clk_mux_determine_rate,
>  };
>  EXPORT_SYMBOL_GPL(clk_mux_ops);
>  
>  const struct clk_ops clk_mux_ro_ops = {
> -	.get_parent = clk_mux_get_parent,
> +	.get_parent = _clk_mux_get_parent,
>  };
>  EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
>  
> diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
> index f5d815f..9b34150 100644
> --- a/drivers/clk/nxp/clk-lpc32xx.c
> +++ b/drivers/clk/nxp/clk-lpc32xx.c
> @@ -999,29 +999,16 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
>  	.set_rate = clk_divider_set_rate,
>  };
>  
> -static u8 clk_mux_get_parent(struct clk_hw *hw)
> +static u8 _clk_mux_get_parent(struct clk_hw *hw)
>  {
>  	struct lpc32xx_clk_mux *mux = to_lpc32xx_mux(hw);
> -	u32 num_parents = clk_hw_get_num_parents(hw);
>  	u32 val;
>  
>  	regmap_read(clk_regmap, mux->reg, &val);
>  	val >>= mux->shift;
>  	val &= mux->mask;
>  
> -	if (mux->table) {
> -		u32 i;
> -
> -		for (i = 0; i < num_parents; i++)
> -			if (mux->table[i] == val)
> -				return i;
> -		return -EINVAL;
> -	}
> -
> -	if (val >= num_parents)
> -		return -EINVAL;
> -
> -	return val;
> +	return clk_mux_get_parent(hw, val, mux->table, 0);
>  }
>  
>  static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
> @@ -1036,11 +1023,11 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
>  }
>  
>  static const struct clk_ops lpc32xx_clk_mux_ro_ops = {
> -	.get_parent = clk_mux_get_parent,
> +	.get_parent = _clk_mux_get_parent,
>  };
>  
>  static const struct clk_ops lpc32xx_clk_mux_ops = {
> -	.get_parent = clk_mux_get_parent,
> +	.get_parent = _clk_mux_get_parent,
>  	.set_parent = clk_mux_set_parent,
>  	.determine_rate = __clk_mux_determine_rate,
>  };
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index f711be6..344ad92 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -488,6 +488,12 @@ struct clk_mux {
>  extern const struct clk_ops clk_mux_ops;
>  extern const struct clk_ops clk_mux_ro_ops;
>  
> +unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val,
> +				unsigned int *table,
> +				unsigned long flags);
> +unsigned int clk_mux_reindex(u8 index, unsigned int *table,
> +			     unsigned long flags);
> +
>  struct clk *clk_register_mux(struct device *dev, const char *name,
>  		const char * const *parent_names, u8 num_parents,
>  		unsigned long flags,
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
> 

^ permalink raw reply

* Re: [PATCH v3 2/6] Documentation: DT: Add optional 'timeout-sec' property for sp805
From: Ray Jui @ 2018-05-24 16:42 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Wim Van Sebroeck, Rob Herring, Mark Rutland, Frank Rowand,
	Catalin Marinas, Will Deacon, Robin Murphy, linux-watchdog,
	devicetree, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list
In-Reply-To: <20180524161628.GA28425@roeck-us.net>



On 5/24/2018 9:16 AM, Guenter Roeck wrote:
> On Wed, May 23, 2018 at 05:15:20PM -0700, Ray Jui wrote:
>> Update the SP805 binding document to add optional 'timeout-sec'
>> devicetree property
>>
>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>> ---
>>   Documentation/devicetree/bindings/watchdog/arm,sp805.txt | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/watchdog/arm,sp805.txt b/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
>> index 0fa3629..1debea3 100644
>> --- a/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
>> +++ b/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
>> @@ -19,6 +19,8 @@ Required properties:
>>   
>>   Optional properties:
>>   - interrupts:  Should specify WDT interrupt number
>> +- timeout-sec: Should specify default WDT timeout in seconds. If unset, the
>> +               default timeout in the driver is 30 seconds
> 
> "... the default timeout is determined by the driver" might be better.
> If you want to mandate a default here (not sure if that is a good idea),
> I would suggest to use something like "should be 30 seconds".
> 

Okay. This can be changed to:

- timeout-sec: Should specify default WDT timeout in seconds. If unset, 
the default timeout is determined by the driver.

Please advise how to proceed with this patch series. Should I make the 
above modification and send out v4?

Thanks,

Ray

> Guenter
> 
>>   
>>   Example:
>>   	watchdog@66090000 {
>> -- 
>> 2.1.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v7 4/4] dt-bindings: drm/panel: Document Innolux TV123WAM panel bindings
From: Sandeep Panda @ 2018-05-24 16:41 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: ryadav-sgV2jX0FEOL9JmXXK+q4OQ, Sandeep Panda,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	nganji-sgV2jX0FEOL9JmXXK+q4OQ, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	chandanu-sgV2jX0FEOL9JmXXK+q4OQ
In-Reply-To: <1527180079-12721-1-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Innolux TV123WAM is a 12.3" eDP display panel with
2160x1440 resolution, which can be supported by simple
panel driver.

Changes in v1:
 - Make use of simple panel driver instead of creating
   a new driver for this panel (Sean Paul).
 - Combine dt-binding and driver changes into one patch
   as done by other existing panel support changes.

Changes in v2:
 - Separate driver change from dt-binding documentation (Rob Herring).
 - Add the properties from simple-panel binding that are applicable to
   this panel (Rob Herring).

Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
 .../bindings/display/panel/innolux,tv123wam.txt      | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt

diff --git a/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt b/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt
new file mode 100644
index 0000000..a9b3526
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt
@@ -0,0 +1,20 @@
+Innolux TV123WAM 12.3 inch eDP 2K display panel
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
+
+Required properties:
+- compatible: should be "innolux,tv123wam"
+- power-supply: regulator to provide the supply voltage
+
+Optional properties:
+- enable-gpios: GPIO pin to enable or disable the panel
+- backlight: phandle of the backlight device attached to the panel
+
+Example:
+	panel_edp: panel-edp {
+		compatible = "innolux,tv123wam";
+		enable-gpios = <&msmgpio 31 GPIO_ACTIVE_LOW>;
+		power-supply = <&pm8916_l2>;
+		backlight = <&backlight>;
+	};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related

* [PATCH v7 3/4] drm/panel: add Innolux TV123WAM panel driver support
From: Sandeep Panda @ 2018-05-24 16:41 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: ryadav-sgV2jX0FEOL9JmXXK+q4OQ, Sandeep Panda,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	nganji-sgV2jX0FEOL9JmXXK+q4OQ, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	chandanu-sgV2jX0FEOL9JmXXK+q4OQ
In-Reply-To: <1527180079-12721-1-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Add support for Innolux TV123WAM, which is a 12.3" eDP
display panel with 2160x1440 resolution.

Changes in v1:
 - Add the compatibility string, display_mode and panel_desc
   structures in alphabetical order (Sean Paul).

Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
---
 drivers/gpu/drm/panel/panel-simple.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 234af81..8c72270 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1190,6 +1190,30 @@ static void panel_simple_shutdown(struct device *dev)
 	},
 };
 
+static const struct drm_display_mode innolux_tv123wam_mode = {
+	.clock = 206016,
+	.hdisplay = 2160,
+	.hsync_start = 2160 + 48,
+	.hsync_end = 2160 + 48 + 32,
+	.htotal = 2160 + 48 + 32 + 80,
+	.vdisplay = 1440,
+	.vsync_start = 1440 + 3,
+	.vsync_end = 1440 + 3 + 10,
+	.vtotal = 1440 + 3 + 10 + 27,
+	.vrefresh = 60,
+	.flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
+};
+
+static const struct panel_desc innolux_tv123wam = {
+	.modes = &innolux_tv123wam_mode,
+	.num_modes = 1,
+	.bpc = 8,
+	.size = {
+		.width = 259,
+		.height = 173,
+	},
+};
+
 static const struct drm_display_mode innolux_zj070na_01p_mode = {
 	.clock = 51501,
 	.hdisplay = 1024,
@@ -2037,6 +2061,9 @@ static void panel_simple_shutdown(struct device *dev)
 		.compatible = "innolux,n156bge-l21",
 		.data = &innolux_n156bge_l21,
 	}, {
+		.compatible = "innolux,tv123wam",
+		.data = &innolux_tv123wam,
+	}, {
 		.compatible = "innolux,zj070na-01p",
 		.data = &innolux_zj070na_01p,
 	}, {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related

* [PATCH v7 2/4] dt-bindings: drm/bridge: Document sn65dsi86 bridge bindings
From: Sandeep Panda @ 2018-05-24 16:41 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: ryadav-sgV2jX0FEOL9JmXXK+q4OQ, Sandeep Panda,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	nganji-sgV2jX0FEOL9JmXXK+q4OQ, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	chandanu-sgV2jX0FEOL9JmXXK+q4OQ
In-Reply-To: <1527180079-12721-1-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Document the bindings used for the sn65dsi86 DSI to eDP bridge.

Changes in v1:
 - Rephrase the dt-binding descriptions to be more inline with existing
   bindings (Andrzej Hajda).
 - Add missing dt-binding that are parsed by corresponding driver
   (Andrzej Hajda).

Changes in v2:
 - Remove edp panel specific dt-binding entries. Only keep bridge
   specific entries (Sean Paul).
 - Remove custom-modes dt entry since its usage is removed from driver also (Sean Paul).
 - Remove is-pluggable dt entry since this will not be needed anymore (Sean Paul).

Changes in v3:
 - Remove irq-gpio dt entry and instead populate is an interrupt
   property (Rob Herring).

Changes in v4:
 - Add link to bridge chip datasheet (Stephen Boyd)
 - Add vpll and vcc regulator supply bindings (Stephen Boyd)
 - Add ref clk optional dt binding (Stephen Boyd)
 - Add gpio-controller optional dt binding (Stephen Boyd)

Changes in v5:
 - Use clock property to specify the input refclk (Stephen Boyd).
 - Update gpio cell and pwm cell numbers (Stephen Boyd).

Changes in v6:
 - Add property to mention the lane mapping scheme and polarity inversion
   (Stephen Boyd).

Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
---
 .../bindings/display/bridge/ti,sn65dsi86.txt       | 89 ++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt

diff --git a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt
new file mode 100644
index 0000000..4a771a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt
@@ -0,0 +1,89 @@
+SN65DSI86 DSI to eDP bridge chip
+--------------------------------
+
+This is the binding for Texas Instruments SN65DSI86 bridge.
+http://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=sn65dsi86&fileType=pdf
+
+Required properties:
+- compatible: Must be "ti,sn65dsi86"
+- reg: i2c address of the chip, 0x2d as per datasheet
+- enable-gpios: OF device-tree gpio specification for bridge_en pin
+
+- vccio-supply: A 1.8V supply that powers up the digital IOs.
+- vpll-supply: A 1.8V supply that powers up the displayport PLL.
+- vcca-supply: A 1.2V supply that powers up the analog circuits.
+- vcc-supply: A 1.2V supply that powers up the digital core.
+
+Optional properties:
+- interrupts: Specifier for the SN65DSI86 interrupt line.
+- hpd-gpios: Specifications for HPD gpio pin.
+
+- gpio-controller: Marks the device has a GPIO controller.
+- #gpio-cells    : Should be two. The first cell is the pin number and
+                   the second cell is used to specify flags.
+                   See ../../gpio/gpio.txt for more information.
+- #pwm-cells : Should be one. See ../../pwm/pwm.txt for description of
+               the cell formats.
+
+- clock-names: should be "refclk"
+- clocks: Specification for input reference clock. The reference
+	  clock rate must be 12 MHz, 19.2 MHz, 26 MHz, 27 MHz or 38.4 MHz.
+
+- lane-config: Specification to describe the logical to physical lane
+	       mapping scheme and polarity inversion of lanes.
+
+Required nodes:
+
+This device has two video ports. Their connections are modelled using the
+OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 for DSI input
+- Video port 1 for eDP output
+
+Example
+-------
+
+edp-bridge@2d {
+	compatible = "ti,sn65dsi86";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x2d>;
+
+	enable-gpios = <&msmgpio 33 GPIO_ACTIVE_HIGH>;
+	interrupt-parent = <&gpio3>;
+	interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+
+	vccio-supply = <&pm8916_l17>;
+	vcca-supply = <&pm8916_l6>;
+	vpll-supply = <&pm8916_l17>;
+	vcc-supply = <&pm8916_l6>;
+
+	clock-names = "refclk";
+	clocks = <&input_refclk>;
+
+	lane-config = <0 0>, /* Lane 0 logical is lane 0 phys (!inv) */
+		      <1 1>, /* Lane 1 logical is lane 1 phys (inv) */
+		      <2 0>, /* Lane 2 logical is lane 2 phys (!inv) */
+		      <3 1>; /* Lane 3 logical is lane 3 phys (inv) */
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			edp_bridge_in: endpoint {
+				remote-endpoint = <&dsi_out>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			edp_bridge_out: endpoint {
+				remote-endpoint = <&edp_panel_in>;
+			};
+		};
+	};
+}
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related

* [PATCH v7 1/4] drm/bridge: add support for sn65dsi86 bridge driver
From: Sandeep Panda @ 2018-05-24 16:41 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: ryadav-sgV2jX0FEOL9JmXXK+q4OQ, Sandeep Panda,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	nganji-sgV2jX0FEOL9JmXXK+q4OQ, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	chandanu-sgV2jX0FEOL9JmXXK+q4OQ
In-Reply-To: <1527180079-12721-1-git-send-email-spanda-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

Add support for TI's sn65dsi86 dsi2edp bridge chip.
The chip converts DSI transmitted signal to eDP signal,
which is fed to the connected eDP panel.

This chip can be controlled via either i2c interface or
dsi interface. Currently in driver all the control registers
are being accessed through i2c interface only.
Also as of now HPD support has not been added to bridge
chip driver.

Changes in v1:
 - Split the dt-bindings and the driver support into separate patches
   (Andrzej Hajda).
 - Use of gpiod APIs to parse and configure gpios instead of obsolete ones
   (Andrzej Hajda).
 - Use macros to define the register offsets (Andrzej Hajda).

Changes in v2:
 - Separate out edp panel specific HW resource handling from bridge
   driver and create a separate edp panel drivers to handle panel
   specific mode information and HW resources (Sean Paul).
 - Replace pr_* APIs to DRM_* APIs to log error or debug information
   (Sean Paul).
 - Remove some of the unnecessary structure/variable from driver (Sean
   Paul).
 - Rename the function and structure prefix "sn65dsi86" to "ti_sn_bridge"
   (Sean Paul / Rob Herring).
 - Remove most of the hard-coding and modified the bridge init sequence
   based on current mode (Sean Paul).
 - Remove the existing function to retrieve the EDID data and
   implemented this as an i2c_adapter and use drm_get_edid() (Sean Paul).
 - Remove the dummy irq handler implementation, will add back the
   proper irq handling later (Sean Paul).
 - Capture the required enable gpios in a single array based on dt entry
   instead of having individual descriptor for each gpio (Sean Paul).

Changes in v3:
 - Remove usage of irq_gpio and replace it as "interrupts" property (Rob
   Herring).
 - Remove the unnecessary header file inclusions (Sean Paul).
 - Rearrange the header files in alphabetical order (Sean Paul).
 - Use regmap interface to perform i2c transactions.
 - Update Copyright/License field and address other review comments
   (Jordan Crouse).

Changes in v4:
 - Update License/Copyright (Sean Paul).
 - Add Kconfig and Makefile changes (Sean Paul).
 - Drop i2c gpio handling from this bridge driver, since i2c sda/scl gpios
   will be handled by i2c master.
 - Update required supplies names.
 - Remove unnecessary goto statements (Sean Paul).
 - Add mutex lock to power_ctrl API to avoid race conditions (Sean
   Paul).
 - Add support to parse reference clk frequency from dt(optional).
 - Update the bridge chip enable/disable sequence.

Changes in v5:
 - Fixed Kbuild test service reported warnings.

Changes in v6:
 - Use PM runtime based ref-counting instead of local ref_count mechanism
   (Stephen Boyd).
 - Clean up some debug logs and indentations (Sean Paul).
 - Simplify dp rate calculation (Sean Paul).
 - Add support to configure refclk based on input REFCLK pin or DACP/N
   pin (Stephen Boyd).

Changes in v7:
 - Use static supply entries instead of dynamic allocation (Andrzej
   Hajda).
 - Defer bridge driver probe if panel is not probed (Andrzej Hajda).
 - Update of_graph APIs for correct node reference management. (Andrzej
   Hajda).
 - Remove local display_mode object (Andrzej Hajda).
 - Remove version id check function from driver.

Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
---
 drivers/gpu/drm/bridge/Kconfig        |   9 +
 drivers/gpu/drm/bridge/Makefile       |   1 +
 drivers/gpu/drm/bridge/ti-sn65dsi86.c | 675 ++++++++++++++++++++++++++++++++++
 3 files changed, 685 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/ti-sn65dsi86.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 3b99d5a..8153150 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -108,6 +108,15 @@ config DRM_TI_TFP410
 	---help---
 	  Texas Instruments TFP410 DVI/HDMI Transmitter driver
 
+config DRM_TI_SN65DSI86
+	tristate "TI SN65DSI86 DSI to eDP bridge"
+	depends on OF
+	select DRM_KMS_HELPER
+	select REGMAP_I2C
+	select DRM_PANEL
+	---help---
+	  Texas Instruments SN65DSI86 DSI to eDP Bridge driver
+
 source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 373eb28..3711be8 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -12,4 +12,5 @@ obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
 obj-y += synopsys/
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
new file mode 100644
index 0000000..3c71789
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -0,0 +1,675 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/of_graph.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+/* Link Training specific registers */
+#define SN_DEVICE_REV_REG			0x08
+#define SN_HPD_DISABLE_REG			0x5C
+#define SN_REFCLK_FREQ_REG			0x0A
+#define SN_DSI_LANES_REG			0x10
+#define SN_DSIA_CLK_FREQ_REG			0x12
+#define SN_ENH_FRAME_REG			0x5A
+#define SN_SSC_CONFIG_REG			0x93
+#define SN_DATARATE_CONFIG_REG			0x94
+#define SN_PLL_ENABLE_REG			0x0D
+#define SN_SCRAMBLE_CONFIG_REG			0x95
+#define SN_AUX_WDATA0_REG			0x64
+#define SN_AUX_ADDR_19_16_REG			0x74
+#define SN_AUX_ADDR_15_8_REG			0x75
+#define SN_AUX_ADDR_7_0_REG			0x76
+#define SN_AUX_LENGTH_REG			0x77
+#define SN_AUX_CMD_REG				0x78
+#define SN_ML_TX_MODE_REG			0x96
+/* video config specific registers */
+#define SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG	0x20
+#define SN_CHA_ACTIVE_LINE_LENGTH_HIGH_REG	0x21
+#define SN_CHA_VERTICAL_DISPLAY_SIZE_LOW_REG	0x24
+#define SN_CHA_VERTICAL_DISPLAY_SIZE_HIGH_REG	0x25
+#define SN_CHA_HSYNC_PULSE_WIDTH_LOW_REG	0x2C
+#define SN_CHA_HSYNC_PULSE_WIDTH_HIGH_REG	0x2D
+#define SN_CHA_VSYNC_PULSE_WIDTH_LOW_REG	0x30
+#define SN_CHA_VSYNC_PULSE_WIDTH_HIGH_REG	0x31
+#define SN_CHA_HORIZONTAL_BACK_PORCH_REG	0x34
+#define SN_CHA_VERTICAL_BACK_PORCH_REG		0x36
+#define SN_CHA_HORIZONTAL_FRONT_PORCH_REG	0x38
+#define SN_CHA_VERTICAL_FRONT_PORCH_REG		0x3A
+#define SN_DATA_FORMAT_REG			0x5B
+
+#define MIN_DSI_CLK_FREQ_MHZ	40
+
+/* fudge factor required to account for 8b/10b encoding */
+#define DP_CLK_FUDGE_NUM	10
+#define DP_CLK_FUDGE_DEN	8
+
+#define DPPLL_CLK_SRC_REFCLK	0
+#define DPPLL_CLK_SRC_DSICLK	1
+
+#define SN_DSIA_REFCLK_OFFSET	1
+#define SN_DSIA_LANE_OFFSET	3
+#define SN_DP_LANE_OFFSET	4
+#define SN_DP_DATA_RATE_OFFSET	5
+#define SN_TIMING_HIGH_OFFSET	8
+
+#define SN_ENABLE_VID_STREAM_BIT	BIT(3)
+#define SN_DSIA_NUM_LANES_BITS		(BIT(4) | BIT(3))
+#define SN_DP_NUM_LANES_BITS		(BIT(5) | BIT(4))
+#define SN_DP_DATA_RATE_BITS		(BIT(7) | BIT(6) | BIT(5))
+#define SN_HPD_DISABLE_BIT		BIT(0)
+
+#define SN_REGULATOR_SUPPLY_NUM		4
+
+struct ti_sn_bridge {
+	struct device			*dev;
+	struct regmap			*regmap;
+	struct drm_bridge		bridge;
+	struct drm_connector		connector;
+	struct device_node		*host_node;
+	struct mipi_dsi_device		*dsi;
+	struct clk			*refclk;
+	struct drm_panel		*panel;
+	struct gpio_desc		*enable_gpio;
+	struct regulator_bulk_data	supplies[SN_REGULATOR_SUPPLY_NUM];
+	struct i2c_adapter		*ddc;
+};
+
+static const struct regmap_range ti_sn_bridge_volatile_ranges[] = {
+	{ .range_min = 0, .range_max = 0xff },
+};
+
+static const struct regmap_access_table ti_sn_bridge_volatile_table = {
+	.yes_ranges = ti_sn_bridge_volatile_ranges,
+	.n_yes_ranges = ARRAY_SIZE(ti_sn_bridge_volatile_ranges),
+};
+
+static const struct regmap_config ti_sn_bridge_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.volatile_table = &ti_sn_bridge_volatile_table,
+	.cache_type = REGCACHE_NONE,
+};
+
+static int __maybe_unused ti_sn_bridge_resume(struct device *dev)
+{
+	struct ti_sn_bridge *pdata = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = regulator_bulk_enable(SN_REGULATOR_SUPPLY_NUM, pdata->supplies);
+	if (ret) {
+		DRM_ERROR("failed to enable supplies %d\n", ret);
+		return ret;
+	}
+
+	gpiod_set_value(pdata->enable_gpio, 1);
+
+	return ret;
+}
+
+static int __maybe_unused ti_sn_bridge_suspend(struct device *dev)
+{
+	struct ti_sn_bridge *pdata = dev_get_drvdata(dev);
+	int ret = 0;
+
+	gpiod_set_value(pdata->enable_gpio, 0);
+
+	ret = regulator_bulk_disable(SN_REGULATOR_SUPPLY_NUM, pdata->supplies);
+	if (ret)
+		DRM_ERROR("failed to disable supplies %d\n", ret);
+
+	return ret;
+}
+
+static const struct dev_pm_ops ti_sn_bridge_pm_ops = {
+	SET_RUNTIME_PM_OPS(ti_sn_bridge_suspend, ti_sn_bridge_resume, NULL)
+};
+
+/* Connector funcs */
+static struct ti_sn_bridge *
+connector_to_ti_sn_bridge(struct drm_connector *connector)
+{
+	return container_of(connector, struct ti_sn_bridge, connector);
+}
+
+static int ti_sn_bridge_connector_get_modes(struct drm_connector *connector)
+{
+	struct ti_sn_bridge *pdata = connector_to_ti_sn_bridge(connector);
+	struct edid *edid;
+	u32 num_modes;
+
+	if (pdata->panel) {
+		DRM_DEBUG_KMS("get mode from connected drm_panel\n");
+		return drm_panel_get_modes(pdata->panel);
+	}
+
+	if (!pdata->ddc)
+		return 0;
+
+	pm_runtime_get_sync(pdata->dev);
+	edid = drm_get_edid(connector, pdata->ddc);
+	pm_runtime_put_sync(pdata->dev);
+	if (!edid)
+		return 0;
+
+	drm_mode_connector_update_edid_property(connector, edid);
+	num_modes = drm_add_edid_modes(connector, edid);
+	kfree(edid);
+
+	return num_modes;
+}
+
+static enum drm_mode_status
+ti_sn_bridge_connector_mode_valid(struct drm_connector *connector,
+			     struct drm_display_mode *mode)
+{
+	/* maximum supported resolution is 4K at 60 fps */
+	if (mode->clock > 594000)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs ti_sn_bridge_connector_helper_funcs = {
+	.get_modes = ti_sn_bridge_connector_get_modes,
+	.mode_valid = ti_sn_bridge_connector_mode_valid,
+};
+
+static enum drm_connector_status
+ti_sn_bridge_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct ti_sn_bridge *pdata = connector_to_ti_sn_bridge(connector);
+
+	/**
+	 * TODO: Currently if drm_panel is present, then always
+	 * return the status as connected. Need to add support to detect
+	 * device state for no panel(hot pluggable) scenarios.
+	 */
+	if (pdata->panel)
+		return connector_status_connected;
+	else
+		return connector_status_unknown;
+}
+
+static const struct drm_connector_funcs ti_sn_bridge_connector_funcs = {
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = ti_sn_bridge_connector_detect,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static struct ti_sn_bridge *bridge_to_ti_sn_bridge(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct ti_sn_bridge, bridge);
+}
+
+static const char * const ti_sn_bridge_supply_names[] = {
+	"vcca",
+	"vcc",
+	"vccio",
+	"vpll",
+};
+
+static int ti_sn_bridge_parse_regulators(struct ti_sn_bridge *pdata)
+{
+	unsigned int i;
+
+	for (i = 0; i < SN_REGULATOR_SUPPLY_NUM; i++)
+		pdata->supplies[i].supply = ti_sn_bridge_supply_names[i];
+
+	return devm_regulator_bulk_get(pdata->dev, SN_REGULATOR_SUPPLY_NUM,
+				       pdata->supplies);
+}
+
+static int ti_sn_bridge_attach(struct drm_bridge *bridge)
+{
+	struct mipi_dsi_host *host;
+	struct mipi_dsi_device *dsi;
+	struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+	int ret;
+	const struct mipi_dsi_device_info info = { .type = "ti_sn_bridge",
+						   .channel = 0,
+						   .node = NULL,
+						 };
+
+	if (!bridge->encoder) {
+		DRM_ERROR("Parent encoder object not found\n");
+		return -ENODEV;
+	}
+
+	ret = drm_connector_init(bridge->dev, &pdata->connector,
+				 &ti_sn_bridge_connector_funcs,
+				 DRM_MODE_CONNECTOR_eDP);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector with drm\n");
+		return ret;
+	}
+
+	drm_connector_helper_add(&pdata->connector,
+				 &ti_sn_bridge_connector_helper_funcs);
+	drm_mode_connector_attach_encoder(&pdata->connector, bridge->encoder);
+
+	host = of_find_mipi_dsi_host_by_node(pdata->host_node);
+	if (!host) {
+		DRM_ERROR("failed to find dsi host\n");
+		return -ENODEV;
+	}
+
+	dsi = mipi_dsi_device_register_full(host, &info);
+	if (IS_ERR(dsi)) {
+		DRM_ERROR("failed to create dsi device\n");
+		ret = PTR_ERR(dsi);
+		return ret;
+	}
+
+	/* TODO: setting to 4 lanes always for now */
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+			  MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		DRM_ERROR("failed to attach dsi to host\n");
+		mipi_dsi_device_unregister(dsi);
+		return ret;
+	}
+
+	pdata->dsi = dsi;
+
+	DRM_DEBUG_KMS("ti_sn_bridge attached to dsi\n");
+	/* attach panel to bridge */
+	if (pdata->panel)
+		drm_panel_attach(pdata->panel, &pdata->connector);
+
+	return 0;
+}
+
+static void ti_sn_bridge_disable(struct drm_bridge *bridge)
+{
+	struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+
+	if (pdata->panel) {
+		drm_panel_disable(pdata->panel);
+		drm_panel_unprepare(pdata->panel);
+	}
+
+	/* disable video stream */
+	regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG,
+			   SN_ENABLE_VID_STREAM_BIT, 0);
+	/* semi auto link training mode OFF */
+	regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0);
+	/* disable DP PLL */
+	regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 0);
+}
+
+static u32 ti_sn_bridge_get_dsi_freq(struct ti_sn_bridge *pdata)
+{
+	u32 bit_rate_khz, clk_freq_khz;
+	struct drm_display_mode *mode =
+		&pdata->bridge.encoder->crtc->state->adjusted_mode;
+
+	bit_rate_khz = mode->clock *
+			mipi_dsi_pixel_format_to_bpp(pdata->dsi->format);
+	clk_freq_khz = bit_rate_khz / (pdata->dsi->lanes * 2);
+
+	return clk_freq_khz;
+}
+
+#define REFCLK_LUT_SIZE	5
+
+/* clk frequencies supported by bridge in Hz in case derived from REFCLK pin */
+static const u32 ti_sn_bridge_refclk_lut[] = {
+	12000000,
+	19200000,
+	26000000,
+	27000000,
+	38400000,
+};
+
+/* clk frequencies supported by bridge in Hz in case derived from DACP/N pin */
+static const u32 ti_sn_bridge_dsiclk_lut[] = {
+	468000000,
+	384000000,
+	416000000,
+	486000000,
+	460800000,
+};
+
+static void ti_sn_bridge_set_refclk(struct ti_sn_bridge *pdata)
+{
+	int i = 0;
+	u8 refclk_src;
+	u32 refclk_rate;
+	const u32 *refclk_lut;
+
+	if (pdata->refclk) {
+		refclk_src = DPPLL_CLK_SRC_REFCLK;
+		refclk_rate = clk_get_rate(pdata->refclk);
+		refclk_lut = ti_sn_bridge_refclk_lut;
+		clk_prepare_enable(pdata->refclk);
+	} else {
+		refclk_src = DPPLL_CLK_SRC_DSICLK;
+		refclk_rate = ti_sn_bridge_get_dsi_freq(pdata) * 1000;
+		refclk_lut = ti_sn_bridge_dsiclk_lut;
+	}
+
+	/* for i equals to REFCLK_LUT_SIZE means default frequency */
+	for (i = 0; i < REFCLK_LUT_SIZE; i++)
+		if (refclk_lut[i] == refclk_rate)
+			break;
+
+	regmap_write(pdata->regmap, SN_REFCLK_FREQ_REG,
+		     (refclk_src | (i << SN_DSIA_REFCLK_OFFSET)));
+}
+
+/**
+ * LUT index corresponds to register value and
+ * LUT values corresponds to dp data rate supported
+ * by the bridge in Mbps unit.
+ */
+static const unsigned int ti_sn_bridge_dp_rate_lut[] = {
+	0, 1620, 2160, 2430, 2700, 3240, 4320, 5400
+};
+
+static void ti_sn_bridge_set_dsi_dp_rate(struct ti_sn_bridge *pdata)
+{
+	unsigned int bit_rate_mhz, clk_freq_mhz, dp_rate_mhz;
+	unsigned int val = 0, i = 0;
+	struct drm_display_mode *mode =
+		&pdata->bridge.encoder->crtc->state->adjusted_mode;
+
+	/* set DSIA clk frequency */
+	bit_rate_mhz = (mode->clock / 1000) *
+			mipi_dsi_pixel_format_to_bpp(pdata->dsi->format);
+	clk_freq_mhz = bit_rate_mhz / (pdata->dsi->lanes * 2);
+
+	/* for each increment in val, frequency increases by 5MHz */
+	val = (MIN_DSI_CLK_FREQ_MHZ / 5) +
+		(((clk_freq_mhz - MIN_DSI_CLK_FREQ_MHZ) / 5) & 0xFF);
+	regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val);
+
+	/* set DP data rate */
+	dp_rate_mhz = ((bit_rate_mhz / pdata->dsi->lanes) * DP_CLK_FUDGE_NUM) /
+							DP_CLK_FUDGE_DEN;
+	for (i = 0; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i++)
+		if (ti_sn_bridge_dp_rate_lut[i] > dp_rate_mhz)
+			break;
+
+	regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG,
+			   SN_DP_DATA_RATE_BITS, i << SN_DP_DATA_RATE_OFFSET);
+}
+
+static void ti_sn_bridge_set_video_timings(struct ti_sn_bridge *pdata)
+{
+	struct drm_display_mode *mode =
+		&pdata->bridge.encoder->crtc->state->adjusted_mode;
+
+	regmap_write(pdata->regmap, SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG,
+		     mode->hdisplay & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_ACTIVE_LINE_LENGTH_HIGH_REG,
+		     (mode->hdisplay >> SN_TIMING_HIGH_OFFSET) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_VERTICAL_DISPLAY_SIZE_LOW_REG,
+		     mode->vdisplay & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_VERTICAL_DISPLAY_SIZE_HIGH_REG,
+		     (mode->vdisplay >> SN_TIMING_HIGH_OFFSET) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_HSYNC_PULSE_WIDTH_LOW_REG,
+		     (mode->hsync_end - mode->hsync_start) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_HSYNC_PULSE_WIDTH_HIGH_REG,
+		     ((mode->hsync_end - mode->hsync_start) >>
+		      SN_TIMING_HIGH_OFFSET) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_VSYNC_PULSE_WIDTH_LOW_REG,
+		     (mode->vsync_end - mode->vsync_start) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_VSYNC_PULSE_WIDTH_HIGH_REG,
+		     ((mode->vsync_end - mode->vsync_start) >>
+		      SN_TIMING_HIGH_OFFSET) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_HORIZONTAL_BACK_PORCH_REG,
+		     (mode->htotal - mode->hsync_end) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_VERTICAL_BACK_PORCH_REG,
+		     (mode->vtotal - mode->vsync_end) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_HORIZONTAL_FRONT_PORCH_REG,
+		     (mode->hsync_start - mode->hdisplay) & 0xFF);
+	regmap_write(pdata->regmap, SN_CHA_VERTICAL_FRONT_PORCH_REG,
+		     (mode->vsync_start - mode->vdisplay) & 0xFF);
+	usleep_range(10000, 10500); /* 10ms delay recommended by spec */
+}
+
+static void ti_sn_bridge_enable(struct drm_bridge *bridge)
+{
+	struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+	unsigned int val = 0;
+
+	if (pdata->panel) {
+		drm_panel_prepare(pdata->panel);
+		/* in case drm_panel is connected then HPD is not supported */
+		regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG,
+				   SN_HPD_DISABLE_BIT, SN_HPD_DISABLE_BIT);
+	}
+
+	/* DSI_A lane config */
+	val = (4 - pdata->dsi->lanes) << SN_DSIA_LANE_OFFSET;
+	regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG,
+			   SN_DSIA_NUM_LANES_BITS, val);
+
+	/* DP lane config */
+	val = (pdata->dsi->lanes - 1) << SN_DP_LANE_OFFSET;
+	regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG,
+			   SN_DP_NUM_LANES_BITS, val);
+
+	/* set dsi/dp clk frequency value */
+	ti_sn_bridge_set_dsi_dp_rate(pdata);
+
+	/* enable DP PLL */
+	regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 1);
+	usleep_range(10000, 10500); /* 10ms delay recommended by spec */
+
+	/**
+	 * The SN65DSI86 only supports ASSR Display Authentication method and
+	 * this method is enabled by default. An eDP panel must support this
+	 * authentication method. We need to enable this method in the eDP panel
+	 * at DisplayPort address 0x0010A prior to link training.
+	 */
+	regmap_write(pdata->regmap, SN_AUX_WDATA0_REG, 0x01);
+	regmap_write(pdata->regmap, SN_AUX_ADDR_19_16_REG, 0x00);
+	regmap_write(pdata->regmap, SN_AUX_ADDR_15_8_REG, 0x01);
+	regmap_write(pdata->regmap, SN_AUX_ADDR_7_0_REG, 0x0A);
+	regmap_write(pdata->regmap, SN_AUX_LENGTH_REG, 0x01);
+	regmap_write(pdata->regmap, SN_AUX_CMD_REG, 0x81);
+	usleep_range(10000, 10500); /* 10ms delay recommended by spec */
+
+	/* Semi auto link training mode */
+	regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A);
+	msleep(20); /* 20ms delay recommended by spec */
+
+	/* config video parameters */
+	ti_sn_bridge_set_video_timings(pdata);
+
+	/* enable video stream */
+	regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG,
+			   SN_ENABLE_VID_STREAM_BIT, SN_ENABLE_VID_STREAM_BIT);
+
+	if (pdata->panel)
+		drm_panel_enable(pdata->panel);
+}
+
+static void ti_sn_bridge_pre_enable(struct drm_bridge *bridge)
+{
+	struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+
+	pm_runtime_get_sync(pdata->dev);
+
+	/* configure bridge CLK_SRC and ref_clk */
+	ti_sn_bridge_set_refclk(pdata);
+}
+
+static void ti_sn_bridge_post_disable(struct drm_bridge *bridge)
+{
+	struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge);
+
+	if (pdata->refclk)
+		clk_disable_unprepare(pdata->refclk);
+
+	pm_runtime_put_sync(pdata->dev);
+}
+
+static const struct drm_bridge_funcs ti_sn_bridge_funcs = {
+	.attach = ti_sn_bridge_attach,
+	.pre_enable = ti_sn_bridge_pre_enable,
+	.enable = ti_sn_bridge_enable,
+	.disable = ti_sn_bridge_disable,
+	.post_disable = ti_sn_bridge_post_disable,
+};
+
+static int ti_sn_bridge_parse_dsi_host(struct ti_sn_bridge *pdata)
+{
+	struct device_node *np = pdata->dev->of_node;
+
+	pdata->host_node = of_graph_get_remote_node(np, 0, 0);
+
+	if (!pdata->host_node) {
+		DRM_ERROR("remote dsi host node not found\n");
+		return -ENODEV;
+	}
+	of_node_put(pdata->host_node);
+
+	return 0;
+}
+
+static int ti_sn_bridge_probe(struct i2c_client *client,
+	 const struct i2c_device_id *id)
+{
+	struct ti_sn_bridge *pdata;
+	struct device_node *ddc_node;
+	int ret = 0;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		DRM_ERROR("device doesn't support I2C\n");
+		return -ENODEV;
+	}
+
+	pdata = devm_kzalloc(&client->dev, sizeof(struct ti_sn_bridge),
+			     GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->dev = &client->dev;
+	dev_set_drvdata(&client->dev, pdata);
+
+	ret = drm_of_find_panel_or_bridge(pdata->dev->of_node, 1, 0,
+					  &pdata->panel, NULL);
+	if (ret) {
+		DRM_ERROR("could not find any drm panel node\n");
+		return ret;
+	}
+
+	pdata->regmap = devm_regmap_init_i2c(client,
+					     &ti_sn_bridge_regmap_config);
+	if (IS_ERR(pdata->regmap)) {
+		DRM_ERROR("regmap i2c init failed\n");
+		return PTR_ERR(pdata->regmap);
+	}
+
+	pdata->enable_gpio = devm_gpiod_get(pdata->dev,
+					    "enable", GPIOD_OUT_LOW);
+	if (IS_ERR(pdata->enable_gpio)) {
+		DRM_ERROR("failed to get enable gpio from DT\n");
+		ret = PTR_ERR(pdata->enable_gpio);
+		return ret;
+	}
+
+	ret = ti_sn_bridge_parse_regulators(pdata);
+	if (ret) {
+		DRM_ERROR("failed to parse regulators\n");
+		return ret;
+	}
+
+	ret = ti_sn_bridge_parse_dsi_host(pdata);
+	if (ret)
+		return ret;
+
+	pm_runtime_enable(pdata->dev);
+
+	pdata->refclk = devm_clk_get(pdata->dev, "refclk");
+
+	ddc_node = of_parse_phandle(pdata->dev->of_node, "ddc-i2c-bus", 0);
+	if (ddc_node) {
+		pdata->ddc = of_find_i2c_adapter_by_node(ddc_node);
+		of_node_put(ddc_node);
+		if (!pdata->ddc) {
+			DRM_DEBUG_KMS("failed to read ddc node\n");
+			pm_runtime_disable(pdata->dev);
+			return -EPROBE_DEFER;
+		}
+	} else {
+		DRM_DEBUG_KMS("no ddc property found\n");
+	}
+
+	i2c_set_clientdata(client, pdata);
+
+	pdata->bridge.funcs = &ti_sn_bridge_funcs;
+	pdata->bridge.of_node = client->dev.of_node;
+
+	drm_bridge_add(&pdata->bridge);
+
+	return 0;
+}
+
+static int ti_sn_bridge_remove(struct i2c_client *client)
+{
+	struct ti_sn_bridge *pdata = i2c_get_clientdata(client);
+
+	if (!pdata)
+		return -EINVAL;
+
+	mipi_dsi_detach(pdata->dsi);
+	mipi_dsi_device_unregister(pdata->dsi);
+
+	drm_bridge_remove(&pdata->bridge);
+	pm_runtime_disable(pdata->dev);
+	i2c_put_adapter(pdata->ddc);
+
+	return 0;
+}
+
+static struct i2c_device_id ti_sn_bridge_id[] = {
+	{ "ti,sn65dsi86", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, ti_sn_bridge_id);
+
+static const struct of_device_id ti_sn_bridge_match_table[] = {
+	{.compatible = "ti,sn65dsi86"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ti_sn_bridge_match_table);
+
+static struct i2c_driver ti_sn_bridge_driver = {
+	.driver = {
+		.name = "ti_sn65dsi86",
+		.of_match_table = ti_sn_bridge_match_table,
+		.pm = &ti_sn_bridge_pm_ops,
+	},
+	.probe = ti_sn_bridge_probe,
+	.remove = ti_sn_bridge_remove,
+	.id_table = ti_sn_bridge_id,
+};
+
+module_i2c_driver(ti_sn_bridge_driver);
+MODULE_DESCRIPTION("sn65dsi86 DSI to eDP bridge driver");
+MODULE_LICENSE("GPL v2");
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related

* [PATCH v7 0/4] Add suppport for sn65dsi86 bridge chip and Innolux 2k edp panel
From: Sandeep Panda @ 2018-05-24 16:41 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: ryadav-sgV2jX0FEOL9JmXXK+q4OQ, Sandeep Panda,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	nganji-sgV2jX0FEOL9JmXXK+q4OQ, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	chandanu-sgV2jX0FEOL9JmXXK+q4OQ

Changes in current patchset:
 - Defer bridge driver probe until panel probe happens.
 - Update the of_graph APIs based on comments.
 - Add optional lane-config dt-binding to bridge documentation.

Sandeep Panda (4):
  drm/bridge: add support for sn65dsi86 bridge driver
  dt-bindings: drm/bridge: Document sn65dsi86 bridge bindings
  drm/panel: add Innolux TV123WAM panel driver support
  dt-bindings: drm/panel: Document Innolux TV123WAM panel bindings

 .../bindings/display/bridge/ti,sn65dsi86.txt       |  89 +++
 .../bindings/display/panel/innolux,tv123wam.txt    |  20 +
 drivers/gpu/drm/bridge/Kconfig                     |   9 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/ti-sn65dsi86.c              | 675 +++++++++++++++++++++
 drivers/gpu/drm/panel/panel-simple.c               |  27 +
 6 files changed, 821 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.txt
 create mode 100644 Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt
 create mode 100644 drivers/gpu/drm/bridge/ti-sn65dsi86.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply

* Re: [PATCH v3 4/6] watchdog: sp805: set WDOG_HW_RUNNING when appropriate
From: Ray Jui @ 2018-05-24 16:36 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Wim Van Sebroeck, Rob Herring, Mark Rutland, Frank Rowand,
	Catalin Marinas, Will Deacon, Robin Murphy, linux-watchdog,
	devicetree, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list
In-Reply-To: <20180524161901.GB28425@roeck-us.net>



On 5/24/2018 9:19 AM, Guenter Roeck wrote:
> On Wed, May 23, 2018 at 05:15:22PM -0700, Ray Jui wrote:
>> If the watchdog hardware is already enabled during the boot process,
>> when the Linux watchdog driver loads, it should reset the watchdog and
>> tell the watchdog framework. As a result, ping can be generated from
>> the watchdog framework, until the userspace watchdog daemon takes over
>> control
>>
>> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
>> Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
>> Reviewed-by: Scott Branden <scott.branden@broadcom.com>
> 
> Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> 
> I have one question, though: Is it really correct that both
> INT_ENABLE _and_ RESET_ENABLE have to be set to enable the watdog ?
> What if only RESET_ENABLE is set ?

According to the SP805 TRM, INT_ENABLE needs to be set to high to enable 
the counter and the interrupt. Counter will be stopped if INT_ENABLE is 
cleared. So yes, INT_ENABLE needs to be set.

Thanks,

Ray

> 
> Thanks,
> Guenter
> 
>> ---
>>   drivers/watchdog/sp805_wdt.c | 19 +++++++++++++++++++
>>   1 file changed, 19 insertions(+)
>>
>> diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
>> index 1484609..d662a6f 100644
>> --- a/drivers/watchdog/sp805_wdt.c
>> +++ b/drivers/watchdog/sp805_wdt.c
>> @@ -42,6 +42,7 @@
>>   	/* control register masks */
>>   	#define	INT_ENABLE	(1 << 0)
>>   	#define	RESET_ENABLE	(1 << 1)
>> +	#define	ENABLE_MASK	(INT_ENABLE | RESET_ENABLE)
>>   #define WDTINTCLR		0x00C
>>   #define WDTRIS			0x010
>>   #define WDTMIS			0x014
>> @@ -74,6 +75,15 @@ module_param(nowayout, bool, 0);
>>   MODULE_PARM_DESC(nowayout,
>>   		"Set to 1 to keep watchdog running after device release");
>>   
>> +/* returns true if wdt is running; otherwise returns false */
>> +static bool wdt_is_running(struct watchdog_device *wdd)
>> +{
>> +	struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
>> +	u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);
>> +
>> +	return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK;
>> +}
>> +
>>   /* This routine finds load value that will reset system in required timout */
>>   static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
>>   {
>> @@ -239,6 +249,15 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
>>   	watchdog_init_timeout(&wdt->wdd, 0, &adev->dev);
>>   	wdt_setload(&wdt->wdd, wdt->wdd.timeout);
>>   
>> +	/*
>> +	 * If HW is already running, enable/reset the wdt and set the running
>> +	 * bit to tell the wdt subsystem
>> +	 */
>> +	if (wdt_is_running(&wdt->wdd)) {
>> +		wdt_enable(&wdt->wdd);
>> +		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
>> +	}
>> +
>>   	ret = watchdog_register_device(&wdt->wdd);
>>   	if (ret) {
>>   		dev_err(&adev->dev, "watchdog_register_device() failed: %d\n",
>> -- 
>> 2.1.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCHv5 8/8] Documentation: driver-api: add stratix10 service layer
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-fpga, linux-doc,
	yves.vandervennet, richard.gong, richard.gong
In-Reply-To: <1527179600-26441-1-git-send-email-richard.gong@linux.intel.com>

From: Richard Gong <richard.gong@intel.com>

Add new file stratix10-svc.rst
Add stratix10-svc.rst to driver-api/index.rst

Signed-off-by: Richard Gong <richard.gong@intel.com>
Signed-off-by: Alan Tull <atull@kernel.org>
---
v5: this patch is added in patch set version 5
---
 Documentation/driver-api/index.rst         |  1 +
 Documentation/driver-api/stratix10-svc.rst | 32 ++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 Documentation/driver-api/stratix10-svc.rst

diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index 6d8352c..4b31109 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -49,6 +49,7 @@ available subsections can be seen below.
    dmaengine/index
    slimbus
    soundwire/index
+   stratix10-svc
 
 .. only::  subproject and html
 
diff --git a/Documentation/driver-api/stratix10-svc.rst b/Documentation/driver-api/stratix10-svc.rst
new file mode 100644
index 0000000..ed361d8
--- /dev/null
+++ b/Documentation/driver-api/stratix10-svc.rst
@@ -0,0 +1,32 @@
+
+Intel Stratix10 SoC Service Layer
+=================================
+
+Some features of the Intel Stratix10 SoC require a level of privilege
+higher than the kernel is granted. Such secure features include
+FPGA programming. In terms of the ARMv8 architecture, the kernel runs
+at Exception Level 1 (EL1), access to the features requires
+Exception Level 3 (EL3).
+
+The Intel Stratix10 SoC service layer provides an in kernel API for
+drivers to request access to the secure features. The requests are queued
+and processed one by one. ARM’s SMCCC is used to pass the execution
+of the requests on to a secure monitor (EL3).
+
+.. kernel-doc:: include/linux/stratix10-svc-client.h
+   :functions: stratix10_svc_command_code
+
+.. kernel-doc:: include/linux/stratix10-svc-client.h
+   :functions: stratix10_svc_client_msg
+
+.. kernel-doc:: include/linux/stratix10-svc-client.h
+   :functions: stratix10_svc_command_reconfig_payload
+
+.. kernel-doc:: include/linux/stratix10-svc-client.h
+   :functions: stratix10_svc_cb_data
+
+.. kernel-doc:: include/linux/stratix10-svc-client.h
+   :functions: stratix10_svc_client
+
+.. kernel-doc:: drivers/misc/stratix10-svc.c
+   :export:
-- 
2.7.4

^ permalink raw reply related

* [PATCHv5 7/8] defconfig: enable fpga and service layer
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-fpga, linux-doc,
	yves.vandervennet, richard.gong, richard.gong
In-Reply-To: <1527179600-26441-1-git-send-email-richard.gong@linux.intel.com>

From: Richard Gong <richard.gong@intel.com>

Enable fpga framework, Stratix 10 SoC FPGA manager and Stratix10
Service Layer

Signed-off-by: Richard Gong <richard.gong@intel.com>
Signed-off-by: Alan Tull <atull@kernel.org>
---
v2: this patch is added in patch set version 2
v3: no change
v4: s/CONFIG_INTEL_SERVICE/CONFIG_STRATIX10_SERVICE/
    add CONFIG_OF_FPGA_REGION=y
    s/Intel/Stratix10/ in subject line
v5: no change
---
 arch/arm64/configs/defconfig | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index ecf6137..5f7a9b7 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -180,6 +180,7 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
 CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_NVME=m
+CONFIG_STRATIX10_SERVICE=y
 CONFIG_SRAM=y
 CONFIG_EEPROM_AT25=m
 # CONFIG_SCSI_PROC_FS is not set
@@ -595,6 +596,11 @@ CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_QCOM_L2_PMU=y
 CONFIG_QCOM_L3_PMU=y
 CONFIG_MESON_EFUSE=m
+CONFIG_FPGA=y
+CONFIG_FPGA_MGR_STRATIX10_SOC=y
+CONFIG_FPGA_REGION=y
+CONFIG_FPGA_BRIDGE=y
+CONFIG_OF_FPGA_REGION=y
 CONFIG_QCOM_QFPROM=y
 CONFIG_UNIPHIER_EFUSE=y
 CONFIG_TEE=y
-- 
2.7.4

^ permalink raw reply related

* [PATCHv5 6/8] fpga: add intel stratix10 soc fpga manager driver
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-fpga, linux-doc,
	yves.vandervennet, richard.gong, richard.gong
In-Reply-To: <1527179600-26441-1-git-send-email-richard.gong@linux.intel.com>

From: Alan Tull <atull@kernel.org>

Add driver for reconfiguring Intel Stratix10 SoC FPGA devices.
This driver communicates through the Intel Service Driver which
does communication with privileged hardware (that does the
FPGA programming) through a secure mailbox.

Signed-off-by: Alan Tull <atull@kernel.org>
Signed-off-by: Richard Gong <richard.gong@intel.com>
---
v2: this patch is added in patch set version 2
v3: change to align to the update of service client APIs, and the
    update of fpga_mgr device node
v4: changes to align with stratix10-svc-client API updates
    add Richard's signed-off-by
v5: update to align changes at service layer to minimize service
    layer thread usages
---
 drivers/fpga/Kconfig         |   6 +
 drivers/fpga/Makefile        |   1 +
 drivers/fpga/stratix10-soc.c | 545 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 552 insertions(+)
 create mode 100644 drivers/fpga/stratix10-soc.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index f47ef84..1624a73 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -57,6 +57,12 @@ config FPGA_MGR_ZYNQ_FPGA
 	help
 	  FPGA manager driver support for Xilinx Zynq FPGAs.
 
+config FPGA_MGR_STRATIX10_SOC
+	tristate "Intel Stratix10 SoC FPGA Manager"
+	depends on (ARCH_STRATIX10 && STRATIX10_SERVICE)
+	help
+	  FPGA manager driver support for the Intel Stratix10 SoC.
+
 config FPGA_MGR_XILINX_SPI
 	tristate "Xilinx Configuration over Slave Serial (SPI)"
 	depends on SPI
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 3cb276a..6eef670 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_FPGA_MGR_ALTERA_PS_SPI)	+= altera-ps-spi.o
 obj-$(CONFIG_FPGA_MGR_ICE40_SPI)	+= ice40-spi.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
 obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)	+= socfpga-a10.o
+obj-$(CONFIG_FPGA_MGR_STRATIX10_SOC)	+= stratix10-soc.o
 obj-$(CONFIG_FPGA_MGR_TS73XX)		+= ts73xx-fpga.o
 obj-$(CONFIG_FPGA_MGR_XILINX_SPI)	+= xilinx-spi.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c
new file mode 100644
index 0000000..d645ef7
--- /dev/null
+++ b/drivers/fpga/stratix10-soc.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FPGA Manager Driver for Intel Stratix10 SoC
+ *
+ *  Copyright (C) 2018 Intel Corporation
+ */
+#include <linux/completion.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/stratix10-svc-client.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+/*
+ * FPGA programming requires a higher level of privilege (EL3), per the SoC
+ * design.
+ */
+#define NUM_SVC_BUFS	4
+#define SVC_BUF_SIZE	SZ_512K
+
+/* Indicates buffer is in use if set */
+#define SVC_BUF_LOCK	0
+
+/**
+ * struct s10_svc_buf
+ * @buf: virtual address of buf provided by service layer
+ * @lock: locked if buffer is in use
+ */
+struct s10_svc_buf {
+	char *buf;
+	unsigned long lock;
+};
+
+struct s10_priv {
+	struct stratix10_svc_chan *chan;
+	struct stratix10_svc_client client;
+	struct completion status_return_completion;
+	struct s10_svc_buf svc_bufs[NUM_SVC_BUFS];
+	unsigned long status;
+};
+
+static int s10_svc_send_msg(struct s10_priv *priv,
+			    enum stratix10_svc_command_code command,
+			    void *payload, u32 payload_length)
+{
+	struct stratix10_svc_chan *chan = priv->chan;
+	struct stratix10_svc_client_msg msg;
+	int ret;
+
+	pr_debug("%s cmd=%d payload=%p legnth=%d\n",
+		 __func__, command, payload, payload_length);
+
+	msg.command = command;
+	msg.payload = payload;
+	msg.payload_length = payload_length;
+
+	ret = stratix10_svc_send(chan, &msg);
+	pr_debug("stratix10_svc_send returned status %d\n", ret);
+
+	return ret;
+}
+
+/**
+ * s10_free_buffers
+ * Free buffers allocated from the service layer's pool that are not in use.
+ * @mgr: fpga manager struct
+ * Free all buffers that are not in use.
+ * Return true when all buffers are freed.
+ */
+static bool s10_free_buffers(struct fpga_manager *mgr)
+{
+	struct s10_priv *priv = mgr->priv;
+	uint num_free = 0;
+	uint i;
+
+	for (i = 0; i < NUM_SVC_BUFS; i++) {
+		if (!priv->svc_bufs[i].buf) {
+			num_free++;
+			continue;
+		}
+
+		if (!test_and_set_bit_lock(SVC_BUF_LOCK,
+					   &priv->svc_bufs[i].lock)) {
+			stratix10_svc_free_memory(priv->chan,
+					      priv->svc_bufs[i].buf);
+			priv->svc_bufs[i].buf = NULL;
+			num_free++;
+		}
+	}
+
+	return num_free == NUM_SVC_BUFS;
+}
+
+/**
+ * s10_free_buffer_count
+ * Count how many buffers are not in use.
+ * @mgr: fpga manager struct
+ * Return # of buffers that are not in use.
+ */
+static uint s10_free_buffer_count(struct fpga_manager *mgr)
+{
+	struct s10_priv *priv = mgr->priv;
+	uint num_free = 0;
+	uint i;
+
+	for (i = 0; i < NUM_SVC_BUFS; i++)
+		if (!priv->svc_bufs[i].buf)
+			num_free++;
+
+	return num_free;
+}
+
+/**
+ * s10_unlock_bufs
+ * Given the returned buffer address, match that address to our buffer struct
+ * and unlock that buffer.  This marks it as available to be refilled and sent
+ * (or freed).
+ * @priv: private data
+ * @kaddr: kernel address of buffer that was returned from service layer
+ */
+static void s10_unlock_bufs(struct s10_priv *priv, void *kaddr)
+{
+	uint i;
+
+	if (!kaddr)
+		return;
+
+	for (i = 0; i < NUM_SVC_BUFS; i++)
+		if (priv->svc_bufs[i].buf == kaddr) {
+			clear_bit_unlock(SVC_BUF_LOCK,
+					 &priv->svc_bufs[i].lock);
+			return;
+		}
+
+	WARN(1, "Unknown buffer returned from service layer %p\n", kaddr);
+}
+
+/**
+ * s10_receive_callback
+ * Callback for service layer to use to provide client (this driver) messages
+ * received through the mailbox.
+ * @client: service layer client struct
+ * @data: message
+ */
+static void s10_receive_callback(struct stratix10_svc_client *client,
+				 struct stratix10_svc_cb_data *data)
+{
+	struct s10_priv *priv = client->priv;
+	u32 status;
+	int i;
+
+	WARN_ONCE(!data, "%s: stratix10_svc_rc_data = NULL", __func__);
+
+	status = data->status;
+
+	/*
+	 * Here we set status bits as we receive them.  Elsewhere, we always use
+	 * test_and_clear_bit() to check status in priv->status
+	 */
+	for (i = 0; i <= SVC_STATUS_RECONFIG_ERROR; i++)
+		if (status & (1 << i))
+			set_bit(i, &priv->status);
+
+	if (status & BIT(SVC_STATUS_RECONFIG_BUFFER_DONE)) {
+		s10_unlock_bufs(priv, data->kaddr1);
+		s10_unlock_bufs(priv, data->kaddr2);
+		s10_unlock_bufs(priv, data->kaddr3);
+	}
+
+	complete(&priv->status_return_completion);
+}
+
+/**
+ * s10_ops_write_init
+ * Prepare for FPGA reconfiguration by requesting partial reconfig and
+ * allocating buffers from the service layer.
+ * @mgr: fpga manager
+ * @info: fpga image info
+ * @buf: fpga image buffer
+ * @count: size of buf in bytes
+ */
+static int s10_ops_write_init(struct fpga_manager *mgr,
+			      struct fpga_image_info *info,
+			      const char *buf, size_t count)
+{
+	struct s10_priv *priv = mgr->priv;
+	struct device *dev = priv->client.dev;
+	unsigned long timeout;
+	struct stratix10_svc_command_reconfig_payload payload;
+	char *kbuf;
+	uint i;
+	int ret;
+
+	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
+		dev_info(dev, "Requesting partial reconfiguration.\n");
+		payload.flags |= BIT(COMMAND_RECONFIG_FLAG_PARTIAL);
+	} else {
+		dev_info(dev, "Requesting full reconfiguration.\n");
+	}
+
+	reinit_completion(&priv->status_return_completion);
+	ret = s10_svc_send_msg(priv, COMMAND_RECONFIG,
+			       &payload, sizeof(payload));
+	if (ret)
+		goto init_done;
+
+	timeout = msecs_to_jiffies(SVC_RECONFIG_REQUEST_TIMEOUT_MS);
+	ret = wait_for_completion_interruptible_timeout(
+		&priv->status_return_completion, timeout);
+	if (!ret) {
+		dev_err(dev, "timeout waiting for RECONFIG_REQUEST\n");
+		ret = -ETIMEDOUT;
+		goto init_done;
+	}
+	if (ret < 0) {
+		dev_err(dev, "error (%d) waiting for RECONFIG_REQUEST\n", ret);
+		goto init_done;
+	}
+
+	ret = 0;
+	if (!test_and_clear_bit(SVC_STATUS_RECONFIG_REQUEST_OK,
+				&priv->status)) {
+		ret = -ETIMEDOUT;
+		goto init_done;
+	}
+
+	/* Allocate buffers from the service layer's pool. */
+	for (i = 0; i < NUM_SVC_BUFS; i++) {
+		kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE);
+		if (!kbuf) {
+			s10_free_buffers(mgr);
+			ret = -ENOMEM;
+			goto init_done;
+		}
+
+		priv->svc_bufs[i].buf = kbuf;
+		priv->svc_bufs[i].lock = 0;
+	}
+
+init_done:
+	stratix10_svc_done(priv->chan);
+	return ret;
+}
+
+/**
+ * s10_send_buf
+ * Send a buffer to the service layer queue
+ * @mgr: fpga manager struct
+ * @buf_num: index of buffer in svc_bufs array
+ * @buf: fpga image buffer
+ * @count: size of buf in bytes
+ * Returns # of bytes transferred or -errno, never 0
+ */
+static int s10_send_buf(struct fpga_manager *mgr, uint buf_num,
+			const char *buf, size_t count)
+
+{
+	struct s10_priv *priv = mgr->priv;
+	struct device *dev = priv->client.dev;
+	void *svc_buf;
+	size_t xfer_sz;
+	int ret;
+
+	xfer_sz = count < SVC_BUF_SIZE ? count : SVC_BUF_SIZE;
+
+	svc_buf = priv->svc_bufs[buf_num].buf;
+	memcpy(svc_buf, buf, xfer_sz);
+	ret = s10_svc_send_msg(priv, COMMAND_RECONFIG_DATA_SUBMIT,
+			       svc_buf, xfer_sz);
+	if (ret) {
+		dev_err(dev,
+			"Error while sending data to service layer (%d)", ret);
+		return ret;
+	}
+
+	return xfer_sz;
+}
+
+/**
+ * s10_ops_write
+ * Send a FPGA image to privileged layers to write to the FPGA.  When done
+ * sending, free all service layer buffers we allocated in write_init.
+ * @mgr: fpga manager
+ * @buf: fpga image buffer
+ * @count: size of buf in bytes
+ * Returns 0 for success or negative errno.
+ */
+static int s10_ops_write(struct fpga_manager *mgr, const char *buf,
+			 size_t count)
+{
+	struct s10_priv *priv = mgr->priv;
+	struct device *dev = priv->client.dev;
+	unsigned long timeout;
+	size_t sent = 0;
+	int ret = 0;
+	uint i;
+
+	timeout = msecs_to_jiffies(SVC_RECONFIG_BUFFER_TIMEOUT_MS);
+
+	/* Buffer loop: either send buffers or free them. */
+	while (1) {
+		reinit_completion(&priv->status_return_completion);
+
+		if (count > 0) {
+			for (i = 0; i < NUM_SVC_BUFS; i++)
+				if (!test_and_set_bit_lock(
+					 SVC_BUF_LOCK, &priv->svc_bufs[i].lock))
+					break;
+
+			if (i == NUM_SVC_BUFS)
+				/* wait for a free buffer */
+				continue;
+
+			sent = s10_send_buf(mgr, i, buf, count);
+			/*
+			 * If service queue was full, we won't get a callback.
+			 * Wait and try again
+			 */
+			if (sent < 0)
+				continue;
+
+			count -= sent;
+			buf += sent;
+		} else {
+			s10_free_buffers(mgr);
+			if (s10_free_buffer_count(mgr) == NUM_SVC_BUFS)
+				return 0;
+
+			ret = s10_svc_send_msg(
+				priv, COMMAND_RECONFIG_DATA_CLAIM,
+				NULL, 0);
+			if (ret)
+				break;
+		}
+
+		/*
+		 * If callback hasn't already happened, wait for buffers to be
+		 * returned from service layer
+		 */
+		if (priv->status)
+			ret = 0;
+		else
+			ret = wait_for_completion_interruptible_timeout(
+				&priv->status_return_completion, timeout);
+
+		if (test_and_clear_bit(
+				SVC_STATUS_RECONFIG_BUFFER_DONE, &priv->status))
+			continue;
+
+		if (test_and_clear_bit(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED,
+				       &priv->status))
+			continue;
+
+		if (test_and_clear_bit(SVC_STATUS_RECONFIG_ERROR,
+				       &priv->status)) {
+			dev_err(dev, "ERROR - giving up - SVC_STATUS_RECONFIG_ERROR\n");
+			ret = -EFAULT;
+			break;
+		}
+
+		if (!ret) {
+			dev_err(dev, "timeout waiting for svc layer buffers\n");
+			ret = -ETIMEDOUT;
+			break;
+		}
+		if (ret < 0) {
+			dev_err(dev,
+				"error (%d) waiting for svc layer buffers\n",
+				ret);
+			break;
+		}
+	}
+
+	s10_free_buffers(mgr);
+	if (s10_free_buffer_count(mgr) != NUM_SVC_BUFS)
+		dev_err(dev, "%s not all buffers were freed\n", __func__);
+
+	return ret;
+}
+
+/**
+ * s10_ops_write_complete
+ * Wait for FPGA configuration to be done
+ * @mgr: fpga manager
+ * @info: fpga image info
+ * Returns 0 for success negative errno.
+ */
+static int s10_ops_write_complete(struct fpga_manager *mgr,
+				  struct fpga_image_info *info)
+{
+	struct s10_priv *priv = mgr->priv;
+	struct device *dev = priv->client.dev;
+	unsigned long timeout;
+	int ret;
+
+	timeout = usecs_to_jiffies(info->config_complete_timeout_us);
+
+	do {
+		reinit_completion(&priv->status_return_completion);
+
+		ret = s10_svc_send_msg(priv, COMMAND_RECONFIG_STATUS, NULL, 0);
+		if (ret)
+			break;
+
+		ret = wait_for_completion_interruptible_timeout(
+			&priv->status_return_completion, timeout);
+		if (!ret) {
+			dev_err(dev,
+				"timeout waiting for RECONFIG_COMPLETED\n");
+			ret = -ETIMEDOUT;
+			break;
+		}
+		if (ret < 0) {
+			dev_err(dev,
+				"error (%d) waiting for RECONFIG_COMPLETED\n",
+				ret);
+			break;
+		}
+		/* Not error or timeout, so ret is # of jiffies until timeout */
+		timeout = ret;
+		ret = 0;
+
+		if (test_and_clear_bit(SVC_STATUS_RECONFIG_COMPLETED,
+				       &priv->status))
+			break;
+
+		if (test_and_clear_bit(SVC_STATUS_RECONFIG_ERROR,
+				       &priv->status)) {
+			dev_err(dev, "ERROR - giving up - SVC_STATUS_RECONFIG_ERROR\n");
+			ret = -EFAULT;
+			break;
+		}
+	} while (1);
+
+	stratix10_svc_done(priv->chan);
+	return ret;
+}
+
+static enum fpga_mgr_states s10_ops_state(struct fpga_manager *mgr)
+{
+	return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static const struct fpga_manager_ops s10_ops = {
+	.state = s10_ops_state,
+	.write_init = s10_ops_write_init,
+	.write = s10_ops_write,
+	.write_complete = s10_ops_write_complete,
+};
+
+static int s10_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct s10_priv *priv;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->client.dev = dev;
+	priv->client.receive_cb = s10_receive_callback;
+	priv->client.priv = priv;
+
+	priv->chan = stratix10_svc_request_channel_byname(&priv->client,
+						SVC_CLIENT_FPGA);
+	if (IS_ERR(priv->chan)) {
+		dev_err(dev, "couldn't get service channel (%s)\n",
+			SVC_CLIENT_FPGA);
+		return PTR_ERR(priv->chan);
+	}
+
+	init_completion(&priv->status_return_completion);
+
+	ret = fpga_mgr_register(dev, "Stratix10 SOC FPGA Manager",
+				&s10_ops, priv);
+
+	if (ret)
+		stratix10_svc_free_channel(priv->chan);
+
+	return ret;
+}
+
+static int s10_remove(struct platform_device *pdev)
+{
+	struct fpga_manager *mgr = platform_get_drvdata(pdev);
+	struct s10_priv *priv = mgr->priv;
+
+	fpga_mgr_unregister(&pdev->dev);
+	stratix10_svc_free_channel(priv->chan);
+
+	return 0;
+}
+
+static const struct of_device_id s10_of_match[] = {
+	{ .compatible = "intel,stratix10-soc-fpga-mgr", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, s10_of_match);
+
+static struct platform_driver s10_driver = {
+	.probe = s10_probe,
+	.remove = s10_remove,
+	.driver = {
+		.name	= "Stratix10 SoC FPGA manager",
+		.of_match_table = of_match_ptr(s10_of_match),
+	},
+};
+
+static int __init s10_init(void)
+{
+	struct device_node *fw_np;
+	struct device_node *np;
+	int ret;
+
+	fw_np = of_find_node_by_name(NULL, "svc");
+	if (!fw_np)
+		return -ENODEV;
+
+	np = of_find_matching_node(fw_np, s10_of_match);
+	if (!np) {
+		of_node_put(fw_np);
+		return -ENODEV;
+	}
+
+	of_node_put(np);
+	ret = of_platform_populate(fw_np, s10_of_match, NULL, NULL);
+	of_node_put(fw_np);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&s10_driver);
+}
+
+static void __exit s10_exit(void)
+{
+	return platform_driver_unregister(&s10_driver);
+}
+
+module_init(s10_init);
+module_exit(s10_exit);
+
+MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
+MODULE_DESCRIPTION("Intel Stratix 10 SOC FPGA Manager");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

^ permalink raw reply related

* [PATCHv5 5/8] arm64: dts: stratix10: add fpga manager and region
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-fpga, linux-doc,
	yves.vandervennet, richard.gong, richard.gong
In-Reply-To: <1527179600-26441-1-git-send-email-richard.gong@linux.intel.com>

From: Alan Tull <atull@kernel.org>

Add the Stratix10 FPGA manager and a FPGA region to the
device tree.

Signed-off-by: Alan Tull <atull@kernel.org>
Signed-off-by: Richard Gong <richard.gong@intel.com>
---
v2: this patch is added in patch set version 2
v3: change to put fpga_mgr node under firmware/svc node
v4: s/fpga-mgr@0/fpga-mgr/ to remove unit_address
    add Richard's signed-off-by
v5: no change
---
 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index c257287..8f8f409 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -106,6 +106,14 @@
 		interrupt-parent = <&intc>;
 		ranges = <0 0 0 0xffffffff>;
 
+		base_fpga_region {
+			#address-cells = <0x1>;
+			#size-cells = <0x1>;
+
+			compatible = "fpga-region";
+			fpga-mgr = <&fpga_mgr>;
+		};
+
 		clkmgr: clock-controller@ffd10000 {
 			compatible = "intel,stratix10-clkmgr";
 			reg = <0xffd10000 0x1000>;
@@ -506,6 +514,10 @@
 				compatible = "intel,stratix10-svc";
 				method = "smc";
 				memory-region = <&service_reserved>;
+
+				fpga_mgr: fpga-mgr {
+					compatible = "intel,stratix10-soc-fpga-mgr";
+				};
 			};
 		};
 	};
-- 
2.7.4

^ permalink raw reply related

* [PATCHv5 4/8] dt-bindings: fpga: add Stratix10 SoC FPGA manager binding
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-fpga, linux-doc,
	yves.vandervennet, richard.gong, richard.gong
In-Reply-To: <1527179600-26441-1-git-send-email-richard.gong@linux.intel.com>

From: Alan Tull <atull@kernel.org>

Add a Device Tree binding for the Intel Stratix10 SoC FPGA manager.

Signed-off-by: Alan Tull <atull@kernel.org>
Signed-off-by: Richard Gong <richard.gong@intel.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v2: this patch is added in patch set version 2
v3: change to put fpga_mgr node under firmware/svc node
v4: s/fpga-mgr@0/fpga-mgr/ to remove unit_address
    add Richard's signed-off-by
v5: add Reviewed-by Rob Herring
---
 .../bindings/fpga/intel-stratix10-soc-fpga-mgr.txt      | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fpga/intel-stratix10-soc-fpga-mgr.txt

diff --git a/Documentation/devicetree/bindings/fpga/intel-stratix10-soc-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/intel-stratix10-soc-fpga-mgr.txt
new file mode 100644
index 0000000..6e03f79
--- /dev/null
+++ b/Documentation/devicetree/bindings/fpga/intel-stratix10-soc-fpga-mgr.txt
@@ -0,0 +1,17 @@
+Intel Stratix10 SoC FPGA Manager
+
+Required properties:
+The fpga_mgr node has the following mandatory property, must be located under
+firmware/svc node.
+
+- compatible : should contain "intel,stratix10-soc-fpga-mgr"
+
+Example:
+
+	firmware {
+		svc {
+			fpga_mgr: fpga-mgr {
+				compatible = "intel,stratix10-soc-fpga-mgr";
+			};
+		};
+	};
-- 
2.7.4

^ permalink raw reply related

* [PATCHv5 3/8] driver, misc: add Intel Stratix10 service layer driver
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-fpga, linux-doc,
	yves.vandervennet, richard.gong, richard.gong
In-Reply-To: <1527179600-26441-1-git-send-email-richard.gong@linux.intel.com>

From: Richard Gong <richard.gong@intel.com>

Some features of the Intel Stratix10 SoC require a level of privilege
higher than the kernel is granted. Such secure features include
FPGA programming. In terms of the ARMv8 architecture, the kernel runs
at Exception Level 1 (EL1), access to the features requires
Exception Level 3 (EL3).

The Intel Stratix10 SoC service layer provides an in kernel API for
drivers to request access to the secure features. The requests are queued
and processed one by one. ARM’s SMCCC is used to pass the execution
of the requests on to a secure monitor (EL3).

The header file stratix10-sve-client.h defines the interface between
service providers (FPGA manager is one of them) and service layer.

The header file stratix10-smc.h defines the secure monitor call (SMC)
message protocols used for service layer driver in normal world
(EL1) to communicate with secure monitor SW in secure monitor exception
level 3 (EL3).

Signed-off-by: Richard Gong <richard.gong@intel.com>
Signed-off-by: Alan Tull <atull@kernel.org>
---
v2: Remove intel-service subdirectory and intel-service.h, move
    intel-smc.h and intel-service.c to driver/misc subdirectory
    Correct SPDX markers
    Change service layer driver be 'default n'
    Remove global variables
    Add timeout for do..while() loop
    Add kernel-doc for the functions and structs, correct multiline comments
    Replace kfifo_in/kfifo_out with kfifo_in_spinlocked/kfifo_out_spinlocked
    rename struct intel_svc_data (at client header) to intel_svc_client_msg
    rename struct intel_svc_private_mem to intel_svc_data
    Other corrections/changes from Intel internal code reviews
v3: Change all exported functions with "intel_svc_" as the prefix
    Increase timeout values for claiming back submitted buffer(s)
    Rename struct intel_command_reconfig_payload to
    struct intel_svc_command_reconfig_payload
    Add pr_err() to provide the error return value
    Other corrections/changes
v4: s/intel/stratix10/ on some variables, structs, functions, and file names
    intel-service.c -> stratix10-svc.c
    intel-smc.h -> stratix10-smc.h
    intel-service-client.h -> stratix10-svc-client.h
    Remove non-kernel-doc formatting
v5: add a new API statix10_svc_done() which is called by service client
    when client request is completed or error occurs during request
    process. Which allows service layer to free its resources.
    remove dummy client from service layer client header and service
    layer source file.
    kernel-doc fixes
---
 drivers/misc/Kconfig                 |  12 +
 drivers/misc/Makefile                |   1 +
 drivers/misc/stratix10-smc.h         | 205 ++++++++
 drivers/misc/stratix10-svc.c         | 984 +++++++++++++++++++++++++++++++++++
 include/linux/stratix10-svc-client.h | 199 +++++++
 5 files changed, 1401 insertions(+)
 create mode 100644 drivers/misc/stratix10-smc.h
 create mode 100644 drivers/misc/stratix10-svc.c
 create mode 100644 include/linux/stratix10-svc-client.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 5d71300..5d5b648 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -138,6 +138,18 @@ config INTEL_MID_PTI
 	  an Intel Atom (non-netbook) mobile device containing a MIPI
 	  P1149.7 standard implementation.
 
+config STRATIX10_SERVICE
+	tristate "Stratix10 Service Layer"
+	depends on HAVE_ARM_SMCCC
+	default n
+	help
+	 Stratix10 service layer runs at privileged exception level, interfaces with
+	 the service providers (FPGA manager is one of them) and manages secure
+	 monitor call to communicate with secure monitor software at secure monitor
+	 exception level.
+
+	 Say Y here if you want Stratix10 service layer support.
+
 config SGI_IOC4
 	tristate "SGI IOC4 Base IO support"
 	depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 20be70c..99fed8b 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_AD525X_DPOT)	+= ad525x_dpot.o
 obj-$(CONFIG_AD525X_DPOT_I2C)	+= ad525x_dpot-i2c.o
 obj-$(CONFIG_AD525X_DPOT_SPI)	+= ad525x_dpot-spi.o
 obj-$(CONFIG_INTEL_MID_PTI)	+= pti.o
+obj-$(CONFIG_STRATIX10_SERVICE) += stratix10-svc.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
 obj-$(CONFIG_DUMMY_IRQ)		+= dummy-irq.o
diff --git a/drivers/misc/stratix10-smc.h b/drivers/misc/stratix10-smc.h
new file mode 100644
index 0000000..94615f4
--- /dev/null
+++ b/drivers/misc/stratix10-smc.h
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017-2018, Intel Corporation
+ */
+
+#ifndef __STRATIX10_SMC_H
+#define __STRATIX10_SMC_H
+
+#include <linux/arm-smccc.h>
+#include <linux/bitops.h>
+
+/**
+ * This file defines the Secure Monitor Call (SMC) message protocol used for
+ * service layer driver in normal world (EL1) to communicate with secure
+ * monitor software in Secure Monitor Exception Level 3 (EL3).
+ *
+ * This file is shared with secure firmware (FW) which is out of kernel tree.
+ *
+ * An ARM SMC instruction takes a function identifier and up to 6 64-bit
+ * register values as arguments, and can return up to 4 64-bit register
+ * value. The operation of the secure monitor is determined by the parameter
+ * values passed in through registers.
+ *
+ * EL1 and EL3 communicates pointer as physical address rather than the
+ * virtual address.
+ *
+ * Functions specified by ARM SMC Calling convention:
+ *
+ * FAST call executes atomic operations, returns when the requested operation
+ * has completed.
+ * STD call starts a operation which can be preempted by a non-secure
+ * interrupt. The call can return before the requested operation has
+ * completed.
+ *
+ * a0..a7 is used as register names in the descriptions below, on arm32
+ * that translates to r0..r7 and on arm64 to w0..w7.
+ */
+
+/**
+ * @func_num: function ID
+ */
+#define INTEL_SIP_SMC_STD_CALL_VAL(func_num) \
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_64, \
+	ARM_SMCCC_OWNER_SIP, (func_num))
+
+#define INTEL_SIP_SMC_FAST_CALL_VAL(func_num) \
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \
+	ARM_SMCCC_OWNER_SIP, (func_num))
+
+/**
+ * Return values in INTEL_SIP_SMC_* call
+ *
+ * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION:
+ * Secure monitor software doesn't recognize the request.
+ *
+ * INTEL_SIP_SMC_STATUS_OK:
+ * FPGA configuration completed successfully,
+ * In case of FPGA configuration write operation, it means secure monitor
+ * software can accept the next chunk of FPGA configuration data.
+ *
+ * INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY:
+ * In case of FPGA configuration write operation, it means secure monitor
+ * software is still processing previous data & can't accept the next chunk
+ * of data. Service driver needs to issue
+ * INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE call to query the
+ * completed block(s).
+ *
+ * INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR:
+ * There is error during the FPGA configuration process.
+ */
+#define INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION		0xFFFFFFFF
+#define INTEL_SIP_SMC_STATUS_OK				0x0
+#define INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY		0x1
+#define INTEL_SIP_SMC_FPGA_CONFIG_STATUS_REJECTED       0x2
+#define INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR		0x4
+
+/**
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_START
+ *
+ * Sync call used by service driver at EL1 to request the FPGA in EL3 to
+ * be prepare to receive a new configuration.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_START.
+ * a1: flag for full or partial configuration. 0 for full and 1 for partial
+ * configuration.
+ * a2-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, or INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START 1
+#define INTEL_SIP_SMC_FPGA_CONFIG_START \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_START)
+
+/**
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_WRITE
+ *
+ * Async call used by service driver at EL1 to provide FPGA configuration data
+ * to secure world.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_WRITE.
+ * a1: 64bit physical address of the configuration data memory block
+ * a2: Size of configuration data block.
+ * a3-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY or
+ * INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
+ * a1: 64bit physical address of 1st completed memory block if any completed
+ * block, otherwise zero value.
+ * a2: 64bit physical address of 2nd completed memory block if any completed
+ * block, otherwise zero value.
+ * a3: 64bit physical address of 3rd completed memory block if any completed
+ * block, otherwise zero value.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE 2
+#define INTEL_SIP_SMC_FPGA_CONFIG_WRITE \
+	INTEL_SIP_SMC_STD_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_WRITE)
+
+/**
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE
+ *
+ * Sync call used by service driver at EL1 to track the completed write
+ * transactions. This request is called after INTEL_SIP_SMC_FPGA_CONFIG_WRITE
+ * call returns INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY or
+ * INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
+ * a1: 64bit physical address of 1st completed memory block.
+ * a2: 64bit physical address of 2nd completed memory block if
+ * any completed block, otherwise zero value.
+ * a3: 64bit physical address of 3rd completed memory block if
+ * any completed block, otherwise zero value.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE 3
+#define INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE \
+INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE)
+
+/**
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_ISDONE
+ *
+ * Sync call used by service driver at EL1 to inform secure world that all
+ * data are sent, to check whether or not the secure world had completed
+ * the FPGA configuration process.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_ISDONE.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY or
+ * INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE 4
+#define INTEL_SIP_SMC_FPGA_CONFIG_ISDONE \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_ISDONE)
+
+/**
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM
+ *
+ * Sync call used by service driver at EL1 to query the physical address of
+ * memory block reserved by secure monitor software.
+ *
+ * Call register usage:
+ * a0:INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
+ * a1: start of physical address of reserved memory block.
+ * a2: size of reserved memory block.
+ * a3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM 5
+#define INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_GET_MEM)
+
+/**
+ * Request INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK
+ *
+ * For SMC loop-back mode only, used for internal integration, debugging
+ * or troubleshooting.
+ *
+ * Call register usage:
+ * a0: INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK.
+ * a1-7: not used.
+ *
+ * Return status:
+ * a0: INTEL_SIP_SMC_STATUS_OK or INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR.
+ * a1-3: not used.
+ */
+#define INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK 6
+#define INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK \
+	INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_LOOPBACK)
+
+#endif
diff --git a/drivers/misc/stratix10-svc.c b/drivers/misc/stratix10-svc.c
new file mode 100644
index 0000000..5d07994
--- /dev/null
+++ b/drivers/misc/stratix10-svc.c
@@ -0,0 +1,984 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017-2018, Intel Corporation
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/genalloc.h>
+#include <linux/stratix10-svc-client.h>
+#include <linux/io.h>
+#include <linux/kfifo.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include "stratix10-smc.h"
+
+/**
+ * SVC_NUM_DATA_IN_FIFO - number of struct stratix10_svc_data in the FIFO
+ *
+ * SVC_NUM_CHANNEL - number of channel supported by service layer driver
+ *
+ * FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS - claim back the submitted buffer(s)
+ * from the secure world for FPGA manager to reuse, or to free the buffer(s)
+ * when all bit-stream data had be send.
+ *
+ * FPGA_CONFIG_STATUS_TIMEOUT_SEC - poll the FPGA configuration status,
+ * service layer will return error to FPGA manager when timeout occurs,
+ * timeout is set to 30 seconds (30 * 1000) at Intel Stratix10 SoC.
+ */
+#define SVC_NUM_DATA_IN_FIFO			32
+#define SVC_NUM_CHANNEL				1
+#define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS	200
+#define FPGA_CONFIG_STATUS_TIMEOUT_SEC		30
+
+typedef void (svc_invoke_fn)(unsigned long, unsigned long, unsigned long,
+			     unsigned long, unsigned long, unsigned long,
+			     unsigned long, unsigned long,
+			     struct arm_smccc_res *);
+struct stratix10_svc_chan;
+
+/**
+ * struct stratix10_svc_sh_memory - service shared memory structure
+ * @sync_complete: state for a completion
+ * @addr: physical address of shared memory block
+ * @size: size of shared memory block
+ * @invoke_fn: function to issue secure monitor or hypervisor call
+ *
+ * This struct is used to save physical address and size of shared memory
+ * block. The shared memory blocked is allocated by secure monitor software
+ * at secure world.
+ *
+ * Service layer driver uses the physical address and size to create a memory
+ * pool, then allocates data buffer from that memory pool for service client.
+ */
+struct stratix10_svc_sh_memory {
+	struct completion sync_complete;
+	unsigned long addr;
+	unsigned long size;
+	svc_invoke_fn *invoke_fn;
+};
+
+/**
+ * struct stratix10_svc_data_mem - service memory structure
+ * @vaddr: virtual address
+ * @paddr: physical address
+ * @size: size of memory
+ * @node: link list head node
+ *
+ * This struct is used in a list that keeps track of buffers which have
+ * been allocated or freed from the memory pool. Service layer driver also
+ * uses this struct to transfer physical address to virtual address.
+ */
+struct stratix10_svc_data_mem {
+	void *vaddr;
+	phys_addr_t paddr;
+	size_t size;
+	struct list_head node;
+};
+
+/**
+ * struct stratix10_svc_data - service data structure
+ * @chan: service channel
+ * @paddr: playload physical address
+ * @size: playload size
+ * @command: service command requested by client
+ *
+ * This struct is used in service FIFO for inter-process communication.
+ */
+struct stratix10_svc_data {
+	struct stratix10_svc_chan *chan;
+	phys_addr_t paddr;
+	size_t size;
+	u32 command;
+};
+
+/**
+ * struct stratix10_svc_controller - service controller
+ * @dev: device
+ * @chans: array of service channels
+ * @num_chans: number of channels in 'chans' array
+ * @num_active_client: number of active service client
+ * @node: list management
+ * @genpool: memory pool pointing to the memory region
+ * @task: pointer to the thread task which handles SMC or HVC call
+ * @svc_fifo: a queue for storing service message data
+ * @complete_status: state for completion
+ * @svc_fifo_lock: protect access to service message data queue
+ * @invoke_fn: function to issue secure monitor call or hypervisor call
+ *
+ * This struct is used to create communication channels for service clients, to
+ * handle secure monitor or hypervisor call.
+ */
+struct stratix10_svc_controller {
+	struct device *dev;
+	struct stratix10_svc_chan *chans;
+	int num_chans;
+	int num_active_client;
+	struct list_head node;
+	struct gen_pool *genpool;
+	struct task_struct *task;
+	struct kfifo svc_fifo;
+	struct completion complete_status;
+	spinlock_t svc_fifo_lock;
+	svc_invoke_fn *invoke_fn;
+};
+
+/**
+ * struct stratix10_svc_chan - service communication channel
+ * @ctrl: pointer to service controller which is the provider of this channel
+ * @scl: pointer to service client which owns the channel
+ * @name: service client name associated with the channel
+ * @lock: protect access to the channel
+ *
+ * This struct is used by service client to communicate with service layer, each
+ * service client has its own channel created by service controller.
+ */
+struct stratix10_svc_chan {
+	struct stratix10_svc_controller *ctrl;
+	struct stratix10_svc_client *scl;
+	char *name;
+	spinlock_t lock;
+};
+
+static LIST_HEAD(svc_ctrl);
+static LIST_HEAD(svc_data_mem);
+
+/**
+ * svc_pa_to_va() - translate physical address to virtual address
+ * @addr: to be translated physical address
+ *
+ * Return: valid virtual address or NULL if the provided physical
+ * address doesn't exist.
+ */
+static void *svc_pa_to_va(unsigned long addr)
+{
+	struct stratix10_svc_data_mem *pmem;
+
+	pr_debug("claim back P-addr=0x%016x\n", (unsigned int)addr);
+	list_for_each_entry(pmem, &svc_data_mem, node) {
+		if (pmem->paddr == addr)
+			return pmem->vaddr;
+	}
+
+	/* physical address is not found */
+	return NULL;
+}
+
+/**
+ * svc_thread_cmd_data_claim() - claim back buffer from the secure world
+ * @ctrl: pointer to service layer controller
+ * @p_data: pointer to service data structure
+ * @cb_data: pointer to callback data structure to service client
+ *
+ * Claim back the submitted buffers from the secure world and pass buffer
+ * back to service client (FPGA manager, etc) for reuse.
+ */
+static void svc_thread_cmd_data_claim(struct stratix10_svc_controller *ctrl,
+				      struct stratix10_svc_data *p_data,
+				      struct stratix10_svc_cb_data *cb_data)
+{
+	struct arm_smccc_res res;
+	unsigned long timeout;
+
+	reinit_completion(&ctrl->complete_status);
+	timeout = msecs_to_jiffies(FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS);
+
+	pr_debug("%s: claim back the submitted buffer\n", __func__);
+	do {
+		ctrl->invoke_fn(INTEL_SIP_SMC_FPGA_CONFIG_COMPLETED_WRITE,
+				0, 0, 0, 0, 0, 0, 0, &res);
+
+		if (res.a0 == INTEL_SIP_SMC_STATUS_OK) {
+			if (!res.a1) {
+				complete(&ctrl->complete_status);
+				break;
+			}
+			cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_DONE);
+			cb_data->kaddr1 = svc_pa_to_va(res.a1);
+			cb_data->kaddr2 = (res.a2) ?
+					  svc_pa_to_va(res.a2) : NULL;
+			cb_data->kaddr3 = (res.a3) ?
+					  svc_pa_to_va(res.a3) : NULL;
+			p_data->chan->scl->receive_cb(p_data->chan->scl,
+						      cb_data);
+		} else {
+			pr_debug("%s: secure world busy, polling again\n",
+				 __func__);
+		}
+	} while (res.a0 == INTEL_SIP_SMC_STATUS_OK ||
+		 res.a0 == INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY ||
+		 wait_for_completion_timeout(&ctrl->complete_status, timeout));
+}
+
+/**
+ * svc_thread_cmd_config_status() - check configuration status
+ * @ctrl: pointer to service layer controller
+ * @p_data: pointer to service data structure
+ * @cb_data: pointer to callback data structure to service client
+ *
+ * Check whether the secure firmware at secure world has finished the FPGA
+ * configuration, and then inform FPGA manager the configuration status.
+ */
+static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl,
+					 struct stratix10_svc_data *p_data,
+					 struct stratix10_svc_cb_data *cb_data)
+{
+	struct arm_smccc_res res;
+	int count_in_sec;
+
+	cb_data->kaddr1 = NULL;
+	cb_data->kaddr2 = NULL;
+	cb_data->kaddr3 = NULL;
+	cb_data->status = BIT(SVC_STATUS_RECONFIG_ERROR);
+
+	pr_debug("%s: polling config status\n", __func__);
+
+	count_in_sec = FPGA_CONFIG_STATUS_TIMEOUT_SEC;
+	while (count_in_sec) {
+		ctrl->invoke_fn(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE,
+				0, 0, 0, 0, 0, 0, 0, &res);
+		if ((res.a0 == INTEL_SIP_SMC_STATUS_OK) ||
+		    (res.a0 == INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR))
+			break;
+
+		/*
+		 * configuration is still in progress, wait one second then
+		 * poll again
+		 */
+		msleep(1000);
+		count_in_sec--;
+	};
+
+	if (res.a0 == INTEL_SIP_SMC_STATUS_OK && count_in_sec)
+		cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED);
+
+	p_data->chan->scl->receive_cb(p_data->chan->scl, cb_data);
+}
+
+/**
+ * svc_thread_recv_status_ok() - handle the successful status
+ * @p_data: pointer to service data structure
+ * @cb_data: pointer to callback data structure to service client
+ * @res: result from SMC or HVC call
+ *
+ * Send back the correspond status to the service client (FPGA manager etc).
+ */
+static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data,
+				      struct stratix10_svc_cb_data *cb_data,
+				      struct arm_smccc_res res)
+{
+	cb_data->kaddr1 = NULL;
+	cb_data->kaddr2 = NULL;
+	cb_data->kaddr3 = NULL;
+
+	switch (p_data->command) {
+	case COMMAND_RECONFIG:
+		cb_data->status = BIT(SVC_STATUS_RECONFIG_REQUEST_OK);
+		break;
+	case COMMAND_RECONFIG_DATA_SUBMIT:
+		cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED);
+		break;
+	case COMMAND_NOOP:
+		cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED);
+		cb_data->kaddr1 = svc_pa_to_va(res.a1);
+		break;
+	case COMMAND_RECONFIG_STATUS:
+		cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED);
+		break;
+	default:
+		break;
+	}
+
+	pr_debug("%s: call receive_cb\n", __func__);
+	p_data->chan->scl->receive_cb(p_data->chan->scl, cb_data);
+}
+
+/**
+ * svc_normal_to_secure_thread() - the function to run in the kthread
+ * @data: data pointer for kthread function
+ *
+ * Service layer driver creates stratix10_svc_smc_hvc_call kthread on CPU
+ * node 0, its function stratix10_svc_secure_call_thread is used to handle
+ * SMC or HVC calls between kernel driver and secure monitor software.
+ *
+ * Return: 0 for success or -ENOMEM on error.
+ */
+static int svc_normal_to_secure_thread(void *data)
+{
+	struct stratix10_svc_controller
+			*ctrl = (struct stratix10_svc_controller *)data;
+	struct stratix10_svc_data *pdata;
+	struct stratix10_svc_cb_data *cbdata;
+	struct arm_smccc_res res;
+	unsigned long a0, a1, a2;
+	int ret_fifo = 0;
+
+	pdata =  kmalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	cbdata = kmalloc(sizeof(*cbdata), GFP_KERNEL);
+	if (!cbdata)
+		return -ENOMEM;
+
+	/* default set, to remove build warning */
+	a0 = INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK;
+	a1 = 0;
+	a2 = 0;
+
+	pr_debug("smc_hvc_shm_thread is running\n");
+
+	while (!kthread_should_stop()) {
+		ret_fifo = kfifo_out_spinlocked(&ctrl->svc_fifo,
+						pdata, sizeof(*pdata),
+						&ctrl->svc_fifo_lock);
+
+		if (!ret_fifo)
+			continue;
+
+		pr_debug("get from FIFO pa=0x%016x, command=%u, size=%u\n",
+			 (unsigned int)pdata->paddr, pdata->command,
+			 (unsigned int)pdata->size);
+
+		switch (pdata->command) {
+		case COMMAND_RECONFIG_DATA_CLAIM:
+			svc_thread_cmd_data_claim(ctrl, pdata, cbdata);
+			continue;
+		case COMMAND_RECONFIG:
+			a0 = INTEL_SIP_SMC_FPGA_CONFIG_START;
+			a1 = 0;
+			a2 = 0;
+			break;
+		case COMMAND_RECONFIG_DATA_SUBMIT:
+			a0 = INTEL_SIP_SMC_FPGA_CONFIG_WRITE;
+			a1 = (unsigned long)pdata->paddr;
+			a2 = (unsigned long)pdata->size;
+			break;
+		case COMMAND_RECONFIG_STATUS:
+			a0 = INTEL_SIP_SMC_FPGA_CONFIG_ISDONE;
+			a1 = 0;
+			a2 = 0;
+			break;
+		default:
+			/* it shouldn't happen */
+			break;
+		}
+		pr_debug("%s: before SMC call -- a0=0x%016x a1=0x%016x",
+			 __func__, (unsigned int)a0, (unsigned int)a1);
+		pr_debug(" a2=0x%016x\n", (unsigned int)a2);
+
+		ctrl->invoke_fn(a0, a1, a2, 0, 0, 0, 0, 0, &res);
+
+		pr_debug("%s: after SMC call -- res.a0=0x%016x",
+			 __func__, (unsigned int)res.a0);
+		pr_debug(" res.a1=0x%016x, res.a2=0x%016x",
+			 (unsigned int)res.a1, (unsigned int)res.a2);
+		pr_debug(" res.a3=0x%016x\n", (unsigned int)res.a3);
+
+		switch (res.a0) {
+		case INTEL_SIP_SMC_STATUS_OK:
+			svc_thread_recv_status_ok(pdata, cbdata, res);
+			break;
+		case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY:
+			switch (pdata->command) {
+			case COMMAND_RECONFIG_DATA_SUBMIT:
+				svc_thread_cmd_data_claim(ctrl,
+							  pdata, cbdata);
+				break;
+			case COMMAND_RECONFIG_STATUS:
+				svc_thread_cmd_config_status(ctrl,
+							     pdata, cbdata);
+				break;
+			default:
+				break;
+			}
+			break;
+		case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_REJECTED:
+			pr_debug("%s: STATUS_REJECTED\n", __func__);
+			break;
+		case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR:
+			pr_err("%s: STATUS_ERROR\n", __func__);
+			cbdata->status = BIT(SVC_STATUS_RECONFIG_ERROR);
+			cbdata->kaddr1 = NULL;
+			cbdata->kaddr2 = NULL;
+			cbdata->kaddr3 = NULL;
+			pdata->chan->scl->receive_cb(pdata->chan->scl, cbdata);
+			break;
+		default:
+			break;
+		}
+	};
+
+	kfree(cbdata);
+	kfree(pdata);
+
+	return 0;
+}
+
+/**
+ * svc_normal_to_secure_shm_thread() - the function to run in the kthread
+ * @data: data pointer for kthread function
+ *
+ * Service layer driver creates stratix10_svc_smc_hvc_shm kthread on CPU
+ * node 0, its function stratix10_svc_secure_shm_thread is used to query the
+ * physical address of memory block reserved by secure monitor software at
+ * secure world.
+ *
+ * svc_normal_to_secure_shm_thread() calls do_exit() directly since it is a
+ * standlone thread for which no one will call kthread_stop() or return when
+ * 'kthread_should_stop()' is true.
+ */
+static int svc_normal_to_secure_shm_thread(void *data)
+{
+	struct stratix10_svc_sh_memory
+			*sh_mem = (struct stratix10_svc_sh_memory *)data;
+	struct arm_smccc_res res;
+
+	/* SMC or HVC call to get shared memory info from secure world */
+	sh_mem->invoke_fn(INTEL_SIP_SMC_FPGA_CONFIG_GET_MEM,
+			  0, 0, 0, 0, 0, 0, 0, &res);
+	if (res.a0 == INTEL_SIP_SMC_STATUS_OK) {
+		sh_mem->addr = res.a1;
+		sh_mem->size = res.a2;
+	} else {
+		pr_err("%s: after SMC call -- res.a0=0x%016x",  __func__,
+		       (unsigned int)res.a0);
+		sh_mem->addr = 0;
+		sh_mem->size = 0;
+	}
+
+	complete(&sh_mem->sync_complete);
+	do_exit(0);
+}
+
+/**
+ * svc_get_sh_memory() - get memory block reserved by secure monitor SW
+ * @pdev: pointer to service layer device
+ * @sh_memory: pointer to service shared memory structure
+ *
+ * Return: zero for successfully getting the physical address of memory block
+ * reserved by secure monitor software, or negative value on error.
+ */
+static int svc_get_sh_memory(struct platform_device *pdev,
+				    struct stratix10_svc_sh_memory *sh_memory)
+{
+	struct device *dev = &pdev->dev;
+	struct task_struct *sh_memory_task;
+
+	init_completion(&sh_memory->sync_complete);
+
+	/* smc or hvc call happens on cpu 0 bound kthread */
+	sh_memory_task = kthread_create_on_cpu(svc_normal_to_secure_shm_thread,
+					       (void *)sh_memory,
+						0, "svc_smc_hvc_shm_thread");
+	if (IS_ERR(sh_memory_task)) {
+		dev_err(dev, "fail to create stratix10_svc_smc_shm_thread\n");
+		return -EINVAL;
+	}
+
+	wake_up_process(sh_memory_task);
+
+	if (!wait_for_completion_timeout(&sh_memory->sync_complete, 10 * HZ)) {
+		dev_err(dev,
+			"timeout to get sh-memory paras from secure world\n");
+		return -ETIMEDOUT;
+	}
+
+	if (!sh_memory->addr || !sh_memory->size) {
+		dev_err(dev,
+			"fails to get shared memory info from secure world\n");
+		return -ENOMEM;
+	}
+
+	dev_dbg(dev, "SM software provides paddr: 0x%016x, size: 0x%08x\n",
+		(unsigned int)sh_memory->addr,
+		(unsigned int)sh_memory->size);
+
+	return 0;
+}
+
+/**
+ * svc_create_memory_pool() - create a memory pool from reserved memory block
+ * @pdev: pointer to service layer device
+ * @sh_memory: pointer to service shared memory structure
+ *
+ * Return: pool allocated from reserved memory block or ERR_PTR() on error.
+ */
+static struct gen_pool *
+svc_create_memory_pool(struct platform_device *pdev,
+		       struct stratix10_svc_sh_memory *sh_memory)
+{
+	struct device *dev = &pdev->dev;
+	struct gen_pool *genpool;
+	unsigned long vaddr;
+	phys_addr_t paddr;
+	size_t size;
+	phys_addr_t begin;
+	phys_addr_t end;
+	void *va;
+	size_t page_mask = PAGE_SIZE - 1;
+	int min_alloc_order = 3;
+	int ret;
+
+	begin = roundup(sh_memory->addr, PAGE_SIZE);
+	end = rounddown(sh_memory->addr + sh_memory->size, PAGE_SIZE);
+	paddr = begin;
+	size = end - begin;
+	va = memremap(paddr, size, MEMREMAP_WC);
+	if (!va) {
+		dev_err(dev, "fail to remap shared memory\n");
+		return ERR_PTR(-EINVAL);
+	}
+	vaddr = (unsigned long)va;
+	dev_dbg(dev,
+		"reserved memory vaddr: %p, paddr: 0x%16x size: 0x%8x\n",
+		va, (unsigned int)paddr, (unsigned int)size);
+	if ((vaddr & page_mask) || (paddr & page_mask) ||
+	    (size & page_mask)) {
+		dev_err(dev, "page is not aligned\n");
+		return ERR_PTR(-EINVAL);
+	}
+	genpool = gen_pool_create(min_alloc_order, -1);
+	if (!genpool) {
+		dev_err(dev, "fail to create genpool\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	gen_pool_set_algo(genpool, gen_pool_best_fit, NULL);
+	ret = gen_pool_add_virt(genpool, vaddr, paddr, size, -1);
+	if (ret) {
+		dev_err(dev, "fail to add memory chunk to the pool\n");
+		gen_pool_destroy(genpool);
+		return ERR_PTR(ret);
+	}
+
+	return genpool;
+}
+
+/**
+ * svc_smccc_smc() - secure monitor call between normal and secure world
+ * @a0: argument passed in registers 0
+ * @a1: argument passed in registers 1
+ * @a2: argument passed in registers 2
+ * @a3: argument passed in registers 3
+ * @a4: argument passed in registers 4
+ * @a5: argument passed in registers 5
+ * @a6: argument passed in registers 6
+ * @a7: argument passed in registers 7
+ * @res: result values from register 0 to 3
+ */
+static void svc_smccc_smc(unsigned long a0, unsigned long a1,
+			  unsigned long a2, unsigned long a3,
+			  unsigned long a4, unsigned long a5,
+			  unsigned long a6, unsigned long a7,
+			  struct arm_smccc_res *res)
+{
+	arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+/**
+ * svc_smccc_hvc() - hypervisor call between normal and secure world
+ * @a0: argument passed in registers 0
+ * @a1: argument passed in registers 1
+ * @a2: argument passed in registers 2
+ * @a3: argument passed in registers 3
+ * @a4: argument passed in registers 4
+ * @a5: argument passed in registers 5
+ * @a6: argument passed in registers 6
+ * @a7: argument passed in registers 7
+ * @res: result values from register 0 to 3
+ */
+static void svc_smccc_hvc(unsigned long a0, unsigned long a1,
+			  unsigned long a2, unsigned long a3,
+			  unsigned long a4, unsigned long a5,
+			  unsigned long a6, unsigned long a7,
+			  struct arm_smccc_res *res)
+{
+	arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+/**
+ * get_invoke_func() - invoke SMC or HVC call
+ * @dev: pointer to device
+ *
+ * Return: function pointer to svc_smccc_smc or svc_smccc_hvc.
+ */
+static svc_invoke_fn *get_invoke_func(struct device *dev)
+{
+	const char *method;
+
+	if (of_property_read_string(dev->of_node, "method", &method)) {
+		dev_warn(dev, "missing \"method\" property\n");
+		return ERR_PTR(-ENXIO);
+	}
+
+	if (!strcmp(method, "smc"))
+		return svc_smccc_smc;
+	if (!strcmp(method, "hvc"))
+		return svc_smccc_hvc;
+
+	dev_warn(dev, "invalid \"method\" property: %s\n", method);
+
+	return ERR_PTR(-EINVAL);
+}
+
+/**
+ * stratix10_svc_request_channel_byname() - request a service channel
+ * @client: pointer to service client
+ * @name: service client name
+ *
+ * This function is used by service client to request a service channel.
+ *
+ * Return: a pointer to channel assigned to the client on success,
+ * or ERR_PTR() on error.
+ */
+struct stratix10_svc_chan *stratix10_svc_request_channel_byname(
+	struct stratix10_svc_client *client, const char *name)
+{
+	struct device *dev = client->dev;
+	struct stratix10_svc_controller *controller;
+	struct stratix10_svc_chan *chan;
+	unsigned long flag;
+	int i;
+
+	chan = ERR_PTR(-EPROBE_DEFER);
+	if (list_empty(&svc_ctrl))
+		return ERR_PTR(-ENODEV);
+
+	controller = list_first_entry(&svc_ctrl,
+				      struct stratix10_svc_controller, node);
+	for (i = 0; i < SVC_NUM_CHANNEL; i++) {
+		if (!strcmp(controller->chans[i].name, name)) {
+			chan = &controller->chans[i];
+			break;
+		}
+	}
+
+	if (chan->scl || !try_module_get(controller->dev->driver->owner)) {
+		dev_dbg(dev, "%s: svc not free\n", __func__);
+		return ERR_PTR(-EBUSY);
+	}
+
+	spin_lock_irqsave(&chan->lock, flag);
+	chan->scl = client;
+	chan->ctrl->num_active_client++;
+	spin_unlock_irqrestore(&chan->lock, flag);
+
+	return chan;
+}
+EXPORT_SYMBOL_GPL(stratix10_svc_request_channel_byname);
+
+/**
+ * stratix10_svc_free_channel() - free service channel
+ * @chan: service channel to be freed
+ *
+ * This function is used by service client to free a service channel.
+ */
+void stratix10_svc_free_channel(struct stratix10_svc_chan *chan)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&chan->lock, flag);
+	chan->scl = NULL;
+	chan->ctrl->num_active_client--;
+	module_put(chan->ctrl->dev->driver->owner);
+	spin_unlock_irqrestore(&chan->lock, flag);
+}
+EXPORT_SYMBOL_GPL(stratix10_svc_free_channel);
+
+/**
+ * stratix10_svc_send() - send a message data to the remote
+ * @chan: service channel assigned to the client
+ * @msg: message data to be sent, in the format of
+ * "struct stratix10_svc_client_msg"
+ *
+ * This function is used by service client to add a message to the service
+ * layer driver's queue for being sent to the secure world.
+ *
+ * Return: 0 for success, -ENOMEM or -ENOBUFS on error.
+ */
+int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg)
+{
+	struct stratix10_svc_client_msg
+		*p_msg = (struct stratix10_svc_client_msg *)msg;
+	struct stratix10_svc_data_mem *p_mem;
+	struct stratix10_svc_data *p_data;
+	int ret = 0;
+
+	p_data = kmalloc(sizeof(*p_data), GFP_KERNEL);
+	if (!p_data)
+		return -ENOMEM;
+
+	/* first client will create kernel thread */
+	if (!chan->ctrl->task) {
+		chan->ctrl->task =
+			kthread_create_on_cpu(svc_normal_to_secure_thread,
+					      (void *)chan->ctrl, 0,
+					      "svc_smc_hvc_thread");
+			if (IS_ERR(chan->ctrl->task)) {
+				dev_err(chan->ctrl->dev,
+					"fails to create svc_smc_hvc_thread\n");
+				return -EINVAL;
+			}
+		wake_up_process(chan->ctrl->task);
+	}
+
+	pr_debug("%s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__,
+		 p_msg->payload, p_msg->command,
+		 (unsigned int)p_msg->payload_length);
+
+	p_data->paddr = 0;
+	list_for_each_entry(p_mem, &svc_data_mem, node) {
+		if (p_mem->vaddr == p_msg->payload) {
+			p_data->paddr = p_mem->paddr;
+			break;
+		}
+	}
+
+	p_data->command = p_msg->command;
+	p_data->size = p_msg->payload_length;
+	p_data->chan = chan;
+	pr_debug("%s: put to FIFO pa=0x%016x, cmd=%x, size=%u\n", __func__,
+	       (unsigned int)p_data->paddr, p_data->command,
+	       (unsigned int)p_data->size);
+	ret = kfifo_in_spinlocked(&chan->ctrl->svc_fifo, p_data,
+				  sizeof(*p_data),
+				  &chan->ctrl->svc_fifo_lock);
+
+	kfree(p_data);
+
+	if (!ret)
+		return -ENOBUFS;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(stratix10_svc_send);
+
+/**
+ * stratix10_svc_done() - complete service request transactions
+ * @chan: service channel assigned to the client
+ *
+ * This function should be called when client has finished its request
+ * or there is an error in the request process. It allows the service layer
+ * to stop the running thread to have maximize savings in kernel resources.
+ */
+void stratix10_svc_done(struct stratix10_svc_chan *chan)
+{
+	/* stop thread when thread is running AND only one active client */
+	if (chan->ctrl->task && chan->ctrl->num_active_client <= 1) {
+		pr_debug("svc_smc_hvc_shm_thread is stopped\n");
+		kthread_stop(chan->ctrl->task);
+		chan->ctrl->task = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(stratix10_svc_done);
+
+/**
+ * stratix10_svc_allocate_memory() - allocate memory
+ * @chan: service channel assigned to the client
+ * @size: memory size requested by a specific service client
+ *
+ * Service layer allocates the requested number of bytes buffer from the
+ * memory pool, service client uses this function to get allocated buffers.
+ *
+ * Return: address of allocated memory on success, or ERR_PTR() on error.
+ */
+void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan,
+				    size_t size)
+{
+	struct stratix10_svc_data_mem *pmem;
+	unsigned long va;
+	phys_addr_t pa;
+	struct gen_pool *genpool = chan->ctrl->genpool;
+	size_t s = roundup(size, 1 << genpool->min_alloc_order);
+
+	pmem = devm_kzalloc(chan->ctrl->dev, sizeof(*pmem), GFP_KERNEL);
+	if (!pmem)
+		return ERR_PTR(-ENOMEM);
+
+	va = gen_pool_alloc(genpool, s);
+	if (!va)
+		return ERR_PTR(-ENOMEM);
+
+	memset((void *)va, 0, s);
+	pa = gen_pool_virt_to_phys(genpool, va);
+
+	pmem->vaddr = (void *)va;
+	pmem->paddr = pa;
+	pmem->size = s;
+	list_add_tail(&pmem->node, &svc_data_mem);
+	pr_debug("%s: va=%p, pa=0x%016x\n", __func__,
+		 pmem->vaddr, (unsigned int)pmem->paddr);
+
+	return (void *)va;
+}
+EXPORT_SYMBOL_GPL(stratix10_svc_allocate_memory);
+
+/**
+ * stratix10_svc_free_memory() - free allocated memory
+ * @chan: service channel assigned to the client
+ * @kaddr: memory to be freed
+ *
+ * This function is used by service client to free allocated buffers.
+ */
+void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
+{
+	struct stratix10_svc_data_mem *pmem;
+	size_t size = 0;
+
+	list_for_each_entry(pmem, &svc_data_mem, node)
+		if (pmem->vaddr == kaddr) {
+			size = pmem->size;
+			break;
+		}
+
+	gen_pool_free(chan->ctrl->genpool, (unsigned long)kaddr, size);
+	pmem->vaddr = NULL;
+	list_del(&pmem->node);
+}
+EXPORT_SYMBOL_GPL(stratix10_svc_free_memory);
+
+static const struct of_device_id stratix10_svc_drv_match[] = {
+	{.compatible = "intel,stratix10-svc"},
+	{},
+};
+
+static int stratix10_svc_drv_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct stratix10_svc_controller *controller;
+	struct stratix10_svc_chan *chans;
+	struct gen_pool *genpool;
+	struct stratix10_svc_sh_memory *sh_memory;
+	svc_invoke_fn *invoke_fn;
+	size_t fifo_size;
+	int ret;
+
+	/* get SMC or HVC function */
+	invoke_fn = get_invoke_func(dev);
+	if (IS_ERR(invoke_fn))
+		return -EINVAL;
+
+	sh_memory = devm_kzalloc(dev, sizeof(*sh_memory), GFP_KERNEL);
+	if (!sh_memory)
+		return -ENOMEM;
+
+	sh_memory->invoke_fn = invoke_fn;
+	ret = svc_get_sh_memory(pdev, sh_memory);
+	if (ret)
+		return ret;
+
+	genpool = svc_create_memory_pool(pdev, sh_memory);
+	if (!genpool)
+		return -ENOMEM;
+
+	/* allocate service controller and supporting channel */
+	controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
+	if (!controller)
+		return -ENOMEM;
+
+	chans = devm_kmalloc_array(dev, SVC_NUM_CHANNEL,
+				   sizeof(*chans), GFP_KERNEL | __GFP_ZERO);
+	if (!chans)
+		return -ENOMEM;
+
+	controller->dev = dev;
+	controller->num_chans = SVC_NUM_CHANNEL;
+	controller->num_active_client = 0;
+	controller->chans = chans;
+	controller->genpool = genpool;
+	controller->task = NULL;
+	controller->invoke_fn = invoke_fn;
+	init_completion(&controller->complete_status);
+
+	fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;
+	ret = kfifo_alloc(&controller->svc_fifo, fifo_size, GFP_KERNEL);
+	if (ret) {
+		dev_err(dev, "fails to allocate FIFO\n");
+		return ret;
+	}
+	spin_lock_init(&controller->svc_fifo_lock);
+
+	chans[0].scl = NULL;
+	chans[0].ctrl = controller;
+	chans[0].name = SVC_CLIENT_FPGA;
+	spin_lock_init(&chans[0].lock);
+
+	list_add_tail(&controller->node, &svc_ctrl);
+	platform_set_drvdata(pdev, controller);
+
+	pr_info("Intel Service Layer Driver Initialized\n");
+
+	return ret;
+}
+
+static int stratix10_svc_drv_remove(struct platform_device *pdev)
+{
+	struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
+
+	kfifo_free(&ctrl->svc_fifo);
+	if (ctrl->task) {
+		kthread_stop(ctrl->task);
+		ctrl->task = NULL;
+	}
+	if (ctrl->genpool)
+		gen_pool_destroy(ctrl->genpool);
+	list_del(&ctrl->node);
+
+	return 0;
+}
+
+static struct platform_driver stratix10_svc_driver = {
+	.probe = stratix10_svc_drv_probe,
+	.remove = stratix10_svc_drv_remove,
+	.driver = {
+		.name = "stratix10-svc",
+		.of_match_table = stratix10_svc_drv_match,
+	},
+};
+
+static int __init stratix10_svc_init(void)
+{
+	struct device_node *fw_np;
+	struct device_node *np;
+	int ret;
+
+	fw_np = of_find_node_by_name(NULL, "firmware");
+	if (!fw_np)
+		return -ENODEV;
+
+	np = of_find_matching_node(fw_np, stratix10_svc_drv_match);
+	if (!np) {
+		of_node_put(fw_np);
+		return -ENODEV;
+	}
+
+	of_node_put(np);
+	ret = of_platform_populate(fw_np, stratix10_svc_drv_match, NULL, NULL);
+	of_node_put(fw_np);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&stratix10_svc_driver);
+}
+
+static void __exit stratix10_svc_exit(void)
+{
+	return platform_driver_unregister(&stratix10_svc_driver);
+}
+
+subsys_initcall(stratix10_svc_init);
+module_exit(stratix10_svc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Intel Stratix10 Service Layer Driver");
+MODULE_AUTHOR("Richard Gong <richard.gong@intel.com>");
+MODULE_ALIAS("platform:stratix10-svc");
diff --git a/include/linux/stratix10-svc-client.h b/include/linux/stratix10-svc-client.h
new file mode 100644
index 0000000..0ac6b2c
--- /dev/null
+++ b/include/linux/stratix10-svc-client.h
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017-2018, Intel Corporation
+ */
+
+#ifndef __STRATIX10_SVC_CLIENT_H
+#define __STRATIX10_SVC_CLIENT_H
+
+/**
+ * Service layer driver supports client names
+ *
+ * fpga: for FPGA configuration
+ */
+#define SVC_CLIENT_FPGA			"fpga"
+
+/**
+ * Status of the sent command, in bit number
+ *
+ * SVC_COMMAND_STATUS_RECONFIG_REQUEST_OK:
+ * Secure firmware accepts the request of FPGA reconfiguration.
+ *
+ * SVC_STATUS_RECONFIG_BUFFER_SUBMITTED:
+ * Service client successfully submits FPGA configuration
+ * data buffer to secure firmware.
+ *
+ * SVC_COMMAND_STATUS_RECONFIG_BUFFER_DONE:
+ * Secure firmware completes data process, ready to accept the
+ * next WRITE transaction.
+ *
+ * SVC_COMMAND_STATUS_RECONFIG_COMPLETED:
+ * Secure firmware completes FPGA configuration successfully, FPGA should
+ * be in user mode.
+ *
+ * SVC_COMMAND_STATUS_RECONFIG_BUSY:
+ * FPGA configuration is still in process.
+ *
+ * SVC_COMMAND_STATUS_RECONFIG_ERROR:
+ * Error encountered during FPGA configuration.
+ */
+#define SVC_STATUS_RECONFIG_REQUEST_OK		0
+#define SVC_STATUS_RECONFIG_BUFFER_SUBMITTED	1
+#define SVC_STATUS_RECONFIG_BUFFER_DONE		2
+#define SVC_STATUS_RECONFIG_COMPLETED		3
+#define SVC_STATUS_RECONFIG_BUSY		4
+#define SVC_STATUS_RECONFIG_ERROR		5
+
+/**
+ * Flag bit for COMMAND_RECONFIG
+ *
+ * COMMAND_RECONFIG_FLAG_PARTIAL:
+ * Set to FPGA configuration type (full or partial), the default
+ * is full reconfig.
+ */
+#define COMMAND_RECONFIG_FLAG_PARTIAL   0
+
+/**
+ * Timeout settings for service clients:
+ * timeout value used in Stratix10 FPGA manager driver.
+ */
+#define SVC_RECONFIG_REQUEST_TIMEOUT_MS         100
+#define SVC_RECONFIG_BUFFER_TIMEOUT_MS          240
+
+struct stratix10_svc_chan;
+
+/**
+ * enum stratix10_svc_command_code - supported service commands
+ *
+ * @COMMAND_NOOP: do 'dummy' request for integration/debug/trouble-shooting
+ *
+ * @COMMAND_RECONFIG: ask for FPGA configuration preparation, return status
+ * is SVC_STATUS_RECONFIG_REQUEST_OK
+ *
+ * @COMMAND_RECONFIG_DATA_SUBMIT: submit buffer(s) of bit-stream data for the
+ * FPGA configuration, return status is SVC_STATUS_RECONFIG_BUFFER_SUBMITTED,
+ * or SVC_STATUS_RECONFIG_ERROR
+ *
+ * @COMMAND_RECONFIG_DATA_CLAIM: check the status of the configuration, return
+ * status is SVC_STATUS_RECONFIG_COMPLETED, or SVC_STATUS_RECONFIG_BUSY, or
+ * SVC_STATUS_RECONFIG_ERROR
+ *
+ * @COMMAND_RECONFIG_STATUS: check the status of the configuration, return
+ * status is SVC_STATUS_RECONFIG_COMPLETED, or  SVC_STATUS_RECONFIG_BUSY, or
+ * SVC_STATUS_RECONFIG_ERROR
+ */
+enum stratix10_svc_command_code {
+	COMMAND_NOOP = 0,
+	COMMAND_RECONFIG,
+	COMMAND_RECONFIG_DATA_SUBMIT,
+	COMMAND_RECONFIG_DATA_CLAIM,
+	COMMAND_RECONFIG_STATUS
+};
+
+/**
+ * struct stratix10_svc_client_msg - message sent by client to service
+ * @command: service command
+ * @payload: starting address of data need be processed
+ * @payload_length: data size in bytes
+ */
+struct stratix10_svc_client_msg {
+	void *payload;
+	size_t payload_length;
+	enum stratix10_svc_command_code command;
+};
+
+/**
+ * struct stratix10_svc_command_reconfig_payload - reconfig payload
+ * @flags: flag bit for the type of FPGA configuration
+ */
+struct stratix10_svc_command_reconfig_payload {
+	u32 flags;
+};
+
+/**
+ * struct stratix10_svc_cb_data - callback data structure from service layer
+ * @status: the status of sent command
+ * @kaddr1: address of 1st completed data block
+ * @kaddr2: address of 2nd completed data block
+ * @kaddr3: address of 3rd completed data block
+ */
+struct stratix10_svc_cb_data {
+	u32 status;
+	void *kaddr1;
+	void *kaddr2;
+	void *kaddr3;
+};
+
+/**
+ * struct stratix10_svc_client - service client structure
+ * @dev: the client device
+ * @receive_cb: callback to provide service client the received data
+ * @priv: client private data
+ */
+struct stratix10_svc_client {
+	struct device *dev;
+	void (*receive_cb)(struct stratix10_svc_client *client,
+			   struct stratix10_svc_cb_data *cb_data);
+	void *priv;
+};
+
+/**
+ * stratix10_svc_request_channel_byname() - request service channel
+ * @client: identity of the client requesting the channel
+ * @name: supporting client name defined above
+ *
+ * Return: a pointer to channel assigned to the client on success,
+ * or ERR_PTR() on error.
+ */
+struct stratix10_svc_chan
+*stratix10_svc_request_channel_byname(struct stratix10_svc_client *client,
+	const char *name);
+
+/**
+ * stratix10_svc_free_channel() - free service channel.
+ * @chan: service channel to be freed
+ */
+void stratix10_svc_free_channel(struct stratix10_svc_chan *chan);
+
+/**
+ * stratix10_svc_allocate_memory() - allocate the momory
+ * @chan: service channel assigned to the client
+ * @size: number of bytes client requests
+ *
+ * Service layer allocates the requested number of bytes from the memory
+ * pool for the client.
+ *
+ * Return: the starting address of allocated memory on success, or
+ * ERR_PTR() on error.
+ */
+void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan,
+				    size_t size);
+
+/**
+ * stratix10_svc_free_memory() - free allocated memory
+ * @chan: service channel assigned to the client
+ * @kaddr: starting address of memory to be free back to pool
+ */
+void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr);
+
+/**
+ * stratix10_svc_send() - send a message to the remote
+ * @chan: service channel assigned to the client
+ * @msg: message data to be sent, in the format of
+ * struct stratix10_svc_client_msg
+ *
+ * Return: 0 for success, -ENOMEM or -ENOBUFS on error.
+ */
+int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg);
+
+/**
+ * intel_svc_done() - complete service request
+ * @chan: service channel assigned to the client
+ *
+ * This function is used by service client to inform service layer that
+ * client's service requests are completed, or there is an error in the
+ * request process.
+ */
+void stratix10_svc_done(struct stratix10_svc_chan *chan);
+#endif
+
-- 
2.7.4

^ permalink raw reply related

* [PATCHv5 2/8] arm64: dts: stratix10: add stratix10 service driver binding to base dtsi
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: devicetree, yves.vandervennet, richard.gong, linux-doc,
	linux-fpga, linux-kernel, richard.gong, linux-arm-kernel
In-Reply-To: <1527179600-26441-1-git-send-email-richard.gong@linux.intel.com>

From: Richard Gong <richard.gong@intel.com>

Add Intel Stratix10 service layer to the device tree

Signed-off-by: Richard Gong <richard.gong@intel.com>
Signed-off-by: Alan Tull <atull@kernel.org>
---
v2: Change to put service layer driver node under the firmware node
    Change compatible to "intel, stratix10-svc"
v3: No change
v4: s/service driver/stratix10 service driver/ in subject line
v5: No change
---
 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index d8c94d5..c257287 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -24,6 +24,19 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		service_reserved: svcbuffer@0 {
+			compatible = "shared-dma-pool";
+			reg = <0x0 0x0 0x0 0x1000000>;
+			alignment = <0x1000>;
+			no-map;
+		};
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -487,5 +500,13 @@
 
 			status = "disabled";
 		};
+
+		firmware {
+			svc {
+				compatible = "intel,stratix10-svc";
+				method = "smc";
+				memory-region = <&service_reserved>;
+			};
+		};
 	};
 };
-- 
2.7.4

^ permalink raw reply related

* [PATCHv5 1/8] dt-bindings, firmware: add Intel Stratix10 service layer binding
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-fpga, linux-doc,
	yves.vandervennet, richard.gong, richard.gong
In-Reply-To: <1527179600-26441-1-git-send-email-richard.gong@linux.intel.com>

From: Richard Gong <richard.gong@intel.com>

Add a device tree binding for the Intel Stratix10 service layer driver

Signed-off-by: Richard Gong <richard.gong@intel.com>
Signed-off-by: Alan Tull <atull@kernel.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v2: Change to put service layer driver node under the firmware node
    Change compatible to "intel, stratix10-svc"
v3: No change
v4: Add Rob's Reviewed-by
v5: No change
---
 .../bindings/firmware/intel,stratix10-svc.txt      | 57 ++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/intel,stratix10-svc.txt

diff --git a/Documentation/devicetree/bindings/firmware/intel,stratix10-svc.txt b/Documentation/devicetree/bindings/firmware/intel,stratix10-svc.txt
new file mode 100644
index 0000000..1fa6606
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/intel,stratix10-svc.txt
@@ -0,0 +1,57 @@
+Intel Service Layer Driver for Stratix10 SoC
+============================================
+Intel Stratix10 SoC is composed of a 64 bit quad-core ARM Cortex A53 hard
+processor system (HPS) and Secure Device Manager (SDM). When the FPGA is
+configured from HPS, there needs to be a way for HPS to notify SDM the
+location and size of the configuration data. Then SDM will get the
+configuration data from that location and perform the FPGA configuration.
+
+To meet the whole system security needs and support virtual machine requesting
+communication with SDM, only the secure world of software (EL3, Exception
+Layer 3) can interface with SDM. All software entities running on other
+exception layers must channel through the EL3 software whenever it needs
+service from SDM.
+
+Intel Stratix10 service layer driver, running at privileged exception level
+(EL1, Exception Layer 1), interfaces with the service providers and provides
+the services for FPGA configuration, QSPI, Crypto and warm reset. Service layer
+driver also manages secure monitor call (SMC) to communicate with secure monitor
+code running in EL3.
+
+Required properties:
+-------------------
+The svc node has the following mandatory properties, must be located under
+the firmware node.
+
+- compatible: "intel,stratix10-svc"
+- method: smc or hvc
+        smc - Secure Monitor Call
+        hvc - Hypervisor Call
+- memory-region:
+	phandle to the reserved memory node. See
+	Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+	for details
+
+Example:
+-------
+
+	reserved-memory {
+                #address-cells = <2>;
+                #size-cells = <2>;
+                ranges;
+
+                service_reserved: svcbuffer@0 {
+                        compatible = "shared-dma-pool";
+                        reg = <0x0 0x0 0x0 0x1000000>;
+                        alignment = <0x1000>;
+                        no-map;
+                };
+        };
+
+	firmware {
+		svc {
+			compatible = "intel,stratix10-svc";
+			method = "smc";
+			memory-region = <&service_reserved>;
+		};
+	};
-- 
2.7.4

^ permalink raw reply related

* [PATCHv5 0/8] Add Intel Stratix10 FPGA manager and service layer
From: richard.gong @ 2018-05-24 16:33 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, dinguyen, robh+dt, mark.rutland,
	atull, mdf, arnd, gregkh, corbet
  Cc: linux-arm-kernel, linux-kernel, devicetree, linux-fpga, linux-doc,
	yves.vandervennet, richard.gong, richard.gong

From: Richard Gong <richard.gong@intel.com>

This is the 5th submission of Intel stratix10 service layer patches. Intel
Stratix10 FPGA manager, which is 1st Stratix10 service layer client, is
included in this submission.

Stratix10 service layer patches have been reviewed internally by Alan Tull
and other colleagues at Intel.

Some features of the Intel Stratix10 SoC require a level of privilege
higher than the kernel is granted. Such secure features include
FPGA programming. In terms of the ARMv8 architecture, the kernel runs
at Exception Level 1 (EL1), access to the features requires
Exception Level 3 (EL3).

The Intel Stratix10 service layer provides an in kernel API for drivers to
request access to the secure features. The requests are queued and
processed one by one. ARM’s SMCCC is used to pass the execution of the
requests on to a secure monitor (EL3).

Later the Intel Stratix10 service layer driver will be extended to provide
services for QSPI, Crypto and warm reset.

v2: add patches for FPGA manager, FPGA manager binding, dts and defconfig
    remove intel-service subdirectory and intel-service.h, move intel-smc.h
    and intel-service.c to driver/misc subdirectory
    remove global variables
    change service layer driver be 'default n'
    correct SPDX markers
    add timeout for do..while() loop
    add kernel-doc for the functions and structs, correct multiline comments
    replace kfifo_in/kfifo_out with kfifo_in_spinlocked/kfifo_out_spinlocked
    rename struct intel_svc_data (at client header) to intel_svc_client_msg
    rename struct intel_svc_private_mem to intel_svc_data
    other corrections/changes from Intel internal code reviews
v3: change all exported functions with "intel_svc_" as the prefix
    increase timeout values for claiming back submitted buffer(s)
    rename struct intel_command_reconfig_payload to
    struct intel_svc_command_reconfig_payload
    add pr_err() to provide the error return value
    change to put fpga_mgr node under firmware/svc node
    change to FPGA manager to align the update of service client APIs, and the
    update of fpga_mgr device node
    Other corrections/changes
v4: s/intel/stratix10/ on some variables, structs, functions, and file names
    intel-service.c -> stratix10-svc.c
    intel-smc.h -> stratix10-smc.h
    intel-service-client.h -> stratix10-svc-client.h
    remove non-kernel-doc formatting
    s/fpga-mgr@0/fpga-mgr/ to remove unit_address at fpga_mgr node
    add Rob's Reviewed-by
    add Richard's signed-off-by
v5: add a new API statix10_svc_done() which is called by service client
    when client request is completed or error occurs during request
    process. Which allows service layer to free its resources.
    remove dummy client from service layer client header and service layer
    source file.
    add Rob's Reviewed-by
    add a new file stratix10-svc.rst and add that to driver-api/index.rst
    kernel-doc fixes

Alan Tull (3):
  dt-bindings: fpga: add Stratix10 SoC FPGA manager binding
  arm64: dts: stratix10: add fpga manager and region
  fpga: add intel stratix10 soc fpga manager driver

Richard Gong (5):
  dt-bindings, firmware: add Intel Stratix10 service layer binding
  arm64: dts: stratix10: add stratix10 service driver binding to base
    dtsi
  driver, misc: add Intel Stratix10 service layer driver
  defconfig: enable fpga and service layer
  Documentation: driver-api: add stratix10 service layer

 .../bindings/firmware/intel,stratix10-svc.txt      |  57 ++
 .../bindings/fpga/intel-stratix10-soc-fpga-mgr.txt |  17 +
 Documentation/driver-api/index.rst                 |   1 +
 Documentation/driver-api/stratix10-svc.rst         |  32 +
 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi  |  33 +
 arch/arm64/configs/defconfig                       |   6 +
 drivers/fpga/Kconfig                               |   6 +
 drivers/fpga/Makefile                              |   1 +
 drivers/fpga/stratix10-soc.c                       | 545 ++++++++++++
 drivers/misc/Kconfig                               |  12 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/stratix10-smc.h                       | 205 +++++
 drivers/misc/stratix10-svc.c                       | 984 +++++++++++++++++++++
 include/linux/stratix10-svc-client.h               | 199 +++++
 14 files changed, 2099 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/intel,stratix10-svc.txt
 create mode 100644 Documentation/devicetree/bindings/fpga/intel-stratix10-soc-fpga-mgr.txt
 create mode 100644 Documentation/driver-api/stratix10-svc.rst
 create mode 100644 drivers/fpga/stratix10-soc.c
 create mode 100644 drivers/misc/stratix10-smc.h
 create mode 100644 drivers/misc/stratix10-svc.c
 create mode 100644 include/linux/stratix10-svc-client.h

-- 
2.7.4

^ permalink raw reply

* Re: [PATCH] arm64: dts: msm8916: fix Coresight ETF graph connections
From: Mathieu Poirier @ 2018-05-24 16:32 UTC (permalink / raw)
  To: Ivan T. Ivanov
  Cc: Rob Herring, devicetree, linux-arm-msm, David Brown,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	Andy Gross, Ivan T . Ivanov
In-Reply-To: <20180524044853.713.23166@silver>

On 23 May 2018 at 22:48, Ivan T. Ivanov <iivanov.xz@gmail.com> wrote:
> Quoting Rob Herring (2018-05-23 23:29:29)
>> On Tue, May 8, 2018 at 10:09 AM, Rob Herring <robh@kernel.org> wrote:
>> > The ETF input should be connected to the funnel output, and the ETF
>> > output should be connected to the replicator input. The labels are wrong
>> > and these got swapped:
>> >
>> > Warning (graph_endpoint): /soc/funnel@821000/ports/port@8/endpoint: graph connection to node '/soc/etf@825000/ports/port@1/endpoint' is not bidirectional
>> > Warning (graph_endpoint): /soc/replicator@824000/ports/port@2/endpoint: graph connection to node '/soc/etf@825000/ports/port@0/endpoint' is not bidirectional
>> >
>> > Fixes: 7c10da373698 ("arm64: dts: qcom: Add msm8916 CoreSight components")
>> > Cc: Ivan T. Ivanov <ivan.ivanov@linaro.org>
>> > Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
>> > Cc: Andy Gross <andy.gross@linaro.org>
>> > Cc: David Brown <david.brown@linaro.org>
>> > Cc: linux-arm-msm@vger.kernel.org
>> > Signed-off-by: Rob Herring <robh@kernel.org>
>> > ---
>> >  arch/arm64/boot/dts/qcom/msm8916.dtsi | 4 ++--
>> >  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> Ping. Still seeing warnings in -next for these.
>>
>
>  Hi Rob,
>
>  I no longer have access to this hardware and documentation.
>  I am sure that Mathieu and friends will take care for verification
>  of this patch :-)

The code triggers on the "slave-mode" property rather than the labels,
so this patch has no effect on how a path is established.  I've tested
this on a 410c and things look good.

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Tested-by: Mathieu Poirier <mathieu.poirier@linaro.org>

>
>  Regards,
>  Ivan
>

^ permalink raw reply

* Re: [PATCH v3 4/6] watchdog: sp805: set WDOG_HW_RUNNING when appropriate
From: Guenter Roeck @ 2018-05-24 16:19 UTC (permalink / raw)
  To: Ray Jui
  Cc: Wim Van Sebroeck, Rob Herring, Mark Rutland, Frank Rowand,
	Catalin Marinas, Will Deacon, Robin Murphy, linux-watchdog,
	devicetree, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list
In-Reply-To: <1527120924-12131-5-git-send-email-ray.jui@broadcom.com>

On Wed, May 23, 2018 at 05:15:22PM -0700, Ray Jui wrote:
> If the watchdog hardware is already enabled during the boot process,
> when the Linux watchdog driver loads, it should reset the watchdog and
> tell the watchdog framework. As a result, ping can be generated from
> the watchdog framework, until the userspace watchdog daemon takes over
> control
> 
> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
> Reviewed-by: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> Reviewed-by: Scott Branden <scott.branden@broadcom.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

I have one question, though: Is it really correct that both
INT_ENABLE _and_ RESET_ENABLE have to be set to enable the watdog ?
What if only RESET_ENABLE is set ?

Thanks,
Guenter

> ---
>  drivers/watchdog/sp805_wdt.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
> index 1484609..d662a6f 100644
> --- a/drivers/watchdog/sp805_wdt.c
> +++ b/drivers/watchdog/sp805_wdt.c
> @@ -42,6 +42,7 @@
>  	/* control register masks */
>  	#define	INT_ENABLE	(1 << 0)
>  	#define	RESET_ENABLE	(1 << 1)
> +	#define	ENABLE_MASK	(INT_ENABLE | RESET_ENABLE)
>  #define WDTINTCLR		0x00C
>  #define WDTRIS			0x010
>  #define WDTMIS			0x014
> @@ -74,6 +75,15 @@ module_param(nowayout, bool, 0);
>  MODULE_PARM_DESC(nowayout,
>  		"Set to 1 to keep watchdog running after device release");
>  
> +/* returns true if wdt is running; otherwise returns false */
> +static bool wdt_is_running(struct watchdog_device *wdd)
> +{
> +	struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
> +	u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);
> +
> +	return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK;
> +}
> +
>  /* This routine finds load value that will reset system in required timout */
>  static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
>  {
> @@ -239,6 +249,15 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
>  	watchdog_init_timeout(&wdt->wdd, 0, &adev->dev);
>  	wdt_setload(&wdt->wdd, wdt->wdd.timeout);
>  
> +	/*
> +	 * If HW is already running, enable/reset the wdt and set the running
> +	 * bit to tell the wdt subsystem
> +	 */
> +	if (wdt_is_running(&wdt->wdd)) {
> +		wdt_enable(&wdt->wdd);
> +		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
> +	}
> +
>  	ret = watchdog_register_device(&wdt->wdd);
>  	if (ret) {
>  		dev_err(&adev->dev, "watchdog_register_device() failed: %d\n",
> -- 
> 2.1.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 2/6] Documentation: DT: Add optional 'timeout-sec' property for sp805
From: Guenter Roeck @ 2018-05-24 16:16 UTC (permalink / raw)
  To: Ray Jui
  Cc: Wim Van Sebroeck, Rob Herring, Mark Rutland, Frank Rowand,
	Catalin Marinas, Will Deacon, Robin Murphy, linux-watchdog,
	devicetree, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list
In-Reply-To: <1527120924-12131-3-git-send-email-ray.jui@broadcom.com>

On Wed, May 23, 2018 at 05:15:20PM -0700, Ray Jui wrote:
> Update the SP805 binding document to add optional 'timeout-sec'
> devicetree property
> 
> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
> ---
>  Documentation/devicetree/bindings/watchdog/arm,sp805.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/watchdog/arm,sp805.txt b/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
> index 0fa3629..1debea3 100644
> --- a/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
> +++ b/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
> @@ -19,6 +19,8 @@ Required properties:
>  
>  Optional properties:
>  - interrupts:  Should specify WDT interrupt number
> +- timeout-sec: Should specify default WDT timeout in seconds. If unset, the
> +               default timeout in the driver is 30 seconds

"... the default timeout is determined by the driver" might be better.
If you want to mandate a default here (not sure if that is a good idea),
I would suggest to use something like "should be 30 seconds".

Guenter

>  
>  Example:
>  	watchdog@66090000 {
> -- 
> 2.1.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] scripts/dtc: Fixed format mismatch in fprintf
From: Frank Rowand @ 2018-05-24 16:11 UTC (permalink / raw)
  To: nixiaoming, robh+dt; +Cc: devicetree, linux-kernel
In-Reply-To: <20180524025018.73187-1-nixiaoming@huawei.com>

On 05/23/18 19:50, nixiaoming wrote:
> format specifier "d" need arg type "int" , but the according arg
> "fdt32_to_cpu(xxx)" has type "unsigned int"
> 
> Signed-off-by: nixiaoming <nixiaoming@huawei.com>
> ---
>  scripts/dtc/fdtdump.c  | 6 +++---
>  scripts/dtc/flattree.c | 2 +-
>  2 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
> index 7d460a5..851bb6f 100644
> --- a/scripts/dtc/fdtdump.c
> +++ b/scripts/dtc/fdtdump.c
> @@ -66,12 +66,12 @@ static void dump_blob(void *blob)
>  
>  	printf("/dts-v1/;\n");
>  	printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
> -	printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
> +	printf("// totalsize:\t\t0x%x (%u)\n", totalsize, totalsize);
>  	printf("// off_dt_struct:\t0x%x\n", off_dt);
>  	printf("// off_dt_strings:\t0x%x\n", off_str);
>  	printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
> -	printf("// version:\t\t%d\n", version);
> -	printf("// last_comp_version:\t%d\n",
> +	printf("// version:\t\t%u\n", version);
> +	printf("// last_comp_version:\t%u\n",
>  	       fdt32_to_cpu(bph->last_comp_version));
>  	if (version >= 2)
>  		printf("// boot_cpuid_phys:\t0x%x\n",
> diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
> index 8d268fb..28da281 100644
> --- a/scripts/dtc/flattree.c
> +++ b/scripts/dtc/flattree.c
> @@ -393,7 +393,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int version)
>  			padlen = 0;
>  			if (quiet < 1)
>  				fprintf(stderr,
> -					"Warning: blob size %d >= minimum size %d\n",
> +					"Warning: blob size %u >= minimum size %d\n",
>  					fdt32_to_cpu(fdt.totalsize), minsize);
>  		}
>  	}
> 


We import this file from the upstream dtc project.  Please send patches
for this file to:

   David Gibson <david@gibson.dropbear.id.au>
   devicetree-compiler@vger.kernel.org

Thanks,

Frank

^ permalink raw reply

* Re: [PATCH 1/5] Documentation: DT: Add optional 'timeout-sec' property for sp805
From: Guenter Roeck @ 2018-05-24 16:07 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Mark Rutland, devicetree, linux-watchdog, Catalin Marinas,
	Will Deacon, linux-kernel, Rob Herring, Ray Jui,
	bcm-kernel-feedback-list, Wim Van Sebroeck, Frank Rowand,
	linux-arm-kernel
In-Reply-To: <91d27df4-29d0-de7f-6805-c3e5f329caf3@arm.com>

On Thu, May 24, 2018 at 02:25:34PM +0100, Robin Murphy wrote:
> On 23/05/18 19:10, Guenter Roeck wrote:
> >On Wed, May 23, 2018 at 11:57:25AM +0100, Robin Murphy wrote:
> >>On 22/05/18 19:47, Ray Jui wrote:
> >>>Update the SP805 binding document to add optional 'timeout-sec'
> >>>devicetree property
> >>>
> >>>Signed-off-by: Ray Jui <ray.jui@broadcom.com>
> >>>Reviewed-by: Scott Branden <scott.branden@broadcom.com>
> >>>---
> >>>  Documentation/devicetree/bindings/watchdog/sp805-wdt.txt | 2 ++
> >>>  1 file changed, 2 insertions(+)
> >>>
> >>>diff --git a/Documentation/devicetree/bindings/watchdog/sp805-wdt.txt b/Documentation/devicetree/bindings/watchdog/sp805-wdt.txt
> >>>index edc4f0e..f898a86 100644
> >>>--- a/Documentation/devicetree/bindings/watchdog/sp805-wdt.txt
> >>>+++ b/Documentation/devicetree/bindings/watchdog/sp805-wdt.txt
> >>>@@ -19,6 +19,8 @@ Required properties:
> >>>  Optional properties:
> >>>  - interrupts : Should specify WDT interrupt number.
> >>>+- timeout-sec : Should specify default WDT timeout in seconds. If unset, the
> >>>+                default timeout is 30 seconds
> >>
> >>According to the SP805 TRM, the default interval is dependent on the rate of
> >>WDOGCLK, but would typically be a lot longer than that :/
> >>
> >Depends on the definition of "default". In the context of watchdog drivers,
> >it is (or should be) a driver default, not a chip default.
> 
> DT describes hardware, not driver behaviour.
> 

In this case it describes expected system behavior. Most definitely
it does not describe some hardware default.

Please note that I do not engage in discussions I consider bike-shedding.
This is one of those. Dropping out.

Guenter

^ permalink raw reply

* Re: [PATCH v3 5/6] spi: at91-usart: add driver for at91-usart as spi
From: Radu Pirea @ 2018-05-24 16:04 UTC (permalink / raw)
  To: Mark Brown
  Cc: Andy Shevchenko, devicetree, open list:SERIAL DRIVERS,
	Linux Kernel Mailing List, linux-arm Mailing List, linux-spi,
	Mark Rutland, Rob Herring, Lee Jones, Greg Kroah-Hartman,
	Jiri Slaby, Richard Genoud, alexandre.belloni, Nicolas Ferre
In-Reply-To: <20180517045437.GE20254@sirena.org.uk>



On 05/17/2018 07:54 AM, Mark Brown wrote:
> On Tue, May 15, 2018 at 12:22:24PM +0300, Radu Pirea wrote:
>> On Mon, 2018-05-14 at 20:38 +0300, Andy Shevchenko wrote:
> 
>>> So, what is not going as expected in "SPI core takes care of CSs"
>>> case?
>>> Did you use oscilloscope for that?
> 
>> Yes, I used and CSs was not asserted. Anyway, I will will try again.
> 
> If the core chip select handling is not working properly for some reason
> then the core chip select handling should be fixed rather than just open
> coding in your driver - probably it's also broken for other users.
> 

Hi Mark,

I found the fix for cs-gpios. If I change spi_add_device function like 
this(see below) everything is ok.

int spi_add_device(struct spi_device *spi)

...

     if (ctlr->cs_gpios){
         spi->cs_gpio = ctlr->cs_gpios[spi->chip_select];
         if(gpio_is_valid(spi->cs_gpio))
             gpio_direction_output(spi->cs_gpio, !(spi->mode & 
SPI_CS_HIGH));

     }

...

     return status;
}

In the subsystem gpio direction of pins is never set and 
gpio_set_value() don't set the direction.
In my opinion gpio_direction_output() set direction should be called in 
spi_add_device. What do you think? Is ok?

^ permalink raw reply

* Re: [PATCH v2 4/7] Bluetooth: Add new quirk for non-persistent setup settings
From: Sean Wang @ 2018-05-24 15:30 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Mark Rutland, devicetree, Johan Hedberg, LKML, BlueZ development,
	Rob Herring, linux-mediatek, linux-arm-kernel
In-Reply-To: <37400FCE-8F9A-433B-8E3A-DE9CBEB469D7@holtmann.org>

On Thu, 2018-05-24 at 09:47 +0200, Marcel Holtmann wrote:
> Hi Sean,
> 
> >>>> 
> >>>> [ ... ]

[ ... ]

> > I post it as plain text as below 
> > 
> > 
> > Bluetooth monitor ver 5.37
> > = Note: Linux version 4.16.0-rc1+ (aarch64)                            0.641494
> > = Note: Bluetooth subsystem version 2.22                               0.641502
> > = New Index: 00:00:46:76:22:01 (BR/EDR,UART,hci0)               [hci0] 0.641505
> > * Unknown packet (code 14 len 30)                                      0.641509
> >        01 00 00 00 02 00 01 0e 00 01 00 00 00 10 62 6c  ..............bl
> >        75 65 74 6f 6f 74 68 64 00 00 00 00 00 00        uetoothd......  
> > * Unknown packet (code 14 len 30)                                      0.641592
> >        02 00 00 00 02 00 01 0e 00 01 00 00 00 10 62 74  ..............bt
> >        6d 6f 6e 00 00 00 00 00 00 00 00 00 00 00        mon...........  
> > * Unknown packet (code 16 len 7)                                [hci0] 6.536771
> >        01 00 00 00 05 00 01                             .......         
> > = Open Index: 00:00:46:76:22:01                                 [hci0] 6.717019
> > = Index Info: 00:00:46:76:22:01 (MediaTek, Inc.)                [hci0] 6.717030
> 
> can you try with the latest BlueZ 5.49 or git version. Seems it actually stumbles over the extra packet here. Fun fact is that I can not get a backtrace to pin-point the issue in btmon and why it crashes.
> 

I had less experience updating user land BlueZ, but I can try it as possible and see whether Unknown packets still are present at newest version BlueZ. Hopefully I don't misunderstand your point here. 


> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.741093
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.742088
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.743102
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.744105
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.745109
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.746104
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.747097
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.748090
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.749078
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.750070
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.751061
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.752054
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.753046
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.754038
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.755031
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.756025
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.757013
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.758006
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.758999
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.759991
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.760983
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.761975
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.762963
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.763956
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.764948
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.765941
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.766933
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.767926
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.768919
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.769914
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.770909
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.771908
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.772904
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.773898
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.774892
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.775890
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.776882
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.777877
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.778871
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.779869
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.780864
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.781858
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.782852
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.783850
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.784845
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.785839
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.786833
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.787831
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.788826
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.789820
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.790814
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.791813
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.792809
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.793803
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.794798
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.795797
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.796791
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.797786
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.798779
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.799778
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.800774
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.801769
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.802763
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.803761
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.804755
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.805749
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.806743
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.807741
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.808737
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.809731
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.810725
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.811725
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.812719
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.813714
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.814708
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.815705
> >        02 01 01 00 00                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.816378
> >        02 01 01 00 00                                   .....           
> 
> Why do I see only HCI events here? Is this event conveying any useful information. It is kinda complicated that this is 0xe4 event code which is actually reserved for future use by the Bluetooth SIG. Are there any accompanying HCI commands for this and they just not make it into btmon?
> 

I have made all vendor HCI commands go through BlueZ core in v2 patch. 

And for these HCI events, they are all corresponding to vendor ACL data, applied only to firmware setup packets, but they're not being sent via BlueZ core, so they are not being logged in btmon.

As for its event, where heading 0xe4 refers to a vendor event and is used on notification of that either vendor ACL data or vendor HCI command have been done.

> 
> 
> > < HCI Command: Vendor (0x3f|0x006f) plen 5                      [hci0] 6.816413
> >        01 07 01 00 04                                   .....           
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 6.816536
> >        02 07 01 00 00                                   .....           
> > < HCI Command: Vendor (0x3f|0x006f) plen 6                      [hci0] 8.845071
> >        01 06 02 00 00 01                                ......          
> >> HCI Event: Unknown (0xe4) plen 5                              [hci0] 8.923456
> >        02 06 01 00 00                                   .....           
> 
> Here it looks like you have 0x006f opcode with first octet 0x01 for command and then vendor event 0xe4 with first octet 0x02 for event. I assume the second octet is then the vendor command code for these.
> 

Yes, you're right.

> > < HCI Command: Reset (0x03|0x0003) plen 0                      [hci0] 10.861118
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.865763
> >      Reset (0x03|0x0003) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Read Local Supported Fe.. (0x04|0x0003) plen 0  [hci0] 10.865805
> >> HCI Event: Command Complete (0x0e) plen 12                   [hci0] 10.865965
> >      Read Local Supported Features (0x04|0x0003) ncmd 1
> >        Status: Success (0x00)
> >        Features: 0xbf 0x3e 0x8d 0xfe 0xdb 0xff 0x7b 0x87
> >          3 slot packets
> >          5 slot packets
> >          Encryption
> >          Slot offset
> >          Timing accuracy
> >          Role switch
> >          Sniff mode
> >          Power control requests
> >          Channel quality driven data rate (CQDDR)
> >          SCO link
> >          HV2 packets
> >          HV3 packets
> >          CVSD synchronous data
> >          Power control
> >          Transparent synchronous data
> >          Broadcast Encryption
> >          Enhanced Data Rate ACL 2 Mbps mode
> >          Enhanced Data Rate ACL 3 Mbps mode
> >          Enhanced inquiry scan
> >          Interlaced inquiry scan
> >          Interlaced page scan
> >          RSSI with inquiry results
> >          Extended SCO link (EV3 packets)
> >          EV4 packets
> >          EV5 packets
> >          AFH capable slave
> >          AFH classification slave
> >          LE Supported (Controller)
> >          3-slot Enhanced Data Rate ACL packets
> >          5-slot Enhanced Data Rate ACL packets
> >          Sniff subrating
> >          Pause encryption
> >          AFH capable master
> >          AFH classification master
> >          Enhanced Data Rate eSCO 2 Mbps mode
> >          Enhanced Data Rate eSCO 3 Mbps mode
> >          3-slot Enhanced Data Rate eSCO packets
> >          Extended Inquiry Response
> >          Simultaneous LE and BR/EDR (Controller)
> >          Secure Simple Pairing
> >          Encapsulated PDU
> >          Erroneous Data Reporting
> >          Non-flushable Packet Boundary Flag
> >          Link Supervision Timeout Changed Event
> >          Inquiry TX Power Level
> >          Enhanced Power Control
> >          Extended features
> > < HCI Command: Read Local Version Info.. (0x04|0x0001) plen 0  [hci0] 10.865987
> >> HCI Event: Vendor (0xff) plen 9                              [hci0] 10.866259
> >        29 19 09 17 20 48 07 11 00                       )... H…       
> 
> Is this meant to happen here?
> 

If event received is not expected as the specification defines, I think it's probably incorrect.

But it requires more discussion with firmware people to make it clearer.

> >> HCI Event: Command Complete (0x0e) plen 12                   [hci0] 10.866372
> >      Read Local Version Information (0x04|0x0001) ncmd 1
> >        Status: Success (0x00)
> >        HCI version: Bluetooth 4.2 (0x08) - Revision 4359 (0x1107)
> >        LMP version: Bluetooth 4.2 (0x08) - Subversion 2329 (0x0919)
> >        Manufacturer: MediaTek, Inc. (70)
> > < HCI Command: Read BD ADDR (0x04|0x0009) plen 0               [hci0] 10.866391
> >> HCI Event: Command Complete (0x0e) plen 10                   [hci0] 10.866539
> >      Read BD ADDR (0x04|0x0009) ncmd 1
> >        Status: Success (0x00)
> >        Address: 00:00:46:76:22:01 (OLIVETTI NORTH AMERICA)
> > < HCI Command: Read Buffer Size (0x04|0x0005) plen 0           [hci0] 10.866609
> >> HCI Event: Command Complete (0x0e) plen 11                   [hci0] 10.866754
> >      Read Buffer Size (0x04|0x0005) ncmd 1
> >        Status: Success (0x00)
> >        ACL MTU: 1021 ACL max packet: 8
> >        SCO MTU: 184  SCO max packet: 1
> > < HCI Command: Read Class of Device (0x03|0x0023) plen 0       [hci0] 10.866775
> >> HCI Event: Command Complete (0x0e) plen 7                    [hci0] 10.866920
> >      Read Class of Device (0x03|0x0023) ncmd 1
> >        Status: Success (0x00)
> >        Class: 0x001f00
> >          Major class: Uncategorized, specific device code not specified
> >          Minor class: 0x00
> > < HCI Command: Read Local Name (0x03|0x0014) plen 0            [hci0] 10.866939
> >> HCI Event: Command Complete (0x0e) plen 252                  [hci0] 10.867256
> >      Read Local Name (0x03|0x0014) ncmd 1
> >        Status: Success (0x00)
> >        Name: MTK MT7622 #1
> > < HCI Command: Read Voice Setting (0x03|0x0025) plen 0         [hci0] 10.867308
> >> HCI Event: Command Complete (0x0e) plen 6                    [hci0] 10.867447
> >      Read Voice Setting (0x03|0x0025) ncmd 1
> >        Status: Success (0x00)
> >        Setting: 0x0060
> >          Input Coding: Linear
> >          Input Data Format: 2's complement
> >          Input Sample Size: 16-bit
> >          # of bits padding at MSB: 0
> >          Air Coding Format: CVSD
> > < HCI Command: Read Number of Supporte.. (0x03|0x0038) plen 0  [hci0] 10.867474
> >> HCI Event: Command Complete (0x0e) plen 5                    [hci0] 10.867611
> >      Read Number of Supported IAC (0x03|0x0038) ncmd 1
> >        Status: Success (0x00)
> >        Number of IAC: 4
> > < HCI Command: Read Current IAC LAP (0x03|0x0039) plen 0       [hci0] 10.867678
> >> HCI Event: Command Complete (0x0e) plen 8                    [hci0] 10.867865
> >      Read Current IAC LAP (0x03|0x0039) ncmd 1
> >        Status: Success (0x00)
> >        Number of IAC: 1
> >        Access code: 0x9e8b33 (General Inquiry)
> > < HCI Command: Set Event Filter (0x03|0x0005) plen 1           [hci0] 10.867890
> >        Type: Clear All Filters (0x00)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.868033
> >      Set Event Filter (0x03|0x0005) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Write Connection Accept.. (0x03|0x0016) plen 2  [hci0] 10.868054
> >        Timeout: 20000.000 msec (0x7d00)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.868235
> >      Write Connection Accept Timeout (0x03|0x0016) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: LE Read Buffer Size (0x08|0x0002) plen 0        [hci0] 10.868262
> >> HCI Event: Command Complete (0x0e) plen 7                    [hci0] 10.868392
> >      LE Read Buffer Size (0x08|0x0002) ncmd 1
> >        Status: Success (0x00)
> >        Data packet length: 251
> >        Num data packets: 8
> > < HCI Command: LE Read Local Supported.. (0x08|0x0003) plen 0  [hci0] 10.868413
> >> HCI Event: Command Complete (0x0e) plen 12                   [hci0] 10.868587
> >      LE Read Local Supported Features (0x08|0x0003) ncmd 1
> >        Status: Success (0x00)
> >        Features: 0xfd 0x00 0x00 0x00 0x00 0x00 0x00 0x00
> >          LE Encryption
> >          Extended Reject Indication
> >          Slave-initiated Features Exchange
> >          LE Ping
> >          LE Data Packet Length Extension
> >          LL Privacy
> >          Extended Scanner Filter Policies
> > < HCI Command: LE Read Supported States (0x08|0x001c) plen 0   [hci0] 10.868646
> >> HCI Event: Command Complete (0x0e) plen 12                   [hci0] 10.868787
> >      LE Read Supported States (0x08|0x001c) ncmd 1
> >        Status: Success (0x00)
> >        States: 0x000000001fffffff
> >          Non-connectable Advertising State
> >          Scannable Advertising State
> >          Connectable Advertising State
> >          High Duty Cycle Directed Advertising State
> >          Passive Scanning State
> >          Active Scanning State
> >          Initiating State
> >            and Connection State (Master Role)
> >          Connection State (Slave Role)
> >          Non-connectable Advertising State
> >            and Passive Scanning State
> >          Scannable Advertising State
> >            and Passive Scanning State
> >          Connectable Advertising State
> >            and Passive Scanning State
> >          High Duty Cycle Directed Advertising State
> >            and Passive Scanning State
> >          Non-connectable Advertising State
> >            and Active Scanning State
> >          Scannable Advertising State
> >            and Active Scanning State
> >          Connectable Advertising State
> >            and Active Scanning State
> >          High Duty Cycle Directed Advertising State
> >            and Active Scanning State
> >          Non-connectable Advertising State
> >            and Initiating State
> >          Scannable Advertising State
> >            and Initiating State
> >          Non-connectable Advertising State
> >            and Connection State (Master Role)
> >          Scannable Advertising State
> >            and Connection State (Master Role)
> >          Non-connectable Advertising State
> >            and Connection State (Slave Role)
> >          Scannable Advertising State
> >            and Connection State (Slave Role)
> >          Passive Scanning State
> >            and Initiating State
> >          Active Scanning State
> >            and Initiating State
> >          Passive Scanning State
> >            and Connection State (Master Role)
> >          Active Scanning State
> >            and Connection State (Master Role)
> >          Passive Scanning State
> >            and Connection State (Slave Role)
> >          Active Scanning State
> >            and Connection State (Slave Role)
> >          Initiating State
> >            and Connection State (Master Role)
> >            and Master Role & Master Role
> > < HCI Command: Read Local Supported Co.. (0x04|0x0002) plen 0  [hci0] 10.868807
> >> HCI Event: Command Complete (0x0e) plen 68                   [hci0] 10.868985
> >      Read Local Supported Commands (0x04|0x0002) ncmd 1
> >        Status: Success (0x00)
> >        Commands: 176 entries
> >          Inquiry (Octet 0 - Bit 0)
> >          Inquiry Cancel (Octet 0 - Bit 1)
> >          Periodic Inquiry Mode (Octet 0 - Bit 2)
> >          Exit Periodic Inquiry Mode (Octet 0 - Bit 3)
> >          Create Connection (Octet 0 - Bit 4)
> >          Disconnect (Octet 0 - Bit 5)
> >          Add SCO Connection (Octet 0 - Bit 6)
> >          Create Connection Cancel (Octet 0 - Bit 7)
> >          Accept Connection Request (Octet 1 - Bit 0)
> >          Reject Connection Request (Octet 1 - Bit 1)
> >          Link Key Request Reply (Octet 1 - Bit 2)
> >          Link Key Request Negative Reply (Octet 1 - Bit 3)
> >          PIN Code Request Reply (Octet 1 - Bit 4)
> >          PIN Code Request Negative Reply (Octet 1 - Bit 5)
> >          Change Connection Packet Type (Octet 1 - Bit 6)
> >          Authentication Requested (Octet 1 - Bit 7)
> >          Set Connection Encryption (Octet 2 - Bit 0)
> >          Change Connection Link Key (Octet 2 - Bit 1)
> >          Master Link Key (Octet 2 - Bit 2)
> >          Remote Name Request (Octet 2 - Bit 3)
> >          Remote Name Request Cancel (Octet 2 - Bit 4)
> >          Read Remote Supported Features (Octet 2 - Bit 5)
> >          Read Remote Extended Features (Octet 2 - Bit 6)
> >          Read Remote Version Information (Octet 2 - Bit 7)
> >          Read Clock Offset (Octet 3 - Bit 0)
> >          Read LMP Handle (Octet 3 - Bit 1)
> >          Sniff Mode (Octet 4 - Bit 2)
> >          Exit Sniff Mode (Octet 4 - Bit 3)
> >          QoS Setup (Octet 4 - Bit 6)
> >          Role Discovery (Octet 4 - Bit 7)
> >          Switch Role (Octet 5 - Bit 0)
> >          Read Link Policy Settings (Octet 5 - Bit 1)
> >          Write Link Policy Settings (Octet 5 - Bit 2)
> >          Read Default Link Policy Settings (Octet 5 - Bit 3)
> >          Write Default Link Policy Settings (Octet 5 - Bit 4)
> >          Flow Specification (Octet 5 - Bit 5)
> >          Set Event Mask (Octet 5 - Bit 6)
> >          Reset (Octet 5 - Bit 7)
> >          Set Event Filter (Octet 6 - Bit 0)
> >          Flush (Octet 6 - Bit 1)
> >          Read PIN Type (Octet 6 - Bit 2)
> >          Write PIN Type (Octet 6 - Bit 3)
> >          Create New Unit Key (Octet 6 - Bit 4)
> >          Read Stored Link Key (Octet 6 - Bit 5)
> >          Write Stored Link Key (Octet 6 - Bit 6)
> >          Delete Stored Link Key (Octet 6 - Bit 7)
> >          Write Local Name (Octet 7 - Bit 0)
> >          Read Local Name (Octet 7 - Bit 1)
> >          Read Connection Accept Timeout (Octet 7 - Bit 2)
> >          Write Connection Accept Timeout (Octet 7 - Bit 3)
> >          Read Page Timeout (Octet 7 - Bit 4)
> >          Write Page Timeout (Octet 7 - Bit 5)
> >          Read Scan Enable (Octet 7 - Bit 6)
> >          Write Scan Enable (Octet 7 - Bit 7)
> >          Read Page Scan Activity (Octet 8 - Bit 0)
> >          Write Page Scan Activity (Octet 8 - Bit 1)
> >          Read Inquiry Scan Activity (Octet 8 - Bit 2)
> >          Write Inquiry Scan Activity (Octet 8 - Bit 3)
> >          Read Authentication Enable (Octet 8 - Bit 4)
> >          Write Authentication Enable (Octet 8 - Bit 5)
> >          Read Encryption Mode (Octet 8 - Bit 6)
> >          Write Encryption Mode (Octet 8 - Bit 7)
> >          Read Class of Device (Octet 9 - Bit 0)
> >          Write Class of Device (Octet 9 - Bit 1)
> >          Read Voice Setting (Octet 9 - Bit 2)
> >          Write Voice Setting (Octet 9 - Bit 3)
> >          Read Automatic Flush Timeout (Octet 9 - Bit 4)
> >          Write Automatic Flush Timeout (Octet 9 - Bit 5)
> >          Read Num Broadcast Retransmissions (Octet 9 - Bit 6)
> >          Write Num Broadcast Retransmissions (Octet 9 - Bit 7)
> >          Read Transmit Power Level (Octet 10 - Bit 2)
> >          Read Sync Flow Control Enable (Octet 10 - Bit 3)
> >          Write Sync Flow Control Enable (Octet 10 - Bit 4)
> >          Set Controller To Host Flow Control (Octet 10 - Bit 5)
> >          Host Buffer Size (Octet 10 - Bit 6)
> >          Host Number of Completed Packets (Octet 10 - Bit 7)
> >          Read Link Supervision Timeout (Octet 11 - Bit 0)
> >          Write Link Supervision Timeout (Octet 11 - Bit 1)
> >          Read Number of Supported IAC (Octet 11 - Bit 2)
> >          Read Current IAC LAP (Octet 11 - Bit 3)
> >          Write Current IAC LAP (Octet 11 - Bit 4)
> >          Read Page Scan Mode (Octet 11 - Bit 7)
> >          Write Page Scan Mode (Octet 12 - Bit 0)
> >          Set AFH Host Channel Classification (Octet 12 - Bit 1)
> >          Read Inquiry Scan Type (Octet 12 - Bit 4)
> >          Write Inquiry Scan Type (Octet 12 - Bit 5)
> >          Read Inquiry Mode (Octet 12 - Bit 6)
> >          Write Inquiry Mode (Octet 12 - Bit 7)
> >          Read Page Scan Type (Octet 13 - Bit 0)
> >          Write Page Scan Type (Octet 13 - Bit 1)
> >          Read AFH Channel Assessment Mode (Octet 13 - Bit 2)
> >          Write AFH Channel Assessment Mode (Octet 13 - Bit 3)
> >          Read Local Version Information (Octet 14 - Bit 3)
> >          Read Local Supported Features (Octet 14 - Bit 5)
> >          Read Local Extended Features (Octet 14 - Bit 6)
> >          Read Buffer Size (Octet 14 - Bit 7)
> >          Read Country Code (Octet 15 - Bit 0)
> >          Read BD ADDR (Octet 15 - Bit 1)
> >          Read Failed Contact Counter (Octet 15 - Bit 2)
> >          Reset Failed Contact Counter (Octet 15 - Bit 3)
> >          Read Link Quality (Octet 15 - Bit 4)
> >          Read RSSI (Octet 15 - Bit 5)
> >          Read AFH Channel Map (Octet 15 - Bit 6)
> >          Read Clock (Octet 15 - Bit 7)
> >          Read Loopback Mode (Octet 16 - Bit 0)
> >          Write Loopback Mode (Octet 16 - Bit 1)
> >          Enable Device Under Test Mode (Octet 16 - Bit 2)
> >          Setup Synchronous Connection (Octet 16 - Bit 3)
> >          Accept Synchronous Connection Request (Octet 16 - Bit 4)
> >          Reject Synchronous Connection Request (Octet 16 - Bit 5)
> >          Read Extended Inquiry Response (Octet 17 - Bit 0)
> >          Write Extended Inquiry Response (Octet 17 - Bit 1)
> >          Refresh Encryption Key (Octet 17 - Bit 2)
> >          Sniff Subrating (Octet 17 - Bit 4)
> >          Read Simple Pairing Mode (Octet 17 - Bit 5)
> >          Write Simple Pairing Mode (Octet 17 - Bit 6)
> >          Read Local OOB Data (Octet 17 - Bit 7)
> >          Read Inquiry Response TX Power Level (Octet 18 - Bit 0)
> >          Write Inquiry Transmit Power Level (Octet 18 - Bit 1)
> >          Read Default Erroneous Data Reporting (Octet 18 - Bit 2)
> >          Write Default Erroneous Data Reporting (Octet 18 - Bit 3)
> >          IO Capability Request Reply (Octet 18 - Bit 7)
> >          User Confirmation Request Reply (Octet 19 - Bit 0)
> >          User Confirmation Request Neg Reply (Octet 19 - Bit 1)
> >          User Passkey Request Reply (Octet 19 - Bit 2)
> >          User Passkey Request Negative Reply (Octet 19 - Bit 3)
> >          Remote OOB Data Request Reply (Octet 19 - Bit 4)
> >          Write Simple Pairing Debug Mode (Octet 19 - Bit 5)
> >          Enhanced Flush (Octet 19 - Bit 6)
> >          Remote OOB Data Request Neg Reply (Octet 19 - Bit 7)
> >          Send Keypress Notification (Octet 20 - Bit 2)
> >          IO Capability Request Negative Reply (Octet 20 - Bit 3)
> >          Read Encryption Key Size (Octet 20 - Bit 4)
> >          Set Event Mask Page 2 (Octet 22 - Bit 2)
> >          Read Enhanced Transmit Power Level (Octet 24 - Bit 0)
> >          Enhanced Setup Synchronous Connection (Octet 29 - Bit 3)
> >          Enhanced Accept Synchronous Connection Request (Octet 29 - Bit 4)
> >          Read Local Supported Codecs (Octet 29 - Bit 5)
> >          Set Triggered Clock Capture (Octet 30 - Bit 5)
> >          Truncated Page (Octet 30 - Bit 6)
> >          Truncated Page Cancel (Octet 30 - Bit 7)
> >          Set Connectionless Slave Broadcast (Octet 31 - Bit 0)
> >          Start Synchronization Train (Octet 31 - Bit 2)
> >          Set Reserved LT_ADDR (Octet 31 - Bit 4)
> >          Delete Reserved LT_ADDR (Octet 31 - Bit 5)
> >          Set Connectionless Slave Broadcast Data (Octet 31 - Bit 6)
> >          Read Synchronization Train Parameters (Octet 31 - Bit 7)
> >          Write Synchronization Train Parameters (Octet 32 - Bit 0)
> >          Remote OOB Extended Data Request Reply (Octet 32 - Bit 1)
> >          Read Authenticated Payload Timeout (Octet 32 - Bit 4)
> >          Write Authenticated Payload Timeout (Octet 32 - Bit 5)
> >          Read Local OOB Extended Data (Octet 32 - Bit 6)
> >          Write Secure Connections Test Mode (Octet 32 - Bit 7)
> >          Read Extended Page Timeout (Octet 33 - Bit 0)
> >          Write Extended Page Timeout (Octet 33 - Bit 1)
> >          Read Extended Inquiry Length (Octet 33 - Bit 2)
> >          Write Extended Inquiry Length (Octet 33 - Bit 3)
> >          LE Set Data Length (Octet 33 - Bit 6)
> >          LE Read Suggested Default Data Length (Octet 33 - Bit 7)
> >          LE Write Suggested Default Data Length (Octet 34 - Bit 0)
> >          LE Read Local P-256 Public Key (Octet 34 - Bit 1)
> >          LE Generate DHKey (Octet 34 - Bit 2)
> >          LE Add Device To Resolving List (Octet 34 - Bit 3)
> >          LE Remove Device From Resolving List (Octet 34 - Bit 4)
> >          LE Clear Resolving List (Octet 34 - Bit 5)
> >          LE Read Resolving List Size (Octet 34 - Bit 6)
> >          LE Read Peer Resolvable Address (Octet 34 - Bit 7)
> >          LE Read Local Resolvable Address (Octet 35 - Bit 0)
> >          LE Set Address Resolution Enable (Octet 35 - Bit 1)
> >          LE Set Resolvable Private Address Timeout (Octet 35 - Bit 2)
> >          LE Read Maximum Data Length (Octet 35 - Bit 3)
> >          Octet 35 - Bit 4 
> >          Octet 35 - Bit 5 
> >          Octet 35 - Bit 6 
> >          Octet 35 - Bit 7 
> >          Octet 36 - Bit 0 
> 
> So you support the PHY commands, but do not indicate support LE 2M or LE Coded? Also these are Bluetooth 5.0 commands.
> 

To be honest. When I ported the device into Bluez core, a unexpected event for LE read local feature would cause a fail at Bluez core, so I made a hack on Bluez core  

to allow that I can keeping bring up the device without be blocked by the issue most probably from firmware.

Below code snippet is the only thing I added to avoid a fail at Bluez core to bring up the device.

@@ -927,6 +927,8 @@ static void hci_cc_le_read_local_features(struct hci_dev *hdev,
                return;

        memcpy(hdev->le_features, rp->features, 8);
+       hdev->le_features[0] = 0;
+       hdev->le_features[1] = 0;
 }


> > < HCI Command: Write Simple Pairing Mode (0x03|0x0056) plen 1  [hci0] 10.869023
> >        Mode: Enabled (0x01)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.869185
> >      Write Simple Pairing Mode (0x03|0x0056) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Write Inquiry Mode (0x03|0x0045) plen 1         [hci0] 10.869239
> >        Mode: Inquiry Result with RSSI or Extended Inquiry Result (0x02)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.869371
> >      Write Inquiry Mode (0x03|0x0045) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Read Inquiry Response T.. (0x03|0x0058) plen 0  [hci0] 10.869396
> >> HCI Event: Command Complete (0x0e) plen 5                    [hci0] 10.869552
> >      Read Inquiry Response TX Power Level (0x03|0x0058) ncmd 1
> >        Status: Success (0x00)
> >        TX power: -1 dBm
> > < HCI Command: Read Local Extended Fea.. (0x04|0x0004) plen 1  [hci0] 10.869572
> >        Page: 1
> >> HCI Event: Command Complete (0x0e) plen 14                   [hci0] 10.869729
> >      Read Local Extended Features (0x04|0x0004) ncmd 1
> >        Status: Success (0x00)
> >        Page: 1/2
> >        Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
> >          Secure Simple Pairing (Host Support)
> > < HCI Command: Set Event Mask (0x03|0x0001) plen 8             [hci0] 10.869783
> >        Mask: 0x3dbff807fffbffff
> >          Inquiry Complete
> >          Inquiry Result
> >          Connection Complete
> >          Connection Request
> >          Disconnection Complete
> >          Authentication Complete
> >          Remote Name Request Complete
> >          Encryption Change
> >          Change Connection Link Key Complete
> >          Master Link Key Complete
> >          Read Remote Supported Features Complete
> >          Read Remote Version Information Complete
> >          QoS Setup Complete
> >          Command Complete
> >          Command Status
> >          Hardware Error
> >          Flush Occurred
> >          Role Change
> >          Mode Change
> >          Return Link Keys
> >          PIN Code Request
> >          Link Key Request
> >          Link Key Notification
> >          Loopback Command
> >          Data Buffer Overflow
> >          Max Slots Change
> >          Read Clock Offset Complete
> >          Connection Packet Type Changed
> >          QoS Violation
> >          Page Scan Mode Change
> >          Page Scan Repetition Mode Change
> >          Flow Specification Complete
> >          Inquiry Result with RSSI
> >          Read Remote Extended Features Complete
> >          Synchronous Connection Complete
> >          Synchronous Connection Changed
> >          Sniff Subrating
> >          Extended Inquiry Result
> >          Encryption Key Refresh Complete
> >          IO Capability Request
> >          IO Capability Request Reply
> >          User Confirmation Request
> >          User Passkey Request
> >          Remote OOB Data Request
> >          Simple Pairing Complete
> >          Link Supervision Timeout Changed
> >          Enhanced Flush Complete
> >          User Passkey Notification
> >          Keypress Notification
> >          Remote Host Supported Features Notification
> >          LE Meta
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.869921
> >      Set Event Mask (0x03|0x0001) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Read Stored Link Key (0x03|0x000d) plen 7       [hci0] 10.869947
> >        Address: 00:00:00:00:00:00 (OUI 00-00-00)
> >        Read all: 0x01
> >> HCI Event: Command Complete (0x0e) plen 8                    [hci0] 10.870129
> >      Read Stored Link Key (0x03|0x000d) ncmd 1
> >        Status: Success (0x00)
> >        Max num keys: 4
> >        Num keys: 0
> > < HCI Command: Write Default Link Poli.. (0x02|0x000f) plen 2  [hci0] 10.870148
> >        Link policy: 0x0005
> >          Enable Role Switch
> >          Enable Sniff Mode
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.870310
> >      Write Default Link Policy Settings (0x02|0x000f) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Read Page Scan Activity (0x03|0x001b) plen 0    [hci0] 10.870331
> >> HCI Event: Command Complete (0x0e) plen 8                    [hci0] 10.870485
> >      Read Page Scan Activity (0x03|0x001b) ncmd 1
> >        Status: Success (0x00)
> >        Interval: 1280.000 msec (0x0800)
> >        Window: 11.250 msec (0x0012)
> > < HCI Command: Read Page Scan Type (0x03|0x0046) plen 0        [hci0] 10.870504
> >> HCI Event: Command Complete (0x0e) plen 5                    [hci0] 10.870652
> >      Read Page Scan Type (0x03|0x0046) ncmd 1
> >        Status: Success (0x00)
> >        Type: Standard Scan (0x00)
> > < HCI Command: LE Set Event Mask (0x08|0x0001) plen 8          [hci0] 10.870671
> >        Mask: 0x0000000000000980
> >          LE Read Local P-256 Public Key Complete
> >          LE Generate DHKey Complete
> >          Unknown mask (0x0000000000000800)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.870839
> >      LE Set Event Mask (0x08|0x0001) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Write LE Host Supported (0x03|0x006d) plen 2    [hci0] 10.870859
> >        Supported: 0x01
> >        Simultaneous: 0x00
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.871028
> >      Write LE Host Supported (0x03|0x006d) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Read Local Extended Fea.. (0x04|0x0004) plen 1  [hci0] 10.871059
> >        Page: 2
> >> HCI Event: Command Complete (0x0e) plen 14                   [hci0] 10.871201
> >      Read Local Extended Features (0x04|0x0004) ncmd 1
> >        Status: Success (0x00)
> >        Page: 2/2
> >        Features: 0x25 0x0b 0x00 0x00 0x00 0x00 0x00 0x00
> >          Connectionless Slave Broadcast - Master
> >          Synchronization Train
> >          Generalized interlaced scan
> >          Secure Connections (Controller Support)
> >          Ping
> >          Train nudging
> > < HCI Command: Delete Stored Link Key (0x03|0x0012) plen 7     [hci0] 10.871240
> >        Address: 00:00:00:00:00:00 (OUI 00-00-00)
> >        Delete all: 0x01
> >> HCI Event: Command Complete (0x0e) plen 6                    [hci0] 10.871384
> >      Delete Stored Link Key (0x03|0x0012) ncmd 1
> >        Status: Success (0x00)
> >        Num keys: 0
> > < HCI Command: Set Event Mask Page 2 (0x03|0x0063) plen 8      [hci0] 10.871403
> >        Mask: 0x0000000000b0c000
> >          Triggered Clock Capture
> >          Synchronization Train Complete
> >          Slave Page Response Timeout
> >          Connectionless Slave Broadcast Channel Map Change
> >          Authenticated Payload Timeout Expired
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.871566
> >      Set Event Mask Page 2 (0x03|0x0063) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Read Local Supported Co.. (0x04|0x000b) plen 0  [hci0] 10.871599
> >> HCI Event: Command Complete (0x0e) plen 8                    [hci0] 10.871750
> >      Read Local Supported Codecs (0x04|0x000b) ncmd 1
> >        Status: Success (0x00)
> >        Number of supported codecs: 2
> >          Codec: CVSD (0x02)
> >          Codec: Transparent (0x03)
> >        Number of vendor codecs: 0
> > < HCI Command: Read Synchronization Tr.. (0x03|0x0077) plen 0  [hci0] 10.871769
> >> HCI Event: Command Complete (0x0e) plen 11                   [hci0] 10.871928
> >      Read Synchronization Train Parameters (0x03|0x0077) ncmd 1
> >        Status: Success (0x00)
> >        Interval: 0.000 msec (0x0000)
> >        Timeout: 0.000 msec (0x00000000)
> >        Service data: 0x00
> > < HCI Command: Write Secure Connection.. (0x03|0x007a) plen 1  [hci0] 10.871947
> >        Support: Enabled (0x01)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.872098
> >      Write Secure Connections Host Support (0x03|0x007a) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Unknown (0x08|0x0031) plen 3                    [hci0] 10.872156
> >        03 00 00                                         ...             
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.872322
> >      Unknown (0x08|0x0031) ncmd 1
> >        Status: Success (0x00)
> > = Index Info: 00:00:46:76:22:01 (MediaTek, Inc.)               [hci0] 10.872361
> 
> This extra index info worries me a little bit. I need to check if that is suppose to happen.
> > < HCI Command: LE Set Scan Response D.. (0x08|0x0009) plen 32  [hci0] 10.872431
> >        Length: 10
> >        Name (complete): builder
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.872606
> >      LE Set Scan Response Data (0x08|0x0009) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Write Scan Enable (0x03|0x001a) plen 1          [hci0] 10.872627
> >        Scan enable: Page Scan (0x02)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.872819
> >      Write Scan Enable (0x03|0x001a) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Write Class of Device (0x03|0x0024) plen 3      [hci0] 10.872841
> >        Class: 0x000000
> >          Major class: Miscellaneous
> >          Minor class: 0x00
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.873036
> >      Write Class of Device (0x03|0x0024) ncmd 1
> >        Status: Success (0x00)
> > * Unknown packet (code 17 len 9)                               [hci0] 10.873069
> >        02 00 00 00 07 00 00 00 00                       .........       
> > * Unknown packet (code 17 len 9)                               [hci0] 10.873069
> >        01 00 00 00 07 00 00 00 00                       .........       
> > < HCI Command: Write Local Name (0x03|0x0013) plen 248         [hci0] 10.873096
> >        Name: builder
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.873446
> >      Write Local Name (0x03|0x0013) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Write Extended Inquir.. (0x03|0x0052) plen 241  [hci0] 10.873470
> >        FEC: Not required (0x00)
> >        Name (complete): builder
> >        TX power: -1 dBm
> >        Device ID: USB Implementer's Forum assigned (0x0002)
> >          Vendor: Linux Foundation (0x1d6b)
> >          Product: 0x0246
> >          Version: 5.2.11 (0x052b)
> >        16-bit Service UUIDs (complete): 4 entries
> >          Generic Access Profile (0x1800)
> >          Generic Attribute Profile (0x1801)
> >          A/V Remote Control (0x110e)
> >          A/V Remote Control Target (0x110c)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 10.873857
> >      Write Extended Inquiry Response (0x03|0x0052) ncmd 1
> >        Status: Success (0x00)
> > * Unknown packet (code 17 len 13)                              [hci0] 10.873903
> >        01 00 00 00 01 00 05 00 00 d1 0a 00 00           .............   
> > * Unknown packet (code 17 len 10)                              [hci0] 10.873913
> >        02 00 00 00 06 00 d1 0a 00 00                    ..........      
> > * Unknown packet (code 16 len 7)                               [hci0] 17.803939
> >        01 00 00 00 05 00 00                             .......         
> > < HCI Command: Write Scan Enable (0x03|0x001a) plen 1          [hci0] 17.803983
> >        Scan enable: No Scans (0x00)
> >> HCI Event: Command Complete (0x0e) plen 4                    [hci0] 17.804233
> >      Write Scan Enable (0x03|0x001a) ncmd 1
> >        Status: Success (0x00)
> > < HCI Command: Vendor (0x3f|0x006f) plen 6                     [hci0] 17.804282
> >        01 06 02 00 00 00                                ......          
> >> HCI Event: Unknown (0xe4) plen 5                             [hci0] 17.804636
> >        02 06 01 00 00                                   .....           
> > * Unknown packet (code 17 len 13)                              [hci0] 17.811580
> >        01 00 00 00 01 00 05 00 00 d0 0a 00 00           .............   
> > * Unknown packet (code 17 len 10)                              [hci0] 17.811596
> >        02 00 00 00 06 00 d0 0a 00 00                    ..........      
> > = Close Index: 00:00:46:76:22:01                               [hci0] 17.811625
> 
> Regards
> 
> Marcel
> 

^ permalink raw reply

* [PATCH v2 9/9] ARM: dts: silk: Drop MTD partitioning from DT
From: Marek Vasut @ 2018-05-24 15:07 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: devicetree, Geert Uytterhoeven, Wolfram Sang, linux-renesas-soc,
	Laurent Pinchart, Simon Horman, Marek Vasut
In-Reply-To: <20180524150721.28964-1-marek.vasut+renesas@gmail.com>

Drop the MTD partitioning from DT, since it does not describe HW
and to give way to a more flexible kernel command line partition
passing.

To retain the original partitioning, assure you have enabled
CONFIG_MTD_CMDLINE_PARTS in your kernel config and add the
following to your kernel command line:

  mtdparts=spi0.0:256k(loader),4m(user),-(flash)

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Simon Horman <horms+renesas@verge.net.au>
Cc: Wolfram Sang <wsa@the-dreams.de>
Cc: linux-renesas-soc@vger.kernel.org
---
V2: Drop the @0 anchor from the commit message, use 4m
---
 arch/arm/boot/dts/r8a7794-silk.dts | 21 ---------------------
 1 file changed, 21 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
index 7808aaee6644..b8163a0e2190 100644
--- a/arch/arm/boot/dts/r8a7794-silk.dts
+++ b/arch/arm/boot/dts/r8a7794-silk.dts
@@ -444,27 +444,6 @@
 		spi-cpol;
 		spi-cpha;
 		m25p,fast-read;
-
-		partitions {
-			compatible = "fixed-partitions";
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			partition@0 {
-				label = "loader";
-				reg = <0x00000000 0x00040000>;
-				read-only;
-			};
-			partition@40000 {
-				label = "user";
-				reg = <0x00040000 0x00400000>;
-				read-only;
-			};
-			partition@440000 {
-				label = "flash";
-				reg = <0x00440000 0x03bc0000>;
-			};
-		};
 	};
 };
 
-- 
2.16.2

^ 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