Openwrt中MT7628/MT7688的全部GPIO複用配置及常用接口DTS配置總結

Openwrt的不同版本中關於MT7628,MT7688的GPIO配置,存在或多或少的一些小問題

下面將以MT7628AN爲基礎,介紹其全部的GPIO功能複用配置,以及需要注意的地方

MT76x8一個就47個可作爲GPIO引腳,如下

 關於其全部的功能複用表可以參考MTK官方的開發demo版Linkit

 在這全部的引腳中,需要特別注意的是:

1. 網口模式,因爲MTK的設計,一共5個網口,要麼全部作爲普通網口使用,要麼只有一個網口(Port0),沒有中間選項;

因此,如果需要用到UART2,SDCARD等功能時,系統只剩一個P0網口可用,這也是MTK所宣傳的IOT模式

2. SPI接口,datasheet介紹可以作爲GPIO使用,但是因爲大多系統都接了SPI NOR Flash,因此其不能設置爲GPIO模式;而SPI_CS1另一個SPI片選腳,倒是不受影響,可作爲GPIO

3. 關於GPIO/GPO的描述,比如I2C的兩個腳是GPO,但經實際測試,描述爲GPO的其實可以作爲輸入使用

 

關於DTS配置,其主要參考arch/mips/ralink/mt7620.c文件

static struct rt2880_pmx_group mt7628an_pinmux_data[] = {
	GRP_G("pwm1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_PWM1),
	GRP_G("pwm0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_PWM0),
	GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_UART2),
	GRP_G("uart1", uart1_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_UART1),
	GRP_G("i2c", i2c_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_I2C),
	GRP("refclk", refclk_grp_mt7628, 1, MT7628_GPIO_MODE_REFCLK),
	GRP("perst", perst_grp_mt7628, 1, MT7628_GPIO_MODE_PERST),
	GRP("wdt", wdt_grp_mt7628, 1, MT7628_GPIO_MODE_WDT),
	GRP("spi", spi_grp_mt7628, 1, MT7628_GPIO_MODE_SPI),
	GRP_G("sdmode", sd_mode_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_SDMODE),
	GRP_G("uart0", uart0_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_UART0),
	GRP_G("i2s", i2s_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_I2S),
	GRP_G("spi cs1", spi_cs1_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_CS1),
	GRP_G("spis", spis_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_SPIS),
	GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_GPIO),
	GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
				1, MT7628_GPIO_MODE_WLED_AN)
}

在DTS文件中,填寫對應的name和func名字就可以,如:

pinctrl {
    state_default: pinctrl0 {
	gpio {
	    ralink,group = "gpio","wled_an", "i2s", "refclk", "perst", "wdt", "spi cs1";
	    ralink,function = "gpio";
	};
}

常用接口及功能配置如下:

UART1開啓:

uart1@d00 {
	status = "okay";
};

SPI_CS1 開啓,使用系統spi控制器,注意pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>,配置CS1爲SPI_CS1功能,同時應該去掉pinctrl0中"spi cs1"的GPIO複用

spi@b00 {
	status = "okay";

	pinctrl-names = "default";
	pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>;
        
        spidev@1 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "spidev";
		reg = <1 0>;
		spi-max-frequency = <40000000>;
        };
}

GPIO模擬SPI配置,如:使用I2S的複用腳0-3,注意先配置I2S爲GPIO模式

spi-gpio {
		compatible = "spi-gpio";
		#address-cells = <0x1>;
		cs-gpios = <&gpio0 2 0>;
		gpio-sck = <&gpio0 0 0>;
		gpio-mosi = <&gpio0 3 0>;
		gpio-miso = <&gpio0 1 0>;
		num-chipselects = <1>;
		spidev@0 {
			#address-cells = <0x1>;
			compatible = "spidev";
			spi-max-frequency = <10000000>;
			reg = <0>;
		};
	};

I2C的RTC時鐘配置,以PCF8563爲例,注意reg地址的問題,pcf8563地址是0x51,常用的ds1307是0x68

i2c@900 {
	status = "okay";
	rtc@51 {
		compatible = "nxp,pcf8563";
		 reg = <0x51>;
	};
};

