Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * R-Car Gen1 RESET/WDT, R-Car Gen2, Gen3, and RZ/G RST Driver
0004  *
0005  * Copyright (C) 2016 Glider bvba
0006  */
0007 
0008 #include <linux/err.h>
0009 #include <linux/io.h>
0010 #include <linux/of_address.h>
0011 #include <linux/soc/renesas/rcar-rst.h>
0012 
0013 #define WDTRSTCR_RESET      0xA55A0002
0014 #define WDTRSTCR        0x0054
0015 
0016 #define CR7BAR          0x0070
0017 #define CR7BAREN        BIT(4)
0018 #define CR7BAR_MASK     0xFFFC0000
0019 
0020 static void __iomem *rcar_rst_base;
0021 static u32 saved_mode __initdata;
0022 static int (*rcar_rst_set_rproc_boot_addr_func)(u64 boot_addr);
0023 
0024 static int rcar_rst_enable_wdt_reset(void __iomem *base)
0025 {
0026     iowrite32(WDTRSTCR_RESET, base + WDTRSTCR);
0027     return 0;
0028 }
0029 
0030 /*
0031  * Most of the R-Car Gen3 SoCs have an ARM Realtime Core.
0032  * Firmware boot address has to be set in CR7BAR before
0033  * starting the realtime core.
0034  * Boot address must be aligned on a 256k boundary.
0035  */
0036 static int rcar_rst_set_gen3_rproc_boot_addr(u64 boot_addr)
0037 {
0038     if (boot_addr & ~(u64)CR7BAR_MASK) {
0039         pr_err("Invalid boot address got %llx\n", boot_addr);
0040         return -EINVAL;
0041     }
0042 
0043     iowrite32(boot_addr, rcar_rst_base + CR7BAR);
0044     iowrite32(boot_addr | CR7BAREN, rcar_rst_base + CR7BAR);
0045 
0046     return 0;
0047 }
0048 
0049 struct rst_config {
0050     unsigned int modemr;        /* Mode Monitoring Register Offset */
0051     int (*configure)(void __iomem *base);   /* Platform specific config */
0052     int (*set_rproc_boot_addr)(u64 boot_addr);
0053 };
0054 
0055 static const struct rst_config rcar_rst_gen1 __initconst = {
0056     .modemr = 0x20,
0057 };
0058 
0059 static const struct rst_config rcar_rst_gen2 __initconst = {
0060     .modemr = 0x60,
0061     .configure = rcar_rst_enable_wdt_reset,
0062 };
0063 
0064 static const struct rst_config rcar_rst_gen3 __initconst = {
0065     .modemr = 0x60,
0066     .set_rproc_boot_addr = rcar_rst_set_gen3_rproc_boot_addr,
0067 };
0068 
0069 static const struct rst_config rcar_rst_gen4 __initconst = {
0070     .modemr = 0x00,     /* MODEMR0 and it has CPG related bits */
0071 };
0072 
0073 static const struct of_device_id rcar_rst_matches[] __initconst = {
0074     /* RZ/G1 is handled like R-Car Gen2 */
0075     { .compatible = "renesas,r8a7742-rst", .data = &rcar_rst_gen2 },
0076     { .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 },
0077     { .compatible = "renesas,r8a7744-rst", .data = &rcar_rst_gen2 },
0078     { .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 },
0079     { .compatible = "renesas,r8a77470-rst", .data = &rcar_rst_gen2 },
0080     /* RZ/G2 is handled like R-Car Gen3 */
0081     { .compatible = "renesas,r8a774a1-rst", .data = &rcar_rst_gen3 },
0082     { .compatible = "renesas,r8a774b1-rst", .data = &rcar_rst_gen3 },
0083     { .compatible = "renesas,r8a774c0-rst", .data = &rcar_rst_gen3 },
0084     { .compatible = "renesas,r8a774e1-rst", .data = &rcar_rst_gen3 },
0085     /* R-Car Gen1 */
0086     { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 },
0087     { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
0088     /* R-Car Gen2 */
0089     { .compatible = "renesas,r8a7790-rst", .data = &rcar_rst_gen2 },
0090     { .compatible = "renesas,r8a7791-rst", .data = &rcar_rst_gen2 },
0091     { .compatible = "renesas,r8a7792-rst", .data = &rcar_rst_gen2 },
0092     { .compatible = "renesas,r8a7793-rst", .data = &rcar_rst_gen2 },
0093     { .compatible = "renesas,r8a7794-rst", .data = &rcar_rst_gen2 },
0094     /* R-Car Gen3 */
0095     { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen3 },
0096     { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen3 },
0097     { .compatible = "renesas,r8a77961-rst", .data = &rcar_rst_gen3 },
0098     { .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen3 },
0099     { .compatible = "renesas,r8a77970-rst", .data = &rcar_rst_gen3 },
0100     { .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen3 },
0101     { .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 },
0102     { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 },
0103     /* R-Car Gen4 */
0104     { .compatible = "renesas,r8a779a0-rst", .data = &rcar_rst_gen4 },
0105     { .compatible = "renesas,r8a779f0-rst", .data = &rcar_rst_gen4 },
0106     { .compatible = "renesas,r8a779g0-rst", .data = &rcar_rst_gen4 },
0107     { /* sentinel */ }
0108 };
0109 
0110 static int __init rcar_rst_init(void)
0111 {
0112     const struct of_device_id *match;
0113     const struct rst_config *cfg;
0114     struct device_node *np;
0115     void __iomem *base;
0116     int error = 0;
0117 
0118     np = of_find_matching_node_and_match(NULL, rcar_rst_matches, &match);
0119     if (!np)
0120         return -ENODEV;
0121 
0122     base = of_iomap(np, 0);
0123     if (!base) {
0124         pr_warn("%pOF: Cannot map regs\n", np);
0125         error = -ENOMEM;
0126         goto out_put;
0127     }
0128 
0129     rcar_rst_base = base;
0130     cfg = match->data;
0131     rcar_rst_set_rproc_boot_addr_func = cfg->set_rproc_boot_addr;
0132 
0133     saved_mode = ioread32(base + cfg->modemr);
0134     if (cfg->configure) {
0135         error = cfg->configure(base);
0136         if (error) {
0137             pr_warn("%pOF: Cannot run SoC specific configuration\n",
0138                 np);
0139             goto out_put;
0140         }
0141     }
0142 
0143     pr_debug("%pOF: MODE = 0x%08x\n", np, saved_mode);
0144 
0145 out_put:
0146     of_node_put(np);
0147     return error;
0148 }
0149 
0150 int __init rcar_rst_read_mode_pins(u32 *mode)
0151 {
0152     int error;
0153 
0154     if (!rcar_rst_base) {
0155         error = rcar_rst_init();
0156         if (error)
0157             return error;
0158     }
0159 
0160     *mode = saved_mode;
0161     return 0;
0162 }
0163 
0164 int rcar_rst_set_rproc_boot_addr(u64 boot_addr)
0165 {
0166     if (!rcar_rst_set_rproc_boot_addr_func)
0167         return -EIO;
0168 
0169     return rcar_rst_set_rproc_boot_addr_func(boot_addr);
0170 }
0171 EXPORT_SYMBOL_GPL(rcar_rst_set_rproc_boot_addr);