本文共 5494 字,大约阅读时间需要 18 分钟。
SoC内部都包含pin控制器,通过控制pin的寄存器,我们可以配置一个或者一组引脚的功能和特性
linux系统下采用pinctrl子系统管理所有的IO管脚# ls out/target/product/msm8998/obj/kernel/msm-4.4/drivers/pinctrl/qcom/ -l总用量 1668-rw-r--r-- 1 root root 821920 6月 8 13:37 built-in.o-rw-r--r-- 1 root root 136 6月 8 15:33 modules.builtin-rw-r--r-- 1 root root 0 6月 8 15:35 modules.order-rw-r--r-- 1 root root 254448 6月 8 13:37 pinctrl-msm8998.o-rw-r--r-- 1 root root 206232 11月 10 2017 pinctrl-msm.o-rw-r--r-- 1 root root 233064 11月 10 2017 pinctrl-sdm660.o-rw-r--r-- 1 root root 155960 11月 10 2017 pinctrl-wcd.o
驱动位置kernel/msm-4.4/drivers/pinctrl/qcom/pinctrl-msm8998.c
platform_driver_register(&msm8998_pinctrl_driver);static const struct of_device_id msm8998_pinctrl_of_match[] = { { .compatible = "qcom,msm8998-pinctrl", }, { },}static const struct msm_pinctrl_soc_data msm8998_pinctrl = { .pins = msm8998_pins,//管脚描述,包括管脚编号和管脚字符串描述 .npins = ARRAY_SIZE(msm8998_pins),//管脚的总个数 .functions = msm8998_functions,//数组描述所有的SOC所支持的mux functions .nfunctions = ARRAY_SIZE(msm8998_functions), .groups = msm8998_groups,//描述引脚SOC支持的所有引脚组的阵列 .ngroups = ARRAY_SIZE(msm8998_groups), .ngpios = 153,//可以导出的gpio的数量};
dts
compatible = "qcom,msm8998-pinctrl";kernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi://msm_uart功能uart_console_active: uart_console_active { mux { pins = "gpio4", "gpio5"; function = "blsp_uart8_a";//串口功能 }; config { pins = "gpio4", "gpio5"; drive-strength = <2>; bias-disable; }; };led_disable: led_disable { mux { pins = "gpio21"; function = "gpio";//gpio功能 }; config { pins = "gpio21"; drive_strength = <2>; output-low; bias-disable; }; };
在drivers/gpio下实现了通用的基于gpiolib的GPIO驱动,
其中定义了一个通用的用于描述底层GPIO控制器的gpio_chip结构体, 并要求具体的SoC实现gpio_chip结构体的成员函数, 最后透过gpiochip_add()注册gpio_chip kernel/msm-4.4/drivers/gpio/gpiolib.c 在用户空间/sys/class/gpio目录下看到msm8998:/sys/class/gpio # lsexport gpiochip346 gpiochip506 gpiochip666 gpiochip826 gpiochip986 gpiochip0 gpiochip378 gpiochip538 gpiochip698 gpiochip858 unexport gpiochip1018 gpiochip410 gpiochip570 gpiochip730 gpiochip890 gpiochip1019 gpiochip442 gpiochip602 gpiochip762 gpiochip922 gpiochip341 gpiochip474 gpiochip634 gpiochip794 gpiochip954 操作gpio以gpio21为例msm8998:/sys/class/gpio # echo 21 > exportmsm8998:/sys/class/gpio # cd gpio21/echo in/out > direction //设置gpio输入或输出msm8998:/sys/class/gpio/gpio21 # echo out > directionmsm8998:/sys/class/gpio/gpio21 # echo '1' > value //设置gpio的电平操作完成后msm8998:/sys/class/gpio # echo 21 > unexport
主要操作direction和value这两个文件
direction 用来配置输入(in)还是输出(out) value 如果这个GPIO配置成了输入,那么通过cat value可以查看当前这个GPIO是什么电位 如果配置成了输出,那么可以通过echo 1/0 > value给这个GPIO口指定输出电平1)单个gpio的配置kernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsist,reset-gpio = <&tlmm 89 0x00>;驱动代码的获取int rest_gpio = of_get_named_gpio_flags(np,”st, reset-gpio”, 0, NULL); gpio_request(rest_gpio, "gpio_name"); gpio_direction_output(rest_gpio, 1); gpio_set_value(rest_gpio, 0); gpio_free(rest_gpio); 关于TLMMMSM Socs拥有pinmux controller作为Top-LEVEL Mode Multiplexer(TLMM)TLMM支持复用和配置不同类型的pins2)用pinctrl配置设备树,一次配置多个gpio在驱动里边常常碰到驱动相关的一个或者几个gpio,在 醒来或者睡眠的时候需要设置成不同的类型,例如醒来的时候是i2c端口,但睡眠的时候可能要 设置成GPIO并把输出设置成0等。参考:kernel/msm-4.4/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txtkernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi pinctrl-0 = <&ts_active>; //引用ts_active pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;//引用ts_int_suspend ts-reset_suspend在kernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi中ts_mux { ts_active: ts_active { mux { pins = "gpio89", "gpio125"; function = "gpio"; }; config { pins = "gpio89", "gpio125"; drive-strength = <16>; bias-pull-up;//上拉 }; }; ts_reset_suspend: ts_reset_suspend { mux { pins = "gpio89"; function = "gpio"; }; config { pins = "gpio89"; drive-strength = <2>; bias-pull-down;//下拉 }; }; ts_int_suspend: ts_int_suspend { mux { pins = "gpio125"; function = "gpio"; }; config { pins = "gpio125"; drive-strength = <2>; bias-disable; }; }; };};内核驱动代码kernel/msm-4.4/drivers/input/touchscreen/st/fts.ckernel/msm-4.4/drivers/input/touchscreen/ft5x06_ts.cft5x06_data->ts_pinctrl = devm_pinctrl_get(&(ft5x06_data->client->dev));//获取device对应节点下的pinctrlft5x06_data->pinctrl_state_active = pinctrl_lookup_state(ft5x06_data->ts_pinctrl,PINCTRL_STATE_ACTIVE);//通过pinctrl名获取pinctrl对应状态ft5x06_data->pinctrl_state_release = pinctrl_lookup_state(ft5x06_data->ts_pinctrl,PINCTRL_STATE_RELEASE);pinctrl_select_state(data->ts_pinctrl,data->pinctrl_state_release);设置pinctrl的状态为pinctrl_state_releasedevm_pinctrl_put(ft5x06_data->ts_pinctrl);//释放资源
转载地址:http://dakni.baihongyu.com/