Commit e2d8a714a7e6047124581b93d1cfe9c7702cedd4
Committed by
Tom Rini
1 parent
96495d90fe
Exists in
v2017.01-smarct4x
and in
48 other branches
sandbox: Convert GPIOs to use driver model
Convert sandbox over to use driver model GPIOs. Signed-off-by: Simon Glass <sjg@chromium.org>
Showing 4 changed files with 151 additions and 88 deletions Side-by-side Diff
arch/sandbox/include/asm/gpio.h
... | ... | @@ -29,7 +29,7 @@ |
29 | 29 | * @param gp GPIO number |
30 | 30 | * @return -1 on error, 0 if GPIO is low, >0 if high |
31 | 31 | */ |
32 | -int sandbox_gpio_get_value(unsigned gp); | |
32 | +int sandbox_gpio_get_value(struct device *dev, unsigned int offset); | |
33 | 33 | |
34 | 34 | /** |
35 | 35 | * Set the simulated value of a GPIO (used only in sandbox test code) |
... | ... | @@ -38,7 +38,7 @@ |
38 | 38 | * @param value value to set (0 for low, non-zero for high) |
39 | 39 | * @return -1 on error, 0 if ok |
40 | 40 | */ |
41 | -int sandbox_gpio_set_value(unsigned gp, int value); | |
41 | +int sandbox_gpio_set_value(struct device *dev, unsigned int offset, int value); | |
42 | 42 | |
43 | 43 | /** |
44 | 44 | * Return the simulated direction of a GPIO (used only in sandbox test code) |
... | ... | @@ -46,7 +46,7 @@ |
46 | 46 | * @param gp GPIO number |
47 | 47 | * @return -1 on error, 0 if GPIO is input, >0 if output |
48 | 48 | */ |
49 | -int sandbox_gpio_get_direction(unsigned gp); | |
49 | +int sandbox_gpio_get_direction(struct device *dev, unsigned int offset); | |
50 | 50 | |
51 | 51 | /** |
52 | 52 | * Set the simulated direction of a GPIO (used only in sandbox test code) |
... | ... | @@ -55,12 +55,8 @@ |
55 | 55 | * @param output 0 to set as input, 1 to set as output |
56 | 56 | * @return -1 on error, 0 if ok |
57 | 57 | */ |
58 | -int sandbox_gpio_set_direction(unsigned gp, int output); | |
59 | - | |
60 | -/* Display information about each GPIO */ | |
61 | -void gpio_info(void); | |
62 | - | |
63 | -#define gpio_status() gpio_info() | |
58 | +int sandbox_gpio_set_direction(struct device *dev, unsigned int offset, | |
59 | + int output); | |
64 | 60 | |
65 | 61 | #endif |
board/sandbox/sandbox/sandbox.c
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | */ |
5 | 5 | |
6 | 6 | #include <common.h> |
7 | - | |
7 | +#include <dm.h> | |
8 | 8 | #include <os.h> |
9 | 9 | |
10 | 10 | /* |
... | ... | @@ -13,6 +13,11 @@ |
13 | 13 | * Here we initialize it. |
14 | 14 | */ |
15 | 15 | gd_t *gd; |
16 | + | |
17 | +/* Add a simple GPIO device */ | |
18 | +U_BOOT_DEVICE(gpio_sandbox) = { | |
19 | + .name = "gpio_sandbox", | |
20 | +}; | |
16 | 21 | |
17 | 22 | void flush_cache(unsigned long start, unsigned long size) |
18 | 23 | { |
drivers/gpio/sandbox.c
... | ... | @@ -4,8 +4,13 @@ |
4 | 4 | */ |
5 | 5 | |
6 | 6 | #include <common.h> |
7 | +#include <dm.h> | |
8 | +#include <fdtdec.h> | |
9 | +#include <malloc.h> | |
7 | 10 | #include <asm/gpio.h> |
8 | 11 | |
12 | +DECLARE_GLOBAL_DATA_PTR; | |
13 | + | |
9 | 14 | /* Flags for each GPIO */ |
10 | 15 | #define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */ |
11 | 16 | #define GPIOF_HIGH (1 << 1) /* Currently set high */ |
12 | 17 | |
13 | 18 | |
14 | 19 | |
15 | 20 | |
16 | 21 | |
17 | 22 | |
18 | 23 | |
19 | 24 | |
... | ... | @@ -16,34 +21,30 @@ |
16 | 21 | u8 flags; /* flags (GPIOF_...) */ |
17 | 22 | }; |
18 | 23 | |
19 | -/* | |
20 | - * State of GPIOs | |
21 | - * TODO: Put this into sandbox state | |
22 | - */ | |
23 | -static struct gpio_state state[CONFIG_SANDBOX_GPIO_COUNT]; | |
24 | - | |
25 | 24 | /* Access routines for GPIO state */ |
26 | -static u8 *get_gpio_flags(unsigned gp) | |
25 | +static u8 *get_gpio_flags(struct device *dev, unsigned offset) | |
27 | 26 | { |
28 | - /* assert()'s could be disabled, so make sure we handle that */ | |
29 | - assert(gp < ARRAY_SIZE(state)); | |
30 | - if (gp >= ARRAY_SIZE(state)) { | |
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 | 31 | static u8 invalid_flags; |
32 | - printf("sandbox_gpio: error: invalid gpio %u\n", gp); | |
32 | + printf("sandbox_gpio: error: invalid gpio %u\n", offset); | |
33 | 33 | return &invalid_flags; |
34 | 34 | } |
35 | 35 | |
36 | - return &state[gp].flags; | |
36 | + return &state[offset].flags; | |
37 | 37 | } |
38 | 38 | |
39 | -static int get_gpio_flag(unsigned gp, int flag) | |
39 | +static int get_gpio_flag(struct device *dev, unsigned offset, int flag) | |
40 | 40 | { |
41 | - return (*get_gpio_flags(gp) & flag) != 0; | |
41 | + return (*get_gpio_flags(dev, offset) & flag) != 0; | |
42 | 42 | } |
43 | 43 | |
44 | -static int set_gpio_flag(unsigned gp, int flag, int value) | |
44 | +static int set_gpio_flag(struct device *dev, unsigned offset, int flag, | |
45 | + int value) | |
45 | 46 | { |
46 | - u8 *gpio = get_gpio_flags(gp); | |
47 | + u8 *gpio = get_gpio_flags(dev, offset); | |
47 | 48 | |
48 | 49 | if (value) |
49 | 50 | *gpio |= flag; |
50 | 51 | |
... | ... | @@ -53,11 +54,12 @@ |
53 | 54 | return 0; |
54 | 55 | } |
55 | 56 | |
56 | -static int check_reserved(unsigned gpio, const char *func) | |
57 | +static int check_reserved(struct device *dev, unsigned offset, | |
58 | + const char *func) | |
57 | 59 | { |
58 | - if (!get_gpio_flag(gpio, GPIOF_RESERVED)) { | |
59 | - printf("sandbox_gpio: %s: error: gpio %u not reserved\n", | |
60 | - func, gpio); | |
60 | + if (!get_gpio_flag(dev, offset, GPIOF_RESERVED)) { | |
61 | + printf("sandbox_gpio: %s: error: offset %u not reserved\n", | |
62 | + func, offset); | |
61 | 63 | return -1; |
62 | 64 | } |
63 | 65 | |
64 | 66 | |
65 | 67 | |
66 | 68 | |
67 | 69 | |
68 | 70 | |
69 | 71 | |
70 | 72 | |
71 | 73 | |
72 | 74 | |
73 | 75 | |
74 | 76 | |
75 | 77 | |
76 | 78 | |
77 | 79 | |
78 | 80 | |
79 | 81 | |
80 | 82 | |
81 | 83 | |
82 | 84 | |
83 | 85 | |
84 | 86 | |
85 | 87 | |
86 | 88 | |
87 | 89 | |
88 | 90 | |
89 | 91 | |
90 | 92 | |
91 | 93 | |
92 | 94 | |
93 | 95 | |
94 | 96 | |
95 | 97 | |
96 | 98 | |
97 | 99 | |
98 | 100 | |
99 | 101 | |
100 | 102 | |
101 | 103 | |
102 | 104 | |
103 | 105 | |
... | ... | @@ -68,127 +70,186 @@ |
68 | 70 | * Back-channel sandbox-internal-only access to GPIO state |
69 | 71 | */ |
70 | 72 | |
71 | -int sandbox_gpio_get_value(unsigned gp) | |
73 | +int sandbox_gpio_get_value(struct device *dev, unsigned offset) | |
72 | 74 | { |
73 | - if (get_gpio_flag(gp, GPIOF_OUTPUT)) | |
74 | - debug("sandbox_gpio: get_value on output gpio %u\n", gp); | |
75 | - return get_gpio_flag(gp, GPIOF_HIGH); | |
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); | |
76 | 78 | } |
77 | 79 | |
78 | -int sandbox_gpio_set_value(unsigned gp, int value) | |
80 | +int sandbox_gpio_set_value(struct device *dev, unsigned offset, int value) | |
79 | 81 | { |
80 | - return set_gpio_flag(gp, GPIOF_HIGH, value); | |
82 | + return set_gpio_flag(dev, offset, GPIOF_HIGH, value); | |
81 | 83 | } |
82 | 84 | |
83 | -int sandbox_gpio_get_direction(unsigned gp) | |
85 | +int sandbox_gpio_get_direction(struct device *dev, unsigned offset) | |
84 | 86 | { |
85 | - return get_gpio_flag(gp, GPIOF_OUTPUT); | |
87 | + return get_gpio_flag(dev, offset, GPIOF_OUTPUT); | |
86 | 88 | } |
87 | 89 | |
88 | -int sandbox_gpio_set_direction(unsigned gp, int output) | |
90 | +int sandbox_gpio_set_direction(struct device *dev, unsigned offset, int output) | |
89 | 91 | { |
90 | - return set_gpio_flag(gp, GPIOF_OUTPUT, output); | |
92 | + return set_gpio_flag(dev, offset, GPIOF_OUTPUT, output); | |
91 | 93 | } |
92 | 94 | |
93 | 95 | /* |
94 | 96 | * These functions implement the public interface within U-Boot |
95 | 97 | */ |
96 | 98 | |
97 | -/* set GPIO port 'gp' as an input */ | |
98 | -int gpio_direction_input(unsigned gp) | |
99 | +/* set GPIO port 'offset' as an input */ | |
100 | +static int sb_gpio_direction_input(struct device *dev, unsigned offset) | |
99 | 101 | { |
100 | - debug("%s: gp:%u\n", __func__, gp); | |
102 | + debug("%s: offset:%u\n", __func__, offset); | |
101 | 103 | |
102 | - if (check_reserved(gp, __func__)) | |
104 | + if (check_reserved(dev, offset, __func__)) | |
103 | 105 | return -1; |
104 | 106 | |
105 | - return sandbox_gpio_set_direction(gp, 0); | |
107 | + return sandbox_gpio_set_direction(dev, offset, 0); | |
106 | 108 | } |
107 | 109 | |
108 | -/* set GPIO port 'gp' as an output, with polarity 'value' */ | |
109 | -int gpio_direction_output(unsigned gp, int value) | |
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) | |
110 | 113 | { |
111 | - debug("%s: gp:%u, value = %d\n", __func__, gp, value); | |
114 | + debug("%s: offset:%u, value = %d\n", __func__, offset, value); | |
112 | 115 | |
113 | - if (check_reserved(gp, __func__)) | |
116 | + if (check_reserved(dev, offset, __func__)) | |
114 | 117 | return -1; |
115 | 118 | |
116 | - return sandbox_gpio_set_direction(gp, 1) | | |
117 | - sandbox_gpio_set_value(gp, value); | |
119 | + return sandbox_gpio_set_direction(dev, offset, 1) | | |
120 | + sandbox_gpio_set_value(dev, offset, value); | |
118 | 121 | } |
119 | 122 | |
120 | -/* read GPIO IN value of port 'gp' */ | |
121 | -int gpio_get_value(unsigned gp) | |
123 | +/* read GPIO IN value of port 'offset' */ | |
124 | +static int sb_gpio_get_value(struct device *dev, unsigned offset) | |
122 | 125 | { |
123 | - debug("%s: gp:%u\n", __func__, gp); | |
126 | + debug("%s: offset:%u\n", __func__, offset); | |
124 | 127 | |
125 | - if (check_reserved(gp, __func__)) | |
128 | + if (check_reserved(dev, offset, __func__)) | |
126 | 129 | return -1; |
127 | 130 | |
128 | - return sandbox_gpio_get_value(gp); | |
131 | + return sandbox_gpio_get_value(dev, offset); | |
129 | 132 | } |
130 | 133 | |
131 | -/* write GPIO OUT value to port 'gp' */ | |
132 | -int gpio_set_value(unsigned gp, int value) | |
134 | +/* write GPIO OUT value to port 'offset' */ | |
135 | +static int sb_gpio_set_value(struct device *dev, unsigned offset, int value) | |
133 | 136 | { |
134 | - debug("%s: gp:%u, value = %d\n", __func__, gp, value); | |
137 | + debug("%s: offset:%u, value = %d\n", __func__, offset, value); | |
135 | 138 | |
136 | - if (check_reserved(gp, __func__)) | |
139 | + if (check_reserved(dev, offset, __func__)) | |
137 | 140 | return -1; |
138 | 141 | |
139 | - if (!sandbox_gpio_get_direction(gp)) { | |
140 | - printf("sandbox_gpio: error: set_value on input gpio %u\n", gp); | |
142 | + if (!sandbox_gpio_get_direction(dev, offset)) { | |
143 | + printf("sandbox_gpio: error: set_value on input gpio %u\n", | |
144 | + offset); | |
141 | 145 | return -1; |
142 | 146 | } |
143 | 147 | |
144 | - return sandbox_gpio_set_value(gp, value); | |
148 | + return sandbox_gpio_set_value(dev, offset, value); | |
145 | 149 | } |
146 | 150 | |
147 | -int gpio_request(unsigned gp, const char *label) | |
151 | +static int sb_gpio_request(struct device *dev, unsigned offset, | |
152 | + const char *label) | |
148 | 153 | { |
149 | - debug("%s: gp:%u, label:%s\n", __func__, gp, label); | |
154 | + struct gpio_dev_priv *uc_priv = dev->uclass_priv; | |
155 | + struct gpio_state *state = dev_get_priv(dev); | |
150 | 156 | |
151 | - if (gp >= ARRAY_SIZE(state)) { | |
152 | - printf("sandbox_gpio: error: invalid gpio %u\n", gp); | |
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); | |
153 | 161 | return -1; |
154 | 162 | } |
155 | 163 | |
156 | - if (get_gpio_flag(gp, GPIOF_RESERVED)) { | |
157 | - printf("sandbox_gpio: error: gpio %u already reserved\n", gp); | |
164 | + if (get_gpio_flag(dev, offset, GPIOF_RESERVED)) { | |
165 | + printf("sandbox_gpio: error: gpio %u already reserved\n", | |
166 | + offset); | |
158 | 167 | return -1; |
159 | 168 | } |
160 | 169 | |
161 | - state[gp].label = label; | |
162 | - return set_gpio_flag(gp, GPIOF_RESERVED, 1); | |
170 | + state[offset].label = label; | |
171 | + return set_gpio_flag(dev, offset, GPIOF_RESERVED, 1); | |
163 | 172 | } |
164 | 173 | |
165 | -int gpio_free(unsigned gp) | |
174 | +static int sb_gpio_free(struct device *dev, unsigned offset) | |
166 | 175 | { |
167 | - debug("%s: gp:%u\n", __func__, gp); | |
176 | + struct gpio_state *state = dev_get_priv(dev); | |
168 | 177 | |
169 | - if (check_reserved(gp, __func__)) | |
178 | + debug("%s: offset:%u\n", __func__, offset); | |
179 | + | |
180 | + if (check_reserved(dev, offset, __func__)) | |
170 | 181 | return -1; |
171 | 182 | |
172 | - state[gp].label = NULL; | |
173 | - return set_gpio_flag(gp, GPIOF_RESERVED, 0); | |
183 | + state[offset].label = NULL; | |
184 | + return set_gpio_flag(dev, offset, GPIOF_RESERVED, 0); | |
174 | 185 | } |
175 | 186 | |
176 | -/* Display GPIO information */ | |
177 | -void gpio_info(void) | |
187 | +static int sb_gpio_get_state(struct device *dev, unsigned int offset, | |
188 | + char *buf, int bufsize) | |
178 | 189 | { |
179 | - unsigned gpio; | |
190 | + struct gpio_dev_priv *uc_priv = dev->uclass_priv; | |
191 | + struct gpio_state *state = dev_get_priv(dev); | |
192 | + const char *label; | |
180 | 193 | |
181 | - puts("Sandbox GPIOs\n"); | |
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 : ""); | |
182 | 202 | |
183 | - for (gpio = 0; gpio < ARRAY_SIZE(state); ++gpio) { | |
184 | - const char *label = state[gpio].label; | |
203 | + return 0; | |
204 | +} | |
185 | 205 | |
186 | - printf("%4d: %s: %d [%c] %s\n", | |
187 | - gpio, | |
188 | - sandbox_gpio_get_direction(gpio) ? "out" : " in", | |
189 | - sandbox_gpio_get_value(gpio), | |
190 | - get_gpio_flag(gpio, GPIOF_RESERVED) ? 'x' : ' ', | |
191 | - label ? label : ""); | |
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; | |
192 | 235 | } |
236 | + | |
237 | + dev->priv = calloc(sizeof(struct gpio_state), uc_priv->gpio_count); | |
238 | + | |
239 | + return 0; | |
193 | 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 | +}; |
include/configs/sandbox.h