LED配置參考,注意MT76x8有兩組GPIO,GPIO0對應0-31,GPIO1對應32-46

gpio-leds {
		compatible = "gpio-leds";
		modpwr {
			label = "modpwr";
			gpios = <&gpio1 8 1>;
		};
		modrst {
			label = "modrst";
			gpios = <&gpio1 4 0>;
		};
		heart {
			label = "heart";
			gpios = <&gpio1 6 1>;
		};
}

lable對應運行系統中/sys/class/leds/lable/brightness 的lable名字

gpios = <&gpio1 8 1>; 表示GPIO1組,8 表示 32+8 即GPIO40,1表示低電平有效,即默認輸出高電平

按鍵配置參考,

gpio-keys-polled {
		compatible = "gpio-keys-polled";
		#address-cells = <1>;
		#size-cells = <0>;
		poll-interval = <20>;
		vccin {
			label = "BTN_0";
			gpios = <&gpio0 6 0>;
			linux,code = <0x100>;
		};
		reset {
			label = "reset";
			gpios = <&gpio1 7 1>;
			linux,code = <0x198>;
		};
	};

poll-interval 表示輸入檢測消抖時間,label對應於運行系統中/etc/rc.button/lable,即按鍵後對應的執行腳本文件,如上述配置,系統中應該存在reset和BTN_0兩個腳本, gpios同LED說明

linux,code = <0x198>; 對應input.h的宏定義值,配合驅動文件gpio-button-hotplug.c中的相關配置,如:

static struct bh_map button_map[] = {
	BH_MAP(BTN_0,		"BTN_0"),
	BH_MAP(BTN_1,		"BTN_1"),
	BH_MAP(BTN_2,		"BTN_2"),
	BH_MAP(BTN_3,		"BTN_3"),
	BH_MAP(BTN_4,		"BTN_4"),
	BH_MAP(BTN_5,		"BTN_5"),
	BH_MAP(BTN_6,		"BTN_6"),
	BH_MAP(BTN_7,		"BTN_7"),
	BH_MAP(BTN_8,		"BTN_8"),
	BH_MAP(BTN_9,		"BTN_9"),
	BH_MAP(KEY_POWER,	"power"),
	BH_MAP(KEY_RESTART,	"reset"),
	BH_MAP(KEY_RFKILL,	"rfkill"),
	BH_MAP(KEY_WPS_BUTTON,	"wps"),
	BH_MAP(KEY_WIMAX,	"wwan"),
};

其原理是gpio-button-hotplug驅動會檢測按鍵事件,然後通過netlionk方式廣播出來,proc會一直監測事件,觸發hotplug,進而執行到相關reset等腳本,熱拔插事件也是此類方式,具體不再詳細介紹,本文主要介紹引腳複用配置

另,還需注意的是,配置了相關引腳功能後,還需在kernel中開啓相關驅動模塊以及選擇相關的應用才能正常使用

到此,常用接口基本介紹完畢

下面大概提一下不同openwrt版本中的代碼錯誤,以下只貼出正確的code,各位看客有功能錯誤的各自根據自己的現有版本對比修正即可

1. 看門狗dts 地址錯誤,位置:target/linux/ramips/dts/mt7628an.dtsi

watchdog: watchdog@100 {
	compatible = "ralink,mt7628an-wdt", "mediatek,mt7621-wdt";
	reg = <0x100 0x30>;

	resets = <&rstctrl 8>;
	reset-names = "wdt";

	interrupt-parent = <&intc>;
	interrupts = <24>;
};

根據DataSheet,watchdog的偏移地址應該是100

同時,如果需要自行喂狗的話,注意先關閉proc進程中自動喂狗功能

2. REFCLK,PERST的配置錯誤,位置arch/mips/ralink/mt7620.c,原來的reclk和perst引腳配置反了

static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 37, 1) };
static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 36, 1) };

3. PHY 0-4的LED不能作爲GPIO的問題,參考補丁文件:

--- a/arch/mips/ralink/mt7620.c	2018-09-04 17:14:33.000000000 +0800
+++ b/arch/mips/ralink/mt7620.c	2018-04-09 08:28:51.000000000 +0800
@@ -138,8 +138,8 @@
 	FUNC("i2c", 0, 4, 2),
 };
 
