]>
git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/pinctrl/pinctrl-uclass.c
2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
4 * SPDX-License-Identifier: GPL-2.0+
10 #include <linux/list.h>
11 #include <dm/device.h>
13 #include <dm/pinctrl.h>
14 #include <dm/uclass.h>
16 DECLARE_GLOBAL_DATA_PTR
;
18 #if CONFIG_IS_ENABLED(PINCTRL_FULL)
20 * pinctrl_config_one() - apply pinctrl settings for a single node
22 * @config: pin configuration node
23 * @return: 0 on success, or negative error code on failure
25 static int pinctrl_config_one(struct udevice
*config
)
27 struct udevice
*pctldev
;
28 const struct pinctrl_ops
*ops
;
32 pctldev
= dev_get_parent(pctldev
);
34 dev_err(config
, "could not find pctldev\n");
37 if (pctldev
->uclass
->uc_drv
->id
== UCLASS_PINCTRL
)
41 ops
= pinctrl_get_ops(pctldev
);
42 return ops
->set_state(pctldev
, config
);
46 * pinctrl_select_state_full() - full implementation of pinctrl_select_state
48 * @dev: peripheral device
49 * @statename: state name, like "default"
50 * @return: 0 on success, or negative error code on failure
52 static int pinctrl_select_state_full(struct udevice
*dev
, const char *statename
)
54 const void *fdt
= gd
->fdt_blob
;
55 int node
= dev
->of_offset
;
56 char propname
[32]; /* long enough */
60 struct udevice
*config
;
61 int state
, size
, i
, ret
;
63 state
= fdt_find_string(fdt
, node
, "pinctrl-names", statename
);
67 * If statename is not found in "pinctrl-names",
68 * assume statename is just the integer state ID.
70 state
= simple_strtoul(statename
, &end
, 10);
75 snprintf(propname
, sizeof(propname
), "pinctrl-%d", state
);
76 list
= fdt_getprop(fdt
, node
, propname
, &size
);
80 size
/= sizeof(*list
);
81 for (i
= 0; i
< size
; i
++) {
82 phandle
= fdt32_to_cpu(*list
++);
84 config_node
= fdt_node_offset_by_phandle(fdt
, phandle
);
85 if (config_node
< 0) {
86 dev_err(dev
, "prop %s index %d invalid phandle\n",
90 ret
= uclass_get_device_by_of_offset(UCLASS_PINCONFIG
,
91 config_node
, &config
);
95 ret
= pinctrl_config_one(config
);
104 * pinconfig_post-bind() - post binding for PINCONFIG uclass
105 * Recursively bind its children as pinconfig devices.
107 * @dev: pinconfig device
108 * @return: 0 on success, or negative error code on failure
110 static int pinconfig_post_bind(struct udevice
*dev
)
112 const void *fdt
= gd
->fdt_blob
;
113 int offset
= dev
->of_offset
;
117 for (offset
= fdt_first_subnode(fdt
, offset
);
119 offset
= fdt_next_subnode(fdt
, offset
)) {
121 * If this node has "compatible" property, this is not
122 * a pin configuration node, but a normal device. skip.
124 fdt_get_property(fdt
, offset
, "compatible", &ret
);
128 if (ret
!= -FDT_ERR_NOTFOUND
)
131 name
= fdt_get_name(fdt
, offset
, NULL
);
134 ret
= device_bind_driver_to_node(dev
, "pinconfig", name
,
143 UCLASS_DRIVER(pinconfig
) = {
144 .id
= UCLASS_PINCONFIG
,
145 .post_bind
= pinconfig_post_bind
,
149 U_BOOT_DRIVER(pinconfig_generic
) = {
151 .id
= UCLASS_PINCONFIG
,
155 static int pinctrl_select_state_full(struct udevice
*dev
, const char *statename
)
160 static int pinconfig_post_bind(struct udevice
*dev
)
167 * pinctrl_select_state_simple() - simple implementation of pinctrl_select_state
169 * @dev: peripheral device
170 * @return: 0 on success, or negative error code on failure
172 static int pinctrl_select_state_simple(struct udevice
*dev
)
174 struct udevice
*pctldev
;
175 struct pinctrl_ops
*ops
;
179 * For simplicity, assume the first device of PINCTRL uclass
180 * is the correct one. This is most likely OK as there is
181 * usually only one pinctrl device on the system.
183 ret
= uclass_get_device(UCLASS_PINCTRL
, 0, &pctldev
);
187 ops
= pinctrl_get_ops(pctldev
);
188 if (!ops
->set_state_simple
) {
189 dev_dbg(dev
, "set_state_simple op missing\n");
193 return ops
->set_state_simple(pctldev
, dev
);
196 int pinctrl_select_state(struct udevice
*dev
, const char *statename
)
199 * Try full-implemented pinctrl first.
200 * If it fails or is not implemented, try simple one.
202 if (pinctrl_select_state_full(dev
, statename
))
203 return pinctrl_select_state_simple(dev
);
208 int pinctrl_request(struct udevice
*dev
, int func
, int flags
)
210 struct pinctrl_ops
*ops
= pinctrl_get_ops(dev
);
215 return ops
->request(dev
, func
, flags
);
218 int pinctrl_request_noflags(struct udevice
*dev
, int func
)
220 return pinctrl_request(dev
, func
, 0);
223 int pinctrl_get_periph_id(struct udevice
*dev
, struct udevice
*periph
)
225 struct pinctrl_ops
*ops
= pinctrl_get_ops(dev
);
227 if (!ops
->get_periph_id
)
230 return ops
->get_periph_id(dev
, periph
);
234 * pinconfig_post-bind() - post binding for PINCTRL uclass
235 * Recursively bind child nodes as pinconfig devices in case of full pinctrl.
237 * @dev: pinctrl device
238 * @return: 0 on success, or negative error code on failure
240 static int pinctrl_post_bind(struct udevice
*dev
)
242 const struct pinctrl_ops
*ops
= pinctrl_get_ops(dev
);
245 dev_dbg(dev
, "ops is not set. Do not bind.\n");
250 * If set_state callback is set, we assume this pinctrl driver is the
251 * full implementation. In this case, its child nodes should be bound
252 * so that peripheral devices can easily search in parent devices
253 * during later DT-parsing.
256 return pinconfig_post_bind(dev
);
261 UCLASS_DRIVER(pinctrl
) = {
262 .id
= UCLASS_PINCTRL
,
263 .post_bind
= pinctrl_post_bind
,