linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Add board support for TS-4600
@ 2016-12-14 23:12 Sebastien Bourdelin
  2016-12-14 23:12 ` [PATCH 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
	Sebastien Bourdelin

This patch serie adds support for the TS-4600 boards rev A and B. These
boards, manufactured by Technologic Systems, are based on an i.MX28.

This serie include the support for the watchdog which could be enable
at Linux boot time depending on the bootloader.

The watchdog and few peripherals are implemented in a FPGA, and can
only be access using a custom GPIOs bit-banged bus which is called the
NBUS by Technologic Systems.
A driver for this bus is also included and used by the watchdog.

Sebastien Bourdelin (6):
  of: documentation: add bindings documentation for TS-4600
  ARM: dts: TS-4600: add basic device tree
  dt-bindings: bus: Add documentation for the Technologic Systems NBUS
  bus: add driver for the Technologic Systems NBUS
  ARM: dts: TS-4600: add NBUS support
  watchdog: ts4600: add driver for TS-4600 watchdog

 .../devicetree/bindings/arm/technologic.txt        |   5 +
 Documentation/devicetree/bindings/bus/ts-nbus.txt  |  50 +++
 .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 +
 arch/arm/boot/dts/Makefile                         |   2 +
 arch/arm/boot/dts/imx28-ts4600-common.dtsi         | 126 ++++++
 arch/arm/boot/dts/imx28-ts4600-rev-a.dts           |  22 +
 arch/arm/boot/dts/imx28-ts4600-rev-b.dts           |  22 +
 drivers/bus/Kconfig                                |   9 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/ts-nbus.c                              | 451 +++++++++++++++++++++
 drivers/watchdog/Kconfig                           |  10 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/ts4600_wdt.c                      | 213 ++++++++++
 include/linux/ts-nbus.h                            |  17 +
 14 files changed, 945 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/bus/ts-nbus.txt
 create mode 100644 Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-common.dtsi
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-rev-a.dts
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-rev-b.dts
 create mode 100644 drivers/bus/ts-nbus.c
 create mode 100644 drivers/watchdog/ts4600_wdt.c
 create mode 100644 include/linux/ts-nbus.h

-- 
2.10.2

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/6] of: documentation: add bindings documentation for TS-4600
  2016-12-14 23:12 [PATCH 0/6] Add board support for TS-4600 Sebastien Bourdelin
@ 2016-12-14 23:12 ` Sebastien Bourdelin
  2016-12-19 22:05   ` Rob Herring
  2016-12-14 23:12 ` [PATCH 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
	Sebastien Bourdelin

This adds the documentation for the TS-4600 by Technologic Systems.

Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
 Documentation/devicetree/bindings/arm/technologic.txt | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/technologic.txt b/Documentation/devicetree/bindings/arm/technologic.txt
index 33797ac..e9d6d65 100644
--- a/Documentation/devicetree/bindings/arm/technologic.txt
+++ b/Documentation/devicetree/bindings/arm/technologic.txt
@@ -1,6 +1,11 @@
 Technologic Systems Platforms Device Tree Bindings
 --------------------------------------------------
 
+TS-4600 is a System-on-Module based on the Freescale i.MX28 System-on-Chip.
+It can be mounted on a carrier board providing additional peripheral connectors.
+Required root node properties:
+	- compatible = "technologic,imx28-ts4600", "fsl,imx28"
+
 TS-4800 board
 Required root node properties:
 	- compatible = "technologic,imx51-ts4800", "fsl,imx51";
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/6] ARM: dts: TS-4600: add basic device tree
  2016-12-14 23:12 [PATCH 0/6] Add board support for TS-4600 Sebastien Bourdelin
  2016-12-14 23:12 ` [PATCH 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
@ 2016-12-14 23:12 ` Sebastien Bourdelin
  2016-12-14 23:12 ` [PATCH 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
	Sebastien Bourdelin

These device trees add support for the TS-4600 by Technologic Systems.

More details here:
  http://wiki.embeddedarm.com/wiki/TS-4600

Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
 arch/arm/boot/dts/Makefile                 |  2 +
 arch/arm/boot/dts/imx28-ts4600-common.dtsi | 78 ++++++++++++++++++++++++++++++
 arch/arm/boot/dts/imx28-ts4600-rev-a.dts   | 22 +++++++++
 arch/arm/boot/dts/imx28-ts4600-rev-b.dts   | 22 +++++++++
 4 files changed, 124 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-common.dtsi
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-rev-a.dts
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-rev-b.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index c558ba7..5a79fab 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -466,6 +466,8 @@ dtb-$(CONFIG_ARCH_MXS) += \
 	imx28-m28cu3.dtb \
 	imx28-m28evk.dtb \
 	imx28-sps1.dtb \
+	imx28-ts4600-rev-a.dtb \
+	imx28-ts4600-rev-b.dtb \
 	imx28-tx28.dtb
 dtb-$(CONFIG_ARCH_NOMADIK) += \
 	ste-nomadik-s8815.dtb \
diff --git a/arch/arm/boot/dts/imx28-ts4600-common.dtsi b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
new file mode 100644
index 0000000..04bd5a5
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx28.dtsi"
+#include "dt-bindings/gpio/gpio.h"
+
+/ {
+
+	compatible = "technologic,imx28-ts4600", "fsl,imx28";
+
+	apb@80000000 {
+		apbh@80000000 {
+			ssp0: ssp@80010000 {
+				compatible = "fsl,imx28-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a
+					     &mmc0_sck_cfg
+					     &en_sd_pwr>;
+				broken-cd = <1>;
+				bus-width = <4>;
+				vmmc-supply = <&reg_vddio_sd0>;
+				status = "okay";
+			};
+
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+
+				en_sd_pwr: en_sd_pwr {
+					fsl,pinmux-ids = <
+						MX28_PAD_PWM3__GPIO_3_28
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+			};
+		};
+
+		apbx@80040000 {
+			pwm: pwm@80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm2_pins_a>;
+				status = "okay";
+			};
+
+			duart: serial@80074000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_vddio_sd0: vddio-sd0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-boot-on;
+			gpio = <&gpio3 28 0>;
+		};
+	};
+
+};
diff --git a/arch/arm/boot/dts/imx28-ts4600-rev-a.dts b/arch/arm/boot/dts/imx28-ts4600-rev-a.dts
new file mode 100644
index 0000000..e8cb729
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-rev-a.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx28-ts4600-common.dtsi"
+
+/ {
+	model = "Technologic Systems i.MX28 TS-4600 Rev A";
+
+	memory {
+		reg = <0x40000000 0x08000000>;   /* 128MB */
+	};
+
+};
diff --git a/arch/arm/boot/dts/imx28-ts4600-rev-b.dts b/arch/arm/boot/dts/imx28-ts4600-rev-b.dts
new file mode 100644
index 0000000..a115f83
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-rev-b.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx28-ts4600-common.dtsi"
+
+/ {
+	model = "Technologic Systems i.MX28 TS-4600 Rev B";
+
+	memory {
+		reg = <0x40000000 0x10000000>;   /* 256MB */
+	};
+
+};
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS
  2016-12-14 23:12 [PATCH 0/6] Add board support for TS-4600 Sebastien Bourdelin
  2016-12-14 23:12 ` [PATCH 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
  2016-12-14 23:12 ` [PATCH 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
@ 2016-12-14 23:12 ` Sebastien Bourdelin
  2016-12-19 22:12   ` Rob Herring
  2016-12-14 23:12 ` [PATCH 4/6] bus: add driver " Sebastien Bourdelin
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
	Sebastien Bourdelin

Add binding documentation for the Technologic Systems NBUS that is used
to interface with peripherals in the FPGA of the TS-4600 SoM.

Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
 Documentation/devicetree/bindings/bus/ts-nbus.txt | 50 +++++++++++++++++++++++
 1 file changed, 50 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/bus/ts-nbus.txt

diff --git a/Documentation/devicetree/bindings/bus/ts-nbus.txt b/Documentation/devicetree/bindings/bus/ts-nbus.txt
new file mode 100644
index 0000000..2f777ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/ts-nbus.txt
@@ -0,0 +1,50 @@
+Technologic Systems NBUS
+
+The NBUS is a bus used to interface with peripherals in the Technologic
+Systems FPGA on the TS-4600 SoM.
+
+Required properties :
+ - compatible     : "technologic,ts-nbus", "simple-bus"
+ - #address-cells : must be 1
+ - #size-cells    : must be 0
+ - pws            : The PWM pin connected to the clock line on the FPGA
+ - data-gpios	  : The GPIO pin connected to the data line on the FPGA
+ - csn-gpios	  : The GPIO pin connected to the csn line on the FPGA
+ - txrx-gpios	  : The GPIO pin connected to the txrx line on the FPGA
+ - strobe-gpios	  : The GPIO pin connected to the stobe line on the FPGA
+ - ale-gpios	  : The GPIO pin connected to the ale line on the FPGA
+ - rdy-gpios	  : The GPIO pin connected to the rdy line on the FPGA
+
+Child nodes:
+
+The NBUS node can contain zero or more child nodes representing peripherals
+on the bus.
+
+Example:
+
+	nbus {
+		compatible = "technologic,ts-nbus", "simple-bus";
+		pinctrl-0 = <&nbus_pins>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pwms = <&pwm 2 83>;
+		data-gpios   = <&gpio0 0 GPIO_ACTIVE_HIGH
+				&gpio0 1 GPIO_ACTIVE_HIGH
+				&gpio0 2 GPIO_ACTIVE_HIGH
+				&gpio0 3 GPIO_ACTIVE_HIGH
+				&gpio0 4 GPIO_ACTIVE_HIGH
+				&gpio0 5 GPIO_ACTIVE_HIGH
+				&gpio0 6 GPIO_ACTIVE_HIGH
+				&gpio0 7 GPIO_ACTIVE_HIGH>;
+		csn-gpios    = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+		txrx-gpios   = <&gpio0 24 GPIO_ACTIVE_HIGH>;
+		strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
+		ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+		rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+
+		wdt@2a {
+			compatible = "...";
+
+			/* ... */
+		};
+	};
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/6] bus: add driver for the Technologic Systems NBUS
  2016-12-14 23:12 [PATCH 0/6] Add board support for TS-4600 Sebastien Bourdelin
                   ` (2 preceding siblings ...)
  2016-12-14 23:12 ` [PATCH 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
@ 2016-12-14 23:12 ` Sebastien Bourdelin
  2016-12-30  7:58   ` Linus Walleij
  2016-12-14 23:12 ` [PATCH 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
	Sebastien Bourdelin

This driver implements a GPIOs bit-banged bus, called the NBUS by
Technologic Systems. It is used to communicate with the peripherals in
the FPGA on the TS-4600 SoM.

Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
 drivers/bus/Kconfig     |   9 +
 drivers/bus/Makefile    |   1 +
 drivers/bus/ts-nbus.c   | 451 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/ts-nbus.h |  17 ++
 4 files changed, 478 insertions(+)
 create mode 100644 drivers/bus/ts-nbus.c
 create mode 100644 include/linux/ts-nbus.h

diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 7875105..74e72b3 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -150,6 +150,15 @@ config TEGRA_ACONNECT
 	  Driver for the Tegra ACONNECT bus which is used to interface with
 	  the devices inside the Audio Processing Engine (APE) for Tegra210.
 
+config TS_NBUS
+	tristate "Technologic Systems NBUS Driver"
+	default y
+	depends on SOC_IMX28
+	depends on OF_GPIO && PWM
+	help
+	  Driver for the Technologic Systems NBUS which is used to interface
+	  with the peripherals in the FPGA of the TS-4600 SoM.
+
 config UNIPHIER_SYSTEM_BUS
 	tristate "UniPhier System Bus driver"
 	depends on ARCH_UNIPHIER && OF
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index c6cfa6b..83f874a 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -19,5 +19,6 @@ obj-$(CONFIG_QCOM_EBI2)		+= qcom-ebi2.o
 obj-$(CONFIG_SUNXI_RSB)		+= sunxi-rsb.o
 obj-$(CONFIG_SIMPLE_PM_BUS)	+= simple-pm-bus.o
 obj-$(CONFIG_TEGRA_ACONNECT)	+= tegra-aconnect.o
+obj-$(CONFIG_TS_NBUS)		+= ts-nbus.o
 obj-$(CONFIG_UNIPHIER_SYSTEM_BUS)	+= uniphier-system-bus.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o
diff --git a/drivers/bus/ts-nbus.c b/drivers/bus/ts-nbus.c
new file mode 100644
index 0000000..44fc89d
--- /dev/null
+++ b/drivers/bus/ts-nbus.c
@@ -0,0 +1,451 @@
+/*
+ * NBUS driver for TS-4600 based boards
+ *
+ * Copyright (c) 2016 - Savoir-faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This driver implements a GPIOs bit-banged bus, called the NBUS by Technologic
+ * Systems. It is used to communicate with the peripherals in the FPGA on the
+ * TS-4600 SoM.
+ */
+
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+static DEFINE_MUTEX(ts_nbus_lock);
+static bool ts_nbus_ready;
+
+#define TS_NBUS_READ_MODE  0
+#define TS_NBUS_WRITE_MODE 1
+#define TS_NBUS_DIRECTION_IN  0
+#define TS_NBUS_DIRECTION_OUT 1
+#define TS_NBUS_WRITE_ADR 0
+#define TS_NBUS_WRITE_VAL 1
+
+struct ts_nbus {
+	struct pwm_device *pwm;
+	int num_data;
+	int *data;
+	int csn;
+	int txrx;
+	int strobe;
+	int ale;
+	int rdy;
+};
+
+static struct ts_nbus *ts_nbus;
+
+/*
+ * request all gpios required by the bus.
+ */
+static int ts_nbus_init(struct platform_device *pdev)
+{
+	int err;
+	int i;
+
+	for (i = 0; i < ts_nbus->num_data; i++) {
+		err = devm_gpio_request_one(&pdev->dev, ts_nbus->data[i],
+					    GPIOF_OUT_INIT_HIGH,
+					    "TS NBUS data");
+		if (err)
+			return err;
+	}
+
+	err = devm_gpio_request_one(&pdev->dev, ts_nbus->csn,
+				    GPIOF_OUT_INIT_HIGH,
+				    "TS NBUS csn");
+	if (err)
+		return err;
+
+	err = devm_gpio_request_one(&pdev->dev, ts_nbus->txrx,
+				    GPIOF_OUT_INIT_HIGH,
+				    "TS NBUS txrx");
+	if (err)
+		return err;
+
+	err = devm_gpio_request_one(&pdev->dev, ts_nbus->strobe,
+				    GPIOF_OUT_INIT_HIGH,
+				    "TS NBUS strobe");
+	if (err)
+		return err;
+
+	err = devm_gpio_request_one(&pdev->dev, ts_nbus->ale,
+				    GPIOF_OUT_INIT_HIGH,
+				    "TS NBUS ale");
+	if (err)
+		return err;
+
+	err = devm_gpio_request_one(&pdev->dev, ts_nbus->rdy,
+				    GPIOF_IN,
+				    "TS NBUS rdy");
+	if (err)
+		return err;
+
+	return 0;
+}
+
+/*
+ * retrieve all gpios used by the bus from the device tree.
+ */
+static int ts_nbus_get_of_pdata(struct device *dev, struct device_node *np)
+{
+	int num_data;
+	int *data;
+	int ret;
+	int i;
+
+	ret = of_gpio_named_count(np, "data-gpios");
+	if (ret < 0) {
+		dev_err(dev,
+			"failed to count GPIOs in DT property data-gpios\n");
+		return ret;
+	}
+	num_data = ret;
+	data = devm_kzalloc(dev, num_data * sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	for (i = 0; i < num_data; i++) {
+		ret = of_get_named_gpio(np, "data-gpios", i);
+		if (ret < 0) {
+			dev_err(dev, "failed to retrieve data-gpio from dts\n");
+			return ret;
+		}
+		data[i] = ret;
+	}
+	ts_nbus->num_data = num_data;
+	ts_nbus->data = data;
+
+	ret = of_get_named_gpio(np, "csn-gpios", 0);
+	if (ret < 0) {
+		dev_err(dev, "failed to retrieve csn-gpio from dts\n");
+		return ret;
+	}
+	ts_nbus->csn = ret;
+
+	ret = of_get_named_gpio(np, "txrx-gpios", 0);
+	if (ret < 0) {
+		dev_err(dev, "failed to retrieve txrx-gpio from dts\n");
+		return ret;
+	}
+	ts_nbus->txrx = ret;
+
+	ret = of_get_named_gpio(np, "strobe-gpios", 0);
+	if (ret < 0) {
+		dev_err(dev, "failed to retrieve strobe-gpio from dts\n");
+		return ret;
+	}
+	ts_nbus->strobe = ret;
+
+	ret = of_get_named_gpio(np, "ale-gpios", 0);
+	if (ret < 0) {
+		dev_err(dev, "failed to retrieve ale-gpio from dts\n");
+		return ret;
+	}
+	ts_nbus->ale = ret;
+
+	ret = of_get_named_gpio(np, "rdy-gpios", 0);
+	if (ret < 0) {
+		dev_err(dev, "failed to retrieve rdy-gpio from dts\n");
+		return ret;
+	}
+	ts_nbus->rdy = ret;
+
+	return 0;
+}
+
+/*
+ * the txrx gpio is used by the FPGA to know if the following transactions
+ * should be handled to read or write a value.
+ */
+static inline void ts_nbus_set_mode(int mode)
+{
+	if (mode == TS_NBUS_READ_MODE)
+		gpio_set_value(ts_nbus->txrx, 0);
+	else
+		gpio_set_value(ts_nbus->txrx, 1);
+}
+
+/*
+ * the data gpios are used for reading and writing values, their directions
+ * should be adjusted accordingly.
+ */
+static inline void ts_nbus_set_direction(int direction)
+{
+	int i;
+
+	for (i = 0; i < ts_nbus->num_data; i++) {
+		if (direction == TS_NBUS_DIRECTION_IN)
+			gpio_direction_input(ts_nbus->data[i]);
+		else
+			gpio_direction_output(ts_nbus->data[i], 1);
+	}
+}
+
+/*
+ * reset the bus in its initial state.
+ */
+static inline void ts_nbus_reset_bus(void)
+{
+	int i;
+
+	for (i = 0; i < ts_nbus->num_data; i++)
+		gpio_set_value(ts_nbus->data[i], 0);
+
+	gpio_set_value(ts_nbus->csn, 0);
+	gpio_set_value(ts_nbus->strobe, 0);
+	gpio_set_value(ts_nbus->ale, 0);
+}
+
+/*
+ * let the FPGA knows it can process.
+ */
+static inline void ts_nbus_start_transaction(void)
+{
+	gpio_set_value(ts_nbus->strobe, 1);
+}
+
+/*
+ * return the byte value read from the data gpios.
+ */
+static inline u8 ts_nbus_read_byte(void)
+{
+	int i;
+	u8 value = 0;
+
+	for (i = 0; i < ts_nbus->num_data; i++)
+		if (ts_nbus->data[i])
+			value |= 1 << i;
+
+	return value;
+}
+
+/*
+ * set the data gpios accordingly to the byte value.
+ */
+static inline void ts_nbus_write_byte(u8 byte)
+{
+	int i;
+
+	for (i = 0; i < ts_nbus->num_data; i++)
+		if (byte & (1 << i))
+			gpio_set_value(ts_nbus->data[i], 1);
+}
+
+/*
+ * reading the bus consists of resetting the bus, then notifying the FPGA to
+ * send the data in the data gpios and return the read value.
+ */
+static inline u8 ts_nbus_read_bus(void)
+{
+	ts_nbus_reset_bus();
+	ts_nbus_start_transaction();
+
+	return ts_nbus_read_byte();
+}
+
+/*
+ * writing to the bus consists of resetting the bus, then define the type of
+ * command (address/value), write the data and notify the FPGA to retrieve the
+ * value in the data gpios.
+ */
+static inline void ts_nbus_write_bus(int cmd, u8 value)
+{
+	ts_nbus_reset_bus();
+
+	if (cmd == TS_NBUS_WRITE_ADR)
+		gpio_set_value(ts_nbus->ale, 1);
+
+	ts_nbus_write_byte(value);
+	ts_nbus_start_transaction();
+}
+
+/*
+ * read the value in the FPGA register at the given address.
+ */
+u16 ts_nbus_read(u8 adr)
+{
+	int i;
+	u16 val;
+
+	/* bus access must be atomic */
+	mutex_lock(&ts_nbus_lock);
+
+	/* set the bus in read mode */
+	ts_nbus_set_mode(TS_NBUS_READ_MODE);
+
+	/* write address */
+	ts_nbus_write_bus(TS_NBUS_WRITE_ADR, adr);
+
+	/* set the data gpios direction as input before reading */
+	ts_nbus_set_direction(TS_NBUS_DIRECTION_IN);
+
+	/* reading value MSB first */
+	do {
+		val = 0;
+		for (i = 1; i >= 0; i--)
+			val |= (ts_nbus_read_bus() << (i * 8));
+		gpio_set_value(ts_nbus->csn, 1);
+	} while (gpio_get_value(ts_nbus->rdy));
+
+	/* restore the data gpios direction as output after reading */
+	ts_nbus_set_direction(TS_NBUS_DIRECTION_OUT);
+
+	mutex_unlock(&ts_nbus_lock);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(ts_nbus_read);
+
+/*
+ * write the desired value in the FPGA register at the given address.
+ */
+int ts_nbus_write(u8 adr, u16 value)
+{
+	int i;
+
+	/* bus access must be atomic */
+	mutex_lock(&ts_nbus_lock);
+
+	/* set the bus in write mode */
+	ts_nbus_set_mode(TS_NBUS_WRITE_MODE);
+
+	/* write address */
+	ts_nbus_write_bus(TS_NBUS_WRITE_ADR, adr);
+
+	/* writing value MSB first */
+	for (i = 1; i >= 0; i--)
+		ts_nbus_write_bus(TS_NBUS_WRITE_VAL, (u8)(value >> (i * 8)));
+
+	/* wait for completion */
+	gpio_set_value(ts_nbus->csn, 1);
+	while (gpio_get_value(ts_nbus->rdy) != 0) {
+		gpio_set_value(ts_nbus->csn, 0);
+		gpio_set_value(ts_nbus->csn, 1);
+	}
+
+	mutex_unlock(&ts_nbus_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ts_nbus_write);
+
+/*
+ * helper function to know the state of the bus.
+ * this function is useful to let peripherals defer their probing while the bus
+ * is not ready.
+ */
+bool ts_nbus_is_ready(void)
+{
+	bool nbus_state;
+
+	mutex_lock(&ts_nbus_lock);
+	nbus_state = ts_nbus_ready;
+	mutex_unlock(&ts_nbus_lock);
+
+	return nbus_state;
+}
+EXPORT_SYMBOL_GPL(ts_nbus_is_ready);
+
+static int ts_nbus_probe(struct platform_device *pdev)
+{
+	struct pwm_device *pwm;
+	struct pwm_args pargs;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	ts_nbus = devm_kzalloc(dev, sizeof(*ts_nbus), GFP_KERNEL);
+	if (!ts_nbus)
+		return -ENOMEM;
+
+	ret = ts_nbus_get_of_pdata(dev, np);
+	if (ret)
+		return ret;
+	ret = ts_nbus_init(pdev);
+	if (ret < 0)
+		return ret;
+
+	pwm = devm_pwm_get(dev, NULL);
+	if (IS_ERR(pwm)) {
+		ret = PTR_ERR(pwm);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "unable to request PWM\n");
+		return ret;
+	}
+
+	pwm_get_args(pwm, &pargs);
+	if (!pargs.period) {
+		dev_err(&pdev->dev, "invalid PWM period\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * FIXME: pwm_apply_args() should be removed when switching to
+	 * the atomic PWM API.
+	 */
+	pwm_apply_args(pwm);
+	ret = pwm_config(pwm, pargs.period, pargs.period);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * we can now start the FPGA and let the peripherals knows the bus is
+	 * ready.
+	 */
+	pwm_enable(pwm);
+	ts_nbus->pwm = pwm;
+
+	mutex_lock(&ts_nbus_lock);
+	ts_nbus_ready = true;
+	mutex_unlock(&ts_nbus_lock);
+
+	dev_info(dev, "initialized\n");
+
+	return 0;
+}
+
+static int ts_nbus_remove(struct platform_device *pdev)
+{
+	/* disable bus access */
+	mutex_lock(&ts_nbus_lock);
+	ts_nbus_ready = false;
+	mutex_unlock(&ts_nbus_lock);
+
+	/* shutdown the FPGA */
+	pwm_disable(ts_nbus->pwm);
+
+	return 0;
+}
+
+static const struct of_device_id ts_nbus_of_match[] = {
+	{ .compatible = "technologic,ts-nbus", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ts_nbus_of_match);
+
+static struct platform_driver ts_nbus_driver = {
+	.probe		= ts_nbus_probe,
+	.remove		= ts_nbus_remove,
+	.driver		= {
+		.name	= "ts_nbus",
+		.of_match_table = ts_nbus_of_match,
+	},
+};
+
+module_platform_driver(ts_nbus_driver);
+
+MODULE_ALIAS("platform:ts_nbus");
+MODULE_AUTHOR("Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>");
+MODULE_DESCRIPTION("Technologic Systems NBUS");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/ts-nbus.h b/include/linux/ts-nbus.h
new file mode 100644
index 0000000..5fcdb96
--- /dev/null
+++ b/include/linux/ts-nbus.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2016 - Savoir-faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _TS_NBUS_H
+#define _TS_NBUS_H
+
+extern u16 ts_nbus_read(u8 adr);
+extern int ts_nbus_write(u8 adr, u16 value);
+extern bool ts_nbus_is_ready(void);
+
+#endif /* _TS_NBUS_H */
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 5/6] ARM: dts: TS-4600: add NBUS support
  2016-12-14 23:12 [PATCH 0/6] Add board support for TS-4600 Sebastien Bourdelin
                   ` (3 preceding siblings ...)
  2016-12-14 23:12 ` [PATCH 4/6] bus: add driver " Sebastien Bourdelin
@ 2016-12-14 23:12 ` Sebastien Bourdelin
  2016-12-30  8:01   ` Linus Walleij
  2016-12-14 23:12 ` [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
  2016-12-14 23:12 ` [PATCH 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
  6 siblings, 1 reply; 18+ messages in thread
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
	Sebastien Bourdelin

This commit enables the NBUS on the TS-4600, using the ts-nbus driver.

Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
 arch/arm/boot/dts/imx28-ts4600-common.dtsi | 43 ++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/arch/arm/boot/dts/imx28-ts4600-common.dtsi b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
index 04bd5a5..b668933 100644
--- a/arch/arm/boot/dts/imx28-ts4600-common.dtsi
+++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
@@ -44,6 +44,28 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
+				nbus_pins: nbus_pins {
+					fsl,pinmux-ids = <
+						MX28_PAD_GPMI_D00__GPIO_0_0
+						MX28_PAD_GPMI_D01__GPIO_0_1
+						MX28_PAD_GPMI_D02__GPIO_0_2
+						MX28_PAD_GPMI_D03__GPIO_0_3
+						MX28_PAD_GPMI_D04__GPIO_0_4
+						MX28_PAD_GPMI_D05__GPIO_0_5
+						MX28_PAD_GPMI_D06__GPIO_0_6
+						MX28_PAD_GPMI_D07__GPIO_0_7
+						MX28_PAD_GPMI_CE0N__GPIO_0_16
+						MX28_PAD_GPMI_RDY1__GPIO_0_21
+						MX28_PAD_GPMI_RDN__GPIO_0_24
+						MX28_PAD_GPMI_WRN__GPIO_0_25
+						MX28_PAD_GPMI_ALE__GPIO_0_26
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+
+				};
+
 			};
 		};
 
@@ -75,4 +97,25 @@
 		};
 	};
 
+	nbus {
+		compatible = "technologic,ts-nbus", "simple-bus";
+		pinctrl-0 = <&nbus_pins>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pwms = <&pwm 2 83>;
+		data-gpios   = <&gpio0 0 GPIO_ACTIVE_HIGH
+				&gpio0 1 GPIO_ACTIVE_HIGH
+				&gpio0 2 GPIO_ACTIVE_HIGH
+				&gpio0 3 GPIO_ACTIVE_HIGH
+				&gpio0 4 GPIO_ACTIVE_HIGH
+				&gpio0 5 GPIO_ACTIVE_HIGH
+				&gpio0 6 GPIO_ACTIVE_HIGH
+				&gpio0 7 GPIO_ACTIVE_HIGH>;
+		csn-gpios    = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+		txrx-gpios   = <&gpio0 24 GPIO_ACTIVE_HIGH>;
+		strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
+		ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+		rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+	};
+
 };
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2016-12-14 23:12 [PATCH 0/6] Add board support for TS-4600 Sebastien Bourdelin
                   ` (4 preceding siblings ...)
  2016-12-14 23:12 ` [PATCH 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
@ 2016-12-14 23:12 ` Sebastien Bourdelin
  2016-12-15 10:28   ` kbuild test robot
                     ` (2 more replies)
  2016-12-14 23:12 ` [PATCH 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
  6 siblings, 3 replies; 18+ messages in thread
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
	Sebastien Bourdelin

This watchdog is instantiated in a FPGA and can only be access using a
GPIOs bit-banged bus, called the NBUS by Technologic Systems.
The watchdog is made of only one register, called the feed register.
Writing to this register will re-arm the watchdog for a given time (and
enable it if it was disable). It can be disabled by writing a special
value into it.

Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
 .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
 arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +
 drivers/watchdog/Kconfig                           |  10 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/ts4600_wdt.c                      | 213 +++++++++++++++++++++
 5 files changed, 245 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
 create mode 100644 drivers/watchdog/ts4600_wdt.c

diff --git a/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt b/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
new file mode 100644
index 0000000..61d620e
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
@@ -0,0 +1,16 @@
+TS-4600 Technologic Systems Watchdog
+
+Required properties:
+- compatible: must be "technologic,ts4600-wdt"
+- reg: offset to the FPGA's watchdog register
+
+Optional property:
+- timeout-sec: contains the watchdog timeout in seconds.
+
+Example:
+
+wdt {
+	compatible = "technologic,ts4600-wdt";
+	reg = <0x2a>;
+	timeout-sec = <10>;
+};
diff --git a/arch/arm/boot/dts/imx28-ts4600-common.dtsi b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
index b668933..dd7318c 100644
--- a/arch/arm/boot/dts/imx28-ts4600-common.dtsi
+++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
@@ -116,6 +116,11 @@
 		strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
 		ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
 		rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+
+		wdt@2a {
+			compatible = "technologic,ts4600-wdt";
+			reg = <0x2a>;
+		};
 	};
 
 };
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 3eb58cb..7a8e176 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -500,6 +500,16 @@ config NUC900_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called nuc900_wdt.
 
+config TS4600_WATCHDOG
+	tristate "TS-4600 Watchdog"
+	depends on HAS_IOMEM && OF
+	depends on SOC_IMX28 || COMPILE_TEST
+	select WATCHDOG_CORE
+	help
+	  Technologic Systems TS-4600 has watchdog timer implemented in
+	  an external FPGA. Say Y here if you want to support for the
+	  watchdog timer on TS-4600 board.
+
 config TS4800_WATCHDOG
 	tristate "TS-4800 Watchdog"
 	depends on HAS_IOMEM && OF
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4a..d4b4bd2 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_RN5T618_WATCHDOG) += rn5t618_wdt.o
 obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
 obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
+obj-$(CONFIG_TS4600_WATCHDOG) += ts4600_wdt.o
 obj-$(CONFIG_TS4800_WATCHDOG) += ts4800_wdt.o
 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
diff --git a/drivers/watchdog/ts4600_wdt.c b/drivers/watchdog/ts4600_wdt.c
new file mode 100644
index 0000000..db91b40
--- /dev/null
+++ b/drivers/watchdog/ts4600_wdt.c
@@ -0,0 +1,213 @@
+/*
+ * Watchdog driver for TS-4600 based boards
+ *
+ * Copyright (c) 2016 - Savoir-faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The watchdog on the TS-4600 based boards is in an FPGA and can only be
+ * accessed using a GPIO bit-banged bus called the NBUS by Technologic Systems.
+ * The logic for the watchdog is the same then for the TS-4800 SoM, only the way
+ * to access it change, therefore this driver is heavely based on the ts4800_wdt
+ * driver from Damien Riegel <damien.riegel@savoirfairelinux.com>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/ts-nbus.h>
+#include <linux/watchdog.h>
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+	"Watchdog cannot be stopped once started (default="
+	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+/* possible feed values */
+#define TS4600_WDT_FEED_2S       0x1
+#define TS4600_WDT_FEED_10S      0x2
+#define TS4600_WDT_DISABLE       0x3
+
+struct ts4600_wdt {
+	struct watchdog_device  wdd;
+	u32                     feed_offset;
+	u32                     feed_val;
+};
+
+/*
+ * TS-4600 supports the following timeout values:
+ *
+ *   value desc
+ *   ---------------------
+ *     0    feed for 338ms
+ *     1    feed for 2.706s
+ *     2    feed for 10.824s
+ *     3    disable watchdog
+ *
+ * Keep the regmap/timeout map ordered by timeout
+ */
+static const struct {
+	const int timeout;
+	const int regval;
+} ts4600_wdt_map[] = {
+	{ 2,  TS4600_WDT_FEED_2S },
+	{ 10, TS4600_WDT_FEED_10S },
+};
+
+#define MAX_TIMEOUT_INDEX       (ARRAY_SIZE(ts4600_wdt_map) - 1)
+
+static void ts4600_write_feed(struct ts4600_wdt *wdt, u32 val)
+{
+	ts_nbus_write(wdt->feed_offset, val);
+}
+
+static int ts4600_wdt_start(struct watchdog_device *wdd)
+{
+	struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	ts4600_write_feed(wdt, wdt->feed_val);
+
+	return 0;
+}
+
+static int ts4600_wdt_stop(struct watchdog_device *wdd)
+{
+	struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	ts4600_write_feed(wdt, TS4600_WDT_DISABLE);
+	return 0;
+}
+
+static int ts4600_wdt_set_timeout(struct watchdog_device *wdd,
+				  unsigned int timeout)
+{
+	struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
+	int i;
+
+	for (i = 0; i < MAX_TIMEOUT_INDEX; i++) {
+		if (ts4600_wdt_map[i].timeout >= timeout)
+			break;
+	}
+
+	wdd->timeout = ts4600_wdt_map[i].timeout;
+	wdt->feed_val = ts4600_wdt_map[i].regval;
+
+	return 0;
+}
+
+static const struct watchdog_ops ts4600_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = ts4600_wdt_start,
+	.stop = ts4600_wdt_stop,
+	.set_timeout = ts4600_wdt_set_timeout,
+};
+
+static const struct watchdog_info ts4600_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.identity = "TS-4600 Watchdog",
+};
+
+static int ts4600_wdt_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct watchdog_device *wdd;
+	struct ts4600_wdt *wdt;
+	u32 reg;
+	int ret;
+
+	ret = of_property_read_u32(np, "reg", &reg);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "missing reg property\n");
+		return ret;
+	}
+
+	/* check for the NBUS state and defer the probing if it is not ready */
+	if (!ts_nbus_is_ready())
+		return -EPROBE_DEFER;
+
+	/* allocate memory for watchdog struct */
+	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	/* set offset to know where to write */
+	wdt->feed_offset = reg;
+
+	/* Initialize struct watchdog_device */
+	wdd = &wdt->wdd;
+	wdd->parent = &pdev->dev;
+	wdd->info = &ts4600_wdt_info;
+	wdd->ops = &ts4600_wdt_ops;
+	wdd->min_timeout = ts4600_wdt_map[0].timeout;
+	wdd->max_timeout = ts4600_wdt_map[MAX_TIMEOUT_INDEX].timeout;
+
+	watchdog_set_drvdata(wdd, wdt);
+	watchdog_set_nowayout(wdd, nowayout);
+	watchdog_init_timeout(wdd, 0, &pdev->dev);
+
+	/*
+	 * As this watchdog supports only a few values, ts4600_wdt_set_timeout
+	 * must be called to initialize timeout and feed_val with valid values.
+	 * Default to maximum timeout if none, or an invalid one, is provided in
+	 * device tree.
+	 */
+	if (!wdd->timeout)
+		wdd->timeout = wdd->max_timeout;
+	ts4600_wdt_set_timeout(wdd, wdd->timeout);
+
+	/*
+	 * The feed register is write-only, so it is not possible to determine
+	 * watchdog's state. Disable it to be in a known state.
+	 */
+	ts4600_wdt_stop(wdd);
+
+	ret = watchdog_register_device(wdd);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to register watchdog device\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, wdt);
+
+	dev_info(&pdev->dev,
+		 "initialized (timeout = %d sec, nowayout = %d)\n",
+		 wdd->timeout, nowayout);
+
+	return 0;
+}
+
+static int ts4600_wdt_remove(struct platform_device *pdev)
+{
+	struct ts4600_wdt *wdt = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&wdt->wdd);
+
+	return 0;
+}
+
+static const struct of_device_id ts4600_wdt_of_match[] = {
+	{ .compatible = "technologic,ts4600-wdt", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ts4600_wdt_of_match);
+
+static struct platform_driver ts4600_wdt_driver = {
+	.probe		= ts4600_wdt_probe,
+	.remove		= ts4600_wdt_remove,
+	.driver		= {
+		.name	= "ts4600_wdt",
+		.of_match_table = ts4600_wdt_of_match,
+	},
+};
+
+module_platform_driver(ts4600_wdt_driver);
+
+MODULE_AUTHOR("Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ts4600_wdt");
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/6] ARM: dts: TS-4600: add basic device tree
  2016-12-14 23:12 [PATCH 0/6] Add board support for TS-4600 Sebastien Bourdelin
                   ` (5 preceding siblings ...)
  2016-12-14 23:12 ` [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
@ 2016-12-14 23:12 ` Sebastien Bourdelin
  6 siblings, 0 replies; 18+ messages in thread
From: Sebastien Bourdelin @ 2016-12-14 23:12 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
	Sebastien Bourdelin

These device trees add support for the TS-4600 by Technologic Systems.

More details here:
  http://wiki.embeddedarm.com/wiki/TS-4600

Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
 arch/arm/boot/dts/Makefile                 |  2 +
 arch/arm/boot/dts/imx28-ts4600-common.dtsi | 78 ++++++++++++++++++++++++++++++
 arch/arm/boot/dts/imx28-ts4600-rev-a.dts   | 22 +++++++++
 arch/arm/boot/dts/imx28-ts4600-rev-b.dts   | 22 +++++++++
 4 files changed, 124 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-common.dtsi
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-rev-a.dts
 create mode 100644 arch/arm/boot/dts/imx28-ts4600-rev-b.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index c558ba7..5a79fab 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -466,6 +466,8 @@ dtb-$(CONFIG_ARCH_MXS) += \
 	imx28-m28cu3.dtb \
 	imx28-m28evk.dtb \
 	imx28-sps1.dtb \
+	imx28-ts4600-rev-a.dtb \
+	imx28-ts4600-rev-b.dtb \
 	imx28-tx28.dtb
 dtb-$(CONFIG_ARCH_NOMADIK) += \
 	ste-nomadik-s8815.dtb \
diff --git a/arch/arm/boot/dts/imx28-ts4600-common.dtsi b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
new file mode 100644
index 0000000..04bd5a5
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx28.dtsi"
+#include "dt-bindings/gpio/gpio.h"
+
+/ {
+
+	compatible = "technologic,imx28-ts4600", "fsl,imx28";
+
+	apb@80000000 {
+		apbh@80000000 {
+			ssp0: ssp@80010000 {
+				compatible = "fsl,imx28-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a
+					     &mmc0_sck_cfg
+					     &en_sd_pwr>;
+				broken-cd = <1>;
+				bus-width = <4>;
+				vmmc-supply = <&reg_vddio_sd0>;
+				status = "okay";
+			};
+
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+
+				en_sd_pwr: en_sd_pwr {
+					fsl,pinmux-ids = <
+						MX28_PAD_PWM3__GPIO_3_28
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+			};
+		};
+
+		apbx@80040000 {
+			pwm: pwm@80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm2_pins_a>;
+				status = "okay";
+			};
+
+			duart: serial@80074000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_vddio_sd0: vddio-sd0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-boot-on;
+			gpio = <&gpio3 28 0>;
+		};
+	};
+
+};
diff --git a/arch/arm/boot/dts/imx28-ts4600-rev-a.dts b/arch/arm/boot/dts/imx28-ts4600-rev-a.dts
new file mode 100644
index 0000000..e8cb729
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-rev-a.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx28-ts4600-common.dtsi"
+
+/ {
+	model = "Technologic Systems i.MX28 TS-4600 Rev A";
+
+	memory {
+		reg = <0x40000000 0x08000000>;   /* 128MB */
+	};
+
+};
diff --git a/arch/arm/boot/dts/imx28-ts4600-rev-b.dts b/arch/arm/boot/dts/imx28-ts4600-rev-b.dts
new file mode 100644
index 0000000..a115f83
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-ts4600-rev-b.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Savoir-Faire Linux
+ * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx28-ts4600-common.dtsi"
+
+/ {
+	model = "Technologic Systems i.MX28 TS-4600 Rev B";
+
+	memory {
+		reg = <0x40000000 0x10000000>;   /* 256MB */
+	};
+
+};
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2016-12-14 23:12 ` [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
@ 2016-12-15 10:28   ` kbuild test robot
  2016-12-19 22:13   ` Rob Herring
  2016-12-23  1:53   ` Guenter Roeck
  2 siblings, 0 replies; 18+ messages in thread
From: kbuild test robot @ 2016-12-15 10:28 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: kbuild-all, linux-kernel, linux-watchdog, linux-arm-kernel,
	devicetree, kernel, mark, kris, horms+renesas, treding,
	jonathanh, f.fainelli, fabio.estevam, kernel, shawnguo, linux,
	linux, wim, mark.rutland, robh+dt, damien.riegel, lucile.quirion,
	olof, arnd, suzuki.poulose, linus.walleij, will.deacon,
	yamada.masahiro, Sebastien Bourdelin

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

Hi Sebastien,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.9]
[cannot apply to next-20161215]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Sebastien-Bourdelin/of-documentation-add-bindings-documentation-for-TS-4600/20161215-072238
config: i386-allyesconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/built-in.o: In function `ts4600_wdt_start':
>> ts4600_wdt.c:(.text+0x2333d64): undefined reference to `ts_nbus_write'
   drivers/built-in.o: In function `ts4600_wdt_stop':
   ts4600_wdt.c:(.text+0x2333d85): undefined reference to `ts_nbus_write'
   drivers/built-in.o: In function `ts4600_wdt_probe':
   ts4600_wdt.c:(.text+0x2333e66): undefined reference to `ts_nbus_write'
