usb: dwc_otg_310: Fixed that otg-host cannot transport LS device data.
[firefly-linux-kernel-4.4.55.git] / drivers / power / reset / rockchip-reboot.c
1 /*
2  * Rockchip SoCs Reboot Driver
3  *
4  * Copyright (C) 2015 Fuzhou Rockchip Electronics Co., Ltd
5  *
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.
9  */
10
11 #include <linux/platform_device.h>
12 #include <linux/reboot.h>
13 #include <linux/regmap.h>
14 #include <linux/of.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/rockchip/common.h>
17 #include <asm/system_misc.h>
18
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
22
23 enum {
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 */
37 };
38
39 static struct regmap *cru;
40 static struct regmap *pmugrf;
41
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
51
52 #define RK3368_PMUGRF_OS_REG0   0x200
53 #define RK3368_PMUGRF_OS_REG1   0x204
54
55 static void rk3368_reboot(char str, const char *cmd)
56 {
57         u32 flag, mode;
58
59         rockchip_restart_get_boot_mode(cmd, &flag, &mode);
60         /* for loader */
61         regmap_write(pmugrf, RK3368_PMUGRF_OS_REG0, flag);
62         /* for linux */
63         regmap_write(pmugrf, RK3368_PMUGRF_OS_REG1, mode);
64
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);
73 }
74
75 static __init int rk3368_reboot_init(struct platform_device *pdev)
76 {
77         u32 flag, mode, rst_st;
78         struct device_node *np = pdev->dev.of_node;
79
80         cru = syscon_regmap_lookup_by_phandle(np, "rockchip,cru");
81         if (IS_ERR(cru)) {
82                 dev_err(&pdev->dev, "No rockchip,cru phandle specified");
83                 return PTR_ERR(cru);
84         }
85
86         pmugrf = syscon_regmap_lookup_by_phandle(np, "rockchip,pmugrf");
87         if (IS_ERR(pmugrf)) {
88                 dev_err(&pdev->dev, "No rockchip,pmugrf phandle specified");
89                 return PTR_ERR(pmugrf);
90         }
91
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);
95
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);
103
104         arm_pm_restart = rk3368_reboot;
105
106         return 0;
107 }
108
109 static struct of_device_id rockchip_reboot_of_match[] __refdata = {
110         { .compatible = "rockchip,rk3368-reboot", .data = rk3368_reboot_init },
111         {}
112 };
113
114 static int __init rockchip_reboot_probe(struct platform_device *pdev)
115 {
116         const struct of_device_id *match;
117         int (*init)(struct platform_device *);
118
119         match = of_match_node(rockchip_reboot_of_match, pdev->dev.of_node);
120         if (match) {
121                 init = match->data;
122                 if (init)
123                         return init(pdev);
124         }
125
126         return 0;
127 }
128
129 static struct platform_driver rockchip_reboot_driver = {
130         .driver = {
131                 .name = "rockchip-reboot",
132                 .of_match_table = rockchip_reboot_of_match,
133         },
134 };
135
136 static int __init rockchip_reboot_init(void)
137 {
138         return platform_driver_probe(&rockchip_reboot_driver,
139                         rockchip_reboot_probe);
140 }
141 subsys_initcall(rockchip_reboot_init);