Message ID | 20220609213513.88479-1-j.neuschaefer@gmx.net |
---|---|
State | New |
Headers | show |
Series | [v4] soc: nuvoton: Add SoC info driver for WPCM450 | expand |
On Thu, Jun 9, 2022 at 11:35 PM Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote: > > Add a SoC information driver for Nuvoton WPCM450 SoCs. It provides > information such as the SoC revision. > > Usage example: > > # grep . /sys/devices/soc0/* > /sys/devices/soc0/family:Nuvoton NPCM > /sys/devices/soc0/revision:A3 > /sys/devices/soc0/soc_id:WPCM450 > > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net> > Reviewed-by: Joel Stanley <joel@jms.id.au> > Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de> Looks good overall. > +menuconfig WPCM450_SOC > + bool "Nuvoton WPCM450 SoC driver" > + default y if ARCH_WPCM450 It would be nice to make this a tristate option, as we generally like to keep optional drivers out of the allmodconfig vmlinux file, even if this is a tiny one. Just add the trivial cleanup function and MODULE_LICENSE() etc tags. Arnd
On Wed, Jun 15, 2022 at 04:00:17PM +0200, Arnd Bergmann wrote: > On Thu, Jun 9, 2022 at 11:35 PM Jonathan Neuschäfer > <j.neuschaefer@gmx.net> wrote: > > > > Add a SoC information driver for Nuvoton WPCM450 SoCs. It provides > > information such as the SoC revision. > > > > Usage example: > > > > # grep . /sys/devices/soc0/* > > /sys/devices/soc0/family:Nuvoton NPCM > > /sys/devices/soc0/revision:A3 > > /sys/devices/soc0/soc_id:WPCM450 > > > > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net> > > Reviewed-by: Joel Stanley <joel@jms.id.au> > > Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de> > > Looks good overall. > > > +menuconfig WPCM450_SOC > > + bool "Nuvoton WPCM450 SoC driver" > > + default y if ARCH_WPCM450 > > It would be nice to make this a tristate option, as we generally > like to keep optional drivers out of the allmodconfig vmlinux file, > even if this is a tiny one. Ok. > Just add the trivial cleanup function and MODULE_LICENSE() etc tags. The right thing to do seems to be to unregister the SoC device in the cleanup function. Is that what you mean? Jonathan
On Fri, Jun 17, 2022 at 11:28 AM Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote: > > Just add the trivial cleanup function and MODULE_LICENSE() etc tags. > > The right thing to do seems to be to unregister the SoC device in the > cleanup function. Is that what you mean? Yes, plus kfree() the soc_device_attribute, or make it statically allocated. Arnd
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index 86ccf5970bc1b..cca3dfa5c6aea 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -14,6 +14,7 @@ source "drivers/soc/ixp4xx/Kconfig" source "drivers/soc/litex/Kconfig" source "drivers/soc/mediatek/Kconfig" source "drivers/soc/microchip/Kconfig" +source "drivers/soc/nuvoton/Kconfig" source "drivers/soc/pxa/Kconfig" source "drivers/soc/qcom/Kconfig" source "drivers/soc/renesas/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 919716e0e7001..b9eb3c75e551a 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_SOC_XWAY) += lantiq/ obj-$(CONFIG_LITEX_SOC_CONTROLLER) += litex/ obj-y += mediatek/ obj-y += microchip/ +obj-y += nuvoton/ obj-y += pxa/ obj-y += amlogic/ obj-y += qcom/ diff --git a/drivers/soc/nuvoton/Kconfig b/drivers/soc/nuvoton/Kconfig new file mode 100644 index 0000000000000..50166f37096b7 --- /dev/null +++ b/drivers/soc/nuvoton/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +menuconfig WPCM450_SOC + bool "Nuvoton WPCM450 SoC driver" + default y if ARCH_WPCM450 + select SOC_BUS + help + Say Y here to compile the SoC information driver for Nuvoton + WPCM450 SoCs. + + This driver provides information such as the SoC model and + revision. diff --git a/drivers/soc/nuvoton/Makefile b/drivers/soc/nuvoton/Makefile new file mode 100644 index 0000000000000..e30317b4e8290 --- /dev/null +++ b/drivers/soc/nuvoton/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_WPCM450_SOC) += wpcm450-soc.o diff --git a/drivers/soc/nuvoton/wpcm450-soc.c b/drivers/soc/nuvoton/wpcm450-soc.c new file mode 100644 index 0000000000000..9ff876ea71361 --- /dev/null +++ b/drivers/soc/nuvoton/wpcm450-soc.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Nuvoton WPCM450 SoC Identification + * + * Copyright (C) 2022 Jonathan Neuschäfer + */ + +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/sys_soc.h> + +#define GCR_PDID 0 +#define PDID_CHIP(x) ((x) & 0x00ffffff) +#define CHIP_WPCM450 0x926450 +#define PDID_REV(x) ((x) >> 24) + +struct revision { + u8 number; + const char *name; +}; + +static const struct revision revisions[] __initconst = { + { 0x00, "Z1" }, + { 0x03, "Z2" }, + { 0x04, "Z21" }, + { 0x08, "A1" }, + { 0x09, "A2" }, + { 0x0a, "A3" }, + {} +}; + +static const char * __init get_revision(unsigned int rev) +{ + int i; + + for (i = 0; revisions[i].name; i++) + if (revisions[i].number == rev) + return revisions[i].name; + return NULL; +} + +static int __init wpcm450_soc_init(void) +{ + struct soc_device_attribute *attr; + struct soc_device *soc; + const char *revision; + struct regmap *gcr; + u32 pdid; + int ret; + + if (!of_machine_is_compatible("nuvoton,wpcm450")) + return 0; + + gcr = syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr"); + if (IS_ERR(gcr)) + return PTR_ERR(gcr); + ret = regmap_read(gcr, GCR_PDID, &pdid); + if (ret) + return ret; + + if (PDID_CHIP(pdid) != CHIP_WPCM450) { + pr_warn("Unknown chip ID in GCR.PDID: 0x%06x\n", PDID_CHIP(pdid)); + return -ENODEV; + } + + revision = get_revision(PDID_REV(pdid)); + if (!revision) { + pr_warn("Unknown chip revision in GCR.PDID: 0x%02x\n", PDID_REV(pdid)); + return -ENODEV; + } + + attr = kzalloc(sizeof(*attr), GFP_KERNEL); + if (!attr) + return -ENOMEM; + + attr->family = "Nuvoton NPCM"; + attr->soc_id = "WPCM450"; + attr->revision = revision; + soc = soc_device_register(attr); + if (IS_ERR(soc)) { + kfree(attr); + pr_warn("Could not register SoC device\n"); + return PTR_ERR(soc); + } + + return 0; +} +device_initcall(wpcm450_soc_init);