* [PATCH v2 2/2] ARM: i.MX8M: convert the machine init to the soc driver
2024-01-16 17:10 [PATCH v2 1/2] Port SoC framework from Linux Marco Felsch
@ 2024-01-16 17:10 ` Marco Felsch
2024-01-24 8:27 ` [PATCH v2 1/2] Port SoC framework from Linux Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Marco Felsch @ 2024-01-16 17:10 UTC (permalink / raw)
To: barebox
Convert the i.MX8M machine init code to the previously introduced soc
framework. The soc driver was mostly copied from Linux with slightly
adaptions for barebox. To the soc driver is called during the
postcore_initcall to keep the level aligned with the previous imx_init().
The ocotp clock must keept running else the ARM-SMCCC stuck for calls
where the TF-A tries to access the ocotp.
A sample output of the new introduced soc0 device:
|
| barebox@FSL i.MX8MM EVKB:/ devinfo soc0
| Bus: soc
| Parameters:
| family: Freescale i.MX (type: string)
| machine: FSL i.MX8MM EVKB (type: string)
| revision: 1.0 (type: string)
| serial_number: 15182A09DAB5B3C9 (type: string)
| soc_id: i.MX8MM (type: string)
Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
Changelog:
v2:
- make use of xasprintf()
- check of_compatible early and return no error if it does not match
arch/arm/mach-imx/Kconfig | 1 +
arch/arm/mach-imx/imx.c | 12 +-
arch/arm/mach-imx/imx8m.c | 137 +----------------
drivers/soc/imx/Makefile | 1 +
drivers/soc/imx/soc-imx8m.c | 296 ++++++++++++++++++++++++++++++++++++
5 files changed, 307 insertions(+), 140 deletions(-)
create mode 100644 drivers/soc/imx/soc-imx8m.c
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 5429b80b0fdf..3aa551fd5334 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -157,6 +157,7 @@ config ARCH_IMX8M
select IMX8M_DRAM
select PBL_VERIFY_PIGGY if HABV4
select ARM_USE_COMPRESSED_DTB
+ select SOC_BUS
imply FSL_CAAM_RNG_PBL_INIT if HAVE_OPTEE
config ARCH_IMX8MM
diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index c97e566e0c56..f3491c6df7fa 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -95,6 +95,10 @@ static int imx_init(void)
return 0;
}
+ /*
+ * Don't add new SoCs to this list, instead use the new
+ * soc framework (see soc-imx8m.c).
+ */
if (cpu_is_mx1())
ret = imx1_init();
else if (cpu_is_mx21())
@@ -118,13 +122,13 @@ static int imx_init(void)
else if (cpu_is_mx7())
ret = imx7_init();
else if (cpu_is_mx8mm())
- ret = imx8mm_init();
+ ret = 0;
else if (cpu_is_mx8mn())
- ret = imx8mn_init();
+ ret = 0;
else if (cpu_is_mx8mp())
- ret = imx8mp_init();
+ ret = 0;
else if (cpu_is_mx8mq())
- ret = imx8mq_init();
+ ret = 0;
else if (cpu_is_mx93())
ret = imx93_init();
else if (cpu_is_vf610())
diff --git a/arch/arm/mach-imx/imx8m.c b/arch/arm/mach-imx/imx8m.c
index 73b420b38697..52e42ee9ef63 100644
--- a/arch/arm/mach-imx/imx8m.c
+++ b/arch/arm/mach-imx/imx8m.c
@@ -2,28 +2,16 @@
#include <init.h>
#include <common.h>
-#include <asm/optee.h>
#include <linux/sizes.h>
#include <io.h>
-#include <pm_domain.h>
#include <asm/syscounter.h>
#include <asm/system.h>
-#include <asm-generic/memory_layout.h>
#include <mach/imx/generic.h>
-#include <mach/imx/revision.h>
-#include <mach/imx/imx8mq.h>
#include <mach/imx/imx8m-ccm-regs.h>
-#include <mach/imx/reset-reason.h>
-#include <mach/imx/ocotp.h>
-#include <mach/imx/imx8mp-regs.h>
-#include <mach/imx/imx8mq-regs.h>
-#include <mach/imx/scratch.h>
-#include <mach/imx/tzasc.h>
#include <soc/imx8m/clk-early.h>
-#include <tee/optee.h>
+#include <linux/bitfield.h>
#include <linux/iopoll.h>
-#include <linux/arm-smccc.h>
#define IMX_SIP_BUILDINFO 0xC2000003
#define IMX_SIP_BUILDINFO_GET_COMMITHASH 0x00
@@ -51,129 +39,6 @@ void imx8m_ccgr_clock_disable(int index)
ccm + IMX8M_CCM_CCGRn_CLR(index));
}
-u64 imx8m_uid(void)
-{
- return imx_ocotp_read_uid(IOMEM(MX8M_OCOTP_BASE_ADDR));
-}
-
-static int imx8m_init(const char *cputypestr)
-{
- void __iomem *src = IOMEM(MX8M_SRC_BASE_ADDR);
-
- genpd_activate();
-
- /*
- * Reset reasons seem to be identical to that of i.MX7
- */
- imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons);
- pr_info("%s unique ID: %llx\n", cputypestr, imx8m_uid());
-
- if (IS_ENABLED(CONFIG_PBL_OPTEE) && tzc380_is_enabled()) {
- static struct of_optee_fixup_data optee_fixup_data = {
- .shm_size = OPTEE_SHM_SIZE,
- .method = "smc",
- };
-
- optee_set_membase(imx8m_scratch_get_optee_hdr());
- of_optee_fixup(of_get_root_node(), &optee_fixup_data);
- of_register_fixup(of_optee_fixup, &optee_fixup_data);
- }
-
- return 0;
-}
-
-int imx8mm_init(void)
-{
- void __iomem *anatop = IOMEM(MX8M_ANATOP_BASE_ADDR);
- uint32_t type = FIELD_GET(DIGPROG_MAJOR,
- readl(anatop + MX8MM_ANATOP_DIGPROG));
- const char *cputypestr;
-
- imx8mm_boot_save_loc();
-
- switch (type) {
- case IMX8M_CPUTYPE_IMX8MM:
- cputypestr = "i.MX8MM";
- break;
- default:
- cputypestr = "unknown i.MX8M";
- break;
- };
-
- imx_set_silicon_revision(cputypestr, imx8mm_cpu_revision());
-
- return imx8m_init(cputypestr);
-}
-
-int imx8mn_init(void)
-{
- void __iomem *anatop = IOMEM(MX8M_ANATOP_BASE_ADDR);
- uint32_t type = FIELD_GET(DIGPROG_MAJOR,
- readl(anatop + MX8MN_ANATOP_DIGPROG));
- const char *cputypestr;
-
- imx8mn_boot_save_loc();
-
- switch (type) {
- case IMX8M_CPUTYPE_IMX8MN:
- cputypestr = "i.MX8MN";
- break;
- default:
- cputypestr = "unknown i.MX8M";
- break;
- };
-
- imx_set_silicon_revision(cputypestr, imx8mn_cpu_revision());
-
- return imx8m_init(cputypestr);
-}
-
-int imx8mp_init(void)
-{
- void __iomem *anatop = IOMEM(MX8MP_ANATOP_BASE_ADDR);
- uint32_t type = FIELD_GET(DIGPROG_MAJOR,
- readl(anatop + MX8MP_ANATOP_DIGPROG));
- const char *cputypestr;
-
- imx8mp_boot_save_loc();
-
- switch (type) {
- case IMX8M_CPUTYPE_IMX8MP:
- cputypestr = "i.MX8MP";
- break;
- default:
- cputypestr = "unknown i.MX8M";
- break;
- };
-
- imx_set_silicon_revision(cputypestr, imx8mp_cpu_revision());
-
- return imx8m_init(cputypestr);
-}
-
-int imx8mq_init(void)
-{
- void __iomem *anatop = IOMEM(MX8M_ANATOP_BASE_ADDR);
- uint32_t type = FIELD_GET(DIGPROG_MAJOR,
- readl(anatop + MX8MQ_ANATOP_DIGPROG));
- const char *cputypestr;
-
- imx8mq_boot_save_loc();
-
- switch (type) {
- case IMX8M_CPUTYPE_IMX8MQ:
- cputypestr = "i.MX8MQ";
- break;
- default:
- cputypestr = "unknown i.MX8M";
- break;
- };
-
- imx_set_silicon_revision(cputypestr, imx8mq_cpu_revision());
-
- return imx8m_init(cputypestr);
-}
-
#define INTPLL_DIV20_CLKE_MASK BIT(27)
#define INTPLL_DIV10_CLKE_MASK BIT(25)
#define INTPLL_DIV8_CLKE_MASK BIT(23)
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
index bd1717b03883..9d9c2e88798c 100644
--- a/drivers/soc/imx/Makefile
+++ b/drivers/soc/imx/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
obj-$(CONFIG_IMX8M_FEATCTRL) += imx8m-featctrl.o
+obj-$(CONFIG_ARCH_IMX8M) += soc-imx8m.o
diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c
new file mode 100644
index 000000000000..c648b201b747
--- /dev/null
+++ b/drivers/soc/imx/soc-imx8m.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: 2024 Marco Felsch, Pengutronix
+/*
+ * Based on Linux drivers/soc/imx/soc-imx8m.c:
+ * Copyright 2019 NXP.
+ */
+
+#include <init.h>
+#include <of.h>
+#include <of_address.h>
+#include <pm_domain.h>
+
+#include <asm/optee.h>
+#include <asm-generic/memory_layout.h>
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+#include <linux/arm-smccc.h>
+#include <linux/clk.h>
+
+#include <mach/imx/generic.h>
+#include <mach/imx/imx8m-regs.h>
+#include <mach/imx/reset-reason.h>
+#include <mach/imx/revision.h>
+#include <mach/imx/scratch.h>
+#include <mach/imx/tzasc.h>
+
+#include <tee/optee.h>
+
+#define REV_B1 0x21
+
+#define IMX8MQ_SW_INFO_B1 0x40
+#define IMX8MQ_SW_MAGIC_B1 0xff0055aa
+
+#define IMX_SIP_GET_SOC_INFO 0xc2000006
+
+#define OCOTP_UID_LOW 0x410
+#define OCOTP_UID_HIGH 0x420
+
+#define IMX8MP_OCOTP_UID_OFFSET 0x10
+
+/* Same as ANADIG_DIGPROG_IMX7D */
+#define ANADIG_DIGPROG_IMX8MM 0x800
+
+struct imx8_soc_data {
+ char *name;
+ u32 (*soc_revision)(void);
+ void (*save_boot_loc)(void);
+};
+
+static u64 soc_uid;
+
+#ifdef CONFIG_HAVE_ARM_SMCCC
+static u32 imx8mq_soc_revision_from_atf(void)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res);
+
+ if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
+ return 0;
+ else
+ return res.a0 & 0xff;
+}
+#else
+static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
+#endif
+
+static u32 __init imx8mq_soc_revision(void)
+{
+ struct device_node *np;
+ void __iomem *ocotp_base;
+ u32 magic;
+ u32 rev;
+ struct clk *clk;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
+ if (!np)
+ return 0;
+
+ ocotp_base = of_iomap(np, 0);
+ WARN_ON(!ocotp_base);
+ clk = of_clk_get_by_name(np, NULL);
+ if (IS_ERR(clk)) {
+ WARN_ON(IS_ERR(clk));
+ return 0;
+ }
+
+ clk_prepare_enable(clk);
+
+ /*
+ * SOC revision on older imx8mq is not available in fuses so query
+ * the value from ATF instead.
+ */
+ rev = imx8mq_soc_revision_from_atf();
+ if (!rev) {
+ magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1);
+ if (magic == IMX8MQ_SW_MAGIC_B1)
+ rev = REV_B1;
+ }
+
+ soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
+ soc_uid <<= 32;
+ soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
+
+ /* Keep the OCOTP clk on for the TF-A else the CPU stuck */
+ of_node_put(np);
+
+ return rev;
+}
+
+static void __init imx8mm_soc_uid(void)
+{
+ void __iomem *ocotp_base;
+ struct device_node *np;
+ struct clk *clk;
+ u32 offset = of_machine_is_compatible("fsl,imx8mp") ?
+ IMX8MP_OCOTP_UID_OFFSET : 0;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
+ if (!np)
+ return;
+
+ ocotp_base = of_iomap(np, 0);
+ WARN_ON(!ocotp_base);
+ clk = of_clk_get_by_name(np, NULL);
+ if (IS_ERR(clk)) {
+ WARN_ON(IS_ERR(clk));
+ return;
+ }
+
+ clk_prepare_enable(clk);
+
+ soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
+ soc_uid <<= 32;
+ soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
+
+ /* Keep the OCOTP clk on for the TF-A else the CPU stuck */
+ of_node_put(np);
+}
+
+static u32 __init imx8mm_soc_revision(void)
+{
+ struct device_node *np;
+ void __iomem *anatop_base;
+ u32 rev;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
+ if (!np)
+ return 0;
+
+ anatop_base = of_iomap(np, 0);
+ WARN_ON(!anatop_base);
+
+ rev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM);
+
+ of_node_put(np);
+
+ imx8mm_soc_uid();
+
+ return rev;
+}
+
+static const struct imx8_soc_data imx8mq_soc_data = {
+ .name = "i.MX8MQ",
+ .soc_revision = imx8mq_soc_revision,
+ .save_boot_loc = imx8mq_boot_save_loc,
+};
+
+static const struct imx8_soc_data imx8mm_soc_data = {
+ .name = "i.MX8MM",
+ .soc_revision = imx8mm_soc_revision,
+ .save_boot_loc = imx8mm_boot_save_loc,
+};
+
+static const struct imx8_soc_data imx8mn_soc_data = {
+ .name = "i.MX8MN",
+ .soc_revision = imx8mm_soc_revision,
+ .save_boot_loc = imx8mn_boot_save_loc,
+};
+
+static const struct imx8_soc_data imx8mp_soc_data = {
+ .name = "i.MX8MP",
+ .soc_revision = imx8mm_soc_revision,
+ .save_boot_loc = imx8mp_boot_save_loc,
+};
+
+static __maybe_unused const struct of_device_id imx8_soc_match[] = {
+ { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, },
+ { .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, },
+ { .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, },
+ { .compatible = "fsl,imx8mp", .data = &imx8mp_soc_data, },
+ { }
+};
+
+static int imx8_soc_imx8m_init(struct soc_device_attribute *soc_dev_attr)
+{
+ void __iomem *src = IOMEM(MX8M_SRC_BASE_ADDR);
+ const char *uid = soc_dev_attr->serial_number;
+ const char *cputypestr = soc_dev_attr->soc_id;
+
+ genpd_activate();
+
+ /*
+ * Reset reasons seem to be identical to that of i.MX7
+ */
+ imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons);
+ pr_info("%s unique ID: %s\n", cputypestr, uid);
+
+ if (IS_ENABLED(CONFIG_PBL_OPTEE) && tzc380_is_enabled()) {
+ static struct of_optee_fixup_data optee_fixup_data = {
+ .shm_size = OPTEE_SHM_SIZE,
+ .method = "smc",
+ };
+
+ optee_set_membase(imx8m_scratch_get_optee_hdr());
+ of_optee_fixup(of_get_root_node(), &optee_fixup_data);
+ of_register_fixup(of_optee_fixup, &optee_fixup_data);
+ }
+
+ return 0;
+}
+
+#define imx8_revision(soc_rev) \
+ soc_rev ? \
+ xasprintf("%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \
+ "unknown"
+
+static int __init imx8_soc_init(void)
+{
+ struct device_node *of_root = of_get_root_node();
+ struct soc_device_attribute *soc_dev_attr;
+ struct soc_device *soc_dev;
+ const struct of_device_id *id;
+ u32 soc_rev = 0;
+ const struct imx8_soc_data *data;
+ int ret;
+
+ id = of_match_node(imx8_soc_match, of_root);
+ if (!id)
+ return 0;
+
+ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ if (!soc_dev_attr)
+ return -ENOMEM;
+
+ soc_dev_attr->family = "Freescale i.MX";
+
+ ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine);
+ if (ret)
+ goto free_soc;
+
+ data = id->data;
+ if (data) {
+ soc_dev_attr->soc_id = data->name;
+ if (data->soc_revision)
+ soc_rev = data->soc_revision();
+ if (data->save_boot_loc)
+ data->save_boot_loc();
+ }
+
+ soc_dev_attr->revision = imx8_revision(soc_rev);
+ if (!soc_dev_attr->revision) {
+ ret = -ENOMEM;
+ goto free_soc;
+ }
+
+ soc_dev_attr->serial_number = xasprintf("%016llX", soc_uid);
+ if (!soc_dev_attr->serial_number) {
+ ret = -ENOMEM;
+ goto free_rev;
+ }
+
+ soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR(soc_dev)) {
+ ret = PTR_ERR(soc_dev);
+ goto free_serial_number;
+ }
+
+ imx_set_silicon_revision(soc_dev_attr->soc_id, soc_rev);
+
+ return imx8_soc_imx8m_init(soc_dev_attr);
+
+free_serial_number:
+ kfree(soc_dev_attr->serial_number);
+free_rev:
+ if (strcmp(soc_dev_attr->revision, "unknown"))
+ kfree(soc_dev_attr->revision);
+free_soc:
+ kfree(soc_dev_attr);
+ return ret;
+}
+/* Aligned with imx_init() to not cause regressions */
+postcore_initcall(imx8_soc_init);
+MODULE_LICENSE("GPL");
--
2.39.2
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2 1/2] Port SoC framework from Linux
2024-01-16 17:10 [PATCH v2 1/2] Port SoC framework from Linux Marco Felsch
2024-01-16 17:10 ` [PATCH v2 2/2] ARM: i.MX8M: convert the machine init to the soc driver Marco Felsch
@ 2024-01-24 8:27 ` Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2024-01-24 8:27 UTC (permalink / raw)
To: Marco Felsch; +Cc: barebox
Hi Marco,
Looks good to me. Can you rebase on current master?
Sascha
On Tue, Jan 16, 2024 at 06:10:25PM +0100, Marco Felsch wrote:
> This adds the initial support for the Linux soc framework which can be
> used to register all SoC relevant informations. The framework can be
> used by driver to check for errata for an specific soc(-revision) in the
> future since this require porting the matching function.
>
> For now it gathers all required SoC information and provide a standard
> interface to query the data via device params.
>
> Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
> ---
> Changelog:
> v2:
> - nothing
>
> drivers/base/Kconfig | 3 +
> drivers/base/Makefile | 1 +
> drivers/base/soc.c | 123 ++++++++++++++++++++++++++++++++++++++++
> include/linux/sys_soc.h | 39 +++++++++++++
> 4 files changed, 166 insertions(+)
> create mode 100644 drivers/base/soc.c
> create mode 100644 include/linux/sys_soc.h
>
> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index 612a84be33e7..21a4793cfa47 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -6,4 +6,7 @@ config PM_GENERIC_DOMAINS
> config FEATURE_CONTROLLER
> bool "Feature controller support" if COMPILE_TEST || SANDBOX
>
> +config SOC_BUS
> + bool
> +
> source "drivers/base/regmap/Kconfig"
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index e8e354cdaabc..acc53763da35 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -7,3 +7,4 @@ obj-y += regmap/
>
> obj-$(CONFIG_PM_GENERIC_DOMAINS) += power.o
> obj-$(CONFIG_FEATURE_CONTROLLER) += featctrl.o
> +obj-$(CONFIG_SOC_BUS) += soc.o
> diff --git a/drivers/base/soc.c b/drivers/base/soc.c
> new file mode 100644
> index 000000000000..a481f8987b56
> --- /dev/null
> +++ b/drivers/base/soc.c
> @@ -0,0 +1,123 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// SPDX-FileCopyrightText: 2024 Marco Felsch, Pengutronix
> +/*
> + * Based on Linux drivers/base/soc.c:
> + * Copyright (C) ST-Ericsson SA 2011
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <of.h>
> +
> +#include <linux/slab.h>
> +#include <linux/sys_soc.h>
> +#include <linux/err.h>
> +
> +struct soc_device {
> + struct device dev;
> + struct soc_device_attribute *attr;
> +};
> +
> +static struct bus_type soc_bus_type = {
> + .name = "soc",
> +};
> +static bool soc_bus_registered;
> +
> +static void soc_device_add_params(struct soc_device *soc_dev)
> +{
> + struct soc_device_attribute *attr = soc_dev->attr;
> + struct device *dev = &soc_dev->dev;
> +
> + if (attr->machine)
> + dev_add_param_string_fixed(dev, "machine", attr->machine);
> + if (attr->family)
> + dev_add_param_string_fixed(dev, "family", attr->family);
> + if (attr->revision)
> + dev_add_param_string_fixed(dev, "revision", attr->revision);
> + if (attr->serial_number)
> + dev_add_param_string_fixed(dev, "serial_number", attr->serial_number);
> + if (attr->soc_id)
> + dev_add_param_string_fixed(dev, "soc_id", attr->soc_id);
> +}
> +
> +static void soc_device_get_machine(struct soc_device_attribute *soc_dev_attr)
> +{
> + struct device_node *np;
> +
> + if (soc_dev_attr->machine)
> + return;
> +
> + np = of_find_node_by_path("/");
> + of_property_read_string(np, "model", &soc_dev_attr->machine);
> + of_node_put(np);
> +}
> +
> +static struct soc_device_attribute *early_soc_dev_attr;
> +
> +struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr)
> +{
> + struct soc_device *soc_dev;
> + int ret;
> +
> + soc_device_get_machine(soc_dev_attr);
> +
> + if (!soc_bus_registered) {
> + if (early_soc_dev_attr)
> + return ERR_PTR(-EBUSY);
> + early_soc_dev_attr = soc_dev_attr;
> + return NULL;
> + }
> +
> + soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
> + if (!soc_dev) {
> + ret = -ENOMEM;
> + goto out1;
> + }
> +
> + soc_dev->attr = soc_dev_attr;
> + soc_dev->dev.bus = &soc_bus_type;
> + soc_dev->dev.id = DEVICE_ID_DYNAMIC;
> +
> + dev_set_name(&soc_dev->dev, "soc");
> +
> + ret = device_register(&soc_dev->dev);
> + if (ret) {
> + put_device(&soc_dev->dev);
> + goto out2;
> + }
> +
> + soc_device_add_params(soc_dev);
> +
> + return soc_dev;
> +
> +out2:
> + kfree(soc_dev);
> +out1:
> + return ERR_PTR(ret);
> +}
> +EXPORT_SYMBOL_GPL(soc_device_register);
> +
> +/* Ensure soc_dev->attr is freed after calling soc_device_unregister. */
> +void soc_device_unregister(struct soc_device *soc_dev)
> +{
> + device_unregister(&soc_dev->dev);
> + kfree(soc_dev);
> + early_soc_dev_attr = NULL;
> +}
> +EXPORT_SYMBOL_GPL(soc_device_unregister);
> +
> +static int __init soc_bus_register(void)
> +{
> + int ret;
> +
> + ret = bus_register(&soc_bus_type);
> + if (ret)
> + return ret;
> + soc_bus_registered = true;
> +
> + if (early_soc_dev_attr)
> + return PTR_ERR(soc_device_register(early_soc_dev_attr));
> +
> + return 0;
> +}
> +core_initcall(soc_bus_register);
> diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h
> new file mode 100644
> index 000000000000..fd597ae54096
> --- /dev/null
> +++ b/include/linux/sys_soc.h
> @@ -0,0 +1,39 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) ST-Ericsson SA 2011
> + * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson.
> + */
> +#ifndef __SOC_BUS_H
> +#define __SOC_BUS_H
> +
> +#include <linux/device.h>
> +
> +struct soc_device_attribute {
> + const char *machine;
> + const char *family;
> + const char *revision;
> + const char *serial_number;
> + const char *soc_id;
> + const void *data;
> +};
> +
> +/**
> + * soc_device_register - register SoC as a device
> + * @soc_plat_dev_attr: Attributes passed from platform to be attributed to a SoC
> + */
> +struct soc_device *soc_device_register(
> + struct soc_device_attribute *soc_plat_dev_attr);
> +
> +/**
> + * soc_device_unregister - unregister SoC device
> + * @dev: SoC device to be unregistered
> + */
> +void soc_device_unregister(struct soc_device *soc_dev);
> +
> +/**
> + * soc_device_to_device - helper function to fetch struct device
> + * @soc: Previously registered SoC device container
> + */
> +struct device *soc_device_to_device(struct soc_device *soc);
> +
> +#endif /* __SOC_BUS_H */
> --
> 2.39.2
>
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 3+ messages in thread