内核使用的是天嵌移植好的linux4.1.15版本的内核,看它的设备树中用到pinctrl的配置不是很理解,理解一番后现在记录下:
1、以led_gpio为例:
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_leds>;
led1 {
label = "LED1";
gpios = <&gpio5 7 GPIO_ACTIVE_LOW>; //led 使用的引脚,与触发电平
};
led2 {
label = "LED2";
gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
};
};
pinctrl_gpio_leds: gpio_leds{
fsl,pins = <
MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x70a1 //led1
MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02 0x70a1 //led2
>;
};
pinctrl的配置信息在上串代码的最后,有两个数据结构;
MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07的定义在imx6ul-pinfunc.h中:
看到头文件上方有对这个五个数据的定义:
这个五个变量的定义我们 是知道了,但是还有个变量,让我百思不得其解,无奈只能百度然后看源码;
源码在:drivers/pinctrl/freescale/pinctrl-imx.c目录下,imx_pinctrl_parse_groups()函数调用了这些参数,源码如下:
static int imx_pinctrl_parse_groups(struct device_node *np,
struct imx_pin_group *grp,
struct imx_pinctrl_soc_info *info,
u32 index)
{
int size, pin_size;
const __be32 *list;
int i;
u32 config;
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
if (info->flags & SHARE_MUX_CONF_REG)
pin_size = SHARE_FSL_PIN_SIZE;
else
pin_size = FSL_PIN_SIZE;
/* Initialise group */
grp->name = np->name;
/*
* the binding format is fsl,pins = <PIN_FUNC_ID CONFIG ...>,
* do sanity check and calculate pins number
*/
list = of_get_property(np, "fsl,pins", &size);
if (!list) {
dev_err(info->dev, "no fsl,pins property in node %s\n", np->full_name);
return -EINVAL;
}
/* we do not check return since it's safe node passed down */
if (!size || size % pin_size) {
dev_err(info->dev, "Invalid fsl,pins property in node %s\n", np->full_name);
return -EINVAL;
}
grp->npins = size / pin_size;
grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(struct imx_pin),
GFP_KERNEL);
grp->pin_ids = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
GFP_KERNEL);
if (!grp->pins || ! grp->pin_ids)
return -ENOMEM;
for (i = 0; i < grp->npins; i++) {
u32 mux_reg = be32_to_cpu(*list++);
u32 conf_reg;
unsigned int pin_id;
struct imx_pin_reg *pin_reg;
struct imx_pin *pin = &grp->pins[i];
if (!(info->flags & ZERO_OFFSET_VALID) && !mux_reg)
mux_reg = -1;
if (info->flags & SHARE_MUX_CONF_REG) {
conf_reg = mux_reg;
} else {
conf_reg = be32_to_cpu(*list++);
if (!(info->flags & ZERO_OFFSET_VALID) && !conf_reg)
conf_reg = -1;
}
pin_id = (mux_reg != -1) ? mux_reg / 4 : conf_reg / 4;
pin_reg = &info->pin_regs[pin_id];
pin->pin = pin_id;
grp->pin_ids[i] = pin_id;
pin_reg->mux_reg = mux_reg;
pin_reg->conf_reg = conf_reg;
pin->input_reg = be32_to_cpu(*list++);
pin->mux_mode = be32_to_cpu(*list++);
pin->input_val = be32_to_cpu(*list++);
/* SION bit is in mux register */
config = be32_to_cpu(*list++);
if (config & IMX_PAD_SION)
pin->mux_mode |= IOMUXC_CONFIG_SION;
pin->config = config & ~IMX_PAD_SION;
dev_dbg(info->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name,
pin->mux_mode, pin->config);
}
return 0;
}
这里能看到,最后一个参数(第六个参数)的配置为config,显而易见是用于配制config_reg寄存器的值。
现在去看看这个配置寄存器做什么什么功能在数据手册得第1598页:
从手册可以看出这个寄存器是用来配置io的模式用的,上拉电阻多少,io速度等,pad_ctrl的值就是第六个参数了;
现在参数的意义我们都知道了,但是源代码有点刚看了不是很明白,看下其他设备树对比下,理解如下:
/* SION bit is in mux register */
config = be32_to_cpu(*list++);
if (config & IMX_PAD_SION)
pin->mux_mode |= IOMUXC_CONFIG_SION;
pin->config = config & ~IMX_PAD_SION;
先判断下是否为输入,如果是输入端口,配置mux_mode模式为输入模式;
为什么是与上这个值呢,去看下设备树源码就明白了:
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX6UL_PAD_CSI_VSYNC__I2C2_SDA 0x4001b8b0
MX6UL_PAD_CSI_HSYNC__I2C2_SCL 0x4001b8b0
>;
};
SION含义:software input on filed