Unverified Commit 0491871b authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'renesas-drivers-for-v5.17-tag1' of...

Merge tag 'renesas-drivers-for-v5.17-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into arm/drivers

Renesas driver updates for v5.17

  - Add a remoteproc API for controlling the Cortex-R7 boot address on
    R-Car Gen3 SoCs,
  - Consolidate product register handling.

* tag 'renesas-drivers-for-v5.17-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel:
  soc: renesas: Consolidate product register handling
  soc: renesas: rcar-rst: Add support to set rproc boot address

Link: https://lore.kernel.org/r/cover.1638530612.git.geert+renesas@glider.be


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 13605725 05b22caa
Loading
Loading
Loading
Loading
+40 −3
Original line number Diff line number Diff line
@@ -13,15 +13,43 @@
#define WDTRSTCR_RESET		0xA55A0002
#define WDTRSTCR		0x0054

#define CR7BAR			0x0070
#define CR7BAREN		BIT(4)
#define CR7BAR_MASK		0xFFFC0000

static void __iomem *rcar_rst_base;
static u32 saved_mode __initdata;
static int (*rcar_rst_set_rproc_boot_addr_func)(u64 boot_addr);

static int rcar_rst_enable_wdt_reset(void __iomem *base)
{
	iowrite32(WDTRSTCR_RESET, base + WDTRSTCR);
	return 0;
}

/*
 * Most of the R-Car Gen3 SoCs have an ARM Realtime Core.
 * Firmware boot address has to be set in CR7BAR before
 * starting the realtime core.
 * Boot address must be aligned on a 256k boundary.
 */
static int rcar_rst_set_gen3_rproc_boot_addr(u64 boot_addr)
{
	if (boot_addr & ~(u64)CR7BAR_MASK) {
		pr_err("Invalid boot address got %llx\n", boot_addr);
		return -EINVAL;
	}

	iowrite32(boot_addr, rcar_rst_base + CR7BAR);
	iowrite32(boot_addr | CR7BAREN, rcar_rst_base + CR7BAR);

	return 0;
}

struct rst_config {
	unsigned int modemr;		/* Mode Monitoring Register Offset */
	int (*configure)(void __iomem *base);	/* Platform specific config */
	int (*set_rproc_boot_addr)(u64 boot_addr);
};

