]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/sandbox.c
sandbox: Convert GPIOs to use driver model
[karo-tx-uboot.git] / drivers / gpio / sandbox.c
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors.
3  * SPDX-License-Identifier:     GPL-2.0+
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <fdtdec.h>
9 #include <malloc.h>
10 #include <asm/gpio.h>
11
12 DECLARE_GLOBAL_DATA_PTR;
13
14 /* Flags for each GPIO */
15 #define GPIOF_OUTPUT    (1 << 0)        /* Currently set as an output */
16 #define GPIOF_HIGH      (1 << 1)        /* Currently set high */
17 #define GPIOF_RESERVED  (1 << 2)        /* Is in use / requested */
18
19 struct gpio_state {
20         const char *label;      /* label given by requester */
21         u8 flags;               /* flags (GPIOF_...) */
22 };
23
24 /* Access routines for GPIO state */
25 static u8 *get_gpio_flags(struct device *dev, unsigned offset)
26 {
27         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
28         struct gpio_state *state = dev_get_priv(dev);
29
30         if (offset >= uc_priv->gpio_count) {
31                 static u8 invalid_flags;
32                 printf("sandbox_gpio: error: invalid gpio %u\n", offset);
33                 return &invalid_flags;
34         }
35
36         return &state[offset].flags;
37 }
38
39 static int get_gpio_flag(struct device *dev, unsigned offset, int flag)
40 {
41         return (*get_gpio_flags(dev, offset) & flag) != 0;
42 }
43
44 static int set_gpio_flag(struct device *dev, unsigned offset, int flag,
45                          int value)
46 {
47         u8 *gpio = get_gpio_flags(dev, offset);
48
49         if (value)
50                 *gpio |= flag;
51         else
52                 *gpio &= ~flag;
53
54         return 0;
55 }
56
57 static int check_reserved(struct device *dev, unsigned offset,
58                           const char *func)
59 {
60         if (!get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
61                 printf("sandbox_gpio: %s: error: offset %u not reserved\n",
62                        func, offset);
63                 return -1;
64         }
65
66         return 0;
67 }
68
69 /*
70  * Back-channel sandbox-internal-only access to GPIO state
71  */
72
73 int sandbox_gpio_get_value(struct device *dev, unsigned offset)
74 {
75         if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
76                 debug("sandbox_gpio: get_value on output gpio %u\n", offset);
77         return get_gpio_flag(dev, offset, GPIOF_HIGH);
78 }
79
80 int sandbox_gpio_set_value(struct device *dev, unsigned offset, int value)
81 {
82         return set_gpio_flag(dev, offset, GPIOF_HIGH, value);
83 }
84
85 int sandbox_gpio_get_direction(struct device *dev, unsigned offset)
86 {
87         return get_gpio_flag(dev, offset, GPIOF_OUTPUT);
88 }
89
90 int sandbox_gpio_set_direction(struct device *dev, unsigned offset, int output)
91 {
92         return set_gpio_flag(dev, offset, GPIOF_OUTPUT, output);
93 }
94
95 /*
96  * These functions implement the public interface within U-Boot
97  */
98
99 /* set GPIO port 'offset' as an input */
100 static int sb_gpio_direction_input(struct device *dev, unsigned offset)
101 {
102         debug("%s: offset:%u\n", __func__, offset);
103
104         if (check_reserved(dev, offset, __func__))
105                 return -1;
106
107         return sandbox_gpio_set_direction(dev, offset, 0);
108 }
109
110 /* set GPIO port 'offset' as an output, with polarity 'value' */
111 static int sb_gpio_direction_output(struct device *dev, unsigned offset,
112                                     int value)
113 {
114         debug("%s: offset:%u, value = %d\n", __func__, offset, value);
115
116         if (check_reserved(dev, offset, __func__))
117                 return -1;
118
119         return sandbox_gpio_set_direction(dev, offset, 1) |
120                 sandbox_gpio_set_value(dev, offset, value);
121 }
122
123 /* read GPIO IN value of port 'offset' */
124 static int sb_gpio_get_value(struct device *dev, unsigned offset)
125 {
126         debug("%s: offset:%u\n", __func__, offset);
127
128         if (check_reserved(dev, offset, __func__))
129                 return -1;
130
131         return sandbox_gpio_get_value(dev, offset);
132 }
133
134 /* write GPIO OUT value to port 'offset' */
135 static int sb_gpio_set_value(struct device *dev, unsigned offset, int value)
136 {
137         debug("%s: offset:%u, value = %d\n", __func__, offset, value);
138
139         if (check_reserved(dev, offset, __func__))
140                 return -1;
141
142         if (!sandbox_gpio_get_direction(dev, offset)) {
143                 printf("sandbox_gpio: error: set_value on input gpio %u\n",
144                        offset);
145                 return -1;
146         }
147
148         return sandbox_gpio_set_value(dev, offset, value);
149 }
150
151 static int sb_gpio_request(struct device *dev, unsigned offset,
152                            const char *label)
153 {
154         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
155         struct gpio_state *state = dev_get_priv(dev);
156
157         debug("%s: offset:%u, label:%s\n", __func__, offset, label);
158
159         if (offset >= uc_priv->gpio_count) {
160                 printf("sandbox_gpio: error: invalid gpio %u\n", offset);
161                 return -1;
162         }
163
164         if (get_gpio_flag(dev, offset, GPIOF_RESERVED)) {
165                 printf("sandbox_gpio: error: gpio %u already reserved\n",
166                        offset);
167                 return -1;
168         }
169
170         state[offset].label = label;
171         return set_gpio_flag(dev, offset, GPIOF_RESERVED, 1);
172 }
173
174 static int sb_gpio_free(struct device *dev, unsigned offset)
175 {
176         struct gpio_state *state = dev_get_priv(dev);
177
178         debug("%s: offset:%u\n", __func__, offset);
179
180         if (check_reserved(dev, offset, __func__))
181                 return -1;
182
183         state[offset].label = NULL;
184         return set_gpio_flag(dev, offset, GPIOF_RESERVED, 0);
185 }
186
187 static int sb_gpio_get_state(struct device *dev, unsigned int offset,
188                              char *buf, int bufsize)
189 {
190         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
191         struct gpio_state *state = dev_get_priv(dev);
192         const char *label;
193
194         label = state[offset].label;
195         snprintf(buf, bufsize, "%s%d: %s: %d [%c]%s%s",
196                  uc_priv->bank_name ? uc_priv->bank_name : "", offset,
197                  sandbox_gpio_get_direction(dev, offset) ? "out" : " in",
198                  sandbox_gpio_get_value(dev, offset),
199                  get_gpio_flag(dev, offset, GPIOF_RESERVED) ? 'x' : ' ',
200                  label ? " " : "",
201                  label ? label : "");
202
203         return 0;
204 }
205
206 static const struct dm_gpio_ops gpio_sandbox_ops = {
207         .request                = sb_gpio_request,
208         .free                   = sb_gpio_free,
209         .direction_input        = sb_gpio_direction_input,
210         .direction_output       = sb_gpio_direction_output,
211         .get_value              = sb_gpio_get_value,
212         .set_value              = sb_gpio_set_value,
213         .get_state              = sb_gpio_get_state,
214 };
215
216 static int sandbox_gpio_ofdata_to_platdata(struct device *dev)
217 {
218         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
219
220         uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
221                                              "num-gpios", 0);
222         uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
223                                          "gpio-bank-name", NULL);
224
225         return 0;
226 }
227
228 static int gpio_sandbox_probe(struct device *dev)
229 {
230         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
231
232         if (dev->of_offset == -1) {
233                 /* Tell the uclass how many GPIOs we have */
234                 uc_priv->gpio_count = CONFIG_SANDBOX_GPIO_COUNT;
235         }
236
237         dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count);
238
239         return 0;
240 }
241
242 static const struct device_id sandbox_gpio_ids[] = {
243         { .compatible = "sandbox,gpio" },
244         { }
245 };
246
247 U_BOOT_DRIVER(gpio_sandbox) = {
248         .name   = "gpio_sandbox",
249         .id     = UCLASS_GPIO,
250         .of_match = sandbox_gpio_ids,
251         .ofdata_to_platdata = sandbox_gpio_ofdata_to_platdata,
252         .probe  = gpio_sandbox_probe,
253         .ops    = &gpio_sandbox_ops,
254 };