blob: 3ddb637ab779fd213b20b1af7cad2bb4c192b5b9 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Felix Brack7bc23542017-03-22 11:26:44 +01002/*
3 * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
Dario Binacchi596c5082021-04-11 09:39:49 +02004 * Copyright (C) 2021 Dario Binacchi <dariobin@libero.it>
Felix Brack7bc23542017-03-22 11:26:44 +01005 */
6
7#include <common.h>
Simon Glass11c89f32017-05-17 17:18:03 -06008#include <dm.h>
Simon Glass9bc15642020-02-03 07:36:16 -07009#include <dm/device_compat.h>
Dario Binacchi596c5082021-04-11 09:39:49 +020010#include <dm/devres.h>
Felix Brack7bc23542017-03-22 11:26:44 +010011#include <dm/pinctrl.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090012#include <linux/libfdt.h>
Dario Binacchi596c5082021-04-11 09:39:49 +020013#include <linux/list.h>
Felix Brack7bc23542017-03-22 11:26:44 +010014#include <asm/io.h>
Dario Binacchi596c5082021-04-11 09:39:49 +020015#include <sort.h>
Felix Brack7bc23542017-03-22 11:26:44 +010016
Dario Binacchi3b488022021-04-11 09:39:39 +020017/**
18 * struct single_pdata - platform data
19 * @base: first configuration register
20 * @offset: index of last configuration register
21 * @mask: configuration-value mask bits
22 * @width: configuration register bit width
23 * @bits_per_mux: true if one register controls more than one pin
24 */
Felix Brack7bc23542017-03-22 11:26:44 +010025struct single_pdata {
Dario Binacchi3b488022021-04-11 09:39:39 +020026 fdt_addr_t base;
27 int offset;
28 u32 mask;
Dario Binacchi9e4051f2021-04-11 09:39:44 +020029 u32 width;
Adam Ford6305a5c2019-06-10 13:15:55 -050030 bool bits_per_mux;
Felix Brack7bc23542017-03-22 11:26:44 +010031};
32
Dario Binacchi3b488022021-04-11 09:39:39 +020033/**
Dario Binacchi596c5082021-04-11 09:39:49 +020034 * struct single_func - pinctrl function
35 * @node: list node
36 * @name: pinctrl function name
37 * @npins: number of entries in pins array
38 * @pins: pins array
39 */
40struct single_func {
41 struct list_head node;
42 const char *name;
43 unsigned int npins;
44 unsigned int *pins;
45};
46
47/**
Dario Binacchi235132c2021-04-11 09:39:47 +020048 * struct single_priv - private data
49 * @bits_per_pin: number of bits per pin
50 * @npins: number of selectable pins
Dario Binacchif3ecbc12021-04-11 09:39:48 +020051 * @pin_name: temporary buffer to store the pin name
Dario Binacchi235132c2021-04-11 09:39:47 +020052 */
53struct single_priv {
54 unsigned int bits_per_pin;
55 unsigned int npins;
Dario Binacchif3ecbc12021-04-11 09:39:48 +020056 char pin_name[PINNAME_SIZE];
Dario Binacchi596c5082021-04-11 09:39:49 +020057 struct list_head functions;
Dario Binacchi235132c2021-04-11 09:39:47 +020058};
59
60/**
Dario Binacchi3b488022021-04-11 09:39:39 +020061 * struct single_fdt_pin_cfg - pin configuration
62 *
63 * This structure is used for the pin configuration parameters in case
64 * the register controls only one pin.
65 *
66 * @reg: configuration register offset
67 * @val: configuration register value
68 */
Felix Brack7bc23542017-03-22 11:26:44 +010069struct single_fdt_pin_cfg {
Dario Binacchi3b488022021-04-11 09:39:39 +020070 fdt32_t reg;
71 fdt32_t val;
Felix Brack7bc23542017-03-22 11:26:44 +010072};
73
Dario Binacchi3b488022021-04-11 09:39:39 +020074/**
75 * struct single_fdt_bits_cfg - pin configuration
76 *
77 * This structure is used for the pin configuration parameters in case
78 * the register controls more than one pin.
79 *
80 * @reg: configuration register offset
81 * @val: configuration register value
82 * @mask: configuration register mask
83 */
Adam Ford6305a5c2019-06-10 13:15:55 -050084struct single_fdt_bits_cfg {
Dario Binacchi3b488022021-04-11 09:39:39 +020085 fdt32_t reg;
86 fdt32_t val;
87 fdt32_t mask;
Adam Ford6305a5c2019-06-10 13:15:55 -050088};
89
Dario Binacchi54dfe522021-04-11 09:39:46 +020090static unsigned int single_read(struct udevice *dev, fdt_addr_t reg)
91{
92 struct single_pdata *pdata = dev_get_plat(dev);
93
94 switch (pdata->width) {
95 case 8:
96 return readb(reg);
97 case 16:
98 return readw(reg);
99 default: /* 32 bits */
100 return readl(reg);
101 }
102
103 return readb(reg);
104}
105
106static void single_write(struct udevice *dev, unsigned int val, fdt_addr_t reg)
107{
108 struct single_pdata *pdata = dev_get_plat(dev);
109
110 switch (pdata->width) {
111 case 8:
112 writeb(val, reg);
113 break;
114 case 16:
115 writew(val, reg);
116 break;
117 default: /* 32 bits */
118 writel(val, reg);
119 }
Dario Binacchi596c5082021-04-11 09:39:49 +0200120}
121
122/**
123 * single_get_pin_by_offset() - get a pin based on the register offset
124 * @dev: single driver instance
125 * @offset: register offset from the base
126 */
127static int single_get_pin_by_offset(struct udevice *dev, unsigned int offset)
128{
129 struct single_pdata *pdata = dev_get_plat(dev);
130 struct single_priv *priv = dev_get_priv(dev);
131
132 if (offset > pdata->offset) {
133 dev_err(dev, "mux offset out of range: 0x%x (0x%x)\n",
134 offset, pdata->offset);
135 return -EINVAL;
136 }
137
138 if (pdata->bits_per_mux)
139 return (offset * BITS_PER_BYTE) / priv->bits_per_pin;
140
141 return offset / (pdata->width / BITS_PER_BYTE);
142}
143
144static int single_get_offset_by_pin(struct udevice *dev, unsigned int pin)
145{
146 struct single_pdata *pdata = dev_get_plat(dev);
147 struct single_priv *priv = dev_get_priv(dev);
148 unsigned int mux_bytes;
149
150 if (pin >= priv->npins)
151 return -EINVAL;
152
153 mux_bytes = pdata->width / BITS_PER_BYTE;
154 if (pdata->bits_per_mux) {
155 int byte_num;
156
157 byte_num = (priv->bits_per_pin * pin) / BITS_PER_BYTE;
158 return (byte_num / mux_bytes) * mux_bytes;
159 }
160
161 return pin * mux_bytes;
162}
163
164static const char *single_get_pin_function(struct udevice *dev,
165 unsigned int pin)
166{
167 struct single_priv *priv = dev_get_priv(dev);
168 struct single_func *func;
169 int i;
170
171 list_for_each_entry(func, &priv->functions, node) {
172 for (i = 0; i < func->npins; i++) {
173 if (pin == func->pins[i])
174 return func->name;
175
176 if (pin < func->pins[i])
177 break;
178 }
179 }
180
181 return NULL;
182}
183
184static int single_get_pin_muxing(struct udevice *dev, unsigned int pin,
185 char *buf, int size)
186{
187 struct single_pdata *pdata = dev_get_plat(dev);
188 struct single_priv *priv = dev_get_priv(dev);
189 fdt_addr_t reg;
190 const char *fname;
191 unsigned int val;
192 int offset, pin_shift = 0;
193
194 offset = single_get_offset_by_pin(dev, pin);
195 if (offset < 0)
196 return offset;
197
198 reg = pdata->base + offset;
199 val = single_read(dev, reg);
200
201 if (pdata->bits_per_mux)
202 pin_shift = pin % (pdata->width / priv->bits_per_pin) *
203 priv->bits_per_pin;
204
205 val &= (pdata->mask << pin_shift);
206 fname = single_get_pin_function(dev, pin);
207 snprintf(buf, size, "%pa 0x%08x %s", &reg, val,
208 fname ? fname : "UNCLAIMED");
209 return 0;
210}
211
212static struct single_func *single_allocate_function(struct udevice *dev,
213 unsigned int group_pins)
214{
215 struct single_func *func;
216
217 func = devm_kmalloc(dev, sizeof(*func), GFP_KERNEL);
218 if (!func)
219 return ERR_PTR(-ENOMEM);
220
221 func->pins = devm_kmalloc(dev, sizeof(unsigned int) * group_pins,
222 GFP_KERNEL);
223 if (!func->pins)
224 return ERR_PTR(-ENOMEM);
225
226 return func;
227}
228
229static int single_pin_compare(const void *s1, const void *s2)
230{
231 int pin1 = *(const unsigned int *)s1;
232 int pin2 = *(const unsigned int *)s2;
233
234 return pin1 - pin2;
Dario Binacchi54dfe522021-04-11 09:39:46 +0200235}
236
Felix Brack7bc23542017-03-22 11:26:44 +0100237/**
238 * single_configure_pins() - Configure pins based on FDT data
239 *
240 * @dev: Pointer to single pin configuration device which is the parent of
241 * the pins node holding the pin configuration data.
242 * @pins: Pointer to the first element of an array of register/value pairs
243 * of type 'struct single_fdt_pin_cfg'. Each such pair describes the
244 * the pin to be configured and the value to be used for configuration.
245 * This pointer points to a 'pinctrl-single,pins' property in the
246 * device-tree.
247 * @size: Size of the 'pins' array in bytes.
248 * The number of register/value pairs in the 'pins' array therefore
249 * equals to 'size / sizeof(struct single_fdt_pin_cfg)'.
Dario Binacchi596c5082021-04-11 09:39:49 +0200250 * @fname: Function name.
Felix Brack7bc23542017-03-22 11:26:44 +0100251 */
252static int single_configure_pins(struct udevice *dev,
253 const struct single_fdt_pin_cfg *pins,
Dario Binacchi596c5082021-04-11 09:39:49 +0200254 int size, const char *fname)
Felix Brack7bc23542017-03-22 11:26:44 +0100255{
Simon Glass95588622020-12-22 19:30:28 -0700256 struct single_pdata *pdata = dev_get_plat(dev);
Dario Binacchi596c5082021-04-11 09:39:49 +0200257 struct single_priv *priv = dev_get_priv(dev);
258 int n, pin, count = size / sizeof(struct single_fdt_pin_cfg);
259 struct single_func *func;
Dario Binacchie02eea32021-04-11 09:39:40 +0200260 phys_addr_t reg;
Dario Binacchic3ed31f2021-04-11 09:39:41 +0200261 u32 offset, val;
Felix Brack7bc23542017-03-22 11:26:44 +0100262
Dario Binacchi12f50452021-04-11 09:39:45 +0200263 /* If function mask is null, needn't enable it. */
264 if (!pdata->mask)
265 return 0;
266
Dario Binacchi596c5082021-04-11 09:39:49 +0200267 func = single_allocate_function(dev, count);
268 if (IS_ERR(func))
269 return PTR_ERR(func);
270
271 func->name = fname;
272 func->npins = 0;
James Baleand2f96ad2017-04-18 21:06:35 -0500273 for (n = 0; n < count; n++, pins++) {
Dario Binacchic3ed31f2021-04-11 09:39:41 +0200274 offset = fdt32_to_cpu(pins->reg);
275 if (offset < 0 || offset > pdata->offset) {
Dario Binacchi596c5082021-04-11 09:39:49 +0200276 dev_err(dev, " invalid register offset 0x%x\n",
Dario Binacchic3ed31f2021-04-11 09:39:41 +0200277 offset);
Felix Brack7bc23542017-03-22 11:26:44 +0100278 continue;
279 }
Dario Binacchic3ed31f2021-04-11 09:39:41 +0200280
281 reg = pdata->base + offset;
James Baleand2f96ad2017-04-18 21:06:35 -0500282 val = fdt32_to_cpu(pins->val) & pdata->mask;
Dario Binacchi596c5082021-04-11 09:39:49 +0200283 pin = single_get_pin_by_offset(dev, offset);
284 if (pin < 0) {
285 dev_err(dev, " failed to get pin by offset %x\n",
286 offset);
287 continue;
288 }
289
Dario Binacchi54dfe522021-04-11 09:39:46 +0200290 single_write(dev, (single_read(dev, reg) & ~pdata->mask) | val,
291 reg);
Dario Binacchi35f4ac52021-04-11 09:39:42 +0200292 dev_dbg(dev, " reg/val %pa/0x%08x\n", &reg, val);
Dario Binacchi596c5082021-04-11 09:39:49 +0200293 func->pins[func->npins] = pin;
294 func->npins++;
Felix Brack7bc23542017-03-22 11:26:44 +0100295 }
Dario Binacchi596c5082021-04-11 09:39:49 +0200296
297 qsort(func->pins, func->npins, sizeof(func->pins[0]),
298 single_pin_compare);
299 list_add(&func->node, &priv->functions);
Felix Brack7bc23542017-03-22 11:26:44 +0100300 return 0;
301}
302
Adam Ford6305a5c2019-06-10 13:15:55 -0500303static int single_configure_bits(struct udevice *dev,
304 const struct single_fdt_bits_cfg *pins,
Dario Binacchi596c5082021-04-11 09:39:49 +0200305 int size, const char *fname)
Adam Ford6305a5c2019-06-10 13:15:55 -0500306{
Simon Glass95588622020-12-22 19:30:28 -0700307 struct single_pdata *pdata = dev_get_plat(dev);
Dario Binacchi596c5082021-04-11 09:39:49 +0200308 struct single_priv *priv = dev_get_priv(dev);
309 int n, pin, count = size / sizeof(struct single_fdt_bits_cfg);
310 int npins_in_reg, pin_num_from_lsb;
311 struct single_func *func;
Dario Binacchie02eea32021-04-11 09:39:40 +0200312 phys_addr_t reg;
Dario Binacchi596c5082021-04-11 09:39:49 +0200313 u32 offset, val, mask, bit_pos, val_pos, mask_pos, submask;
Adam Ford6305a5c2019-06-10 13:15:55 -0500314
Dario Binacchi596c5082021-04-11 09:39:49 +0200315 npins_in_reg = pdata->width / priv->bits_per_pin;
316 func = single_allocate_function(dev, count * npins_in_reg);
317 if (IS_ERR(func))
318 return PTR_ERR(func);
319
320 func->name = fname;
321 func->npins = 0;
Adam Ford6305a5c2019-06-10 13:15:55 -0500322 for (n = 0; n < count; n++, pins++) {
Dario Binacchic3ed31f2021-04-11 09:39:41 +0200323 offset = fdt32_to_cpu(pins->reg);
324 if (offset < 0 || offset > pdata->offset) {
325 dev_dbg(dev, " invalid register offset 0x%x\n",
326 offset);
Adam Ford6305a5c2019-06-10 13:15:55 -0500327 continue;
328 }
Dario Binacchic3ed31f2021-04-11 09:39:41 +0200329
330 reg = pdata->base + offset;
Adam Ford6305a5c2019-06-10 13:15:55 -0500331
Dario Binacchi596c5082021-04-11 09:39:49 +0200332 pin = single_get_pin_by_offset(dev, offset);
333 if (pin < 0) {
334 dev_err(dev, " failed to get pin by offset 0x%pa\n",
335 &reg);
336 continue;
337 }
338
Adam Ford6305a5c2019-06-10 13:15:55 -0500339 mask = fdt32_to_cpu(pins->mask);
340 val = fdt32_to_cpu(pins->val) & mask;
Dario Binacchi54dfe522021-04-11 09:39:46 +0200341 single_write(dev, (single_read(dev, reg) & ~mask) | val, reg);
Dario Binacchi35f4ac52021-04-11 09:39:42 +0200342 dev_dbg(dev, " reg/val %pa/0x%08x\n", &reg, val);
Dario Binacchi596c5082021-04-11 09:39:49 +0200343
344 while (mask) {
345 bit_pos = __ffs(mask);
346 pin_num_from_lsb = bit_pos / priv->bits_per_pin;
347 mask_pos = pdata->mask << bit_pos;
348 val_pos = val & mask_pos;
349 submask = mask & mask_pos;
350
351 if ((mask & mask_pos) == 0) {
352 dev_err(dev, "Invalid mask at 0x%x\n", offset);
353 break;
354 }
355
356 mask &= ~mask_pos;
357
358 if (submask != mask_pos) {
359 dev_warn(dev,
360 "Invalid submask 0x%x at 0x%x\n",
361 submask, offset);
362 continue;
363 }
364
365 func->pins[func->npins] = pin + pin_num_from_lsb;
366 func->npins++;
367 }
Adam Ford6305a5c2019-06-10 13:15:55 -0500368 }
Dario Binacchi596c5082021-04-11 09:39:49 +0200369
370 qsort(func->pins, func->npins, sizeof(func->pins[0]),
371 single_pin_compare);
372 list_add(&func->node, &priv->functions);
Adam Ford6305a5c2019-06-10 13:15:55 -0500373 return 0;
374}
Felix Brack7bc23542017-03-22 11:26:44 +0100375static int single_set_state(struct udevice *dev,
376 struct udevice *config)
377{
Felix Brack7bc23542017-03-22 11:26:44 +0100378 const struct single_fdt_pin_cfg *prop;
Adam Ford6305a5c2019-06-10 13:15:55 -0500379 const struct single_fdt_bits_cfg *prop_bits;
Felix Brack7bc23542017-03-22 11:26:44 +0100380 int len;
381
Lokesh Vutla0bef0262020-04-22 22:55:31 +0530382 prop = dev_read_prop(config, "pinctrl-single,pins", &len);
Adam Ford6305a5c2019-06-10 13:15:55 -0500383
Felix Brack7bc23542017-03-22 11:26:44 +0100384 if (prop) {
385 dev_dbg(dev, "configuring pins for %s\n", config->name);
386 if (len % sizeof(struct single_fdt_pin_cfg)) {
387 dev_dbg(dev, " invalid pin configuration in fdt\n");
388 return -FDT_ERR_BADSTRUCTURE;
389 }
Dario Binacchi596c5082021-04-11 09:39:49 +0200390 single_configure_pins(dev, prop, len, config->name);
Adam Ford6305a5c2019-06-10 13:15:55 -0500391 return 0;
Felix Brack7bc23542017-03-22 11:26:44 +0100392 }
393
Adam Ford6305a5c2019-06-10 13:15:55 -0500394 /* pinctrl-single,pins not found so check for pinctrl-single,bits */
Lokesh Vutla0bef0262020-04-22 22:55:31 +0530395 prop_bits = dev_read_prop(config, "pinctrl-single,bits", &len);
Adam Ford6305a5c2019-06-10 13:15:55 -0500396 if (prop_bits) {
397 dev_dbg(dev, "configuring pins for %s\n", config->name);
398 if (len % sizeof(struct single_fdt_bits_cfg)) {
399 dev_dbg(dev, " invalid bits configuration in fdt\n");
400 return -FDT_ERR_BADSTRUCTURE;
401 }
Dario Binacchi596c5082021-04-11 09:39:49 +0200402 single_configure_bits(dev, prop_bits, len, config->name);
Adam Ford6305a5c2019-06-10 13:15:55 -0500403 return 0;
404 }
405
406 /* Neither 'pinctrl-single,pins' nor 'pinctrl-single,bits' were found */
Felix Brack7bc23542017-03-22 11:26:44 +0100407 return len;
408}
409
Dario Binacchif3ecbc12021-04-11 09:39:48 +0200410static const char *single_get_pin_name(struct udevice *dev,
411 unsigned int selector)
412{
413 struct single_priv *priv = dev_get_priv(dev);
414
415 if (selector >= priv->npins)
416 snprintf(priv->pin_name, PINNAME_SIZE, "Error");
417 else
418 snprintf(priv->pin_name, PINNAME_SIZE, "PIN%u", selector);
419
420 return priv->pin_name;
421}
422
Dario Binacchi235132c2021-04-11 09:39:47 +0200423static int single_get_pins_count(struct udevice *dev)
424{
425 struct single_priv *priv = dev_get_priv(dev);
426
427 return priv->npins;
428}
429
430static int single_probe(struct udevice *dev)
431{
432 struct single_pdata *pdata = dev_get_plat(dev);
433 struct single_priv *priv = dev_get_priv(dev);
434 u32 size;
435
Dario Binacchi596c5082021-04-11 09:39:49 +0200436 INIT_LIST_HEAD(&priv->functions);
437
Dario Binacchi235132c2021-04-11 09:39:47 +0200438 size = pdata->offset + pdata->width / BITS_PER_BYTE;
439 priv->npins = size / (pdata->width / BITS_PER_BYTE);
440 if (pdata->bits_per_mux) {
441 priv->bits_per_pin = fls(pdata->mask);
442 priv->npins *= (pdata->width / priv->bits_per_pin);
443 }
444
445 dev_dbg(dev, "%d pins\n", priv->npins);
446 return 0;
447}
448
Simon Glassaad29ae2020-12-03 16:55:21 -0700449static int single_of_to_plat(struct udevice *dev)
Felix Brack7bc23542017-03-22 11:26:44 +0100450{
451 fdt_addr_t addr;
Dario Binacchi22fb01d2021-04-11 09:39:43 +0200452 fdt_size_t size;
Simon Glass95588622020-12-22 19:30:28 -0700453 struct single_pdata *pdata = dev_get_plat(dev);
Dario Binacchi9e4051f2021-04-11 09:39:44 +0200454 int ret;
Felix Brack7bc23542017-03-22 11:26:44 +0100455
Dario Binacchi9e4051f2021-04-11 09:39:44 +0200456 ret = dev_read_u32(dev, "pinctrl-single,register-width", &pdata->width);
457 if (ret) {
458 dev_err(dev, "missing register width\n");
459 return ret;
460 }
Felix Brack7bc23542017-03-22 11:26:44 +0100461
Dario Binacchi54dfe522021-04-11 09:39:46 +0200462 switch (pdata->width) {
463 case 8:
464 case 16:
465 case 32:
466 break;
467 default:
468 dev_err(dev, "wrong register width\n");
469 return -EINVAL;
470 }
471
Dario Binacchi22fb01d2021-04-11 09:39:43 +0200472 addr = dev_read_addr_size(dev, "reg", &size);
473 if (addr == FDT_ADDR_T_NONE) {
474 dev_err(dev, "failed to get base register size\n");
475 return -EINVAL;
476 }
477
478 pdata->offset = size - pdata->width / BITS_PER_BYTE;
Felix Brack7bc23542017-03-22 11:26:44 +0100479
Patrick Delaunayaf2fb742020-01-13 11:34:55 +0100480 addr = dev_read_addr(dev);
Felix Brack7bc23542017-03-22 11:26:44 +0100481 if (addr == FDT_ADDR_T_NONE) {
482 dev_dbg(dev, "no valid base register address\n");
483 return -EINVAL;
484 }
485 pdata->base = addr;
486
Dario Binacchi12f50452021-04-11 09:39:45 +0200487 ret = dev_read_u32(dev, "pinctrl-single,function-mask", &pdata->mask);
488 if (ret) {
489 pdata->mask = 0;
490 dev_warn(dev, "missing function register mask\n");
491 }
492
Patrick Delaunayaf2fb742020-01-13 11:34:55 +0100493 pdata->bits_per_mux = dev_read_bool(dev, "pinctrl-single,bit-per-mux");
Adam Ford6305a5c2019-06-10 13:15:55 -0500494
Felix Brack7bc23542017-03-22 11:26:44 +0100495 return 0;
496}
497
498const struct pinctrl_ops single_pinctrl_ops = {
Dario Binacchi235132c2021-04-11 09:39:47 +0200499 .get_pins_count = single_get_pins_count,
Dario Binacchif3ecbc12021-04-11 09:39:48 +0200500 .get_pin_name = single_get_pin_name,
Felix Brack7bc23542017-03-22 11:26:44 +0100501 .set_state = single_set_state,
Dario Binacchi596c5082021-04-11 09:39:49 +0200502 .get_pin_muxing = single_get_pin_muxing,
Felix Brack7bc23542017-03-22 11:26:44 +0100503};
504
505static const struct udevice_id single_pinctrl_match[] = {
506 { .compatible = "pinctrl-single" },
507 { /* sentinel */ }
508};
509
510U_BOOT_DRIVER(single_pinctrl) = {
511 .name = "single-pinctrl",
512 .id = UCLASS_PINCTRL,
513 .of_match = single_pinctrl_match,
514 .ops = &single_pinctrl_ops,
Simon Glass71fa5b42020-12-03 16:55:18 -0700515 .plat_auto = sizeof(struct single_pdata),
Dario Binacchi235132c2021-04-11 09:39:47 +0200516 .priv_auto = sizeof(struct single_priv),
Simon Glassaad29ae2020-12-03 16:55:21 -0700517 .of_to_plat = single_of_to_plat,
Dario Binacchi235132c2021-04-11 09:39:47 +0200518 .probe = single_probe,
Felix Brack7bc23542017-03-22 11:26:44 +0100519};