2 * Rockchip SoCs Reboot Driver
4 * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/platform_device.h>
12 #include <linux/reboot.h>
13 #include <linux/regmap.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/rockchip/common.h>
17 #include <asm/system_misc.h>
19 /* high 24 bits is tag, low 8 bits is type */
20 #define SYS_LOADER_REBOOT_FLAG 0x5242C300
21 #define SYS_KERNRL_REBOOT_FLAG 0xC3524200
24 BOOT_NORMAL = 0,/* normal boot */
25 BOOT_LOADER, /* enter loader rockusb mode */
26 BOOT_MASKROM, /* enter maskrom rockusb mode (not support now) */
27 BOOT_RECOVER, /* enter recover */
28 BOOT_NORECOVER, /* do not enter recover */
29 BOOT_SECONDOS, /* boot second OS (not support now) */
30 BOOT_WIPEDATA, /* enter recover and wipe data */
31 BOOT_WIPEALL, /* enter recover and wipe all data */
32 BOOT_CHECKIMG, /* check firmware img with backup part in loader mode */
33 BOOT_FASTBOOT, /* enter fast boot mode */
34 BOOT_SECUREBOOT_DISABLE,
35 BOOT_CHARGING, /* enter charge mode */
36 BOOT_MAX, /* MAX VALID BOOT TYPE */
39 static struct regmap *cru;
40 static struct regmap *pmugrf;
42 #define RK3368_CRU_APLLB_CON3 0x0c
43 #define RK3368_CRU_APLLL_CON3 0x01c
44 #define RK3368_CRU_CPLL_CON3 0x03c
45 #define RK3368_CRU_GPLL_CON3 0x04c
46 #define RK3368_CRU_NPLL_CON3 0x05c
47 #define RK3368_CRU_GLB_SRST_FST_VALUE 0x280
48 #define RK3368_CRU_GLB_SRST_SND_VALUE 0x284
49 #define RK3368_CRU_GLB_RST_CON 0x388
50 #define RK3368_CRU_GLB_RST_ST 0x38c
52 #define RK3368_PMUGRF_OS_REG0 0x200
53 #define RK3368_PMUGRF_OS_REG1 0x204
55 static void rk3368_reboot(char str, const char *cmd)
59 rockchip_restart_get_boot_mode(cmd, &flag, &mode);
61 regmap_write(pmugrf, RK3368_PMUGRF_OS_REG0, flag);
63 regmap_write(pmugrf, RK3368_PMUGRF_OS_REG1, mode);
65 /* pll enter slow mode */
66 regmap_write(cru, RK3368_CRU_APLLB_CON3, 0x03000000);
67 regmap_write(cru, RK3368_CRU_APLLL_CON3, 0x03000000);
68 regmap_write(cru, RK3368_CRU_CPLL_CON3, 0x03000000);
69 regmap_write(cru, RK3368_CRU_GPLL_CON3, 0x03000000);
70 regmap_write(cru, RK3368_CRU_NPLL_CON3, 0x03000000);
71 regmap_update_bits(cru, RK3368_CRU_GLB_RST_CON, 3 << 2, 1 << 2);
72 regmap_write(cru, RK3368_CRU_GLB_SRST_SND_VALUE, 0xeca8);
75 static __init int rk3368_reboot_init(struct platform_device *pdev)
77 u32 flag, mode, rst_st;
78 struct device_node *np = pdev->dev.of_node;
80 cru = syscon_regmap_lookup_by_phandle(np, "rockchip,cru");
82 dev_err(&pdev->dev, "No rockchip,cru phandle specified");
86 pmugrf = syscon_regmap_lookup_by_phandle(np, "rockchip,pmugrf");
88 dev_err(&pdev->dev, "No rockchip,pmugrf phandle specified");
89 return PTR_ERR(pmugrf);
92 regmap_read(pmugrf, RK3368_PMUGRF_OS_REG0, &flag);
93 regmap_read(pmugrf, RK3368_PMUGRF_OS_REG1, &mode);
94 regmap_read(cru, RK3368_CRU_GLB_RST_ST, &rst_st);
96 if (flag == (SYS_KERNRL_REBOOT_FLAG | BOOT_RECOVER))
97 mode = BOOT_MODE_RECOVERY;
98 if (rst_st & ((1 << 4) | (1 << 5)))
99 mode = BOOT_MODE_WATCHDOG;
100 else if (rst_st & ((1 << 2) | (1 << 3)))
101 mode = BOOT_MODE_TSADC;
102 rockchip_boot_mode_init(flag, mode);
104 arm_pm_restart = rk3368_reboot;
109 static struct of_device_id rockchip_reboot_of_match[] __refdata = {
110 { .compatible = "rockchip,rk3368-reboot", .data = rk3368_reboot_init },
114 static int __init rockchip_reboot_probe(struct platform_device *pdev)
116 const struct of_device_id *match;
117 int (*init)(struct platform_device *);
119 match = of_match_node(rockchip_reboot_of_match, pdev->dev.of_node);
129 static struct platform_driver rockchip_reboot_driver = {
131 .name = "rockchip-reboot",
132 .of_match_table = rockchip_reboot_of_match,
136 static int __init rockchip_reboot_init(void)
138 return platform_driver_probe(&rockchip_reboot_driver,
139 rockchip_reboot_probe);
141 subsys_initcall(rockchip_reboot_init);