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开启:
-
status = "okay";
-
};
SPI_CS1 开启,使用系统spi控制器,注意pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>,配置CS1为SPI_CS1功能,同时应该去掉pinctrl0中"spi cs1"的GPIO复用
-
status = "okay";
-
pinctrl-names = "default";
-
pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>;
-
#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>;
-
#address-cells = <0x1>;
-
compatible = "spidev";
-
spi-max-frequency = <10000000>;
-
reg = <0>;
-
};
-
};
I2C的RTC时钟配置,以PCF8563为例,注意reg地址的问题,pcf8563地址是0x51,常用的ds1307是0x68
-
status = "okay";
-
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: [email protected] {
-
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 }
-
};