基于Amlogic T972:结合DTS驱动Datasheet,解析Pinctrl子系统GPIO脚的复用方法

Posted 阿迷创客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Amlogic T972:结合DTS驱动Datasheet,解析Pinctrl子系统GPIO脚的复用方法相关的知识,希望对你有一定的参考价值。

文章目录

前言

本文结合Amlogic T972平台的设备树(DTS)、驱动源码、Datasheet,重点关注如何通过Pinctrl子系统,实现PIN脚的复用。
通过DTS的3个例子的分析,结合datasheet,确认了PIN脚复用方法。另一方面,自然也解析出了DTS中pinctrl部分的书写方法。

  • 对于Andorid驱动的开发,如楼下所用Amlogic T972平台,在原厂所提供的AOSP源码中,在其DTS文件中,各个PIN脚的配置均已做好,只需使用或改变PIN脚功能时,只需在DTS中修改即可。

  • 例如,如果我们想将例(3)中的GPIOZ_1和GPIOZ_2脚,对应于i2c1_z,作为i2c1(即i2c-1)来使用,则只需:

    • i2c1_h_pins 更换为 i2c1_z_pins
    • i2c1_h_pins_slp_input 更换为 i2c1_z_pins_slp_input
  • 楼上的做法,其实就是通过PIN MUX,设置其通路寄存器,将GPIOZ_1和GPIOZ_2脚连接至i2c1模块


//common\\arch\\arm\\boot\\dts\\amlogic\\tl1_t962x2_x301_1g.dts
&i2c1 
	status = "okay";
	clock-frequency = <300000>;
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&i2c1_z_pins>; //备注:如楼上,从i2c1_h_pins切换为i2c1_z_pins
	pinctrl-1 = <&i2c1_z_pins_slp_input>;//备注:即可给i2c1换一对PIN脚
;

一、概念

Pinctrl 即Pin controller(Soc的引脚控制器)。所有的Soc引脚,它们的功能、状态等,都需要经过配置后才可使用,下面就是一个如何控制引脚的逻辑框图。

最左边的【PAD】是最终的引脚,而它的功能,是由它右边的部分决定的,例如此PAD连接的是哪个module、它的状态是什么等等。具体的框图分析,要详细阅读datasheet,并结合驱动代码来了解,将在另外一篇文章中介绍。

1.1 Pinctrl devices

提供服务,可以用它来复用引脚、配置引脚,是一个软件上的概念。

1.2 Pinctrl client devices

使用服务,Pinctrl系统的客户,即使用Pinctrl系统的设备。声明自己要使用哪些引脚的哪些功能,怎么配置它们。

注意:Pin controller和GPIO Controller不同:(1) Pin controller 通过控制MUX功能复用,可以控制一个的具体功能,例如将具体的PIN设置为I2C功能,或者简单的GPIO功能;(2)GPIO Controller只有普通GPIO功能,如上拉、下拉、设置输入或输出方向。(3)两者的关系是先用Pin controller把引脚配置为GPIO,再用GPIO Controler把引脚配置为输入或输出。

二、例(1)GPIOZ_9/10 复用为 i2c2_z

2.1 Pin controller devices

2.1.1 设备树配置: dts

&pinctrl_periphs 

// …… 省略 ……

	i2c2_z_pins:i2c2_z 
		mux 
			groups = "i2c2_sda_z", //"i2c2_sda_z"在源码中配置,楼下其余地方groups实现方法相同
				"i2c2_sck_z";
			function = "i2c2";
			bias-pull-up;
			drive-strength = <3>;
		;
	;

	i2c2_z_pins_slp_input:i2c2_z_slp_input 
		mux 
			groups = "GPIOZ_9", "GPIOZ_10";
			function = "gpio_periphs";
			input-enable;
			bias-disable;
		;
	;

2.1.2 源码:驱动配置

