Commit 32d8b52b authored by Olof Johansson's avatar Olof Johansson

Merge tag 'renesas-sysc-for-v4.12' of...

Merge tag 'renesas-sysc-for-v4.12' of https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/drivers

Renesas ARM Based SoC Sysc Updates for v4.12

* Add support for R-Car H3 ES2.0

* tag 'renesas-sysc-for-v4.12' of https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas:
  soc: renesas: rcar-sysc: Add support for R-Car H3 ES2.0
  soc: renesas: rcar-sysc: Add support for fixing up power area tables
  soc: renesas: Register SoC device early
  base: soc: Allow early registration of a single SoC device
  base: soc: Let soc_device_match() return no match when called too early
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 63466c49 fcb87087
......@@ -109,15 +109,18 @@ static void soc_release(struct device *dev)
kfree(soc_dev);
}
static struct soc_device_attribute *early_soc_dev_attr;
struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr)
{
struct soc_device *soc_dev;
int ret;
if (!soc_bus_type.p) {
ret = bus_register(&soc_bus_type);
if (ret)
goto out1;
if (early_soc_dev_attr)
return ERR_PTR(-EBUSY);
early_soc_dev_attr = soc_dev_attr;
return NULL;
}
soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
......@@ -159,45 +162,53 @@ void soc_device_unregister(struct soc_device *soc_dev)
ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
device_unregister(&soc_dev->dev);
early_soc_dev_attr = NULL;
}
static int __init soc_bus_register(void)
{
if (soc_bus_type.p)
return 0;
int ret;
ret = bus_register(&soc_bus_type);
if (ret)
return ret;
if (early_soc_dev_attr)
return PTR_ERR(soc_device_register(early_soc_dev_attr));
return bus_register(&soc_bus_type);
return 0;
}
core_initcall(soc_bus_register);
static int soc_device_match_one(struct device *dev, void *arg)
static int soc_device_match_attr(const struct soc_device_attribute *attr,
const struct soc_device_attribute *match)
{
struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
const struct soc_device_attribute *match = arg;
if (match->machine &&
(!soc_dev->attr->machine ||
!glob_match(match->machine, soc_dev->attr->machine)))
(!attr->machine || !glob_match(match->machine, attr->machine)))
return 0;
if (match->family &&
(!soc_dev->attr->family ||
!glob_match(match->family, soc_dev->attr->family)))
(!attr->family || !glob_match(match->family, attr->family)))
return 0;
if (match->revision &&
(!soc_dev->attr->revision ||
!glob_match(match->revision, soc_dev->attr->revision)))
(!attr->revision || !glob_match(match->revision, attr->revision)))
return 0;
if (match->soc_id &&
(!soc_dev->attr->soc_id ||
!glob_match(match->soc_id, soc_dev->attr->soc_id)))
(!attr->soc_id || !glob_match(match->soc_id, attr->soc_id)))
return 0;
return 1;
}
static int soc_device_match_one(struct device *dev, void *arg)
{
struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
return soc_device_match_attr(soc_dev->attr, arg);
}
/*
* soc_device_match - identify the SoC in the machine
* @matches: zero-terminated array of possible matches
......@@ -230,6 +241,11 @@ const struct soc_device_attribute *soc_device_match(
break;
ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
soc_device_match_one);
if (ret < 0 && early_soc_dev_attr)
ret = soc_device_match_attr(early_soc_dev_attr,
matches);
if (ret < 0)
return NULL;
if (!ret)
matches++;
else
......
/*
* Renesas R-Car H3 System Controller
*
* Copyright (C) 2016 Glider bvba
* Copyright (C) 2016-2017 Glider bvba
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -10,12 +10,13 @@
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/sys_soc.h>
#include <dt-bindings/power/r8a7795-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
static struct rcar_sysc_area r8a7795_areas[] __initdata = {
{ "always-on", 0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca57-scu", 0x1c0, 0, R8A7795_PD_CA57_SCU, R8A7795_PD_ALWAYS_ON,
PD_SCU },
......@@ -40,6 +41,7 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
{ "a3vp", 0x340, 0, R8A7795_PD_A3VP, R8A7795_PD_ALWAYS_ON },
{ "cr7", 0x240, 0, R8A7795_PD_CR7, R8A7795_PD_ALWAYS_ON },
{ "a3vc", 0x380, 0, R8A7795_PD_A3VC, R8A7795_PD_ALWAYS_ON },
/* A2VC0 exists on ES1.x only */
{ "a2vc0", 0x3c0, 0, R8A7795_PD_A2VC0, R8A7795_PD_A3VC },
{ "a2vc1", 0x3c0, 1, R8A7795_PD_A2VC1, R8A7795_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A7795_PD_3DG_A, R8A7795_PD_ALWAYS_ON },
......@@ -50,7 +52,27 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
{ "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON },
};
/*
* Fixups for R-Car H3 revisions after ES1.x
*/
static const struct soc_device_attribute r8a7795es1[] __initconst = {
{ .soc_id = "r8a7795", .revision = "ES1.*" },
{ /* sentinel */ }
};
static int __init r8a7795_sysc_init(void)
{
if (!soc_device_match(r8a7795es1))
rcar_sysc_nullify(r8a7795_areas, ARRAY_SIZE(r8a7795_areas),
R8A7795_PD_A2VC0);
return 0;
}
const struct rcar_sysc_info r8a7795_sysc_info __initconst = {
.init = r8a7795_sysc_init,
.areas = r8a7795_areas,
.num_areas = ARRAY_SIZE(r8a7795_areas),
};
......@@ -2,7 +2,7 @@
* R-Car SYSC Power management support
*
* Copyright (C) 2014 Magnus Damm
* Copyright (C) 2015-2016 Glider bvba
* Copyright (C) 2015-2017 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
......@@ -334,6 +334,12 @@ static int __init rcar_sysc_pd_init(void)
info = match->data;
if (info->init) {
error = info->init();
if (error)
return error;
}
has_cpg_mstp = of_find_compatible_node(NULL, NULL,
"renesas,cpg-mstp-clocks");
......@@ -377,6 +383,11 @@ static int __init rcar_sysc_pd_init(void)
const struct rcar_sysc_area *area = &info->areas[i];
struct rcar_sysc_pd *pd;
if (!area->name) {
/* Skip NULLified area */
continue;
}
pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
if (!pd) {
error = -ENOMEM;
......@@ -406,6 +417,18 @@ static int __init rcar_sysc_pd_init(void)
}
early_initcall(rcar_sysc_pd_init);
void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
unsigned int num_areas, u8 id)
{
unsigned int i;
for (i = 0; i < num_areas; i++)
if (areas[i].isr_bit == id) {
areas[i].name = NULL;
return;
}
}
void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
{
u32 syscimr;
......
......@@ -46,6 +46,7 @@ struct rcar_sysc_area {
*/
struct rcar_sysc_info {
int (*init)(void); /* Optional */
const struct rcar_sysc_area *areas;
unsigned int num_areas;
};
......@@ -59,4 +60,13 @@ extern const struct rcar_sysc_info r8a7792_sysc_info;
extern const struct rcar_sysc_info r8a7794_sysc_info;
extern const struct rcar_sysc_info r8a7795_sysc_info;
extern const struct rcar_sysc_info r8a7796_sysc_info;
/*
* Helpers for fixing up power area tables depending on SoC revision
*/
extern void rcar_sysc_nullify(struct rcar_sysc_area *areas,
unsigned int num_areas, u8 id);
#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
......@@ -270,4 +270,4 @@ static int __init renesas_soc_init(void)
return 0;
}
core_initcall(renesas_soc_init);
early_initcall(renesas_soc_init);
......@@ -33,7 +33,7 @@
#define R8A7795_PD_CA53_SCU 21
#define R8A7795_PD_3DG_E 22
#define R8A7795_PD_A3IR 24
#define R8A7795_PD_A2VC0 25
#define R8A7795_PD_A2VC0 25 /* ES1.x only */
#define R8A7795_PD_A2VC1 26
/* Always-on power area */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment