MT7688修改Linux下内核驱动中的dts文件,管脚复用功能转换之4通道PWM
1.首先,DTS部分的知识就不说了,使用的内核版本为openWrt 15.05
BusyBox v1.23.2 (2019-02-02 12:12:33 CST) built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
2.查看以下DTS文件(路径)target/linux/ramips/dts/LINKIT7688.dts 其中有以下定义
pinctrl {
state_default: pinctrl0 {
gpio {
ralink,group = "gpio";
ralink,function = "gpio";
};
perst {
ralink,group = "perst";
ralink,function = "gpio";
};
refclk {
ralink,group = "refclk";
ralink,function = "gpio";
};
i2s {
ralink,group = "i2s";
ralink,function = "gpio";
};
spis {
ralink,group = "spis";
ralink,function = "gpio";
};
wled_kn {
ralink,group = "wled_kn";
ralink,function = "gpio";
};
wled_an {
ralink,group = "wled_an";
ralink,function = "wled_an";
};
wdt {
ralink,group = "wdt";
ralink,function = "gpio";
};
};
};
ralink,group = "wled_an"; ralink,function = "wled_an";这里的group、function 到底是啥东西,向我这个第一次看到这玩意的人简直就是简直。。。。
没法子找资料,看代码;最后明白了这个DTS文件对应的解析文件在linux-3.18.45/arch/mips/ralink/mt7620.c中。请看以下代码:
static struct rt2880_pmx_func pwm1_grp_mt7628[] = {
FUNC("sdxc d6", 3, 19, 1),
FUNC("utif", 2, 19, 1),
FUNC("gpio", 1, 19, 1),
FUNC("pwm1", 0, 19, 1),
};
static struct rt2880_pmx_func pwm0_grp_mt7628[] = {
FUNC("sdxc d7", 3, 18, 1),
FUNC("utif", 2, 18, 1),
FUNC("gpio", 1, 18, 1),
FUNC("pwm0", 0, 18, 1),
};
static struct rt2880_pmx_func uart2_grp_mt7628[] = {
FUNC("sdxc d5 d4", 3, 20, 2),
FUNC("pwm", 2, 20, 2),
FUNC("gpio", 1, 20, 2),
FUNC("uart2", 0, 20, 2),
};
static struct rt2880_pmx_func uart1_grp_mt7628[] = {
FUNC("sw_r", 3, 45, 2),
FUNC("pwm", 2, 45, 2),
FUNC("gpio", 1, 45, 2),
FUNC("uart1", 0, 45, 2),
};
static struct rt2880_pmx_func i2c_grp_mt7628[] = {
FUNC("-", 3, 4, 2),
FUNC("debug", 2, 4, 2),
FUNC("gpio", 1, 4, 2),
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 wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) };
static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) };
static struct rt2880_pmx_func sd_mode_grp_mt7628[] = {
FUNC("jtag", 3, 22, 8),
FUNC("utif", 2, 22, 8),
FUNC("gpio", 1, 22, 8),
FUNC("sdxc", 0, 22, 8),
};
static struct rt2880_pmx_func uart0_grp_mt7628[] = {
FUNC("-", 3, 12, 2),
FUNC("-", 2, 12, 2),
FUNC("gpio", 1, 12, 2),
FUNC("uart0", 0, 12, 2),
};
static struct rt2880_pmx_func i2s_grp_mt7628[] = {
FUNC("antenna", 3, 0, 4),
FUNC("pcm", 2, 0, 4),
FUNC("gpio", 1, 0, 4),
FUNC("i2s", 0, 0, 4),
};
static struct rt2880_pmx_func spi_cs1_grp_mt7628[] = {
FUNC("-", 3, 6, 1),
FUNC("refclk", 2, 6, 1),
FUNC("gpio", 1, 6, 1),
FUNC("spi cs1", 0, 6, 1),
};
static struct rt2880_pmx_func spis_grp_mt7628[] = {
FUNC("pwm", 3, 14, 4),
FUNC("util", 2, 14, 4),
FUNC("gpio", 1, 14, 4),
FUNC("spis", 0, 14, 4),
};
static struct rt2880_pmx_func gpio_grp_mt7628[] = {
FUNC("pcie", 3, 11, 1),
FUNC("refclk", 2, 11, 1),
FUNC("gpio", 1, 11, 1),
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),
};
static struct rt2880_pmx_func wled_an_grp_mt7628[] = {
FUNC("rsvd", 3, 35, 1),
FUNC("rsvd", 2, 35, 1),
FUNC("gpio", 1, 35, 1),
FUNC("wled_an", 0, 35, 1),
};
#define MT7628_GPIO_MODE_MASK 0x3
#define MT7628_GPIO_MODE_WLED_KN 48
#define MT7628_GPIO_MODE_WLED_AN 32
#define MT7628_GPIO_MODE_PWM1 30
#define MT7628_GPIO_MODE_PWM0 28
#define MT7628_GPIO_MODE_UART2 26
#define MT7628_GPIO_MODE_UART1 24
#define MT7628_GPIO_MODE_I2C 20
#define MT7628_GPIO_MODE_REFCLK 18
#define MT7628_GPIO_MODE_PERST 16
#define MT7628_GPIO_MODE_WDT 14
#define MT7628_GPIO_MODE_SPI 12
#define MT7628_GPIO_MODE_SDMODE 10
#define MT7628_GPIO_MODE_UART0 8
#define MT7628_GPIO_MODE_I2S 6
#define MT7628_GPIO_MODE_CS1 4
#define MT7628_GPIO_MODE_SPIS 2
#define MT7628_GPIO_MODE_GPIO 0
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),
GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_WLED_KN),
{ 0 }
};
ralink,group = "wled_an"; 就是 GRP_G("wled_an", ; ralink,function = "wled_an";就是FUNC("wled_an" ,好明确了这一点后修改吧。
3.pwm0 和pwm1默认状态下使用,所以修改uart2中的复用管脚pwm2 pwm3 ,修改如下;
A。首先你采用的是什么单板就使用哪一个DTS文件,例如LINK7688.DTS下
uart2@e00 {
// status = "okay";//modefied by carn
};
将UART2功能关闭,另外文件引用了/include/ "mt7628an.dtsi",修改"mt7628an.dtsi"如下:
[......]
pwm@5000 {
compatible = "mediatek,mt7628-pwm";
reg = <0x5000 0x1000>;
resets = <&rstctrl 31>;
reset-names = "pwm";
pinctrl-names = "default";
//pinctrl-0 = <&pwm0_pins>, <&pwm1_pins>;//modefied by carn
pinctrl-0 = <&pwm0_pins>, <&pwm1_pins>, <&uart2_pins>;//增加uart2_pins中的引脚
status = "disabled";
};
[......]
uart2_pins: uart2 {
uart2 {
ralink,group = "uart2";
//ralink,function = "uart2";
ralink,function = "pwm";//将这组引脚复用成pwm功能
};
};
[......]
保存退出 :wq 编译刷固件
默认情况下内核中已有驱动了路径:linux-3.18.45/drivers/pwm/pwm-mediatek.c
root@**:/sys/class/pwm# ls
pwmchip0
root@**:/sys/class/pwm# cd pwmchip0/
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0# ls
device export npwm subsystem uevent unexport
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0# echo 0 > export
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0# echo 1 > export
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0# echo 2 > export
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0# echo 3 > export
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0# ls
device npwm pwm1 pwm3 uevent
export pwm0 pwm2 subsystem unexport
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0# cd pwm3/
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0/pwm3# ls
duty_cycle enable period polarity uevent
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0/pwm3# echo 1000000 > period
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0/pwm3# echo 500000 > duty_cycle
root@**:/sys/devices/10000000.palmbus/10005000.pwm/pwm/pwmchip0/pwm3# echo 1 > enable