Devicetree
 help / color / mirror / Atom feed
* Re: [RESEND][PATCH 5/6] dt-bindings: gpio: Update gpio bindings for LS2088A
From: Rob Herring @ 2016-11-14 17:14 UTC (permalink / raw)
  To: Abhimanyu Saini
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	shawnguo-DgEjT+Ai2ygdnm+yROfE0A, scott.wood-3arQi8VN3Tc,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Priyanka Jain,
	Ashish Kumar
In-Reply-To: <1478597664-14799-6-git-send-email-abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>

On Tue, Nov 08, 2016 at 03:04:23PM +0530, Abhimanyu Saini wrote:
> Signed-off-by: Priyanka Jain <priyanka.jain-3arQi8VN3Tc@public.gmane.org>
> Signed-off-by: Ashish Kumar <ashish.kumar-3arQi8VN3Tc@public.gmane.org>
> Signed-off-by: Abhimanyu Saini <abhimanyu.saini-3arQi8VN3Tc@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Rob Herring @ 2016-11-14 17:18 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Lee Jones, Andy Gross, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1478622577-20699-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Tue, Nov 08, 2016 at 04:29:36PM +0000, Srinivas Kandagatla wrote:
> This patch adds support to PM8821 PMIC and interrupt support.
> PM8821 is companion device that supplements primary PMIC PM8921 IC.
> 
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> Tested this patch for MPP and IRQ functionality on IFC6410 and SD600 EVAL
> board with mpps PM8821 and PM8921.
> 
>  .../devicetree/bindings/mfd/qcom-pm8xxx.txt        |   1 +

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>  drivers/mfd/pm8921-core.c                          | 368 +++++++++++++++++++--
>  2 files changed, 340 insertions(+), 29 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 1/2] pinctrl: sunxi: Add support for interrupt debouncing
From: Rob Herring @ 2016-11-14 17:19 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Linus Walleij, Alexandre Courbot,
	linux-gpio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Chen-Yu Tsai
In-Reply-To: <7dbb47b16d83b843705aa05d4a5f1f7dfdc4e9a3.1478636546.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

On Tue, Nov 08, 2016 at 09:24:00PM +0100, Maxime Ripard wrote:
> The pin controller found in the Allwinner SoCs has support for interrupts
> debouncing.
> 
> However, this is not done per-pin, preventing us from using the generic
> pinconf binding for that, but per irq bank, which, depending on the SoC,
> ranges from one to five.
> 
> Introduce a device-wide property to deal with this using a microsecond
> resolution. We can re-use the per-pin input-debounce property for that, so
> let's do it!
> 
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 14 ++++++++++++-

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>  drivers/pinctrl/sunxi/pinctrl-sunxi.c                                 | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h                                 |  7 ++++++-
>  3 files changed, 102 insertions(+), 0 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/6] dt-bindings: mdio-mux: Add documentation for mdio mux for NSP SoC
From: Rob Herring @ 2016-11-14 17:22 UTC (permalink / raw)
  To: Yendapally Reddy Dhananjaya Reddy
  Cc: Mark Rutland, Russell King, Ray Jui, Scott Branden, Jon Mason,
	Florian Fainelli, Kishon Vijay Abraham I,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
	netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1478683994-12008-2-git-send-email-yendapally.reddy-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

On Wed, Nov 09, 2016 at 04:33:09AM -0500, Yendapally Reddy Dhananjaya Reddy wrote:
> Add documentation for mdio mux available in Broadcom NSP SoC
> 
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
> ---
>  .../devicetree/bindings/net/brcm,mdio-mux-nsp.txt  | 57 ++++++++++++++++++++++
>  1 file changed, 57 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-nsp.txt

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 2/6] dt-bindings: phy: Add documentation for NSP USB3 PHY
From: Rob Herring @ 2016-11-14 17:23 UTC (permalink / raw)
  To: Yendapally Reddy Dhananjaya Reddy
  Cc: Mark Rutland, Russell King, Ray Jui, Scott Branden, Jon Mason,
	Florian Fainelli, Kishon Vijay Abraham I,
	bcm-kernel-feedback-list, netdev, devicetree, linux-kernel,
	linux-arm-kernel
In-Reply-To: <1478683994-12008-3-git-send-email-yendapally.reddy@broadcom.com>

On Wed, Nov 09, 2016 at 04:33:10AM -0500, Yendapally Reddy Dhananjaya Reddy wrote:
> Add documentation for USB3 PHY available in Northstar plus SoC
> 
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
> ---
>  .../devicetree/bindings/phy/brcm,nsp-usb3-phy.txt  | 39 ++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
> 
> diff --git a/Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt b/Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
> new file mode 100644
> index 0000000..30cf4b9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/brcm,nsp-usb3-phy.txt
> @@ -0,0 +1,39 @@
> +Broadcom USB3 phy binding northstar plus SoC
> +This is a child bus node of "brcm,mdio-mux-nsp" node.
> +
> +Required mdio bus properties:
> +- reg: MDIO Bus number for the MDIO interface
> +- #address-cells: must be 1
> +- #size-cells: must be 0
> +
> +Required PHY properties:
> +- compatible: should be "brcm,nsp-usb3-phy"
> +- reg: Phy address in the MDIO interface
> +- usb3-ctrl-syscon: handler of syscon node defining physical address
> +  of usb3 control register.
> +- #phy-cells: must be 0
> +
> +Required usb3 control properties:
> +- compatible: should be "brcm,nsp-usb3-ctrl"
> +- reg: offset and length of the control registers
> +
> +Example:
> +
> +	mdio@0 {
> +		reg = <0x0>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		usb3_phy: usb3-phy@10 {

Just 'usb-phy@10'. With that,

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

^ permalink raw reply

* Re: [PATCH v2 7/9] arm64: dts: rockchip: add pd_edp node for rk3399
From: Doug Anderson @ 2016-11-14 17:26 UTC (permalink / raw)
  To: Caesar Wang
  Cc: Heiko Stuebner, Eddie Cai, Tomasz Figa, zhangqing, David Wu,
	Jianqun Xu, Yakir Yang, Brian Norris,
	linux-kernel@vger.kernel.org, open list:ARM/Rockchip SoC...,
	devicetree@vger.kernel.org, Rob Herring, Will Deacon,
	Mark Rutland, Catalin Marinas,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <1478697721-2323-8-git-send-email-wxt@rock-chips.com>

Caesar,

On Wed, Nov 9, 2016 at 5:21 AM, Caesar Wang <wxt@rock-chips.com> wrote:
> From: zhangqing <zhangqing@rock-chips.com>
>
> 1. add pd node for RK3399 Soc
> 2. create power domain tree
> 3. add qos node for domain

No step #3 since there doesn't appear to be a qos node for eDP.  Your
patch doesn't add one and I can't find one in the TRM.

> 4. add the pd support for edp
>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> Signed-off-by: Caesar Wang <wxt@rock-chips.com>
> ---
>
> Changes in v2: None
>
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index 74deb44..09ebf4e 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -835,6 +835,10 @@
>                         };
>
>                         /* These power domains are grouped by VD_LOGIC */
> +                       pd_edp@RK3399_PD_EDP {
> +                               reg = <RK3399_PD_EDP>;
> +                               clocks = <&cru PCLK_EDP_CTRL>;

Are you sure that PCLK_EDP isn't needed as well?  After the super
hard-to-debug problems we just faced with the missing GMAC clock in
the power domains, I figure it's at least worth a check.  ;)

> +                       };
>                         pd_emmc@RK3399_PD_EMMC {
>                                 reg = <RK3399_PD_EMMC>;
>                                 clocks = <&cru ACLK_EMMC>;
> @@ -1364,6 +1368,7 @@
>                 status = "disabled";
>                 pinctrl-names = "default";
>                 pinctrl-0 = <&edp_hpd>;
> +               power-domains = <&power RK3399_PD_EDP>;
>
>                 ports {
>                         #address-cells = <1>;

Other than the question about the clock and the nits about the commit
message, this all looks fine to me.  Feel free to add my Reviewed-by
if you fix those things.


-Doug

^ permalink raw reply

* Re: [PATCH v2] mtd/spi-nor: Add SPI memory controllers for Aspeed SoCs
From: Rob Herring @ 2016-11-14 17:27 UTC (permalink / raw)
  To: Cédric Le Goater
  Cc: linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, David Woodhouse,
	Brian Norris, Boris Brezillon, Marek Vasut, Richard Weinberger,
	Cyrille Pitchen, devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Rutland,
	Joel Stanley
In-Reply-To: <1478688149-4554-1-git-send-email-clg-Bxea+6Xhats@public.gmane.org>

On Wed, Nov 09, 2016 at 11:42:29AM +0100, Cédric Le Goater wrote:
> This driver adds mtd support for spi-nor attached to either or both of
> the Firmware Memory Controller or the SPI Flash Controller (AST2400
> only).
> 
> The SMC controllers on the Aspeed AST2500 SoC are very similar to the
> ones found on the AST2400. The differences are on the number of
> supported flash modules and their default mappings in the SoC address
> space.
> 
> The Aspeed AST2500 has one SPI controller for the BMC firmware and two
> for the host firmware. All controllers have now the same set of
> registers compatible with the AST2400 FMC controller and the legacy
> 'SMC' controller is fully gone.
> 
> Each controller has a memory range on which it maps its flash module
> slaves. Each slave is assigned a memory window for its mapping that
> can be changed at bootime with the Segment Address Register.
> 
> Each SPI flash slave can then be accessed in two modes: Command and
> User. When in User mode, accesses to the memory segment of the slaves
> are translated in SPI transfers. When in Command mode, the HW
> generates the SPI commands automatically and the memory segment is
> accessed as if doing a MMIO.
> 
> Currently, only the User mode is supported. Command mode needs a
> little more work to check that the memory window on the AHB bus fits
> the module size.
> 
> Based on previous work from Milton D. Miller II <miltonm-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> 
> Signed-off-by: Cédric Le Goater <clg-Bxea+6Xhats@public.gmane.org>
> ---
>  Tested on:
> 
>  * OpenPOWER Palmetto (AST2400) with
>  	FMC controller : n25q256a
> 	SPI controller : mx25l25635e and n25q512ax3
> 
>  * Evaluation board (AST2500) with
>  	FMC controller : w25q256 
> 	SPI controller : w25q256
> 
>  * OpenPOWER Witherspoon (AST2500) with
>  	FMC controller : mx25l25635e * 2
> 	SPI controller : mx66l1g45g
> 
>  Changes since v2:
> 
>  - added a set4b ops to handle difference in the controllers
>  - simplified the IO routines
>  - prepared for fast read using dummy cycles
> 
>  Work in progress:
> 
>  - read optimization using higher SPI clock frequencies
>  - command mode to direct reads from AHB
>  - DMA support
> 
>  .../devicetree/bindings/mtd/aspeed-smc.txt         |  72 ++

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>  drivers/mtd/spi-nor/Kconfig                        |  12 +
>  drivers/mtd/spi-nor/Makefile                       |   1 +
>  drivers/mtd/spi-nor/aspeed-smc.c                   | 783 +++++++++++++++++++++
>  4 files changed, 868 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/aspeed-smc.txt
>  create mode 100644 drivers/mtd/spi-nor/aspeed-smc.c
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 0/3] ARM64: dts: meson-gxl: Enable Ethernet
From: Kevin Hilman @ 2016-11-14 17:28 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: carlo, linux-amlogic, linux-arm-kernel, linux-kernel, devicetree
In-Reply-To: <20161107104357.24428-1-narmstrong@baylibre.com>

Neil Armstrong <narmstrong@baylibre.com> writes:

> The Amlogic Meson GXL SoCs have an internal RMII PHY that is muxed with the
> external RGMII pins.
>
> The internal PHY is added in the GXL dtsi and support for each
> board is added in intermediate board family dtsi or final dts.

Tested external phy and internal phy (using p231 DT) on my p230 board.

Applied to v4.10/dt64

Kevin

^ permalink raw reply

* Re: [PATCH v4 3/3] dt-bindings: i2c: pxa: Update the documentation for the Armada 3700
From: Rob Herring @ 2016-11-14 17:28 UTC (permalink / raw)
  To: Romain Perier
  Cc: Wolfram Sang, linux-i2c, devicetree, Ian Campbell, Pawel Moll,
	Mark Rutland, Kumar Gala, Jason Cooper, Andrew Lunn,
	Sebastian Hesselbarth, Gregory Clement, linux-arm-kernel,
	Thomas Petazzoni, Nadav Haklai, Omri Itach, Shadi Ammouri,
	Yahuda Yitschak, Hanna Hawa, Neta Zur Hershkovits, Igal Liberman
In-Reply-To: <20161109115715.2557-4-romain.perier@free-electrons.com>

On Wed, Nov 09, 2016 at 12:57:15PM +0100, Romain Perier wrote:
> This commit documents the compatible string to have the compatibility for
> the I2C unit found in the Armada 3700.
> 
> Signed-off-by: Romain Perier <romain.perier@free-electrons.com>
> ---
> 
> Changes in v2:
>  - Fixed wrong compatible string, it should be "marvell,armada-3700-i2c"
>    and not "marvell,armada-3700".
> 
>  Documentation/devicetree/bindings/i2c/i2c-pxa.txt | 1 +
>  1 file changed, 1 insertion(+)

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

^ permalink raw reply

* [PATCH 0/2] ARM: da850: enable the MSTPRI and DDR2/mDDR drivers
From: Bartosz Golaszewski @ 2016-11-14 17:32 UTC (permalink / raw)
  To: Kevin Hilman, Michael Turquette, Sekhar Nori, Rob Herring,
	Frank Rowand, Mark Rutland, Peter Ujfalusi, Russell King
  Cc: linux-devicetree, LKML, linux-drm, Bartosz Golaszewski,
	Tomi Valkeinen, Jyri Sarha, arm-soc, Laurent Pinchart

This is a follow-up for my previous series:

  ARM: da850: new drivers for better LCDC support

from which the new drivers were merged, while the patch adding the
panel node was nacked and has been dropped.

The first patch in this series enables the new drivers in da850.dtsi.
It has been changed since the last iteration to not disable the added
nodes. Also: the patch enabling the nodes in da850-lcdk.dts has been
dropped too.

The second patch updates the davinci defconfig.

Bartosz Golaszewski (2):
  ARM: dts: da850: add the mstpri and ddrctl nodes
  ARM: davinci_all_defconfig: enable the mstpri and ddrctl drivers

 arch/arm/boot/dts/da850.dtsi           | 9 +++++++++
 arch/arm/configs/davinci_all_defconfig | 2 ++
 2 files changed, 11 insertions(+)

-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH 1/2] ARM: dts: da850: add the mstpri and ddrctl nodes
From: Bartosz Golaszewski @ 2016-11-14 17:32 UTC (permalink / raw)
  To: Kevin Hilman, Michael Turquette, Sekhar Nori, Rob Herring,
	Frank Rowand, Mark Rutland, Peter Ujfalusi, Russell King
  Cc: linux-devicetree, LKML, linux-drm, Bartosz Golaszewski,
	Tomi Valkeinen, Jyri Sarha, arm-soc, Laurent Pinchart
In-Reply-To: <1479144724-14231-1-git-send-email-bgolaszewski@baylibre.com>

Add the nodes for the MSTPRI configuration and DDR2/mDDR memory
controller drivers to da850.dtsi.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 arch/arm/boot/dts/da850.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 1bb1f6d..1635218 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -440,6 +440,11 @@
 			interrupts = <52>;
 			status = "disabled";
 		};
