soc: renesas: Identify SoC and register with the SoC bus
Subsystems (5)
Geert Uytterhoeven
maintainercover soc: renesas: Identify SoC and register with the SoC bus
Hi all,
Some Renesas SoCs may exist in different revisions, providing slightly different functionalities (e.g. R-Car H3 ES1.x and ES2.0). This needs to be catered for by drivers and/or platform code. The recently proposed soc_device_match() API seems like a good fit to handle this.
This patch series implements the core infrastructure to provide SoC and revision information through the SoC bus for Renesas ARM SoCs. It consists of 4 patches:
- Patch 1 avoids a crash when SoC revision information is needed and provided early,
- Patch 2 (from Arnd) introduces the soc_device_match() API. I don't know if, when, and through which channel this patch is planned to go upstream,
- Patch 3 fixes a bug in soc_device_match(), causing a crash when trying to match on an SoC attribute that is not provided (seen on EMEV2, RZ/A, and R-Car M1A, which lack revision information),
- Patch 4 identifies Renesas SoCs and registers them with the SoC bus.
Tested on (family, machine, soc_id, optional revision):
Emma Mobile EV2, EMEV2 KZM9D Board, emev2
RZ/A, Genmai, r7s72100
R-Mobile, APE6EVM, r8a73a4, ES1.0
R-Mobile, armadillo 800 eva, r8a7740, ES2.0
R-Car Gen1, bockw, r8a7778
R-Car Gen1, marzen, r8a7779, ES1.0
R-Car Gen2, Lager, r8a7790, ES1.0
R-Car Gen2, Koelsch, r8a7791, ES1.0
R-Car Gen2, Gose, r8a7793, ES1.0
R-Car Gen2, Alt, r8a7794, ES1.0
R-Car Gen3, Renesas Salvator-X board based on r8a7795, r8a7795, ES1.0
R-Car Gen3, Renesas Salvator-X board based on r8a7796, r8a7796, ES1.0
SH-Mobile, KZM-A9-GT, sh73a0, ES2.0For your convenience, this series is also available in the topic/renesas-soc-id-v1 branch of my renesas-drivers git repository atgit://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git
Thanks for your comments!
Arnd Bergmann (1):
base: soc: Introduce soc_device_match() interface
Geert Uytterhoeven (3):
base: soc: Early register bus when needed
base: soc: Check for NULL SoC device attributes [RFC] soc: renesas: Identify SoC and register with the SoC bus
arch/arm/mach-shmobile/Kconfig | 1 + arch/arm64/Kconfig.platforms | 1 + drivers/base/Kconfig | 1 + drivers/base/soc.c | 79 +++++++++++ drivers/soc/renesas/Makefile | 2 + drivers/soc/renesas/renesas-soc.c | 266 ++++++++++++++++++++++++++++++++++++++ include/linux/sys_soc.h | 3 + 7 files changed, 353 insertions(+) create mode 100644 drivers/soc/renesas/renesas-soc.c
Signature · 12 lines
1.9.1
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus TorvaldsGeert Uytterhoeven
maintainerPATCH 1/4 base: soc: Early register bus when needed
If soc_device_register() is called before soc_bus_register(), it crashes with a NULL pointer dereference.
soc_bus_register() is already a core_initcall(), but drivers/base/ is entered later than e.g. drivers/pinctrl/ and drivers/soc/. Hence there are several subsystems that may need to know SoC revision information, while it's not so easy to initialize the SoC bus even earlier using an initcall.
To fix this, let soc_device_register() register the bus early if that hasn't happened yet.
--- drivers/base/soc.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/base/soc.c +9 -0
@@ -114,6 +114,12 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attrstruct soc_device *soc_dev;int ret; +if (!soc_bus_type.p) { + ret =bus_register (&soc_bus_type); +if (ret) + goto out1; + } + soc_dev =kzalloc (sizeof (*soc_dev),GFP_KERNEL );if (!soc_dev) { ret = -ENOMEM ;
@@ -157,6 +163,9 @@ void soc_device_unregister(struct soc_device *soc_dev)static int __init soc_bus_register (void ) { +if (soc_bus_type.p) +return 0 ; +return bus_register (&soc_bus_type); }core_initcall (soc_bus_register);
Signature · 1 line
1.9.1
Re: [PATCH 1/4] base: soc: Early register bus when needed
Quoted 9 lines · CEST Geert Uytterhoeven
If
soc_device_register()is called beforesoc_bus_register(), it crashes with a NULL pointer dereference.
soc_bus_register()is already acore_initcall(), butdrivers/base/is entered later than e.g.drivers/pinctrl/anddrivers/soc/. Hence there are several subsystems that may need to know SoC revision information, while it's not so easy to initialize the SoC bus even earlier using an initcall.
Quoted 5 lines
To fix this, let
soc_device_register()register the bus early if that hasn't happened yet.Signed-off-by Geert Uytterhoeven <[email protected]>
Not nice, but I can't think of a better alternative, so
Geert Uytterhoeven
maintainerPATCH 2/4 base: soc: Introduce soc_device_match() interface
In reply to Geert UytterhoevenFrom: Arnd Bergmann <[email protected]>
We keep running into cases where device drivers want to know the exact version of the a SoC they are currently running on. In the past, this has usually been done through a vendor specific API that can be called by a driver, or by directly accessing some kind of version register that is not part of the device itself but that belongs to a global register area of the chip.
Common reasons for doing this include:
- A machine is not using devicetree or similar for passing data about on-chip devices, but just announces their presence using boot-time platform devices, and the machine code itself does not care about the revision.
- There is existing firmware or boot loaders with existing DT binaries with generic compatible strings that do not identify the particular revision of each device, but the driver knows which SoC revisions include which part.
- A prerelease version of a chip has some quirks and we are using the same version of the bootloader and the DT blob on both the prerelease and the final version. An update of the DT binding seems inappropriate because that would involve maintaining multiple copies of the dts and/or bootloader.
This patch introduces the soc_device_match() interface that is meant to work like of_match_node() but instead of identifying the version of a device, it identifies the SoC itself using a vendor-agnostic interface.
Unlike of_match_node(), we do not do an exact string compare but instead use glob_match() to allow wildcards in strings.
--- drivers/base/Kconfig | 1 + drivers/base/soc.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/sys_soc.h | 3 +++ 3 files changed, 70 insertions(+)
drivers/base/Kconfig +1 -0
@@ -225,6 +225,7 @@ config GENERIC_CPU_AUTOPROBE config SOC_BUS bool + select GLOB source "drivers/base/regmap/Kconfig"
drivers/base/soc.c +66 -0
75 lines not on this page · raw message
include/linux/sys_soc.h +3 -0
@@ -13,6 +13,7 @@ struct soc_device_attribute {const char *family;const char *revision;const char *soc_id; +const void *data; };/**
@@ -34,4 +35,6 @@ void soc_device_unregister(struct soc_device *soc_dev);*/ struct device *soc_device_to_device (struct soc_device *soc); +const struct soc_device_attribute *soc_device_match ( +const struct soc_device_attribute *matches);#endif /* __SOC_BUS_H */
Signature · 1 line
1.9.1
Greg Kroah-Hartman
maintainerPATCH 2/4 base: soc: Introduce soc_device_match() interface
Quoted 34 lines · Geert Uytterhoeven
From: Arnd Bergmann <[email protected]>
We keep running into cases where device drivers want to know the exact version of the a SoC they are currently running on. In the past, this has usually been done through a vendor specific API that can be called by a driver, or by directly accessing some kind of version register that is not part of the device itself but that belongs to a global register area of the chip.
Common reasons for doing this include:
- A machine is not using devicetree or similar for passing data about on-chip devices, but just announces their presence using boot-time platform devices, and the machine code itself does not care about the revision.
- There is existing firmware or boot loaders with existing DT binaries with generic compatible strings that do not identify the particular revision of each device, but the driver knows which SoC revisions include which part.
- A prerelease version of a chip has some quirks and we are using the same version of the bootloader and the DT blob on both the prerelease and the final version. An update of the DT binding seems inappropriate because that would involve maintaining multiple copies of the dts and/or bootloader.
This patch introduces the
soc_device_match()interface that is meant to work likeof_match_node()but instead of identifying the version of a device, it identifies the SoC itself using a vendor-agnostic interface.Unlike
of_match_node(), we do not do an exact string compare but instead useglob_match()to allow wildcards in strings.
Quoted 8 lines
Signed-off-by Arnd Bergmann <[email protected]>Signed-off-by Yangbo Lu <[email protected]>Signed-off-by Geert Uytterhoeven <[email protected]>--- drivers/base/Kconfig | 1 + drivers/base/soc.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/sys_soc.h | 3 +++ 3 files changed, 70 insertions(+)
Geert Uytterhoeven
maintainerPATCH 3/4 base: soc: Check for NULL SoC device attributes
In reply to Geert UytterhoevenIf soc_device_match() is used to check the value of a specific attribute that is not present for the current SoC, the kernel crashes with a NULL pointer dereference.
Fix this by explicitly checking for the absence of a needed property, and considering this a non-match.
--- drivers/base/soc.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/base/soc.c +8 -4
@@ -185,19 +185,23 @@ static int soc_device_match_one(struct device *dev, void *arg)const struct soc_device_attribute *match = arg;if (match->machine && - !glob_match (match->machine, soc_dev->attr->machine)) + (!soc_dev->attr->machine || + !glob_match (match->machine, soc_dev->attr->machine)))return 0 ;if (match->family && - !glob_match (match->family, soc_dev->attr->family)) + (!soc_dev->attr->family || + !glob_match (match->family, soc_dev->attr->family)))return 0 ;if (match->revision && - !glob_match (match->revision, soc_dev->attr->revision)) + (!soc_dev->attr->revision || + !glob_match (match->revision, soc_dev->attr->revision)))return 0 ;if (match->soc_id && - !glob_match (match->soc_id, soc_dev->attr->soc_id)) + (!soc_dev->attr->soc_id || + !glob_match (match->soc_id, soc_dev->attr->soc_id)))return 0 ;return 1 ;
Signature · 1 line
1.9.1
Re: [PATCH 3/4] base: soc: Check for NULL SoC device attributes
Quoted 9 lines · CEST Geert Uytterhoeven
If
soc_device_match()is used to check the value of a specific attribute that is not present for the current SoC, the kernel crashes with a NULL pointer dereference.Fix this by explicitly checking for the absence of a needed property, and considering this a non-match.
Signed-off-by Geert Uytterhoeven <[email protected]>
Greg Kroah-Hartman
maintainerPATCH 3/4 base: soc: Check for NULL SoC device attributes
In reply to Geert UytterhoevenQuoted 8 lines · Geert Uytterhoeven
If
soc_device_match()is used to check the value of a specific attribute that is not present for the current SoC, the kernel crashes with a NULL pointer dereference.Fix this by explicitly checking for the absence of a needed property, and considering this a non-match.
Signed-off-by Geert Uytterhoeven <[email protected]>
Geert Uytterhoeven
maintainerPATCH 4/4 soc: renesas: Identify SoC and register with the SoC bus
In reply to Geert UytterhoevenIdentify the SoC type and revision, and register this information with the SoC bus, so it is available under /sys/devices/soc0/, and can be checked where needed using soc_device_match().
In addition, on SoCs that support it, the product ID is read from a hardware register and validated, to catch accidental use of a DTB for a different SoC.
Example:
Detected Renesas r8a7791 ES1.0
...
# cat /sys/devices/soc0/{family,machine,soc_id,revision}
R-Car Gen2
Koelsch
r8a7791
ES1.0---
This patch does NOT add a call to
of_platform_default_populate(NULL, NULL,
soc_device_to_device(soc_dev));Contrary to suggested by commit 74d1d82cdaaec727 ("drivers/base: add bus for System-on-Chip devices), doing so would not only move on-SoC devices from /sys/devices/platform/ to /sys/devices/soc0/, but also all other board (off-SoC) devices specified in the DTB.
--- arch/arm/mach-shmobile/Kconfig | 1 + arch/arm64/Kconfig.platforms | 1 + drivers/soc/renesas/Makefile | 2 + drivers/soc/renesas/renesas-soc.c | 266 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 270 insertions(+) create mode 100644 drivers/soc/renesas/renesas-soc.c
arch/arm/mach-shmobile/Kconfig +1 -0
@@ -42,6 +42,7 @@ menuconfig ARCH_RENESAS select HAVE_ARM_TWD if SMP select NO_IOPORT_MAP select PINCTRL + select SOC_BUS select ZONE_DMA if ARM_LPAE if ARCH_RENESAS
arch/arm64/Kconfig.platforms +1 -0
@@ -131,6 +131,7 @@ config ARCH_RENESAS select PM select PM_GENERIC_DOMAINS select RENESAS_IRQC + select SOC_BUS help This enables support for the ARMv8 based Renesas SoCs.
drivers/soc/renesas/Makefile +2 -0
@@ -1,3 +1,5 @@ +obj-y += renesas-soc.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
drivers/soc/renesas/renesas-soc.c new file +266 -0
266 lines not on this page · raw message
Signature · 1 line
1.9.1
Hi Geert,
I've been offline some weeks, so sorry if I'm not completely up to date, yet, or miss anything.
Overall, having a quick look, the proposal in this patch series and your second series "arm64: renesas: r8a7795: R-Car H3 ES2.0 Prototype" looks nice to me. At least much better than encoding the ESx.x in the device tree as discussed some month ago ;)
Two minor comments below:
Quoted 92 lines · Geert Uytterhoeven
Identify the SoC type and revision, and register this information with the SoC bus, so it is available under
/sys/devices/soc0/, and can be checked where needed usingsoc_device_match().In addition, on SoCs that support it, the product ID is read from a hardware register and validated, to catch accidental use of a DTB for a different SoC.
Example:
Detected Renesas r8a7791 ES1.0 ... # cat /sys/devices/soc0/{family,machine,soc_id,revision} R-Car Gen2 Koelsch r8a7791 ES1.0Signed-off-by Geert Uytterhoeven <[email protected]>---
This patch does NOT add a call toof_platform_default_populate(NULL, NULL, soc_device_to_device(soc_dev));Contrary to suggested by commit
74d1d82cdaaec727("drivers/base: add bus for System-on-Chip devices), doing so would not only move on-SoC devices from/sys/devices/platform/to/sys/devices/soc0/, but also all other board (off-SoC) devices specified in the DTB.--- arch/arm/mach-shmobile/Kconfig | 1 + arch/arm64/Kconfig.platforms | 1 + drivers/soc/renesas/Makefile | 2 + drivers/soc/renesas/renesas-soc.c | 266 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 270 insertions(+) create mode 100644 drivers/soc/renesas/renesas-soc.carch/arm/mach-shmobile/Kconfig +1
-0@@ -42,6 +42,7 @@ menuconfig ARCH_RENESAS select HAVE_ARM_TWD if SMP select NO_IOPORT_MAP select PINCTRL + select SOC_BUS select ZONE_DMA if ARM_LPAE if ARCH_RENESASarch/arm64/Kconfig.platforms +1
-0@@ -131,6 +131,7 @@ config ARCH_RENESAS select PM select PM_GENERIC_DOMAINS select RENESAS_IRQC + select SOC_BUS help This enables support for the ARMv8 based Renesas SoCs.drivers/soc/renesas/Makefile +2
-0@@ -1,3 +1,5 @@ +obj-y += renesas-soc.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.odrivers/soc/renesas/renesas-soc.c new file +15
-0@@ -0,0 +1,266 @@ +/* +* Renesas SoC Identification +* +* Copyright (C) 2014-2016 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 +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ +
drivers/soc/renesas/renesas-soc.c line 25
Quoted 10 lines
drivers/soc/renesas/renesas-soc.c new file +10
-0+#include <linux/io.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/sys_soc.h> + + +struct renesas_family { +const char name[16 ]; +u32 reg;/* CCCR, PVR, or PRR */
I'm wondering if we want to encode this information in the device tree?
From the structs below it looks like this is information would be
typically given in the device tree, and not hard coded in this C code?
On the other hand, above you mention
"catch accidental use of a DTB for a different SoC"
which is a nice feature, too.
So I just want to talk about the pros & cons, most probably both ways are fine.
Quoted 199 lines
drivers/soc/renesas/renesas-soc.c new file +199
-0+}; + +static const struct renesas_family fam_emev2__initconst = { + .name ="Emma Mobile EV2" , +}; + +static const struct renesas_family fam_rmobile__initconst = { + .name ="R-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +}; + +static const struct renesas_family fam_rcar_gen1__initconst = { + .name ="R-Car Gen1" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen2__initconst = { + .name ="R-Car Gen2" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen3__initconst = { + .name ="R-Car Gen3" , + .reg =0xfff00044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rza__initconst = { + .name ="RZ/A" , +}; + +static const struct renesas_family fam_rzg__initconst = { + .name ="RZ/G" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_shmobile__initconst = { + .name ="SH-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +}; + + +struct renesas_soc { +const struct renesas_family *family; +u8 id; +}; + +static const struct renesas_soc soc_emev2__initconst = { + .family = &fam_emev2, +}; + +static const struct renesas_soc soc_rz_a1h__initconst = { + .family = &fam_rza, +}; + +static const struct renesas_soc soc_rmobile_ape6__initconst = { + .family = &fam_rmobile, + .id =0x3f , +}; + +static const struct renesas_soc soc_rmobile_a1__initconst = { + .family = &fam_rmobile, + .id =0x40 , +}; + +static const struct renesas_soc soc_rz_g1m__initconst = { + .family = &fam_rzg, + .id =0x47 , +}; + +static const struct renesas_soc soc_rz_g1e__initconst = { + .family = &fam_rzg, + .id =0x4c , +}; + +static const struct renesas_soc soc_rcar_m1a__initconst = { + .family = &fam_rcar_gen1, +}; + +static const struct renesas_soc soc_rcar_h1__initconst = { + .family = &fam_rcar_gen1, + .id =0x3b , +}; + +static const struct renesas_soc soc_rcar_h2__initconst = { + .family = &fam_rcar_gen2, + .id =0x45 , +}; + +static const struct renesas_soc soc_rcar_m2_w__initconst = { + .family = &fam_rcar_gen2, + .id =0x47 , +}; + +static const struct renesas_soc soc_rcar_v2h__initconst = { + .family = &fam_rcar_gen2, + .id =0x4a , +}; + +static const struct renesas_soc soc_rcar_m2_n__initconst = { + .family = &fam_rcar_gen2, + .id =0x4b , +}; + +static const struct renesas_soc soc_rcar_e2__initconst = { + .family = &fam_rcar_gen2, + .id =0x4c , +}; + +static const struct renesas_soc soc_rcar_h3__initconst = { + .family = &fam_rcar_gen3, + .id =0x4f , +}; + +static const struct renesas_soc soc_rcar_m3_w__initconst = { + .family = &fam_rcar_gen3, + .id =0x52 , +}; + +static const struct renesas_soc soc_shmobile_ag5__initconst = { + .family = &fam_shmobile, + .id =0x37 , +}; + +static const struct of_device_id renesas_socs[]__initconst = { +#ifdef CONFIG_ARCH_EMEV2 + { .compatible ="renesas,emev2" , .data = &soc_emev2 }, +#endif +#ifdef CONFIG_ARCH_R7S72100 + { .compatible ="renesas,r7s72100" , .data = &soc_rz_a1h }, +#endif +#ifdef CONFIG_ARCH_R8A73A4 + { .compatible ="renesas,r8a73a4" , .data = &soc_rmobile_ape6 }, +#endif +#ifdef CONFIG_ARCH_R8A7740 + { .compatible ="renesas,r8a7740" , .data = &soc_rmobile_a1 }, +#endif +#ifdef CONFIG_ARCH_R8A7743 + { .compatible ="renesas,r8a7743" , .data = &soc_rz_g1m }, +#endif +#ifdef CONFIG_ARCH_R8A7745 + { .compatible ="renesas,r8a7745" , .data = &soc_rz_g1e }, +#endif +#ifdef CONFIG_ARCH_R8A7778 + { .compatible ="renesas,r8a7778" , .data = &soc_rcar_m1a }, +#endif +#ifdef CONFIG_ARCH_R8A7779 + { .compatible ="renesas,r8a7779" , .data = &soc_rcar_h1 }, +#endif +#ifdef CONFIG_ARCH_R8A7790 + { .compatible ="renesas,r8a7790" , .data = &soc_rcar_h2 }, +#endif +#ifdef CONFIG_ARCH_R8A7791 + { .compatible ="renesas,r8a7791" , .data = &soc_rcar_m2_w }, +#endif +#ifdef CONFIG_ARCH_R8A7792 + { .compatible ="renesas,r8a7792" , .data = &soc_rcar_v2h }, +#endif +#ifdef CONFIG_ARCH_R8A7793 + { .compatible ="renesas,r8a7793" , .data = &soc_rcar_m2_n }, +#endif +#ifdef CONFIG_ARCH_R8A7794 + { .compatible ="renesas,r8a7794" , .data = &soc_rcar_e2 }, +#endif +#ifdef CONFIG_ARCH_R8A7795 + { .compatible ="renesas,r8a7795" , .data = &soc_rcar_h3 }, +#endif +#ifdef CONFIG_ARCH_R8A7796 + { .compatible ="renesas,r8a7796" , .data = &soc_rcar_m3_w }, +#endif +#ifdef CONFIG_ARCH_SH73A0 + { .compatible ="renesas,sh73a0" , .data = &soc_shmobile_ag5 }, +#endif + {/* sentinel */ } +}; + +static int __init renesas_soc_init (void ) +{ +struct soc_device_attribute *soc_dev_attr; +const struct renesas_family *family; +unsigned int product, esi =0 , esf; +const struct of_device_id *match; +const struct renesas_soc *soc; +struct soc_device *soc_dev; +struct device_node *np; +void __iomem *mapped; + + np =of_find_matching_node_and_match (NULL , renesas_socs, &match); +if (!np) +return -ENODEV ; + +of_node_put (np); + soc = match->data; + family = soc->family; + +if (soc->id) { + mapped =ioremap (family->reg,4 ); +if (!mapped) +return -ENOMEM ; +
drivers/soc/renesas/renesas-soc.c line 234
Quoted 10 lines
drivers/soc/renesas/renesas-soc.c new file +10
-0+ product =readl (mapped); +iounmap (mapped); + +if (((product >>8 ) &0xff ) != soc->id) { +pr_crit ("SoC mismatch (product = 0x%x)\n" , product); +return -ENODEV ; + } + + esi = ((product >>4 ) &0x0f ) +1 ; + esf = product &0xf ;
I'm somehow surprised to see that all SoCs covered here use the same way to encode esi and esf? I would have expected that we need different decoding for different SoCs. But if this isn't the case, even better :)
Best regards
Dirk
Quoted 10 lines · CEST Geert Uytterhoeven
Identify the SoC type and revision, and register this information with the SoC bus, so it is available under
/sys/devices/soc0/, and can be checked where needed usingsoc_device_match().In addition, on SoCs that support it, the product ID is read from a hardware register and validated, to catch accidental use of a DTB for a different SoC.
Example:
Quoted 8 lines
Detected Renesas r8a7791 ES1.0
...
# cat /sys/devices/soc0/{family,machine,soc_id,revision}
R-Car Gen2
Koelsch
r8a7791
ES1.0Seems all reasonable.
Quoted 11 lines
Signed-off-by Geert Uytterhoeven <[email protected]>---
This patch does NOT add a call toof_platform_default_populate(NULL, NULL, soc_device_to_device(soc_dev));Contrary to suggested by commit
74d1d82cdaaec727("drivers/base: add bus for System-on-Chip devices), doing so would not only move on-SoC devices from/sys/devices/platform/to/sys/devices/soc0/, but also all other board (off-SoC) devices specified in the DTB.
Right, we have moved away from that a while ago, and now just use the device for identification, not to model the device hierarchy.
Quoted 26 lines
drivers/soc/renesas/renesas-soc.c new file +20
-0@@ -0,0 +1,266 @@ +/* +* Renesas SoC Identification +* +* Copyright (C) 2014-2016 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 +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/io.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/sys_soc.h>
drivers/soc/renesas/renesas-soc.c line 30
Quoted 10 lines
drivers/soc/renesas/renesas-soc.c new file +10
-0+ + +struct renesas_family { +const char name[16 ]; +u32 reg;/* CCCR, PVR, or PRR */ +}; + +static const struct renesas_family fam_emev2__initconst = { + .name ="Emma Mobile EV2" , +};
As this is not related to the others and doesn't have the respective register, I'd leave the platform out of this, and possibly have a separate driver for it.
drivers/soc/renesas/renesas-soc.c line 54
Quoted 3 lines
drivers/soc/renesas/renesas-soc.c new file +3
-0+static const struct renesas_family fam_rza__initconst = { + .name ="RZ/A" , +};
I'm not sure about the relationship between this one and the others, maybe it should be treated in the same way as emev2 and left out from this driver?
Quoted 19 lines
drivers/soc/renesas/renesas-soc.c new file +19
-0+static const struct renesas_family fam_rmobile__initconst = { + .name ="R-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +}; + +static const struct renesas_family fam_rcar_gen1__initconst = { + .name ="R-Car Gen1" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen2__initconst = { + .name ="R-Car Gen2" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen3__initconst = { + .name ="R-Car Gen3" , + .reg =0xfff00044 ,/* PRR (Product Register) */ +};
drivers/soc/renesas/renesas-soc.c line 64
Quoted 10 lines
drivers/soc/renesas/renesas-soc.c new file +10
-0+ +static const struct renesas_family fam_rzg__initconst = { + .name ="RZ/G" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_shmobile__initconst = { + .name ="SH-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +};
These seem to fall into two distinct categories, maybe there is a better way to group them. What device contain the two kinds of registers (PRR, CCCR)?
Hardcoding the register address seems rather ugly here, so maybe there is a way to have two separate probe methods based on the surrounding register range, and then bind to that?
drivers/soc/renesas/renesas-soc.c line 156
Quoted 8 lines
drivers/soc/renesas/renesas-soc.c new file +8
-0+static const struct of_device_id renesas_socs[]__initconst = { +#ifdef CONFIG_ARCH_EMEV2 + { .compatible ="renesas,emev2" , .data = &soc_emev2 }, +#endif +#ifdef CONFIG_ARCH_R7S72100 + { .compatible ="renesas,r7s72100" , .data = &soc_rz_a1h }, +#endif +#ifdef CONFIG_ARCH_R8A73A4
I think the #ifdefs here will result in warnings for unused symbols when the Kconfig symbols are disabled.
Arnd
Hi Arnd,
Quoted 29 lines · Arnd Bergmann
Quoted 10 lines · CEST Geert Uytterhoeven
Identify the SoC type and revision, and register this information with the SoC bus, so it is available under
/sys/devices/soc0/, and can be checked where needed usingsoc_device_match().In addition, on SoCs that support it, the product ID is read from a hardware register and validated, to catch accidental use of a DTB for a different SoC.
Example:
Quoted 8 lines
Detected Renesas r8a7791 ES1.0 ... # cat /sys/devices/soc0/{family,machine,soc_id,revision} R-Car Gen2 Koelsch r8a7791 ES1.0Seems all reasonable.
Quoted 7 lines
Signed-off-by Geert Uytterhoeven <[email protected]>---
This patch does NOT add a call toof_platform_default_populate(NULL, NULL, soc_device_to_device(soc_dev));
Quoted 8 lines
Quoted 4 lines
Contrary to suggested by commit
74d1d82cdaaec727("drivers/base: add bus for System-on-Chip devices), doing so would not only move on-SoC devices from/sys/devices/platform/to/sys/devices/soc0/, but also all other board (off-SoC) devices specified in the DTB.Right, we have moved away from that a while ago, and now just use the device for identification, not to model the device hierarchy.
OK.
Quoted 32 lines
Quoted 32 lines
drivers/soc/renesas/renesas-soc.c new file +26
-0@@ -0,0 +1,266 @@ +/* +* Renesas SoC Identification +* +* Copyright (C) 2014-2016 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 +* the Free Software Foundation; version 2 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/io.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/sys_soc.h> + + +struct renesas_family { +const char name[16 ]; +u32 reg;/* CCCR, PVR, or PRR */ +};
Quoted 8 lines
drivers/soc/renesas/renesas-soc.c line 30
Quoted 4 lines
drivers/soc/renesas/renesas-soc.c new file +4
-0+ +static const struct renesas_family fam_emev2__initconst = { + .name ="Emma Mobile EV2" , +};As this is not related to the others and doesn't have the respective register, I'd leave the platform out of this, and possibly have a separate driver for it.
OK. Emma Mobile is special, as it doesn't share any drivers with the other SoCs (NEC vs. Hitachi origin).
Quoted 7 lines
drivers/soc/renesas/renesas-soc.c line 54
Quoted 3 lines
drivers/soc/renesas/renesas-soc.c new file +3
-0+static const struct renesas_family fam_rza__initconst = { + .name ="RZ/A" , +};I'm not sure about the relationship between this one and the others, maybe it should be treated in the same way as emev2 and left out from this driver?
While RZ/A doesn't have a version registers (AFAIK), it shares several drivers with the other SoCs (SH/R-Mobile, R-Car).
Hence I'd like to keep it, so we can match for it in these drivers when needed. It has e.g. a different variant of the serial port (SCIF), more closely to the one on SH2 rather than SH4.
Quoted 25 lines
Quoted 25 lines
drivers/soc/renesas/renesas-soc.c new file +25
-0+static const struct renesas_family fam_rmobile__initconst = { + .name ="R-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +}; + +static const struct renesas_family fam_rcar_gen1__initconst = { + .name ="R-Car Gen1" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen2__initconst = { + .name ="R-Car Gen2" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen3__initconst = { + .name ="R-Car Gen3" , + .reg =0xfff00044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rzg__initconst = { + .name ="RZ/G" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; +
Quoted 8 lines
drivers/soc/renesas/renesas-soc.c line 64
Quoted 4 lines
drivers/soc/renesas/renesas-soc.c new file +4
-0+static const struct renesas_family fam_shmobile__initconst = { + .name ="SH-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +};These seem to fall into two distinct categories, maybe there is a better way to group them. What device contain the two kinds of registers (PRR, CCCR)?
Actually there are three (notice the extra "f" on R-Car Gen3 ;-)
Some SoCs have only CCCR, others have only PRR, some have both. On some SoCs one of them can be accessed from the RealTime CPU core (SH) only.
On some SoCs the register is not documented, but present.
If the PRR exists, it's a better choice, as it contains additional information in the high order bits (representing the presence of each big (CA15/CA57), little (CA7/CA53), and RT (CR7) CPU core). Currently we don't use that information, though.
Grouping them in some other way means we would loose the family name, which is exposed through soc_dev_attr->family.
The usefulness of family names is debatable though, as this is more an issue of marketing business.
Quoted 3 lines
Hardcoding the register address seems rather ugly here, so maybe there is a way to have two separate probe methods based on the surrounding register range, and then bind to that?
There's no simple relation between CCCR/PRR and other register blocks. I prefer not to add these to DT, as that would add one more worm to the backwards compatibility can.
Quoted 11 lines
drivers/soc/renesas/renesas-soc.c line 156
Quoted 8 lines
drivers/soc/renesas/renesas-soc.c new file +8
-0+static const struct of_device_id renesas_socs[]__initconst = { +#ifdef CONFIG_ARCH_EMEV2 + { .compatible ="renesas,emev2" , .data = &soc_emev2 }, +#endif +#ifdef CONFIG_ARCH_R7S72100 + { .compatible ="renesas,r7s72100" , .data = &soc_rz_a1h }, +#endif +#ifdef CONFIG_ARCH_R8A73A4I think the #ifdefs here will result in warnings for unused symbols when the
Kconfigsymbols are disabled.
Originally I had __maybe_unused, but it didn't seem to be needed. Do you know which compiler needs it, so I can check?
Thanks for your comments!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 11 lines · CEST Geert Uytterhoeven
Quoted 9 lines · Arnd Bergmann
drivers/soc/renesas/renesas-soc.c line 54
Quoted 3 lines · CEST Geert Uytterhoeven
drivers/soc/renesas/renesas-soc.c new file +3
-0+static const struct renesas_family fam_rza__initconst = { + .name ="RZ/A" , +};I'm not sure about the relationship between this one and the others, maybe it should be treated in the same way as emev2 and left out from this driver?
Quoted 5 lines
While RZ/A doesn't have a version registers (AFAIK), it shares several drivers with the other SoCs (SH/R-Mobile, R-Car).
Hence I'd like to keep it, so we can match for it in these drivers when needed. It has e.g. a different variant of the serial port (SCIF), more closely to the one on SH2 rather than SH4.
I'd prefer seeing a separate soc driver for that one.
Quoted 34 lines
Quoted 25 lines
Quoted 25 lines
drivers/soc/renesas/renesas-soc.c new file +25
-0+static const struct renesas_family fam_rmobile__initconst = { + .name ="R-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +}; + +static const struct renesas_family fam_rcar_gen1__initconst = { + .name ="R-Car Gen1" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen2__initconst = { + .name ="R-Car Gen2" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen3__initconst = { + .name ="R-Car Gen3" , + .reg =0xfff00044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rzg__initconst = { + .name ="RZ/G" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; +Quoted 8 lines
drivers/soc/renesas/renesas-soc.c line 64
Quoted 4 lines
drivers/soc/renesas/renesas-soc.c new file +4
-0+static const struct renesas_family fam_shmobile__initconst = { + .name ="SH-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +};These seem to fall into two distinct categories, maybe there is a better way to group them. What device contain the two kinds of registers (PRR, CCCR)?
Quoted 1 line
Actually there are three (notice the extra "f" on R-Car Gen3 ;-)
I see. Hopefully this is just the same register block at a different location though.
Quoted 9 lines
Some SoCs have only CCCR, others have only PRR, some have both. On some SoCs one of them can be accessed from the RealTime CPU core (SH) only.
On some SoCs the register is not documented, but present.
If the PRR exists, it's a better choice, as it contains additional information in the high order bits (representing the presence of each big (CA15/CA57), little (CA7/CA53), and RT (CR7) CPU core). Currently we don't use that information, though.
Quoted 4 lines
Grouping them in some other way means we would loose the family name, which is exposed through
soc_dev_attr->family.
The usefulness of family names is debatable though, as this is more an issue of marketing business.
How about having a table to look up the family name by the value of the PRR or CCCR then?
Quoted 7 lines
Quoted 3 lines
Hardcoding the register address seems rather ugly here, so maybe there is a way to have two separate probe methods based on the surrounding register range, and then bind to that?
There's no simple relation between CCCR/PRR and other register blocks. I prefer not to add these to DT, as that would add one more worm to the backwards compatibility can.
Hmm, I understand the concern about compatibility with existing DT files, but I also really hate to see hardcoded register addresses.
Any reason against requiring the DT node for future chips though? How about this:
The driver could report the hardcoded strings for the SoCs it already knows about (you have the table anyway) and not report the revision unless there is a regmap containing the CCCR or the PRR, in which case you use that. Future SoCs will provide the PRR (I assume CCCR is only used on the older ones) through a syscon regmap that we can use to find out the exact revision as well.
The existing DT files can gain the syscon device so you can report the revision on those machines as well, unless you use an old DTB.
Quoted 12 lines
Quoted 11 lines
drivers/soc/renesas/renesas-soc.c line 156
Quoted 8 lines
drivers/soc/renesas/renesas-soc.c new file +8
-0+static const struct of_device_id renesas_socs[]__initconst = { +#ifdef CONFIG_ARCH_EMEV2 + { .compatible ="renesas,emev2" , .data = &soc_emev2 }, +#endif +#ifdef CONFIG_ARCH_R7S72100 + { .compatible ="renesas,r7s72100" , .data = &soc_rz_a1h }, +#endif +#ifdef CONFIG_ARCH_R8A73A4I think the #ifdefs here will result in warnings for unused symbols when the
Kconfigsymbols are disabled.
Quoted 2 lines
Originally I had
__maybe_unused, but it didn't seem to be needed. Do you know which compiler needs it, so I can check?
Ah, I remember now: gcc doesn't warn for 'static const' variables unless we pass -Wunused-const, which should be enabled with "make W=1", and we might make that the default in the future (after fixing the handful of drivers currently relying on this).
Why not just drop all the #ifdef here? There should be very little overhead in size, especially if all the data is __initconst.
Arnd
Hi Arnd,
Quoted 11 lines · Arnd Bergmann
Quoted 10 lines · CEST Geert Uytterhoeven
Quoted 8 lines · Arnd Bergmann
drivers/soc/renesas/renesas-soc.c line 54
Quoted 3 lines · CEST Geert Uytterhoeven
drivers/soc/renesas/renesas-soc.c new file +3
-0+static const struct renesas_family fam_rza__initconst = { + .name ="RZ/A" , +};I'm not sure about the relationship between this one and the others, maybe it should be treated in the same way as emev2 and left out from this driver?
Quoted 7 lines
Quoted 5 lines
While RZ/A doesn't have a version registers (AFAIK), it shares several drivers with the other SoCs (SH/R-Mobile, R-Car).
Hence I'd like to keep it, so we can match for it in these drivers when needed. It has e.g. a different variant of the serial port (SCIF), more closely to the one on SH2 rather than SH4.I'd prefer seeing a separate soc driver for that one.
OK, that can be done.
Quoted 34 lines
Quoted 34 lines
Quoted 33 lines
Quoted 19 lines
drivers/soc/renesas/renesas-soc.c new file +19
-0+static const struct renesas_family fam_rmobile__initconst = { + .name ="R-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +}; + +static const struct renesas_family fam_rcar_gen1__initconst = { + .name ="R-Car Gen1" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen2__initconst = { + .name ="R-Car Gen2" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_rcar_gen3__initconst = { + .name ="R-Car Gen3" , + .reg =0xfff00044 ,/* PRR (Product Register) */ +};drivers/soc/renesas/renesas-soc.c line 64
Quoted 10 lines
drivers/soc/renesas/renesas-soc.c new file +10
-0+ +static const struct renesas_family fam_rzg__initconst = { + .name ="RZ/G" , + .reg =0xff000044 ,/* PRR (Product Register) */ +}; + +static const struct renesas_family fam_shmobile__initconst = { + .name ="SH-Mobile" , + .reg =0xe600101c ,/* CCCR (Common Chip Code Register) */ +};These seem to fall into two distinct categories, maybe there is a better way to group them. What device contain the two kinds of registers (PRR, CCCR)?
Quoted 4 lines
Quoted 1 line
Actually there are three (notice the extra "f" on R-Car Gen3 ;-)
I see. Hopefully this is just the same register block at a different location though.
More or less.
Quoted 9 lines
Quoted 9 lines
Some SoCs have only CCCR, others have only PRR, some have both. On some SoCs one of them can be accessed from the RealTime CPU core (SH) only.
On some SoCs the register is not documented, but present.
If the PRR exists, it's a better choice, as it contains additional information in the high order bits (representing the presence of each big (CA15/CA57), little (CA7/CA53), and RT (CR7) CPU core). Currently we don't use that information, though.
Quoted 7 lines
Quoted 4 lines
Grouping them in some other way means we would loose the family name, which is exposed through
soc_dev_attr->family.
The usefulness of family names is debatable though, as this is more an issue of marketing business.How about having a table to look up the family name by the value of the PRR or CCCR then?
Unfortunately there exist SoCs from different families using the same product ID.
And different SoCs from the same family may have a revision register or not (e.g. R-Car H1 has, M1A hasn't).
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Hardcoding the register address seems rather ugly here, so maybe there is a way to have two separate probe methods based on the surrounding register range, and then bind to that?
Quoted 8 lines
Quoted 3 lines
There's no simple relation between CCCR/PRR and other register blocks. I prefer not to add these to DT, as that would add one more worm to the backwards compatibility can.
Hmm, I understand the concern about compatibility with existing DT files, but I also really hate to see hardcoded register addresses.
Any reason against requiring the DT node for future chips though?
For future SoCs, we can easily make it mandatory.
Quoted 11 lines
How about this:
The driver could report the hardcoded strings for the SoCs it already knows about (you have the table anyway) and not report the revision unless there is a regmap containing the CCCR or the PRR, in which case you use that. Future SoCs will provide the PRR (I assume CCCR is only used on the older ones) through a syscon regmap that we can use to find out the exact revision as well.
The existing DT files can gain the syscon device so you can report the revision on those machines as well, unless you use an old DTB.
Hmm... That means that if we have to add a driver quirk to distinguish between different revisions of the same SoC, we have to update the DTB anyway, to add the CCCR/PRR device node.
We might as well just change the compatible value in that DTB for the device that needs the quirk. Which is what we'd like to avoid in the first place.
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
drivers/soc/renesas/renesas-soc.c line 156
Quoted 8 lines
drivers/soc/renesas/renesas-soc.c new file +8
-0+static const struct of_device_id renesas_socs[]__initconst = { +#ifdef CONFIG_ARCH_EMEV2 + { .compatible ="renesas,emev2" , .data = &soc_emev2 }, +#endif +#ifdef CONFIG_ARCH_R7S72100 + { .compatible ="renesas,r7s72100" , .data = &soc_rz_a1h }, +#endif +#ifdef CONFIG_ARCH_R8A73A4I think the #ifdefs here will result in warnings for unused symbols when the
Kconfigsymbols are disabled.
Quoted 7 lines
Quoted 2 lines
Originally I had
__maybe_unused, but it didn't seem to be needed. Do you know which compiler needs it, so I can check?Ah, I remember now: gcc doesn't warn for 'static const' variables unless we pass -Wunused-const, which should be enabled with "make W=1", and we might make that the default in the future (after fixing the handful of drivers currently relying on this).
OK.
Quoted 2 lines
Why not just drop all the #ifdef here? There should be very little overhead in size, especially if all the data is
__initconst.
It still saves ca. 3 KiB for a kernel for a single SoC.
It's been a while I've tried multi_v7_defconfig, but I'm afraid there's no Renesas SoC left that can boot it, due to sheer size.
We're facing the same issue with arm64_defconfig soon (it already fails now if you add a small (1.5 MiB) initrd).
Not to mention RZ/A1H, which is used on some boards running with its 10 MiB of internal SRAM only.
Kernel size does matter, despite no progress on linux-tiny.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 18 lines · CEST Geert Uytterhoeven
Quoted 17 lines · Arnd Bergmann
Quoted 1 line · CEST Geert Uytterhoeven
On Mon, Oct 10, 2016 at 4:23 PM, Arnd Bergmann <[email protected]> wrote:
I'd prefer seeing a separate soc driver for that one.
Quoted 13 lines
Some SoCs have only CCCR, others have only PRR, some have both. On some SoCs one of them can be accessed from the RealTime CPU core (SH) only.
On some SoCs the register is not documented, but present.
If the PRR exists, it's a better choice, as it contains additional information in the high order bits (representing the presence of each big (CA15/CA57), little (CA7/CA53), and RT (CR7) CPU core). Currently we don't use that information, though.Grouping them in some other way means we would loose the family name, which is exposed through
soc_dev_attr->family.
The usefulness of family names is debatable though, as this is more an issue of marketing business.
Quoted 8 lines
Quoted 2 lines
How about having a table to look up the family name by the value of the PRR or CCCR then?
Unfortunately there exist SoCs from different families using the same product ID.
And different SoCs from the same family may have a revision register or not (e.g. R-Car H1 has, M1A hasn't).
Is this something we expect to see more of in the future, or can we expect future chips to handle this more consistently?
Quoted 12 lines
Quoted 11 lines
How about this:
The driver could report the hardcoded strings for the SoCs it already knows about (you have the table anyway) and not report the revision unless there is a regmap containing the CCCR or the PRR, in which case you use that. Future SoCs will provide the PRR (I assume CCCR is only used on the older ones) through a syscon regmap that we can use to find out the exact revision as well.
The existing DT files can gain the syscon device so you can report the revision on those machines as well, unless you use an old DTB.
Quoted 6 lines
Hmm... That means that if we have to add a driver quirk to distinguish between different revisions of the same SoC, we have to update the DTB anyway, to add the CCCR/PRR device node.
We might as well just change the compatible value in that DTB for the device that needs the quirk. Which is what we'd like to avoid in the first place.
Do you have a specific example in mind? If this is only a theoretical problem, we can worry about it when we get there, and then decide if we add a hardcoded register after all.
Quoted 4 lines
Quoted 2 lines
Why not just drop all the #ifdef here? There should be very little overhead in size, especially if all the data is
__initconst.It still saves ca. 3 KiB for a kernel for a single SoC.
Fair enough, that is more than I was expecting from looking at the source. It's probably the of_device_id structures for the most part.
Please just add the __maybe_unused then, to save us a patch in case we make -Wunused-const the default in the future.
Arnd
Hi Arnd,
Quoted 22 lines · Arnd Bergmann
Quoted 21 lines · CEST Geert Uytterhoeven
Quoted 19 lines · Arnd Bergmann
Quoted 1 line · CEST Geert Uytterhoeven
On Mon, Oct 10, 2016 at 4:23 PM, Arnd Bergmann <[email protected]> wrote:
I'd prefer seeing a separate soc driver for that one.
Quoted 9 lines
Some SoCs have only CCCR, others have only PRR, some have both. On some SoCs one of them can be accessed from the RealTime CPU core (SH) only.
On some SoCs the register is not documented, but present.
If the PRR exists, it's a better choice, as it contains additional information in the high order bits (representing the presence of each big (CA15/CA57), little (CA7/CA53), and RT (CR7) CPU core). Currently we don't use that information, though.Quoted 4 lines
Grouping them in some other way means we would loose the family name, which is exposed through
soc_dev_attr->family.
The usefulness of family names is debatable though, as this is more an issue of marketing business.How about having a table to look up the family name by the value of the PRR or CCCR then?
Quoted 8 lines
Quoted 5 lines
Unfortunately there exist SoCs from different families using the same product ID.
And different SoCs from the same family may have a revision register or not (e.g. R-Car H1 has, M1A hasn't).
Is this something we expect to see more of in the future, or can we expect future chips to handle this more consistently?
I expect to see more of these in the future.
Perhaps I just should forget about the product IDs and (marketing) families, and just stick the CCCR/PRR addresses in the of_device_ids?
Then we'll have SoC names (e.g. "r8a7791") and (optional) revisions (e.g. "ES1.0") to match on.
Quoted 19 lines
Quoted 12 lines
Quoted 11 lines
How about this:
The driver could report the hardcoded strings for the SoCs it already knows about (you have the table anyway) and not report the revision unless there is a regmap containing the CCCR or the PRR, in which case you use that. Future SoCs will provide the PRR (I assume CCCR is only used on the older ones) through a syscon regmap that we can use to find out the exact revision as well.
The existing DT files can gain the syscon device so you can report the revision on those machines as well, unless you use an old DTB.
Quoted 6 lines
Hmm... That means that if we have to add a driver quirk to distinguish between different revisions of the same SoC, we have to update the DTB anyway, to add the CCCR/PRR device node.
We might as well just change the compatible value in that DTB for the device that needs the quirk. Which is what we'd like to avoid in the first place.
Quoted 3 lines
Do you have a specific example in mind? If this is only a theoretical problem, we can worry about it when we get there, and then decide if we add a hardcoded register after all.
For R-Car H3, there are small differences between ES1.0 and ES1.1, and more and larger differences between ES1.x and ES2.0, which need different handling (patches already floating around).
For (old) R-Car H1, the SATA driver already handles "renesas,sata-r8a7790-es1", but so far there didn't exist an established process to specify how that compatible value would end up in the DTB (the in-kernel DTS doesn't have it).
There may be more differences I'm not aware of.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Why not just drop all the #ifdef here? There should be very little overhead in size, especially if all the data is
__initconst.It still saves ca. 3 KiB for a kernel for a single SoC.
Fair enough, that is more than I was expecting from looking at the source. It's probably the
of_device_idstructures for the most part.
Yep, ca. 200 bytes per ID.
Quoted 2 lines
Please just add the
__maybe_unusedthen, to save us a patch in case we make -Wunused-const the default in the future.
Sure.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 34 lines · CEST Geert Uytterhoeven
Hi Arnd,
Quoted 22 lines · Arnd Bergmann
Quoted 21 lines · CEST Geert Uytterhoeven
Quoted 19 lines · Arnd Bergmann
Quoted 1 line · CEST Geert Uytterhoeven
On Mon, Oct 10, 2016 at 4:23 PM, Arnd Bergmann <[email protected]> wrote:
I'd prefer seeing a separate soc driver for that one.
Quoted 9 lines
Some SoCs have only CCCR, others have only PRR, some have both. On some SoCs one of them can be accessed from the RealTime CPU core (SH) only.
On some SoCs the register is not documented, but present.
If the PRR exists, it's a better choice, as it contains additional information in the high order bits (representing the presence of each big (CA15/CA57), little (CA7/CA53), and RT (CR7) CPU core). Currently we don't use that information, though.Quoted 4 lines
Grouping them in some other way means we would loose the family name, which is exposed through
soc_dev_attr->family.
The usefulness of family names is debatable though, as this is more an issue of marketing business.How about having a table to look up the family name by the value of the PRR or CCCR then?
Quoted 8 lines
Quoted 5 lines
Unfortunately there exist SoCs from different families using the same product ID.
And different SoCs from the same family may have a revision register or not (e.g. R-Car H1 has, M1A hasn't).
Is this something we expect to see more of in the future, or can we expect future chips to handle this more consistently?
Quoted 6 lines
I expect to see more of these in the future.
Perhaps I just should forget about the product IDs and (marketing) families, and just stick the CCCR/PRR addresses in the
of_device_ids?
Then we'll have SoC names (e.g. "r8a7791") and (optional) revisions (e.g. "ES1.0") to match on.
I don't think listing the marketing names is a problem if we need a full list of all chips in of_device_ids anyway.
I'm still hoping to be able to limit the need for specifying the register addresses in the driver instead.
Quoted 27 lines
Quoted 19 lines
Quoted 12 lines
Quoted 11 lines
How about this:
The driver could report the hardcoded strings for the SoCs it already knows about (you have the table anyway) and not report the revision unless there is a regmap containing the CCCR or the PRR, in which case you use that. Future SoCs will provide the PRR (I assume CCCR is only used on the older ones) through a syscon regmap that we can use to find out the exact revision as well.
The existing DT files can gain the syscon device so you can report the revision on those machines as well, unless you use an old DTB.
Quoted 6 lines
Hmm... That means that if we have to add a driver quirk to distinguish between different revisions of the same SoC, we have to update the DTB anyway, to add the CCCR/PRR device node.
We might as well just change the compatible value in that DTB for the device that needs the quirk. Which is what we'd like to avoid in the first place.Quoted 3 lines
Do you have a specific example in mind? If this is only a theoretical problem, we can worry about it when we get there, and then decide if we add a hardcoded register after all.
For R-Car H3, there are small differences between ES1.0 and ES1.1, and more and larger differences between ES1.x and ES2.0, which need different handling (patches already floating around).
Quoted 5 lines
For (old) R-Car H1, the SATA driver already handles "renesas,sata-r8a7790-es1", but so far there didn't exist an established process to specify how that compatible value would end up in the DTB (the in-kernel DTS doesn't have it).
There may be more differences I'm not aware of.
Ok, so for R-Car H1, I assume we don't need the driver, it would just be a way to replace the current workaround with a different one, right?
For R-Car H3, do we just require driver changes to work with ES2.0, or also DT changes? If the new chip version already implies a new DT, we can require the presence of a device node that has the correct register number.
Arnd
Hi Arnd,
Quoted 35 lines · Arnd Bergmann
Quoted 34 lines · CEST Geert Uytterhoeven
Quoted 22 lines · Arnd Bergmann
Quoted 21 lines · CEST Geert Uytterhoeven
Quoted 19 lines · Arnd Bergmann
Quoted 1 line · CEST Geert Uytterhoeven
On Mon, Oct 10, 2016 at 4:23 PM, Arnd Bergmann <[email protected]> wrote:
I'd prefer seeing a separate soc driver for that one.
Quoted 9 lines
Some SoCs have only CCCR, others have only PRR, some have both. On some SoCs one of them can be accessed from the RealTime CPU core (SH) only.
On some SoCs the register is not documented, but present.
If the PRR exists, it's a better choice, as it contains additional information in the high order bits (representing the presence of each big (CA15/CA57), little (CA7/CA53), and RT (CR7) CPU core). Currently we don't use that information, though.Quoted 4 lines
Grouping them in some other way means we would loose the family name, which is exposed through
soc_dev_attr->family.
The usefulness of family names is debatable though, as this is more an issue of marketing business.How about having a table to look up the family name by the value of the PRR or CCCR then?
Quoted 8 lines
Quoted 5 lines
Unfortunately there exist SoCs from different families using the same product ID.
And different SoCs from the same family may have a revision register or not (e.g. R-Car H1 has, M1A hasn't).
Is this something we expect to see more of in the future, or can we expect future chips to handle this more consistently?
I expect to see more of these in the future.
Quoted 7 lines
Quoted 4 lines
Perhaps I just should forget about the product IDs and (marketing) families, and just stick the CCCR/PRR addresses in the
of_device_ids?
Then we'll have SoC names (e.g. "r8a7791") and (optional) revisions (e.g. "ES1.0") to match on.I don't think listing the marketing names is a problem if we need a full list of all chips in
of_device_idsanyway.
I'm removing the marketing names. We don't match them anyway (and probably shouldn't, as we don't control them anyway, cfr.
https://www.renesas.com/en-us/solutions/automotive/products.html).
Quoted 2 lines
I'm still hoping to be able to limit the need for specifying the register addresses in the driver instead.
Adding DT binding...
Quoted 33 lines
Quoted 27 lines
Quoted 19 lines
Quoted 12 lines
Quoted 11 lines
How about this:
The driver could report the hardcoded strings for the SoCs it already knows about (you have the table anyway) and not report the revision unless there is a regmap containing the CCCR or the PRR, in which case you use that. Future SoCs will provide the PRR (I assume CCCR is only used on the older ones) through a syscon regmap that we can use to find out the exact revision as well.
The existing DT files can gain the syscon device so you can report the revision on those machines as well, unless you use an old DTB.
Quoted 6 lines
Hmm... That means that if we have to add a driver quirk to distinguish between different revisions of the same SoC, we have to update the DTB anyway, to add the CCCR/PRR device node.
We might as well just change the compatible value in that DTB for the device that needs the quirk. Which is what we'd like to avoid in the first place.Quoted 3 lines
Do you have a specific example in mind? If this is only a theoretical problem, we can worry about it when we get there, and then decide if we add a hardcoded register after all.
For R-Car H3, there are small differences between ES1.0 and ES1.1, and more and larger differences between ES1.x and ES2.0, which need different handling (patches already floating around).
Quoted 5 lines
For (old) R-Car H1, the SATA driver already handles "renesas,sata-r8a7790-es1", but so far there didn't exist an established process to specify how that compatible value would end up in the DTB (the in-kernel DTS doesn't have it).
There may be more differences I'm not aware of.
Quoted 7 lines
Ok, so for R-Car H1, I assume we don't need the driver, it would just be a way to replace the current workaround with a different one, right?
For R-Car H3, do we just require driver changes to work with ES2.0, or also DT changes? If the new chip version already implies a new DT, we can require the presence of a device node that has the correct register number.
H3 also needs DT changes for some features (e.g. different number of USB channels, different topology for graphics).
soc_device_match() would mostly (only?) be used to handle limitations and quirks in early revisions. These are intended to be removed once production has been ramped up, and there's no longer a need to support them. However, that also means soc_device_match() would be used to match against early revisions, not against late revisions. I.e. the early SoCs need the chip ID registers declared, not the new ones.
Stay tuned for v2...
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 22 lines · CEST Geert Uytterhoeven
Hi all,
Some Renesas SoCs may exist in different revisions, providing slightly different functionalities (e.g. R-Car H3 ES1.x and ES2.0). This needs to be catered for by drivers and/or platform code. The recently proposed
soc_device_match()API seems like a good fit to handle this.This patch series implements the core infrastructure to provide SoC and revision information through the SoC bus for Renesas ARM SoCs. It consists of 4 patches:
- Patch 1 avoids a crash when SoC revision information is needed and provided early,
- Patch 2 (from Arnd) introduces thesoc_device_match()API. I don't know if, when, and through which channel this patch is planned to go upstream,
- Patch 3 fixes a bug insoc_device_match(), causing a crash when trying to match on an SoC attribute that is not provided (seen on EMEV2, RZ/A, and R-Car M1A, which lack revision information),
- Patch 4 identifies Renesas SoCs and registers them with the SoC bus.Tested on (family, machine,
soc_id, optional revision):
Quoted 13 lines
Emma Mobile EV2, EMEV2 KZM9D Board, emev2
RZ/A, Genmai, r7s72100
R-Mobile, APE6EVM, r8a73a4, ES1.0
R-Mobile, armadillo 800 eva, r8a7740, ES2.0
R-Car Gen1, bockw, r8a7778
R-Car Gen1, marzen, r8a7779, ES1.0
R-Car Gen2, Lager, r8a7790, ES1.0
R-Car Gen2, Koelsch, r8a7791, ES1.0
R-Car Gen2, Gose, r8a7793, ES1.0
R-Car Gen2, Alt, r8a7794, ES1.0
R-Car Gen3, Renesas Salvator-X board based on r8a7795, r8a7795, ES1.0
R-Car Gen3, Renesas Salvator-X board based on r8a7796, r8a7796, ES1.0
SH-Mobile, KZM-A9-GT, sh73a0, ES2.0As mentioned in the comment for the driver patch, I think this makes a lot of sense for the machines that have a revision register, in particular when the interpretation of that register is always done the same way, but I'm a bit skeptical about doing it in the same driver for machines that don't have the register.
Matching by a device rather than the SoC platform also has the advantage that there is no need to maintain a list of compatible numbers in the driver.
Arnd
Hi Arnd,
Quoted 41 lines · Arnd Bergmann
Quoted 20 lines · CEST Geert Uytterhoeven
Some Renesas SoCs may exist in different revisions, providing slightly different functionalities (e.g. R-Car H3 ES1.x and ES2.0). This needs to be catered for by drivers and/or platform code. The recently proposed
soc_device_match()API seems like a good fit to handle this.This patch series implements the core infrastructure to provide SoC and revision information through the SoC bus for Renesas ARM SoCs. It consists of 4 patches:
- Patch 1 avoids a crash when SoC revision information is needed and provided early,
- Patch 2 (from Arnd) introduces thesoc_device_match()API. I don't know if, when, and through which channel this patch is planned to go upstream,
- Patch 3 fixes a bug insoc_device_match(), causing a crash when trying to match on an SoC attribute that is not provided (seen on EMEV2, RZ/A, and R-Car M1A, which lack revision information),
- Patch 4 identifies Renesas SoCs and registers them with the SoC bus.Tested on (family, machine,
soc_id, optional revision):Quoted 13 lines
Emma Mobile EV2, EMEV2 KZM9D Board, emev2 RZ/A, Genmai, r7s72100 R-Mobile, APE6EVM, r8a73a4, ES1.0 R-Mobile, armadillo 800 eva, r8a7740, ES2.0 R-Car Gen1, bockw, r8a7778 R-Car Gen1, marzen, r8a7779, ES1.0 R-Car Gen2, Lager, r8a7790, ES1.0 R-Car Gen2, Koelsch, r8a7791, ES1.0 R-Car Gen2, Gose, r8a7793, ES1.0 R-Car Gen2, Alt, r8a7794, ES1.0 R-Car Gen3, Renesas Salvator-X board based on r8a7795, r8a7795, ES1.0 R-Car Gen3, Renesas Salvator-X board based on r8a7796, r8a7796, ES1.0 SH-Mobile, KZM-A9-GT, sh73a0, ES2.0As mentioned in the comment for the driver patch, I think this makes a lot of sense for the machines that have a revision register, in particular when the interpretation of that register is always done the same way, but I'm a bit skeptical about doing it in the same driver for machines that don't have the register.
Quoted 3 lines
Matching by a device rather than the SoC platform also has the advantage that there is no need to maintain a list of compatible numbers in the driver.
Currently we (usually) use:
- SoC-specific compatible values, to handle known differences within the same family now, and handle future unknown differences,
- Family-specific compatible values, which we define ourselves.
Usually drivers match on the latter.
Every time a new SoC is introduced, we have to update lots of DT binding docs, to add the new SoC-specific compatible values.
Two-phase matching (driver code matches against "renesas,<foo>", driver matches against SoC using soc_device_match()) would allow to remove the burden of updating DT documentation all the time. The drivers would need updates, though.
Another advantage would be that we can reuse .dtsi snippets for SoCs in the same family, which we currently can't easily do due to the SoC-specific compatible values.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Quoted 58 lines · CEST Geert Uytterhoeven
Hi Arnd,
Quoted 41 lines · Arnd Bergmann
Quoted 20 lines · CEST Geert Uytterhoeven
Some Renesas SoCs may exist in different revisions, providing slightly different functionalities (e.g. R-Car H3 ES1.x and ES2.0). This needs to be catered for by drivers and/or platform code. The recently proposed
soc_device_match()API seems like a good fit to handle this.This patch series implements the core infrastructure to provide SoC and revision information through the SoC bus for Renesas ARM SoCs. It consists of 4 patches:
- Patch 1 avoids a crash when SoC revision information is needed and provided early,
- Patch 2 (from Arnd) introduces thesoc_device_match()API. I don't know if, when, and through which channel this patch is planned to go upstream,
- Patch 3 fixes a bug insoc_device_match(), causing a crash when trying to match on an SoC attribute that is not provided (seen on EMEV2, RZ/A, and R-Car M1A, which lack revision information),
- Patch 4 identifies Renesas SoCs and registers them with the SoC bus.Tested on (family, machine,
soc_id, optional revision):Quoted 13 lines
Emma Mobile EV2, EMEV2 KZM9D Board, emev2 RZ/A, Genmai, r7s72100 R-Mobile, APE6EVM, r8a73a4, ES1.0 R-Mobile, armadillo 800 eva, r8a7740, ES2.0 R-Car Gen1, bockw, r8a7778 R-Car Gen1, marzen, r8a7779, ES1.0 R-Car Gen2, Lager, r8a7790, ES1.0 R-Car Gen2, Koelsch, r8a7791, ES1.0 R-Car Gen2, Gose, r8a7793, ES1.0 R-Car Gen2, Alt, r8a7794, ES1.0 R-Car Gen3, Renesas Salvator-X board based on r8a7795, r8a7795, ES1.0 R-Car Gen3, Renesas Salvator-X board based on r8a7796, r8a7796, ES1.0 SH-Mobile, KZM-A9-GT, sh73a0, ES2.0As mentioned in the comment for the driver patch, I think this makes a lot of sense for the machines that have a revision register, in particular when the interpretation of that register is always done the same way, but I'm a bit skeptical about doing it in the same driver for machines that don't have the register.
Quoted 3 lines
Matching by a device rather than the SoC platform also has the advantage that there is no need to maintain a list of compatible numbers in the driver.
Currently we (usually) use:
- SoC-specific compatible values, to handle known differences within the same family now, and handle future unknown differences,
- Family-specific compatible values, which we define ourselves.Usually drivers match on the latter.
Every time a new SoC is introduced, we have to update lots of DT binding docs, to add the new SoC-specific compatible values.
Quoted 7 lines
Two-phase matching (driver code matches against "renesas,<foo>", driver matches against SoC using
soc_device_match()) would allow to remove the burden of updating DT documentation all the time. The drivers would need updates, though.
Another advantage would be that we can reuse .dtsi snippets for SoCs in the same family, which we currently can't easily do due to the SoC-specific compatible values.
Interesting idea, but unrelated to my comment above, which was about the soc driver in particular, rather the drivers using it.
Arnd