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

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
Loading
Loading
Loading
Loading
+34 −18
Original line number Diff line number Diff line
@@ -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
+24 −2
Original line number Diff line number Diff line
/*
 * 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),
};
+24 −1
Original line number Diff line number Diff line
@@ -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 @@ out_put:
}
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;
+10 −0
Original line number Diff line number Diff line
@@ -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__ */
+1 −1
Original line number Diff line number Diff line
@@ -270,4 +270,4 @@ static int __init renesas_soc_init(void)

	return 0;
}
core_initcall(renesas_soc_init);
early_initcall(renesas_soc_init);
Loading