imx535中IOMUX控制器
公司做项目,所以就外购了开发板,结果因为视频驱动问题一直无法调通,最后决定不再等客服了,自己来搞了。
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_
下面来分析代码复用是怎么设置的
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 及驱动

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