-static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 36, 1) };
-static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 37, 1) };
+static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 37, 1) };
+static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 36, 1) };
 static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) };
 static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) };
 
@@ -185,23 +185,50 @@
 	FUNC("gpio", 0, 11, 1),
 };
 
-static struct rt2880_pmx_func wled_kn_grp_mt7628[] = {
-	FUNC("rsvd", 3, 35, 1),
-	FUNC("rsvd", 2, 35, 1),
-	FUNC("gpio", 1, 35, 1),
-	FUNC("wled_kn", 0, 35, 1),
+struct rt2880_pmx_func wled_an_grp_mt7628[] = {
+        FUNC("rsvd", 3, 44, 1),
+        FUNC("rsvd", 2, 44, 1),
+        FUNC("gpio", 1, 44, 1),
+        FUNC("wled_an", 0,44, 1),
+};
+
+static struct rt2880_pmx_func ephy_p0_grp_mt7628[] = {
+        FUNC("rsvd", 3, 43, 1),
+        FUNC("rsvd", 2, 43, 1),
+        FUNC("gpio", 1, 43, 1),
+        FUNC("ephy", 0, 43, 1),
+};
+
+static struct rt2880_pmx_func ephy_p1_grp_mt7628[] = {
+        FUNC("rsvd", 3, 42, 1),
+        FUNC("rsvd", 2, 42, 1),
+        FUNC("gpio", 1, 42, 1),
+        FUNC("ephy", 0, 42, 1),
+};
+static struct rt2880_pmx_func ephy_p2_grp_mt7628[] = {
+        FUNC("rsvd", 3, 41, 1),
+        FUNC("rsvd", 2, 41, 1),
+        FUNC("gpio", 1, 41, 1),
+        FUNC("ephy", 0, 41, 1),
+};
+static struct rt2880_pmx_func ephy_p3_grp_mt7628[] = {
+        FUNC("rsvd", 3, 40, 1),
+        FUNC("rsvd", 2, 40, 1),
+        FUNC("gpio", 1, 40, 1),
+        FUNC("ephy", 0, 40, 1),
+};
+static struct rt2880_pmx_func ephy_p4_grp_mt7628[] = {
+        FUNC("rsvd", 3, 39, 1),
+        FUNC("rsvd", 2, 39, 1),
+        FUNC("gpio", 1, 39, 1),
+        FUNC("ephy", 0, 39, 1),
 };
-
-static struct rt2880_pmx_func wled_an_grp_mt7628[] = {
-	FUNC("rsvd", 3, 44, 1),
-	FUNC("rsvd", 2, 44, 1),
-	FUNC("gpio", 1, 44, 1),
-	FUNC("wled_an", 0, 44, 1),
-};
-
 #define MT7628_GPIO_MODE_MASK		0x3
-
-#define MT7628_GPIO_MODE_WLED_KN	48
+#define MT7628_GPIO_MODE_EPHY_P4        42
+#define MT7628_GPIO_MODE_EPHY_P3        40
+#define MT7628_GPIO_MODE_EPHY_P2        38
+#define MT7628_GPIO_MODE_EPHY_P1        36
+#define MT7628_GPIO_MODE_EPHY_P0        34
 #define MT7628_GPIO_MODE_WLED_AN	32
 #define MT7628_GPIO_MODE_PWM1		30
 #define MT7628_GPIO_MODE_PWM0		28
@@ -236,7 +263,12 @@
 	GRP_G("spis", spis_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_SPIS),
 	GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_GPIO),
 	GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_WLED_AN),
-	GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_WLED_KN),
+		GRP_G("ephy_p0", ephy_p0_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_EPHY_P0),
+        GRP_G("ephy_p1", ephy_p1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_EPHY_P1),
+        GRP_G("ephy_p2", ephy_p2_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_EPHY_P2),
+        GRP_G("ephy_p3", ephy_p3_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_EPHY_P3),
+        GRP_G("ephy_p4", ephy_p4_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_EPHY_P4),
+
 	{ 0 }
 };
 
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章