Merge branch 'rcar-rst' into clk-renesas-for-v4.10

soc: renesas: Add R-Car RST driver for obtaining mode pin state
This commit is contained in:
Geert Uytterhoeven 2016-11-02 20:53:26 +01:00
commit a05de66ea6
24 changed files with 246 additions and 100 deletions

View File

@ -0,0 +1,37 @@
DT bindings for the Renesas R-Car and RZ/G Reset Controllers
The R-Car and RZ/G Reset Controllers provide reset control, and implement the
following functions:
- Latching of the levels on mode pins when PRESET# is negated,
- Mode monitoring register,
- Reset control of peripheral devices (on R-Car Gen1),
- Watchdog timer (on R-Car Gen1),
- Register-based reset control and boot address registers for the various CPU
cores (on R-Car Gen2 and Gen3, and on RZ/G).
Required properties:
- compatible: Should be
- "renesas,<soctype>-reset-wdt" for R-Car Gen1,
- "renesas,<soctype>-rst" for R-Car Gen2 and Gen3, and RZ/G
Examples with soctypes are:
- "renesas,r8a7743-rst" (RZ/G1M)
- "renesas,r8a7745-rst" (RZ/G1E)
- "renesas,r8a7778-reset-wdt" (R-Car M1A)
- "renesas,r8a7779-reset-wdt" (R-Car H1)
- "renesas,r8a7790-rst" (R-Car H2)
- "renesas,r8a7791-rst" (R-Car M2-W)
- "renesas,r8a7792-rst" (R-Car V2H
- "renesas,r8a7793-rst" (R-Car M2-N)
- "renesas,r8a7794-rst" (R-Car E2)
- "renesas,r8a7795-rst" (R-Car H3)
- "renesas,r8a7796-rst" (R-Car M3-W)
- reg: Address start and address range for the device.
Example:
rst: reset-controller@e6160000 {
compatible = "renesas,r8a7795-rst";
reg = <0 0xe6160000 0 0x0200>;
};

View File

@ -626,4 +626,9 @@
"sru-src6", "sru-src7", "sru-src8";
};
};
rst: reset-controller@ffcc0000 {
compatible = "renesas,r8a7778-reset-wdt";
reg = <0xffcc0000 0x40>;
};
};

View File

@ -590,6 +590,11 @@
};
};
rst: reset-controller@ffcc0000 {
compatible = "renesas,r8a7779-reset-wdt";
reg = <0xffcc0000 0x48>;
};
sysc: system-controller@ffd85000 {
compatible = "renesas,r8a7779-sysc";
reg = <0xffd85000 0x0200>;

View File

@ -1471,6 +1471,11 @@
};
};
rst: reset-controller@e6160000 {
compatible = "renesas,r8a7790-rst";
reg = <0 0xe6160000 0 0x0100>;
};
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7790-sysc";
reg = <0 0xe6180000 0 0x0200>;

View File

@ -1482,6 +1482,11 @@
};
};
rst: reset-controller@e6160000 {
compatible = "renesas,r8a7791-rst";
reg = <0 0xe6160000 0 0x0100>;
};
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7791-sysc";
reg = <0 0xe6180000 0 0x0200>;

View File

@ -118,6 +118,11 @@
IRQ_TYPE_LEVEL_LOW)>;
};
rst: reset-controller@e6160000 {
compatible = "renesas,r8a7792-rst";
reg = <0 0xe6160000 0 0x0100>;
};
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7792-sysc";
reg = <0 0xe6180000 0 0x0200>;

View File

@ -1279,6 +1279,11 @@
};
};
rst: reset-controller@e6160000 {
compatible = "renesas,r8a7793-rst";
reg = <0 0xe6160000 0 0x0100>;
};
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7793-sysc";
reg = <0 0xe6180000 0 0x0200>;

View File

@ -1375,6 +1375,11 @@
};
};
rst: reset-controller@e6160000 {
compatible = "renesas,r8a7794-rst";
reg = <0 0xe6160000 0 0x0100>;
};
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7794-sysc";
reg = <0 0xe6180000 0 0x0200>;

View File

