/* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-11-26 GuEe-GUI first version */ #include #include #include #define DBG_TAG "rtdm.pinctrl" #define DBG_LVL DBG_INFO #include #ifdef RT_USING_OFW static rt_err_t ofw_pin_ctrl_confs_apply(struct rt_ofw_node *np, int index) { rt_err_t err = -RT_EEMPTY; rt_phandle phandle; const fdt32_t *cell; struct rt_ofw_prop *prop; char pinctrl_n_name[sizeof("pinctrl-0")]; rt_sprintf(pinctrl_n_name, "pinctrl-%d", index); index = 0; rt_ofw_foreach_prop_u32(np, pinctrl_n_name, prop, cell, phandle) { struct rt_device_pin *pinctrl = RT_NULL; struct rt_ofw_node *conf_np, *pinctrl_np; conf_np = pinctrl_np = rt_ofw_find_node_by_phandle(phandle); if (!conf_np) { err = -RT_EIO; break; } /* * We always assume the phandle in pinctrl-N is the pinctrl-device * node's child node. If not, we need a better way to find it: * * / { * serial@4600 { * device_type = "serial"; * reg = <0x4600 0x100>; * clock-frequency = <0>; * pinctrl-names = "default"; * pinctrl-0 = <&uart_pin>; * }; * * i2c@4700 { * reg = <0x4700 0x100>; * pinctrl-names = "default"; * pinctrl-0 = <&i2c_pin_scl, &i2c_pin_sda>; * }; * * pinctrl: pinctrl { * * uart_pin { * multi,pins = * <0 PD0 1 &uart_rx_pull_up>, * <0 PD1 1 &uart_tx_pull_up>; * }; * * i2c_pin_scl { * single,pins = <0 PB1>; * pull = <&i2c_pull_none_smt>; * function = <1>; * }; * * i2c_pin_sda { * single,pins = <0 PB2>; * pull = <&i2c_pull_none_smt>; * function = <1>; * }; * }; * } */ rt_ofw_foreach_parent_node(pinctrl_np) { if (rt_ofw_prop_read_bool(pinctrl_np, "compatible")) { break; } } if (pinctrl_np) { pinctrl = rt_ofw_data(pinctrl_np); rt_ofw_node_put(pinctrl_np); } if (!pinctrl || !pinctrl->ops || !pinctrl->ops->pin_ctrl_confs_apply) { if (index) { err = -RT_EEMPTY; } else { err = -RT_ERROR; } rt_ofw_node_put(conf_np); break; } err = pinctrl->ops->pin_ctrl_confs_apply(&pinctrl->parent, conf_np); rt_ofw_node_put(conf_np); if (err) { break; } ++index; } return err; } static int ofw_pin_ctrl_confs_lookup(struct rt_ofw_node *np, const char *name) { return rt_ofw_prop_index_of_string(np, "pinctrl-names", name); } static rt_err_t ofw_pin_ctrl_confs_apply_by_name(struct rt_ofw_node *np, const char *name) { int index; rt_err_t err; index = ofw_pin_ctrl_confs_lookup(np, name); if (index >= 0) { err = ofw_pin_ctrl_confs_apply(np, index); } else { err = -RT_EEMPTY; } return err; } #endif /* RT_USING_OFW */ rt_ssize_t rt_pin_ctrl_confs_lookup(struct rt_device *device, const char *name) { rt_ssize_t res; if (device && name) { res = -RT_ENOSYS; #ifdef RT_USING_OFW if (device->ofw_node) { res = ofw_pin_ctrl_confs_lookup(device->ofw_node, name); } #endif /* RT_USING_OFW */ } else { res = -RT_EINVAL; } return res; } rt_err_t rt_pin_ctrl_confs_apply(struct rt_device *device, int index) { rt_err_t err; if (device && index >= 0) { err = -RT_ENOSYS; #ifdef RT_USING_OFW if (device->ofw_node) { err = ofw_pin_ctrl_confs_apply(device->ofw_node, index); } #endif /* RT_USING_OFW */ } else { err = -RT_EINVAL; } return err; } rt_err_t rt_pin_ctrl_confs_apply_by_name(struct rt_device *device, const char *name) { rt_err_t err; if (device) { if (!name) { name = "default"; } err = -RT_ENOSYS; #ifdef RT_USING_OFW if (device->ofw_node) { err = ofw_pin_ctrl_confs_apply_by_name(device->ofw_node, name); } #endif /* RT_USING_OFW */ } else { err = -RT_EINVAL; } return err; }