Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/drivers/pinctrl/pinctrl-generic.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 * Copyright (C) 2015  Masahiro Yamada <yamada.masahiro@socionext.com>
4
 */
5
6
#include <dm.h>
7
#include <dm/device_compat.h>
8
#include <linux/compat.h>
9
#include <dm/pinctrl.h>
10
11
/**
12
 * pinctrl_pin_name_to_selector() - return the pin selector for a pin
13
 *
14
 * @dev: pin controller device
15
 * @pin: the pin name to look up
16
 * @return: pin selector, or negative error code on failure
17
 */
18
static int pinctrl_pin_name_to_selector(struct udevice *dev, const char *pin)
19
0
{
20
0
  const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
21
0
  unsigned npins, selector;
22
23
0
  if (!ops->get_pins_count || !ops->get_pin_name) {
24
0
    dev_dbg(dev, "get_pins_count or get_pin_name missing\n");
25
0
    return -ENOENT;
26
0
  }
27
28
0
  npins = ops->get_pins_count(dev);
29
30
  /* See if this pctldev has this pin */
31
0
  for (selector = 0; selector < npins; selector++) {
32
0
    const char *pname = ops->get_pin_name(dev, selector);
33
34
0
    if (!strcmp(pin, pname))
35
0
      return selector;
36
0
  }
37
38
0
  return -ENOENT;
39
0
}
40
41
/**
42
 * pinctrl_group_name_to_selector() - return the group selector for a group
43
 *
44
 * @dev: pin controller device
45
 * @group: the pin group name to look up
46
 * @return: pin group selector, or negative error code on failure
47
 */
48
static int pinctrl_group_name_to_selector(struct udevice *dev,
49
            const char *group)
50
0
{
51
0
  const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
52
0
  unsigned ngroups, selector;
53
54
0
  if (!ops->get_groups_count || !ops->get_group_name) {
55
0
    dev_dbg(dev, "get_groups_count or get_group_name missing\n");
56
0
    return -ENOENT;
57
0
  }
58
59
0
  ngroups = ops->get_groups_count(dev);
60
61
  /* See if this pctldev has this group */
62
0
  for (selector = 0; selector < ngroups; selector++) {
63
0
    const char *gname = ops->get_group_name(dev, selector);
64
65
0
    if (!strcmp(group, gname))
66
0
      return selector;
67
0
  }
68
69
0
  return -ENOENT;
70
0
}
71
72
#if CONFIG_IS_ENABLED(PINMUX)
73
/**
74
 * pinmux_func_name_to_selector() - return the function selector for a function
75
 *
76
 * @dev: pin controller device
77
 * @function: the function name to look up
78
 * @return: function selector, or negative error code on failure
79
 */
80
static int pinmux_func_name_to_selector(struct udevice *dev,
81
          const char *function)
82
0
{
83
0
  const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
84
0
  unsigned nfuncs, selector = 0;
85
86
0
  if (!ops->get_functions_count || !ops->get_function_name) {
87
0
    dev_dbg(dev,
88
0
      "get_functions_count or get_function_name missing\n");
89
0
    return -ENOENT;
90
0
  }
91
92
0
  nfuncs = ops->get_functions_count(dev);
93
94
  /* See if this pctldev has this function */
95
0
  for (selector = 0; selector < nfuncs; selector++) {
96
0
    const char *fname = ops->get_function_name(dev, selector);
97
98
0
    if (!strcmp(function, fname))
99
0
      return selector;
100
0
  }
101
102
0
  return -ENOENT;
103
0
}
104
105
/**
106
 * pinmux_enable_setting() - enable pin-mux setting for a certain pin/group
107
 *
108
 * @dev: pin controller device
109
 * @is_group: target of operation (true: pin group, false: pin)
110
 * @selector: pin selector or group selector, depending on @is_group
111
 * @func_selector: function selector
112
 * @return: 0 on success, or negative error code on failure
113
 */
114
static int pinmux_enable_setting(struct udevice *dev, bool is_group,
115
         unsigned selector, unsigned func_selector)
