171 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			171 lines
		
	
	
		
			3.5 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 "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;
							 | 
						||
| 
								 | 
							
								}
							 |