@ -15,7 +15,6 @@
* GNU General Public License for more details.
*/
#include <linux/clk/renesas.h>
#include <linux/io.h>
#include <linux/irqchip.h>
@ -23,19 +22,6 @@
#include "common.h"
#define MODEMR 0xffcc0020
static void __init r8a7778_timer_init(void)
{
u32 mode;
void __iomem *modemr = ioremap_nocache(MODEMR, 4);
BUG_ON(!modemr);
mode = ioread32(modemr);
iounmap(modemr);
r8a7778_clocks_init(mode);
}
#define INT2SMSKCR0 0x82288 /* 0xfe782288 */
#define INT2SMSKCR1 0x8228c /* 0xfe78228c */
@ -70,6 +56,5 @@ DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
.init_early = shmobile_init_delay,
.init_irq = r8a7778_init_irq_dt,
.init_late = shmobile_init_late,
.init_time = r8a7778_timer_init,
.dt_compat = r8a7778_compat_dt,
MACHINE_END

View File

@ -14,8 +14,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk/renesas.h>
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
@ -76,30 +74,6 @@ static void __init r8a7779_init_irq_dt(void)
__raw_writel(0x003fee3f, INT2SMSKCR4);
}
#define MODEMR 0xffcc0020
static u32 __init r8a7779_read_mode_pins(void)
{
static u32 mode;
static bool mode_valid;
if (!mode_valid) {
void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
BUG_ON(!modemr);
mode = ioread32(modemr);
iounmap(modemr);
mode_valid = true;
}
return mode;
}
static void __init r8a7779_init_time(void)
{
r8a7779_clocks_init(r8a7779_read_mode_pins());
clocksource_probe();
}
static const char *const r8a7779_compat_dt[] __initconst = {
"renesas,r8a7779",
NULL,
@ -109,7 +83,6 @@ DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
.smp = smp_ops(r8a7779_smp_ops),
.map_io = r8a7779_map_io,
.init_early = shmobile_init_delay,
.init_time = r8a7779_init_time,
.init_irq = r8a7779_init_irq_dt,
.init_late = shmobile_init_late,
.dt_compat = r8a7779_compat_dt,

View File

@ -15,7 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/clk/renesas.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <linux/device.h>
#include <linux/dma-contiguous.h>
@ -71,7 +71,6 @@ static unsigned int __init get_extal_freq(void)
void __init rcar_gen2_timer_init(void)
{
u32 mode = rcar_gen2_read_mode_pins();
#ifdef CONFIG_ARM_ARCH_TIMER
void __iomem *base;
u32 freq;
@ -130,7 +129,7 @@ void __init rcar_gen2_timer_init(void)
iounmap(base);
#endif /* CONFIG_ARM_ARCH_TIMER */
rcar_gen2_clocks_init(mode);
of_clk_init(NULL);
clocksource_probe();
}

View File

@ -321,6 +321,11 @@
#power-domain-cells = <0>;
};
rst: reset-controller@e6160000 {
compatible = "renesas,r8a7795-rst";
reg = <0 0xe6160000 0 0x0200>;
};
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7795-sysc";
reg = <0 0xe6180000 0 0x0400>;

View File

@ -233,6 +233,11 @@
#power-domain-cells = <0>;
};
rst: reset-controller@e6160000 {
compatible = "renesas,r8a7796-rst";
reg = <0 0xe6160000 0 0x0200>;
};
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7796-sysc";
reg = <0 0xe6180000 0 0x0400>;

View File

@ -12,6 +12,7 @@
#include <linux/clk/renesas.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/soc/renesas/rcar-rst.h>
struct r8a7778_cpg {
struct clk_onecell_data data;
@ -83,6 +84,18 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np)
struct clk **clks;
unsigned int i;
int num_clks;
u32 mode;
if (rcar_rst_read_mode_pins(&mode))
return;
BUG_ON(!(mode & BIT(19)));
cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
(!!(mode & BIT(12)) << 1) |
(!!(mode & BIT(11)));
cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
(!!(mode & BIT(1)));
num_clks = of_property_count_strings(np, "clock-output-names");
if (num_clks < 0) {
@ -130,16 +143,3 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np)
CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
r8a7778_cpg_clocks_init);
void __init r8a7778_clocks_init(u32 mode)
{
BUG_ON(!(mode & BIT(19)));
cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
(!!(mode & BIT(12)) << 1) |
(!!(mode & BIT(11)));
cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
(!!(mode & BIT(1)));
of_clk_init(NULL);
}

View File