116
0
{
117
0
  const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
118
119
0
  if (is_group) {
120
0
    if (!ops->pinmux_group_set) {
121
0
      dev_dbg(dev, "pinmux_group_set op missing\n");
122
0
      return -ENOENT;
123
0
    }
124
125
0
    return ops->pinmux_group_set(dev, selector, func_selector);
126
0
  } else {
127
0
    if (!ops->pinmux_set) {
128
0
      dev_dbg(dev, "pinmux_set op missing\n");
129
0
      return -ENOENT;
130
0
    }
131
0
    return ops->pinmux_set(dev, selector, func_selector);
132
0
  }
133
0
}
134
#else
135
static int pinmux_func_name_to_selector(struct udevice *dev,
136
          const char *function)
137
{
138
  return 0;
139
}
140
141
static int pinmux_enable_setting(struct udevice *dev, bool is_group,
142
         unsigned selector, unsigned func_selector)
143
{
144
  return 0;
145
}
146
#endif
147
148
#if CONFIG_IS_ENABLED(PINCONF)
149
/**
150
 * pinconf_prop_name_to_param() - return parameter ID for a property name
151
 *
152
 * @dev: pin controller device
153
 * @property: property name in DTS, such as "bias-pull-up", "slew-rate", etc.
154
 * @default_value: return default value in case no value is specified in DTS
155
 * @return: return pamater ID, or negative error code on failure
156
 */
157
static int pinconf_prop_name_to_param(struct udevice *dev,
158
              const char *property, u32 *default_value)
159
0
{
160
0
  const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
161
0
  const struct pinconf_param *p, *end;
162
163
0
  if (!ops->pinconf_num_params || !ops->pinconf_params) {
164
0
    dev_dbg(dev, "pinconf_num_params or pinconf_params missing\n");
165
0
    return -ENOENT;
166
0
  }
167
168
0
  p = ops->pinconf_params;
169
0
  end = p + ops->pinconf_num_params;
170
171
  /* See if this pctldev supports this parameter */
172
0
  for (; p < end; p++) {
173
0
    if (!strcmp(property, p->property)) {
174
0
      *default_value = p->default_value;
175
0
      return p->param;
176
0
    }
177
0
  }
178
179
0
  return -ENOENT;
180
0
}
181
182
/**
183
 * pinconf_enable_setting() - apply pin configuration for a certain pin/group
184
 *
185
 * @dev: pin controller device
186
 * @is_group: target of operation (true: pin group, false: pin)
187
 * @selector: pin selector or group selector, depending on @is_group
188
 * @param: configuration paramter
189
 * @argument: argument taken by some configuration parameters
190
 * @return: 0 on success, or negative error code on failure
191
 */
192
static int pinconf_enable_setting(struct udevice *dev, bool is_group,
193
          unsigned selector, unsigned param,
194
          u32 argument)
195
0
{
196
0
  const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
197
198
0
  if (is_group) {
199
0
    if (!ops->pinconf_group_set) {
200
0
      dev_dbg(dev, "pinconf_group_set op missing\n");
201
0
      return -ENOENT;
202
0
    }
203
204
0
    return ops->pinconf_group_set(dev, selector, param,
205
0
                argument);
206
0
  } else {
207
0
    if (!ops->pinconf_set) {
208
0
      dev_dbg(dev, "pinconf_set op missing\n");
209
0
      return -ENOENT;
210
0
    }
211
0
    return ops->pinconf_set(dev, selector, param, argument);
212
0
  }
213
0
}
214
#else
215
static int pinconf_prop_name_to_param(struct udevice *dev,
216
              const char *property, u32 *default_value)
217
{
218
  return -ENOENT;
219
}
220
221
static int pinconf_enable_setting(struct udevice *dev, bool is_group,
222
          unsigned selector, unsigned param,
223
          u32 argument)
224
{
225
  return 0;
226
}
227
#endif
228
229
enum pinmux_subnode_type {
230
  PST_NONE = 0,
231
  PST_PIN,
232
  PST_GROUP,
233
  PST_PINMUX,
234
};
235
236
static const char *alloc_name_with_prefix(const char *name, const char *prefix)
237
0
{
238
0
  if (prefix) {
239
0
    char *name_with_prefix = malloc(strlen(prefix) + strlen(name) + 1);
240
0
    if (name_with_prefix)
241
0
      sprintf(name_with_prefix, "%s%s", prefix, name);
242
0
    return name_with_prefix;
243
0
  } else {
244
0
    return name;
245
0
  }
246
0
}
247
248
static void free_name_with_prefix(const char *name_with_prefix, const char *prefix)
249
0
{
250
0
  if (prefix)
251
0
    free((char *)name_with_prefix);
252
0
}
253
254
/**
255
 * pinctrl_generic_set_state_one() - set state for a certain pin/group
256
 * Apply all pin multiplexing and pin configurations specified by @config
257
 * for a given pin or pin group.
258
 *
259
 * @dev: pin controller device
260
 * @config: pseudo device pointing to config node
261
 * @subnode_type: target of operation (pin, group, or pin specified by a pinmux
262
 * group)
263
 * @selector: pin selector or group selector, depending on @subnode_type
264
 * @return: 0 on success, or negative error code on failure
265
 */
