Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[sfrench/cifs-2.6.git] / drivers / soc / renesas / rcar-rst.c
1 /*
2  * R-Car Gen1 RESET/WDT, R-Car Gen2, Gen3, and RZ/G RST Driver
3  *
4  * Copyright (C) 2016 Glider bvba
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file "COPYING" in the main directory of this archive
8  * for more details.
9  */
10
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/of_address.h>
14 #include <linux/soc/renesas/rcar-rst.h>
15
16 struct rst_config {
17         unsigned int modemr;    /* Mode Monitoring Register Offset */
18 };
19
20 static const struct rst_config rcar_rst_gen1 __initconst = {
21         .modemr = 0x20,
22 };
23
24 static const struct rst_config rcar_rst_gen2 __initconst = {
25         .modemr = 0x60,
26 };
27
28 static const struct of_device_id rcar_rst_matches[] __initconst = {
29         /* RZ/G is handled like R-Car Gen2 */
30         { .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 },
31         { .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 },
32         /* R-Car Gen1 */
33         { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 },
34         { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
35         /* R-Car Gen2 */
36         { .compatible = "renesas,r8a7790-rst", .data = &rcar_rst_gen2 },
37         { .compatible = "renesas,r8a7791-rst", .data = &rcar_rst_gen2 },
38         { .compatible = "renesas,r8a7792-rst", .data = &rcar_rst_gen2 },
39         { .compatible = "renesas,r8a7793-rst", .data = &rcar_rst_gen2 },
40         { .compatible = "renesas,r8a7794-rst", .data = &rcar_rst_gen2 },
41         /* R-Car Gen3 is handled like R-Car Gen2 */
42         { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 },
43         { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 },
44         { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen2 },
45         { /* sentinel */ }
46 };
47
48 static void __iomem *rcar_rst_base __initdata;
49 static u32 saved_mode __initdata;
50
51 static int __init rcar_rst_init(void)
52 {
53         const struct of_device_id *match;
54         const struct rst_config *cfg;
55         struct device_node *np;
56         void __iomem *base;
57         int error = 0;
58
59         np = of_find_matching_node_and_match(NULL, rcar_rst_matches, &match);
60         if (!np)
61                 return -ENODEV;
62
63         base = of_iomap(np, 0);
64         if (!base) {
65                 pr_warn("%pOF: Cannot map regs\n", np);
66                 error = -ENOMEM;
67                 goto out_put;
68         }
69
70         rcar_rst_base = base;
71         cfg = match->data;
72         saved_mode = ioread32(base + cfg->modemr);
73
74         pr_debug("%pOF: MODE = 0x%08x\n", np, saved_mode);
75
76 out_put:
77         of_node_put(np);
78         return error;
79 }
80
81 int __init rcar_rst_read_mode_pins(u32 *mode)
82 {
83         int error;
84
85         if (!rcar_rst_base) {
86                 error = rcar_rst_init();
87                 if (error)
88                         return error;
89         }
90
91         *mode = saved_mode;
92         return 0;
93 }