[PATCH v5 2/2] watchdog: Add Spreadtrum watchdog driver

2017-11-03 Thread Eric Long
This patch adds the watchdog driver for Spreadtrum SC9860 platform.

Signed-off-by: Eric Long 
---
Changes since v4:
 - Remove sprd_wdt_remove().
 - Add devm_add_action() for sprd_wdt_disable().

Changes since v3:
 - Update Kconfig SPRD_WATCHDOG help messages.
 - Correct the wrong spell words.
 - Rename SPRD_WDT_CNT_HIGH_VALUE as SPRD_WDT_CNT_HIGH_SHIFT.
 - Remove unused macor.
 - Update sprd_wdt_set_pretimeout() api.
 - Add wdt->wdd.timeout default value.
 - Use devm_watchdog_register_device() to register wdt device.
 - If module does not support NOWAYOUT, disable wdt when remove this driver.
 - Call sprd_wdt_disable() every wdt suspend.

Changes since v2:
 - Rename all the macors, add SPRD tag at the head of the macro names.
 - Rename SPRD_WDT_CLK as SPRD_WTC_CNT_STEP.
 - Remove the code which check timeout value at the wrong place.
 - Add min/max timeout value limit.
 - Remove set WDOG_HW_RUNNING status at sprd_wdt_enable().
 - Add timeout/pretimeout judgment when set them.
 - Support WATCHDOG_NOWAYOUT status.

Changes since v1:
 - Use pretimeout instead of own implementation.
 - Fix timeout loop when loading timeout values.
 - use the infrastructure to read and set "timeout-sec" property.
 - Add conditions when start or stop watchdog.
 - Change the position of enabling watchdog.
 - Other optimization.
---
 drivers/watchdog/Kconfig|   8 +
 drivers/watchdog/Makefile   |   1 +
 drivers/watchdog/sprd_wdt.c | 407 
 3 files changed, 416 insertions(+)
 create mode 100644 drivers/watchdog/sprd_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c722cbf..3367a8c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -787,6 +787,14 @@ config UNIPHIER_WATCHDOG
  To compile this driver as a module, choose M here: the
  module will be called uniphier_wdt.
 
+config SPRD_WATCHDOG
+   tristate "Spreadtrum watchdog support"
+   depends on ARCH_SPRD || COMPILE_TEST
+   select WATCHDOG_CORE
+   help
+ Say Y here to include watchdog timer supported
+ by Spreadtrum system.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 56adf9f..187cca2 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
 obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o
 obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o
 obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o
+obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c
new file mode 100644
index 000..88f6f84
--- /dev/null
+++ b/drivers/watchdog/sprd_wdt.c
@@ -0,0 +1,407 @@
+/*
+ * Spreadtrum watchdog driver
+ * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SPRD_WDT_LOAD_LOW  0x0
+#define SPRD_WDT_LOAD_HIGH 0x4
+#define SPRD_WDT_CTRL  0x8
+#define SPRD_WDT_INT_CLR   0xc
+#define SPRD_WDT_INT_RAW   0x10
+#define SPRD_WDT_INT_MSK   0x14
+#define SPRD_WDT_CNT_LOW   0x18
+#define SPRD_WDT_CNT_HIGH  0x1c
+#define SPRD_WDT_LOCK  0x20
+#define SPRD_WDT_IRQ_LOAD_LOW  0x2c
+#define SPRD_WDT_IRQ_LOAD_HIGH 0x30
+
+/* WDT_CTRL */
+#define SPRD_WDT_INT_EN_BITBIT(0)
+#define SPRD_WDT_CNT_EN_BITBIT(1)
+#define SPRD_WDT_NEW_VER_ENBIT(2)
+#define SPRD_WDT_RST_EN_BITBIT(3)
+
+/* WDT_INT_CLR */
+#define SPRD_WDT_INT_CLEAR_BIT BIT(0)
+#define SPRD_WDT_RST_CLEAR_BIT BIT(3)
+
+/* WDT_INT_RAW */
+#define SPRD_WDT_INT_RAW_BIT   BIT(0)
+#define SPRD_WDT_RST_RAW_BIT   BIT(3)
+#define SPRD_WDT_LD_BUSY_BIT   BIT(4)
+
+/* 1s equal to 32768 counter steps */
+#define SPRD_WDT_CNT_STEP  32768
+
+#define SPRD_WDT_UNLOCK_KEY0xe551
+#define SPRD_WDT_MIN_TIMEOUT   3
+#define SPRD_WDT_MAX_TIMEOUT   60
+
+#define SPRD_WDT_CNT_HIGH_SHIFT16
+#define SPRD_WDT_LOW_VALUE_MASKGENMASK(15, 0)
+#define SPRD_WDT_LOAD_TIMEOUT  1000
+
+struct sprd_wdt {
+   void __iomem *base;
+   struct watchdog_device 

[PATCH v5 2/2] watchdog: Add Spreadtrum watchdog driver

2017-11-03 Thread Eric Long
This patch adds the watchdog driver for Spreadtrum SC9860 platform.

Signed-off-by: Eric Long 
---
Changes since v4:
 - Remove sprd_wdt_remove().
 - Add devm_add_action() for sprd_wdt_disable().

Changes since v3:
 - Update Kconfig SPRD_WATCHDOG help messages.
 - Correct the wrong spell words.
 - Rename SPRD_WDT_CNT_HIGH_VALUE as SPRD_WDT_CNT_HIGH_SHIFT.
 - Remove unused macor.
 - Update sprd_wdt_set_pretimeout() api.
 - Add wdt->wdd.timeout default value.
 - Use devm_watchdog_register_device() to register wdt device.
 - If module does not support NOWAYOUT, disable wdt when remove this driver.
 - Call sprd_wdt_disable() every wdt suspend.

Changes since v2:
 - Rename all the macors, add SPRD tag at the head of the macro names.
 - Rename SPRD_WDT_CLK as SPRD_WTC_CNT_STEP.
 - Remove the code which check timeout value at the wrong place.
 - Add min/max timeout value limit.
 - Remove set WDOG_HW_RUNNING status at sprd_wdt_enable().
 - Add timeout/pretimeout judgment when set them.
 - Support WATCHDOG_NOWAYOUT status.

Changes since v1:
 - Use pretimeout instead of own implementation.
 - Fix timeout loop when loading timeout values.
 - use the infrastructure to read and set "timeout-sec" property.
 - Add conditions when start or stop watchdog.
 - Change the position of enabling watchdog.
 - Other optimization.
---
 drivers/watchdog/Kconfig|   8 +
 drivers/watchdog/Makefile   |   1 +
 drivers/watchdog/sprd_wdt.c | 407 
 3 files changed, 416 insertions(+)
 create mode 100644 drivers/watchdog/sprd_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c722cbf..3367a8c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -787,6 +787,14 @@ config UNIPHIER_WATCHDOG
  To compile this driver as a module, choose M here: the
  module will be called uniphier_wdt.
 
+config SPRD_WATCHDOG
+   tristate "Spreadtrum watchdog support"
+   depends on ARCH_SPRD || COMPILE_TEST
+   select WATCHDOG_CORE
+   help
+ Say Y here to include watchdog timer supported
+ by Spreadtrum system.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 56adf9f..187cca2 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
 obj-$(CONFIG_ZX2967_WATCHDOG) += zx2967_wdt.o
 obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o
 obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o
+obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c
new file mode 100644
index 000..88f6f84
--- /dev/null
+++ b/drivers/watchdog/sprd_wdt.c
@@ -0,0 +1,407 @@
+/*
+ * Spreadtrum watchdog driver
+ * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SPRD_WDT_LOAD_LOW  0x0
+#define SPRD_WDT_LOAD_HIGH 0x4
+#define SPRD_WDT_CTRL  0x8
+#define SPRD_WDT_INT_CLR   0xc
+#define SPRD_WDT_INT_RAW   0x10
+#define SPRD_WDT_INT_MSK   0x14
+#define SPRD_WDT_CNT_LOW   0x18
+#define SPRD_WDT_CNT_HIGH  0x1c
+#define SPRD_WDT_LOCK  0x20
+#define SPRD_WDT_IRQ_LOAD_LOW  0x2c
+#define SPRD_WDT_IRQ_LOAD_HIGH 0x30
+
+/* WDT_CTRL */
+#define SPRD_WDT_INT_EN_BITBIT(0)
+#define SPRD_WDT_CNT_EN_BITBIT(1)
+#define SPRD_WDT_NEW_VER_ENBIT(2)
+#define SPRD_WDT_RST_EN_BITBIT(3)
+
+/* WDT_INT_CLR */
+#define SPRD_WDT_INT_CLEAR_BIT BIT(0)
+#define SPRD_WDT_RST_CLEAR_BIT BIT(3)
+
+/* WDT_INT_RAW */
+#define SPRD_WDT_INT_RAW_BIT   BIT(0)
+#define SPRD_WDT_RST_RAW_BIT   BIT(3)
+#define SPRD_WDT_LD_BUSY_BIT   BIT(4)
+
+/* 1s equal to 32768 counter steps */
+#define SPRD_WDT_CNT_STEP  32768
+
+#define SPRD_WDT_UNLOCK_KEY0xe551
+#define SPRD_WDT_MIN_TIMEOUT   3
+#define SPRD_WDT_MAX_TIMEOUT   60
+
+#define SPRD_WDT_CNT_HIGH_SHIFT16
+#define SPRD_WDT_LOW_VALUE_MASKGENMASK(15, 0)
+#define SPRD_WDT_LOAD_TIMEOUT  1000
+
+struct sprd_wdt {
+   void __iomem *base;
+   struct watchdog_device wdd;
+   struct clk