Blackrose's Blog Blackrose's Blog

imx535中IOMUX控制器

in technologyread (294) 文章转载请注明来源!

公司做项目,所以就外购了开发板,结果因为视频驱动问题一直无法调通,最后决定不再等客服了,自己来搞了。
Freescale的这块芯片,灰常的强大,自身集成了大量的功能,IPU、VPU、USB什么的,但是芯片规格却很小,所以发热量也很大。以前写裸机程序都是按步骤做,结果这次不太一样了。
裸机程序编写步骤:
1.配置复用脚到相应外设
2.配置外设的参数
3.启动外设

这里是大体的步骤,之前接触过友善和海思的芯片,但只在2440上写过裸机。对复用的理解就是当管脚不够用时,多个功能可以同时使用一个管脚,所以在使用相应外设时,要设置管脚的属性。这样是没错,但是当功能太多时,可能会出现一个管脚多于4种以上的功能,这就变得有些麻烦了。所以,imx535上的IOMUXC的出现就是解决这个问题。那么,具体是怎么解决这个问题呢?
芯片的功能很多,那么就有不同功能的针脚重叠,而实际上,每个功能需要配置多个pin才能使用,而每一个pin的不同意义,称为mode。假如要使用UART功能,直接配置RXD、TXD就好了,先确定相应管脚是RXD、TXD功能。
1.配置管脚到相应功能上,即mode
2.配置管脚的电平有效方式,即pull up/down

imx535芯片把一个针脚的不同功能称为ALT mode,最多有8个ALT modes。每种功能称为block。而多个功能block,又放在一个pad中,这样pad中blocks的针脚是大多相同,pad只去管理针脚的modes就可以了,即pad Register。
芯片中有多个pad,所以用一个IOMUXC不好管理,就有了IOMUXC cell,对应每个pad,用来配置pull up/down。

IOMUXC有4种register
GPR,选择SOC上的通用属性的模式,但与IOMUXC没有关系
Observability Register,用来作测试用
Software MUX Control Register, 配置IOMUXC的复用,并且“连接”到PAD上的相应功能
PAD setting Register,控制PAD配置,多个PAD的设置会被分组放在同一个Register中,配置时会影响分组中的其它PAD

IOMUXC_SW_MUX_CTL_PAD_,控制复用模式
IOMUXC_SW_PAD_CTL_PAD_,配置具体的某个PAD

下面来分析代码复用是怎么设置的

arch/arm/mach-mx5/mx53_smd.c
1963 MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
1964     /* Maintainer: Freescale Semiconductor, Inc. */
1965     .fixup = fixup_mxc_board,
1966     .map_io = mx5_map_io,
1967     .init_irq = mx5_init_irq,
1968     .init_machine = mxc_board_init,
1969     .timer = &mxc_timer,
1970 MACHINE_END

mxc_board_init会在启动时被调用,而它又会调用mx53_smd_io_init()

arch/arm/mach-mx5/mx53_smd.c
1418 static void __init mx53_smd_io_init(void)
1419 {
1420 
1421     mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
1422                     ARRAY_SIZE(mx53_smd_pads));
1423     mx53_pads_init();
1424 

1475 }

这里出现了mx53_smd_pads,是个结构体

 167 static struct pad_desc mx53_smd_pads[] = {
 168     /* UART 1*/     
 169     MX53_PAD_CSI0_D10__UART1_TXD,
 170     MX53_PAD_CSI0_D11__UART1_RXD,
 171     /*UART2*/
 172     MX53_PAD_ATA_DMARQ__UART2_TXD,
 173     MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
 174     MX53_PAD_ATA_INTRQ__UART2_CTS,
 175     MX53_PAD_ATA_DIOR__UART2_RTS,

结构体里面的是宏,果断展开之

arch/arm/plat-mxc/include/mach/iomux-mx53.h
547 #define MX53_PAD_CSI0_D10__UART1_TXD        IOMUX_PAD(0x414, 0xE8, 2, 0x0, 0, MX53_UART_PAD_CTRL)
548 #define MX53_PAD_CSI0_D11__UART1_RXD        IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
549 #define MX53_PAD_ATA_DIOW__UART1_TXD    IOMUX_PAD(0x5F0, 0x270, 3, 0x0, \
550                         0, MX53_UART_PAD_CTRL)
551 #define MX53_PAD_ATA_DMACK__UART1_RXD   IOMUX_PAD(0x5F4, 0x274, 3, 0x880, \
552                         3, MX53_UART_PAD_CTRL)

