am5728通过DM框架配置GPIO管脚

来源:互联网 发布:cdp 知乎 编辑:程序博客网 时间:2024/06/05 02:49

以配置gpio3_31为例:
查看芯片手册:
这里写图片描述
这里gpio3_31为复用管脚,首先要配置寄存器将此管脚设置为gpio功能。
vim board/ti/am57xx/mux_data.h 所有多路复寄存器信息都在此定义:

const struct pad_conf_entry core_padconf_array_essential_x15[] = {    {GPMC_AD0, (M2 | PIN_INPUT | MANUAL_MODE)},   /*gpmc_ad0.vin3a_d0 */     {GPMC_AD1, (M2 | PIN_INPUT | MANUAL_MODE)},    /* gpmc_ad1.vin3a_d1 */     {GPMC_AD2, (M2 | PIN_INPUT | MANUAL_MODE)},     /* gpmc_ad2.vin3a_d2 */     {GPMC_AD3, (M2 | PIN_INPUT | MANUAL_MODE)},     /* gpmc_ad3.vin3a_d3 */     {GPMC_AD4, (M2 | PIN_INPUT | MANUAL_MODE)},     /* gpmc_ad4.vin3a_d4 */     ...     {VIN2A_FLD0, (M14 | PIN_INPUT_PULLUP)}, /* vin2a_fld0.gpio3_30 */     {VIN2A_HSYNC0, (M14 | PIN_INPUT_PULLUP)},       /* vin2a_hsync0.gpio    3_31 */     {VIN2A_VSYNC0, (M14 | PIN_INPUT)},      /* vin2a_vsync0.gpio4_0 */     {VIN2A_D0, (M11 | PIN_INPUT)},  /* vin2a_d0.pr1_uart0_rxd */     {VIN2A_D1, (M11 | PIN_OUTPUT)}, /* vin2a_d1.pr1_uart0_txd */     ...

接下来看看uboot代码中如何设置多路复用的:
vim board/ti/am57xx/board.c

512  *ctrl = &dra7xx_ctrl;660   pconf = core_padconf_array_essential_x15;661   pconf_sz =ARRAY_SIZE(core_padconf_array_essential_x15);678    /* Do the muxing here */679   do_set_mux32((*ctrl)->control_padconf_core_base, pconf, pconf_sz);

照猫画虎,自己的代码这样写:
1.定义结构体:

const struct pad_conf_entry my_gpio3_31[] = {    {VIN2A_HSYNC0, (M14 | PIN_OUTPUT_PULLDOWN)}, };

2.设置参数:

struct omap_sys_ctrl_regs const **ctrl = NULL;*ctrl = &dra7xx_ctrl;const struct pad_conf_entry *pconf = my_gpio3_31;nt pconf_sz = ARRAY_SIZE(my_gpio3_31);

3.调用do_set_mux32()函数设置多路复用

do_set_mux32((*ctrl)>control_padconf_core_base,pconf,pconf_sz);

这下用多路复用就设置好了。
配置好多路复用后,就可以调用gpio接口函数设置管脚的高低了。
虽然像gpio_request,gpio_direction_output 这样的老接口还可以用,这里用新的DM框架来配置GPIO口。

1)在设备树文件下添加节点
vim .config, 找到CONFIG_DEFAULT_DEVICE_TREE=”am57xx-beagle-x15”,说am5728用到的设备树文件为am57xx-beagle-x15.dts,在设备树文件下添加如下节点:

 88 /* my code start*/ 89         set_gpio { 90             compatible = "set_gpio,test"; 91             gpios = <&gpio3 31 GPIO_ACTIVE_HIGH>; 92         }; 93 /*my code end*/

2.通过fdt_node_offset_by_compatible函数找到该节点

struct gpio_desc gpio3_31_desc;int node;node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "set_gpio,test");

该函数通过”set_gpio,test”与设备树的compatible字段进行匹配,如果找到则返回相应的节点。
3.申请GPIO资源

int res = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0, &gpio3_31_desc, GPIOD_IS_OUT)

该函数通过node节点和gpios字段最终找到gpio3_31,并将这些信息保存到gpio3_31_desc结构体中。
4.设置gpio引脚

dm_gpio_set_value(&gpio3_31_desc, 0)

将此gpio管脚配置为高或低。

至此gpio3_31的配置完成。

可以在uboot中添加命令,通过参数配置任意一个gpio引脚,这里只将配置此引脚的命令添加到uboot中:
在cmd文件下创建setgpio.c文件:

static int do_setgpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]){    const struct pad_conf_entry my_gpio3_31[] = {        {VIN2A_HSYNC0, (M14 | PIN_OUTPUT_PULLDOWN)},    };    struct omap_sys_ctrl_regs const **ctrl = NULL;    *ctrl = &dra7xx_ctrl;    const struct pad_conf_entry *pconf = my_gpio3_31;    int pconf_sz = ARRAY_SIZE(my_gpio3_31);    do_set_mux32((*ctrl)->control_padconf_core_base, pconf, pconf_sz);    /*老版本GPIO接口*//*    if(gpio_request(95, "gpio3_31")){        printf("request resource error!\n");        return 0;    }    if(!strcmp(argv[1], "down")){        gpio_direction_output(95, 0);        }    else{        gpio_direction_output(95, 1);        }    gpio_free(95);*/    /*新版本GPIO接口*/    struct gpio_desc gpio3_31_desc;    int node;    struct udevice *dev = NULL;    node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "set_gpio,test");    if(node < 0){        printf("#################\n");        printf("node cannot find\n");        printf("##################\n");        return -1;    }    int res = gpio_request_by_name_nodev(gd->fdt_blob, node, "gpios", 0, &gpio3_31_desc, GPIOD_IS_OUT);    if(res){        printf("##################\n");        printf("request GPIO resource failure!\n");        printf("##################\n");        return -1;    }    dm_gpio_set_value(&gpio3_31_desc, (*argv[1] - '0'));    dm_gpio_free(dev, &gpio3_31_desc);    return 0;}U_BOOT_CMD(        setgpio, 2, 0, do_setgpio,         "set gpio3_31 pin",         "setgpio 0 - set the pins to low\n"         "setgpio 1 - set the pins to high\n");

在Makefile中添加:obj-y += setgpio.o
编译uboot便会有setgpio命令:
setgpio 0:将gpio3_31配置为低电平。
setgpio 1:将gpio3_31配置为高电平。

附录:DM框架下的GPIO接口

int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, struct gpio_desc *desc, int flags)
通过对应的udevice找到其dtsi节点中属性名为list_name的GPIO属性并转化为gpio_desc,并且request。

int gpio_request_by_name_nodev(const void *blob, int node, const char *list_name, int index, struct gpio_desc *desc, int flags)
通过对应的dtsi节点中属性名为list_name的GPIO属性并转化为gpio_desc,并且request。

int dm_gpio_request(struct gpio_desc *desc, const char *label)
申请gpio_desc描述的GPIO

int dm_gpio_get_value(const struct gpio_desc *desc)
获取gpio_desc描述的GPIO的值

int dm_gpio_set_value(const struct gpio_desc *desc, int value)
设置gpio_desc描述的GPIO的值

int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
设置gpio_desc描述的GPIO的输入输出方向,带标志

int dm_gpio_set_dir(struct gpio_desc *desc)
设置gpio_desc描述的GPIO的输入输出方向

static inline bool dm_gpio_is_valid(const struct gpio_desc *desc)
判断gpio_desc是否可用

原创粉丝点击