+
+		mstpri: mstpri@14110 {
+			compatible = "ti,da850-mstpri";
+			reg = <0x14110 0x0c>;
+		};
 	};
 	aemif: aemif@68000000 {
 		compatible = "ti,da850-aemif";
@@ -451,4 +456,8 @@
 			  1 0 0x68000000 0x00008000>;
 		status = "disabled";
 	};
+	ddrctl: ddrctl@b0000000 {
+		compatible = "ti,da850-ddr-controller";
+		reg = <0xb0000000 0xe8>;
+	};
 };
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* [PATCH 2/2] ARM: davinci_all_defconfig: enable the mstpri and ddrctl drivers
From: Bartosz Golaszewski @ 2016-11-14 17:32 UTC (permalink / raw)
  To: Kevin Hilman, Michael Turquette, Sekhar Nori, Rob Herring,
	Frank Rowand, Mark Rutland, Peter Ujfalusi, Russell King
  Cc: linux-devicetree, LKML, linux-drm, Bartosz Golaszewski,
	Tomi Valkeinen, Jyri Sarha, arm-soc, Laurent Pinchart
In-Reply-To: <1479144724-14231-1-git-send-email-bgolaszewski@baylibre.com>

With the da8xx memory controller and master peripheral priority
drivers merged and corresponding device tree changes in place we can
now enable appropriate options by default.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 arch/arm/configs/davinci_all_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index b5e978f..f814f01 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -56,6 +56,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
+CONFIG_DA8XX_MSTPRI=y
 CONFIG_MTD=m
 CONFIG_MTD_BLOCK=m
 CONFIG_MTD_CFI=m
@@ -187,6 +188,7 @@ CONFIG_DMADEVICES=y
 CONFIG_TI_EDMA=y
 CONFIG_MEMORY=y
 CONFIG_TI_AEMIF=m
+CONFIG_DA8XX_DDRCTL=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=m
-- 
2.9.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related

* Re: [PATCH 2/2] ARM: dts: apq8064: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:32 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Lee Jones, Rob Herring, Andy Gross, devicetree, linux-kernel,
	linux-arm-msm, linux-soc, linux-arm-kernel
In-Reply-To: <20161108191343.GP25787@tuxbot>

Thanks Bjorn for review comments.


On 08/11/16 19:13, Bjorn Andersson wrote:
> On Tue 08 Nov 08:29 PST 2016, Srinivas Kandagatla wrote:
>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
>> ---
>>  arch/arm/boot/dts/qcom-apq8064.dtsi | 28 ++++++++++++++++++++++++++++
>>  1 file changed, 28 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
>> index 1dbe697..fde006c 100644
>> --- a/arch/arm/boot/dts/qcom-apq8064.dtsi
>> +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
>> @@ -627,6 +627,34 @@
>>  			clock-names = "core";
>>  		};
>>
>> +		qcom,ssbi@c00000 {
>
> No "qcom," in the node name.
Will fix it in next version,  I agree with rest of the comments too.
All of them will be fixed in next version.
>
>> +			compatible = "qcom,ssbi";
>> +			reg = <0x00c00000 0x1000>;
>> +			qcom,controller-type = "pmic-arbiter";
>> +
>> +			pmicintc2: pmic@1 {
>
> I think we should follow Linus' lead and label this "pm8821".
>
>> +				compatible = "qcom,pm8821";
>> +				interrupt-parent = <&tlmm_pinmux>;
>> +				interrupts = <76 8>;
>
> Please spell out IRQ_TYPE_LEVEL_LOW.
>
> And interrupts-extended = <&tlmm_pinmux 76 IRQ_TYPE_LEVEL_LOW> combines
> the two lines nicely.
>
>> +				#interrupt-cells = <2>;
>> +				interrupt-controller;
>> +				#address-cells = <1>;
>> +				#size-cells = <0>;
>> +
>> +				pm8821_mpps: mpps@50 {
>> +
>
> Extra newline.
>
>> +					compatible = "qcom,pm8821-mpp", "qcom,ssbi-mpp";
>> +					reg = <0x50>;
>> +
>> +					interrupts = <24 1>, <25 1>, <26 1>,
>> +						     <27 1>;
>
> I think these should be IRQ_TYPE_NONE per the discussion on how to share
> interrupts between the gpio/mpp driver and other clients.
>
> On the other hand, per the pm8821 driver we only support LEVEL_LOW
> (high?).
>
>> +
>> +					gpio-controller;
>> +					#gpio-cells = <2>;
>> +		                };
>> +			};
>> +		};
>> +
>
> Regards,
> Bjorn
>

^ permalink raw reply

* Re: [PATCH] arm64: dts: juno: fix cluster sleep state entry latency on all SoC versions
From: Liviu Dudau @ 2016-11-14 17:32 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Lorenzo Pieralisi,
	Jon Medhurst (Tixy)
In-Reply-To: <1479137189-15378-1-git-send-email-sudeep.holla-5wv7dgnIgG8@public.gmane.org>

On Mon, Nov 14, 2016 at 03:26:29PM +0000, Sudeep Holla wrote:
> The core and the cluster sleep state entry latencies can't be same as
> cluster sleep involves more work compared to core level e.g. shared
> cache maintenance.
> 
> Experiments have shown on an average about 100us more latency for the
> cluster sleep state compared to the core level sleep. This patch fixes
> the entry latency for the cluster sleep state.
> 
> Fixes: 28e10a8f3a03 ("arm64: dts: juno: Add idle-states to device tree")
> Cc: Liviu Dudau <liviu.dudau-5wv7dgnIgG8@public.gmane.org>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
> Cc: "Jon Medhurst (Tixy)" <tixy-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Signed-off-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>

Looks sensible to me.

Reviewed-by: Liviu Dudau <Liviu.Dudau-5wv7dgnIgG8@public.gmane.org>

> ---
>  arch/arm64/boot/dts/arm/juno-r1.dts | 2 +-
>  arch/arm64/boot/dts/arm/juno-r2.dts | 2 +-
>  arch/arm64/boot/dts/arm/juno.dts    | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
> 
> Hi,
> 
> This was found recently when I found that core sleep was chosen when
> entering suspend-to-idle state on Juno. Since the wakeup(entry+exit)
> latency matched for the both states, cpu sleep state was chosen to enter
> in suspend-to-idle.
> 
> Regards,
> Sudeep
> 
> diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts
> index 3be8a3ef671c..eec37feee8fc 100644
> --- a/arch/arm64/boot/dts/arm/juno-r1.dts
> +++ b/arch/arm64/boot/dts/arm/juno-r1.dts
> @@ -76,7 +76,7 @@
>  				compatible = "arm,idle-state";
>  				arm,psci-suspend-param = <0x1010000>;
>  				local-timer-stop;
> -				entry-latency-us = <300>;
> +				entry-latency-us = <400>;
>  				exit-latency-us = <1200>;
>  				min-residency-us = <2500>;
>  			};
> diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts
> index 614fc9227943..28f40ec44090 100644
> --- a/arch/arm64/boot/dts/arm/juno-r2.dts
> +++ b/arch/arm64/boot/dts/arm/juno-r2.dts
> @@ -76,7 +76,7 @@
>  				compatible = "arm,idle-state";
>  				arm,psci-suspend-param = <0x1010000>;
>  				local-timer-stop;
> -				entry-latency-us = <300>;
> +				entry-latency-us = <400>;
>  				exit-latency-us = <1200>;
>  				min-residency-us = <2500>;
>  			};
> diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
> index 6b4135e9cfe5..ac5ceb73f45f 100644
> --- a/arch/arm64/boot/dts/arm/juno.dts
> +++ b/arch/arm64/boot/dts/arm/juno.dts
> @@ -76,7 +76,7 @@
>  				compatible = "arm,idle-state";
>  				arm,psci-suspend-param = <0x1010000>;
>  				local-timer-stop;
> -				entry-latency-us = <300>;
> +				entry-latency-us = <400>;
>  				exit-latency-us = <1200>;
>  				min-residency-us = <2500>;
>  			};
> --
> 2.7.4
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:33 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Lee Jones, Rob Herring, Andy Gross,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20161108190751.GO25787@tuxbot>

Thanks Bjorn for review comments.

On 08/11/16 19:07, Bjorn Andersson wrote:
> On Tue 08 Nov 08:29 PST 2016, Srinivas Kandagatla wrote:
>
>> This patch adds support to PM8821 PMIC and interrupt support.
>> PM8821 is companion device that supplements primary PMIC PM8921 IC.
>>
>
> Linus Walleij has a patch out for renaming a lot of things in this file,
> so we should probably make sure that lands and then rebase this ontop.
>
Yep, Will rebase on top of it.

