]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
dm: soc: Introduce UCLASS_SOC for SOC ID and attribute matching
authorDave Gerlach <d-gerlach@ti.com>
Thu, 16 Jul 2020 04:39:57 +0000 (23:39 -0500)
committerSimon Glass <sjg@chromium.org>
Mon, 20 Jul 2020 17:37:47 +0000 (11:37 -0600)
Introduce UCLASS_SOC to be used for SOC identification and attribute
matching based on the SoC ID info. This allows drivers to be provided
for SoCs to retrieve SoC identifying information and also for matching
device attributes for selecting SoC specific data.

This is useful for other device drivers that may need different
parameters or quirks enabled depending on the specific device variant in
use.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
drivers/soc/Kconfig
drivers/soc/Makefile
drivers/soc/soc-uclass.c [new file with mode: 0644]
include/dm/uclass-id.h
include/soc.h [new file with mode: 0644]

index 7b4e4d613088232ecbde52d41d8f5bcb4364b7e7..e715dfd017121ff4c6638ce9743f09ed48dfefe1 100644 (file)
@@ -1,5 +1,14 @@
 menu "SOC (System On Chip) specific Drivers"
 
+config SOC_DEVICE
+       bool "Enable SoC Device ID drivers using Driver Model"
+       help
+         This allows drivers to be provided for SoCs to help in identifying
+         the SoC in use and matching SoC attributes for selecting SoC
+         specific data. This is useful for other device drivers that may
+         need different parameters or quirks enabled depending on the
+         specific device variant in use.
+
 source "drivers/soc/ti/Kconfig"
 
 endmenu
index ce253b7aa88612f2425dd0fbe5d8c003693ac365..1c09a84656704371a904ff38d00e46e87fa47085 100644 (file)
@@ -3,3 +3,4 @@
 # Makefile for the U-Boot SOC specific device drivers.
 
 obj-$(CONFIG_SOC_TI) += ti/
+obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
diff --git a/drivers/soc/soc-uclass.c b/drivers/soc/soc-uclass.c
new file mode 100644 (file)
index 0000000..c32d647
--- /dev/null
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
+ *     Dave Gerlach <d-gerlach@ti.com>
+ */
+
+#include <common.h>
+#include <soc.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/lists.h>
+#include <dm/root.h>
+
+int soc_get(struct udevice **devp)
+{
+       return uclass_first_device_err(UCLASS_SOC, devp);
+}
+
+int soc_get_machine(struct udevice *dev, char *buf, int size)
+{
+       struct soc_ops *ops = soc_get_ops(dev);
+
+       if (!ops->get_machine)
+               return -ENOSYS;
+
+       return ops->get_machine(dev, buf, size);
+}
+
+int soc_get_family(struct udevice *dev, char *buf, int size)
+{
+       struct soc_ops *ops = soc_get_ops(dev);
+
+       if (!ops->get_family)
+               return -ENOSYS;
+
+       return ops->get_family(dev, buf, size);
+}
+
+int soc_get_revision(struct udevice *dev, char *buf, int size)
+{
+       struct soc_ops *ops = soc_get_ops(dev);
+
+       if (!ops->get_revision)
+               return -ENOSYS;
+
+       return ops->get_revision(dev, buf, size);
+}
+
+const struct soc_attr *
+soc_device_match(const struct soc_attr *matches)
+{
+       bool match;
+       struct udevice *soc;
+       char str[SOC_MAX_STR_SIZE];
+
+       if (!matches)
+               return NULL;
+
+       if (soc_get(&soc))
+               return NULL;
+
+       while (1) {
+               if (!(matches->machine || matches->family ||
+                     matches->revision))
+                       break;
+
+               match = true;
+
+               if (matches->machine) {
+                       if (!soc_get_machine(soc, str, SOC_MAX_STR_SIZE)) {
+                               if (strcmp(matches->machine, str))
+                                       match = false;
+                       }
+               }
+
+               if (matches->family) {
+                       if (!soc_get_family(soc, str, SOC_MAX_STR_SIZE)) {
+                               if (strcmp(matches->family, str))
+                                       match = false;
+                       }
+               }
+
+               if (matches->revision) {
+                       if (!soc_get_revision(soc, str, SOC_MAX_STR_SIZE)) {
+                               if (strcmp(matches->revision, str))
+                                       match = false;
+                       }
+               }
+
+               if (match)
+                       return matches;
+
+               matches++;
+       }
+
+       return NULL;
+}
+
+UCLASS_DRIVER(soc) = {
+       .id             = UCLASS_SOC,
+       .name           = "soc",
+};
index 7837d459f18c8a09d0b4c8ed74d02653ea716cfb..690a8ed4df49c1c900ad5055daf6e1ef9537de13 100644 (file)
@@ -97,6 +97,7 @@ enum uclass_id {
        UCLASS_SERIAL,          /* Serial UART */
        UCLASS_SIMPLE_BUS,      /* Bus with child devices */
        UCLASS_SMEM,            /* Shared memory interface */
+       UCLASS_SOC,             /* SOC Device */
        UCLASS_SOUND,           /* Playing simple sounds */
        UCLASS_SPI,             /* SPI bus */
        UCLASS_SPI_FLASH,       /* SPI flash */
diff --git a/include/soc.h b/include/soc.h
new file mode 100644 (file)
index 0000000..a55eb1b
--- /dev/null
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
+ *     Dave Gerlach <d-gerlach@ti.com>
+ */
+
+#ifndef __SOC_H
+#define __SOC_H
+
+#define SOC_MAX_STR_SIZE       128
+
+/**
+ * struct soc_attr - Contains SoC identify information to be used in
+ *                  SoC matching. An array of these structs
+ *                  representing different SoCs can be passed to
+ *                  soc_device_match and the struct matching the SoC
+ *                  in use will be returned.
+ *
+ * @family   - Name of SoC family that can include multiple related SoC
+ *            variants. Example: am33
+ * @machine  - Name of a specific SoC. Example: am3352
+ * @revision - Name of a specific SoC revision. Example: SR1.1
+ * @data     - A pointer to user data for the SoC variant
+ */
+struct soc_attr {
+       const char *family;
+       const char *machine;
+       const char *revision;
+       const void *data;
+};
+
+struct soc_ops {
+       /**
+        * get_machine() - Get machine name of an SOC
+        *
+        * @dev:        Device to check (UCLASS_SOC)
+        * @buf:        Buffer to place string
+        * @size:       Size of string space
+        * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+        */
+       int (*get_machine)(struct udevice *dev, char *buf, int size);
+
+       /**
+        * get_revision() - Get revision name of a SOC
+        *
+        * @dev:        Device to check (UCLASS_SOC)
+        * @buf:        Buffer to place string
+        * @size:       Size of string space
+        * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+        */
+       int (*get_revision)(struct udevice *dev, char *buf, int size);
+
+       /**
+        * get_family() - Get family name of an SOC
+        *
+        * @dev:        Device to check (UCLASS_SOC)
+        * @buf:        Buffer to place string
+        * @size:       Size of string space
+        * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+        */
+       int (*get_family)(struct udevice *dev, char *buf, int size);
+};
+
+#define soc_get_ops(dev)        ((struct soc_ops *)(dev)->driver->ops)
+
+#ifdef CONFIG_SOC_DEVICE
+/**
+ * soc_get() - Return the soc device for the soc in use.
+ * @devp: Pointer to structure to receive the soc device.
+ *
+ * Since there can only be at most one SOC instance, the API can supply a
+ * function that returns the unique device.
+ *
+ * Return: 0 if OK, -ve on error.
+ */
+int soc_get(struct udevice **devp);
+
+/**
+ * soc_get_machine() - Get machine name of an SOC
+ * @dev:       Device to check (UCLASS_SOC)
+ * @buf:       Buffer to place string
+ * @size:      Size of string space
+ *
+ * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int soc_get_machine(struct udevice *dev, char *buf, int size);
+
+/**
+ * soc_get_revision() - Get revision name of an SOC
+ * @dev:       Device to check (UCLASS_SOC)
+ * @buf:       Buffer to place string
+ * @size:      Size of string space
+ *
+ * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int soc_get_revision(struct udevice *dev, char *buf, int size);
+
+/**
+ * soc_get_family() - Get family name of an SOC
+ * @dev:       Device to check (UCLASS_SOC)
+ * @buf:       Buffer to place string
+ * @size:      Size of string space
+ *
+ * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int soc_get_family(struct udevice *dev, char *buf, int size);
+
+/**
+ * soc_device_match() - Return match from an array of soc_attr
+ * @matches:   Array with any combination of family, revision or machine set
+ *
+ * Return: Pointer to struct from matches array with set attributes matching
+ *        those provided by the soc device, or NULL if no match found.
+ */
+const struct soc_attr *
+soc_device_match(const struct soc_attr *matches);
+
+#else
+static inline int soc_get(struct udevice **devp)
+{
+       return -ENOSYS;
+}
+
+static inline int soc_get_machine(struct udevice *dev, char *buf, int size)
+{
+       return -ENOSYS;
+}
+
+static inline int soc_get_revision(struct udevice *dev, char *buf, int size)
+{
+       return -ENOSYS;
+}
+
+static inline int soc_get_family(struct udevice *dev, char *buf, int size)
+{
+       return -ENOSYS;
+}
+
+static inline const struct soc_attr *
+soc_device_match(const struct soc_attr *matches)
+{
+       return NULL;
+}
+#endif
+#endif /* _SOC_H */