0001
0002
0003
0004
0005
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
0032
0033
0034
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;
0051 int (*configure)(void __iomem *base);
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,
0071 };
0072
0073 static const struct of_device_id rcar_rst_matches[] __initconst = {
0074
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
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
0086 { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 },
0087 { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
0088
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
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
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 { }
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);