>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> ---
>> Tested this patch for MPP and IRQ functionality on IFC6410 and SD600 EVAL
>> board with mpps PM8821 and PM8921.
>>
>>  .../devicetree/bindings/mfd/qcom-pm8xxx.txt        |   1 +
>>  drivers/mfd/pm8921-core.c                          | 368 +++++++++++++++++++--
>>  2 files changed, 340 insertions(+), 29 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
>> index 37a088f..8f1b4ec 100644
>> --- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
>> +++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
>> @@ -11,6 +11,7 @@ voltages and other various functionality to Qualcomm SoCs.
>>  	Definition: must be one of:
>>  		    "qcom,pm8058"
>>  		    "qcom,pm8921"
>> +		    "qcom,pm8821"
>>
>>  - #address-cells:
>>  	Usage: required
>> diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
>> index 0e3a2ea..28c2470 100644
>> --- a/drivers/mfd/pm8921-core.c
>> +++ b/drivers/mfd/pm8921-core.c
>> @@ -28,16 +28,26 @@
>>  #include <linux/mfd/core.h>
>>
>>  #define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
>> -
>> -#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
>> -#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
>> -#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
>> -#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
>> -#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
>> -#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
>> -#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
>> -#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
>> -#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
>
> Keep these (per argumentation that follows), but try to name them
> appropriately.
>
Yes, I agree, I will address all the comments related to register 
defines in next version.
...
>
>>
>>  #define	PM_IRQF_LVL_SEL			0x01	/* level select */
>>  #define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
>> @@ -54,30 +64,41 @@
>>  #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
>>
>>  #define PM8921_NR_IRQS		256
>> +#define PM8821_NR_IRQS		112
>>
>>  struct pm_irq_chip {
>>  	struct regmap		*regmap;
>>  	spinlock_t		pm_irq_lock;
>>  	struct irq_domain	*irqdomain;
>> +	unsigned int		irq_reg_base;
>>  	unsigned int		num_irqs;
>>  	unsigned int		num_blocks;
>>  	unsigned int		num_masters;
>>  	u8			config[0];
>>  };
>>
>> +struct pm8xxx_data {
>> +	int num_irqs;
>> +	unsigned int		irq_reg_base;
>
> As far as I can see this is always SSBI_PM8821_REG_ADDR_IRQ_BASE in the
> 8821 functions and SSBI_REG_ADDR_IRQ_BASE in the pm8xxx functions. If
> you have disjunct code paths I think it's better to not obscure this
> with a variable.
>
> Try renaming the constants appropriately instead. This also has the
> benefit of reducing the size of the patch slightly.
>
Yep, will remove reg_base variable.

>>

...
>>
>> +static int pm8821_read_master_irq(const struct pm_irq_chip *chip,
>> +				  int m, unsigned int *master)
>> +{
>
> I think you should inline this, as you already have the calls unrolled
> in pm8821_irq_handler().

We can just call regmap_read directly from the caller function, and get 
rid of this function all together.
>
>> +	unsigned int base;
>> +
>> +	if (!m)
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
>> +	else
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
>> +
>> +	return regmap_read(chip->regmap, base, master);
>> +}
>> +
>> +static int pm8821_read_block_irq(struct pm_irq_chip *chip, int master,
>> +				 u8 block, unsigned int *bits)
>> +{
>> +	int rc;
>> +
>> +	unsigned int base;
>
> Odd empty line between rc and base. (And btw, sorting your local
> variables in descending length make things pretty).
Yep, will fix it in next version.

>
>> +
>> +	if (!master)
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
>> +	else
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
>> +
>> +	spin_lock(&chip->pm_irq_lock);
>
> The reason why this is done under a lock in the other case is because
> the status register is paged, so you shouldn't need it here.
>
Thanks for the info, will remove it.

> With this updated I think you can favorably inline this into
> pm8821_irq_block_handler().
>
>> +
>> +	rc = regmap_read(chip->regmap, base + block, bits);
>> +	if (rc)
>> +		pr_err("Failed Reading Status rc=%d\n", rc);
>> +
>> +	spin_unlock(&chip->pm_irq_lock);
>> +	return rc;
>> +}
>> +
>> +static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
>> +				    int master_number, int block)
>> +{
>> +	int pmirq, irq, i, ret;
>> +	unsigned int bits;
>> +
>> +	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
>> +	if (ret) {
>> +		pr_err("Failed reading %d block ret=%d", block, ret);
>> +		return ret;
>> +	}
>> +	if (!bits) {
>> +		pr_err("block bit set in master but no irqs: %d", block);
>> +		return 0;
>> +	}
>> +
>> +	/* Convert block offset to global block number */
>> +	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
>
> So this is block -= 1 for master 0 and block += 6 for master 1, is the
> latter correct?
>
Yes, both of them are correct.

for master 0 which has block numbers from 1-7 should translate to 0-6 in 
linear space.
for master 1 which has block numbers from 1-7 should translate to 7-13 
in linear space.

so for master0 it is -=1 and and for master1 it is +=6 seems correct.

>> +
>> +	/* Check IRQ bits */
>> +	for (i = 0; i < 8; i++) {
>> +		if (bits & BIT(i)) {
>> +			pmirq = block * 8 + i;
>> +			irq = irq_find_mapping(chip->irqdomain, pmirq);
>> +			generic_handle_irq(irq);
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int pm8821_irq_read_master(struct pm_irq_chip *chip,
>> +				int master_number, u8 master_val)
>
> This isn't so much a matter of "reading master X" as "handle master X".
>
Agreed, it would be more consistent with pm8xxx too.
> Also, you don't care about the return value, so no need to return one...
>
Yep will fix it.
>> +{
>> +	int ret = 0;
>> +	int block;
>> +
>> +	for (block = 1; block < 8; block++) {
>> +		if (master_val & BIT(block)) {
>> +			ret |= pm8821_irq_block_handler(chip,
>> +					master_number, block);
>> +		}
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static void pm8821_irq_handler(struct irq_desc *desc)
>> +{
>> +	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
>> +	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
>> +	int ret;
>> +	unsigned int master;
>> +
>> +	chained_irq_enter(irq_chip, desc);
>> +	/* check master 0 */
>> +	ret = pm8821_read_master_irq(chip, 0, &master);
>> +	if (ret) {
>> +		pr_err("Failed to re:Qad master 0 ret=%d\n", ret);
>> +		return;
>> +	}
>> +
>> +	if (master & ~PM8821_IRQ_MASTER1_SET)
>
> Rather than having a define for MASTER1_SET use BIT(0) here and write a
> comment like:
>
Yep, I will add some comments in this area.
> "bits 1 through 7 marks the first 7 blocks"
>
>> +		pm8821_irq_read_master(chip, 0, master);
>> +
>
> and then
>
> "bit 0 is set if second master contains any bits"
>
> Or just skip this optimization and check the two masters unconditionally
> in a loop.
>
>> +	/* check master 1 */
>> +	if (!(master & PM8821_IRQ_MASTER1_SET))
>> +		goto done;
>> +
>> +	ret = pm8821_read_master_irq(chip, 1, &master);
>> +	if (ret) {
>> +		pr_err("Failed to read master 1 ret=%d\n", ret);
>> +		return;
>> +	}
>> +
>> +	pm8821_irq_read_master(chip, 1, master);
>> +
>> +done:
>> +	chained_irq_exit(irq_chip, desc);
>> +}
>> +
>>  static void pm8xxx_irq_mask_ack(struct irq_data *d)
>>  {
>>  	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
>> @@ -254,13 +394,15 @@ static int pm8xxx_irq_get_irqchip_state(struct irq_data *d,
>>  	irq_bit = pmirq % 8;
>>
>>  	spin_lock(&chip->pm_irq_lock);
>> -	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
>> +	rc = regmap_write(chip->regmap, chip->irq_reg_base +
>> +			  SSBI_REG_ADDR_IRQ_BLK_SEL, block);
>>  	if (rc) {
>>  		pr_err("Failed Selecting Block %d rc=%d\n", block, rc);
>>  		goto bail;
>>  	}
>>
>> -	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
>> +	rc = regmap_read(chip->regmap, chip->irq_reg_base +
>> +			 SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
>>  	if (rc) {
>>  		pr_err("Failed Reading Status rc=%d\n", rc);
>>  		goto bail;
>> @@ -299,6 +441,151 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
>>  	.map = pm8xxx_irq_domain_map,
>>  };
>>
>> +static void pm8821_irq_mask_ack(struct irq_data *d)
>> +{
>> +	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
>> +	unsigned int base, pmirq = irqd_to_hwirq(d);
>> +	u8 block, master;
>> +	int irq_bit, rc;
>> +
>> +	block = pmirq / 8;
>> +	master = block / PM8821_BLOCKS_PER_MASTER;
>> +	irq_bit = pmirq % 8;
>> +	block %= PM8821_BLOCKS_PER_MASTER;
>
> You can deobfuscate this somewhat by instead of testing for !master
> below you just do:
>
> if (block < PM8821_BLOCKS_PER_MASTER) {
> 	base =
> } else {
> 	base =
> 	block -= PM8821_BLOCKS_PER_MASTER;
> }
>
Done some cleanup in register defines which avoids this totally.
>> +
>> +	if (!master)
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
>> +	else
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
>> +
>> +	spin_lock(&chip->pm_irq_lock);
>
> The irqchip code grabs a lock on the irq_desc, so this can't race with
> unmask - and the regmap_update_bits() is internally protecting the
> read/write cycle.
>
> So you shouldn't need to lock around this section.
>
Yep.
>> +	rc = regmap_update_bits(chip->regmap,
>> +				base + PM8821_IRQ_MASK_REG_OFFSET + block,
>> +				BIT(irq_bit), BIT(irq_bit));
>> +
>> +	if (rc) {
>> +		pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
>> +		goto fail;
>> +	}
>> +
>> +	rc = regmap_update_bits(chip->regmap,
>> +				base + PM8821_IRQ_CLEAR_OFFSET + block,
>> +				BIT(irq_bit), BIT(irq_bit));
>> +
>> +	if (rc) {
>> +		pr_err("Failed to read/write IT_CLEAR IRQ:%d rc=%d\n",
>> +								pmirq, rc);
>> +	}
>> +
>> +fail:
>> +	spin_unlock(&chip->pm_irq_lock);
>> +}
>> +
>> +static void pm8821_irq_unmask(struct irq_data *d)
>> +{
>> +	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
>> +	unsigned int base, pmirq = irqd_to_hwirq(d);
>> +	int irq_bit, rc;
>> +	u8 block, master;
>> +
>> +	block = pmirq / 8;
>> +	master = block / PM8821_BLOCKS_PER_MASTER;
>> +	irq_bit = pmirq % 8;
>> +	block %= PM8821_BLOCKS_PER_MASTER;
>
> As mask().
>
>> +
>> +	if (!master)
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
>> +	else
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
>> +
>> +	spin_lock(&chip->pm_irq_lock);
>
> As mask().
>
>> +
>> +	rc = regmap_update_bits(chip->regmap,
>> +				base + PM8821_IRQ_MASK_REG_OFFSET + block,
>> +				BIT(irq_bit), ~BIT(irq_bit));
>> +
>> +	if (rc)
>> +		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
>> +
>> +	spin_unlock(&chip->pm_irq_lock);
>> +}
>> +
>> +static int pm8821_irq_set_type(struct irq_data *d, unsigned int flow_type)
>> +{
>> +
>> +	/*
>> +	 * PM8821 IRQ controller does not have explicit software support for
>> +	 * IRQ flow type.
>> +	 */
>
> Is returning "success" here the right thing to do? Shouldn't we just
> omit the function? Or did you perhaps hit some clients that wouldn't
> deal with that?
>
Will remove this totally.
>> +	return 0;
>> +}
>> +
>> +static int pm8821_irq_get_irqchip_state(struct irq_data *d,
>> +					enum irqchip_irq_state which,
>> +					bool *state)
>> +{
>> +	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
>> +	int pmirq, rc;
>> +	u8 block, irq_bit, master;
>> +	unsigned int bits;
>> +	unsigned int base;
>> +	unsigned long flags;
>> +
>> +	pmirq = irqd_to_hwirq(d);
>> +
>> +	block = pmirq / 8;
>> +	master = block / PM8821_BLOCKS_PER_MASTER;
>> +	irq_bit = pmirq % 8;
>> +	block %= PM8821_BLOCKS_PER_MASTER;
>> +
>
> Simplify as in mask().
taken care by new register defines.
>
>> +	if (!master)
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER0;
>> +	else
>> +		base = chip->irq_reg_base + SSBI_REG_ADDR_IRQ_MASTER1;
>> +
>> +	spin_lock_irqsave(&chip->pm_irq_lock, flags);
>
> No need to lock here as we're just reading a single register.
>
yep done.

>> +
>> +	rc = regmap_read(chip->regmap,
>> +		base + PM8821_IRQ_RT_STATUS_OFFSET + block, &bits);
>> +	if (rc) {
>> +		pr_err("Failed Reading Status rc=%d\n", rc);
>> +		goto bail_out;
>> +	}
>> +
>> +	*state = !!(bits & BIT(irq_bit));
>> +
>> +bail_out:
>> +	spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
>> +
>> +	return rc;
>> +}
>> +
>> +static struct irq_chip pm8821_irq_chip = {
>> +	.name		= "pm8821",
>> +	.irq_mask_ack	= pm8821_irq_mask_ack,
>> +	.irq_unmask	= pm8821_irq_unmask,
>> +	.irq_set_type	= pm8821_irq_set_type,
>> +	.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
>> +	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
>> +};
>> +
>
> Regards,
> Bjorn
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2 1/2] mfd: pm8xxx: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:52 UTC (permalink / raw)
  To: Lee Jones
  Cc: bjorn.andersson, Rob Herring, Andy Gross, devicetree,
	linux-kernel, linux-arm-msm, linux-soc, linux-arm-kernel,
	Srinivas Kandagatla

This patch adds support to PM8821 PMIC and interrupt support.
PM8821 is companion device that supplements primary PMIC PM8921 IC.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Acked-by: Rob Herring <robh@kernel.org>
---
Changes from v1:
	- Removed unnessary locking spotted by Bjorn
	- updated register naming to reflect PM8821
	- lot of cleanups suggested by Bjorn
	- rebased on top of Linus Walleij's pm8xxx namespace
	 cleanup patch. 

 .../devicetree/bindings/mfd/qcom-pm8xxx.txt        |   1 +
 drivers/mfd/qcom-pm8xxx.c                          | 247 ++++++++++++++++++++-
 2 files changed, 238 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
index 37a088f..8f1b4ec 100644
--- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
@@ -11,6 +11,7 @@ voltages and other various functionality to Qualcomm SoCs.
 	Definition: must be one of:
 		    "qcom,pm8058"
 		    "qcom,pm8921"
+		    "qcom,pm8821"
 
 - #address-cells:
 	Usage: required
diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c
index 7f9620e..dc347d3 100644
--- a/drivers/mfd/qcom-pm8xxx.c
+++ b/drivers/mfd/qcom-pm8xxx.c
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/ssbi.h>
 #include <linux/regmap.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/mfd/core.h>
 
@@ -39,6 +40,20 @@
 #define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
 #define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
 
+#define	PM8821_SSBI_REG_ADDR_IRQ_BASE	0x100
+#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
+#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
+#define	PM8821_SSBI_REG(m, b, offset) \
+			((m == 0) ? \
+			(PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
+			(PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
+#define	PM8821_SSBI_ADDR_IRQ_ROOT(m, b)		PM8821_SSBI_REG(m, b, 0x0)
+#define	PM8821_SSBI_ADDR_IRQ_CLEAR(m, b)	PM8821_SSBI_REG(m, b, 0x01)
+#define	PM8821_SSBI_ADDR_IRQ_MASK(m, b)		PM8821_SSBI_REG(m, b, 0x08)
+#define	PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b)	PM8821_SSBI_REG(m, b, 0x0f)
+
+#define	PM8821_BLOCKS_PER_MASTER	7
+
 #define	PM_IRQF_LVL_SEL			0x01	/* level select */
 #define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
 #define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
@@ -54,6 +69,7 @@
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
 #define PM8XXX_NR_IRQS		256
+#define PM8821_NR_IRQS		112
 
 struct pm_irq_chip {
 	struct regmap		*regmap;
@@ -65,6 +81,12 @@ struct pm_irq_chip {
 	u8			config[0];
 };
 
+struct pm_irq_data {
+	int num_irqs;
+	const struct irq_domain_ops  *irq_domain_ops;
+	void (*irq_handler)(struct irq_desc *desc);
+};
+
 static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
 				 unsigned int *ip)
 {
@@ -182,6 +204,84 @@ static void pm8xxx_irq_handler(struct irq_desc *desc)
 	chained_irq_exit(irq_chip, desc);
 }
 
+static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
+				     int master, int block)
+{
+	int pmirq, irq, i, ret;
+	unsigned int bits;
+
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
+	if (ret) {
+		pr_err("Failed reading %d block ret=%d", block, ret);
+		return;
+	}
+	if (!bits) {
+		pr_err("block bit set in master but no irqs: %d", block);
+		return;
+	}
+
+	/* Convert block offset to global block number */
+	block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
+
+	/* Check IRQ bits */
+	for (i = 0; i < 8; i++) {
+		if (bits & BIT(i)) {
+			pmirq = block * 8 + i;
+			irq = irq_find_mapping(chip->irqdomain, pmirq);
+			generic_handle_irq(irq);
+		}
+	}
+
+}
+
+static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
+					     int master, u8 master_val)
+{
+	int block;
+
+	for (block = 1; block < 8; block++)
+		if (master_val & BIT(block))
+			pm8821_irq_block_handler(chip, master, block);
+
+}
+
+static void pm8821_irq_handler(struct irq_desc *desc)
+{
+	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+	unsigned int master;
+	int ret;
+
+	chained_irq_enter(irq_chip, desc);
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
+	if (ret) {
+		pr_err("Failed to re:Qad master 0 ret=%d\n", ret);
+		return;
+	}
+
+	 /* bits 1 through 7 marks the first 7 blocks in master 0*/
+	if (master & GENMASK(7, 1))
+		pm8821_irq_master_handler(chip, 0, master);
+
+	 /* bit 0 marks if master 1 contains any bits */
+	if (!(master & BIT(0)))
+		goto done;
+
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
+	if (ret) {
+		pr_err("Failed to read master 1 ret=%d\n", ret);
+		return;
+	}
+
+	pm8821_irq_master_handler(chip, 1, master);
+
+done:
+	chained_irq_exit(irq_chip, desc);
+}
+
 static void pm8xxx_irq_mask_ack(struct irq_data *d)
 {
 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
@@ -299,6 +399,110 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
 	.map = pm8xxx_irq_domain_map,
 };
 
+static void pm8821_irq_mask_ack(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	u8 block, master;
+	int irq_bit, rc;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+				BIT(irq_bit), BIT(irq_bit));
+
+	if (rc) {
+		pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
+		return;
+	}
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
+				BIT(irq_bit), BIT(irq_bit));
+
+	if (rc) {
+		pr_err("Failed to read/write IT_CLEAR IRQ:%d rc=%d\n",
+								pmirq, rc);
+	}
+
+}
+
+static void pm8821_irq_unmask(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	int irq_bit, rc;
+	u8 block, master;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+				BIT(irq_bit), ~BIT(irq_bit));
+
+	if (rc)
+		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
+
+}
+
+static int pm8821_irq_get_irqchip_state(struct irq_data *d,
+					enum irqchip_irq_state which,
+					bool *state)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	int rc, pmirq = irqd_to_hwirq(d);
+	u8 block, irq_bit, master;
+	unsigned int bits;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_read(chip->regmap,
+		PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
+	if (rc) {
+		pr_err("Failed Reading Status rc=%d\n", rc);
+		return rc;
+	}
+
+	*state = !!(bits & BIT(irq_bit));
+
+	return rc;
+}
+
+static struct irq_chip pm8821_irq_chip = {
+	.name		= "pm8821",
+	.irq_mask_ack	= pm8821_irq_mask_ack,
+	.irq_unmask	= pm8821_irq_unmask,
+	.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				   irq_hw_number_t hwirq)
+{
+	struct pm_irq_chip *chip = d->host_data;
+
+	irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq);
+	irq_set_chip_data(irq, chip);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops pm8821_irq_domain_ops = {
+	.xlate = irq_domain_xlate_twocell,
+	.map = pm8821_irq_domain_map,
+};
+
 static const struct regmap_config ssbi_regmap_config = {
 	.reg_bits = 16,
 	.val_bits = 8,
@@ -308,22 +512,44 @@ static const struct regmap_config ssbi_regmap_config = {
 	.reg_write = ssbi_reg_write
 };
 
+static const struct pm_irq_data pm8xxx_data = {
+	.num_irqs = PM8XXX_NR_IRQS,
+	.irq_domain_ops = &pm8xxx_irq_domain_ops,
+	.irq_handler = pm8xxx_irq_handler,
+};
+
+static const struct pm_irq_data pm8821_data = {
+	.num_irqs = PM8821_NR_IRQS,
+	.irq_domain_ops = &pm8821_irq_domain_ops,
+	.irq_handler = pm8821_irq_handler,
+};
+
 static const struct of_device_id pm8xxx_id_table[] = {
-	{ .compatible = "qcom,pm8018", },
-	{ .compatible = "qcom,pm8058", },
-	{ .compatible = "qcom,pm8921", },
+	{ .compatible = "qcom,pm8018", .data = &pm8xxx_data},
+	{ .compatible = "qcom,pm8058", .data = &pm8xxx_data},
+	{ .compatible = "qcom,pm8821", .data = &pm8821_data},
+	{ .compatible = "qcom,pm8921", .data = &pm8xxx_data},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
 
 static int pm8xxx_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *match;
+	const struct pm_irq_data *data;
 	struct regmap *regmap;
 	int irq, rc;
 	unsigned int val;
 	u32 rev;
 	struct pm_irq_chip *chip;
-	unsigned int nirqs = PM8XXX_NR_IRQS;
+
+	match = of_match_node(pm8xxx_id_table, pdev->dev.of_node);
+	if (!match) {
+		dev_err(&pdev->dev, "No matching driver data found\n");
+		return -EINVAL;
+	}
+
+	data = match->data;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
@@ -354,25 +580,26 @@ static int pm8xxx_probe(struct platform_device *pdev)
 	rev |= val << BITS_PER_BYTE;
 
 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
-					sizeof(chip->config[0]) * nirqs,
-					GFP_KERNEL);
+			    sizeof(chip->config[0]) * data->num_irqs,
+			    GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
 	platform_set_drvdata(pdev, chip);
 	chip->regmap = regmap;
-	chip->num_irqs = nirqs;
+	chip->num_irqs = data->num_irqs;
 	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
 	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
 	spin_lock_init(&chip->pm_irq_lock);
 
-	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
-						&pm8xxx_irq_domain_ops,
+	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
+						data->num_irqs,
+						data->irq_domain_ops,
 						chip);
 	if (!chip->irqdomain)
 		return -ENODEV;
 
-	irq_set_chained_handler_and_data(irq, pm8xxx_irq_handler, chip);
+	irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
 	irq_set_irq_wake(irq, 1);
 
 	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
-- 
2.10.1

^ permalink raw reply related

* [PATCH v2 2/2] ARM: dts: apq8064: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:52 UTC (permalink / raw)
  To: Lee Jones
  Cc: bjorn.andersson, Rob Herring, Andy Gross, devicetree,
	linux-kernel, linux-arm-msm, linux-soc, linux-arm-kernel,
	Srinivas Kandagatla
In-Reply-To: <1479145933-9849-1-git-send-email-srinivas.kandagatla@linaro.org>

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 arch/arm/boot/dts/qcom-apq8064.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 268bd47..c61ba32 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -627,6 +627,33 @@
 			clock-names = "core";
 		};
 
+		ssbi@c00000 {
+			compatible = "qcom,ssbi";
+			reg = <0x00c00000 0x1000>;
+			qcom,controller-type = "pmic-arbiter";
+
+			pm8821: pmic@1 {
+				compatible = "qcom,pm8821";
+				interrupt-parent = <&tlmm_pinmux>;
+				interrupts = <76 IRQ_TYPE_LEVEL_LOW>;
+				#interrupt-cells = <2>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pm8821_mpps: mpps@50 {
+					compatible = "qcom,pm8821-mpp", "qcom,ssbi-mpp";
+					reg = <0x50>;
+					interrupts = <24 IRQ_TYPE_NONE>,
+						     <25 IRQ_TYPE_NONE>,
+						     <26 IRQ_TYPE_NONE>,
+						     <27 IRQ_TYPE_NONE>;
+					gpio-controller;
+					#gpio-cells = <2>;
+		                };
+			};
+		};
+
 		qcom,ssbi@500000 {
 			compatible = "qcom,ssbi";
 			reg = <0x00500000 0x1000>;
-- 
2.10.1

^ permalink raw reply related

* Re: [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Bjorn Andersson @ 2016-11-14 17:53 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Lee Jones, Rob Herring, Andy Gross,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <852fbb95-852e-0612-77a8-b0b072a68c51-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Mon 14 Nov 09:33 PST 2016, Srinivas Kandagatla wrote:

[..]
> >>+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
> >>+				    int master_number, int block)
> >>+{
> >>+	int pmirq, irq, i, ret;
> >>+	unsigned int bits;
> >>+
> >>+	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
> >>+	if (ret) {
> >>+		pr_err("Failed reading %d block ret=%d", block, ret);
> >>+		return ret;
> >>+	}
> >>+	if (!bits) {
> >>+		pr_err("block bit set in master but no irqs: %d", block);
> >>+		return 0;
> >>+	}
> >>+
> >>+	/* Convert block offset to global block number */
> >>+	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
> >
> >So this is block -= 1 for master 0 and block += 6 for master 1, is the
> >latter correct?
> >
> Yes, both of them are correct.
> 
> for master 0 which has block numbers from 1-7 should translate to 0-6 in
> linear space.
> for master 1 which has block numbers from 1-7 should translate to 7-13 in
> linear space.
> 
> so for master0 it is -=1 and and for master1 it is +=6 seems correct.
> 

Ahh, because block is 1-indexed when we enter, so have to switch base
and then calculate the global number, like:

  block = block - 1 + (master * PER_MASTER) + 7

but we cancel out the subtraction. I agree that this looks correct then.

I would prefer less of a mixture between 0-indexing and 1-indexing, but
I don't have any good ideas on how to restructure it to make it better.

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 1/2] can: holt_hi311x: document device tree bindings
From: Akshay Bhat @ 2016-11-14 17:55 UTC (permalink / raw)
  To: wg, mkl, robh+dt
  Cc: mark.rutland, linux-can, netdev, devicetree, linux-kernel,
	Akshay Bhat, Akshay Bhat

Document the HOLT HI-311x CAN device tree bindings.

Signed-off-by: Akshay Bhat <nodeax@gmail.com>
---
 .../devicetree/bindings/net/can/holt_hi311x.txt    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/can/holt_hi311x.txt

diff --git a/Documentation/devicetree/bindings/net/can/holt_hi311x.txt b/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
new file mode 100644
index 0000000..23aa94e
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
@@ -0,0 +1,24 @@
+* Holt HI-311X stand-alone CAN controller device tree bindings
+
+Required properties:
+ - compatible: Should be one of the following:
+   - "holt,hi3110" for HI-3110
+ - reg: SPI chip select.
+ - clocks: The clock feeding the CAN controller.
+ - interrupt-parent: The parent interrupt controller.
+ - interrupts: Should contain IRQ line for the CAN controller.
+
+Optional properties:
+ - vdd-supply: Regulator that powers the CAN controller.
+ - xceiver-supply: Regulator that powers the CAN transceiver.
+
+Example:
+	can0: can@1 {
+		compatible = "holt,hi3110";
+		reg = <1>;
+		clocks = <&clk32m>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <13 IRQ_TYPE_EDGE_RISING>;
+		vdd-supply = <&reg5v0>;
+		xceiver-supply = <&reg5v0>;
+	};
-- 
2.8.1

^ permalink raw reply related

* [PATCH 2/2] can: spi: hi311x: Add Holt HI-311x CAN driver
From: Akshay Bhat @ 2016-11-14 17:55 UTC (permalink / raw)
  To: wg, mkl, robh+dt
  Cc: mark.rutland, linux-can, netdev, devicetree, linux-kernel,
	Akshay Bhat, Akshay Bhat
In-Reply-To: <1479146144-29143-1-git-send-email-akshay.bhat@timesys.com>

This patch adds support for the Holt HI-311x CAN controller. The HI311x
CAN controller is capable of transmitting and receiving standard data
frames, extended data frames and remote frames. The HI311x interfaces
with the host over SPI.

Datasheet: www.holtic.com/documents/371-hi-3110_v-rev-jpdf.do

Signed-off-by: Akshay Bhat <nodeax@gmail.com>
---
 drivers/net/can/spi/Kconfig  |    6 +
 drivers/net/can/spi/Makefile |    1 +
 drivers/net/can/spi/hi311x.c | 1071 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1078 insertions(+)
 create mode 100644 drivers/net/can/spi/hi311x.c

diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig
index 148cae5..9eb1bb1 100644
--- a/drivers/net/can/spi/Kconfig
+++ b/drivers/net/can/spi/Kconfig
@@ -7,4 +7,10 @@ config CAN_MCP251X
 	---help---
 	  Driver for the Microchip MCP251x SPI CAN controllers.
 
+config CAN_HI311X
+	tristate "Holt HI311x SPI CAN controllers"
+	depends on CAN_DEV && SPI && HAS_DMA
+	---help---
+	  Driver for the Holt HI311x SPI CAN controllers.
+
 endmenu
diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile
index 0e86040..eac7c3a 100644
--- a/drivers/net/can/spi/Makefile
+++ b/drivers/net/can/spi/Makefile
@@ -4,3 +4,4 @@
 
 
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
+obj-$(CONFIG_CAN_HI311X)	+= hi311x.o
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
new file mode 100644
index 0000000..1020166
--- /dev/null
+++ b/drivers/net/can/spi/hi311x.c
@@ -0,0 +1,1071 @@
+/* CAN bus driver for Holt HI3110 CAN Controller with SPI Interface
+ *
+ * Based on Microchip 251x CAN Controller (mcp251x) Linux kernel driver
+ *
+ * Copyright(C) Timesys Corporation 2016
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/can/core.h>
+#include <linux/can/dev.h>
+#include <linux/can/led.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/freezer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/uaccess.h>
+
+#define HI3110_MASTER_RESET        0x56
+#define HI3110_READ_CTRL0          0xD2
+#define HI3110_READ_CTRL1          0xD4
+#define HI3110_READ_STATF          0xE2
+#define HI3110_WRITE_CTRL0         0x14
+#define HI3110_WRITE_CTRL1         0x16
+#define HI3110_WRITE_INTE          0x1C
+#define HI3110_WRITE_BTR0          0x18
+#define HI3110_WRITE_BTR1          0x1A
+#define HI3110_READ_BTR0           0xD6
+#define HI3110_READ_BTR1           0xD8
+#define HI3110_READ_INTF           0xDE
+#define HI3110_READ_ERR            0xDC
+#define HI3110_READ_FIFO_WOTIME    0x48
+#define HI3110_WRITE_FIFO          0x12
+#define HI3110_READ_MESSTAT        0xDA
+#define HI3110_READ_TEC            0xEC
+
+#define HI3110_CTRL0_MODE_MASK     (7 << 5)
+#define HI3110_CTRL0_NORMAL_MODE   (0 << 5)
+#define HI3110_CTRL0_LOOPBACK_MODE (1 << 5)
+#define HI3110_CTRL0_MONITOR_MODE  (2 << 5)
+#define HI3110_CTRL0_SLEEP_MODE    (3 << 5)
+#define HI3110_CTRL0_INIT_MODE     (4 << 5)
+
+#define HI3110_CTRL1_TXEN          BIT(7)
+
+#define HI3110_INT_RXTMP           BIT(7)
+#define HI3110_INT_RXFIFO          BIT(6)
+#define HI3110_INT_TXCPLT          BIT(5)
+#define HI3110_INT_BUSERR          BIT(4)
+#define HI3110_INT_MCHG            BIT(3)
+#define HI3110_INT_WAKEUP          BIT(2)
+#define HI3110_INT_F1MESS          BIT(1)
+#define HI3110_INT_F0MESS          BIT(0)
+
+#define HI3110_ERR_BUSOFF          BIT(7)
+#define HI3110_ERR_TXERRP          BIT(6)
+#define HI3110_ERR_RXERRP          BIT(5)
+#define HI3110_ERR_BITERR          BIT(4)
+#define HI3110_ERR_FRMERR          BIT(3)
+#define HI3110_ERR_CRCERR          BIT(2)
+#define HI3110_ERR_ACKERR          BIT(1)
+#define HI3110_ERR_STUFERR         BIT(0)
+#define HI3110_ERR_PROTOCOL_MASK   (0x1F)
+
+#define HI3110_STAT_RXFMTY         BIT(1)
+
+#define HI3110_BTR0_SJW_SHIFT      6
+#define HI3110_BTR0_BRP_SHIFT      0
+
+#define HI3110_BTR1_SAMP_3PERBIT   (1 << 7)
+#define HI3110_BTR1_SAMP_1PERBIT   (0 << 7)
+#define HI3110_BTR1_TSEG2_SHIFT    4
+#define HI3110_BTR1_TSEG1_SHIFT    0
+
+#define HI3110_FIFO_WOTIME_TAG_OFF 0
+#define HI3110_FIFO_WOTIME_ID_OFF  1
+#define HI3110_FIFO_WOTIME_DLC_OFF 5
+#define HI3110_FIFO_WOTIME_DAT_OFF 6
+
+#define HI3110_FIFO_WOTIME_TAG_IDE BIT(7)
+#define HI3110_FIFO_WOTIME_ID_RTR  BIT(0)
+
+#define HI3110_FIFO_TAG_OFF        0
+#define HI3110_FIFO_ID_OFF         1
+#define HI3110_FIFO_STD_DLC_OFF    3
+#define HI3110_FIFO_STD_DATA_OFF   4
+#define HI3110_FIFO_EXT_DLC_OFF    5
+#define HI3110_FIFO_EXT_DATA_OFF   6
+
+#define CAN_FRAME_MAX_DATA_LEN 8
+#define RX_BUF_LEN             15
+#define TX_STD_BUF_LEN         12
+#define TX_EXT_BUF_LEN         14
+#define CAN_FRAME_MAX_BITS     128
+
+#define TX_ECHO_SKB_MAX	1
+
+#define HI3110_OST_DELAY_MS (10)
+
+#define DEVICE_NAME "hi3110"
+
+static int hi3110_enable_dma = 1; /* Enable SPI DMA. Default: 1 (On) */
+module_param(hi3110_enable_dma, int, 0444);
+MODULE_PARM_DESC(hi3110_enable_dma, "Enable SPI DMA. Default: 1 (On)");
+
+static const struct can_bittiming_const hi3110_bittiming_const = {
+	.name = DEVICE_NAME,
+	.tseg1_min = 2,
+	.tseg1_max = 16,
+	.tseg2_min = 2,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 64,
+	.brp_inc = 1,
+};
+
+enum hi3110_model {
+	CAN_HI3110_HI3110	= 0x3110,
+};
+
+struct hi3110_priv {
+	struct can_priv	   can;
+	struct net_device *net;
+	struct spi_device *spi;
+	enum hi3110_model model;
+
+	struct mutex hi3110_lock; /* SPI device lock */
+
+	u8 *spi_tx_buf;
+	u8 *spi_rx_buf;
+	dma_addr_t spi_tx_dma;
+	dma_addr_t spi_rx_dma;
+
+	struct sk_buff *tx_skb;
+	int tx_len;
+
+	struct workqueue_struct *wq;
+	struct work_struct tx_work;
+	struct work_struct restart_work;
+
+	int force_quit;
+	int after_suspend;
+#define AFTER_SUSPEND_UP 1
+#define AFTER_SUSPEND_DOWN 2
+#define AFTER_SUSPEND_POWER 4
+#define AFTER_SUSPEND_RESTART 8
+	int restart_tx;
+	struct regulator *power;
+	struct regulator *transceiver;
+	struct clk *clk;
+};
+
+static void hi3110_clean(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+
+	if (priv->tx_skb || priv->tx_len)
+		net->stats.tx_errors++;
+	if (priv->tx_skb)
+		dev_kfree_skb(priv->tx_skb);
+	if (priv->tx_len)
+		can_free_echo_skb(priv->net, 0);
+	priv->tx_skb = NULL;
+	priv->tx_len = 0;
+}
+
+/* Note about handling of error return of hi3110_spi_trans: accessing
+ * registers via SPI is not really different conceptually than using
+ * normal I/O assembler instructions, although it's much more
+ * complicated from a practical POV. So it's not advisable to always
+ * check the return value of this function. Imagine that every
+ * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
+ * error();", it would be a great mess (well there are some situation
+ * when exception handling C++ like could be useful after all). So we
+ * just check that transfers are OK at the beginning of our
+ * conversation with the chip and to avoid doing really nasty things
+ * (like injecting bogus packets in the network stack).
+ */
+static int hi3110_spi_trans(struct spi_device *spi, int len)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct spi_transfer t = {
+		.tx_buf = priv->spi_tx_buf,
+		.rx_buf = priv->spi_rx_buf,
+		.len = len,
+		.cs_change = 0,
+	};
+	struct spi_message m;
+	int ret;
+
+	spi_message_init(&m);
+
+	if (hi3110_enable_dma) {
+		t.tx_dma = priv->spi_tx_dma;
+		t.rx_dma = priv->spi_rx_dma;
+		m.is_dma_mapped = 1;
+	}
+
+	spi_message_add_tail(&t, &m);
+
+	ret = spi_sync(spi, &m);
+
+	if (ret)
+		dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret);
+	return ret;
+}
+
+static u8 hi3110_cmd(struct spi_device *spi, uint8_t command)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = command;
+	dev_dbg(&spi->dev, "hi3110_cmd: %02X\n", command);
+
+	return hi3110_spi_trans(spi, 1);
+}
+
+static u8 hi3110_read(struct spi_device *spi, uint8_t command)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	u8 val = 0;
+
+	priv->spi_tx_buf[0] = command;
+	hi3110_spi_trans(spi, 2);
+	val = priv->spi_rx_buf[1];
+	dev_dbg(&spi->dev, "hi3110_read: %02X, %02X\n", command, val);
+
+	return val;
+}
+
+static void hi3110_write(struct spi_device *spi, u8 reg, uint8_t val)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = reg;
+	priv->spi_tx_buf[1] = val;
+	dev_dbg(&spi->dev, "hi3110_write: %02X, %02X\n", reg, val);
+
+	hi3110_spi_trans(spi, 2);
+}
+
+static void hi3110_hw_tx_frame(struct spi_device *spi, u8 *buf, int len)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = HI3110_WRITE_FIFO;
+	memcpy(priv->spi_tx_buf + 1, buf, len);
+	hi3110_spi_trans(spi, len + 1);
+}
+
+static void hi3110_hw_tx(struct spi_device *spi, struct can_frame *frame)
+{
+	u8 buf[TX_EXT_BUF_LEN];
+
+	buf[HI3110_FIFO_TAG_OFF] = 0;
+
+	if (frame->can_id & CAN_EFF_FLAG) {
+		/* Extended frame */
+		buf[HI3110_FIFO_ID_OFF] = (frame->can_id & CAN_EFF_MASK) >> 21;
+		buf[HI3110_FIFO_ID_OFF + 1] =
+			((((frame->can_id & CAN_EFF_MASK) >> 18) & 0x07) << 5) |
+			0x18 | /* Recessive SRR and IDE */
+			(((frame->can_id & CAN_EFF_MASK) >> 15) & 0x07);
+		buf[HI3110_FIFO_ID_OFF + 2] =
+			(frame->can_id & CAN_EFF_MASK) >> 7;
+		buf[HI3110_FIFO_ID_OFF + 3] =
+			((frame->can_id & CAN_EFF_MASK) << 1) |
+			((frame->can_id & CAN_RTR_FLAG) ? 1 : 0);
+
+		buf[HI3110_FIFO_EXT_DLC_OFF] = frame->can_dlc;
+
+		memcpy(buf + HI3110_FIFO_EXT_DATA_OFF,
+		       frame->data, frame->can_dlc);
+
+		hi3110_hw_tx_frame(spi, buf, TX_EXT_BUF_LEN -
+				   (CAN_FRAME_MAX_DATA_LEN - frame->can_dlc));
+	} else {
+		/* Standard frame */
+		buf[HI3110_FIFO_ID_OFF] =   (frame->can_id & CAN_SFF_MASK) >> 3;
+		buf[HI3110_FIFO_ID_OFF + 1] =
+			((frame->can_id & CAN_SFF_MASK) << 5) |
+			((frame->can_id & CAN_RTR_FLAG) ? (1 << 4) : 0);
+
+		buf[HI3110_FIFO_STD_DLC_OFF] = frame->can_dlc;
+
+		memcpy(buf + HI3110_FIFO_STD_DATA_OFF,
+		       frame->data, frame->can_dlc);
+
+		hi3110_hw_tx_frame(spi, buf, TX_STD_BUF_LEN -
+				   (CAN_FRAME_MAX_DATA_LEN - frame->can_dlc));
+	}
+}
+
+static void hi3110_hw_rx_frame(struct spi_device *spi, u8 *buf)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = HI3110_READ_FIFO_WOTIME;
+	hi3110_spi_trans(spi, RX_BUF_LEN);
+	memcpy(buf, priv->spi_rx_buf + 1, RX_BUF_LEN - 1);
+}
+
+static void hi3110_hw_rx(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct sk_buff *skb;
+	struct can_frame *frame;
+	u8 buf[RX_BUF_LEN - 1];
+
+	skb = alloc_can_skb(priv->net, &frame);
+	if (!skb) {
+		dev_err(&spi->dev, "cannot allocate RX skb\n");
+		priv->net->stats.rx_dropped++;
+		return;
+	}
+
+	hi3110_hw_rx_frame(spi, buf);
+	if (buf[HI3110_FIFO_WOTIME_TAG_OFF] & HI3110_FIFO_WOTIME_TAG_IDE) {
+		/* IDE is recessive (1), indicating extended 29-bit frame */
+		frame->can_id = CAN_EFF_FLAG;
+		frame->can_id |=
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF] << 21) |
+		 (((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0xE0) >> 5) << 18) |
+		 ((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0x07) << 15) |
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF + 2] << 7) |
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF + 3] >> 1);
+	} else {
+		/* IDE is dominant (0), frame indicating standard 11-bit */
+		frame->can_id =
+			(buf[HI3110_FIFO_WOTIME_ID_OFF] << 3) |
+			((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0xE0) >> 5);
+	}
+
+	if (buf[HI3110_FIFO_WOTIME_ID_OFF + 3] & HI3110_FIFO_WOTIME_ID_RTR) {
+		/* RTR is recessive (1), indicating remote request frame */
+		frame->can_id |= CAN_RTR_FLAG;
+	}
+
+	/* Data length */
+	frame->can_dlc = get_can_dlc(buf[HI3110_FIFO_WOTIME_DLC_OFF] & 0x0F);
+	memcpy(frame->data, buf + HI3110_FIFO_WOTIME_DAT_OFF, frame->can_dlc);
+
+	priv->net->stats.rx_packets++;
+	priv->net->stats.rx_bytes += frame->can_dlc;
+
+	can_led_event(priv->net, CAN_LED_EVENT_RX);
+
+	netif_rx_ni(skb);
+}
+
+static void hi3110_hw_sleep(struct spi_device *spi)
+{
+	hi3110_write(spi, HI3110_WRITE_CTRL0, HI3110_CTRL0_SLEEP_MODE);
+}
+
+static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb,
+					  struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	if (priv->tx_skb || priv->tx_len) {
+		dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
+		return NETDEV_TX_BUSY;
+	}
+
+	if (can_dropped_invalid_skb(net, skb))
+		return NETDEV_TX_OK;
+
+	netif_stop_queue(net);
+	priv->tx_skb = skb;
+	queue_work(priv->wq, &priv->tx_work);
+
+	return NETDEV_TX_OK;
+}
+
+static int hi3110_do_set_mode(struct net_device *net, enum can_mode mode)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+
+	switch (mode) {
+	case CAN_MODE_START:
+		hi3110_clean(net);
+		/* We have to delay work since SPI I/O may sleep */
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		priv->restart_tx = 1;
+		if (priv->can.restart_ms == 0)
+			priv->after_suspend = AFTER_SUSPEND_RESTART;
+		queue_work(priv->wq, &priv->restart_work);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int hi3110_set_normal_mode(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	u8 reg;
+
+	hi3110_write(spi, HI3110_WRITE_INTE, HI3110_INT_BUSERR |
+		     HI3110_INT_RXFIFO | HI3110_INT_TXCPLT);
+
+	/* Enable TX */
+	hi3110_write(spi, HI3110_WRITE_CTRL1, HI3110_CTRL1_TXEN);
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+		/* Put device into loopback mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_LOOPBACK_MODE);
+	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
+		/* Put device into listen-only mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_MONITOR_MODE);
+	} else {
+		/* Put device into normal mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_NORMAL_MODE);
+
+		/* Wait for the device to enter normal mode */
+		mdelay(HI3110_OST_DELAY_MS);
+		reg = hi3110_read(spi, HI3110_READ_CTRL0);
+		if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_NORMAL_MODE)
+			return -EBUSY;
+	}
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+	return 0;
+}
+
+static int hi3110_do_set_bittiming(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	struct spi_device *spi = priv->spi;
+
+	hi3110_write(spi, HI3110_WRITE_BTR0,
+		     ((bt->sjw - 1) << HI3110_BTR0_SJW_SHIFT) |
+		     ((bt->brp - 1) << HI3110_BTR0_BRP_SHIFT));
+
+	hi3110_write(spi, HI3110_WRITE_BTR1,
+		     (priv->can.ctrlmode &
+		     CAN_CTRLMODE_3_SAMPLES ?
+		     HI3110_BTR1_SAMP_3PERBIT : HI3110_BTR1_SAMP_1PERBIT) |
+		     ((bt->phase_seg1 + bt->prop_seg - 1)
+		     << HI3110_BTR1_TSEG1_SHIFT) |
+		     ((bt->phase_seg2 - 1) << HI3110_BTR1_TSEG2_SHIFT));
+
+	dev_dbg(&spi->dev, "BT: 0x%02x 0x%02x\n",
+		hi3110_read(spi, HI3110_READ_BTR0),
+		hi3110_read(spi, HI3110_READ_BTR1));
+
+	return 0;
+}
+
+static int hi3110_setup(struct net_device *net, struct hi3110_priv *priv,
+			struct spi_device *spi)
+{
+	hi3110_do_set_bittiming(net);
+	return 0;
+}
+
+static int hi3110_hw_reset(struct spi_device *spi)
+{
+	u8 reg;
+	int ret;
+
+	/* Wait for oscillator startup timer after power up */
+	mdelay(HI3110_OST_DELAY_MS);
+
+	ret = hi3110_cmd(spi, HI3110_MASTER_RESET);
+	if (ret)
+		return ret;
+
+	/* Wait for oscillator startup timer after reset */
+	mdelay(HI3110_OST_DELAY_MS);
+
+	reg = hi3110_read(spi, HI3110_READ_CTRL0);
+	if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_INIT_MODE)
+		return -ENODEV;
+
+	/* As per the datasheet it appears the error flags are
+	 * not cleared on reset. Explicitly clear them by performing a read
+	 */
+	hi3110_read(spi, HI3110_READ_ERR);
+
+	return 0;
+}
+
+static int hi3110_hw_probe(struct spi_device *spi)
+{
+	u8 statf;
+
+	hi3110_hw_reset(spi);
+
+	/* Confirm correct operation by checking against reset values
+	 * in datasheet
+	 */
+	statf = hi3110_read(spi, HI3110_READ_STATF);
+
+	dev_dbg(&spi->dev, "statf: %02X\n", statf);
+
+	if (statf != 0x82)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int hi3110_power_enable(struct regulator *reg, int enable)
+{
+	if (IS_ERR_OR_NULL(reg))
+		return 0;
+
+	if (enable)
+		return regulator_enable(reg);
+	else
+		return regulator_disable(reg);
+}
+
+static void hi3110_open_clean(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	free_irq(spi->irq, priv);
+	hi3110_hw_sleep(spi);
+	hi3110_power_enable(priv->transceiver, 0);
+	close_candev(net);
+}
+
+static int hi3110_stop(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	close_candev(net);
+
+	priv->force_quit = 1;
+	free_irq(spi->irq, priv);
+	destroy_workqueue(priv->wq);
+	priv->wq = NULL;
+
+	mutex_lock(&priv->hi3110_lock);
+
+	/* Disable transmit, interrupts and clear flags */
+	hi3110_write(spi, HI3110_WRITE_CTRL1, 0x0);
+	hi3110_write(spi, HI3110_WRITE_INTE, 0x0);
+	hi3110_read(spi, HI3110_READ_INTF);
+
+	hi3110_clean(net);
+
+	hi3110_hw_sleep(spi);
+
+	hi3110_power_enable(priv->transceiver, 0);
+
+	priv->can.state = CAN_STATE_STOPPED;
+
+	mutex_unlock(&priv->hi3110_lock);
+
+	can_led_event(net, CAN_LED_EVENT_STOP);
+
+	return 0;
+}
+
+static void hi3110_error_skb(struct net_device *net, int can_id,
+			     int data1, int data2)
+{
+	struct sk_buff *skb;
+	struct can_frame *frame;
+
+	skb = alloc_can_err_skb(net, &frame);
+	if (skb) {
+		frame->can_id |= can_id;
+		frame->data[1] = data1;
+		frame->data[2] = data2;
+		netif_rx_ni(skb);
+	} else {
+		netdev_err(net, "cannot allocate error skb\n");
+	}
+}
+
+static void hi3110_tx_work_handler(struct work_struct *ws)
+{
+	struct hi3110_priv *priv = container_of(ws, struct hi3110_priv,
+						 tx_work);
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+	struct can_frame *frame;
+
+	mutex_lock(&priv->hi3110_lock);
+	if (priv->tx_skb) {
+		if (priv->can.state == CAN_STATE_BUS_OFF) {
+			hi3110_clean(net);
+		} else {
+			frame = (struct can_frame *)priv->tx_skb->data;
+
+			if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN)
+				frame->can_dlc = CAN_FRAME_MAX_DATA_LEN;
+			hi3110_hw_tx(spi, frame);
+			priv->tx_len = 1 + frame->can_dlc;
+			can_put_echo_skb(priv->tx_skb, net, 0);
+			priv->tx_skb = NULL;
+		}
+	}
+	mutex_unlock(&priv->hi3110_lock);
+}
+
+static void hi3110_restart_work_handler(struct work_struct *ws)
+{
+	struct hi3110_priv *priv = container_of(ws, struct hi3110_priv,
+						 restart_work);
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+
+	mutex_lock(&priv->hi3110_lock);
+	if (priv->after_suspend) {
+		hi3110_hw_reset(spi);
+		hi3110_setup(net, priv, spi);
+		if (priv->after_suspend & AFTER_SUSPEND_RESTART) {
+			hi3110_set_normal_mode(spi);
+		} else if (priv->after_suspend & AFTER_SUSPEND_UP) {
+			netif_device_attach(net);
+			hi3110_clean(net);
+			hi3110_set_normal_mode(spi);
+			netif_wake_queue(net);
+		} else {
+			hi3110_hw_sleep(spi);
+		}
+		priv->after_suspend = 0;
+		priv->force_quit = 0;
+	}
+
+	if (priv->restart_tx) {
+		priv->restart_tx = 0;
+		hi3110_clean(net);
+		netif_wake_queue(net);
+		hi3110_error_skb(net, CAN_ERR_RESTARTED, 0, 0);
+	}
+	mutex_unlock(&priv->hi3110_lock);
+}
+
+static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
+{
+	struct hi3110_priv *priv = dev_id;
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+
+	mutex_lock(&priv->hi3110_lock);
+
+	while (!priv->force_quit) {
+		enum can_state new_state;
+		u8 intf;
+		u8 eflag;
+		int can_id = 0, data1 = 0, data2 = 0;
+
+		while (!(HI3110_STAT_RXFMTY &
+			hi3110_read(spi, HI3110_READ_STATF))) {
+			hi3110_hw_rx(spi);
+		};
+
+		intf = hi3110_read(spi, HI3110_READ_INTF);
+		eflag = hi3110_read(spi, HI3110_READ_ERR);
+		/* Update can state */
+		if (eflag & HI3110_ERR_BUSOFF) {
+			new_state = CAN_STATE_BUS_OFF;
+			can_id |= CAN_ERR_BUSOFF;
+		} else if (eflag & HI3110_ERR_TXERRP) {
+			new_state = CAN_STATE_ERROR_PASSIVE;
+			can_id |= CAN_ERR_CRTL;
+			data1 |= CAN_ERR_CRTL_TX_PASSIVE;
+		} else if (eflag & HI3110_ERR_RXERRP) {
+			new_state = CAN_STATE_ERROR_PASSIVE;
+			can_id |= CAN_ERR_CRTL;
+			data1 |= CAN_ERR_CRTL_RX_PASSIVE;
+		} else {
+			new_state = CAN_STATE_ERROR_ACTIVE;
+		}
+
+		/* Check for protocol errors */
+		if (eflag & HI3110_ERR_PROTOCOL_MASK) {
+			can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+			priv->can.can_stats.bus_error++;
+			priv->net->stats.rx_errors++;
+			if (eflag & HI3110_ERR_BITERR)
+				data2 |= CAN_ERR_PROT_BIT;
+			else if (eflag & HI3110_ERR_FRMERR)
+				data2 |= CAN_ERR_PROT_FORM;
+			else if (eflag & HI3110_ERR_STUFERR)
+				data2 |= CAN_ERR_PROT_STUFF;
+			else
+				data2 |= CAN_ERR_PROT_UNSPEC;
+		}
+
+		/* Update can state statistics */
+		switch (priv->can.state) {
+		case CAN_STATE_ERROR_ACTIVE:
+			if (new_state >= CAN_STATE_ERROR_WARNING &&
+			    new_state <= CAN_STATE_BUS_OFF)
+				priv->can.can_stats.error_warning++;
+		/* fallthrough */
+		case CAN_STATE_ERROR_WARNING:
+			if (new_state >= CAN_STATE_ERROR_PASSIVE &&
+			    new_state <= CAN_STATE_BUS_OFF)
+				priv->can.can_stats.error_passive++;
+			break;
+		default:
+			break;
+		}
+		priv->can.state = new_state;
+
+		if (intf & HI3110_INT_BUSERR) {
+			/* Note: HI3110 Does report overflow errors */
+			hi3110_error_skb(net, can_id, data1, data2);
+		}
+
+		if (priv->can.state == CAN_STATE_BUS_OFF) {
+			if (priv->can.restart_ms == 0) {
+				priv->force_quit = 1;
+				priv->can.can_stats.bus_off++;
+				can_bus_off(net);
+				hi3110_hw_sleep(spi);
+				break;
+			}
+		}
+
+		if (intf == 0)
+			break;
+
+		if (intf & HI3110_INT_TXCPLT) {
+			net->stats.tx_packets++;
+			net->stats.tx_bytes += priv->tx_len - 1;
+			can_led_event(net, CAN_LED_EVENT_TX);
+			if (priv->tx_len) {
+				can_get_echo_skb(net, 0);
+				priv->tx_len = 0;
+			}
+			netif_wake_queue(net);
+		}
+	}
+	mutex_unlock(&priv->hi3110_lock);
+	return IRQ_HANDLED;
+}
+
+static int hi3110_open(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+	unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING;
+	int ret;
+
+	ret = open_candev(net);
+	if (ret) {
+		dev_err(&spi->dev, "unable to set initial baudrate!\n");
+		return ret;
+	}
+
+	mutex_lock(&priv->hi3110_lock);
+	hi3110_power_enable(priv->transceiver, 1);
+
+	priv->force_quit = 0;
+	priv->tx_skb = NULL;
+	priv->tx_len = 0;
+
+	ret = request_threaded_irq(spi->irq, NULL, hi3110_can_ist,
+				   flags, DEVICE_NAME, priv);
+	if (ret) {
+		dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
+		hi3110_power_enable(priv->transceiver, 0);
+		close_candev(net);
+		goto open_unlock;
+	}
+
+	priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
+			   0);
+	INIT_WORK(&priv->tx_work, hi3110_tx_work_handler);
+	INIT_WORK(&priv->restart_work, hi3110_restart_work_handler);
+
+	ret = hi3110_hw_reset(spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	ret = hi3110_setup(net, priv, spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	ret = hi3110_set_normal_mode(spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	can_led_event(net, CAN_LED_EVENT_OPEN);
+	netif_wake_queue(net);
+
+open_unlock:
+	mutex_unlock(&priv->hi3110_lock);
+	return ret;
+}
+
+static const struct net_device_ops hi3110_netdev_ops = {
+	.ndo_open = hi3110_open,
+	.ndo_stop = hi3110_stop,
+	.ndo_start_xmit = hi3110_hard_start_xmit,
+};
+
+static const struct of_device_id hi3110_of_match[] = {
+	{
+		.compatible	= "holt,hi3110",
+		.data		= (void *)CAN_HI3110_HI3110,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hi3110_of_match);
+
+static const struct spi_device_id hi3110_id_table[] = {
+	{
+		.name		= "hi3110",
+		.driver_data	= (kernel_ulong_t)CAN_HI3110_HI3110,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, hi3110_id_table);
+
+static int hi3110_can_probe(struct spi_device *spi)
+{
+	const struct of_device_id *of_id = of_match_device(hi3110_of_match,
+							   &spi->dev);
+	struct net_device *net;
+	struct hi3110_priv *priv;
+	struct clk *clk;
+	int freq, ret;
+
+	clk = devm_clk_get(&spi->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&spi->dev, "no CAN clock source defined\n");
+		return PTR_ERR(clk);
+	}
+	freq = clk_get_rate(clk);
+
+	/* Sanity check */
+	if (freq > 40000000)
+		return -ERANGE;
+
+	/* Allocate can/net device */
+	net = alloc_candev(sizeof(struct hi3110_priv), TX_ECHO_SKB_MAX);
+	if (!net)
+		return -ENOMEM;
+
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		if (ret)
+			goto out_free;
+	}
+
+	net->netdev_ops = &hi3110_netdev_ops;
+	net->flags |= IFF_ECHO;
+
+	priv = netdev_priv(net);
+	priv->can.bittiming_const = &hi3110_bittiming_const;
+	priv->can.do_set_mode = hi3110_do_set_mode;
+	priv->can.clock.freq = freq / 2;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
+		CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
+	if (of_id)
+		priv->model = (enum hi3110_model)of_id->data;
+	else
+		priv->model = spi_get_device_id(spi)->driver_data;
+	priv->net = net;
+	priv->clk = clk;
+
+	spi_set_drvdata(spi, priv);
+
+	/* Configure the SPI bus */
+	spi->bits_per_word = 8;
+	ret = spi_setup(spi);
+	if (ret)
+		goto out_clk;
+
+	priv->power = devm_regulator_get_optional(&spi->dev, "vdd");
+	priv->transceiver = devm_regulator_get_optional(&spi->dev, "xceiver");
+	if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||
+	    (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {
+		ret = -EPROBE_DEFER;
+		goto out_clk;
+	}
+
+	ret = hi3110_power_enable(priv->power, 1);
+	if (ret)
+		goto out_clk;
+
+	priv->spi = spi;
+	mutex_init(&priv->hi3110_lock);
+
+	/* If requested, allocate DMA buffers */
+	if (hi3110_enable_dma) {
+		spi->dev.coherent_dma_mask = ~0;
+
+		/* Minimum coherent DMA allocation is PAGE_SIZE, so allocate
+		 * that much and share it between Tx and Rx DMA buffers.
+		 */
+		priv->spi_tx_buf = dmam_alloc_coherent(&spi->dev,
+						      PAGE_SIZE,
+						      &priv->spi_tx_dma,
+						      GFP_DMA);
+
+		if (priv->spi_tx_buf) {
+			priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2));
+			priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma +
+							(PAGE_SIZE / 2));
+		} else {
+			/* Fall back to non-DMA */
+			hi3110_enable_dma = 0;
+		}
+	}
+
+	/* Allocate non-DMA buffers */
+	if (!hi3110_enable_dma) {
+		priv->spi_tx_buf = devm_kzalloc(&spi->dev, RX_BUF_LEN,
+				GFP_KERNEL);
+		if (!priv->spi_tx_buf) {
+			ret = -ENOMEM;
+			goto error_probe;
+		}
+		priv->spi_rx_buf = devm_kzalloc(&spi->dev, RX_BUF_LEN,
+				GFP_KERNEL);
+
+		if (!priv->spi_rx_buf) {
+			ret = -ENOMEM;
+			goto error_probe;
+		}
+	}
+
+	SET_NETDEV_DEV(net, &spi->dev);
+
+	ret = hi3110_hw_probe(spi);
+	if (ret) {
+		if (ret == -ENODEV)
+			dev_err(&spi->dev, "Cannot initialize %x. Wrong wiring?\n",
+				priv->model);
+		goto error_probe;
+	}
+	hi3110_hw_sleep(spi);
+
+	ret = register_candev(net);
+	if (ret)
+		goto error_probe;
+
+	devm_can_led_init(net);
+	netdev_info(net, "%x successfully initialized.\n", priv->model);
+
+	return 0;
+
+error_probe:
+	hi3110_power_enable(priv->power, 0);
+
+out_clk:
+	if (!IS_ERR(clk))
+		clk_disable_unprepare(clk);
+
+out_free:
+	free_candev(net);
+
+	dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
+	return ret;
+}
+
+static int hi3110_can_remove(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct net_device *net = priv->net;
+
+	unregister_candev(net);
+
+	hi3110_power_enable(priv->power, 0);
+
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
+
+	free_candev(net);
+
+	return 0;
+}
+
+static int __maybe_unused hi3110_can_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct net_device *net = priv->net;
+
+	priv->force_quit = 1;
+	disable_irq(spi->irq);
+
+	/* Note: at this point neither IST nor workqueues are running.
+	 * open/stop cannot be called anyway so locking is not needed
+	 */
+	if (netif_running(net)) {
+		netif_device_detach(net);
+
+		hi3110_hw_sleep(spi);
+		hi3110_power_enable(priv->transceiver, 0);
+		priv->after_suspend = AFTER_SUSPEND_UP;
+	} else {
+		priv->after_suspend = AFTER_SUSPEND_DOWN;
+	}
+
+	if (!IS_ERR_OR_NULL(priv->power)) {
+		regulator_disable(priv->power);
+		priv->after_suspend |= AFTER_SUSPEND_POWER;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused hi3110_can_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	if (priv->after_suspend & AFTER_SUSPEND_POWER)
+		hi3110_power_enable(priv->power, 1);
+
+	if (priv->after_suspend & AFTER_SUSPEND_UP) {
+		hi3110_power_enable(priv->transceiver, 1);
+		queue_work(priv->wq, &priv->restart_work);
+	} else {
+		priv->after_suspend = 0;
+	}
+
+	priv->force_quit = 0;
+	enable_irq(spi->irq);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend,
+	hi3110_can_resume);
+
+static struct spi_driver hi3110_can_driver = {
+	.driver = {
+		.name = DEVICE_NAME,
+		.of_match_table = hi3110_of_match,
+		.pm = &hi3110_can_pm_ops,
+	},
+	.id_table = hi3110_id_table,
+	.probe = hi3110_can_probe,
+	.remove = hi3110_can_remove,
+};
+
+module_spi_driver(hi3110_can_driver);
+
+MODULE_AUTHOR("Akshay Bhat <akshay.bhat@timesys.com>");
+MODULE_AUTHOR("Casey Fitzpatrick <casey.fitzpatrick@timesys.com>");
+MODULE_DESCRIPTION("Holt HI-3110 CAN driver");
+MODULE_LICENSE("GPL v2");
-- 
2.8.1

