]> Git Repo - J-u-boot.git/blob - drivers/button/button-gpio.c
Merge tag 'u-boot-atmel-2021.04-a' of https://gitlab.denx.de/u-boot/custodians/u...
[J-u-boot.git] / drivers / button / button-gpio.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 Philippe Reynes <[email protected]>
4  */
5
6 #include <common.h>
7 #include <button.h>
8 #include <dm.h>
9 #include <dm/lists.h>
10 #include <dm/uclass-internal.h>
11 #include <log.h>
12 #include <asm/gpio.h>
13
14 struct button_gpio_priv {
15         struct gpio_desc gpio;
16 };
17
18 static enum button_state_t button_gpio_get_state(struct udevice *dev)
19 {
20         struct button_gpio_priv *priv = dev_get_priv(dev);
21         int ret;
22
23         if (!dm_gpio_is_valid(&priv->gpio))
24                 return -EREMOTEIO;
25         ret = dm_gpio_get_value(&priv->gpio);
26         if (ret < 0)
27                 return ret;
28
29         return ret ? BUTTON_ON : BUTTON_OFF;
30 }
31
32 static int button_gpio_probe(struct udevice *dev)
33 {
34         struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev);
35         struct button_gpio_priv *priv = dev_get_priv(dev);
36         int ret;
37
38         /* Ignore the top-level button node */
39         if (!uc_plat->label)
40                 return 0;
41
42         ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_IN);
43         if (ret)
44                 return ret;
45
46         return 0;
47 }
48
49 static int button_gpio_remove(struct udevice *dev)
50 {
51         /*
52          * The GPIO driver may have already been removed. We will need to
53          * address this more generally.
54          */
55         if (!IS_ENABLED(CONFIG_SANDBOX)) {
56                 struct button_gpio_priv *priv = dev_get_priv(dev);
57
58                 if (dm_gpio_is_valid(&priv->gpio))
59                         dm_gpio_free(dev, &priv->gpio);
60         }
61
62         return 0;
63 }
64
65 static int button_gpio_bind(struct udevice *parent)
66 {
67         struct udevice *dev;
68         ofnode node;
69         int ret;
70
71         dev_for_each_subnode(node, parent) {
72                 struct button_uc_plat *uc_plat;
73                 const char *label;
74
75                 label = ofnode_read_string(node, "label");
76                 if (!label) {
77                         debug("%s: node %s has no label\n", __func__,
78                               ofnode_get_name(node));
79                         return -EINVAL;
80                 }
81                 ret = device_bind_driver_to_node(parent, "button_gpio",
82                                                  ofnode_get_name(node),
83                                                  node, &dev);
84                 if (ret)
85                         return ret;
86                 uc_plat = dev_get_uclass_plat(dev);
87                 uc_plat->label = label;
88         }
89
90         return 0;
91 }
92
93 static const struct button_ops button_gpio_ops = {
94         .get_state      = button_gpio_get_state,
95 };
96
97 static const struct udevice_id button_gpio_ids[] = {
98         { .compatible = "gpio-keys" },
99         { .compatible = "gpio-keys-polled" },
100         { }
101 };
102
103 U_BOOT_DRIVER(button_gpio) = {
104         .name           = "button_gpio",
105         .id             = UCLASS_BUTTON,
106         .of_match       = button_gpio_ids,
107         .ops            = &button_gpio_ops,
108         .priv_auto      = sizeof(struct button_gpio_priv),
109         .bind           = button_gpio_bind,
110         .probe          = button_gpio_probe,
111         .remove         = button_gpio_remove,
112 };
This page took 0.033204 seconds and 4 git commands to generate.