171 lines
3.3 KiB
C
171 lines
3.3 KiB
C
/*
|
|
* 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 "dev_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 = -1;
|
|
rt_uint8_t mode;
|
|
rt_uint8_t value;
|
|
rt_uint32_t flags;
|
|
char gpios_name[64];
|
|
struct rt_device_pin *pin_dev = 0;
|
|
struct rt_ofw_node *pin_dev_np = 0;
|
|
struct rt_ofw_cell_args pin_args = {0};
|
|
|
|
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;
|
|
}
|