@ -18,6 +18,7 @@
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a7779-clock.h>
@ -88,8 +89,6 @@ static const unsigned int cpg_plla_mult[4] __initconst = { 42, 48, 56, 64 };
* Initialization
*/
static u32 cpg_mode __initdata;
static struct clk * __init
r8a7779_cpg_register_clock(struct device_node *np, struct r8a7779_cpg *cpg,
const struct cpg_clk_config *config,
@ -127,6 +126,10 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
struct clk **clks;
unsigned int i, plla_mult;
int num_clks;
u32 mode;
if (rcar_rst_read_mode_pins(&mode))
return;
num_clks = of_property_count_strings(np, "clock-output-names");
if (num_clks < 0) {
@ -148,8 +151,8 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
cpg->data.clks = clks;
cpg->data.clk_num = num_clks;
config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(cpg_mode)];
plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(cpg_mode)];
config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(mode)];
plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(mode)];
for (i = 0; i < num_clks; ++i) {
const char *name;
@ -173,10 +176,3 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
}
CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks",
r8a7779_cpg_clocks_init);
void __init r8a7779_clocks_init(u32 mode)
{
cpg_mode = mode;
of_clk_init(NULL);
}

View File

@ -19,6 +19,7 @@
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/soc/renesas/rcar-rst.h>
struct rcar_gen2_cpg {
struct clk_onecell_data data;
@ -364,6 +365,23 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
4, 0, table, &cpg->lock);
}
/*
* Reset register definitions.
*/
#define MODEMR 0xe6160060
static u32 __init rcar_gen2_read_mode_pins(void)
{
void __iomem *modemr = ioremap_nocache(MODEMR, 4);
u32 mode;
BUG_ON(!modemr);
mode = ioread32(modemr);
iounmap(modemr);
return mode;
}
static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
{
const struct cpg_pll_config *config;
@ -372,6 +390,13 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
unsigned int i;
int num_clks;
if (rcar_rst_read_mode_pins(&cpg_mode)) {
/* Backward-compatibility with old DT */
pr_warn("%s: failed to obtain mode pins from RST\n",
np->full_name);
cpg_mode = rcar_gen2_read_mode_pins();
}
num_clks = of_property_count_strings(np, "clock-output-names");
if (num_clks < 0) {
pr_err("%s: failed to count clocks\n", __func__);
@ -420,10 +445,3 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
}
CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks",
rcar_gen2_cpg_clocks_init);
void __init rcar_gen2_clocks_init(u32 mode)
{
cpg_mode = mode;
of_clk_init(NULL);
}

View File

@ -15,6 +15,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
@ -311,7 +312,12 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
static int __init r8a7795_cpg_mssr_init(struct device *dev)
{
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
u32 cpg_mode = rcar_gen3_read_mode_pins();
u32 cpg_mode;
int error;
error = rcar_rst_read_mode_pins(&cpg_mode);
if (error)
return error;
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
if (!cpg_pll_config->extal_div) {

View File

@ -16,6 +16,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
@ -235,7 +236,12 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
static int __init r8a7796_cpg_mssr_init(struct device *dev)
{
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
u32 cpg_mode = rcar_gen3_read_mode_pins();
u32 cpg_mode;
int error;
error = rcar_rst_read_mode_pins(&cpg_mode);
if (error)
return error;
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
if (!cpg_pll_config->extal_div) {

View File

@ -333,23 +333,6 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
__clk_get_name(parent), 0, mult, div);
}
/*
* Reset register definitions.
*/
#define MODEMR 0xe6160060
u32 __init rcar_gen3_read_mode_pins(void)
{
void __iomem *modemr = ioremap_nocache(MODEMR, 4);
u32 mode;
BUG_ON(!modemr);
mode = ioread32(modemr);
iounmap(modemr);
return mode;
}
int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
unsigned int clk_extalr)
{

View File

@ -33,7 +33,6 @@ struct rcar_gen3_cpg_pll_config {
#define CPG_RCKCR 0x240
u32 rcar_gen3_read_mode_pins(void);
struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
struct clk **clks, void __iomem *base);

View File

@ -1,3 +1,8 @@
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_R8A7779) += rcar-sysc.o r8a7779-sysc.o
obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o
obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o

View File

@ -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;
}

View File

@ -20,10 +20,6 @@ struct device;
struct device_node;
struct generic_pm_domain;
void r8a7778_clocks_init(u32 mode);
void r8a7779_clocks_init(u32 mode);
void rcar_gen2_clocks_init(u32 mode);
void cpg_mstp_add_clk_domain(struct device_node *np);
#ifdef CONFIG_CLK_RENESAS_CPG_MSTP
int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev);

View File

@ -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__ */