[component][drivers]add pinctrl/pin-irqchip (#8383)

This commit is contained in:
zms123456 2024-02-29 22:27:27 +08:00 committed by GitHub
parent 195f94ef1d
commit 97c5edf947
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 847 additions and 7 deletions

View File

@ -344,10 +344,6 @@ config RT_USING_PHY
bool "Using ethernet phy device drivers" bool "Using ethernet phy device drivers"
default n default n
config RT_USING_PIN
bool "Using generic GPIO device drivers"
default n
config RT_USING_ADC config RT_USING_ADC
bool "Using ADC device drivers" bool "Using ADC device drivers"
default n default n
@ -970,6 +966,8 @@ menuconfig RT_USING_VIRTIO
source "$RTT_DIR/components/drivers/ofw/Kconfig" source "$RTT_DIR/components/drivers/ofw/Kconfig"
source "$RTT_DIR/components/drivers/pic/Kconfig" source "$RTT_DIR/components/drivers/pic/Kconfig"
source "$RTT_DIR/components/drivers/pin/Kconfig"
source "$RTT_DIR/components/drivers/pinctrl/Kconfig"
source "$RTT_DIR/components/drivers/ktime/Kconfig" source "$RTT_DIR/components/drivers/ktime/Kconfig"
source "$RTT_DIR/components/drivers/clk/Kconfig" source "$RTT_DIR/components/drivers/clk/Kconfig"

View File

@ -18,10 +18,25 @@
extern "C" { extern "C" {
#endif #endif
#ifdef RT_USING_DM
#include <drivers/pic.h>
struct rt_pin_irqchip
{
struct rt_pic parent;
int irq;
rt_base_t pin_range[2];
};
#endif /* RT_USING_DM */
/* pin device and operations for RT-Thread */ /* pin device and operations for RT-Thread */
struct rt_device_pin struct rt_device_pin
{ {
struct rt_device parent; struct rt_device parent;
#ifdef RT_USING_DM
struct rt_pin_irqchip irqchip;
#endif /* RT_USING_DM */
const struct rt_pin_ops *ops; const struct rt_pin_ops *ops;
}; };
@ -36,6 +51,39 @@ struct rt_device_pin
#define PIN_MODE_INPUT_PULLDOWN 0x03 #define PIN_MODE_INPUT_PULLDOWN 0x03
#define PIN_MODE_OUTPUT_OD 0x04 #define PIN_MODE_OUTPUT_OD 0x04
#ifdef RT_USING_PINCTRL
enum
{
PIN_CONFIG_BIAS_BUS_HOLD,
PIN_CONFIG_BIAS_DISABLE,
PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
PIN_CONFIG_BIAS_PULL_DOWN,
PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
PIN_CONFIG_BIAS_PULL_UP,
PIN_CONFIG_DRIVE_OPEN_DRAIN,
PIN_CONFIG_DRIVE_OPEN_SOURCE,
PIN_CONFIG_DRIVE_PUSH_PULL,
PIN_CONFIG_DRIVE_STRENGTH,
PIN_CONFIG_DRIVE_STRENGTH_UA,
PIN_CONFIG_INPUT_DEBOUNCE,
PIN_CONFIG_INPUT_ENABLE,
PIN_CONFIG_INPUT_SCHMITT,
PIN_CONFIG_INPUT_SCHMITT_ENABLE,
PIN_CONFIG_MODE_LOW_POWER,
PIN_CONFIG_MODE_PWM,
PIN_CONFIG_OUTPUT,
PIN_CONFIG_OUTPUT_ENABLE,
PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS,
PIN_CONFIG_PERSIST_STATE,
PIN_CONFIG_POWER_SOURCE,
PIN_CONFIG_SKEW_DELAY,
PIN_CONFIG_SLEEP_HARDWARE_STATE,
PIN_CONFIG_SLEW_RATE,
PIN_CONFIG_END = 0x7f,
PIN_CONFIG_MAX = 0xff,
};
#endif /* RT_USING_PINCTRL */
#define PIN_IRQ_MODE_RISING 0x00 #define PIN_IRQ_MODE_RISING 0x00
#define PIN_IRQ_MODE_FALLING 0x01 #define PIN_IRQ_MODE_FALLING 0x01
#define PIN_IRQ_MODE_RISING_FALLING 0x02 #define PIN_IRQ_MODE_RISING_FALLING 0x02
@ -66,6 +114,16 @@ struct rt_pin_irq_hdr
void (*hdr)(void *args); void (*hdr)(void *args);
void *args; void *args;
}; };
#ifdef RT_USING_PINCTRL
struct rt_pin_ctrl_conf_params
{
const char *propname;
rt_uint32_t param;
rt_uint32_t default_value;
};
#endif /* RT_USING_PINCTRL */
struct rt_pin_ops struct rt_pin_ops
{ {
void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode); void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode);
@ -76,6 +134,13 @@ struct rt_pin_ops
rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_base_t pin); rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_base_t pin);
rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled); rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled);
rt_base_t (*pin_get)(const char *name); rt_base_t (*pin_get)(const char *name);
#ifdef RT_USING_DM
rt_err_t (*pin_irq_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode);
rt_ssize_t (*pin_parse)(struct rt_device *device, struct rt_ofw_cell_args *args, rt_uint32_t *flags);
#endif
#ifdef RT_USING_PINCTRL
rt_err_t (*pin_ctrl_confs_apply)(struct rt_device *device, void *fw_conf_np);
#endif /* RT_USING_PINCTRL */
}; };
int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data); int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data);
@ -88,6 +153,24 @@ rt_err_t rt_pin_attach_irq(rt_base_t pin, rt_uint8_t mode,
rt_err_t rt_pin_detach_irq(rt_base_t pin); rt_err_t rt_pin_detach_irq(rt_base_t pin);
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint8_t enabled); rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint8_t enabled);
#ifdef RT_USING_DM
rt_ssize_t rt_pin_get_named_pin(struct rt_device *dev, const char *propname, int index,
rt_uint8_t *out_mode, rt_uint8_t *out_value);
rt_ssize_t rt_pin_get_named_pin_count(struct rt_device *dev, const char *propname);
#ifdef RT_USING_OFW
rt_ssize_t rt_ofw_get_named_pin(struct rt_ofw_node *np, const char *propname, int index,
rt_uint8_t *out_mode, rt_uint8_t *out_value);
rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname);
#endif
#endif /* RT_USING_DM */
#ifdef RT_USING_PINCTRL
rt_ssize_t rt_pin_ctrl_confs_lookup(struct rt_device *device, const char *name);
rt_err_t rt_pin_ctrl_confs_apply(struct rt_device *device, int index);
rt_err_t rt_pin_ctrl_confs_apply_by_name(struct rt_device *device, const char *name);
#endif /* RT_USING_PINCTRL */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DT_BINDINGS_PIN_PIN_H__
#define __DT_BINDINGS_PIN_PIN_H__
/* Bit 0 express polarity */
#define PIN_ACTIVE_HIGH 0
#define PIN_ACTIVE_LOW 1
/* Bit 1 express single-endedness */
#define PIN_PUSH_PULL 0
#define PIN_SINGLE_ENDED 2
/* Bit 2 express Open drain or open source */
#define PIN_LINE_OPEN_SOURCE 0
#define PIN_LINE_OPEN_DRAIN 4
/*
* Open Drain/Collector is the combination of single-ended open drain interface.
* Open Source/Emitter is the combination of single-ended open source interface.
*/
#define PIN_OPEN_DRAIN (PIN_SINGLE_ENDED | PIN_LINE_OPEN_DRAIN)
#define PIN_OPEN_SOURCE (PIN_SINGLE_ENDED | PIN_LINE_OPEN_SOURCE)
/* Bit 3 express PIN suspend/resume and reset persistence */
#define PIN_PERSISTENT 0
#define PIN_TRANSITORY 8
/* Bit 4 express pull up */
#define PIN_PULL_UP 16
/* Bit 5 express pull down */
#define PIN_PULL_DOWN 32
/* Bit 6 express pull disable */
#define PIN_PULL_DISABLE 64
#endif /* __DT_BINDINGS_PIN_PIN_H__ */

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __DT_BINDINGS_PIN_STATE_H__
#define __DT_BINDINGS_PIN_STATE_H__
#define PIND_FLAGS_BIT_DIR_SET (1 << 0)
#define PIND_FLAGS_BIT_DIR_OUT (1 << 1)
#define PIND_FLAGS_BIT_DIR_VAL (1 << 2)
#define PIND_FLAGS_BIT_OPEN_DRAIN (1 << 3)
#define PIND_FLAGS_BIT_NONEXCLUSIVE (1 << 4)
/* Don't change anything */
#define PIND_ASIS 0
/* Set lines to input mode */
#define PIND_IN PIND_FLAGS_BIT_DIR_SET
/* Set lines to output and drive them low */
#define PIND_OUT_LOW (PIND_FLAGS_BIT_DIR_SET | PIND_FLAGS_BIT_DIR_OUT)
/* Set lines to output and drive them high */
#define PIND_OUT_HIGH (PIND_FLAGS_BIT_DIR_SET | PIND_FLAGS_BIT_DIR_OUT | PIND_FLAGS_BIT_DIR_VAL)
/* Set lines to open-drain output and drive them low */
#define PIND_OUT_LOW_OPEN_DRAIN (PIND_OUT_LOW | PIND_FLAGS_BIT_OPEN_DRAIN)
/* Set lines to open-drain output and drive them high */
#define PIND_OUT_HIGH_OPEN_DRAIN (PIND_OUT_HIGH | PIND_FLAGS_BIT_OPEN_DRAIN)
#endif /* __DT_BINDINGS_PIN_STATE_H__ */

