Freescale 设备树DDR3引脚复用初始化

imxq6

VERSION = 4
PATCHLEVEL = 1
SUBLEVEL = 15

设备树初始化结构

//E:\workProject\kernel_imx\arch\arm\mach-imx\busfreq-imx.c
static struct platform_driver busfreq_driver = {
	.driver = {
		.name = "imx_busfreq",
		.owner  = THIS_MODULE,
		.of_match_table = imx_busfreq_ids,
		},
	.probe = busfreq_probe,
};
module_init(busfreq_init);
busfreq_init
	platform_driver_register(&busfreq_driver)	

模块进入函数busfreq_init调用platform_driver_register函数注册busfreq_driver
busfreq_driver结构的probe注册为busfreq_probe。将会在注册平台设备的时候回调此busfreq_probe函数。

busfreq_probe

//E:\workProject\kernel_imx\arch\arm\mach-imx\busfreq_ddr3.c
static int busfreq_probe(struct platform_device *pdev)
{
	if (cpu_is_imx6q() || cpu_is_imx6dl()){
			if (ddr_type == MMDC_MDMISC_DDR_TYPE_DDR3)
			err = init_mmdc_ddr3_settings_imx6_smp(pdev);
			else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
			err = init_mmdc_lpddr2_settings_mx6q(pdev);
	}
}

DDR3为例。

//E:\workProject\kernel_imx\arch\arm\mach-imx\busfreq_ddr3.c
int init_mmdc_ddr3_settings_imx6_smp(struct platform_device *busfreq_pdev)
{
	if (cpu_is_imx6q())
		node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc");
	iomux_base = of_iomap(node, 0);
}

在这里就能看到利用of_find_compatible_node函数查找设备树节点"fsl,imx6q-iomuxc"。根据Freescale提供的参考文件
Documentation\devicetree\bindings\pinctrl\fsl,imx6q-pinctrl.txt。提到的需要指定IO口复用控制器

Required properties:
- compatible: "fsl,imx6q-iomuxc"
- fsl,pins: two integers array, represents a group of pins mux and config
  setting. The format is fsl,pins = , PIN_FUNC_ID is a
  pin working on a specific function, CONFIG is the pad setting value like
  pull-up for this pin. Please refer to imx6q datasheet for the valid pad
  config settings.

显然就将设备树节点以及驱动链接起来了。

得到节点以后

init_mmdc_ddr3_settings_imx6_smp函数调用
node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc");得到节点以后将其映射到保存到iomux_base

	if (cpu_is_imx6q()) {
		/* store the IOMUX settings at boot. */
		for (i = 0; i < iomux_settings_size; i++) {
			iomux_offsets_mx6q[i][1] =
				readl_relaxed(iomux_base +
					iomux_offsets_mx6q[i][0]);
			iram_iomux_settings[i + 1][0] =
				iomux_offsets_mx6q[i][0];
			iram_iomux_settings[i + 1][1] =
				iomux_offsets_mx6q[i][1];
		}
	}

上面有几个比教重要的数值

  • iomux_settings_size
  • iomux_offsets_mx6q
  • iram_iomux_settings
    iomux_settings_size
    追溯
unsigned long iomux_offsets_mx6q[][2] = {
	{0x5A8, 0x0},
	{0x5B0, 0x0},
	{0x524, 0x0},
	{0x51C, 0x0},
	{0x518, 0x0},
	{0x50C, 0x0},
	{0x5B8, 0x0},
	{0x5C0, 0x0},
};
iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q);   
//iomux_settings_size  == 8

根据imx6q-sabrelite\include\imx6q.dtsi指定的地址

iomuxc: iomuxc@020e0000 

那么
iomux_offsets_mx6q[i][1] = readl_relaxed(iomux_base+iomux_offsets_mx6q[i][0]);
假设i==1。对应的值为0x5B0
iomux_offsets_mx6q[i][1] = readl_relaxed(0x20e05B0);
0x20e05B0对应的寄存器地址为IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1_P

分析

加入要设置另外的寄存器地址应该怎么解决了??

参考资料

你可能感兴趣的:(linux,基础)