^ permalink raw reply related

* Re: [PATCH] dt-bindings: Add Keith&Koep vendor prefix
From: Marek Vasut @ 2016-11-14 18:14 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA; +Cc: Rob Herring, Fabio Estevam, Shawn Guo
In-Reply-To: <20161114101217.3580-1-marex-ynQEQJNshbs@public.gmane.org>

On 11/14/2016 11:12 AM, Marek Vasut wrote:
> Add vendor prefix for Keith&Koep GmbH , http://keith-koep.com/en/
> 
> Signed-off-by: Marek Vasut <marex-ynQEQJNshbs@public.gmane.org>
> Cc: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
> Cc: Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

Please ignore, I see the patch was applied and the rebase didn't drop
it. Sorry for the noise.

-- 
Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 1/2] phy: rockchip-inno-usb2: correct clk_ops callback
From: Doug Anderson @ 2016-11-14 18:15 UTC (permalink / raw)
  To: William Wu
  Cc: Kishon Vijay Abraham I, Heiko Stübner,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	open list:ARM/Rockchip SoC...,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
	Frank Wang, 黄涛, Brian Norris, Guenter Roeck
In-Reply-To: <1479106911-16049-2-git-send-email-wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

William

On Sun, Nov 13, 2016 at 11:01 PM, William Wu <wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org> wrote:
> Since we needs to delay ~1ms to wait for 480MHz output clock
> of USB2 PHY to become stable after turn on it, the delay time
> is pretty long for something that's supposed to be "atomic"
> like a clk_enable(). Consider that clk_enable() will disable
> interrupt and that a 1ms interrupt latency is not sensible.
>
> The 480MHz output clock should be handled in prepare callbacks
> which support gate a clk if the operation may sleep.
>
> Signed-off-by: William Wu <wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> ---
>  drivers/phy/phy-rockchip-inno-usb2.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)