View File

@ -5,9 +5,6 @@ src = []
CPPPATH = [cwd + '/../include'] CPPPATH = [cwd + '/../include']
group = [] group = []
if GetDepend(['RT_USING_PIN']):
src = src + ['pin.c']
if GetDepend(['RT_USING_ADC']): if GetDepend(['RT_USING_ADC']):
src = src + ['adc.c'] src = src + ['adc.c']

3
components/drivers/pin/Kconfig Executable file
View File

@ -0,0 +1,3 @@
menuconfig RT_USING_PIN
bool "Using Generic GPIO device drivers"
default y

View File

@ -0,0 +1,21 @@
from building import *
group = []
if not GetDepend(['RT_USING_PIN']):
Return('group')
cwd = GetCurrentDir()
CPPPATH = [cwd + '/../include']
src = ['pin.c']
if GetDepend(['RT_USING_DM']):
src += ['pin_dm.c']
if GetDepend(['RT_USING_OFW']):
src += ['pin_ofw.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,220 @@
/*
* 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 "pin_dm.h"
static void pin_dm_irq_mask(struct rt_pic_irq *pirq)
{
struct rt_device_pin *gpio = pirq->pic->priv_data;
gpio->ops->pin_irq_enable(&gpio->parent, pirq->hwirq, 0);
}
static void pin_dm_irq_unmask(struct rt_pic_irq *pirq)
{
struct rt_device_pin *gpio = pirq->pic->priv_data;
gpio->ops->pin_irq_enable(&gpio->parent, pirq->hwirq, 1);
}
static rt_err_t pin_dm_irq_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode)
{
rt_uint8_t pin_mode;
struct rt_device_pin *gpio = pirq->pic->priv_data;
switch (mode)
{
case RT_IRQ_MODE_EDGE_RISING:
pin_mode = PIN_IRQ_MODE_RISING;
break;
case RT_IRQ_MODE_EDGE_FALLING:
pin_mode = PIN_IRQ_MODE_FALLING;
break;
case RT_IRQ_MODE_EDGE_BOTH:
pin_mode = PIN_IRQ_MODE_RISING_FALLING;
break;
case RT_IRQ_MODE_LEVEL_HIGH:
pin_mode = PIN_IRQ_MODE_HIGH_LEVEL;
break;
case RT_IRQ_MODE_LEVEL_LOW:
pin_mode = PIN_IRQ_MODE_LOW_LEVEL;
break;
default:
return -RT_ENOSYS;
}
return gpio->ops->pin_irq_mode(&gpio->parent, pirq->hwirq, pin_mode);
}
static int pin_dm_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
{
int irq = -1;
struct rt_device_pin *gpio = pic->priv_data;
struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq);
if (pirq)
{
irq = rt_pic_config_irq(pic, hwirq, hwirq);
if (irq >= 0)
{
rt_pic_cascade(pirq, gpio->irqchip.irq);
rt_pic_irq_set_triger_mode(irq, mode);
}
}
return irq;
}
static rt_err_t pin_dm_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
{
rt_err_t err = RT_EOK;
if (args->args_count == 2)
{
out_pirq->hwirq = args->args[0];
out_pirq->mode = args->args[1] & RT_IRQ_MODE_MASK;
}
else
{
err = -RT_EINVAL;
}
return err;
}
static struct rt_pic_ops pin_dm_ops =
{
.name = "GPIO",
.irq_enable = pin_dm_irq_mask,
.irq_disable = pin_dm_irq_unmask,
.irq_mask = pin_dm_irq_mask,
.irq_unmask = pin_dm_irq_unmask,
.irq_set_triger_mode = pin_dm_irq_set_triger_mode,
.irq_map = pin_dm_irq_map,
.irq_parse = pin_dm_irq_parse,
};
rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin)
{
rt_err_t err;
if (gpio)
{
struct rt_pin_irqchip *irqchip = &gpio->irqchip;
if (pin >= irqchip->pin_range[0] && pin <= irqchip->pin_range[1])
{
struct rt_pic_irq *pirq;
pirq = rt_pic_find_irq(&irqchip->parent, pin - irqchip->pin_range[0]);
if (pirq->irq >= 0)
{
err = rt_pic_handle_isr(pirq);
}
else
{
err = -RT_EINVAL;
}
}
else
{
err = -RT_EINVAL;
}
}
else
{
err = -RT_EINVAL;
}
return err;
}
rt_err_t pin_pic_init(struct rt_device_pin *gpio)
{
rt_err_t err;
if (gpio)
{
struct rt_pin_irqchip *irqchip = &gpio->irqchip;
if (irqchip->pin_range[0] >= 0 && irqchip->pin_range[1] >= irqchip->pin_range[0])
{
struct rt_pic *pic = &irqchip->parent;
rt_size_t pin_nr = irqchip->pin_range[1] - irqchip->pin_range[0] + 1;
pic->priv_data = gpio;
pic->ops = &pin_dm_ops;
/* Make sure the type of gpio for pic */
gpio->parent.parent.type = RT_Object_Class_Device;
rt_pic_default_name(&irqchip->parent);
err = rt_pic_linear_irq(pic, pin_nr);
rt_pic_user_extends(pic);
}
else
{
err = -RT_EINVAL;
}
}
else
{
err = -RT_EINVAL;
}
return err;
}
rt_ssize_t rt_pin_get_named_pin(struct rt_device *dev, const char *propname, int index,
rt_uint8_t *out_mode, rt_uint8_t *out_value)
{
rt_ssize_t res = -RT_ENOSYS;
RT_ASSERT(dev != RT_NULL);
#ifdef RT_USING_OFW
if (dev->ofw_node)
{
res = rt_ofw_get_named_pin(dev->ofw_node, propname, index, out_mode, out_value);
}
else
{
res = -RT_EINVAL;
}
#endif /* RT_USING_OFW */
return res;
}
rt_ssize_t rt_pin_get_named_pin_count(struct rt_device *dev, const char *propname)
{
rt_ssize_t count = -RT_ENOSYS;
RT_ASSERT(dev != RT_NULL);
#ifdef RT_USING_OFW
if (dev->ofw_node)
{
count = rt_ofw_get_named_pin_count(dev->ofw_node, propname);
}
else
{
count = -RT_EINVAL;
}
#endif /* RT_USING_OFW */
return count;
}