static const struct rst_config rcar_rst_gen1 __initconst = {
@@ -35,6 +63,7 @@ static const struct rst_config rcar_rst_gen2 __initconst = {

static const struct rst_config rcar_rst_gen3 __initconst = {
	.modemr = 0x60,
	.set_rproc_boot_addr = rcar_rst_set_gen3_rproc_boot_addr,
};

static const struct rst_config rcar_rst_r8a779a0 __initconst = {
@@ -76,9 +105,6 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
	{ /* 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;
@@ -100,6 +126,8 @@ static int __init rcar_rst_init(void)

	rcar_rst_base = base;
	cfg = match->data;
	rcar_rst_set_rproc_boot_addr_func = cfg->set_rproc_boot_addr;

	saved_mode = ioread32(base + cfg->modemr);
	if (cfg->configure) {
		error = cfg->configure(base);
@@ -130,3 +158,12 @@ int __init rcar_rst_read_mode_pins(u32 *mode)
	*mode = saved_mode;
	return 0;
}

int rcar_rst_set_rproc_boot_addr(u64 boot_addr)
{
	if (!rcar_rst_set_rproc_boot_addr_func)
		return -EIO;

	return rcar_rst_set_rproc_boot_addr_func(boot_addr);
}
EXPORT_SYMBOL_GPL(rcar_rst_set_rproc_boot_addr);
+56 −59
Original line number Diff line number Diff line
@@ -328,94 +328,92 @@ static const struct of_device_id renesas_socs[] __initconst = {
	{ /* sentinel */ }
};

struct renesas_id {
	unsigned int offset;
	u32 mask;
};

static const struct renesas_id id_bsid __initconst = {
	.offset = 0,
	.mask = 0xff0000,
	/*
	 * TODO: Upper 4 bits of BSID are for chip version, but the format is
	 * not known at this time so we don't know how to specify eshi and eslo
	 */
};

static const struct renesas_id id_rzg2l __initconst = {
	.offset = 0xa04,
	.mask = 0xfffffff,
};

static const struct renesas_id id_prr __initconst = {
	.offset = 0,
	.mask = 0xff00,
};

static const struct of_device_id renesas_ids[] __initconst = {
	{ .compatible = "renesas,bsid",			.data = &id_bsid },
	{ .compatible = "renesas,r9a07g044-sysc",	.data = &id_rzg2l },
	{ .compatible = "renesas,prr",			.data = &id_prr },
	{ /* sentinel */ }
};

static int __init renesas_soc_init(void)
{
	struct soc_device_attribute *soc_dev_attr;
	unsigned int product, eshi = 0, eslo;
	const struct renesas_family *family;
	const struct of_device_id *match;
	const struct renesas_soc *soc;
	const struct renesas_id *id;
	void __iomem *chipid = NULL;
	struct soc_device *soc_dev;
	struct device_node *np;
	unsigned int product, eshi = 0, eslo;
	const char *soc_id;

	match = of_match_node(renesas_socs, of_root);
	if (!match)
		return -ENODEV;

	soc_id = strchr(match->compatible, ',') + 1;
	soc = match->data;
	family = soc->family;

	np = of_find_compatible_node(NULL, NULL, "renesas,bsid");
	if (np) {
		chipid = of_iomap(np, 0);
		of_node_put(np);

		if (chipid) {
			product = readl(chipid);
			iounmap(chipid);

			if (soc->id && ((product >> 16) & 0xff) != soc->id) {
				pr_warn("SoC mismatch (product = 0x%x)\n",
					product);
				return -ENODEV;
			}
		}

		/*
		 * TODO: Upper 4 bits of BSID are for chip version, but the
		 * format is not known at this time so we don't know how to
		 * specify eshi and eslo
		 */

		goto done;
	}

	np = of_find_compatible_node(NULL, NULL, "renesas,r9a07g044-sysc");
	if (np) {
		chipid = of_iomap(np, 0);
		of_node_put(np);

		if (chipid) {
			product = readl(chipid + 0x0a04);
			iounmap(chipid);

			if (soc->id && (product & 0xfffffff) != soc->id) {
				pr_warn("SoC mismatch (product = 0x%x)\n",
					product);
				return -ENODEV;
			}
		}

		goto done;
	}

	/* Try PRR first, then hardcoded fallback */
	np = of_find_compatible_node(NULL, NULL, "renesas,prr");
	np = of_find_matching_node_and_match(NULL, renesas_ids, &match);
	if (np) {
		id = match->data;
		chipid = of_iomap(np, 0);
		of_node_put(np);
	} else if (soc->id && family->reg) {
		/* Try hardcoded CCCR/PRR fallback */
		id = &id_prr;
		chipid = ioremap(family->reg, 4);
	}

	if (chipid) {
		product = readl(chipid);
		product = readl(chipid + id->offset);
		iounmap(chipid);

		if (id == &id_prr) {
			/* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */
			if ((product & 0x7fff) == 0x5210)
				product ^= 0x11;
			/* R-Car M3-W ES1.3 incorrectly identifies as ES2.1 */
			if ((product & 0x7fff) == 0x5211)
				product ^= 0x12;
		if (soc->id && ((product >> 8) & 0xff) != soc->id) {

			eshi = ((product >> 4) & 0x0f) + 1;
			eslo = product & 0xf;
		}

		if (soc->id &&
		    ((product & id->mask) >> __ffs(id->mask)) != soc->id) {
			pr_warn("SoC mismatch (product = 0x%x)\n", product);
			return -ENODEV;
		}
		eshi = ((product >> 4) & 0x0f) + 1;
		eslo = product & 0xf;
	}

done:
	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
	if (!soc_dev_attr)
		return -ENOMEM;
@@ -425,8 +423,7 @@ static int __init renesas_soc_init(void)
	of_node_put(np);

	soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL);
	soc_dev_attr->soc_id = kstrdup_const(strchr(match->compatible, ',') + 1,
					     GFP_KERNEL);
	soc_dev_attr->soc_id = kstrdup_const(soc_id, GFP_KERNEL);
	if (eshi)
		soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", eshi,
						   eslo);
+2 −0
Original line number Diff line number Diff line
@@ -4,8 +4,10 @@

#ifdef CONFIG_RST_RCAR
int rcar_rst_read_mode_pins(u32 *mode);
int rcar_rst_set_rproc_boot_addr(u64 boot_addr);
#else
static inline int rcar_rst_read_mode_pins(u32 *mode) { return -ENODEV; }
static inline int rcar_rst_set_rproc_boot_addr(u64 boot_addr) { return -ENODEV; }
#endif

#endif /* __LINUX_SOC_RENESAS_RCAR_RST_H__ */