summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-sprd-adi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi-sprd-adi.c')
-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}