IOMUX_PAD继续展开

 63 #define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _select_input_ofs, \
 64         _select_input, _pad_ctrl)               \
 65         {                           \
 66             .mux_ctrl_ofs     = _mux_ctrl_ofs,      \
 67             .mux_mode         = _mux_mode,          \
 68             .pad_ctrl_ofs     = _pad_ctrl_ofs,      \
 69             .pad_ctrl         = _pad_ctrl,          \
 70             .select_input_ofs = _select_input_ofs,      \
 71             .select_input     = _select_input,      \
 72         }

现在来分析,UART1中的TXD脚,需要配置mode和pad中的针脚参数
IOMUXC_SW_MUX_CTL_PAD_CSIO_DAT10
addr = base + e8h
value = 010b
config UART1_IPP_UART_RXD_MUX_SELECT_INPUT for ALT2 mode

IOMUXC_SW_MUX_CTL_PAD_PATA_DIOW
addr = base + 270h
value = 011b (ALT3)
config UART1_IPP_UART_RXD_MUX_SELECT_INPUT for ALT3 mode

IOMUXC_SW_PAD_CTL_PAD_CSIO_DAT10
addr = base + 414h

IOMUXC_SW_PAD_CTL_PAD_PATA_DIOW
addr = base + 5f0h

IOMUXC_UART1_IPP_UART_RXD_MUX_SELECT_INPUT
addr = base +878h

以上是从DATASHEET中得到的,要使针脚具有TXD的功能,需要设置两个PAD。所以,MUX_SELECT_INPUT要设置两次,MUX_PATA_DIOW是用来选择SELECT_INPUT的mode,相应的PAD_CTL_PAD的CSIO_DAT10和PATA_DIOW是配置参数,如pull up/down有效。我们可以总结下:
1.针对不同的复用模式,mode要设置两次
2.SELECT_INPUT的也要设置两次
3.不同mode下的参数也要设置

CSIO_DAT10
MUX: base + mux_offset = mode
PAD: base + pad_offset = pad_ctrl
SELECT: base + select_offset = select_input

mux_offset = 0xe8,pad_offset = 0x414,select_offset = 0x0
mode = 2, pad_ctrl = MX53_UART_PAD_CTRL, select_input = 0

base在map_io中有设置

255 #define IOMUXC_BASE_ADDR    (AIPS1_BASE_ADDR + 0x000A8000)
241 #define AIPS1_BASE_ADDR     0x73F00000

但这里的地址是0x73f00000,而DATASHEET是0x53f00000,翻了下资料,AHB和IP连接,这个地方内存会不连续,至于具体原因,看DATASHEET(无力吐槽了,imx535的DATASHEET竟然5100页,我勒个去,真怀疑freescale的员工是从intel出来的)

最后,base地址在计算时用的是virtualaddr,所以有平台真好


 66 int mxc_iomux_v3_setup_pad(struct pad_desc *pad)
 67 {
 68    
 69     //1 I don't know if mux_ctrl_ofs is 0x3FF, it will be failed
 70     if (pad->mux_ctrl_ofs!=0x3FF)
 71     {
 72         __raw_writel(pad->mux_mode, base + pad->mux_ctrl_ofs);
 73     }
 74    
 75     printk("base = %p\n", base);
 76 
 77     if (pad->select_input_ofs)
 78         __raw_writel(pad->select_input,
 79                 base + pad->select_input_ofs); 
 80 
 81     if (!(pad->pad_ctrl & NO_PAD_CTRL) && pad->pad_ctrl_ofs)
 82         __raw_writel(pad->pad_ctrl, base + pad->pad_ctrl_ofs);
 83 
 84     return 0;
 85 }

这是最终的设置函数,每个pad_desc都会写值,这个pad_desc就是上面的mx53_smd_pads中的每一项,所以这个数组中把所有的复用包括了。

参考文献
mapleft的笔记-MX51 GPIO 及驱动

文章二维码

扫描二维码,在手机上阅读!

发表新评论
博客已萌萌哒运行
© 2018 由 Typecho 强力驱动.Theme by Yodu
前篇 后篇
雷姆
拉姆