blob: 22ee40c343338022a3c2921a779b32930748a653 [file] [log] [blame]
Nandor Han6521e5d2021-06-10 16:56:44 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c), Vaisala Oyj
4 */
5
Nandor Han6521e5d2021-06-10 16:56:44 +03006#include <asm/gpio.h>
7#include <dm.h>
8#include <dm/devres.h>
9#include <errno.h>
10#include <reboot-mode/reboot-mode-gpio.h>
11#include <reboot-mode/reboot-mode.h>
12
13DECLARE_GLOBAL_DATA_PTR;
14
15static int reboot_mode_get(struct udevice *dev, u32 *buf)
16{
17 int ret;
18 struct reboot_mode_gpio_platdata *plat_data;
19
20 if (!buf)
21 return -EINVAL;
22
23 plat_data = dev_get_plat(dev);
24 if (!plat_data)
25 return -EINVAL;
26
27 ret = dm_gpio_get_values_as_int(plat_data->gpio_desc,
28 plat_data->gpio_count);
29 if (ret < 0)
30 return ret;
31
32 *buf = ret;
33
34 return 0;
35}
36
37static int reboot_mode_probe(struct udevice *dev)
38{
39 struct reboot_mode_gpio_platdata *plat_data;
40
41 plat_data = dev_get_plat(dev);
42 if (!plat_data)
43 return -EINVAL;
44
45 int ret;
46
47#if CONFIG_IS_ENABLED(OF_CONTROL)
48 ret = gpio_get_list_count(dev, "gpios");
49 if (ret < 0)
50 return ret;
51
52 plat_data->gpio_count = ret;
53#endif
54
55 if (plat_data->gpio_count <= 0)
56 return -EINVAL;
57
58 plat_data->gpio_desc = devm_kcalloc(dev, plat_data->gpio_count,
59 sizeof(struct gpio_desc), 0);
60 if (!plat_data->gpio_desc)
61 return -ENOMEM;
62
63#if CONFIG_IS_ENABLED(OF_CONTROL)
64 ret = gpio_request_list_by_name(dev, "gpios", plat_data->gpio_desc,
65 plat_data->gpio_count, GPIOD_IS_IN);
66 if (ret < 0)
67 return ret;
68#else
69 for (int i = 0; i < plat_data->gpio_count; i++) {
70 struct reboot_mode_gpio_config *gpio =
71 plat_data->gpios_config + i;
72 struct gpio_desc *desc = plat_data->gpio_desc + i;
73
74 ret = uclass_get_device_by_seq(UCLASS_GPIO,
75 gpio->gpio_dev_offset,
76 &desc->dev);
77 if (ret < 0)
78 return ret;
79
80 desc->flags = gpio->flags;
81 desc->offset = gpio->gpio_offset;
82
83 ret = dm_gpio_request(desc, "");
84 if (ret < 0)
85 return ret;
86
87 ret = dm_gpio_set_dir(desc);
88 if (ret < 0)
89 return ret;
90 }
91#endif
92 return 0;
93}
94
95static int reboot_mode_remove(struct udevice *dev)
96{
97 struct reboot_mode_gpio_platdata *plat_data;
98
99 plat_data = dev_get_plat(dev);
100 if (!plat_data)
101 return -EINVAL;
102
103 return gpio_free_list(dev, plat_data->gpio_desc, plat_data->gpio_count);
104}
105
106#if CONFIG_IS_ENABLED(OF_CONTROL)
107static const struct udevice_id reboot_mode_ids[] = {
108 { .compatible = "reboot-mode-gpio", 0 },
109 { }
110};
111#endif
112
113static const struct reboot_mode_ops reboot_mode_gpio_ops = {
114 .get = reboot_mode_get,
115};
116
117U_BOOT_DRIVER(reboot_mode_gpio) = {
118 .name = "reboot-mode-gpio",
119 .id = UCLASS_REBOOT_MODE,
120 .probe = reboot_mode_probe,
121 .remove = reboot_mode_remove,
122#if CONFIG_IS_ENABLED(OF_CONTROL)
123 .of_match = reboot_mode_ids,
124#endif
125 .plat_auto = sizeof(struct reboot_mode_gpio_platdata),
126 .ops = &reboot_mode_gpio_ops,
127};