266
static int pinctrl_generic_set_state_one(struct udevice *dev,
267
           struct udevice *config,
268
           const char *prefix,
269
           enum pinmux_subnode_type subnode_type,
270
           unsigned selector)
271
0
{
272
0
  const char *function_propname;
273
0
  const char *propname;
274
0
  const void *value;
275
0
  struct ofprop property;
276
0
  int len, func_selector, param, ret;
277
0
  u32 arg, default_val;
278
279
0
  assert(subnode_type != PST_NONE);
280
281
0
  function_propname = alloc_name_with_prefix("function", prefix);
282
0
  if (!function_propname)
283
0
    return -ENOMEM;
284
285
0
  dev_for_each_property(property, config) {
286
0
    value = dev_read_prop_by_prop(&property, &propname, &len);
287
0
    if (!value) {
288
0
      free_name_with_prefix(function_propname, prefix);
289
0
      return -EINVAL;
290
0
    }
291
292
    /* pinmux subnodes already have their muxing set */
293
0
    if (subnode_type != PST_PINMUX &&
294
0
        !strcmp(propname, function_propname)) {
295
0
      func_selector = pinmux_func_name_to_selector(dev,
296
0
                     value);
297
0
      if (func_selector < 0) {
298
0
        free_name_with_prefix(function_propname, prefix);
299
0
        return func_selector;
300
0
      }
301
0
      ret = pinmux_enable_setting(dev,
302
0
                subnode_type == PST_GROUP,
303
0
                selector,
304
0
                func_selector);
305
0
    } else {
306
0
      param = pinconf_prop_name_to_param(dev, propname,
307
0
                 &default_val);
308
0
      if (param < 0)
309
0
        continue; /* just skip unknown properties */
310
311
0
      if (len >= sizeof(fdt32_t))
312
0
        arg = fdt32_to_cpu(*(fdt32_t *)value);
313
0
      else
314
0
        arg = default_val;
315
316
0
      ret = pinconf_enable_setting(dev,
317
0
                 subnode_type == PST_GROUP,
318
0
                 selector, param, arg);
319
0
    }
320
321
0
    if (ret) {
322
0
      free_name_with_prefix(function_propname, prefix);
323
0
      return ret;
324
0
    }
325
0
  }
326
327
0
  free_name_with_prefix(function_propname, prefix);
328
0
  return 0;
329
0
}
330
331
/**
332
 * pinctrl_generic_get_subnode_type() - determine whether there is a valid
333
 * pins, groups, or pinmux property in the config node
334
 *
335
 * @dev: pin controller device
336
 * @config: pseudo device pointing to config node
337
 * @count: number of specifiers contained within the property
338
 * @return: the type of the subnode, or PST_NONE
339
 */
340
static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev,
341
                 struct udevice *config,
342
                 const char *prefix,
343
                 int *count)
344
0
{
345
0
  const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
346
0
  const char *propname;
347
348
0
  propname = alloc_name_with_prefix("pins", prefix);
349
0
  if (!propname)
350
0
    return -ENOMEM;
351
0
  *count = dev_read_string_count(config, propname);
352
0
  free_name_with_prefix(propname, prefix);
353
0
  if (*count >= 0)
354
0
    return PST_PIN;
355
356
0
  propname = alloc_name_with_prefix("groups", prefix);
357
0
  if (!propname)
358
0
    return -ENOMEM;
359
0
  *count = dev_read_string_count(config, propname);
360
0
  free_name_with_prefix(propname, prefix);
361
0
  if (*count >= 0)
362
0
    return PST_GROUP;
363
364
0
  if (ops->pinmux_property_set) {
365
0
    propname = alloc_name_with_prefix("pinmux", prefix);
366
0
    if (!propname)
367
0
      return -ENOMEM;
368
0
    *count = dev_read_size(config, propname);
369
0
    free_name_with_prefix(propname, prefix);
370
0
    if (*count >= 0 && !(*count % sizeof(u32))) {
371
0
      *count /= sizeof(u32);
372
0
      return PST_PINMUX;
373
0
    }
374
0
  }
375
376
0
  *count = 0;
377
0
  return PST_NONE;
378
0
}
379
380
/**
381
 * pinctrl_generic_set_state_subnode() - apply all settings in config node
382
 *
383
 * @dev: pin controller device
384
 * @config: pseudo device pointing to config node
385
 * @prefix: device tree property prefix (e.g. vendor specific)
386
 * @return: 0 on success, or negative error code on failure
387
 */
