IMX6 dts 配置GPIO

 

IMX6 有很多系列版本,芯片的寄存器有一些是不一样的,我使用的CPU具体的partnumber 为 FREESCALE_MCIMX6U5EVM10AC
 

需求:配置 引脚 GPIO6_IO04 为输出高电平。

 

IMX6 GPIO 介绍,根据 TRM Chapter 2 Memory Maps 可知。IMX6 有7组GPIO,每组32个引脚。Base Address如下:

GPIO7_BASE   0x020B4000 
GPIO6_BASE   0x020B0000 
GPIO5_BASE   0x020AC000 
GPIO4_BASE   0x020A8000 
GPIO3_BASE   0x020A4000 
GPIO2_BASE   0x020A0000 
GPIO1_BASE   0x0209C000 

 

1 GPIO 操作(memmory)

(1) 使能 gpio clocks 

     根据TRM,这款imx6 和imx6ull 不同,imx6ull 需要通过寄存器来配置,时能gpio的clocks ,如下

 

   不过 IMX6U5 这款,默认都是使能的,我在TRM里并没有找到直接配置的寄存器。应该不用配置。

(2) 设置引脚复用

     比如 GPIO6_IO04 这个引脚,在TRM里搜索 GPIO6_IO04 , 我们需要将此引脚配置成 ALT5 也就是GPIO的模式。

那就需要 配置 IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA18 这个寄存器

注意,一定要将 SION这个bit 设置为1 ,否则 从寄存器读出来的值 将一直为0 

(3) 设置上下拉参数

    TRM 搜索 CSI0_DAT18 , 我们需要配置 IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA18
 

正常GPIO, 可以设置为 0x1b0b0

(4)设置GPIO的方向 GPIOx_GDIR

       设置引脚方向,每位对应一个引脚, 1-output, 0-input

(5)设置GPIO的电平值  GPIOx_GDIR

     设置输出引脚的电平,每位对应一个引脚, 1-高电平, 0-低电平

 

2 设备树对GPIO的配置

      基于 linux-imx_4.14.98_2.0.0_ga 。 

     关于 IMX6 DTS的解析可参考 drivers/pinctrl/freescale/pinctrl-imx.c

     以配置引脚 GPIO6_IO04  为例。在 arch/arm/boot/dts/imx6dl-pinfunc.h 中搜索 GPIO6_IO04 ,可以看到这个引脚的6中复用功能,我们记住 其中GPIO的这一项,其他复用类似。

在设备树中添加,MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 其实已经代表了 复用关系, 0x1b0b0 是配置的上下拉参数。

 

如果要操作GPIO,可以使用GPIO子系统 

在linux在驱动中使用gpio_request时,io 端口号为 IMX_GPIO_NR(6,4)=32×(6-1)+4=164;

在arch/arm/mach-imx/hardware.h,IMX_GPIO_NR定义为

#define IMX_GPIO_NR(bank, nr)        (((bank) - 1) * 32 + (nr))

提供一个example

#include <linux/gpio.h>

#define IMX_GPIO_NR(bank, nr)        (((bank) - 1) * 32 + (nr))

#define MINI_PCIE_POWER_RESET_DELAY    5000 // 5000 ms

static int gpio_set_val( int base, int num, int value)
{
	int gpio = 32*base + num;
	if (gpio_request_one( gpio , GPIOF_OUT_INIT_LOW, "gpio_out") < 0) {
		pr_err("Failed to request GPIO%d for GPIO%d_%d\n", gpio, base,num);
		return -1;
	}
	gpio_set_value( gpio, value); 
	//gpio_free( gpio );
	
	return 0;
}


static int gpio_reset_one( int base, int num, int time)
{
	int gpio = 32*base + num;
	if (gpio_request_one( gpio, GPIOF_OUT_INIT_HIGH, "gpio_out") < 0) {
		pr_err("Failed to request GPIO%d for GPIO%d_%d\n", gpio, base,num);
		return -1;
	}
	gpio_set_value( gpio, 1); 
	mdelay( 100 );

	gpio_set_value( gpio, 0); 
	mdelay( time );

	gpio_set_value( gpio, 1); 
	mdelay( 100 );
	
	//gpio_free( gpio );
	return 0;
}

gpio_reset_one(6, 4, MINI_PCIE_POWER_RESET_DELAY);

注意,如果free掉gpio 之后,gpio的电平值将会发生变化,不受控制。

 

再分享一个通过shell 在应用层来读取或者配置GPIO的方法,前提是在dts里面已经配置好复用模式。

 

#!/bin/sh

if [ "$#" != "2" ] && [ "$#" != "3" ];then
   echo "usage of read :$0 2 25"
   echo "usage of write :$0 2 25 0"
   echo "usage of reset :$0 2 25 reset"
   exit -1
fi

base=$1
num=$2

case $base in
        1)
            PHY_ADDRESS=0x0209C000
            ;;
        2)
            PHY_ADDRESS=0x020A0000
            ;;
        3)
            PHY_ADDRESS=0x020A4000
            ;;
        4)
            PHY_ADDRESS=0x020A8000
            ;;
        5)
            PHY_ADDRESS=0x020AC000
            ;;
        6)
            PHY_ADDRESS=0x020B0000
            ;;
        7)
            PHY_ADDRESS=0x020B4000
            ;;
        *)
            echo "base error"
            exit -1
esac

DIR_REG=$[$PHY_ADDRESS+0x4]
DATA_REG=$[$PHY_ADDRESS+0x0]

DIR_VAL=`devmem $DIR_REG`
DATA_VAL=`devmem $DATA_REG`

bit_set=$((1<<num))
bit_clear=$((~(1<<num) & 0xFFFFFFFF))

#printf "bit_set = 0x%x\n" $bit_set
#printf "bit_clear = 0x%x\n" $bit_clear

GPIO_READ()
{
  if [ $(( DIR_VAL&(1<<num))) -eq $((1<<num)) ];then
      DIR="out"
  else
      DIR="in"
  fi

  if [ $(( DATA_VAL&(1<<num))) -eq $((1<<num)) ];then
      VAL=1
  else
      VAL=0
  fi
   printf "Get GPIO%d DIR_REG :0x%x[ 0x%x ] GPIO%d_%d = %s\n" $base $DIR_REG $DIR_VAL $base $num $DIR
   printf "Get GPIO%d DATA_REG :0x%x[ 0x%x ] GPIO%d_%d = %d\n" $base $DATA_REG $DATA_VAL $base $num $VAL
}

GPIO_Set_High()
{
   # set to out_put
   DIR_VAL=$(( $DIR_VAL | $bit_set ))
   devmem $DIR_REG 32 $DIR_VAL

   DATA_VAL=$(( $DATA_VAL | $bit_set ))
   devmem $DATA_REG 32 $DATA_VAL
}

GPIO_Set_Low()
{
   # set to out_put
   DIR_VAL=$(( $DIR_VAL | $bit_set ))
   devmem $DIR_REG 32 $DIR_VAL

   DATA_VAL=$(( $DATA_VAL & $bit_clear ))
   devmem $DATA_REG 32 $DATA_VAL
}

#printf "=========Before===========\n"
#GPIO_READ

if [ "$#" == "2" ];then
   GPIO_READ
   exit -1
fi

if [ "$3" == "1" ];then
    GPIO_Set_High
elif [ "$3" == "0" ];then
    GPIO_Set_Low
elif [ "$3" == "reset" ];then
    GPIO_Set_High
        sleep 0.5
    GPIO_Set_Low
        sleep 0.5
    GPIO_Set_High
        sleep 0.5
fi

使用方法如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值