| From df1f0347e86be731d8c0d7347d98ef246c1f4ffa Mon Sep 17 00:00:00 2001 |
| From: Geert Uytterhoeven <geert+renesas@glider.be> |
| Date: Fri, 27 May 2016 11:56:53 +0200 |
| Subject: [PATCH 059/299] soc: renesas: Add R-Car RST driver |
| |
| Add a driver for the Renesas R-Car Gen1 RESET/WDT and R-Car Gen2/Gen3 |
| and RZ/G RST module. |
| |
| For now this driver just provides an API to obtain the state of the mode |
| pins, as latched at reset time. As this is typically called from the |
| probe function of a clock driver, which can run much earlier than any |
| initcall, calling rcar_rst_read_mode_pins() just forces an early |
| initialization of the driver. |
| |
| Despite the current simple and almost identical handling for all |
| supported SoCs, the driver matches against SoC-specific compatible |
| values, as the features provided by the hardware module differ a lot |
| across the various SoC families and members. |
| |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| Acked-by: Dirk Behme <dirk.behme@de.bosch.com> |
| (cherry picked from commit 527c02f66d263d2eeff237a2326c3278cfc03d3b) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| |
| Conflicts: |
| drivers/soc/renesas/Makefile |
| --- |
| drivers/soc/renesas/Makefile | 5 + |
| drivers/soc/renesas/rcar-rst.c | 92 +++++++++++++++++++++++++++++++++++ |
| include/linux/soc/renesas/rcar-rst.h | 6 ++ |
| 3 files changed, 103 insertions(+) |
| create mode 100644 drivers/soc/renesas/rcar-rst.c |
| create mode 100644 include/linux/soc/renesas/rcar-rst.h |
| |
| --- a/drivers/soc/renesas/Makefile |
| +++ b/drivers/soc/renesas/Makefile |
| @@ -1,5 +1,10 @@ |
| obj-$(CONFIG_SOC_BUS) += renesas-soc.o |
| |
| +obj-$(CONFIG_ARCH_RCAR_GEN1) += rcar-rst.o |
| +obj-$(CONFIG_ARCH_RCAR_GEN2) += rcar-rst.o |
| +obj-$(CONFIG_ARCH_R8A7795) += rcar-rst.o |
| +obj-$(CONFIG_ARCH_R8A7796) += rcar-rst.o |
| + |
| obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o |
| obj-$(CONFIG_ARCH_R8A7745) += rcar-sysc.o r8a7745-sysc.o |
| obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o |
| --- /dev/null |
| +++ b/drivers/soc/renesas/rcar-rst.c |
| @@ -0,0 +1,92 @@ |
| +/* |
| + * R-Car Gen1 RESET/WDT, R-Car Gen2, Gen3, and RZ/G RST Driver |
| + * |
| + * Copyright (C) 2016 Glider bvba |
| + * |
| + * This file is subject to the terms and conditions of the GNU General Public |
| + * License. See the file "COPYING" in the main directory of this archive |
| + * for more details. |
| + */ |
| + |
| +#include <linux/err.h> |
| +#include <linux/io.h> |
| +#include <linux/of_address.h> |
| +#include <linux/soc/renesas/rcar-rst.h> |
| + |
| +struct rst_config { |
| + unsigned int modemr; /* Mode Monitoring Register Offset */ |
| +}; |
| + |
| +static const struct rst_config rcar_rst_gen1 __initconst = { |
| + .modemr = 0x20, |
| +}; |
| + |
| +static const struct rst_config rcar_rst_gen2 __initconst = { |
| + .modemr = 0x60, |
| +}; |
| + |
| +static const struct of_device_id rcar_rst_matches[] __initconst = { |
| + /* RZ/G is handled like R-Car Gen2 */ |
| + { .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 }, |
| + { .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 }, |
| + /* R-Car Gen1 */ |
| + { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 }, |
| + { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 }, |
| + /* R-Car Gen2 */ |
| + { .compatible = "renesas,r8a7790-rst", .data = &rcar_rst_gen2 }, |
| + { .compatible = "renesas,r8a7791-rst", .data = &rcar_rst_gen2 }, |
| + { .compatible = "renesas,r8a7792-rst", .data = &rcar_rst_gen2 }, |
| + { .compatible = "renesas,r8a7793-rst", .data = &rcar_rst_gen2 }, |
| + { .compatible = "renesas,r8a7794-rst", .data = &rcar_rst_gen2 }, |
| + /* R-Car Gen3 is handled like R-Car Gen2 */ |
| + { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 }, |
| + { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, |
| + { /* sentinel */ } |
| +}; |
| + |
| +static void __iomem *rcar_rst_base __initdata; |
| +static u32 saved_mode __initdata; |
| + |
| +static int __init rcar_rst_init(void) |
| +{ |
| + const struct of_device_id *match; |
| + const struct rst_config *cfg; |
| + struct device_node *np; |
| + void __iomem *base; |
| + int error = 0; |
| + |
| + np = of_find_matching_node_and_match(NULL, rcar_rst_matches, &match); |
| + if (!np) |
| + return -ENODEV; |
| + |
| + base = of_iomap(np, 0); |
| + if (!base) { |
| + pr_warn("%s: Cannot map regs\n", np->full_name); |
| + error = -ENOMEM; |
| + goto out_put; |
| + } |
| + |
| + rcar_rst_base = base; |
| + cfg = match->data; |
| + saved_mode = ioread32(base + cfg->modemr); |
| + |
| + pr_debug("%s: MODE = 0x%08x\n", np->full_name, saved_mode); |
| + |
| +out_put: |
| + of_node_put(np); |
| + return error; |
| +} |
| + |
| +int __init rcar_rst_read_mode_pins(u32 *mode) |
| +{ |
| + int error; |
| + |
| + if (!rcar_rst_base) { |
| + error = rcar_rst_init(); |
| + if (error) |
| + return error; |
| + } |
| + |
| + *mode = saved_mode; |
| + return 0; |
| +} |
| --- /dev/null |
| +++ b/include/linux/soc/renesas/rcar-rst.h |
| @@ -0,0 +1,6 @@ |
| +#ifndef __LINUX_SOC_RENESAS_RCAR_RST_H__ |
| +#define __LINUX_SOC_RENESAS_RCAR_RST_H__ |
| + |
| +int rcar_rst_read_mode_pins(u32 *mode); |
| + |
| +#endif /* __LINUX_SOC_RENESAS_RCAR_RST_H__ */ |