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
函数。
//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];
}
}
上面有几个比教重要的数值
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
。
加入要设置另外的寄存器地址应该怎么解决了??