linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/6] Add board support for TS-4600
@ 2017-05-05 19:32 Sebastien Bourdelin
  2017-05-05 19:32 ` [PATCH v3 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Sebastien Bourdelin @ 2017-05-05 19:32 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linux, linus.walleij, shawnguo
  Cc: fabio.estevam, mark, kris, 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                                |   8 +
 drivers/bus/Makefile                               |   1 +
 drivers/bus/ts-nbus.c                              | 375 +++++++++++++++++++++
 drivers/watchdog/Kconfig                           |  11 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/ts4600_wdt.c                      | 185 ++++++++++
 include/linux/ts-nbus.h                            |  18 +
 14 files changed, 842 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.12.0

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

* [PATCH v3 1/6] of: documentation: add bindings documentation for TS-4600
  2017-05-05 19:32 [PATCH v3 0/6] Add board support for TS-4600 Sebastien Bourdelin
@ 2017-05-05 19:32 ` Sebastien Bourdelin
  2017-05-05 19:32 ` [PATCH v3 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Sebastien Bourdelin @ 2017-05-05 19:32 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linux, linus.walleij, shawnguo
  Cc: fabio.estevam, mark, kris, Sebastien Bourdelin

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

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
---
Changes v2 -> v3:
  - rebase on master

Changes v1 -> v2:
  - rebase on master
  - add ack by Rob Herring <robh@kernel.org>
---
 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 33797acad846..e9d6d6575566 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.12.0

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

* [PATCH v3 2/6] ARM: dts: TS-4600: add basic device tree
  2017-05-05 19:32 [PATCH v3 0/6] Add board support for TS-4600 Sebastien Bourdelin
  2017-05-05 19:32 ` [PATCH v3 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
@ 2017-05-05 19:32 ` Sebastien Bourdelin
  2017-05-05 19:32 ` [PATCH v3 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Sebastien Bourdelin @ 2017-05-05 19:32 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linux, linus.walleij, shawnguo
  Cc: fabio.estevam, mark, kris, 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>
---
Changes v2 -> v3:
  - rebase on master

Changes v1 -> v2:
  - rebase on master
---
 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 011808490fed..acf54eeacb57 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -495,6 +495,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 000000000000..04bd5a5c0cb4
--- /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 000000000000..e8cb72988fcf
--- /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 000000000000..a115f831fe2b
--- /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.12.0

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

* [PATCH v3 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS
  2017-05-05 19:32 [PATCH v3 0/6] Add board support for TS-4600 Sebastien Bourdelin
  2017-05-05 19:32 ` [PATCH v3 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
  2017-05-05 19:32 ` [PATCH v3 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
@ 2017-05-05 19:32 ` Sebastien Bourdelin
  2017-05-11 13:50   ` Linus Walleij
  2017-05-12 15:17   ` Rob Herring
  2017-05-05 19:32 ` [PATCH v3 4/6] bus: add driver " Sebastien Bourdelin
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 17+ messages in thread
From: Sebastien Bourdelin @ 2017-05-05 19:32 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linux, linus.walleij, shawnguo
  Cc: fabio.estevam, mark, kris, 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>
---
Changes v2 -> v3:
  - rebase on master
  - fix typo (suggested by Rob Herring)

Changes v1 -> v2:
  - rebase on master
  - remove the simple-bus compatibility as the root node will now
  populate child nodes (suggested by Rob Herring)
  - use the ts vendor prefix for gpios (suggested by Rob Herring)
---
 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 000000000000..905600adfb64
--- /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"
+ - #address-cells	: must be 1
+ - #size-cells		: must be 0
+ - pwms			: The PWM bound to the FPGA
+ - ts-data-gpios	: The 8 GPIO pins connected to the data lines on the FPGA
+ - ts-csn-gpios		: The GPIO pin connected to the csn line on the FPGA
+ - ts-txrx-gpios	: The GPIO pin connected to the txrx line on the FPGA
+ - ts-strobe-gpios	: The GPIO pin connected to the stobe line on the FPGA
+ - ts-ale-gpios		: The GPIO pin connected to the ale line on the FPGA
+ - ts-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";
+		pinctrl-0 = <&nbus_pins>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pwms = <&pwm 2 83>;
+		ts-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>;
+		ts-csn-gpios    = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+		ts-txrx-gpios   = <&gpio0 24 GPIO_ACTIVE_HIGH>;
+		ts-strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
+		ts-ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+		ts-rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+
+		watchdog@2a {
+			compatible = "...";
+
+			/* ... */
+		};
+	};
-- 
2.12.0

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

* [PATCH v3 4/6] bus: add driver for the Technologic Systems NBUS
  2017-05-05 19:32 [PATCH v3 0/6] Add board support for TS-4600 Sebastien Bourdelin
                   ` (2 preceding siblings ...)
  2017-05-05 19:32 ` [PATCH v3 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
@ 2017-05-05 19:32 ` Sebastien Bourdelin
  2017-05-11 13:56   ` Linus Walleij
  2017-05-05 19:32 ` [PATCH v3 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
  2017-05-05 19:32 ` [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
  5 siblings, 1 reply; 17+ messages in thread
From: Sebastien Bourdelin @ 2017-05-05 19:32 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linux, linus.walleij, shawnguo
  Cc: fabio.estevam, mark, kris, 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>
---
Changes v2 -> v3:
  - rebase on master
  - remove all call to the "inline" keyword in functions to let the
  compiler decide when required (suggested by Linus Walleij)
  - move the struct ts_nbus to the driver code instead of its header
  file (suggested by Linus Walleij)
  - use the bitops header and the BIT macro (suggested by Linus Walleij)
  - move the mutex to the struct ts_nbus instead to have it statically
  declared in the driver code (suggested by Linus Walleij)
  - remove the ts_nbus_set_mode function to simplify the logic
  (suggested by Linus Walleij)
  - the nbus will always need 8 data lines, remove the use of the
  ndescs when dealing with the data gpios and hardcode the value for
  simplicity instead (suggested by Linus Walleij)
  - add more comments (suggested by Linus Walleij)
  - rework all the ts_nbus_read_... functions to propagate the
  gpiod_get_value_... errno code (suggested by Linus Walleij)
  - few typos and code reformating for lisibility

Changes v1 -> v2:
  - rebase on master
  - the driver now populate its child nodes
  - remove the 'default y' option from the Kconfig
  - rework the driver to not use singleton anymore (suggested by Linus
  Walleij)
  - replace the use of the legacy GPIO API with gpiod (suggested by
  Linus Walleij)
  - use the ts vendor prefix for gpios (suggested by Rob Herring)
---
 drivers/bus/Kconfig     |   8 ++
 drivers/bus/Makefile    |   1 +
 drivers/bus/ts-nbus.c   | 375 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/ts-nbus.h |  18 +++
 4 files changed, 402 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 0a52da439abf..a9998081b01e 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -158,6 +158,14 @@ config TEGRA_GMI
 	  Driver for the Tegra Generic Memory Interface bus which can be used
 	  to attach devices such as NOR, UART, FPGA and more.
 
+config TS_NBUS
+	tristate "Technologic Systems NBUS Driver"
+	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 cc6364bec054..72377f77651c 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -20,6 +20,7 @@ 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_TEGRA_GMI)		+= tegra-gmi.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 000000000000..25714421f911
--- /dev/null
+++ b/drivers/bus/ts-nbus.c
@@ -0,0 +1,375 @@
+/*
+ * 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/bitops.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/ts-nbus.h>
+
+#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;
+	struct gpio_descs *data;
+	struct gpio_desc *csn;
+	struct gpio_desc *txrx;
+	struct gpio_desc *strobe;
+	struct gpio_desc *ale;
+	struct gpio_desc *rdy;
+	struct mutex lock;
+};
+
+/*
+ * request all gpios required by the bus.
+ */
+static int ts_nbus_init_pdata(struct platform_device *pdev, struct ts_nbus
+		*ts_nbus)
+{
+	ts_nbus->data = devm_gpiod_get_array(&pdev->dev, "ts-data",
+			GPIOD_OUT_HIGH);
+	if (IS_ERR(ts_nbus->data)) {
+		dev_err(&pdev->dev, "failed to retrieve ts-data-gpio from dts\n");
+		return PTR_ERR(ts_nbus->data);
+	}
+
+	ts_nbus->csn = devm_gpiod_get(&pdev->dev, "ts-csn", GPIOD_OUT_HIGH);
+	if (IS_ERR(ts_nbus->csn)) {
+		dev_err(&pdev->dev, "failed to retrieve ts-csn-gpio from dts\n");
+		return PTR_ERR(ts_nbus->csn);
+	}
+
+	ts_nbus->txrx = devm_gpiod_get(&pdev->dev, "ts-txrx", GPIOD_OUT_HIGH);
+	if (IS_ERR(ts_nbus->txrx)) {
+		dev_err(&pdev->dev, "failed to retrieve ts-txrx-gpio from dts\n");
+		return PTR_ERR(ts_nbus->txrx);
+	}
+
+	ts_nbus->strobe = devm_gpiod_get(&pdev->dev, "ts-strobe", GPIOD_OUT_HIGH);
+	if (IS_ERR(ts_nbus->strobe)) {
+		dev_err(&pdev->dev, "failed to retrieve ts-strobe-gpio from dts\n");
+		return PTR_ERR(ts_nbus->strobe);
+	}
+
+	ts_nbus->ale = devm_gpiod_get(&pdev->dev, "ts-ale", GPIOD_OUT_HIGH);
+	if (IS_ERR(ts_nbus->ale)) {
+		dev_err(&pdev->dev, "failed to retrieve ts-ale-gpio from dts\n");
+		return PTR_ERR(ts_nbus->ale);
+	}
+
+	ts_nbus->rdy = devm_gpiod_get(&pdev->dev, "ts-rdy", GPIOD_IN);
+	if (IS_ERR(ts_nbus->rdy)) {
+		dev_err(&pdev->dev, "failed to retrieve ts-rdy-gpio from dts\n");
+		return PTR_ERR(ts_nbus->rdy);
+	}
+
+	return 0;
+}
+
+/*
+ * the data gpios are used for reading and writing values, their directions
+ * should be adjusted accordingly.
+ */
+static void ts_nbus_set_direction(struct ts_nbus *ts_nbus, int direction)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		if (direction == TS_NBUS_DIRECTION_IN)
+			gpiod_direction_input(ts_nbus->data->desc[i]);
+		else
+			/* when used as output the default state of the data
+			 * lines are set to high */
+			gpiod_direction_output(ts_nbus->data->desc[i], 1);
+	}
+}
+
+/*
+ * reset the bus in its initial state.
+ * The data, csn, strobe and ale lines must be zero'ed to let the FPGA knows a
+ * new transaction can be process.
+ */
+static void ts_nbus_reset_bus(struct ts_nbus *ts_nbus)
+{
+	int i;
+	int values[8];
+
+	for (i = 0; i < 8; i++)
+		values[i] = 0;
+
+	gpiod_set_array_value_cansleep(8, ts_nbus->data->desc, values);
+	gpiod_set_value_cansleep(ts_nbus->csn, 0);
+	gpiod_set_value_cansleep(ts_nbus->strobe, 0);
+	gpiod_set_value_cansleep(ts_nbus->ale, 0);
+}
+
+/*
+ * let the FPGA knows it can process.
+ */
+static void ts_nbus_start_transaction(struct ts_nbus *ts_nbus)
+{
+	gpiod_set_value_cansleep(ts_nbus->strobe, 1);
+}
+
+/*
+ * read a byte value from the data gpios.
+ * return 0 on success or negative errno on failure.
+ */
+static int ts_nbus_read_byte(struct ts_nbus *ts_nbus, u8 *val)
+{
+	struct gpio_descs *gpios = ts_nbus->data;
+	int ret, i;
+
+	*val = 0;
+	for (i = 0; i < 8; i++) {
+		ret = gpiod_get_value_cansleep(gpios->desc[i]);
+		if (ret < 0)
+			return ret;
+		if (ret)
+			*val |= BIT(i);
+	}
+
+	return 0;
+}
+
+/*
+ * set the data gpios accordingly to the byte value.
+ */
+static void ts_nbus_write_byte(struct ts_nbus *ts_nbus, u8 byte)
+{
+	struct gpio_descs *gpios = ts_nbus->data;
+	int i;
+	int values[8];
+
+	for (i = 0; i < 8; i++)
+		if (byte & BIT(i))
+			values[i] = 1;
+		else
+			values[i] = 0;
+
+	gpiod_set_array_value_cansleep(8, gpios->desc, values);
+}
+
+/*
+ * 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.
+ * return 0 on success or negative errno on failure.
+ */
+static int ts_nbus_read_bus(struct ts_nbus *ts_nbus, u8 *val)
+{
+	ts_nbus_reset_bus(ts_nbus);
+	ts_nbus_start_transaction(ts_nbus);
+
+	return ts_nbus_read_byte(ts_nbus, val);
+}
+
+/*
+ * 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 void ts_nbus_write_bus(struct ts_nbus *ts_nbus, int cmd, u8 val)
+{
+	ts_nbus_reset_bus(ts_nbus);
+
+	if (cmd == TS_NBUS_WRITE_ADR)
+		gpiod_set_value_cansleep(ts_nbus->ale, 1);
+
+	ts_nbus_write_byte(ts_nbus, val);
+	ts_nbus_start_transaction(ts_nbus);
+}
+
+/*
+ * read the value in the FPGA register at the given address.
+ * return 0 on success or negative errno on failure.
+ */
+int ts_nbus_read(struct ts_nbus *ts_nbus, u8 adr, u16 *val)
+{
+	int ret, i;
+	u8 byte;
+
+	/* bus access must be atomic */
+	mutex_lock(&ts_nbus->lock);
+
+	/* set the bus in read mode */
+	gpiod_set_value_cansleep(ts_nbus->txrx, 0);
+
+	/* write address */
+	ts_nbus_write_bus(ts_nbus, TS_NBUS_WRITE_ADR, adr);
+
+	/* set the data gpios direction as input before reading */
+	ts_nbus_set_direction(ts_nbus, TS_NBUS_DIRECTION_IN);
+
+	/* reading value MSB first */
+	do {
+		*val = 0;
+		byte = 0;
+		for (i = 1; i >= 0; i--) {
+			/* read a byte from the bus, leave on error */
+			ret = ts_nbus_read_bus(ts_nbus, &byte);
+			if (ret < 0)
+				goto err;
+
+			/* append the byte read to the final value */
+			*val |= byte << (i * 8);
+		}
+		gpiod_set_value_cansleep(ts_nbus->csn, 1);
+		ret = gpiod_get_value_cansleep(ts_nbus->rdy);
+	} while (ret);
+
+err:
+	/* restore the data gpios direction as output after reading */
+	ts_nbus_set_direction(ts_nbus, TS_NBUS_DIRECTION_OUT);
+
+	mutex_unlock(&ts_nbus->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ts_nbus_read);
+
+/*
+ * write the desired value in the FPGA register at the given address.
+ */
+int ts_nbus_write(struct ts_nbus *ts_nbus, u8 adr, u16 val)
+{
+	int i;
+
+	/* bus access must be atomic */
+	mutex_lock(&ts_nbus->lock);
+
+	/* set the bus in write mode */
+	gpiod_set_value_cansleep(ts_nbus->txrx, 1);
+
+	/* write address */
+	ts_nbus_write_bus(ts_nbus, TS_NBUS_WRITE_ADR, adr);
+
+	/* writing value MSB first */
+	for (i = 1; i >= 0; i--)
+		ts_nbus_write_bus(ts_nbus, TS_NBUS_WRITE_VAL, (u8)(val >> (i * 8)));
+
+	/* wait for completion */
+	gpiod_set_value_cansleep(ts_nbus->csn, 1);
+	while (gpiod_get_value_cansleep(ts_nbus->rdy) != 0) {
+		gpiod_set_value_cansleep(ts_nbus->csn, 0);
+		gpiod_set_value_cansleep(ts_nbus->csn, 1);
+	}
+
+	mutex_unlock(&ts_nbus->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ts_nbus_write);
+
+static int ts_nbus_probe(struct platform_device *pdev)
+{
+	struct pwm_device *pwm;
+	struct pwm_args pargs;
+	struct device *dev = &pdev->dev;
+	struct ts_nbus *ts_nbus;
+	int ret;
+
+	ts_nbus = devm_kzalloc(dev, sizeof(*ts_nbus), GFP_KERNEL);
+	if (!ts_nbus)
+		return -ENOMEM;
+
+	mutex_init(&ts_nbus->lock);
+
+	ret = ts_nbus_init_pdata(pdev, ts_nbus);
+	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 populate the peripherals.
+	 */
+	pwm_enable(pwm);
+	ts_nbus->pwm = pwm;
+
+	/*
+	 * let the child nodes retrieve this instance of the ts-nbus.
+	 */
+	dev_set_drvdata(dev, ts_nbus);
+
+	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+	if (ret < 0)
+		return ret;
+
+	dev_info(dev, "initialized\n");
+
+	return 0;
+}
+
+static int ts_nbus_remove(struct platform_device *pdev)
+{
+	struct ts_nbus *ts_nbus = dev_get_drvdata(&pdev->dev);
+
+	/* shutdown the FPGA */
+	mutex_lock(&ts_nbus->lock);
+	pwm_disable(ts_nbus->pwm);
+	mutex_unlock(&ts_nbus->lock);
+
+	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 000000000000..5bd4c822f7cf
--- /dev/null
+++ b/include/linux/ts-nbus.h
@@ -0,0 +1,18 @@
+/*
+ * 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
+
+struct ts_nbus;
+
+extern int ts_nbus_read(struct ts_nbus *ts_nbus, u8 adr, u16 *val);
+extern int ts_nbus_write(struct ts_nbus *ts_nbus, u8 adr, u16 val);
+
+#endif /* _TS_NBUS_H */
-- 
2.12.0

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

* [PATCH v3 5/6] ARM: dts: TS-4600: add NBUS support
  2017-05-05 19:32 [PATCH v3 0/6] Add board support for TS-4600 Sebastien Bourdelin
                   ` (3 preceding siblings ...)
  2017-05-05 19:32 ` [PATCH v3 4/6] bus: add driver " Sebastien Bourdelin
@ 2017-05-05 19:32 ` Sebastien Bourdelin
  2017-05-11 13:56   ` Linus Walleij
  2017-05-05 19:32 ` [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
  5 siblings, 1 reply; 17+ messages in thread
From: Sebastien Bourdelin @ 2017-05-05 19:32 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linux, linus.walleij, shawnguo
  Cc: fabio.estevam, mark, kris, 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>
---
Changes v2 -> v3:
  - rebase on master

Changes v1 -> v2:
  - rebase on master
  - remove the simple-bus compatibility as the root node will now
  populate the child nodes (suggested by Rob Herring)
  - add the vendor prefix to all gpio (suggested by Rob Herring)
---
 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 04bd5a5c0cb4..c6282d5479de 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";
+		pinctrl-0 = <&nbus_pins>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pwms = <&pwm 2 83>;
+		ts-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>;
+		ts-csn-gpios    = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+		ts-txrx-gpios   = <&gpio0 24 GPIO_ACTIVE_HIGH>;
+		ts-strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
+		ts-ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+		ts-rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+	};
+
 };
-- 
2.12.0

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

* [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2017-05-05 19:32 [PATCH v3 0/6] Add board support for TS-4600 Sebastien Bourdelin
                   ` (4 preceding siblings ...)
  2017-05-05 19:32 ` [PATCH v3 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
@ 2017-05-05 19:32 ` Sebastien Bourdelin
  2017-05-08 13:27   ` Rob Herring
                     ` (2 more replies)
  5 siblings, 3 replies; 17+ messages in thread
From: Sebastien Bourdelin @ 2017-05-05 19:32 UTC (permalink / raw)
  To: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linux, linus.walleij, shawnguo
  Cc: fabio.estevam, mark, kris, 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>
---
Changes v2 -> v3:
  - rebase on master
  - remove the timeout table to simplify the logic (suggested by
  Guenter Roeck)
  - fix the set_timeout function (suggested by Guenter Roeck)
  - hardcode the max_hw_heartbeat_ms value based on the ts4600 max
  timeout value supported (suggested by Guenter Roeck)
  - remove the max_timeout usage and set a default timeout value
(suggested by Guenter Roeck)
  - use the devm_watchdog_register_device function instead of
  watchdog_register_device (suggested by Guenter Roeck)

Changes v1 -> v2:
  - rebase on master
  - retrieve the ts_nbus instantiated by the parent node (suggested by
  Linus Walleij)
  - rename the wdt by watchdog in the device tree and in the
  documentation (suggested by Rob Herring)
  - add a dependency to the TS_NBUS driver in the Kconfig (suggested by
  Guenter Roeck)
  - simplify the set_timeout function (suggested by Guenter Roeck)
  - use the max_hw_heartbeat_ms callback instead of the max_timeout
  callback (suggested by Guenter Roeck)
---
 .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
 arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +
 drivers/watchdog/Kconfig                           |  11 ++
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/ts4600_wdt.c                      | 185 +++++++++++++++++++++
 5 files changed, 218 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 000000000000..7de00ceae341
--- /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:
+
+watchdog {
+	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 c6282d5479de..092c2eed0fe7 100644
--- a/arch/arm/boot/dts/imx28-ts4600-common.dtsi
+++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
@@ -116,6 +116,11 @@
 		ts-strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
 		ts-ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
 		ts-rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+
+		watchdog@2a {
+			compatible = "technologic,ts4600-wdt";
+			reg = <0x2a>;
+		};
 	};
 
 };
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 52a70ee6014f..408ad7c92cb3 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -520,6 +520,17 @@ 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 TS_NBUS
+	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 a2126e2a99ae..19553f27061a 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -62,6 +62,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 000000000000..ed530dd2f800
--- /dev/null
+++ b/drivers/watchdog/ts4600_wdt.c
@@ -0,0 +1,185 @@
+/*
+ * 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) ")");
+
+/*
+ * 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
+ */
+#define TS4600_WDT_FEED_2S       0x1
+#define TS4600_WDT_FEED_10S      0x2
+#define TS4600_WDT_DISABLE       0x3
+
+struct ts4600_wdt {
+	struct watchdog_device  wdd;
+	struct ts_nbus		*ts_nbus;
+	u32                     feed_offset;
+	u32                     feed_val;
+};
+
+static void ts4600_write_feed(struct ts4600_wdt *wdt, u32 val)
+{
+	ts_nbus_write(wdt->ts_nbus, 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);
+
+	if (timeout <= 2) {
+		wdd->timeout = 2;
+		wdt->feed_val = TS4600_WDT_FEED_2S;
+	} else {
+		wdd->timeout = timeout < 10 ? 10 : timeout;
+		wdt->feed_val = TS4600_WDT_FEED_10S;
+	}
+
+	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 *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct ts_nbus *ts_nbus;
+	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;
+	}
+
+	/* allocate memory for watchdog struct */
+	wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	/* set offset to know where to write */
+	wdt->feed_offset = reg;
+
+	/* keep a pointer to the ts_nbus instanciated by the parent node */
+	ts_nbus = dev_get_drvdata(dev->parent);
+	if (!ts_nbus) {
+		dev_err(dev, "missing ts-nbus compatible parent node\n");
+		return PTR_ERR(ts_nbus);
+	}
+	wdt->ts_nbus = ts_nbus;
+
+	/* Initialize struct watchdog_device */
+	wdd = &wdt->wdd;
+	wdd->parent = dev;
+	wdd->info = &ts4600_wdt_info;
+	wdd->ops = &ts4600_wdt_ops;
+	wdd->min_timeout = 2;
+	wdd->max_hw_heartbeat_ms = 10824;
+	wdd->timeout = 30;
+
+	watchdog_set_drvdata(wdd, wdt);
+	watchdog_set_nowayout(wdd, nowayout);
+	watchdog_init_timeout(wdd, 0, dev);
+
+	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 = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
+	if (ret) {
+		dev_err(dev, "failed to register watchdog device\n");
+		return ret;
+	}
+
+	dev_info(dev, "initialized (timeout = %d sec, nowayout = %d)\n",
+		 wdd->timeout, nowayout);
+
+	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,
+	.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.12.0

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

* Re: [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2017-05-05 19:32 ` [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
@ 2017-05-08 13:27   ` Rob Herring
  2017-05-11  7:22   ` Shawn Guo
  2017-05-14 14:40   ` Guenter Roeck
  2 siblings, 0 replies; 17+ messages in thread
From: Rob Herring @ 2017-05-08 13:27 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, linux, linus.walleij, shawnguo, fabio.estevam, mark,
	kris

On Fri, May 05, 2017 at 03:32:59PM -0400, 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>
> ---
> Changes v2 -> v3:
>   - rebase on master
>   - remove the timeout table to simplify the logic (suggested by
>   Guenter Roeck)
>   - fix the set_timeout function (suggested by Guenter Roeck)
>   - hardcode the max_hw_heartbeat_ms value based on the ts4600 max
>   timeout value supported (suggested by Guenter Roeck)
>   - remove the max_timeout usage and set a default timeout value
> (suggested by Guenter Roeck)
>   - use the devm_watchdog_register_device function instead of
>   watchdog_register_device (suggested by Guenter Roeck)
> 
> Changes v1 -> v2:
>   - rebase on master
>   - retrieve the ts_nbus instantiated by the parent node (suggested by
>   Linus Walleij)
>   - rename the wdt by watchdog in the device tree and in the
>   documentation (suggested by Rob Herring)
>   - add a dependency to the TS_NBUS driver in the Kconfig (suggested by
>   Guenter Roeck)
>   - simplify the set_timeout function (suggested by Guenter Roeck)
>   - use the max_hw_heartbeat_ms callback instead of the max_timeout
>   callback (suggested by Guenter Roeck)
> ---
>  .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
>  arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +

Please add acks when posting new versions. I acked v2.

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

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

* Re: [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2017-05-05 19:32 ` [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
  2017-05-08 13:27   ` Rob Herring
@ 2017-05-11  7:22   ` Shawn Guo
  2017-05-14 14:39     ` Guenter Roeck
  2017-05-14 14:40   ` Guenter Roeck
  2 siblings, 1 reply; 17+ messages in thread
From: Shawn Guo @ 2017-05-11  7:22 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linux, linus.walleij, fabio.estevam, mark, kris

On Fri, May 05, 2017 at 03:32:59PM -0400, 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>
> ---
> Changes v2 -> v3:
>   - rebase on master
>   - remove the timeout table to simplify the logic (suggested by
>   Guenter Roeck)
>   - fix the set_timeout function (suggested by Guenter Roeck)
>   - hardcode the max_hw_heartbeat_ms value based on the ts4600 max
>   timeout value supported (suggested by Guenter Roeck)
>   - remove the max_timeout usage and set a default timeout value
> (suggested by Guenter Roeck)
>   - use the devm_watchdog_register_device function instead of
>   watchdog_register_device (suggested by Guenter Roeck)
> 
> Changes v1 -> v2:
>   - rebase on master
>   - retrieve the ts_nbus instantiated by the parent node (suggested by
>   Linus Walleij)
>   - rename the wdt by watchdog in the device tree and in the
>   documentation (suggested by Rob Herring)
>   - add a dependency to the TS_NBUS driver in the Kconfig (suggested by
>   Guenter Roeck)
>   - simplify the set_timeout function (suggested by Guenter Roeck)
>   - use the max_hw_heartbeat_ms callback instead of the max_timeout
>   callback (suggested by Guenter Roeck)
> ---
>  .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
>  arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +

The dts change shouldn't be mixed within driver patch.

Shawn

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

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

* Re: [PATCH v3 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS
  2017-05-05 19:32 ` [PATCH v3 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
@ 2017-05-11 13:50   ` Linus Walleij
  2017-05-12 15:17   ` Rob Herring
  1 sibling, 0 replies; 17+ messages in thread
From: Linus Walleij @ 2017-05-11 13:50 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, Rob Herring, Guenter Roeck, Shawn Guo, Fabio Estevam,
	Mark Featherston, kris

On Fri, May 5, 2017 at 9:32 PM, Sebastien Bourdelin
<sebastien.bourdelin@savoirfairelinux.com> 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>
> ---
> Changes v2 -> v3:
>   - rebase on master
>   - fix typo (suggested by Rob Herring)

Looks good to me.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v3 4/6] bus: add driver for the Technologic Systems NBUS
  2017-05-05 19:32 ` [PATCH v3 4/6] bus: add driver " Sebastien Bourdelin
@ 2017-05-11 13:56   ` Linus Walleij
  0 siblings, 0 replies; 17+ messages in thread
From: Linus Walleij @ 2017-05-11 13:56 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, Rob Herring, Guenter Roeck, Shawn Guo, Fabio Estevam,
	Mark Featherston, kris

On Fri, May 5, 2017 at 9:32 PM, 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>
> ---
> Changes v2 -> v3:

This driver is pretty.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

For future development (that is not about this patch, please
merge this):

> +static int ts_nbus_read_byte(struct ts_nbus *ts_nbus, u8 *val)
> +{
> +       struct gpio_descs *gpios = ts_nbus->data;
> +       int ret, i;
> +
> +       *val = 0;
> +       for (i = 0; i < 8; i++) {
> +               ret = gpiod_get_value_cansleep(gpios->desc[i]);
> +               if (ret < 0)
> +                       return ret;
> +               if (ret)
> +                       *val |= BIT(i);
> +       }
> +
> +       return 0;
> +}

That makes it pretty obvious that we really need gpiod_get_array_cansleep()
does it not. That would just become some single register read in
this case.

If you get some time one of these days and wand to have a go at adding
it to gpiolib using this driver as a testbed, do not hesitate.

Yours,
Linus Walleij

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

* Re: [PATCH v3 5/6] ARM: dts: TS-4600: add NBUS support
  2017-05-05 19:32 ` [PATCH v3 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
@ 2017-05-11 13:56   ` Linus Walleij
  0 siblings, 0 replies; 17+ messages in thread
From: Linus Walleij @ 2017-05-11 13:56 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, Rob Herring, Guenter Roeck, Shawn Guo, Fabio Estevam,
	Mark Featherston, kris

On Fri, May 5, 2017 at 9:32 PM, 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>
> ---
> Changes v2 -> v3:
>   - rebase on master

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v3 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS
  2017-05-05 19:32 ` [PATCH v3 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
  2017-05-11 13:50   ` Linus Walleij
@ 2017-05-12 15:17   ` Rob Herring
  1 sibling, 0 replies; 17+ messages in thread
From: Rob Herring @ 2017-05-12 15:17 UTC (permalink / raw)
  To: Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, linux, linus.walleij, shawnguo, fabio.estevam, mark,
	kris

On Fri, May 05, 2017 at 03:32:56PM -0400, 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>
> ---
> Changes v2 -> v3:
>   - rebase on master
>   - fix typo (suggested by Rob Herring)
> 
> Changes v1 -> v2:
>   - rebase on master
>   - remove the simple-bus compatibility as the root node will now
>   populate child nodes (suggested by Rob Herring)
>   - use the ts vendor prefix for gpios (suggested by Rob Herring)
> ---
>  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 000000000000..905600adfb64
> --- /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"
> + - #address-cells	: must be 1
> + - #size-cells		: must be 0
> + - pwms			: The PWM bound to the FPGA
> + - ts-data-gpios	: The 8 GPIO pins connected to the data lines on the FPGA
> + - ts-csn-gpios		: The GPIO pin connected to the csn line on the FPGA
> + - ts-txrx-gpios	: The GPIO pin connected to the txrx line on the FPGA
> + - ts-strobe-gpios	: The GPIO pin connected to the stobe line on the FPGA
> + - ts-ale-gpios		: The GPIO pin connected to the ale line on the FPGA
> + - ts-rdy-gpios		: The GPIO pin connected to the rdy line on the FPGA

Vendor prefixes are in the form <vendor>,<propname>. So ts,rdy-gpios.

Rob

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

* Re: [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2017-05-11  7:22   ` Shawn Guo
@ 2017-05-14 14:39     ` Guenter Roeck
  2017-05-15  2:00       ` Shawn Guo
  0 siblings, 1 reply; 17+ messages in thread
From: Guenter Roeck @ 2017-05-14 14:39 UTC (permalink / raw)
  To: Shawn Guo, Sebastien Bourdelin
  Cc: linux-kernel, linux-watchdog, linux-arm-kernel, devicetree,
	kernel, robh, linus.walleij, fabio.estevam, mark, kris

On 05/11/2017 12:22 AM, Shawn Guo wrote:
> On Fri, May 05, 2017 at 03:32:59PM -0400, 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>
>> ---
>> Changes v2 -> v3:
>>   - rebase on master
>>   - remove the timeout table to simplify the logic (suggested by
>>   Guenter Roeck)
>>   - fix the set_timeout function (suggested by Guenter Roeck)
>>   - hardcode the max_hw_heartbeat_ms value based on the ts4600 max
>>   timeout value supported (suggested by Guenter Roeck)
>>   - remove the max_timeout usage and set a default timeout value
>> (suggested by Guenter Roeck)
>>   - use the devm_watchdog_register_device function instead of
>>   watchdog_register_device (suggested by Guenter Roeck)
>>
>> Changes v1 -> v2:
>>   - rebase on master
>>   - retrieve the ts_nbus instantiated by the parent node (suggested by
>>   Linus Walleij)
>>   - rename the wdt by watchdog in the device tree and in the
>>   documentation (suggested by Rob Herring)
>>   - add a dependency to the TS_NBUS driver in the Kconfig (suggested by
>>   Guenter Roeck)
>>   - simplify the set_timeout function (suggested by Guenter Roeck)
>>   - use the max_hw_heartbeat_ms callback instead of the max_timeout
>>   callback (suggested by Guenter Roeck)
>> ---
>>  .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
>>  arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +
>
> The dts change shouldn't be mixed within driver patch.
>

Maybe, but Rob Acked the devicetree changes, so I don't see a reason
for splitting it up now.

Guenter

> Shawn
>
>>  drivers/watchdog/Kconfig                           |  11 ++
>>  drivers/watchdog/Makefile                          |   1 +
>>  drivers/watchdog/ts4600_wdt.c                      | 185 +++++++++++++++++++++
>>  5 files changed, 218 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/watchdog/ts4600-wdt.txt
>>  create mode 100644 drivers/watchdog/ts4600_wdt.c
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

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

* Re: [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2017-05-05 19:32 ` [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
  2017-05-08 13:27   ` Rob Herring
  2017-05-11  7:22   ` Shawn Guo
@ 2017-05-14 14:40   ` Guenter Roeck
  2 siblings, 0 replies; 17+ messages in thread
From: Guenter Roeck @ 2017-05-14 14:40 UTC (permalink / raw)
  To: Sebastien Bourdelin, linux-kernel, linux-watchdog,
	linux-arm-kernel, devicetree, kernel, robh, linus.walleij,
	shawnguo
  Cc: fabio.estevam, mark, kris

On 05/05/2017 12:32 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>

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

When you send v4, please retain unless you make other changes.

Thanks,
Guenter

> ---
> Changes v2 -> v3:
>   - rebase on master
>   - remove the timeout table to simplify the logic (suggested by
>   Guenter Roeck)
>   - fix the set_timeout function (suggested by Guenter Roeck)
>   - hardcode the max_hw_heartbeat_ms value based on the ts4600 max
>   timeout value supported (suggested by Guenter Roeck)
>   - remove the max_timeout usage and set a default timeout value
> (suggested by Guenter Roeck)
>   - use the devm_watchdog_register_device function instead of
>   watchdog_register_device (suggested by Guenter Roeck)
>
> Changes v1 -> v2:
>   - rebase on master
>   - retrieve the ts_nbus instantiated by the parent node (suggested by
>   Linus Walleij)
>   - rename the wdt by watchdog in the device tree and in the
>   documentation (suggested by Rob Herring)
>   - add a dependency to the TS_NBUS driver in the Kconfig (suggested by
>   Guenter Roeck)
>   - simplify the set_timeout function (suggested by Guenter Roeck)
>   - use the max_hw_heartbeat_ms callback instead of the max_timeout
>   callback (suggested by Guenter Roeck)
> ---
>  .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
>  arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +
>  drivers/watchdog/Kconfig                           |  11 ++
>  drivers/watchdog/Makefile                          |   1 +
>  drivers/watchdog/ts4600_wdt.c                      | 185 +++++++++++++++++++++
>  5 files changed, 218 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 000000000000..7de00ceae341
> --- /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:
> +
> +watchdog {
> +	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 c6282d5479de..092c2eed0fe7 100644
> --- a/arch/arm/boot/dts/imx28-ts4600-common.dtsi
> +++ b/arch/arm/boot/dts/imx28-ts4600-common.dtsi
> @@ -116,6 +116,11 @@
>  		ts-strobe-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
>  		ts-ale-gpios    = <&gpio0 26 GPIO_ACTIVE_HIGH>;
>  		ts-rdy-gpios    = <&gpio0 21 GPIO_ACTIVE_HIGH>;
> +
> +		watchdog@2a {
> +			compatible = "technologic,ts4600-wdt";
> +			reg = <0x2a>;
> +		};
>  	};
>
>  };
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 52a70ee6014f..408ad7c92cb3 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -520,6 +520,17 @@ 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 TS_NBUS
> +	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 a2126e2a99ae..19553f27061a 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -62,6 +62,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 000000000000..ed530dd2f800
> --- /dev/null
> +++ b/drivers/watchdog/ts4600_wdt.c
> @@ -0,0 +1,185 @@
> +/*
> + * 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) ")");
> +
> +/*
> + * 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
> + */
> +#define TS4600_WDT_FEED_2S       0x1
> +#define TS4600_WDT_FEED_10S      0x2
> +#define TS4600_WDT_DISABLE       0x3
> +
> +struct ts4600_wdt {
> +	struct watchdog_device  wdd;
> +	struct ts_nbus		*ts_nbus;
> +	u32                     feed_offset;
> +	u32                     feed_val;
> +};
> +
> +static void ts4600_write_feed(struct ts4600_wdt *wdt, u32 val)
> +{
> +	ts_nbus_write(wdt->ts_nbus, 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);
> +
> +	if (timeout <= 2) {
> +		wdd->timeout = 2;
> +		wdt->feed_val = TS4600_WDT_FEED_2S;
> +	} else {
> +		wdd->timeout = timeout < 10 ? 10 : timeout;
> +		wdt->feed_val = TS4600_WDT_FEED_10S;
> +	}
> +
> +	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 *dev = &pdev->dev;
> +	struct device_node *np = dev->of_node;
> +	struct ts_nbus *ts_nbus;
> +	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;
> +	}
> +
> +	/* allocate memory for watchdog struct */
> +	wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
> +	if (!wdt)
> +		return -ENOMEM;
> +
> +	/* set offset to know where to write */
> +	wdt->feed_offset = reg;
> +
> +	/* keep a pointer to the ts_nbus instanciated by the parent node */
> +	ts_nbus = dev_get_drvdata(dev->parent);
> +	if (!ts_nbus) {
> +		dev_err(dev, "missing ts-nbus compatible parent node\n");
> +		return PTR_ERR(ts_nbus);
> +	}
> +	wdt->ts_nbus = ts_nbus;
> +
> +	/* Initialize struct watchdog_device */
> +	wdd = &wdt->wdd;
> +	wdd->parent = dev;
> +	wdd->info = &ts4600_wdt_info;
> +	wdd->ops = &ts4600_wdt_ops;
> +	wdd->min_timeout = 2;
> +	wdd->max_hw_heartbeat_ms = 10824;
> +	wdd->timeout = 30;
> +
> +	watchdog_set_drvdata(wdd, wdt);
> +	watchdog_set_nowayout(wdd, nowayout);
> +	watchdog_init_timeout(wdd, 0, dev);
> +
> +	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 = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
> +	if (ret) {
> +		dev_err(dev, "failed to register watchdog device\n");
> +		return ret;
> +	}
> +
> +	dev_info(dev, "initialized (timeout = %d sec, nowayout = %d)\n",
> +		 wdd->timeout, nowayout);
> +
> +	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,
> +	.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] 17+ messages in thread

* Re: [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2017-05-14 14:39     ` Guenter Roeck
@ 2017-05-15  2:00       ` Shawn Guo
  2017-05-15  2:30         ` Guenter Roeck
  0 siblings, 1 reply; 17+ messages in thread
From: Shawn Guo @ 2017-05-15  2:00 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Sebastien Bourdelin, robh, linux-watchdog, mark, devicetree,
	linus.walleij, linux-kernel, kris, kernel, fabio.estevam,
	linux-arm-kernel

On Sun, May 14, 2017 at 07:39:33AM -0700, Guenter Roeck wrote:
> On 05/11/2017 12:22 AM, Shawn Guo wrote:
> >On Fri, May 05, 2017 at 03:32:59PM -0400, 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>
> >>---
> >>Changes v2 -> v3:
> >>  - rebase on master
> >>  - remove the timeout table to simplify the logic (suggested by
> >>  Guenter Roeck)
> >>  - fix the set_timeout function (suggested by Guenter Roeck)
> >>  - hardcode the max_hw_heartbeat_ms value based on the ts4600 max
> >>  timeout value supported (suggested by Guenter Roeck)
> >>  - remove the max_timeout usage and set a default timeout value
> >>(suggested by Guenter Roeck)
> >>  - use the devm_watchdog_register_device function instead of
> >>  watchdog_register_device (suggested by Guenter Roeck)
> >>
> >>Changes v1 -> v2:
> >>  - rebase on master
> >>  - retrieve the ts_nbus instantiated by the parent node (suggested by
> >>  Linus Walleij)
> >>  - rename the wdt by watchdog in the device tree and in the
> >>  documentation (suggested by Rob Herring)
> >>  - add a dependency to the TS_NBUS driver in the Kconfig (suggested by
> >>  Guenter Roeck)
> >>  - simplify the set_timeout function (suggested by Guenter Roeck)
> >>  - use the max_hw_heartbeat_ms callback instead of the max_timeout
> >>  callback (suggested by Guenter Roeck)
> >>---
> >> .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
> >> arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +
> >
> >The dts change shouldn't be mixed within driver patch.
> >
> 
> Maybe, but Rob Acked the devicetree changes, so I don't see a reason
> for splitting it up now.

What Rob Acked is devicetree bindings, and ARM dts changes should
normally go via arm-soc tree, unless there is a good reason they
shouldn't.

Shawn

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

* Re: [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
  2017-05-15  2:00       ` Shawn Guo
@ 2017-05-15  2:30         ` Guenter Roeck
  0 siblings, 0 replies; 17+ messages in thread
From: Guenter Roeck @ 2017-05-15  2:30 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Sebastien Bourdelin, robh, linux-watchdog, mark, devicetree,
	linus.walleij, linux-kernel, kris, kernel, fabio.estevam,
	linux-arm-kernel

On 05/14/2017 07:00 PM, Shawn Guo wrote:
> On Sun, May 14, 2017 at 07:39:33AM -0700, Guenter Roeck wrote:
>> On 05/11/2017 12:22 AM, Shawn Guo wrote:
>>> On Fri, May 05, 2017 at 03:32:59PM -0400, 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>
>>>> ---
>>>> Changes v2 -> v3:
>>>>  - rebase on master
>>>>  - remove the timeout table to simplify the logic (suggested by
>>>>  Guenter Roeck)
>>>>  - fix the set_timeout function (suggested by Guenter Roeck)
>>>>  - hardcode the max_hw_heartbeat_ms value based on the ts4600 max
>>>>  timeout value supported (suggested by Guenter Roeck)
>>>>  - remove the max_timeout usage and set a default timeout value
>>>> (suggested by Guenter Roeck)
>>>>  - use the devm_watchdog_register_device function instead of
>>>>  watchdog_register_device (suggested by Guenter Roeck)
>>>>
>>>> Changes v1 -> v2:
>>>>  - rebase on master
>>>>  - retrieve the ts_nbus instantiated by the parent node (suggested by
>>>>  Linus Walleij)
>>>>  - rename the wdt by watchdog in the device tree and in the
>>>>  documentation (suggested by Rob Herring)
>>>>  - add a dependency to the TS_NBUS driver in the Kconfig (suggested by
>>>>  Guenter Roeck)
>>>>  - simplify the set_timeout function (suggested by Guenter Roeck)
>>>>  - use the max_hw_heartbeat_ms callback instead of the max_timeout
>>>>  callback (suggested by Guenter Roeck)
>>>> ---
>>>> .../devicetree/bindings/watchdog/ts4600-wdt.txt    |  16 ++
>>>> arch/arm/boot/dts/imx28-ts4600-common.dtsi         |   5 +
>>>
>>> The dts change shouldn't be mixed within driver patch.
>>>
>>
>> Maybe, but Rob Acked the devicetree changes, so I don't see a reason
>> for splitting it up now.
>
> What Rob Acked is devicetree bindings, and ARM dts changes should
> normally go via arm-soc tree, unless there is a good reason they
> shouldn't.
>
Ok, good point.

Guenter

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

end of thread, other threads:[~2017-05-15  2:30 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-05 19:32 [PATCH v3 0/6] Add board support for TS-4600 Sebastien Bourdelin
2017-05-05 19:32 ` [PATCH v3 1/6] of: documentation: add bindings documentation " Sebastien Bourdelin
2017-05-05 19:32 ` [PATCH v3 2/6] ARM: dts: TS-4600: add basic device tree Sebastien Bourdelin
2017-05-05 19:32 ` [PATCH v3 3/6] dt-bindings: bus: Add documentation for the Technologic Systems NBUS Sebastien Bourdelin
2017-05-11 13:50   ` Linus Walleij
2017-05-12 15:17   ` Rob Herring
2017-05-05 19:32 ` [PATCH v3 4/6] bus: add driver " Sebastien Bourdelin
2017-05-11 13:56   ` Linus Walleij
2017-05-05 19:32 ` [PATCH v3 5/6] ARM: dts: TS-4600: add NBUS support Sebastien Bourdelin
2017-05-11 13:56   ` Linus Walleij
2017-05-05 19:32 ` [PATCH v3 6/6] watchdog: ts4600: add driver for TS-4600 watchdog Sebastien Bourdelin
2017-05-08 13:27   ` Rob Herring
2017-05-11  7:22   ` Shawn Guo
2017-05-14 14:39     ` Guenter Roeck
2017-05-15  2:00       ` Shawn Guo
2017-05-15  2:30         ` Guenter Roeck
2017-05-14 14:40   ` Guenter Roeck

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