Device tree .dts parser, it's like Tinyxml
///////////////paser dts
gedit /root/project_board/free_imx/myandroid/kernel_imx/drivers/of/fdt.c
void __init unflatten_device_tree(void)
{
//of_allnodes get full Tree
__unflatten_device_tree(initial_boot_params, &of_allnodes, early_init_dt_alloc_memory_arch);
of_alias_scan(early_init_dt_alloc_memory_arch); //start parser
}
///
gedit /root/project_board/free_imx/myandroid/kernel_imx/drivers/of/base.c
//function list,
void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
{
...
...
// search each node
// first node refer to /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/boot/dts/imx6dl.dtsi
for_each_property_of_node(of_aliases, pp)
{
...
np = of_find_node_by_path(pp->value); //find path and its value
...
}
...
...
}
///////////////init device
gedit /root/project_board/free_imx/myandroid/kernel_imx/init/main.c
static void __init do_initcalls(void)
{
int level;
for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
do_initcall_level(level); //when level = 3 init imx6q_init_machine
}
///
gedit /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/mach-imx/mach-imx6q.c
static void __init imx6q_init_machine(void)
{
struct device *parent;
mxc_arch_reset_init_dt();
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
of_platform_populate(NULL, of_default_bus_match_table, imx6q_auxdata_lookup, parent);
//call of_find_compatible_node get match node
imx6q_enet_init();
imx_anatop_init();
imx6_pm_init();
imx6q_csi_mux_init();
imx6q_mini_pcie_init();
}
///init "fsl,imx6q-anatop", "arm,pl310-cache", "fsl,imx51-src", "fsl,imx6q-gpc"
gedit /root/project_board/free_imx/myandroid/kernel_imx/drivers/of/base.c
of_find_compatible_node(struct device_node *from,
const char *type,
const char *compatible)
{
...
for ( ;np ;np = np->allnext)
{
if (type && !(np->type && (of_node_cmp(np->type, type) == 0)))
continue;
if (__of_device_is_compatible(np, compatible) && of_node_get(np))
break;
}
...
return np; //return match node
}
//////////////////////////////////u-boot///////////////////////////////////////
EX1:
open [IMX6DQRM.pdf]
find EIM_A17 in page. 263
EIM_A17 has mode ALT0, ALT1, ALT2, ALT5, ALT7
select ALT5 - GPIO2_IO21
///
open [IMX6DQRM.pdf]
find EIM_ADDR17 in page. 2241
[field descriptions] show pin function
///
open [matrix io bd ep2 20160125.pdf]
find EIM_A17 in page. 8
pin 50 EIM_A17 set as GPIO2_IO21
///
C code:
gedit /root/project_board/lollipop51/myandroid/bootable/bootloader/uboot-imx/arch/arm/include/asm/imx-common/iomux-v3.h
#define MUX_PAD_CTRL(x) ((iomux_v3_cfg_t)(x) << MUX_PAD_CTRL_SHIFT)
///
gedit /root/project_board/lollipop51/myandroid/bootable/bootloader/uboot-imx/board/freescale/mx6sabresd/mx6sabresd.c
#define EPDC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_SPEED_MED | \
PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
///
gedit /root/project_board/lollipop51/myandroid/bootable/bootloader/uboot-imx/board/freescale/mx6sabresd/mx6sabresd.c
find
imx_iomux_v3_setup_pad(MX6_PAD_EIM_A17__GPIO2_IO21 | MUX_PAD_CTRL(EPDC_PAD_CTRL));
///
MX6_PAD_EIM_A17__GPIO2_IO21
explain: pin EIM_A17 select function to GPIO2_IO21
///
PAD_CTL_PKE
explain: Pull / Keep Enable Field = 1b
Pull/Keeper Enabled
///
PAD_CTL_SPEED_MED
explain: Speed Field = 10b
MEDIUM — Medium frequency (100, 150 MHz)
///
PAD_CTL_DSE_40ohm
explain: DSE = 110b
40_OHM — 25 Ohm @ 3.3V, 40 Ohm @ 1.8V
///
PAD_CTL_HYS
explain: Hysteresis = 1
schmitt trigger input
//////////////////////////linux kernel/////////////////////////////////////
EX2:
open [IMX6DQRM.pdf]
find NANDF_D3 in page. 281
NANDF_D3 has mode ALT0, ALT1, ALT5
select ALT5 - GPIO2_IO03
///
open [IMX6DQRM.pdf]
find PAD_CTL_PAD_NAND_DATA03 in page. 2579
[field descriptions] show pin function
///
open [matrix som bd ep2 20150325.pdf.pdf]
find NANDF_D3 in page. 20
pin NANDF_D3 set as GPIO2_IO03 in pin 87
///
open [matrix som bd ep2 20150325.pdf.pdf]
find 87 in page. 7
pin 87 connect to GPIO2_IO3
///
DTS Work:
/root/project_board/free_imx/myandroid/kernel_imx/arch/arm/boot/dts/Makefile
find [imx6dq-matrix_io.dtb]
Makefile assign to compile imx6dq-matrix_io.dts
///
/root/project_board/free_imx/myandroid/kernel_imx/arch/arm/boot/dts/imx6dq-matrix_io.dts
#include "imx6q.dtsi"
...
...
MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x80000000 //0x80000000 default value do nothing in C code
MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 //0x80000000 default value do nothing in C code
...
MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b098 //will set this value to pinctrl-imx.c
...
///
0x1b098 = 0001 1011 0000 1001 1000(b)
HYS = 1(b)
ENABLED — Schmitt trigger input
PUS = 10(b)
100K_OHM_PU — 100K Ohm Pull Up
PUE = 1(b)
PULL — Pull Enabled //select Pull function
PKE = 1(b)
ENABLED — Pull Enabled
SPEED = 10(b)
MEDIUM — Medium frequency (100, 150 MHz)
DSE = 011(b)
90_OHM — 50 Ohm @ 3.3V, 90 Ohm @ 1.8V
///dts setting
/root/project_board/free_imx/myandroid/kernel_imx/arch/arm/boot/dts/imx6q.dtsi
iomuxc: iomuxc@ 0x020e0000
{ compatible = "fsl,imx6q-iomuxc"; };
///C Code:
gedit /root/project_board/free_imx/myandroid/kernel_imx/init/main.c
static void __init do_initcalls(void)
{
int level;
for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
do_initcall_level(level); //when level = 3 call imx6q_pinctrl_probe
}
///
gedit /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/mach-imx/mx6.h
#define MX6Q_IOMUXC_BASE_ADDR 0x020e0000 //match as iomuxc: iomuxc@ 0x020e0000
gedit /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/boot/dts/imx6q-pinfunc.h
<mux_reg, conf_reg, input_reg, mux_mode, input_val>
#define MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x308 0x6f0 0x000 0x5 0x0
///
gedit /root/project_board/free_imx/myandroid/kernel_imx/drivers/pinctrl/pinctrl-imx6q.c
static struct of_device_id imx6q_pinctrl_of_match[] =
{
{ .compatible = "fsl,imx6q-iomuxc", },
{ /* sentinel */ }
};
static int imx6q_pinctrl_probe(struct platform_device *pdev)
{
return imx_pinctrl_probe(pdev, &imx6q_pinctrl_info);
}
///
/root/project_board/free_imx/myandroid/kernel_imx/drivers/pinctrl/pinctrl-imx.c
int imx_pinctrl_probe(struct platform_device *pdev, struct imx_pinctrl_soc_info *info)
{
...
...
ret = imx_pinctrl_probe_dt(pdev, info);
...
...
//call pinctrl_register-> pinctrl_select_state -> pinconf_apply_setting -> imx_pinconf_set
ipctl->pctl = pinctrl_register(&imx_pinctrl_desc, &pdev->dev, ipctl);
...
...
}
///
/root/project_board/free_imx/myandroid/kernel_imx/drivers/pinctrl/pinctrl-imx.c
static int imx_pinctrl_probe_dt(struct platform_device *pdev, struct imx_pinctrl_soc_info *info)
{
...
...
//np->name = "iomuxc"
for_each_child_of_node(np, child)
{
//child->name = "board_gpios"
ret = imx_pinctrl_parse_functions(child, info, i++);
if (ret)
{
dev_err(&pdev->dev, "failed to parse function\n");
return ret;
}
}
...
...
}
///
/root/project_board/free_imx/myandroid/kernel_imx/drivers/pinctrl/pinctrl-imx.c
static int imx_pinctrl_parse_functions(...)
{
...
...
for_each_child_of_node(np, child)
{
func->groups[i] = child->name;
grp = &info->groups[grp_index++];
ret = imx_pinctrl_parse_groups(child, grp, info, i++); //work here
if (ret)
return ret;
}
...
}
///
/root/project_board/free_imx/myandroid/kernel_imx/drivers/pinctrl/pinctrl-imx.c
static int imx_pinctrl_parse_groups(...)
{
...
...
//get from MX6QDL_PAD_NANDF_D3__GPIO2_IO03
pin_reg->mux_reg = mux_reg; //0x308
pin_reg->conf_reg = conf_reg; //0x6f0
grp->input_reg[i] = be32_to_cpu(*list++); //0x000
grp->mux_mode[i] = be32_to_cpu(*list++); //0x5
grp->input_val[i] = be32_to_cpu(*list++); //0x0
//get value from /root/project_board/free_imx/myandroid/kernel_imx/arch/arm/boot/dts/imx6dq-matrix_io.dts
grp->configs[i] = config & ~IMX_PAD_SION; //0x1b098
...
...
}
///call from pinctrl_register
gedit /root/project_board/free_imx/myandroid/kernel_imx/drivers/pinctrl/pinctrl-imx.c
static int imx_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin_id, unsigned long config)
{
...
...
writel(config, ipctl->base + pin_reg->conf_reg); //config = 0x1b098
...
...
}
沒有留言:
張貼留言