Reviewed-by: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 2/2] phy: rockchip-inno-usb2: correct 480MHz output clock stable time
From: Doug Anderson @ 2016-11-14 18:17 UTC (permalink / raw)
  To: William Wu
  Cc: Kishon Vijay Abraham I, Heiko Stübner,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	open list:ARM/Rockchip SoC..., devicetree@vger.kernel.org,
	Rob Herring, Frank Wang, 黄涛, Brian Norris,
	Guenter Roeck
In-Reply-To: <1479115631-20137-3-git-send-email-wulf@rock-chips.com>

William,

On Mon, Nov 14, 2016 at 1:27 AM, William Wu <wulf@rock-chips.com> wrote:
> We found that the system crashed due to 480MHz output clock of
> USB2 PHY was unstable after clock had been enabled by gpu module.
>
> Theoretically, 1 millisecond is a critical value for 480MHz
> output clock stable time, so we try to change the delay time
> to 1.2 millisecond to avoid this issue.
>
> And the commit ed907fb1d7c3 ("phy: rockchip-inno-usb2: correct
> clk_ops callback") used prepare callbacks instead of enable
> callbacks to support gate a clk if the operation may sleep. So
> we can switch from delay to sleep functions.
>
> Signed-off-by: William Wu <wulf@rock-chips.com>
> ---
> Changes in v3:
> - fix kbuild test error: too few arguments to function 'usleep_range'
>
> Changes in v2:
> - use usleep_range() function instead of mdelay()
>
>  drivers/phy/phy-rockchip-inno-usb2.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c
> index 365e077..0e52b25 100644
> --- a/drivers/phy/phy-rockchip-inno-usb2.c
> +++ b/drivers/phy/phy-rockchip-inno-usb2.c
> @@ -166,7 +166,7 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
>                         return ret;
>
>                 /* waitting for the clk become stable */
> -               mdelay(1);
> +               usleep_range(1200, 1300);

Sight nit that you could also fix the spelling from "waitting" to "waiting".

...but that's pre-existing, so:

Reviewed-by: Douglas Anderson <dianders@chromium.org>

^ permalink raw reply

* [PATCH v6] media: et8ek8: add device tree binding documentation
From: Pavel Machek @ 2016-11-14 18:30 UTC (permalink / raw)
  To: Rob Herring
  Cc: ivo.g.dimitrov.75, sakari.ailus, sre, pali.rohar, linux-media,
	pawel.moll, mark.rutland, ijc+devicetree, galak, mchehab,
	devicetree, linux-kernel
In-Reply-To: <20161107104648.GB5326@amd>

[-- Attachment #1: Type: text/plain, Size: 2159 bytes --]

Add device tree binding documentation for toshiba et8ek8 sensor.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
Signed-off-by: Pavel Machek <pavel@ucw.cz>

---

v6: added missing article, fixed signal polarity.

diff --git a/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt b/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt
new file mode 100644
index 0000000..b03b21d
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/toshiba,et8ek8.txt
@@ -0,0 +1,53 @@
+Toshiba et8ek8 5MP sensor
+
+Toshiba et8ek8 5MP sensor is an image sensor found in Nokia N900 device
+
+More detailed documentation can be found in
+Documentation/devicetree/bindings/media/video-interfaces.txt .
+
+
+Mandatory properties
+--------------------
+
+- compatible: "toshiba,et8ek8"
+- reg: I2C address (0x3e, or an alternative address)
+- vana-supply: Analogue voltage supply (VANA), 2.8 volts
+- clocks: External clock to the sensor
+- clock-frequency: Frequency of the external clock to the sensor. Camera
+  driver will set this frequency on the external clock. The clock frequency is
+  a pre-determined frequency known to be suitable to the board.
+- reset-gpios: XSHUTDOWN GPIO. The XSHUTDOWN signal is active low. The sensor
+  is in hardware standby mode when the signal is in the low state.
+
+
+Endpoint node mandatory properties
+----------------------------------
+
+- remote-endpoint: A phandle to the bus receiver's endpoint node.
+
+Endpoint node optional properties
+----------------------------------
+
+- clock-lanes: <0>
+- data-lanes: <1..n>
+
+Example
+-------
+
+&i2c3 {
+	clock-frequency = <400000>;
+
+	cam1: camera@3e {
+		compatible = "toshiba,et8ek8";
+		reg = <0x3e>;
+		vana-supply = <&vaux4>;
+		clocks = <&isp 0>;
+		clock-frequency = <9600000>;
+		reset-gpio = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* 102 */
+		port {
+			csi_cam1: endpoint {
+				remote-endpoint = <&csi_out1>;
+			};
+		};
+	};
+};

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply related

* Re: [PATCH] ARM64: dts: meson-gxbb-vega-s95: Add SD/SDIO/MMC and PWM nodes
From: Kevin Hilman @ 2016-11-14 18:31 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	carlo-KA+7E9HrN00dnm+yROfE0A, afaerber-l3A5Bk7waGM,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	will.deacon-5wv7dgnIgG8, catalin.marinas-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161112130719.24995-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> writes:

> All boards from the Tronsmart Vega S95 series are sharing similar MMC
> based hardware.
> sd_emmc_a is used to connect a Broadcom based SDIO wifi card (supported
> by the brcmfmac driver). The 32.768KHz LPO clock for the wifi chip is
> generated by PWM_E.
> sd_emmc_b is routed to the SD-card. Unlike p20x there is no GPIO
> regulator, meaning it only supports 3.3V (which seems to be hard-wired).
> The eMMC chip is connected to sd_emmc_c and is implemented similar to
> the meson-gxbb-p20x boards (meaning that hard-wired fixed regulators
> are used).
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Applied to v4.10/dt64.

Kevin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply


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