背景
根據orangepi zero2使用者手冊說明,linux5.13核心不能使用 modprobe fbtft_device
驅動spi lcd
檢視linux核心原始碼提交記錄,發現在v5.4-rc3中刪除了fbtft_device.c檔案
commit如下
staging/fbtft: Remove fbtft_device
Commit c440eee ("Staging: fbtft: Switch to the gpio descriptor
interface") removed the gpio code from fbtft_device rendering it useless.
fbtft_device is a module that was used on the Raspberry Pi to dynamically
add fbtft devices when the Pi didn't have Device Tree support.
Just remove the module since it's the responsibility of Device Tree, ACPI
or platform code to add devices.
Fixes: c440eee ("Staging: fbtft: Switch to the gpio descriptor interface")
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Link: https://lore.kernel.org/r/20190917171843.10334-2-noralf@tronnes.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
“fbtft_device用來在樹莓派沒有裝置樹時,自動新增fbtft裝置,刪除這個模組因為新增裝置是裝置樹、ACPI或者平臺程式碼的責任”
所以是因為原來的程式碼不符合裝置和驅動分離的原則,所以給刪除了,但其實驅動程式依然在,理論上只需要將裝置硬體資訊註冊到核心,就可以正常執行了,可以透過裝置樹或者模組
dts
下面看下orangepi官方修改後的核心原始碼中的裝置樹,分支orange-pi-6.1-sun50iw9
https://github.com/orangepi-xunlong/linux-orangepi
sun50i-h616.dtsi
從晶片級(h616)的dts可以看到spi有spi0和spi1,spi0有一個cs0,spi1有cs0和cs1
/omit-if-no-ref/
spi0_pins: spi0-pins {
pins = "PC0", "PC2", "PC4";
function = "spi0";
};
/omit-if-no-ref/
spi0_cs0_pin: spi0-cs0-pin {
pins = "PC3";
function = "spi0";
};
/omit-if-no-ref/
spi1_pins: spi1-pins {
pins = "PH6", "PH7", "PH8";
function = "spi1";
};
/omit-if-no-ref/
spi1_cs0_pin: spi1-cs0-pin {
pins = "PH5";
function = "spi1";
};
/omit-if-no-ref/
spi1_cs1_pin: spi1-cs1-pin {
pins = "PH9";
function = "spi1";
};
spi1裝置只新增了cs1,cs0引腳沒有用在spi1上,而是複用在了i2c3
spi0: spi@5010000 {
compatible = "allwinner,sun50i-h616-spi",
"allwinner,sun8i-h3-spi";
reg = <0x05010000 0x1000>;
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
clock-names = "ahb", "mod";
resets = <&ccu RST_BUS_SPI0>;
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
dmas = <&dma 22>, <&dma 22>;
dma-names = "rx", "tx";
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
spi1: spi@5011000 {
compatible = "allwinner,sun50i-h616-spi",
"allwinner,sun8i-h3-spi";
reg = <0x05011000 0x1000>;
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
clock-names = "ahb", "mod";
resets = <&ccu RST_BUS_SPI1>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>, <&spi1_cs1_pin>;
dmas = <&dma 23>, <&dma 23>;
dma-names = "rx", "tx";
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
sun50i-h616-orangepi-zero2.dts
從板級(orangepi zero2)dts可以看到新增了一個spidev@1裝置,但是預設未啟用
&spi1 {
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>, <&spi1_cs1_pin>;
spidev@1 {
compatible = "rohm,dh2228fv";
status = "disabled";
reg = <1>;
spi-max-frequency = <1000000>;
};
};
硬體
可以看到spi0用來連線NOR FLASH,所以肯定不可以再用來連線lcd了
spi1在26PIN引出,並且cs0和cs1都有,不過cs0複用在了i2c3的TWI3-SDA引腳上,所以我們使用spi1驅動lcd,並且使用cs1
硬體接線如下,實際上就是使用者手冊推薦的連線
dts替換
新建ili9341.dts檔案
vim ili9341.dts
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target = <&spi1>;
__overlay__ {
status = "okay";
ili9341: ili9341@0 {
compatible = "ilitek,ili9341";
reg = <1>;
spi-max-frequency = <40000000>;
rotate = <0>;
bgr;
fps = <30>;
buswidth = <8>;
reset-gpios = <&pio 2 9 1>;
dc-gpios = <&pio 2 6 0>;
led-gpios = <&pio 2 5 0>;
debug = <0>;
};
};
};
};
替換裝置樹,執行後reboot
orangepi-add-overlay ili9341.dts
不出意外的話,console預設會顯示在lcd上,可以使用fbi指令測試
su root
apt update
apt install fbi
fbi -vt 1 -noverbose -d /dev/fb0 /boot/boot.bmp
關於pinctrl-0和cs-gpios
使用cs-gpios定義片選訊號使用的引腳,來自ChatGPT3.5
spi@40013000 {
compatible = "some-vendor,spi-bus";
reg = <0x40013000>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
cs-gpios = <&gpio1 10 0>, <&gpio1 11 0>; // 定義兩個片選 GPIO
spidev0: spidev@0 {
compatible = "some-vendor,spidev";
reg = <0>; // 對應 cs-gpios 的第一個 GPIO (gpio1 10)
spi-max-frequency = <10000000>;
status = "okay";
};
spidev1: spidev@1 {
compatible = "some-vendor,spidev";
reg = <1>; // 對應 cs-gpios 的第二個 GPIO (gpio1 11)
spi-max-frequency = <10000000>;
status = "okay";
};
};
pinctrl-0已經包含了spi1_cs1_pin,所以spidev的reg直接使用1也可以找到,就不需要cs-gpios了
&spi1 {
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>, <&spi1_cs1_pin>;
spidev@1 {
compatible = "rohm,dh2228fv";
status = "disabled";
reg = <1>;
spi-max-frequency = <1000000>;
};
};