Message ID | 20200508100100.20740-3-grygorii.strashko@ti.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | soc: ti: add k3 platforms chipid module driver | expand |
On Fri, May 8, 2020 at 12:01 PM Grygorii Strashko <grygorii.strashko@ti.com> wrote: > +static int __init k3_chipinfo_init(void) > +{ > + struct soc_device_attribute *soc_dev_attr; > + struct soc_device *soc_dev; > + struct device_node *node; > + struct regmap *regmap; > + u32 partno_id; > + u32 variant; > + u32 jtag_id; > + u32 mfg; > + int ret; > + > + node = of_find_compatible_node(NULL, NULL, "ti,am654-chipid"); > + if (!node) > + return -ENODEV; This will fail the initcall and print a warning when the kernel runs on any other SoC. Would it be possible to just make this a platform_driver? If not, I think you should silently return success when the device node is absent. Arnd
Hi Arnd, On 09/05/2020 01:17, Arnd Bergmann wrote: > On Fri, May 8, 2020 at 12:01 PM Grygorii Strashko > <grygorii.strashko@ti.com> wrote: > >> +static int __init k3_chipinfo_init(void) >> +{ >> + struct soc_device_attribute *soc_dev_attr; >> + struct soc_device *soc_dev; >> + struct device_node *node; >> + struct regmap *regmap; >> + u32 partno_id; >> + u32 variant; >> + u32 jtag_id; >> + u32 mfg; >> + int ret; >> + >> + node = of_find_compatible_node(NULL, NULL, "ti,am654-chipid"); >> + if (!node) >> + return -ENODEV; > > This will fail the initcall and print a warning when the kernel runs on any > other SoC. Would it be possible to just make this a platform_driver? > > If not, I think you should silently return success when the device > node is absent. Thank you for your report. Can' make it platform drv., as te SoC info need to be accessible by divers early. I'll fix it to return success.
On Mon, May 11, 2020 at 1:11 PM Grygorii Strashko <grygorii.strashko@ti.com> wrote: > > Hi Arnd, > > On 09/05/2020 01:17, Arnd Bergmann wrote: > > On Fri, May 8, 2020 at 12:01 PM Grygorii Strashko > > <grygorii.strashko@ti.com> wrote: > > > >> +static int __init k3_chipinfo_init(void) > >> +{ > >> + struct soc_device_attribute *soc_dev_attr; > >> + struct soc_device *soc_dev; > >> + struct device_node *node; > >> + struct regmap *regmap; > >> + u32 partno_id; > >> + u32 variant; > >> + u32 jtag_id; > >> + u32 mfg; > >> + int ret; > >> + > >> + node = of_find_compatible_node(NULL, NULL, "ti,am654-chipid"); > >> + if (!node) > >> + return -ENODEV; > > > > This will fail the initcall and print a warning when the kernel runs on any > > other SoC. Would it be possible to just make this a platform_driver? > > > > If not, I think you should silently return success when the device > > node is absent. > > Thank you for your report. > Can' make it platform drv., as the SoC info need to be accessible by divers early. Which drivers in particular? In most cases you should be able to still do this right by relying on initcall ordering as long as this one can only be built-in (or possibly only a module for compile-testing). Arnd
Hi Arnd, On 11/05/2020 15:43, Arnd Bergmann wrote: > On Mon, May 11, 2020 at 1:11 PM Grygorii Strashko > <grygorii.strashko@ti.com> wrote: >> >> Hi Arnd, >> >> On 09/05/2020 01:17, Arnd Bergmann wrote: >>> On Fri, May 8, 2020 at 12:01 PM Grygorii Strashko >>> <grygorii.strashko@ti.com> wrote: >>> >>>> +static int __init k3_chipinfo_init(void) >>>> +{ >>>> + struct soc_device_attribute *soc_dev_attr; >>>> + struct soc_device *soc_dev; >>>> + struct device_node *node; >>>> + struct regmap *regmap; >>>> + u32 partno_id; >>>> + u32 variant; >>>> + u32 jtag_id; >>>> + u32 mfg; >>>> + int ret; >>>> + >>>> + node = of_find_compatible_node(NULL, NULL, "ti,am654-chipid"); >>>> + if (!node) >>>> + return -ENODEV; >>> >>> This will fail the initcall and print a warning when the kernel runs on any >>> other SoC. Would it be possible to just make this a platform_driver? >>> >>> If not, I think you should silently return success when the device >>> node is absent. >> >> Thank you for your report. >> Can' make it platform drv., as the SoC info need to be accessible by divers early. > > Which drivers in particular? In most cases you should be able to still do this > right by relying on initcall ordering as long as this one can only be built-in > (or possibly only a module for compile-testing). Thanks for you review. As I'm aware of right now, it's going to be: ringacc, dma, net drv and mmc. So, It seems should work with platform_driver and subsys_initcall. I'll try it.
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 4486e055794c..e192fb788836 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -91,6 +91,16 @@ config TI_K3_RINGACC and a consumer. There is one RINGACC module per NAVSS on TI AM65x SoCs If unsure, say N. +config TI_K3_SOCINFO + bool + depends on ARCH_K3 || COMPILE_TEST + select SOC_BUS + select MFD_SYSCON + help + Include support for the SoC bus socinfo for the TI K3 Multicore SoC + platforms to provide information about the SoC family and + variant to user space. + endif # SOC_TI config TI_SCI_INTA_MSI_DOMAIN diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index bec827937a5f..1110e5c98685 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o obj-$(CONFIG_TI_K3_RINGACC) += k3-ringacc.o +obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c new file mode 100644 index 000000000000..57c6bde7adf5 --- /dev/null +++ b/drivers/soc/ti/k3-socinfo.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TI K3 SoC info driver + * + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/sys_soc.h> + +#define CTRLMMR_WKUP_JTAGID_REG 0 +/* + * Bits: + * 31-28 VARIANT Device variant + * 27-12 PARTNO Part number + * 11-1 MFG Indicates TI as manufacturer (0x17) + * 1 Always 1 + */ +#define CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT (28) +#define CTRLMMR_WKUP_JTAGID_VARIANT_MASK GENMASK(31, 28) + +#define CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT (12) +#define CTRLMMR_WKUP_JTAGID_PARTNO_MASK GENMASK(27, 12) + +#define CTRLMMR_WKUP_JTAGID_MFG_SHIFT (1) +#define CTRLMMR_WKUP_JTAGID_MFG_MASK GENMASK(11, 1) + +#define CTRLMMR_WKUP_JTAGID_MFG_TI 0x17 + +static const struct k3_soc_id { + unsigned int id; + const char *family_name; +} k3_soc_ids[] = { + { 0xBB5A, "AM65X" }, + { 0xBB64, "J721E" }, +}; + +static int __init partno_to_names(unsigned int partno, + struct soc_device_attribute *soc_dev_attr) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(k3_soc_ids); i++) + if (partno == k3_soc_ids[i].id) { + soc_dev_attr->family = k3_soc_ids[i].family_name; + return 0; + } + + return -EINVAL; +} + +static int __init k3_chipinfo_init(void) +{ + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + struct device_node *node; + struct regmap *regmap; + u32 partno_id; + u32 variant; + u32 jtag_id; + u32 mfg; + int ret; + + node = of_find_compatible_node(NULL, NULL, "ti,am654-chipid"); + if (!node) + return -ENODEV; + + regmap = device_node_to_regmap(node); + of_node_put(node); + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + ret = regmap_read(regmap, CTRLMMR_WKUP_JTAGID_REG, &jtag_id); + if (ret < 0) + return ret; + + mfg = (jtag_id & CTRLMMR_WKUP_JTAGID_MFG_MASK) >> + CTRLMMR_WKUP_JTAGID_MFG_SHIFT; + + if (mfg != CTRLMMR_WKUP_JTAGID_MFG_TI) { + pr_err("Invalid MFG SoC\n"); + return -ENODEV; + } + + variant = (jtag_id & CTRLMMR_WKUP_JTAGID_VARIANT_MASK) >> + CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT; + variant++; + + partno_id = (jtag_id & CTRLMMR_WKUP_JTAGID_PARTNO_MASK) >> + CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT; + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return -ENOMEM; + + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0", variant); + if (!soc_dev_attr->revision) { + ret = -ENOMEM; + goto err; + } + + ret = partno_to_names(partno_id, soc_dev_attr); + if (ret) { + pr_err("Unknown SoC JTAGID[0x%08X]\n", jtag_id); + ret = -ENODEV; + goto err_free_rev; + } + + node = of_find_node_by_path("/"); + of_property_read_string(node, "model", &soc_dev_attr->machine); + of_node_put(node); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + ret = PTR_ERR(soc_dev); + goto err_free_rev; + } + + pr_info("Family:%s rev:%s JTAGID[0x%08x] Detected\n", + soc_dev_attr->family, + soc_dev_attr->revision, jtag_id); + + return 0; + +err_free_rev: + kfree(soc_dev_attr->revision); +err: + kfree(soc_dev_attr); + return ret; +} + +subsys_initcall(k3_chipinfo_init);