388
static int pinctrl_generic_set_state_subnode(struct udevice *dev,
389
               struct udevice *config,
390
               const char *prefix)
391
0
{
392
0
  enum pinmux_subnode_type subnode_type;
393
0
  const char *propname;
394
0
  const char *name;
395
0
  int count, selector, i, ret, scratch;
396
0
  const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */
397
398
0
  subnode_type = pinctrl_generic_get_subnode_type(dev, config, prefix, &count);
399
400
0
  debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name,
401
0
        count);
402
403
0
  if (subnode_type == PST_PINMUX) {
404
0
    propname = alloc_name_with_prefix("pinmux", prefix);
405
0
    if (!propname)
406
0
      return -ENOMEM;
407
0
    pinmux_groups = dev_read_prop(config, propname, &scratch);
408
0
    free_name_with_prefix(propname, prefix);
409
0
    if (!pinmux_groups)
410
0
      return -EINVAL;
411
0
  }
412
413
0
  for (i = 0; i < count; i++) {
414
0
    switch (subnode_type) {
415
0
    case PST_PIN:
416
0
      propname = alloc_name_with_prefix("pins", prefix);
417
0
      if (!propname)
418
0
        return -ENOMEM;
419
0
      ret = dev_read_string_index(config, propname, i, &name);
420
0
      free_name_with_prefix(propname, prefix);
421
0
      if (ret)
422
0
        return ret;
423
0
      selector = pinctrl_pin_name_to_selector(dev, name);
424
0
      break;
425
0
    case PST_GROUP:
426
0
      propname = alloc_name_with_prefix("groups", prefix);
427
0
      if (!propname)
428
0
        return -ENOMEM;
429
0
      ret = dev_read_string_index(config, propname, i, &name);
430
0
      free_name_with_prefix(propname, prefix);
431
0
      if (ret)
432
0
        return ret;
433
0
      selector = pinctrl_group_name_to_selector(dev, name);
434
0
      break;
435
0
    case PST_PINMUX: {
436
0
      const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
437
0
      u32 pinmux_group = fdt32_to_cpu(pinmux_groups[i]);
438
439
      /* Checked for in pinctrl_generic_get_subnode_type */
440
0
      selector = ops->pinmux_property_set(dev, pinmux_group);
441
0
      break;
442
0
    }
443
0
    case PST_NONE:
444
0
    default:
445
      /* skip this node; may contain config child nodes */
446
0
      return 0;
447
0
    }
448
449
0
    if (selector < 0)
450
0
      return selector;
451
452
0
    ret = pinctrl_generic_set_state_one(dev, config, prefix,
453
0
                subnode_type, selector);
454
0
    if (ret)
455
0
      return ret;
456
0
  }
457
458
0
  return 0;
459
0
}
460
461
int pinctrl_generic_set_state_prefix(struct udevice *dev, struct udevice *config,
462
             const char *prefix)
463
0
{
464
0
  struct udevice *child;
465
0
  int ret;
466
467
0
  ret = pinctrl_generic_set_state_subnode(dev, config, prefix);
468
0
  if (ret)
469
0
    return ret;
470
471
0
  for (device_find_first_child(config, &child);
472
0
       child;
473
0
       device_find_next_child(&child)) {
474
0
    ret = pinctrl_generic_set_state_subnode(dev, child, prefix);
475
0
    if (ret)
476
0
      return ret;
477
0
  }
478
479
0
  return 0;
480
0
}
481
482
int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config)
483
0
{
484
  return pinctrl_generic_set_state_prefix(dev, config, NULL);
485
0
}