]> Git Repo - u-boot.git/blob - drivers/sysinfo/gpio.c
clk: a1: add new clocks for USB stack
[u-boot.git] / drivers / sysinfo / gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2021 Sean Anderson <[email protected]>
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <log.h>
9 #include <sysinfo.h>
10 #include <asm/gpio.h>
11 #include <dm/device_compat.h>
12
13 /**
14  * struct sysinfo_gpio_priv - GPIO sysinfo private data
15  * @gpios: List of GPIOs used to detect the revision
16  * @gpio_num: The number of GPIOs in @gpios
17  * @revision: The revision as detected from the GPIOs.
18  */
19 struct sysinfo_gpio_priv {
20         struct gpio_desc *gpios;
21         int gpio_num, revision;
22 };
23
24 static int sysinfo_gpio_detect(struct udevice *dev)
25 {
26         int ret;
27         struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
28
29         ret = dm_gpio_get_values_as_int_base3(priv->gpios, priv->gpio_num);
30         if (ret < 0)
31                 return ret;
32
33         priv->revision = ret;
34         return 0;
35 }
36
37 static int sysinfo_gpio_get_int(struct udevice *dev, int id, int *val)
38 {
39         struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
40
41         switch (id) {
42         case SYSINFO_ID_BOARD_MODEL:
43                 *val = priv->revision;
44                 return 0;
45         default:
46                 return -EINVAL;
47         };
48 }
49
50 static int sysinfo_gpio_get_str(struct udevice *dev, int id, size_t size, char *val)
51 {
52         struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
53
54         switch (id) {
55         case SYSINFO_ID_BOARD_MODEL: {
56                 const char *name = NULL;
57                 int i, ret;
58                 u32 revision;
59
60                 for (i = 0; ; i++) {
61                         ret = dev_read_u32_index(dev, "revisions", i,
62                                                  &revision);
63                         if (ret) {
64                                 if (ret != -EOVERFLOW)
65                                         return ret;
66                                 break;
67                         }
68
69                         if (revision == priv->revision) {
70                                 ret = dev_read_string_index(dev, "names", i,
71                                                             &name);
72                                 if (ret < 0)
73                                         return ret;
74                                 break;
75                         }
76                 }
77                 if (!name)
78                         name = "unknown";
79
80                 strncpy(val, name, size);
81                 val[size - 1] = '\0';
82                 return 0;
83         }
84         default:
85                 return -EINVAL;
86         };
87 }
88
89 static const struct sysinfo_ops sysinfo_gpio_ops = {
90         .detect = sysinfo_gpio_detect,
91         .get_int = sysinfo_gpio_get_int,
92         .get_str = sysinfo_gpio_get_str,
93 };
94
95 static int sysinfo_gpio_probe(struct udevice *dev)
96 {
97         int ret;
98         struct sysinfo_gpio_priv *priv = dev_get_priv(dev);
99
100         priv->gpio_num = gpio_get_list_count(dev, "gpios");
101         if (priv->gpio_num < 0) {
102                 dev_err(dev, "could not get gpios length (err = %d)\n",
103                         priv->gpio_num);
104                 return priv->gpio_num;
105         }
106
107         priv->gpios = calloc(priv->gpio_num, sizeof(*priv->gpios));
108         if (!priv->gpios) {
109                 dev_err(dev, "could not allocate memory for %d gpios\n",
110                         priv->gpio_num);
111                 return -ENOMEM;
112         }
113
114         ret = gpio_request_list_by_name(dev, "gpios", priv->gpios,
115                                         priv->gpio_num, GPIOD_IS_IN);
116         if (ret != priv->gpio_num) {
117                 dev_err(dev, "could not get gpios (err = %d)\n",
118                         priv->gpio_num);
119                 return ret;
120         }
121
122         if (!dev_read_bool(dev, "revisions") || !dev_read_bool(dev, "names")) {
123                 dev_err(dev, "revisions or names properties missing\n");
124                 return -ENOENT;
125         }
126
127         return 0;
128 }
129
130 static const struct udevice_id sysinfo_gpio_ids[] = {
131         { .compatible = "gpio-sysinfo" },
132         { /* sentinel */ }
133 };
134
135 U_BOOT_DRIVER(sysinfo_gpio) = {
136         .name           = "sysinfo_gpio",
137         .id             = UCLASS_SYSINFO,
138         .of_match       = sysinfo_gpio_ids,
139         .ops            = &sysinfo_gpio_ops,
140         .priv_auto      = sizeof(struct sysinfo_gpio_priv),
141         .probe          = sysinfo_gpio_probe,
142 };
This page took 0.035398 seconds and 4 git commands to generate.