//common\\drivers\\amlogic\\pinctrl\\pinctrl-meson-axg-pmx.h
#define GROUP(grp, f)							\\
									\\
		.name = #grp,						\\
		.pins = grp ## _pins,                                   \\
		.num_pins = ARRAY_SIZE(grp ## _pins),			\\
		.data = (const struct meson_pmx_axg_data[])		\\
			PMX_DATA(f),					\\
		,							\\
	


//common\\drivers\\amlogic\\pinctrl\\pinctrl-meson-tl1.c
/* i2c2 */
static const unsigned int i2c2_sda_z_pins[] = GPIOZ_10;
static const unsigned int i2c2_sck_z_pins[] = GPIOZ_9;

static struct meson_pmx_group meson_tl1_periphs_groups[] = 
// ……  省略 ……
	/* bank GPIOZ */
	GROUP(i2c2_sda_z,	1), //备注:此处的Group(grp, f=1), 即PMX_DATA(f=1),对应datasheet,正好是I2C_EE_M2
	GROUP(i2c2_sck_z,	1),
// ……  省略 ……


static const char * const i2c2_groups[] = 
	"i2c2_sda_h", "i2c2_sck_h",
	"i2c2_sda_z", "i2c2_sck_z",
;

2.1.3 Datasheet

  • 下图为GPIO脚复用的Fun定义部分,楼上例一的表格遵循相同的循序,从Fun1开始
  • 再次印证,meson_tl1_periphs_groups[]中GROUP(i2c2_sda_z, 1)宏的第2个参数,即为复用Fun的序号,从1开始
  • 总结:若需要将GPIOZ_9和GPIOZ_10配置为i2c2_z,需设置Mux fun=1

2.2 Pinctrl client devices

2.2.1 设备树配置:dts

//mesontl1.dtsi
			i2c2: i2c@1d000 
				compatible = "amlogic,meson-i2c";
				status = "disabled";
				reg = <0x1d000 0x20>;
				interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>,
					<GIC_SPI 94 IRQ_TYPE_EDGE_RISING>;
				#address-cells = <1>;
				#size-cells = <0>;
				clocks = <&clkc CLKID_I2C>;
				clock-frequency = <100000>;
			;
//tl1_t962x2_x301_1g.dts	
&i2c2 
	status = "okay";
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&i2c2_z_pins>; //备注:使用Pinctrl的状态1配置,将配置为i2c2
	pinctrl-1 = <&i2c2_z_pins_slp_input>;//备注:使用Pinctrl的状态2配置,i2c2将配置为GPIO input
	clock-frequency = <400000>;

	tas5805: tas5805@36 
		compatible = "ti,tas5805";
		#sound-dai-cells = <0>;
		codec_name = "tas5805";
		reg = <0x2d>;
		status = "disable";
	;

	ad82584f: ad82584f@62 
		compatible = "ESMT, ad82584f";
		#sound-dai-cells = <0>;
		reg = <0x31>;
		status = "okay";
		reset_pin = <&gpio_ao GPIOAO_6 0>;
	;

;

三、例(2)GPIOH_21/22 复用为 i2c1_h

3.1 Pin controller devices

3.1.1 设备树配置: dts

common\\arch\\arm\\boot\\dts\\amlogic\\mesontl1.dtsi
&pinctrl_periphs 
// …… 省略 ……

	i2c1_h_pins:i2c1_h 
		mux 
			groups = "i2c1_sda_h",
				"i2c1_sck_h";
			function = "i2c1";
			bias-pull-up;
			drive-strength = <3>;
		;
	;

	i2c1_h_pins_slp_input:i2c1_h_slp_input 
		mux 
			groups = "GPIOH_21", "GPIOH_22";
			function = "gpio_periphs";
			input-enable;
			bias-disable;
		;
	;
    // …… 省略 ……
 // end of &pinctrl_periphs 

3.1.2 源码:驱动配置

//common\\drivers\\amlogic\\pinctrl\\pinctrl-meson-axg-pmx.h
#define GROUP(grp, f)							\\
									\\
		.name = #grp,						\\
		.pins = grp ## _pins,                                   \\
		.num_pins = ARRAY_SIZE(grp ## _pins),			\\
		.data = (const struct meson_pmx_axg_data[])		\\
			PMX_DATA(f),					\\
		,							\\
	


//common\\drivers\\amlogic\\pinctrl\\pinctrl-meson-tl1.c
/* i2c1 */
static const unsigned int i2c1_sda_h_pins[] = GPIOH_22;
static const unsigned int i2c1_sck_h_pins[] = GPIOH_21;

static struct meson_pmx_group meson_tl1_periphs_groups[] = 
    // …… 省略 ……
	/* bank GPIOH */
	GROUP(i2c1_sda_h,	1),
	GROUP(i2c1_sck_h,	1),
    // …… 省略 ……

3.1.3 Datasheet

  • 下图为GPIO脚复用的Fun定义部分,从Func=1开始,到~Func=7
  • 再次印证,meson_tl1_periphs_groups[]中GROUP(i2c1_sda_h, 1)宏的第2个参数,即为复用Fun的序号,从1开始
  • 总结:若需要将GPIOH_21和GPIOH_22配置为i2c1_h,需设置Mux fun=1

3.2 Pinctrl client devices

3.2.1 设备树配置:dts

  • 默认状态(“default”):pinctrl-0 = <&i2c1_h_pins>;
  • 睡眠状态(“sleep”):pinctrl-1 = <&i2c1_h_pins_slp_input>;

//common\\arch\\arm\\boot\\dts\\amlogic\\tl1_t962x2_x301_1g.dts
&i2c1 
	status = "okay";
	clock-frequency = <300000>;
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&i2c1_h_pins>; //备注:引用pinctrl的配置0,将配置为i2c1_h
	pinctrl-1 = <&i2c1_h_pins_slp_input>;

	lcd_extern_i2c0: lcd_extern_i2c@0 
		compatible = "lcd_ext, i2c";
		dev_name = "i2c_T5800Q";
		reg = <0x1c>;
		status = "okay";
	;

	lcd_extern_i2c1: lcd_extern_i2c@1 
		compatible = "lcd_ext, i2c";
		dev_name = "i2c_ANX6862";
		reg = <0x20>;
		status = "okay";
	;

	lcd_extern_i2c2: lcd_extern_i2c@2 
		compatible = "lcd_ext, i2c";
		dev_name = "i2c_ANX7911";
		reg = <0x74>;
		status = "okay";
	;

	lcd_extern_i2c3: lcd_extern_i2c@3 
		compatible = "lcd_ext, i2c";
		dev_name = "i2c_CS602";
		reg = <0x66>;
		status = "disable";
	;
;

3.2.2 设备树:图解

四、例(3)GPIOZ_1/2 复用为 i2c1_z

4.1 Pin controller devices

4.1.1 设备树配置: dts

common\\arch\\arm\\boot\\dts\\amlogic\\mesontl1.dtsi
&pinctrl_periphs 
// …… 省略 ……

	i2c1_z_pins:i2c1_z 
		mux 
			groups = "i2c1_sda_z",
				"i2c1_sck_z";
			function = "i2c1";
			bias-pull-up;
			drive-strength = <3>;
		;
	;

	/*
	 * i2c sleep mode1: set the gpio the input
	 * in this scene, pull up power is off
	 */
	i2c1_z_pins_slp_input:i2c1_z_slp_input 
		mux 
			groups = "GPIOZ_1", "GPIOZ_2";
			function = "gpio_periphs";
			input-enable;
			bias-disable;
		;
	;
    // …… 省略 ……
 // end of &pinctrl_periphs 

4.1.2 源码:驱动配置

//common\\drivers\\amlogic\\pinctrl\\pinctrl-meson-axg-pmx.h
#define GROUP(grp, f)							\\
									\\
		.name = #grp,						\\
		.pins = grp ## _pins,                                   \\
		.num_pins = ARRAY_SIZE(grp ## _pins),			\\
		.data = (const struct meson_pmx_axg_data[])		\\
			PMX_DATA(f),					\\
		,							\\
	


//common\\drivers\\amlogic\\pinctrl\\pinctrl-meson-tl1.c
/* i2c2 */
static const unsigned int i2c2_sda_z_pins[] = GPIOZ_10;
static const unsigned int i2c2_sck_z_pins[] = GPIOZ_9;

static struct meson_pmx_group meson_tl1_periphs_groups[] = 
// ……  省略 ……
	/* bank GPIOZ */
	GROUP(i2c2_sda_z,	1), //此处的Group(grp, f=1), 即PMX_DATA(f=1),对应datasheet,正好是I2C_EE_M2
	GROUP(i2c2_sck_z,	1),
// ……  省略 ……


static const char * const i2c2_groups[] = 
	"i2c2_sda_h", "i2c2_sck_h",
	"i2c2_sda_z", "i2c2_sck_z",
;

4.1.3 Datasheet

  • 下图为GPIO脚复用的Fun定义部分,楼上例一的表格遵循相同的循序,从Fun1开始
  • 再次印证,meson_tl1_periphs_groups[]中GROUP(i2c1_sda_z, 3)宏的第2个参数,即为复用Fun的序号,从1开始
  • 总结:若需要将GPIOZ_1和GPIOZ_2配置为i2c1,需设置Mux fun=3

五、结尾

5.1 关于 _z 和 _h 后缀的含义

  • i2c1_z 与 i2c1_h 的区别,_z为使用GPIO_BANK_Z上的PIN脚, 而_h为GPIO_BANK_H上的PIN脚
  • 在例(2)的配置中,实际连接到i2c1模块上的PIN脚复用配置,为GPIO_BANK_H上的PIN脚

以上是关于基于Amlogic T972:结合DTS驱动Datasheet,解析Pinctrl子系统GPIO脚的复用方法的主要内容,如果未能解决你的问题,请参考以下文章

Amlogic T972 AOSP 编译服务器搭建

基于Amlogic 安卓9.0, 驱动简说:Platform平台驱动,驱动与设备的分离

基于Amlogic 安卓9.0, 驱动简说:Platform平台驱动,驱动与设备的分离

基于Amlogic 安卓9.0, 驱动简说:字符设备驱动,手动创建设备

基于Amlogic 安卓9.0, 驱动简说:使用misc框架,让驱动更简单

基于Amlogic 安卓9.0, 驱动简说:使用misc框架,让驱动更简单