123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Copyright (C) 2021 Sean Anderson <sean.anderson@seco.com>
- */
- #include <common.h>
- #include <dm.h>
- #include <log.h>
- #include <sysinfo.h>
- #include <asm/gpio.h>
- #include <dm/device_compat.h>
- /**
- * struct sysinfo_gpio_priv - GPIO sysinfo private data
- * @gpios: List of GPIOs used to detect the revision
- * @gpio_num: The number of GPIOs in @gpios
- * @revision: The revision as detected from the GPIOs.
- */
- struct sysinfo_gpio_priv {
- struct gpio_desc *gpios;
- int gpio_num, revision;
- };
- static int sysinfo_gpio_detect(struct udevice *dev)
- {
- int ret;
- struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
- ret = dm_gpio_get_values_as_int_base3(priv->gpios, priv->gpio_num);
- if (ret < 0)
- return ret;
- priv->revision = ret;
- return 0;
- }
- static int sysinfo_gpio_get_int(struct udevice *dev, int id, int *val)
- {
- struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
- switch (id) {
- case SYSINFO_ID_BOARD_MODEL:
- *val = priv->revision;
- return 0;
- default:
- return -EINVAL;
- };
- }
- static int sysinfo_gpio_get_str(struct udevice *dev, int id, size_t size, char *val)
- {
- struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
- switch (id) {
- case SYSINFO_ID_BOARD_MODEL: {
- const char *name = NULL;
- int i, ret;
- u32 revision;
- for (i = 0; i < priv->gpio_num; i++) {
- ret = dev_read_u32_index(dev, "revisions", i,
- &revision);
- if (ret) {
- if (ret != -EOVERFLOW)
- return ret;
- break;
- }
- if (revision == priv->revision) {
- ret = dev_read_string_index(dev, "names", i,
- &name);
- if (ret < 0)
- return ret;
- break;
- }
- }
- if (!name)
- name = "unknown";
- strncpy(val, name, size);
- val[size - 1] = '\0';
- return 0;
- } default:
- return -EINVAL;
- };
- }
- static const struct sysinfo_ops sysinfo_gpio_ops = {
- .detect = sysinfo_gpio_detect,
- .get_int = sysinfo_gpio_get_int,
- .get_str = sysinfo_gpio_get_str,
- };
- static int sysinfo_gpio_probe(struct udevice *dev)
- {
- int ret;
- struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
- priv->gpio_num = gpio_get_list_count(dev, "gpios");
- if (priv->gpio_num < 0) {
- dev_err(dev, "could not get gpios length (err = %d)\n",
- priv->gpio_num);
- return priv->gpio_num;
- }
- priv->gpios = calloc(priv->gpio_num, sizeof(*priv->gpios));
- if (!priv->gpios) {
- dev_err(dev, "could not allocate memory for %d gpios\n",
- priv->gpio_num);
- return -ENOMEM;
- }
- ret = gpio_request_list_by_name(dev, "gpios", priv->gpios,
- priv->gpio_num, GPIOD_IS_IN);
- if (ret != priv->gpio_num) {
- dev_err(dev, "could not get gpios (err = %d)\n",
- priv->gpio_num);
- return ret;
- }
- if (!dev_read_bool(dev, "revisions") || !dev_read_bool(dev, "names")) {
- dev_err(dev, "revisions or names properties missing\n");
- return -ENOENT;
- }
- return 0;
- }
- static const struct udevice_id sysinfo_gpio_ids[] = {
- { .compatible = "gpio-sysinfo" },
- { /* sentinel */ }
- };
- U_BOOT_DRIVER(sysinfo_gpio) = {
- .name = "sysinfo_gpio",
- .id = UCLASS_SYSINFO,
- .of_match = sysinfo_gpio_ids,
- .ops = &sysinfo_gpio_ops,
- .priv_auto = sizeof(struct sysinfo_gpio_priv),
- .probe = sysinfo_gpio_probe,
- };
|