[PATCH 1/8] dm: soc: Introduce UCLASS_SOC for SOC ID and attribute matching
Simon Glass
sjg at chromium.org
Fri Jul 3 05:50:17 CEST 2020
On Mon, 29 Jun 2020 at 22:38, Dave Gerlach <d-gerlach at ti.com> wrote:
>
> 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.
>
> Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
> ---
> drivers/soc/Kconfig | 9 +++
> drivers/soc/Makefile | 1 +
> drivers/soc/soc-uclass.c | 102 ++++++++++++++++++++++++++++++
> include/dm/uclass-id.h | 1 +
> include/soc.h | 132 +++++++++++++++++++++++++++++++++++++++
> 5 files changed, 245 insertions(+)
> create mode 100644 drivers/soc/soc-uclass.c
> create mode 100644 include/soc.h
Reviewed-by: Simon Glass <sjg at chromium.org>
As Tom says, docs please but looks great otherwise.
Nits below. Do you think it might make sense to have an
integer-encoded version? Maybe it would be more hassle than it is
worth.
>
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index 7b4e4d613088..e715dfd01712 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -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
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index ce253b7aa886..1c09a8465670 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -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
> index 000000000000..22f89514ed7d
> --- /dev/null
> +++ b/drivers/soc/soc-uclass.c
> @@ -0,0 +1,102 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
> + * Dave Gerlach <d-gerlach at 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_device_attribute *
> +soc_device_match(const struct soc_device_attribute *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",
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 7837d459f18c..690a8ed4df49 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -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
> index 000000000000..98e3cc000198
> --- /dev/null
> +++ b/include/soc.h
> @@ -0,0 +1,132 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
> + * Dave Gerlach <d-gerlach at ti.com>
> + */
> +
> +#ifndef __SOC_H
> +#define __SOC_H
> +
> +#define SOC_MAX_STR_SIZE 128
> +
> +struct soc_device_attribute {
Could this be soc_attr or maybe soc_dev_attr? This is too long.
> + const char *machine;
> + const char *family;
> + const char *revision;
> + const void *data;
Please can you comment this struct with what each thing means and an
example for your SoC.
> +};
> +
> +#ifdef CONFIG_SOC_DEVICE
Please drop the #ifdef as there is no harm in defining this.
> +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)
> +
> +/**
> + * 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_device_attribute
> + * @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 ?
> + */
> +const struct soc_device_attribute *
> +soc_device_match(const struct soc_device_attribute *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_device_attribute *
> +soc_device_match(const struct soc_device_attribute *matches)
> +{
> + return NULL;
> +}
> +#endif
> +#endif /* _SOC_H */
> --
> 2.20.1
>
Regards,
Simon
More information about the U-Boot
mailing list