View File

@ -0,0 +1,21 @@
/*
* 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
*/
#ifndef __PIN_DM_H__
#define __PIN_DM_H__
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin);
rt_err_t pin_pic_init(struct rt_device_pin *gpio);
#endif /* __PIN_DM_H__ */

View File

@ -0,0 +1,170 @@
/*
* 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 <dt-bindings/pin/pin.h>
#include "pin_dm.h"
static const char * const gpio_suffixes[] =
{
"gpios", "gpio"
};
rt_ssize_t rt_ofw_get_named_pin(struct rt_ofw_node *np, const char *propname, int index,
rt_uint8_t *out_mode, rt_uint8_t *out_value)
{
rt_ssize_t pin;
rt_uint8_t mode;
rt_uint8_t value;
rt_uint32_t flags;
char gpios_name[64];
struct rt_device_pin *pin_dev;
struct rt_ofw_node *pin_dev_np;
struct rt_ofw_cell_args pin_args;
if (!np && index < 0)
{
return -RT_EINVAL;
}
for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i)
{
if (propname)
{
rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]);
}
else
{
rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]);
}
pin = rt_ofw_parse_phandle_cells(np, gpios_name, "#gpio-cells", index, &pin_args);
if (pin >= 0)
{
break;
}
}
if (pin < 0)
{
return pin;
}
pin_dev_np = pin_args.data;
pin_dev = rt_ofw_data(pin_dev_np);
if (!pin_dev)
{
pin = -RT_ERROR;
goto _out_converts;
}
value = PIN_LOW;
mode = PIN_MODE_OUTPUT;
if (pin_dev->ops->pin_parse)
{
pin = pin_dev->ops->pin_parse(&pin_dev->parent, &pin_args, &flags);
}
else
{
/*
* We always assume that the args[0] is the pin number if driver not
* implemented `pin_parse`.
*/
pin = pin_args.args[0];
goto _out_converts;
}
if (out_mode)
{
if (flags & PIN_OPEN_DRAIN)
{
mode = PIN_MODE_OUTPUT_OD;
}
switch (flags & RT_GENMASK(6, 4))
{
case PIN_PULL_UP:
mode = PIN_MODE_INPUT_PULLUP;
break;
case PIN_PULL_DOWN:
mode = PIN_MODE_INPUT_PULLDOWN;
break;
case PIN_PULL_DISABLE:
mode = PIN_MODE_INPUT;
break;
}
}
if (out_value)
{
if (flags == (PIN_ACTIVE_HIGH | PIN_PUSH_PULL))
{
value = PIN_HIGH;
}
else if (flags == (PIN_ACTIVE_LOW | PIN_PUSH_PULL))
{
value = PIN_LOW;
}
}
_out_converts:
rt_ofw_node_put(pin_dev_np);
if (out_mode)
{
*out_mode = mode;
}
if (out_value)
{
*out_value = value;
}
return pin;
}
rt_ssize_t rt_ofw_get_named_pin_count(struct rt_ofw_node *np, const char *propname)
{
char gpios_name[64];
rt_ssize_t count = 0;
if (!np || !propname)
{
return -RT_EINVAL;
}
for (int i = 0; i < RT_ARRAY_SIZE(gpio_suffixes); ++i)
{
if (propname)
{
rt_snprintf(gpios_name, sizeof(gpios_name), "%s-%s", propname, gpio_suffixes[i]);
}
else
{
rt_snprintf(gpios_name, sizeof(gpios_name), "%s", gpio_suffixes[i]);
}
count = rt_ofw_count_phandle_cells(np, propname, "#gpio-cells");
if (count > 0)
{
break;
}
}
return count;
}

View File

@ -0,0 +1,6 @@
menuconfig RT_USING_PINCTRL
bool "Using Pin controllers device drivers"
depends on RT_USING_DM
depends on RT_USING_PIN
default n

View File

@ -0,0 +1,23 @@
from building import *
group = []
objs = []
if not GetDepend(['RT_USING_PINCTRL']):
Return('group')
cwd = GetCurrentDir()
list = os.listdir(cwd)
CPPPATH = [cwd + '/../include']
src = ['pinctrl.c']
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
objs = objs + group
Return('objs')

View File

@ -0,0 +1,227 @@
/*
* 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 <rtthread.h>
#include <rtservice.h>
#include <rtdevice.h>
#define DBG_TAG "rtdm.pinctrl"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#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;
}