很奇怪,设备树中配置了串口0、串口1、串口2,串口0和串口1都可以正常收发,串口2只能发送,无法接收到数据,接收引脚上有波形。
uart0_pins_a: uart-pins-pe {
pins = "PE0", "PE1";
function = "uart0";
};
uart1_pins_a: uart-pins-pd {
pins = "PD3", "PD4";
function = "uart1";
};
uart2_pins_a: uart2-pins-pd {
pins = "PD14", "PD13";
function = "uart2";
};
经过排查,发现PD14脚的复用功能并未生效,PD14还是禁用的状态(0x7),将其设置为0x3之后就可以收到数据了。
# devmem 0x01c20870
0x77377677
devmem 0x01c20870 32 0x73377677
设备树文件 suniv.dtsi
// SPDX-License-Identifier: (GPL-2.0+ OR X11)
/*
* Copyright 2018 Icenowy Zheng <icenowy@aosc.io>
*/
#include <dt-bindings/clock/suniv-ccu.h>
#include <dt-bindings/reset/suniv-ccu.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
clocks {
#address-cells = <1>;
#size-cells = <1>;
ranges;
osc24M: clk-24M {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "osc24M";
};
osc32k: clk-32k {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32768>;
clock-output-names = "osc32k";
};
fake100M: clk-100M {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <100000000>;
clock-output-names = "fake-100M";
};
};
cpus {
#address-cells = <0>;
#size-cells = <0>;
cpu {
compatible = "arm,arm926ej-s";
device_type = "cpu";
};
};
de: display-engine {
compatible = "allwinner,suniv-display-engine";
allwinner,pipelines = <&fe0>;
status = "disabled";
};
soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
sram-controller@1c00000 {
compatible = "allwinner,sun4i-a10-sram-controller";
reg = <0x01c00000 0x30>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
sram_d: sram@10000 {
compatible = "mmio-sram";
reg = <0x00010000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x00010000 0x1000>;
otg_sram: sram-section@0 {
compatible = "allwinner,sun4i-a10-sram-d";
reg = <0x0000 0x1000>;
status = "disabled";
};
};
};
spi0: spi@1c05000 {
compatible = "allwinner,suniv-spi",
"allwinner,sun8i-h3-spi";
reg = <0x01c05000 0x1000>;
interrupts = <10>;
clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_BUS_SPI0>;
clock-names = "ahb", "mod";
resets = <&ccu RST_BUS_SPI0>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
spi1: spi@1c06000 {
compatible = "allwinner,suniv-spi",
"allwinner,sun8i-h3-spi";
reg = <0x01c06000 0x1000>;
interrupts = <11>;
clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_BUS_SPI1>;
clock-names = "ahb", "mod";
resets = <&ccu RST_BUS_SPI1>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
tcon0: lcd-controller@1c0c000 {
compatible = "allwinner,suniv-tcon";
reg = <0x01c0c000 0x1000>;
interrupts = <29>;
clocks = <&ccu CLK_BUS_LCD>,
<&ccu CLK_TCON>,
<&osc24M>; /* Still unknown */
clock-names = "ahb",
"tcon-ch0",
"tcon-ch1";
clock-output-names = "tcon-pixel-clock";
resets = <&ccu RST_BUS_LCD>;
reset-names = "lcd";
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
tcon0_in: port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
tcon0_in_be0: endpoint@0 {
reg = <0>;
remote-endpoint = <&be0_out_tcon0>;
};
};
tcon0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
};
};
};
mmc0: mmc@1c0f000 {
compatible = "allwinner,suniv-mmc",
"allwinner,sun7i-a20-mmc";
reg = <0x01c0f000 0x1000>;
clocks = <&ccu CLK_BUS_MMC0>,
<&ccu CLK_MMC0>,
<&ccu CLK_MMC0_OUTPUT>,
<&ccu CLK_MMC0_SAMPLE>;
clock-names = "ahb",
"mmc",
"output",
"sample";
resets = <&ccu RST_BUS_MMC0>;
reset-names = "ahb";
interrupts = <23>;
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
mmc1: mmc@1c10000 {
compatible = "allwinner,suniv-mmc",
"allwinner,sun7i-a20-mmc";
reg = <0x01c10000 0x1000>;
clocks = <&ccu CLK_BUS_MMC1>,
<&ccu CLK_MMC1>,
<&ccu CLK_MMC1_OUTPUT>,
<&ccu CLK_MMC1_SAMPLE>;
clock-names = "ahb",
"mmc",
"output",
"sample";
resets = <&ccu RST_BUS_MMC1>;
reset-names = "ahb";
interrupts = <24>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
ccu: clock@1c20000 {
compatible = "allwinner,suniv-ccu";
reg = <0x01c20000 0x400>;
clocks = <&osc24M>, <&osc32k>;
clock-names = "hosc", "losc";
#clock-cells = <1>;
#reset-cells = <1>;
};
intc: interrupt-controller@1c20400 {
compatible = "allwinner,suniv-ic";
reg = <0x01c20400 0x400>;
interrupt-controller;
#interrupt-cells = <1>;
};
pio: pinctrl@1c20800 {
compatible = "allwinner,suniv-pinctrl";
reg = <0x01c20800 0x400>;
interrupts = <38>, <39>, <40>;
clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
clock-names = "apb", "hosc", "losc";
gpio-controller;
interrupt-controller;
#interrupt-cells = <3>;
#gpio-cells = <3>;
spi0_pins_a: spi0-pins-pc {
pins = "PC0", "PC1", "PC2", "PC3";
function = "spi0";
};
spi1_pins_a: spi1-pins-pc {
pins = "PE7", "PE8", "PE9", "PE10";
function = "spi1";
};
lcd_rgb666_pins: lcd-rgb666-pins {
pins = "PD0", "PD1", "PD2", "PD3", "PD4",
"PD5", "PD6", "PD7", "PD8", "PD9",
"PD10", "PD11", "PD12", "PD13", "PD14",
"PD15", "PD16", "PD17", "PD18", "PD19",
"PD20", "PD21";
function = "lcd";
};
uart0_pins_a: uart-pins-pe {
pins = "PE0", "PE1";
function = "uart0";
};
uart1_pins_a: uart-pins-pd {
pins = "PD3", "PD4";
function = "uart1";
};
uart2_pins_a: uart2-pins-pd {
pins = "PD14", "PD13";
function = "uart2";
};
mmc0_pins: mmc0-pins {
pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
function = "mmc0";
};
rtp_pins: rtp-pins {
pins = "PA0", "PA1", "PA2", "PA3";
function = "rtp";
};
i2c0_pins: i2c0 {
pins = "PE11", "PE12";
function = "i2c0";
};
i2c1_pins: i2c1 {
pins = "PD5", "PD6";
function = "i2c1";
};
spi_int: spi_int {
pins = "PE2";
function = "gpio_in";
};
};
timer@1c20c00 {
compatible = "allwinner,suniv-timer";
reg = <0x01c20c00 0x90>;
interrupts = <13>;
clocks = <&osc24M>;
};
wdt: watchdog@1c20ca0 {
compatible = "allwinner,sun6i-a31-wdt";
reg = <0x01c20ca0 0x20>;
};
rtp: rtp@1c24800 {
compatible = "allwinner,sun4i-a10-ts";
reg = <0x01c24800 0x100>;
interrupts = <20>;
allwinner,ts-attached;
#thermal-sensor-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&rtp_pins>;
status = "disabled";
};
uart0: serial@1c25000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c25000 0x400>;
interrupts = <1>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART0>;
resets = <&ccu RST_BUS_UART0>;
status = "disabled";
};
uart1: serial@1c25400 {
compatible = "snps,dw-apb-uart";
reg = <0x01c25400 0x400>;
interrupts = <2>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART1>;
resets = <&ccu RST_BUS_UART1>;
status = "disabled";
};
uart2: serial@1c25800 {
compatible = "snps,dw-apb-uart";
reg = <0x01c25800 0x400>;
interrupts = <3>;
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART2>;
resets = <&ccu RST_BUS_UART2>;
status = "disabled";
};
i2c0: i2c@1C27000 {
compatible = "allwinner,sun6i-a31-i2c";
reg = <0x01C27000 0x400>;
interrupts = <7>;
clocks = <&ccu CLK_BUS_I2C0>;
resets = <&ccu RST_BUS_I2C0>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
i2c1: i2c@1C27400 {
compatible = "allwinner,sun6i-a31-i2c";
reg = <0x01C27400 0x400>;
interrupts = <8>;
clocks = <&ccu CLK_BUS_I2C1>;
resets = <&ccu RST_BUS_I2C1>;
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
usb_otg: usb@1c13000 {
compatible = "allwinner,suniv-musb";
reg = <0x01c13000 0x0400>;
clocks = <&ccu CLK_BUS_OTG>;
resets = <&ccu RST_BUS_OTG>;
interrupts = <26>;
interrupt-names = "mc";
phys = <&usbphy 0>;
phy-names = "usb";
extcon = <&usbphy 0>;
allwinner,sram = <&otg_sram 1>;
status = "disabled";
};
usbphy: phy@1c13400 {
compatible = "allwinner,suniv-usb-phy";
reg = <0x01c13400 0x10>;
reg-names = "phy_ctrl";
clocks = <&ccu CLK_USB_PHY0>;
clock-names = "usb0_phy";
resets = <&ccu RST_USB_PHY0>;
reset-names = "usb0_reset";
#phy-cells = <1>;
status = "disabled";
};
fe0: display-frontend@1e00000 {
compatible = "allwinner,suniv-display-frontend";
reg = <0x01e00000 0x20000>;
interrupts = <30>;
clocks = <&ccu CLK_BUS_DE_FE>, <&ccu CLK_DE_FE>,
<&ccu CLK_DRAM_DE_FE>;
clock-names = "ahb", "mod",
"ram";
resets = <&ccu RST_BUS_DE_FE>;
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
fe0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
fe0_out_be0: endpoint@0 {
reg = <0>;
remote-endpoint = <&be0_in_fe0>;
};
};
};
};
be0: display-backend@1e60000 {
compatible = "allwinner,suniv-display-backend";
reg = <0x01e60000 0x10000>;
reg-names = "be";
interrupts = <31>;
clocks = <&ccu CLK_BUS_DE_BE>, <&ccu CLK_DE_BE>,
<&ccu CLK_DRAM_DE_BE>;
clock-names = "ahb", "mod",
"ram";
resets = <&ccu RST_BUS_DE_BE>;
reset-names = "be";
assigned-clocks = <&ccu CLK_DE_BE>;
assigned-clock-rates = <300000000>;
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
be0_in: port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
be0_in_fe0: endpoint@0 {
reg = <0>;
remote-endpoint = <&fe0_out_be0>;
};
};
be0_out: port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
be0_out_tcon0: endpoint@0 {
reg = <0>;
remote-endpoint = <&tcon0_in_be0>;
};
};
};
};
};
};
设备树 sunxi-f1c100s-nano.dts
// SPDX-License-Identifier: (GPL-2.0+ OR X11)
/*
* Copyright 2018 Icenowy Zheng <icenowy@aosc.io>
*/
/dts-v1/;
#include "suniv-f1c100s.dtsi"
#include <dt-bindings/gpio/gpio.h>
/ {
model = "Lichee Pi Nano";
compatible = "licheepi,licheepi-nano", "allwinner,suniv-f1c100s",
"allwinner,suniv";
aliases {
serial0 = &uart0;
spi0 = &spi0;
};
chosen {
stdout-path = "serial0:115200n8";
};
reg_vcc3v3: vcc3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
};
&otg_sram {
status = "okay";
};
&pio {
dm9051_default:dm9051_default{
};
dm9051_rst:dm9051_rst{
pins = "PE3";
};
dm9051_int:dm9051_int{
pins = "PE2";
};
};
/*&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins_a>;
status = "okay";
flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "winbond,w25q128", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <40000000>;
};
};*/
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins_a>;
status = "okay";
spi-max-frequency = <50000000>;
flash: w25q128@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "winbond,w25q128", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <50000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "u-boot";
reg = <0x000000 0x70000>;
read-only;
};
partition@70000 {
label = "dtb";
reg = <0x70000 0x10000>;
read-only;
};
partition@80000 {
label = "kernel";
reg = <0x80000 0x400000>;
read-only;
};
partition@480000 {
label = "rootfs";
reg = <0x480000 0xB80000>;
};
};
};
};
&spi1 {
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins_a>;
pinctrl-1 = <&spi1_pins_a>;
status = "okay";
spi-max-frequency = <25000000>;
dm9051@0 {
compatible = "davicom,dm9051";
reg = <0>;
spi-max-frequency = <25000000>;/*<109000000>;*/
dm9051_rst = <&pio 4 3 GPIO_ACTIVE_HIGH>; /* PE3 */
status = "okay";
};
};
&spi_int {
interrupt-parent = <&pio>;
interrupts = <39>; /* pe2 */
status = "okay";
};
&i2c1 {
clock_frequency = <400000>;
pinctrl-0 = <&i2c1_pins>;
pinctrl-names = "default";
status = "okay";
rtc@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
status = "okay";
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins_a>;
status = "okay";
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins_a>;
status = "okay";
};
&usb_otg {
dr_mode = "otg";
status = "okay";
};
&usbphy {
usb0_id_det-gpio = <&pio 3 10 GPIO_ACTIVE_HIGH>; /* PD10 */
status = "okay";
};
但是查了下设备树,唯一用到PD14的功能是rgb接口,但是并未启用。很奇怪为什么发送脚已经被正确设置了,接收脚却没有被正确设置复用。
离线
LOG中有一句
[ 0.832283] 1c25400.serial: ttyS1 at MMIO 0x1c25400 (irq = 23, base_baud = 6250000) is a 16550A
[ 0.841925] suniv-pinctrl 1c20800.pinctrl: unsupported function uart2 on pin PD14
[ 0.871149] 1c25800.serial: ttyS2 at MMIO 0x1c25800 (irq = 24, base_baud = 6250000) is a 16550A
[ 0.881947] SCSI Media Changer driver v0.25
回头查查pinctrl中是啥意思
离线
pinctrl 是登记 soc 芯片上面所有引脚复用。
你先搜索一下哪个 pinctrl 文件参与了编译:
find . |grep pinctrl |grep \\.o$
然后看下 D14 是不是没有注册复用UART功能, 只注册了GPIO。
查过了,
./drivers/pinctrl/sunxi/pinctrl-suniv.c 中 第 207行
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd"), /* D20 */
SUNXI_FUNCTION(0x3, "lvds1"), /* RX 这一行*/
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)),
应改为
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd"), /* D20 */
SUNXI_FUNCTION(0x3, "uart2"), /* RX 这一行*/
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)),
离线
那现在可以了吗?
没硬件可以测试,明天到公司测试一下,但看起来应该没啥问题
离线
https://github.com/torvalds/linux/blob/master/drivers/pinctrl/sunxi/pinctrl-suniv-f1c100s.c
SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
SUNXI_FUNCTION(0x2, "lcd"), /* D20 */
SUNXI_FUNCTION(0x3, "lvds1"), /* RX */
果然是这个惊天bug
离线
&spi1 {
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins_a>;
pinctrl-1 = <&spi1_pins_a>;
status = "okay";
spi-max-frequency = <25000000>;
dm9051@0 {
compatible = "davicom,dm9051";
reg = <0>;
spi-max-frequency = <25000000>;/*<109000000>;*/
dm9051_rst = <&pio 4 3 GPIO_ACTIVE_HIGH>; /* PE3 */
status = "okay";
};
};
厚脸求 "davicom,dm9051" 这个的驱动.
离线
好大的bug
离线
十分感谢 苦思冥想了好久 在这找到了答案
离线