>> ts4600_wdt.c:(.text+0x2333ee9): undefined reference to `ts_nbus_is_ready'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 57052 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/6] of: documentation: add bindings documentation for TS-4600
  2016-12-14 23:12 ` [PATCH 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
@ 2016-12-19 22:05   ` Rob Herring
  0 siblings, 0 replies; 18+ messages in thread
From: Rob Herring @ 2016-12-19 22:05 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, mark, kris, horms+renesas, treding, jonathanh,
	f.fainelli, fabio.estevam, kernel, shawnguo, linux, linux, wim,
	mark.rutland, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro

On Wed, Dec 14, 2016 at 06:12:31PM -0500, Sebastien Bourdelin wrote:
> This adds the documentation for the TS-4600 by Technologic Systems.
> 
> Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
> ---
>  Documentation/devicetree/bindings/arm/technologic.txt | 5 +++++
>  1 file changed, 5 insertions(+)

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS
  2016-12-14 23:12 ` [PATCH 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
@ 2016-12-19 22:12   ` Rob Herring
  0 siblings, 0 replies; 18+ messages in thread
From: Rob Herring @ 2016-12-19 22:12 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, mark, kris, horms+renesas, treding, jonathanh,
	f.fainelli, fabio.estevam, kernel, shawnguo, linux, linux, wim,
	mark.rutland, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro

On Wed, Dec 14, 2016 at 06:12:33PM -0500, Sebastien Bourdelin wrote:
> Add binding documentation for the Technologic Systems NBUS that is used
> to interface with peripherals in the FPGA of the TS-4600 SoM.
> 
> Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
> ---
>  Documentation/devicetree/bindings/bus/ts-nbus.txt | 50 +++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/bus/ts-nbus.txt
> 
> diff --git a/Documentation/devicetree/bindings/bus/ts-nbus.txt b/Documentation/devicetree/bindings/bus/ts-nbus.txt
> new file mode 100644
> index 0000000..2f777ee
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/bus/ts-nbus.txt
> @@ -0,0 +1,50 @@
> +Technologic Systems NBUS
> +
> +The NBUS is a bus used to interface with peripherals in the Technologic
> +Systems FPGA on the TS-4600 SoM.
> +
> +Required properties :
> + - compatible     : "technologic,ts-nbus", "simple-bus"
> + - #address-cells : must be 1
> + - #size-cells    : must be 0
> + - pws            : The PWM pin connected to the clock line on the FPGA

Using PWM binding?

> + - data-gpios	  : The GPIO pin connected to the data line on the FPGA
> + - csn-gpios	  : The GPIO pin connected to the csn line on the FPGA
> + - txrx-gpios	  : The GPIO pin connected to the txrx line on the FPGA
> + - strobe-gpios	  : The GPIO pin connected to the stobe line on the FPGA
> + - ale-gpios	  : The GPIO pin connected to the ale line on the FPGA
> + - rdy-gpios	  : The GPIO pin connected to the rdy line on the FPGA

These all need vendor prefix.

This is not any sort of standard bus?

> +
> +Child nodes:
> +
> +The NBUS node can contain zero or more child nodes representing peripherals
> +on the bus.
> +
> +Example:
> +
> +	nbus {
> +		compatible = "technologic,ts-nbus", "simple-bus";

I don't think simple-bus is really valid here. Don't you need the nbus 
driver before the devices are usable?

> +		pinctrl-0 = <&nbus_pins>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		pwms = <&pwm 2 83>;
> +		data-gpios   = <&gpio0 0 GPIO_ACTIVE_HIGH
> +				&gpio0 1 GPIO_ACTIVE_HIGH
> +				&gpio0 2 GPIO_ACTIVE_HIGH
> +				&gpio0 3 GPIO_ACTIVE_HIGH
> +				&gpio0 4 GPIO_ACTIVE_HIGH
> +				&gpio0 5 GPIO_ACTIVE_HIGH
> +				&gpio0 6 GPIO_ACTIVE_HIGH
> +				&gpio0 7 GPIO_ACTIVE_HIGH>;
> +		csn-gpios    = <&gpio0 16 GPIO_ACTIVE_HIGH>;
> +		txrx-gpios   = <&gpio0 24 GPIO_ACTIVE_HIGH>;
> +		strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
> +		ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
> +		rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
> +
> +		wdt@2a {

watchdog@...

> +			compatible = "...";
> +
> +			/* ... */
> +		};
> +	};
> -- 
> 2.10.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2016-12-14 23:12 ` [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
  2016-12-15 10:28   ` kbuild test robot
@ 2016-12-19 22:13   ` Rob Herring
  2016-12-23  1:53   ` Guenter Roeck
  2 siblings, 0 replies; 18+ messages in thread
From: Rob Herring @ 2016-12-19 22:13 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, mark, kris, horms+renesas, treding, jonathanh,
	f.fainelli, fabio.estevam, kernel, shawnguo, linux, linux, wim,
	mark.rutland, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro

On Wed, Dec 14, 2016 at 06:12:36PM -0500, Sebastien Bourdelin wrote:
> This watchdog is instantiated in a FPGA and can only be access using a
> GPIOs bit-banged bus, called the NBUS by Technologic Systems.
> The watchdog is made of only one register, called the feed register.
> Writing to this register will re-arm the watchdog for a given time (and
> enable it if it was disable). It can be disabled by writing a special
> value into it.
> 
> Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
> ---
>  .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
>  arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +

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

>  drivers/watchdog/Kconfig                           |  10 +
>  drivers/watchdog/Makefile                          |   1 +
>  drivers/watchdog/ts4600_wdt.c                      | 213 +++++++++++++++++++++
>  5 files changed, 245 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
>  create mode 100644 drivers/watchdog/ts4600_wdt.c

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2016-12-14 23:12 ` [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
  2016-12-15 10:28   ` kbuild test robot
  2016-12-19 22:13   ` Rob Herring
@ 2016-12-23  1:53   ` Guenter Roeck
  2 siblings, 0 replies; 18+ messages in thread
From: Guenter Roeck @ 2016-12-23  1:53 UTC (permalink / raw)
  To: Sebastien Bourdelin, linux-kernel, linux-watchdog,
	linux-arm-kernel, devicetree, kernel
  Cc: mark, kris, horms+renesas, treding, jonathanh, f.fainelli,
	fabio.estevam, kernel, shawnguo, linux, wim, mark.rutland,
	robh+dt, damien.riegel, lucile.quirion, olof, arnd,
	suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro

On 12/14/2016 03:12 PM, Sebastien Bourdelin wrote:
> This watchdog is instantiated in a FPGA and can only be access using a
> GPIOs bit-banged bus, called the NBUS by Technologic Systems.
> The watchdog is made of only one register, called the feed register.
> Writing to this register will re-arm the watchdog for a given time (and
> enable it if it was disable). It can be disabled by writing a special
> value into it.
>
> Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
> ---
>  .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
>  arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +
>  drivers/watchdog/Kconfig                           |  10 +
>  drivers/watchdog/Makefile                          |   1 +
>  drivers/watchdog/ts4600_wdt.c                      | 213 +++++++++++++++++++++
>  5 files changed, 245 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
>  create mode 100644 drivers/watchdog/ts4600_wdt.c
>
> diff --git a/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt b/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
> new file mode 100644
> index 0000000..61d620e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
> @@ -0,0 +1,16 @@
> +TS-4600 Technologic Systems Watchdog
> +
> +Required properties:
> +- compatible: must be "technologic,ts4600-wdt"
> +- reg: offset to the FPGA's watchdog register
> +
> +Optional property:
> +- timeout-sec: contains the watchdog timeout in seconds.
> +
> +Example:
> +
> +wdt {
> +	compatible = "technologic,ts4600-wdt";
> +	reg = <0x2a>;
> +	timeout-sec = <10>;
> +};
> diff --git a/arch/arm/boot/dts/imx28-ts4600-common.dtsi b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
> index b668933..dd7318c 100644
> --- a/arch/arm/boot/dts/imx28-ts4600-common.dtsi
> +++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
> @@ -116,6 +116,11 @@
>  		strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
>  		ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
>  		rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
> +
> +		wdt@2a {
> +			compatible = "technologic,ts4600-wdt";
> +			reg = <0x2a>;
> +		};
>  	};
>
>  };
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 3eb58cb..7a8e176 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -500,6 +500,16 @@ config NUC900_WATCHDOG
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called nuc900_wdt.
>
> +config TS4600_WATCHDOG
> +	tristate "TS-4600 Watchdog"
> +	depends on HAS_IOMEM && OF
> +	depends on SOC_IMX28 || COMPILE_TEST

Asd 0day reports, this does not work.

> +	select WATCHDOG_CORE
> +	help
> +	  Technologic Systems TS-4600 has watchdog timer implemented in
> +	  an external FPGA. Say Y here if you want to support for the
> +	  watchdog timer on TS-4600 board.
> +
>  config TS4800_WATCHDOG
>  	tristate "TS-4800 Watchdog"
>  	depends on HAS_IOMEM && OF
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index caa9f4a..d4b4bd2 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -61,6 +61,7 @@ obj-$(CONFIG_RN5T618_WATCHDOG) += rn5t618_wdt.o
>  obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
>  obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o
>  obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
> +obj-$(CONFIG_TS4600_WATCHDOG) += ts4600_wdt.o
>  obj-$(CONFIG_TS4800_WATCHDOG) += ts4800_wdt.o
>  obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
>  obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
> diff --git a/drivers/watchdog/ts4600_wdt.c b/drivers/watchdog/ts4600_wdt.c
> new file mode 100644
> index 0000000..db91b40
> --- /dev/null
> +++ b/drivers/watchdog/ts4600_wdt.c
> @@ -0,0 +1,213 @@
> +/*
> + * Watchdog driver for TS-4600 based boards
> + *
> + * Copyright (c) 2016 - Savoir-faire Linux
> + * Author: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + *
> + * The watchdog on the TS-4600 based boards is in an FPGA and can only be
> + * accessed using a GPIO bit-banged bus called the NBUS by Technologic Systems.
> + * The logic for the watchdog is the same then for the TS-4800 SoM, only the way
> + * to access it change, therefore this driver is heavely based on the ts4800_wdt
> + * driver from Damien Riegel <damien.riegel@savoirfairelinux.com>.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/ts-nbus.h>
> +#include <linux/watchdog.h>
> +
> +static bool nowayout = WATCHDOG_NOWAYOUT;
> +module_param(nowayout, bool, 0);
> +MODULE_PARM_DESC(nowayout,
> +	"Watchdog cannot be stopped once started (default="
> +	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
> +
> +/* possible feed values */
> +#define TS4600_WDT_FEED_2S       0x1
> +#define TS4600_WDT_FEED_10S      0x2
> +#define TS4600_WDT_DISABLE       0x3
> +
> +struct ts4600_wdt {
> +	struct watchdog_device  wdd;
> +	u32                     feed_offset;
> +	u32                     feed_val;
> +};
> +
> +/*
> + * TS-4600 supports the following timeout values:
> + *
> + *   value desc
> + *   ---------------------
> + *     0    feed for 338ms
> + *     1    feed for 2.706s
> + *     2    feed for 10.824s
> + *     3    disable watchdog
> + *
> + * Keep the regmap/timeout map ordered by timeout
> + */
> +static const struct {
> +	const int timeout;
> +	const int regval;
> +} ts4600_wdt_map[] = {
> +	{ 2,  TS4600_WDT_FEED_2S },
> +	{ 10, TS4600_WDT_FEED_10S },
> +};
> +
> +#define MAX_TIMEOUT_INDEX       (ARRAY_SIZE(ts4600_wdt_map) - 1)
> +
> +static void ts4600_write_feed(struct ts4600_wdt *wdt, u32 val)
> +{
> +	ts_nbus_write(wdt->feed_offset, val);
> +}
> +
> +static int ts4600_wdt_start(struct watchdog_device *wdd)
> +{
> +	struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> +	ts4600_write_feed(wdt, wdt->feed_val);
> +
> +	return 0;
> +}
> +
> +static int ts4600_wdt_stop(struct watchdog_device *wdd)
> +{
> +	struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> +	ts4600_write_feed(wdt, TS4600_WDT_DISABLE);
> +	return 0;
> +}
> +
> +static int ts4600_wdt_set_timeout(struct watchdog_device *wdd,
> +				  unsigned int timeout)
> +{
> +	struct ts4600_wdt *wdt = watchdog_get_drvdata(wdd);
> +	int i;
> +
> +	for (i = 0; i < MAX_TIMEOUT_INDEX; i++) {
> +		if (ts4600_wdt_map[i].timeout >= timeout)
> +			break;
> +	}

An if/else would be much simpler here.

> +
> +	wdd->timeout = ts4600_wdt_map[i].timeout;
> +	wdt->feed_val = ts4600_wdt_map[i].regval;
> +
> +	return 0;
> +}
> +
> +static const struct watchdog_ops ts4600_wdt_ops = {
> +	.owner = THIS_MODULE,
> +	.start = ts4600_wdt_start,
> +	.stop = ts4600_wdt_stop,
> +	.set_timeout = ts4600_wdt_set_timeout,
> +};
> +
> +static const struct watchdog_info ts4600_wdt_info = {
> +	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
> +	.identity = "TS-4600 Watchdog",
> +};
> +
> +static int ts4600_wdt_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct watchdog_device *wdd;
> +	struct ts4600_wdt *wdt;
> +	u32 reg;
> +	int ret;
> +
> +	ret = of_property_read_u32(np, "reg", &reg);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "missing reg property\n");
> +		return ret;
> +	}
> +
> +	/* check for the NBUS state and defer the probing if it is not ready */
> +	if (!ts_nbus_is_ready())
> +		return -EPROBE_DEFER;
> +
> +	/* allocate memory for watchdog struct */
> +	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> +	if (!wdt)
> +		return -ENOMEM;
> +
> +	/* set offset to know where to write */
> +	wdt->feed_offset = reg;
> +
> +	/* Initialize struct watchdog_device */
> +	wdd = &wdt->wdd;
> +	wdd->parent = &pdev->dev;
> +	wdd->info = &ts4600_wdt_info;
> +	wdd->ops = &ts4600_wdt_ops;
> +	wdd->min_timeout = ts4600_wdt_map[0].timeout;
> +	wdd->max_timeout = ts4600_wdt_map[MAX_TIMEOUT_INDEX].timeout;
> +

Your call, but it might be better and more flexible to just use a single
hardware timeout (such as the 2.x second one), provide it here as
max_hw_heartbeat_ms, and let the kernel handle the actual (and larger)
timeouts.

> +	watchdog_set_drvdata(wdd, wdt);
> +	watchdog_set_nowayout(wdd, nowayout);
> +	watchdog_init_timeout(wdd, 0, &pdev->dev);
> +
> +	/*
> +	 * As this watchdog supports only a few values, ts4600_wdt_set_timeout
> +	 * must be called to initialize timeout and feed_val with valid values.
> +	 * Default to maximum timeout if none, or an invalid one, is provided in
> +	 * device tree.
> +	 */
> +	if (!wdd->timeout)
> +		wdd->timeout = wdd->max_timeout;
> +	ts4600_wdt_set_timeout(wdd, wdd->timeout);
> +
> +	/*
> +	 * The feed register is write-only, so it is not possible to determine
> +	 * watchdog's state. Disable it to be in a known state.
> +	 */
> +	ts4600_wdt_stop(wdd);
> +
> +	ret = watchdog_register_device(wdd);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +			"failed to register watchdog device\n");
> +		return ret;
> +	}
> +
> +	platform_set_drvdata(pdev, wdt);
> +
> +	dev_info(&pdev->dev,
> +		 "initialized (timeout = %d sec, nowayout = %d)\n",
> +		 wdd->timeout, nowayout);
> +
> +	return 0;
> +}
> +
> +static int ts4600_wdt_remove(struct platform_device *pdev)
> +{
> +	struct ts4600_wdt *wdt = platform_get_drvdata(pdev);
> +
> +	watchdog_unregister_device(&wdt->wdd);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id ts4600_wdt_of_match[] = {
> +	{ .compatible = "technologic,ts4600-wdt", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, ts4600_wdt_of_match);
> +
> +static struct platform_driver ts4600_wdt_driver = {
> +	.probe		= ts4600_wdt_probe,
> +	.remove		= ts4600_wdt_remove,
> +	.driver		= {
> +		.name	= "ts4600_wdt",
> +		.of_match_table = ts4600_wdt_of_match,
> +	},
> +};
> +
> +module_platform_driver(ts4600_wdt_driver);
> +
> +MODULE_AUTHOR("Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:ts4600_wdt");
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/6] bus: add driver for the Technologic Systems NBUS
  2016-12-14 23:12 ` [PATCH 4/6] bus: add driver " Sebastien Bourdelin
@ 2016-12-30  7:58   ` Linus Walleij
  2017-02-01 19:56     ` Sebastien Bourdelin
  0 siblings, 1 reply; 18+ messages in thread
From: Linus Walleij @ 2016-12-30  7:58 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, mark, kris, Simon Horman, Thierry Reding, Jon Hunter,
	Florian Fainelli, Fabio Estevam, Sascha Hauer, Shawn Guo,
	Russell King, Guenter Roeck, Wim Van Sebroeck, Mark Rutland,
	Rob Herring, damien.riegel, Lucile Quirion, Olof Johansson,
	Arnd Bergmann, Suzuki K. Poulose, Will Deacon, Masahiro Yamada

On Thu, Dec 15, 2016 at 12:12 AM, Sebastien Bourdelin
<sebastien.bourdelin@savoirfairelinux.com> wrote:

> This driver implements a GPIOs bit-banged bus, called the NBUS by
> Technologic Systems. It is used to communicate with the peripherals in
> the FPGA on the TS-4600 SoM.
>
> Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
(...)

> +#include <linux/gpio.h>

Use:
#include <linux/gpio/consumer.h>
instead, and deal with the fallout.

> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>

Don't use this.

> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +
> +static DEFINE_MUTEX(ts_nbus_lock);
> +static bool ts_nbus_ready;

Why not move this to the struct ts_nbus state container?

It seems to be per-bus not per-system.

> +#define TS_NBUS_READ_MODE  0
> +#define TS_NBUS_WRITE_MODE 1
> +#define TS_NBUS_DIRECTION_IN  0
> +#define TS_NBUS_DIRECTION_OUT 1
> +#define TS_NBUS_WRITE_ADR 0
> +#define TS_NBUS_WRITE_VAL 1
> +
> +struct ts_nbus {
> +       struct pwm_device *pwm;
> +       int num_data;
> +       int *data;
> +       int csn;
> +       int txrx;
> +       int strobe;
> +       int ale;
> +       int rdy;
> +};
> +
> +static struct ts_nbus *ts_nbus;

Nopes. No singletons please.

Use the state container pattern:
Documentation/driver-model/design-patterns.txt

> +/*
> + * request all gpios required by the bus.
> + */
> +static int ts_nbus_init(struct platform_device *pdev)
> +{
> +       int err;
> +       int i;
> +
> +       for (i = 0; i < ts_nbus->num_data; i++) {
> +               err = devm_gpio_request_one(&pdev->dev, ts_nbus->data[i],
> +                                           GPIOF_OUT_INIT_HIGH,
> +                                           "TS NBUS data");
> +               if (err)
> +                       return err;
> +       }

DO not use the legacy GPIO API anywhere.

Reference the device and use gpiod_get() simple, fair and square.

Store struct gpio_desc * pointers in your state container instead.

> +static int ts_nbus_get_of_pdata(struct device *dev, struct device_node *np)
> +{
> +       int num_data;
> +       int *data;
> +       int ret;
> +       int i;
> +
> +       ret = of_gpio_named_count(np, "data-gpios");
> +       if (ret < 0) {
> +               dev_err(dev,
> +                       "failed to count GPIOs in DT property data-gpios\n");
> +               return ret;
> +       }

Do not reinvent the wheel.

Use devm_gpiod_get_array().


> +       ret = of_get_named_gpio(np, "csn-gpios", 0);

And again use devm_gpiod_get(), and gpiod_* accessors.
Applies everywhere.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/6] ARM: dts: TS-4600: add NBUS support
  2016-12-14 23:12 ` [PATCH 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
@ 2016-12-30  8:01   ` Linus Walleij
  0 siblings, 0 replies; 18+ messages in thread
From: Linus Walleij @ 2016-12-30  8:01 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, mark, kris, Simon Horman, Thierry Reding, Jon Hunter,
	Florian Fainelli, Fabio Estevam, Sascha Hauer, Shawn Guo,
	Russell King, Guenter Roeck, Wim Van Sebroeck, Mark Rutland,
	Rob Herring, damien.riegel, Lucile Quirion, Olof Johansson,
	Arnd Bergmann, Suzuki K. Poulose, Will Deacon, Masahiro Yamada

On Thu, Dec 15, 2016 at 12:12 AM, Sebastien Bourdelin
<sebastien.bourdelin@savoirfairelinux.com> wrote:

> This commit enables the NBUS on the TS-4600, using the ts-nbus driver.
>
> Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>

> +       nbus {
> +               compatible = "technologic,ts-nbus", "simple-bus";
> +               pinctrl-0 = <&nbus_pins>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               pwms = <&pwm 2 83>;
> +               data-gpios   = <&gpio0 0 GPIO_ACTIVE_HIGH
> +                               &gpio0 1 GPIO_ACTIVE_HIGH
> +                               &gpio0 2 GPIO_ACTIVE_HIGH
> +                               &gpio0 3 GPIO_ACTIVE_HIGH
> +                               &gpio0 4 GPIO_ACTIVE_HIGH
> +                               &gpio0 5 GPIO_ACTIVE_HIGH
> +                               &gpio0 6 GPIO_ACTIVE_HIGH
> +                               &gpio0 7 GPIO_ACTIVE_HIGH>;
> +               csn-gpios    = <&gpio0 16 GPIO_ACTIVE_HIGH>;
> +               txrx-gpios   = <&gpio0 24 GPIO_ACTIVE_HIGH>;
> +               strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
> +               ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
> +               rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;

devm_gpiod_get(&pdev->dev, "csn", GPIOD_OUT_HIGH); etc will get these
from the spawned
platform device.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/6] bus: add driver for the Technologic Systems NBUS
  2016-12-30  7:58   ` Linus Walleij
@ 2017-02-01 19:56     ` Sebastien Bourdelin
  2017-02-03 13:51       ` Linus Walleij
  0 siblings, 1 reply; 18+ messages in thread
From: Sebastien Bourdelin @ 2017-02-01 19:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, mark, kris, Simon Horman, Thierry Reding, Jon Hunter,
	Florian Fainelli, Fabio Estevam, Sascha Hauer, Shawn Guo,
	Russell King, Guenter Roeck, Wim Van Sebroeck, Mark Rutland,
	Rob Herring, damien.riegel, Lucile Quirion, Olof Johansson,
	Arnd Bergmann, Suzuki K. Poulose, Will Deacon, Masahiro Yamada

Hi Linus,

Thanks for your feedback.
I have a question regarding your recommendation, see below.

On 12/30/2016 02:58 AM, Linus Walleij wrote:

>> +
>> +static DEFINE_MUTEX(ts_nbus_lock);
>> +static bool ts_nbus_ready;
> 
> Why not move this to the struct ts_nbus state container?
> 
> It seems to be per-bus not per-system.
> 
>> +#define TS_NBUS_READ_MODE  0
>> +#define TS_NBUS_WRITE_MODE 1
>> +#define TS_NBUS_DIRECTION_IN  0
>> +#define TS_NBUS_DIRECTION_OUT 1
>> +#define TS_NBUS_WRITE_ADR 0
>> +#define TS_NBUS_WRITE_VAL 1
>> +
>> +struct ts_nbus {
>> +       struct pwm_device *pwm;
>> +       int num_data;
>> +       int *data;
>> +       int csn;
>> +       int txrx;
>> +       int strobe;
>> +       int ale;
>> +       int rdy;
>> +};
>> +
>> +static struct ts_nbus *ts_nbus;
> 
> Nopes. No singletons please.
> 
> Use the state container pattern:
> Documentation/driver-model/design-patterns.txt
> 

I understand the idea but have problem to find a good way to implement it.

Other drivers using the NBUS which are child nodes in the device tree
will use the ts_nbus_write() and ts_nbus_read() functions, it means these
drivers should have a pointer to the allocated ts_nbus and pass it to
the write() and read() functions as an argument if i'm not using a
singleton here.
But i'm lacking knowledge on how to properly share this pointer when
initializing the NBUS driver with the child nodes.

Perhaps my design is not appropriate for what i'm doing, if someone can
point me on a similar problematic it will be really helpful.

Best Regards,
Sebastien.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/6] bus: add driver for the Technologic Systems NBUS
  2017-02-01 19:56     ` Sebastien Bourdelin
@ 2017-02-03 13:51       ` Linus Walleij
  2017-02-03 15:56         ` Sebastien Bourdelin
  0 siblings, 1 reply; 18+ messages in thread
From: Linus Walleij @ 2017-02-03 13:51 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, Mark Featherston, kris, Simon Horman, Thierry Reding,
	Jon Hunter, Florian Fainelli, Fabio Estevam, Sascha Hauer,
	Shawn Guo, Russell King, Guenter Roeck, Wim Van Sebroeck,
	Mark Rutland, Rob Herring, damien.riegel, Lucile Quirion,
	Olof Johansson, Arnd Bergmann, Suzuki K. Poulose, Will Deacon,
	Masahiro Yamada

On Wed, Feb 1, 2017 at 8:56 PM, Sebastien Bourdelin
<sebastien.bourdelin@savoirfairelinux.com> wrote:
> On 12/30/2016 02:58 AM, Linus Walleij wrote:

>>> +static struct ts_nbus *ts_nbus;
>>
>> Nopes. No singletons please.
>>
>> Use the state container pattern:
>> Documentation/driver-model/design-patterns.txt
>
> I understand the idea but have problem to find a good way to implement it.
>
> Other drivers using the NBUS which are child nodes in the device tree
> will use the ts_nbus_write() and ts_nbus_read() functions, it means these
> drivers should have a pointer to the allocated ts_nbus and pass it to
> the write() and read() functions as an argument if i'm not using a
> singleton here.
> But i'm lacking knowledge on how to properly share this pointer when
> initializing the NBUS driver with the child nodes.

Your child nodes I guess will be instatiated as devices as well.

These devices will have the NBUS driver as .parent in their
struct device I guess. Else the design of this bus is tilted.

If the NBUS driver use dev_set_drvdata(dev, state_container_cookie)
the children can use dev_get_drvdata(dev->parent); to get a pointer to
the same cookie.

The subdrivers don't even need to know the members of the state
container as long as you're just passing a pointer to it. It's
enough if you forward-declare it as a "pointer to some struct":

struct foo;

{
   struct foo *fooptr = dev_get_drvdata(dev->parent);
   write(fooptr, 0x10);

etc

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/6] bus: add driver for the Technologic Systems NBUS
  2017-02-03 13:51       ` Linus Walleij
@ 2017-02-03 15:56         ` Sebastien Bourdelin
  0 siblings, 0 replies; 18+ messages in thread
From: Sebastien Bourdelin @ 2017-02-03 15:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, Mark Featherston, kris, Simon Horman, Thierry Reding,
	Jon Hunter, Florian Fainelli, Fabio Estevam, Sascha Hauer,
	Shawn Guo, Russell King, Guenter Roeck, Wim Van Sebroeck,
	Mark Rutland, Rob Herring, damien.riegel, Lucile Quirion,
	Olof Johansson, Arnd Bergmann, Suzuki K. Poulose, Will Deacon,
	Masahiro Yamada

Hi Linus,

On 02/03/2017 08:51 AM, Linus Walleij wrote:
> Your child nodes I guess will be instatiated as devices as well.
> 
> These devices will have the NBUS driver as .parent in their
> struct device I guess. Else the design of this bus is tilted.
> 
> If the NBUS driver use dev_set_drvdata(dev, state_container_cookie)
> the children can use dev_get_drvdata(dev->parent); to get a pointer to
> the same cookie.
> 
> The subdrivers don't even need to know the members of the state
> container as long as you're just passing a pointer to it. It's
> enough if you forward-declare it as a "pointer to some struct":
> 
> struct foo;
> 
> {
>    struct foo *fooptr = dev_get_drvdata(dev->parent);
>    write(fooptr, 0x10);
> 
> etc

Thanks a lot, this is perfect!

Best Regards,
Sebastien.

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2017-02-03 15:56 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-14 23:12 [PATCH 0/6] Add board support for TS-4600 Sebastien Bourdelin
2016-12-14 23:12 ` [PATCH 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
2016-12-19 22:05   ` Rob Herring
2016-12-14 23:12 ` [PATCH 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
2016-12-14 23:12 ` [PATCH 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
2016-12-19 22:12   ` Rob Herring
2016-12-14 23:12 ` [PATCH 4/6] bus: add driver " Sebastien Bourdelin
2016-12-30  7:58   ` Linus Walleij
2017-02-01 19:56     ` Sebastien Bourdelin
2017-02-03 13:51       ` Linus Walleij
2017-02-03 15:56         ` Sebastien Bourdelin
2016-12-14 23:12 ` [PATCH 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
2016-12-30  8:01   ` Linus Walleij
2016-12-14 23:12 ` [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
2016-12-15 10:28   ` kbuild test robot
2016-12-19 22:13   ` Rob Herring
2016-12-23  1:53   ` Guenter Roeck
2016-12-14 23:12 ` [PATCH 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).