最近几天忙于做LCD显示驱动板的原理图和PCB,终于板子投了,大概周一能够收到就可以焊接调试了。
这几天也算是有时间看下驱动相关的东西,先总最简单的GPIO开始说起吧。首先分析下linux下操作imx6s芯片的大概过程和主要函数与宏定义。
不管uboot中还是linux下imx6的GPIO配置都要区分IOMUX和GPIO的配置,首先通过配置IOMUX寄存器,设置芯片的pad管脚为GPIO功能,然后通过GPIO寄存器来设置GPIO功能。
那么我们看下linux下和IOMUX配置相关的几个函数和宏定义:
在看这个之前要先看一个对引脚配置非常关键的64位的数据定义:
typedef u64 iomux_v3_cfg_t 64bit的数据定义 这个就是关于IOMUX/PAD的bit为的定义的组合,iomux_v3_cfg_t的数据域分布如下:MUX_CTRL_OFS: 0..11 (12) Mux控制寄存器地址偏移量,占用12个bit,分布为iomux_v3_cfg_t的第0-11bit PAD_CTRL_OFS: 12..23 (12) Pad控制寄存器地址偏移占用12个bit,分布为iomux_v3_cfg_t的第12-23bit SEL_INPUT_OFS: 24..35 (12) Select input地址偏移量,占用12个bit,分布为iomux_v3_cfg_t的第24-35bit MUX_MODE + SION: 36..40 (5) Mux模式和Software Input On Field.寄存器的设置,占据5位,其中mux mode占用3个bit,SION占用两个bit,分布为iomux_v3_cfg_t的36-40bit PAD_CTRL + NO_PAD_CTRL: 41..58 (18) Pad_ctrl寄存器配置占用18个bit,分布为iomux_v3_cfg_t的41-58bit SEL_INP: 59..62 (4) SEL_INP占用4个bit,分布为iomux_v3_cfg_t的59-62bit reserved: 63 (1) 这个iomux_v3_cfg_t 是后面几乎所有关于GPIO配置的地方都要用到的一个数据。好了,那下面我们先分析几个函数和宏定义
1.
IOMUX_PAD(PAD Control Offset, MUX ControlOffset, MUX Mode, Select Input Offset, Select Input, Pad Control) IOMUX_PAD后面几个参数的定义做如下分析:
PAD Control Offset:pad control register的地址偏移,这个寄存器主要配置引脚物理和电气特性,类似接口形式,上下拉,驱动能力,速度等。
MUX Control Offset:MUX control register的地址偏移,这个寄存器主要是配置引脚的输入路径和引脚的模式选择 ALT0-ALT7. MUX Mode:MUX mode数据,在MUX controlregisters中定义。000-111对应alt0-alt7。 Select Input Offset:MUX control register地址偏移,主要配置功能见上述表格。 Select Input:Select Input data,在select inputregisters定义。 Pad Control:Pad Control data,在Pad controlregisters中定义。 后面我们看看IOMUX_PAD的定义如下:
#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _sel_input_ofs, \
_sel_input, _pad_ctrl) \
(((iomux_v3_cfg_t)(_mux_ctrl_ofs) << MUX_CTRL_OFS_SHIFT) | \
((iomux_v3_cfg_t)(_mux_mode) << MUX_MODE_SHIFT) | \
((iomux_v3_cfg_t)(_pad_ctrl_ofs) << MUX_PAD_CTRL_OFS_SHIFT) | \
((iomux_v3_cfg_t)(_pad_ctrl) << MUX_PAD_CTRL_SHIFT) | \
((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \
((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT))
通过IOMUX_PAD的定义可以看出,这个就是一个宏定义,是一个用来生成iomux_v3_cfg_t 这个数据的方法的定义。
括号里的参数都是按照iomux_v3_cfg_t 的数据域进行不同位数的移位然后相或,来产生iomux_v3_cfg_t 。
那我们看代码中的如下定义:
#define MX6DL_PAD_EIM_A25__GPIO_5_2 IOMUX_PAD(0x0504, 0x0134, 5, 0x0000, 0, NO_PAD_CTRL)
其实这个定义就是针对EIM_A25生成一个iomux_v3_cfg_t数据。
以上只是生成了IOMUX/PAD的相关数据,那么怎么配置IOMUX和GPIO呢,那就继续看下面一个函数
2.int mxc_iomux_v3_setup_pad(iomux_v3_cfg_tpad){ u32mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT; u32mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT; u32sel_input_ofs = (pad & MUX_SEL_INPUT_OFS_MASK) >>MUX_SEL_INPUT_OFS_SHIFT; u32sel_input = (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT; u32pad_ctrl_ofs = (pad & MUX_PAD_CTRL_OFS_MASK) >>MUX_PAD_CTRL_OFS_SHIFT; u32pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT; if(mux_ctrl_ofs) __raw_writel(mux_mode,base + mux_ctrl_ofs); if(sel_input_ofs) __raw_writel(sel_input,base + sel_input_ofs); if(!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs) __raw_writel(pad_ctrl,base + pad_ctrl_ofs); return0; }
这个函数呢也还是围绕着iomux_v3_cfg_t这个64位的数据做文章,大家也都可以看到,基本就是从iomux_v3_cfg_t 中取出和实际引脚对应的mux_mode等实际值,然后通过__raw_writel ()函数来完成引脚功能的实际初始化。
好了到现在我们可以配置IOMUX了,但是如何操作GPIO呢,其实在这个源代码里面没有看见类似直接操作寄存器来操作GPIO输出的函数,因为毕竟到了linux下面直接访问寄存器已经不向uboot或者裸机操作那么简单了,那么我们如何操作GPIO呢,下面就来看下linux的GPIO number的导出。
在imx6下面有GPIO1-7组GPIO,在uboot和GPIO初始化时候可以使用寄存器基地址或者 iomux_v3_cfg_t 这个数据来操作GPIO,但是到了linux就要将GPIO1-7组的GPIO统一编号到linux下,那么如何进行编号呢,可能大家都看到了,在board_mx6q_riot.c文件中有很多类似#define RIOT_USER_LED IMX_GPIO_NR(5, 2)的定义,那么这个IMX_GPIO_NR又是什么呢,我们看看它的定义如下
#define IMX_GPIO_NR(bank, nr) (((bank) - 1) * 32 + (nr))
由此可见这是个将不同组的GPIO统一到linux下的GPIO number的计算公式,即:<GPIO Instance – 1> × 32 + <GPIO Port number>
比如说RIOT板子的用户LED这个GPIO的转换,IMX_GPIO_NR(5,2),就是说在imx6芯片中控制LED的引脚是GPIO5_2,那么转换到linux就是GPIO ((5-1)*32+2)=130,即linux的GPIO数是GPIO-130。
关于linux的GPIO操作我们可以在linux命令行中路径/sys/class/gpio/export中导出GPIO number,然后对GPIO进行操作,来控制GPIO输入和输出,比如刚才分析我们的LED控制引脚在linux下是GPIO-130,那我们就可以进行如下操作:
echo 130 > /sys/class/gpio/export
设置输出命令:
echo out > /sys/class/gpio/gpio30/direction
设置输出1和输出0:
echo 1 > /sys/class/gpio/gpio130/value
echo 0 > /sys/class/gpio/gpio130/value
但是在我们系统中,GPIO-130已经由系统注册为platform设备,所以使用GPIO export会提示资源繁忙无法配置,那在后续的文章中我们就继续分析如何在linux源码中进行GPIO的控制。
|