1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
|
From 697eb56ed8c9b3814ddbd87ae0c6e749ccafc9e3 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 28 Aug 2021 00:27:19 -0500
Subject: [PATCH 50/90] gpio: axp: Select variant from compatible at runtime
There are three major variants of the AXP PMIC GPIO functionality (plus
PMICs with no GPIOs at all). Except for GPIO3 on the AXP209, which uses
a different register layout, it is straightforward to support all three
variants with a single driver. Do this, and in the process remove the
GPIO-related definitions from the PMIC-specific headers, and therefore
the dependency on AXP_PMIC_BUS.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/gpio/Kconfig | 1 -
drivers/gpio/axp_gpio.c | 137 +++++++++++++++++++++-------------------
drivers/power/axp209.c | 6 +-
drivers/power/axp221.c | 4 +-
include/axp152.h | 10 ---
include/axp209.h | 16 ++---
include/axp221.h | 13 ++--
include/axp809.h | 8 ---
include/axp818.h | 8 ---
9 files changed, 89 insertions(+), 114 deletions(-)
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -107,7 +107,6 @@ config ALTERA_PIO
config AXP_GPIO
bool "X-Powers AXP PMICs GPIO driver"
depends on DM_GPIO && PMIC_AXP
- depends on AXP_PMIC_BUS
help
This driver supports the GPIO pins on
X-Powers AXP152, AXP2xx, and AXP8xx PMICs.
--- a/drivers/gpio/axp_gpio.c
+++ b/drivers/gpio/axp_gpio.c
@@ -7,110 +7,117 @@
#include <common.h>
#include <asm/gpio.h>
-#include <axp_pmic.h>
#include <dm.h>
+#include <dm/device-internal.h>
#include <errno.h>
#include <power/pmic.h>
#define AXP_GPIO_PREFIX "AXP0-"
#define AXP_GPIO_COUNT 4
-static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val);
-
-static u8 axp_get_gpio_ctrl_reg(unsigned pin)
-{
- switch (pin) {
- case 0: return AXP_GPIO0_CTRL;
- case 1: return AXP_GPIO1_CTRL;
-#ifdef AXP_GPIO2_CTRL
- case 2: return AXP_GPIO2_CTRL;
-#endif
-#ifdef AXP_GPIO3_CTRL
- case 3: return AXP_GPIO3_CTRL;
-#endif
- }
- return 0;
-}
-
-static int axp_gpio_direction_input(struct udevice *dev, unsigned pin)
-{
- u8 reg;
-
- reg = axp_get_gpio_ctrl_reg(pin);
- if (reg == 0)
- return -EINVAL;
-
- return pmic_reg_write(dev->parent, reg, AXP_GPIO_CTRL_INPUT);
-}
-
-static int axp_gpio_direction_output(struct udevice *dev, unsigned pin,
- int val)
-{
- u8 reg;
-
- reg = axp_get_gpio_ctrl_reg(pin);
- if (reg == 0)
- return -EINVAL;
-
- return pmic_reg_write(dev->parent, reg,
- val ? AXP_GPIO_CTRL_OUTPUT_HIGH :
- AXP_GPIO_CTRL_OUTPUT_LOW);
-}
+#define AXP_GPIO_CTRL_MASK 0x7
+#define AXP_GPIO_CTRL_OUTPUT_LOW 0
+#define AXP_GPIO_CTRL_OUTPUT_HIGH 1
+
+struct axp_gpio_desc {
+ const u8 *pins;
+ u8 npins;
+ u8 status_reg;
+ u8 status_offset;
+ u8 input_mux;
+};
static int axp_gpio_get_value(struct udevice *dev, unsigned pin)
{
- u8 reg, mask;
+ const struct axp_gpio_desc *desc = dev_get_priv(dev);
int ret;
- reg = axp_get_gpio_ctrl_reg(pin);
- if (reg == 0)
- return -EINVAL;
-
- ret = pmic_reg_read(dev->parent, AXP_GPIO_STATE);
+ ret = pmic_reg_read(dev->parent, desc->status_reg);
if (ret < 0)
return ret;
- mask = 1 << (pin + AXP_GPIO_STATE_OFFSET);
-
- return (ret & mask) ? 1 : 0;
+ return !!(ret & BIT(desc->status_offset + pin));
}
-static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val)
+static int axp_gpio_set_flags(struct udevice *dev, unsigned pin, ulong flags)
{
- u8 reg;
+ const struct axp_gpio_desc *desc = dev_get_priv(dev);
+ u8 mux;
- reg = axp_get_gpio_ctrl_reg(pin);
- if (reg == 0)
+ if (flags & (GPIOD_MASK_DSTYPE | GPIOD_MASK_PULL))
return -EINVAL;
- return pmic_reg_write(dev->parent, reg,
- val ? AXP_GPIO_CTRL_OUTPUT_HIGH :
- AXP_GPIO_CTRL_OUTPUT_LOW);
+ if (flags & GPIOD_IS_IN)
+ mux = desc->input_mux;
+ else if (flags & GPIOD_IS_OUT_ACTIVE)
+ mux = AXP_GPIO_CTRL_OUTPUT_HIGH;
+ else
+ mux = AXP_GPIO_CTRL_OUTPUT_LOW;
+
+ return pmic_clrsetbits(dev->parent, desc->pins[pin],
+ AXP_GPIO_CTRL_MASK, mux);
}
static const struct dm_gpio_ops axp_gpio_ops = {
- .direction_input = axp_gpio_direction_input,
- .direction_output = axp_gpio_direction_output,
.get_value = axp_gpio_get_value,
- .set_value = axp_gpio_set_value,
+ .xlate = gpio_xlate_offs_flags,
+ .set_flags = axp_gpio_set_flags,
};
static int axp_gpio_probe(struct udevice *dev)
{
+ struct axp_gpio_desc *desc = (void *)dev_get_driver_data(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ dev_set_priv(dev, desc);
+
/* Tell the uclass how many GPIOs we have */
uc_priv->bank_name = AXP_GPIO_PREFIX;
- uc_priv->gpio_count = AXP_GPIO_COUNT;
+ uc_priv->gpio_count = desc->npins;
return 0;
}
+static const u8 axp152_gpio_pins[] = {
+ 0x90, 0x91, 0x92, 0x93,
+};
+
+static const struct axp_gpio_desc axp152_gpio_desc = {
+ .pins = axp152_gpio_pins,
+ .npins = ARRAY_SIZE(axp152_gpio_pins),
+ .status_reg = 0x97,
+ .status_offset = 4,
+ .input_mux = 3,
+};
+
+static const u8 axp209_gpio_pins[] = {
+ 0x90, 0x92, 0x93,
+};
+
+static const struct axp_gpio_desc axp209_gpio_desc = {
+ .pins = axp209_gpio_pins,
+ .npins = ARRAY_SIZE(axp209_gpio_pins),
+ .status_reg = 0x94,
+ .status_offset = 4,
+ .input_mux = 2,
+};
+
+static const u8 axp221_gpio_pins[] = {
+ 0x90, 0x92,
+};
+
+static const struct axp_gpio_desc axp221_gpio_desc = {
+ .pins = axp221_gpio_pins,
+ .npins = ARRAY_SIZE(axp221_gpio_pins),
+ .status_reg = 0x94,
+ .input_mux = 2,
+};
+
static const struct udevice_id axp_gpio_ids[] = {
- { .compatible = "x-powers,axp152-gpio" },
- { .compatible = "x-powers,axp209-gpio" },
- { .compatible = "x-powers,axp221-gpio" },
- { .compatible = "x-powers,axp813-gpio" },
+ { .compatible = "x-powers,axp152-gpio", .data = (ulong)&axp152_gpio_desc },
+ { .compatible = "x-powers,axp209-gpio", .data = (ulong)&axp209_gpio_desc },
+ { .compatible = "x-powers,axp221-gpio", .data = (ulong)&axp221_gpio_desc },
+ { .compatible = "x-powers,axp813-gpio", .data = (ulong)&axp221_gpio_desc },
{ }
};
--- a/drivers/power/axp209.c
+++ b/drivers/power/axp209.c
@@ -215,15 +215,15 @@ int axp_init(void)
* Turn off LDOIO regulators / tri-state GPIO pins, when rebooting
* from android these are sometimes on.
*/
- rc = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT);
+ rc = pmic_bus_write(AXP209_GPIO0_CTRL, AXP209_GPIO_CTRL_INPUT);
if (rc)
return rc;
- rc = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT);
+ rc = pmic_bus_write(AXP209_GPIO1_CTRL, AXP209_GPIO_CTRL_INPUT);
if (rc)
return rc;
- rc = pmic_bus_write(AXP_GPIO2_CTRL, AXP_GPIO_CTRL_INPUT);
+ rc = pmic_bus_write(AXP209_GPIO2_CTRL, AXP209_GPIO_CTRL_INPUT);
if (rc)
return rc;
--- a/drivers/power/axp221.c
+++ b/drivers/power/axp221.c
@@ -226,11 +226,11 @@ int axp_init(void)
* Turn off LDOIO regulators / tri-state GPIO pins, when rebooting
* from android these are sometimes on.
*/
- ret = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT);
+ ret = pmic_bus_write(AXP221_GPIO0_CTRL, AXP221_GPIO_CTRL_INPUT);
if (ret)
return ret;
- ret = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT);
+ ret = pmic_bus_write(AXP221_GPIO1_CTRL, AXP221_GPIO_CTRL_INPUT);
if (ret)
return ret;
--- a/include/axp152.h
+++ b/include/axp152.h
@@ -14,17 +14,7 @@ enum axp152_reg {
#define AXP152_POWEROFF (1 << 7)
-/* For axp_gpio.c */
#ifdef CONFIG_AXP152_POWER
#define AXP_POWER_STATUS 0x00
#define AXP_POWER_STATUS_ALDO_IN BIT(0)
-#define AXP_GPIO0_CTRL 0x90
-#define AXP_GPIO1_CTRL 0x91
-#define AXP_GPIO2_CTRL 0x92
-#define AXP_GPIO3_CTRL 0x93
-#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */
-#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */
-#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */
-#define AXP_GPIO_STATE 0x97
-#define AXP_GPIO_STATE_OFFSET 0
#endif
--- a/include/axp209.h
+++ b/include/axp209.h
@@ -21,6 +21,9 @@ enum axp209_reg {
AXP209_IRQ_ENABLE5 = 0x44,
AXP209_IRQ_STATUS5 = 0x4c,
AXP209_SHUTDOWN = 0x32,
+ AXP209_GPIO0_CTRL = 0x90,
+ AXP209_GPIO1_CTRL = 0x92,
+ AXP209_GPIO2_CTRL = 0x93,
};
#define AXP209_POWER_STATUS_ON_BY_DC BIT(0)
@@ -73,16 +76,11 @@ enum axp209_reg {
#define AXP209_POWEROFF BIT(7)
-/* For axp_gpio.c */
+#define AXP209_GPIO_CTRL_OUTPUT_LOW 0x00
+#define AXP209_GPIO_CTRL_OUTPUT_HIGH 0x01
+#define AXP209_GPIO_CTRL_INPUT 0x02
+
#ifdef CONFIG_AXP209_POWER
#define AXP_POWER_STATUS 0x00
#define AXP_POWER_STATUS_ALDO_IN BIT(0)
-#define AXP_GPIO0_CTRL 0x90
-#define AXP_GPIO1_CTRL 0x92
-#define AXP_GPIO2_CTRL 0x93
-#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */
-#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */
-#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */
-#define AXP_GPIO_STATE 0x94
-#define AXP_GPIO_STATE_OFFSET 4
#endif
--- a/include/axp221.h
+++ b/include/axp221.h
@@ -44,20 +44,17 @@
#define AXP221_ALDO3_CTRL 0x2a
#define AXP221_SHUTDOWN 0x32
#define AXP221_SHUTDOWN_POWEROFF (1 << 7)
+#define AXP221_GPIO0_CTRL 0x90
+#define AXP221_GPIO1_CTRL 0x92
+#define AXP221_GPIO_CTRL_OUTPUT_LOW 0x00
+#define AXP221_GPIO_CTRL_OUTPUT_HIGH 0x01
+#define AXP221_GPIO_CTRL_INPUT 0x02
#define AXP221_PAGE 0xff
/* Page 1 addresses */
#define AXP221_SID 0x20
-/* For axp_gpio.c */
#ifdef CONFIG_AXP221_POWER
#define AXP_POWER_STATUS 0x00
#define AXP_POWER_STATUS_ALDO_IN BIT(0)
-#define AXP_GPIO0_CTRL 0x90
-#define AXP_GPIO1_CTRL 0x92
-#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */
-#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */
-#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */
-#define AXP_GPIO_STATE 0x94
-#define AXP_GPIO_STATE_OFFSET 0
#endif
--- a/include/axp809.h
+++ b/include/axp809.h
@@ -43,15 +43,7 @@
#define AXP809_SHUTDOWN 0x32
#define AXP809_SHUTDOWN_POWEROFF (1 << 7)
-/* For axp_gpio.c */
#ifdef CONFIG_AXP809_POWER
#define AXP_POWER_STATUS 0x00
#define AXP_POWER_STATUS_ALDO_IN BIT(0)
-#define AXP_GPIO0_CTRL 0x90
-#define AXP_GPIO1_CTRL 0x92
-#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */
-#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */
-#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */
-#define AXP_GPIO_STATE 0x94
-#define AXP_GPIO_STATE_OFFSET 0
#endif
--- a/include/axp818.h
+++ b/include/axp818.h
@@ -57,15 +57,7 @@
#define AXP818_SHUTDOWN 0x32
#define AXP818_SHUTDOWN_POWEROFF (1 << 7)
-/* For axp_gpio.c */
#ifdef CONFIG_AXP818_POWER
#define AXP_POWER_STATUS 0x00
#define AXP_POWER_STATUS_ALDO_IN BIT(0)
-#define AXP_GPIO0_CTRL 0x90
-#define AXP_GPIO1_CTRL 0x92
-#define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */
-#define AXP_GPIO_CTRL_OUTPUT_HIGH 0x01 /* Drive pin high */
-#define AXP_GPIO_CTRL_INPUT 0x02 /* Input */
-#define AXP_GPIO_STATE 0x94
-#define AXP_GPIO_STATE_OFFSET 0
#endif
|