Commit 168b322e authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'imx-drivers-5.12' of...

Merge tag 'imx-drivers-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into arm/drivers

i.MX drivers change for 5.12:

- Change soc-imx8m to use platform driver, so that defer probe can be
  used to resolve dependency on OCOTP clock.

* tag 'imx-drivers-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux:
  soc: imx8m: change to use platform driver

Link: https://lore.kernel.org/r/20210204120150.26186-1-shawnguo@kernel.org


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents ce8ccf21 7d981405
Loading
Loading
Loading
Loading
+72 −12
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@

#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
@@ -29,7 +31,7 @@

struct imx8_soc_data {
	char *name;
	u32 (*soc_revision)(void);
	u32 (*soc_revision)(struct device *dev);
};

static u64 soc_uid;
@@ -50,7 +52,7 @@ static u32 imx8mq_soc_revision_from_atf(void)
static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
#endif

static u32 __init imx8mq_soc_revision(void)
static u32 __init imx8mq_soc_revision(struct device *dev)
{
	struct device_node *np;
	void __iomem *ocotp_base;
@@ -75,9 +77,20 @@ static u32 __init imx8mq_soc_revision(void)
			rev = REV_B1;
	}

	if (dev) {
		int ret;

		ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid);
		if (ret) {
			iounmap(ocotp_base);
			of_node_put(np);
			return ret;
		}
	} else {
		soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
		soc_uid <<= 32;
		soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
	}

	iounmap(ocotp_base);
	of_node_put(np);
@@ -107,7 +120,7 @@ static void __init imx8mm_soc_uid(void)
	of_node_put(np);
}

static u32 __init imx8mm_soc_revision(void)
static u32 __init imx8mm_soc_revision(struct device *dev)
{
	struct device_node *np;
	void __iomem *anatop_base;
@@ -125,7 +138,15 @@ static u32 __init imx8mm_soc_revision(void)
	iounmap(anatop_base);
	of_node_put(np);

	if (dev) {
		int ret;

		ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid);
		if (ret)
			return ret;
	} else {
		imx8mm_soc_uid();
	}

	return rev;
}
@@ -150,7 +171,7 @@ static const struct imx8_soc_data imx8mp_soc_data = {
	.soc_revision = imx8mm_soc_revision,
};

static __maybe_unused const struct of_device_id imx8_soc_match[] = {
static __maybe_unused const struct of_device_id imx8_machine_match[] = {
	{ .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, },
	{ .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, },
	{ .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, },
@@ -158,12 +179,20 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = {
	{ }
};

static __maybe_unused const struct of_device_id imx8_soc_match[] = {
	{ .compatible = "fsl,imx8mq-soc", .data = &imx8mq_soc_data, },
	{ .compatible = "fsl,imx8mm-soc", .data = &imx8mm_soc_data, },
	{ .compatible = "fsl,imx8mn-soc", .data = &imx8mn_soc_data, },
	{ .compatible = "fsl,imx8mp-soc", .data = &imx8mp_soc_data, },
	{ }
};

#define imx8_revision(soc_rev) \
	soc_rev ? \
	kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf,  soc_rev & 0xf) : \
	"unknown"

static int __init imx8_soc_init(void)
static int imx8_soc_info(struct platform_device *pdev)
{
	struct soc_device_attribute *soc_dev_attr;
	struct soc_device *soc_dev;
@@ -182,7 +211,10 @@ static int __init imx8_soc_init(void)
	if (ret)
		goto free_soc;

	id = of_match_node(imx8_soc_match, of_root);
	if (pdev)
		id = of_match_node(imx8_soc_match, pdev->dev.of_node);
	else
		id = of_match_node(imx8_machine_match, of_root);
	if (!id) {
		ret = -ENODEV;
		goto free_soc;
@@ -191,8 +223,16 @@ static int __init imx8_soc_init(void)
	data = id->data;
	if (data) {
		soc_dev_attr->soc_id = data->name;
		if (data->soc_revision)
			soc_rev = data->soc_revision();
		if (data->soc_revision) {
			if (pdev) {
				soc_rev = data->soc_revision(&pdev->dev);
				ret = soc_rev;
				if (ret < 0)
					goto free_soc;
			} else {
				soc_rev = data->soc_revision(NULL);
			}
		}
	}

	soc_dev_attr->revision = imx8_revision(soc_rev);
@@ -230,4 +270,24 @@ static int __init imx8_soc_init(void)
	kfree(soc_dev_attr);
	return ret;
}

/* Retain device_initcall is for backward compatibility with DTS. */
static int __init imx8_soc_init(void)
{
	if (of_find_matching_node_and_match(NULL, imx8_soc_match, NULL))
		return 0;

	return imx8_soc_info(NULL);
}
device_initcall(imx8_soc_init);

static struct platform_driver imx8_soc_info_driver = {
	.probe = imx8_soc_info,
	.driver = {
		.name = "imx8_soc_info",
		.of_match_table = imx8_soc_match,
	},
};

module_platform_driver(imx8_soc_info_driver);
MODULE_LICENSE("GPL v2");