summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorBaolin Wang <baolin.wang@linaro.org>2018-03-19 22:42:14 -0400
committerMark Brown <broonie@kernel.org>2018-03-20 21:55:19 -0400
commitac1775012058e13ef1522938e27f5973d9e3f053 (patch)
treec64b5a4f26a2a7094c76d6e444718983b17f751a /drivers/spi
parenta61aa683655f3182aca6e38404ae9aac03e771ae (diff)
spi: sprd: Add the support of restarting the system
On Spreadtrum platform, we use one PMIC watchdog to reset the whole system with loading one suitable timeout value (usually 50ms) for the watchdog. In theory, we should implement the restart function in drivers/power/reset subsystem to access the PMIC watchdog with regmap. When restart the system, other cores will be stopped by IPI, but if other cores were accessing PMIC with holding the regmap mutex lock, that will cause dead-lock issue if we try to access the PMIC watchdog with regmap to restart the whole system. Thus we can implement the restart function in ADI driver to avoid this issue. Signed-off-by: Baolin Wang <baolin.wang@linaro.org> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-sprd-adi.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c
index 74bbd045aac0..197d4b0d81af 100644
--- a/drivers/spi/spi-sprd-adi.c
+++ b/drivers/spi/spi-sprd-adi.c
@@ -4,6 +4,7 @@
4 * SPDX-License-Identifier: GPL-2.0 4 * SPDX-License-Identifier: GPL-2.0
5 */ 5 */
6 6
7#include <linux/delay.h>
7#include <linux/hwspinlock.h> 8#include <linux/hwspinlock.h>
8#include <linux/init.h> 9#include <linux/init.h>
9#include <linux/io.h> 10#include <linux/io.h>
@@ -12,6 +13,7 @@
12#include <linux/of.h> 13#include <linux/of.h>
13#include <linux/of_device.h> 14#include <linux/of_device.h>
14#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/reboot.h>
15#include <linux/spi/spi.h> 17#include <linux/spi/spi.h>
16#include <linux/sizes.h> 18#include <linux/sizes.h>
17 19
@@ -67,6 +69,40 @@
67#define ADI_READ_TIMEOUT 2000 69#define ADI_READ_TIMEOUT 2000
68#define REG_ADDR_LOW_MASK GENMASK(11, 0) 70#define REG_ADDR_LOW_MASK GENMASK(11, 0)
69 71
72/* Registers definitions for PMIC watchdog controller */
73#define REG_WDG_LOAD_LOW 0x80
74#define REG_WDG_LOAD_HIGH 0x84
75#define REG_WDG_CTRL 0x88
76#define REG_WDG_LOCK 0xa0
77
78/* Bits definitions for register REG_WDG_CTRL */
79#define BIT_WDG_RUN BIT(1)
80#define BIT_WDG_RST BIT(3)
81
82/* Registers definitions for PMIC */
83#define PMIC_RST_STATUS 0xee8
84#define PMIC_MODULE_EN 0xc08
85#define PMIC_CLK_EN 0xc18
86#define BIT_WDG_EN BIT(2)
87
88/* Definition of PMIC reset status register */
89#define HWRST_STATUS_RECOVERY 0x20
90#define HWRST_STATUS_NORMAL 0x40
91#define HWRST_STATUS_ALARM 0x50
92#define HWRST_STATUS_SLEEP 0x60
93#define HWRST_STATUS_FASTBOOT 0x30
94#define HWRST_STATUS_SPECIAL 0x70
95#define HWRST_STATUS_PANIC 0x80
96#define HWRST_STATUS_CFTREBOOT 0x90
97#define HWRST_STATUS_AUTODLOADER 0xa0
98#define HWRST_STATUS_IQMODE 0xb0
99#define HWRST_STATUS_SPRDISK 0xc0
100
101/* Use default timeout 50 ms that converts to watchdog values */
102#define WDG_LOAD_VAL ((50 * 1000) / 32768)
103#define WDG_LOAD_MASK GENMASK(15, 0)
104#define WDG_UNLOCK_KEY 0xe551
105
70struct sprd_adi { 106struct sprd_adi {
71 struct spi_controller *ctlr; 107 struct spi_controller *ctlr;
72 struct device *dev; 108 struct device *dev;
@@ -74,6 +110,7 @@ struct sprd_adi {
74 struct hwspinlock *hwlock; 110 struct hwspinlock *hwlock;
75 unsigned long slave_vbase; 111 unsigned long slave_vbase;
76 unsigned long slave_pbase; 112 unsigned long slave_pbase;
113 struct notifier_block restart_handler;
77}; 114};
78 115
79static int sprd_adi_check_paddr(struct sprd_adi *sadi, u32 paddr) 116static int sprd_adi_check_paddr(struct sprd_adi *sadi, u32 paddr)
@@ -270,6 +307,72 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr,
270 return 0; 307 return 0;
271} 308}
272 309
310static int sprd_adi_restart_handler(struct notifier_block *this,
311 unsigned long mode, void *cmd)
312{
313 struct sprd_adi *sadi = container_of(this, struct sprd_adi,
314 restart_handler);
315 u32 val, reboot_mode = 0;
316
317 if (!cmd)
318 reboot_mode = HWRST_STATUS_NORMAL;
319 else if (!strncmp(cmd, "recovery", 8))
320 reboot_mode = HWRST_STATUS_RECOVERY;
321 else if (!strncmp(cmd, "alarm", 5))
322 reboot_mode = HWRST_STATUS_ALARM;
323 else if (!strncmp(cmd, "fastsleep", 9))
324 reboot_mode = HWRST_STATUS_SLEEP;
325 else if (!strncmp(cmd, "bootloader", 10))
326 reboot_mode = HWRST_STATUS_FASTBOOT;
327 else if (!strncmp(cmd, "panic", 5))
328 reboot_mode = HWRST_STATUS_PANIC;
329 else if (!strncmp(cmd, "special", 7))
330 reboot_mode = HWRST_STATUS_SPECIAL;
331 else if (!strncmp(cmd, "cftreboot", 9))
332 reboot_mode = HWRST_STATUS_CFTREBOOT;
333 else if (!strncmp(cmd, "autodloader", 11))
334 reboot_mode = HWRST_STATUS_AUTODLOADER;
335 else if (!strncmp(cmd, "iqmode", 6))
336 reboot_mode = HWRST_STATUS_IQMODE;
337 else if (!strncmp(cmd, "sprdisk", 7))
338 reboot_mode = HWRST_STATUS_SPRDISK;
339 else
340 reboot_mode = HWRST_STATUS_NORMAL;
341
342 /* Record the reboot mode */
343 sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val);
344 val |= reboot_mode;
345 sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val);
346
347 /* Enable the interface clock of the watchdog */
348 sprd_adi_read(sadi, sadi->slave_pbase + PMIC_MODULE_EN, &val);
349 val |= BIT_WDG_EN;
350 sprd_adi_write(sadi, sadi->slave_pbase + PMIC_MODULE_EN, val);
351
352 /* Enable the work clock of the watchdog */
353 sprd_adi_read(sadi, sadi->slave_pbase + PMIC_CLK_EN, &val);
354 val |= BIT_WDG_EN;
355 sprd_adi_write(sadi, sadi->slave_pbase + PMIC_CLK_EN, val);
356
357 /* Unlock the watchdog */
358 sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, WDG_UNLOCK_KEY);
359
360 /* Load the watchdog timeout value, 50ms is always enough. */
361 sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_LOW,
362 WDG_LOAD_VAL & WDG_LOAD_MASK);
363 sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_HIGH, 0);
364
365 /* Start the watchdog to reset system */
366 sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val);
367 val |= BIT_WDG_RUN | BIT_WDG_RST;
368 sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val);
369
370 mdelay(1000);
371
372 dev_emerg(sadi->dev, "Unable to restart system\n");
373 return NOTIFY_DONE;
374}
375
273static void sprd_adi_hw_init(struct sprd_adi *sadi) 376static void sprd_adi_hw_init(struct sprd_adi *sadi)
274{ 377{
275 struct device_node *np = sadi->dev->of_node; 378 struct device_node *np = sadi->dev->of_node;
@@ -383,6 +486,14 @@ static int sprd_adi_probe(struct platform_device *pdev)
383 goto free_hwlock; 486 goto free_hwlock;
384 } 487 }
385 488
489 sadi->restart_handler.notifier_call = sprd_adi_restart_handler;
490 sadi->restart_handler.priority = 128;
491 ret = register_restart_handler(&sadi->restart_handler);
492 if (ret) {
493 dev_err(&pdev->dev, "can not register restart handler\n");
494 goto free_hwlock;
495 }
496
386 return 0; 497 return 0;
387 498
388free_hwlock: 499free_hwlock:
@@ -397,6 +508,7 @@ static int sprd_adi_remove(struct platform_device *pdev)
397 struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev); 508 struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev);
398 struct sprd_adi *sadi = spi_controller_get_devdata(ctlr); 509 struct sprd_adi *sadi = spi_controller_get_devdata(ctlr);
399 510
511 unregister_restart_handler(&sadi->restart_handler);
400 hwspin_lock_free(sadi->hwlock); 512 hwspin_lock_free(sadi->hwlock);
401 return 0; 513 return 0;
402} 514}