4 Commits

Author SHA1 Message Date
thead_admin
f4327ba402 Linux_SDK_V1.2.1
Signed-off-by: thead_admin <occ_thead@service.alibaba.com>
2023-08-19 00:37:34 +08:00
jianghai
599b048690 eth: gmac: adapt to support DMA 32-bit in skb 2023-07-30 04:42:32 +08:00
thead_admin
b269dc8fa7 apply lpi4a patches 2023-07-30 04:42:27 +08:00
Han Gao
87e5c31f94 Linux_SDK_V1.2.0 2023-07-30 04:39:12 +08:00
121 changed files with 10225 additions and 954 deletions

View File

@@ -21,7 +21,6 @@ config RISCV
select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_KCOV select ARCH_HAS_KCOV
select ARCH_HAS_MMIOWB
select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_SET_DIRECT_MAP select ARCH_HAS_SET_DIRECT_MAP
select ARCH_HAS_SET_MEMORY select ARCH_HAS_SET_MEMORY
@@ -35,6 +34,7 @@ config RISCV
select ARCH_KEEP_MEMBLOCK select ARCH_KEEP_MEMBLOCK
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_RWLOCKS
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_FRAME_POINTERS

View File

@@ -12,15 +12,17 @@ dtb-$(CONFIG_SOC_THEAD) += light-a-val-ddr2G.dtb light-a-val-ddr1G.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-npu-fce.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-npu-fce.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-iso7816.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-iso7816.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-nand.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-nand.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio.dtb light-a-val-audio-i2s-8ch.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-dsi0.dtb light-a-val-dsi1.dtb light-a-val-hdmi.dtb light-a-val-dsi0-dsi1.dtb light-a-val-dsi0-hdmi.dtb light-a-val-dpi0.dtb light-a-val-dpi0-dpi1.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio-tdm.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio-spdif.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-dsi0.dtb light-a-val-dsi1.dtb light-a-val-hdmi.dtb light-a-val-dsi0-dsi1.dtb light-a-val-dsi0-hdmi.dtb light-a-val-dsi0-hdmi-audio.dtb light-a-val-dpi0.dtb light-a-val-dpi0-dpi1.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-wcn.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-wcn.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-gpio-keys.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-gpio-keys.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-khv.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-khv.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-sec.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-sec.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-miniapp-hdmi.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-miniapp-hdmi.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-product.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-product.dtb
dtb-$(CONFIG_SOC_THEAD) += light-b-product.dtb dtb-$(CONFIG_SOC_THEAD) += light-b-product.dtb light-b-product-sec.dtb
dtb-$(CONFIG_SOC_THEAD) += light-b-product-ddr1G.dtb dtb-$(CONFIG_SOC_THEAD) += light-b-product-ddr1G.dtb
dtb-$(CONFIG_SOC_THEAD) += light-b-product-miniapp-hdmi.dtb dtb-$(CONFIG_SOC_THEAD) += light-b-product-miniapp-hdmi.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-full.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-full.dtb
@@ -37,3 +39,4 @@ dtb-$(CONFIG_SOC_THEAD) += light-a-val-android.dtb
dtb-$(CONFIG_SOC_THEAD) += fire-emu.dtb fire-emu-crash.dtb dtb-$(CONFIG_SOC_THEAD) += fire-emu.dtb fire-emu-crash.dtb
dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base.dtb fire-emu-soc-c910x4.dtb fire-emu-gpu-dpu-dsi0.dtb fire-emu-vi-dsp-vo.dtb fire-emu-vi-vp-vo.dtb dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base.dtb fire-emu-soc-c910x4.dtb fire-emu-gpu-dpu-dsi0.dtb fire-emu-vi-dsp-vo.dtb fire-emu-vi-vp-vo.dtb
dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base-sec.dtb

View File

@@ -523,7 +523,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238

View File

@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
/dts-v1/;
/* #include "fire-emu.dts" */
#include "fire-emu-soc-base.dts"
&light_iopmp {
status = "disabled";
};

View File

@@ -338,16 +338,18 @@
clock-frequency = <100000>; clock-frequency = <100000>;
status = "disabled"; status = "disabled";
es8156_audio_codec: es8156@8 { es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
}; status = "disabled";
};
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
status = "disabled";
}; };
}; };
@@ -488,7 +490,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238

View File

@@ -373,7 +373,7 @@
entry-cnt = <4>; entry-cnt = <4>;
control-reg = <0xff 0xff015004>; control-reg = <0xff 0xff015004>;
control-val = <0x1c>; control-val = <0x1c>;
csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>;
}; };
clint0: clint@ffdc000000 { clint0: clint@ffdc000000 {
@@ -1335,8 +1335,7 @@
emmc: sdhci@ffe7080000 { emmc: sdhci@ffe7080000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7080000 0x0 0x10000 reg = <0xff 0xe7080000 0x0 0x10000>;
0xff 0xef014060 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <62>; interrupts = <62>;
interrupt-names = "sdhciirq"; interrupt-names = "sdhciirq";
@@ -1346,8 +1345,7 @@
sdhci0: sd@ffe7090000 { sdhci0: sd@ffe7090000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7090000 0x0 0x10000 reg = <0xff 0xe7090000 0x0 0x10000>;
0xff 0xef014064 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <64>; interrupts = <64>;
interrupt-names = "sdhci0irq"; interrupt-names = "sdhci0irq";
@@ -1357,8 +1355,7 @@
sdhci1: sd@ffe70a0000 { sdhci1: sd@ffe70a0000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe70a0000 0x0 0x10000 reg = <0xff 0xe70a0000 0x0 0x10000>;
0xff 0xef014064 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <71>; interrupts = <71>;
interrupt-names = "sdhci1irq"; interrupt-names = "sdhci1irq";
@@ -1433,7 +1430,7 @@
compatible = "light,light-i2s"; compatible = "light,light-i2s";
reg = <0xff 0xe7034000 0x0 0x4000>; reg = <0xff 0xe7034000 0x0 0x4000>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_i2s0>; pinctrl-0 = <&pinctrl_light_i2s0>;
light,mode = "i2s-master"; light,mode = "i2s-master";
light,sel = "ap_i2s"; light,sel = "ap_i2s";
interrupt-parent = <&intc>; interrupt-parent = <&intc>;

View File

@@ -687,6 +687,7 @@
no-mmc; no-mmc;
non-removable; non-removable;
io_fixed_1v8; io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>; post-power-on-delay-ms = <50>;
wprtn_ignore; wprtn_ignore;
cap-sd-highspeed; cap-sd-highspeed;
@@ -729,7 +730,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238

View File

@@ -63,7 +63,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };

View File

@@ -5,7 +5,7 @@
/dts-v1/; /dts-v1/;
#include "light-a-val.dts" #include "light-a-val-audio.dts"
/ { / {
display-subsystem { display-subsystem {
@@ -40,28 +40,6 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>;
format = "i2s";
cpu {
sound-dai = <&i2s0 0>;
};
codec {
sound-dai = <&es8156_audio_codec>;
};
};
simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s3 0>;
};
codec {
sound-dai = <&es7210_audio_codec>;
};
};
simple-audio-card,dai-link@2 { /* I2S - HDMI */ simple-audio-card,dai-link@2 { /* I2S - HDMI */
reg = <2>; reg = <2>;
@@ -70,7 +48,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };
@@ -78,12 +56,3 @@
&light_i2s { &light_i2s {
status = "okay"; status = "okay";
}; };
&i2s0 {
status = "okay";
};
&i2s3 {
status = "okay";
};

View File

@@ -0,0 +1,100 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
#include "light-a-val-audio.dts"
/ {
model = "T-HEAD Light FM Audio VAL board";
compatible = "thead,light-val-audio-i2s-8ch", "thead,light";
};
&lightsound {
status = "okay";
simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
mclk-fs = <512>;
sound-dai = <&es7210_audio_codec_adc0>;
};
};
simple-audio-card,dai-link@2 { /* I2S - AUDIO SYS CODEC 7210*/
reg = <2>;
format = "i2s";
cpu {
sound-dai = <&i2s_8ch_sd3 3>;
};
codec {
mclk-fs = <512>;
sound-dai = <&es7210_audio_codec_adc0>;
};
};
simple-audio-card,dai-link@3 { /* I2S - AUDIO SYS CODEC 7210_1*/
reg = <3>;
format = "i2s";
cpu {
sound-dai = <&i2s_8ch_sd0 0>;
};
codec {
mclk-fs = <512>;
sound-dai = <&es7210_audio_codec_adc1>;
};
};
simple-audio-card,dai-link@4 { /* I2S - AUDIO SYS CODEC 7210_1*/
reg = <4>;
format = "i2s";
cpu {
sound-dai = <&i2s_8ch_sd1 1>;
};
codec {
mclk-fs = <512>;
sound-dai = <&es7210_audio_codec_adc1>;
};
};
};
&i2s_8ch_sd0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa4>,
<&pinctrl_audio_i2s_8ch_sd0>,
<&pinctrl_audiopa2>,
<&pinctrl_audiopa3>,
<&pinctrl_audiopa8>,
<&pinctrl_audio_i2s_8ch_bus>;
};
&i2s_8ch_sd1 {
status = "okay";
};
&i2s_8ch_sd2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa0>,
<&pinctrl_audio_i2s_8ch_sd2>;
};
&i2s_8ch_sd3 {
status = "okay";
};
&es7210_audio_codec_adc0 {
status = "okay";
channels-max = <8>;
};
&es7210_audio_codec_adc1 {
status = "okay";
channels-max = <8>;
};

View File

@@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
#include "light-a-val.dts"
&spdif0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_spdif0>;
status = "okay";
};
&spdif1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_spdif1>;
status = "okay";
};
&lightsound {
status = "okay";
simple-audio-card,dai-link@0 { /* SPDIF0 */
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&spdif0>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
simple-audio-card,dai-link@1 { /* SPDIF1 */
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&spdif1>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};

View File

@@ -0,0 +1,182 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
#include "light-a-val.dts"
&tdm_slot1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_tdm>;
status = "okay";
};
&tdm_slot2 {
status = "okay";
};
&tdm_slot3 {
status = "okay";
};
&tdm_slot4 {
status = "okay";
};
&tdm_slot5 {
status = "okay";
};
&tdm_slot6 {
status = "okay";
};
&tdm_slot7 {
status = "okay";
};
&tdm_slot8 {
status = "okay";
};
&audio_i2c0 {
clock-frequency = <100000>;
status = "okay";
es7210_adc2: es7210@42 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
reg = <0x42>;
work-mode = "ES7210_TDM_1LRCK_DSPB";
channels-max = <8>;
sound-name-prefix = "ES7210_ADC2";
MVDD-supply = <&soc_aud_adc_3v3_en_reg>;
AVDD-supply = <&soc_aud_adc_3v3_en_reg>;
DVDD-supply = <&soc_dvdd18_aon_reg>;
PVDD-supply = <&soc_dvdd18_aon_reg>;
};
es7210_adc3: es7210@43 {
#sound-dai-cells = <0>;
compatible = "MicArray_1";
reg = <0x43>;
work-mode = "ES7210_TDM_1LRCK_DSPB";
channels-max = <8>;
sound-name-prefix = "ES7210_ADC3";
MVDD-supply = <&soc_aud_adc_3v3_en_reg>;
AVDD-supply = <&soc_aud_adc_3v3_en_reg>;
DVDD-supply = <&soc_dvdd18_aon_reg>;
PVDD-supply = <&soc_dvdd18_aon_reg>;
};
};
&lightsound {
status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"AW87519 IN", "ES8156 ROUT",
"Speaker", "AW87519 VO";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>;
format = "i2s";
cpu {
sound-dai = <&i2s0 0>;
};
codec {
sound-dai = <&es8156_audio_codec>;
};
};
simple-audio-card,dai-link@1 { /* TDM - AUDIO SYS CODEC 7210*/
reg = <1>;
format = "dsp_b";
cpu {
sound-dai = <&tdm_slot1>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
simple-audio-card,dai-link@2 {
reg = <1>;
format = "dsp_b";
cpu {
sound-dai = <&tdm_slot2>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
simple-audio-card,dai-link@3 {
reg = <1>;
format = "dsp_b";
cpu {
sound-dai = <&tdm_slot3>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
simple-audio-card,dai-link@4 {
reg = <1>;
format = "dsp_b";
cpu {
sound-dai = <&tdm_slot4>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
simple-audio-card,dai-link@5 {
reg = <1>;
format = "dsp_b";
cpu {
sound-dai = <&tdm_slot5>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
simple-audio-card,dai-link@6 {
reg = <1>;
format = "dsp_b";
cpu {
sound-dai = <&tdm_slot6>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
simple-audio-card,dai-link@7 {
reg = <1>;
format = "dsp_b";
cpu {
sound-dai = <&tdm_slot7>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
simple-audio-card,dai-link@8 {
reg = <1>;
format = "dsp_b";
cpu {
sound-dai = <&tdm_slot8>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
};
&i2s0 {
status = "okay";
};

View File

@@ -11,8 +11,12 @@
}; };
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -28,22 +32,24 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s3 0>; sound-dai = <&i2s_8ch_sd2 2>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec_adc0>;
}; };
}; };
}; };
&light_i2s {
status = "okay";
};
&i2s0 { &i2s0 {
status = "okay"; status = "okay";
}; };
&i2s3 { &i2s_8ch_sd2 {
status = "okay"; status = "okay";
}; };
&es7210_audio_codec_adc0 {
status = "okay";
};

View File

@@ -11,7 +11,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x40000000>; reg = <0x0 0x200000 0x0 0x3fe00000>;
}; };
}; };

View File

@@ -11,7 +11,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
}; };

View File

@@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
/dts-v1/;
#include "light-a-val-dsi0-hdmi.dts"
&lightsound {
status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>;
format = "i2s";
cpu {
sound-dai = <&i2s0 0>;
};
codec {
sound-dai = <&es8156_audio_codec>;
};
};
simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
sound-dai = <&es7210_audio_codec_adc0>;
};
};
simple-audio-card,dai-link@2 { /* I2S - HDMI */
reg = <2>;
format = "i2s";
cpu {
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
&light_i2s {
status = "okay";
};
&i2s0 {
status = "okay";
};
&i2s_8ch_sd2 {
status = "okay";
};
&es7210_audio_codec_adc0 {
status = "okay";
};

View File

@@ -95,7 +95,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -111,23 +115,27 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s3 0>; sound-dai = <&i2s_8ch_sd2 2>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec_adc0>;
}; };
}; };
}; };
&light_i2s { &light_i2s {
status = "okay"; status = "okay";
}; };
&i2s0 { &i2s0 {
status = "okay"; status = "okay";
}; };
&i2s3 { &i2s_8ch_sd2 {
status = "okay";
};
&es7210_audio_codec_adc0 {
status = "okay"; status = "okay";
}; };

View File

@@ -48,7 +48,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };

View File

@@ -74,6 +74,26 @@
}; };
}; };
&padctrl_audiosys {
status = "okay";
light-audio-padctrl {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_audio_i2s_8ch: audio_i2s_8ch_grp {
thead,pins = <
FM_AUDIO_IO_PA0 0x2 0x008
FM_AUDIO_IO_PA2 0x2 0x008
FM_AUDIO_IO_PA3 0x2 0x008
FM_AUDIO_IO_PA8 0x2 0x008
>;
};
};
};
&lightsound { &lightsound {
status = "okay"; status = "okay";
@@ -92,15 +112,14 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s3 0>; sound-dai = <&i2s_8ch_sd2 2>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec_adc0>;
}; };
}; };
}; };
&light_i2s { &light_i2s {
status = "okay"; status = "okay";
}; };
@@ -109,7 +128,11 @@
status = "okay"; status = "okay";
}; };
&i2s3 { &i2s_8ch_sd2 {
status = "okay";
};
&es7210_audio_codec_adc0 {
status = "okay"; status = "okay";
}; };

View File

@@ -56,10 +56,10 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s3 0>; sound-dai = <&i2s_8ch_sd2 2>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec_adc0>;
}; };
}; };
}; };
@@ -73,7 +73,11 @@
status = "okay"; status = "okay";
}; };
&i2s3 { &i2s_8ch_sd2 {
status = "okay";
};
&es7210_audio_codec_adc0 {
status = "okay"; status = "okay";
}; };

View File

@@ -5,9 +5,13 @@
/dts-v1/; /dts-v1/;
#include "light-a-val-dsi0-hdmi.dts" #include "light-a-val-audio-hdmi.dts"
&light_iopmp { &light_iopmp {
status = "disabled"; status = "disabled";
}; };
&qspi1 {
status = "disabled";
};

View File

@@ -179,7 +179,8 @@
compatible = "thead,light-mbox-client"; compatible = "thead,light-mbox-client";
mbox-names = "906"; mbox-names = "906";
mboxes = <&mbox_910t 2 0>; mboxes = <&mbox_910t 2 0>;
status = "disabled"; audio-mbox-regmap = <&audio_mbox>;
status = "okay";
}; };
lightsound: lightsound@1 { lightsound: lightsound@1 {
@@ -192,9 +193,24 @@
status = "disabled"; status = "disabled";
}; };
light_rpmsg: light_rpmsg {
compatible = "light,rpmsg-bus", "simple-bus";
memory-region = <&rpmsgmem>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
rpmsg: rpmsg{
vdev-nums = <1>;
reg = <0x0 0x1E000000 0 0x10000>;
compatible = "light,light-rpmsg";
status = "okay";
};
};
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
sound-name-prefix = "DUMMY";
status = "okay"; status = "okay";
}; };
@@ -262,6 +278,24 @@
enable-active-high; enable-active-high;
}; };
soc_aud_adc_3v3_en_reg: soc-aud-adc-3v3-en {
compatible = "regulator-fixed";
regulator-name = "soc_aud_adc_3v3_en";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pcal6408ahk_b 1 1>;
enable-active-high;
};
soc_aud_dac_3v3_en_reg: soc-aud-dac-3v3-en {
compatible = "regulator-fixed";
regulator-name = "soc_aud_dac_3v3_en";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pcal6408ahk_b 2 1>;
enable-active-high;
};
wcn_wifi: wireless-wlan { wcn_wifi: wireless-wlan {
compatible = "wlan-platdata"; compatible = "wlan-platdata";
clock-names = "clk_wifi"; clock-names = "clk_wifi";
@@ -512,7 +546,14 @@
reg = <0x0 0x22000000 0x0 0x10000000>; reg = <0x0 0x22000000 0x0 0x10000000>;
no-map; no-map;
}; };
audio_mem: memory@32000000 {
reg = <0x0 0x32000000 0x0 0x6400000>;
no-map;
};
rpmsgmem: memory@1E000000 {
reg = <0x0 0x1E000000 0x0 0x10000>;
no-map;
};
}; };
&adc { &adc {
@@ -556,17 +597,74 @@
&audio_i2c0 { &audio_i2c0 {
clock-frequency = <100000>; clock-frequency = <100000>;
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa6>,
<&pinctrl_audiopa7>,
<&pinctrl_audio_i2c0>;
es8156_audio_codec: es8156@8 { es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
}; sound-name-prefix = "ES8156";
AVDD-supply = <&soc_aud_dac_3v3_en_reg>;
DVDD-supply = <&soc_dvdd18_aon_reg>;
PVDD-supply = <&soc_dvdd18_aon_reg>;
mclk-sclk-ratio = <4>;
};
es7210_audio_codec: es7210@40 { es7210_audio_codec_adc0: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
status = "disabled";
work-mode = "ES7210_NORMAL_I2S";
channels-max = <2>;
mclk-sclk-ratio = <4>;
sound-name-prefix = "ES7210_ADC0";
MVDD-supply = <&soc_aud_adc_3v3_en_reg>;
AVDD-supply = <&soc_aud_adc_3v3_en_reg>;
DVDD-supply = <&soc_dvdd18_aon_reg>;
PVDD-supply = <&soc_dvdd18_aon_reg>;
};
es7210_audio_codec_adc1: es7210@41 {
#sound-dai-cells = <0>;
compatible = "MicArray_1";
reg = <0x41>;
status = "disabled";
work-mode = "ES7210_NORMAL_I2S";
channels-max = <2>;
mclk-sclk-ratio = <4>;
sound-name-prefix = "ES7210_ADC1";
MVDD-supply = <&soc_aud_adc_3v3_en_reg>;
AVDD-supply = <&soc_aud_adc_3v3_en_reg>;
DVDD-supply = <&soc_dvdd18_aon_reg>;
PVDD-supply = <&soc_dvdd18_aon_reg>;
};
audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa";
reg = <0x58>;
reset-gpio = <&pcal6408ahk_b 3 0x1>;
sound-name-prefix = "AW87519";
status = "okay";
};
};
&audio_i2c1 {
clock-frequency = <100000>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa13>,
<&pinctrl_audiopa16>,
<&pinctrl_audio_i2c1>;
pcal6408ahk_b: gpio@20 {
compatible = "nxp,pcal9554b";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
}; };
}; };
@@ -717,6 +815,7 @@
no-mmc; no-mmc;
non-removable; non-removable;
io_fixed_1v8; io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>; post-power-on-delay-ms = <50>;
wprtn_ignore; wprtn_ignore;
cap-sd-highspeed; cap-sd-highspeed;
@@ -759,7 +858,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238
@@ -834,22 +933,151 @@
* Format: <pin_id mux_node config> * Format: <pin_id mux_node config>
*/ */
pinctrl_audiopa1: audiopa1_grp { pinctrl_audiopa0: audiopa0 {
thead,pins = < thead,pins = < FM_AUDIO_PA0 LIGHT_PIN_FUNC_0 0x000 >;
FM_AUDIO_PA1 0x3 0x72
>;
}; };
pinctrl_audiopa1: audiopa1 {
pinctrl_audiopa2: audiopa2_grp { thead,pins = < FM_AUDIO_PA1 LIGHT_PIN_FUNC_0 0x000 >;
thead,pins = < };
FM_AUDIO_PA2 0x0 0x72 pinctrl_audiopa2: audiopa2 {
>; thead,pins = < FM_AUDIO_PA2 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa3: audiopa3 {
thead,pins = < FM_AUDIO_PA3 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa4: audiopa4 {
thead,pins = < FM_AUDIO_PA4 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa5: audiopa5 {
thead,pins = < FM_AUDIO_PA5 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa6: audiopa6 {
thead,pins = < FM_AUDIO_PA6 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa7: audiopa7 {
thead,pins = < FM_AUDIO_PA7 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa8: audiopa8 {
thead,pins = < FM_AUDIO_PA8 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa9: audiopa9 {
thead,pins = < FM_AUDIO_PA9 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa10: audiopa10 {
thead,pins = < FM_AUDIO_PA10 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa11: audiopa11 {
thead,pins = < FM_AUDIO_PA11 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa12: audiopa12 {
thead,pins = < FM_AUDIO_PA12 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa13: audiopa13 {
thead,pins = < FM_AUDIO_PA13 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa14: audiopa14 {
thead,pins = < FM_AUDIO_PA14 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa15: audiopa15 {
thead,pins = < FM_AUDIO_PA15 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa16: audiopa16 {
thead,pins = < FM_AUDIO_PA16 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa17: audiopa17 {
thead,pins = < FM_AUDIO_PA17 LIGHT_PIN_FUNC_0 0x000 >;
}; };
pinctrl_volume: volume_grp { pinctrl_volume: volume_grp {
thead,pins = < thead,pins = <
FM_CPU_JTG_TDI 0x3 0x208 FM_CPU_JTG_TDI 0x3 0x238
FM_CPU_JTG_TDO 0x3 0x208 FM_CPU_JTG_TDO 0x3 0x238
>;
};
};
};
&padctrl_audiosys {
status = "okay";
light-audio-padctrl {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_audio_i2c0: audio_i2c0_grp {
thead,pins = <
FM_AUDIO_IO_PA6 LIGHT_PIN_FUNC_0 0x004
FM_AUDIO_IO_PA7 LIGHT_PIN_FUNC_0 0x004
>;
};
pinctrl_audio_i2c1: audio_i2c1_grp {
thead,pins = <
FM_AUDIO_IO_PA13 LIGHT_PIN_FUNC_1 0x004
FM_AUDIO_IO_PA16 LIGHT_PIN_FUNC_3 0x004
>;
};
pinctrl_audio_i2s0: audio_i2s0_grp {
thead,pins = <
FM_AUDIO_IO_PA9 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA10 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA11 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA12 LIGHT_PIN_FUNC_0 0x008
>;
};
pinctrl_audio_i2s1: audio_i2s1_grp {
thead,pins = <
FM_AUDIO_IO_PA14 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA15 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA17 LIGHT_PIN_FUNC_0 0x008
>;
};
pinctrl_audio_i2s_8ch_bus: audio_i2s_8ch_bus_grp {
thead,pins = <
FM_AUDIO_IO_PA2 LIGHT_PIN_FUNC_3 0x008
FM_AUDIO_IO_PA3 LIGHT_PIN_FUNC_3 0x008
FM_AUDIO_IO_PA8 LIGHT_PIN_FUNC_3 0x008
>;
};
pinctrl_audio_i2s_8ch_sd0: audio_i2s_8ch_sd0_grp {
thead,pins = <
FM_AUDIO_IO_PA4 LIGHT_PIN_FUNC_3 0x008
>;
};
pinctrl_audio_i2s_8ch_sd1: audio_i2s_8ch_sd1_grp {
thead,pins = <
FM_AUDIO_IO_PA5 LIGHT_PIN_FUNC_3 0x008
>;
};
pinctrl_audio_i2s_8ch_sd2: audio_i2s_8ch_sd2_grp {
thead,pins = <
FM_AUDIO_IO_PA0 LIGHT_PIN_FUNC_3 0x008
>;
};
pinctrl_audio_i2s_8ch_sd3: audio_i2s_8ch_sd3_grp {
thead,pins = <
FM_AUDIO_IO_PA1 LIGHT_PIN_FUNC_3 0x008
>;
};
pinctrl_audio_tdm: audio_tdm_grp {
thead,pins = <
FM_AUDIO_IO_PA27 LIGHT_PIN_FUNC_1 0x007
FM_AUDIO_IO_PA28 LIGHT_PIN_FUNC_1 0x007
FM_AUDIO_IO_PA29 LIGHT_PIN_FUNC_1 0x000
>;
};
pinctrl_audio_spdif0: audio_spdif0_grp {
thead,pins = <
FM_AUDIO_IO_PA21 LIGHT_PIN_FUNC_1 0x000
FM_AUDIO_IO_PA22 LIGHT_PIN_FUNC_1 0x007
>;
};
pinctrl_audio_spdif1: audio_spdif1_grp {
thead,pins = <
FM_AUDIO_IO_PA23 LIGHT_PIN_FUNC_1 0x007
FM_AUDIO_IO_PA24 LIGHT_PIN_FUNC_1 0x000
>; >;
}; };
}; };
@@ -989,6 +1217,24 @@
status = "disabled"; status = "disabled";
}; };
&vvcam_sensor1 {
sensor_name = "OV5693";
sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB";
sensor_regulator_voltage_uV = <1800000 1200000 2800000>;
sensor_regulator_timing_us = <70 50 20>;
sensor_rst = <&gpio1_porta 16 0>;
sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>;
DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>;
AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>;
i2c_reg_width = /bits/ 8 <2>;
i2c_data_width = /bits/ 8 <1>;
i2c_addr = /bits/ 8 <0x36>;
i2c_bus = /bits/ 8 <3>;
status = "okay";
};
&vvcam_sensor2 { &vvcam_sensor2 {
sensor_name = "GC5035"; sensor_name = "GC5035";
sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN"; sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN";
@@ -1073,6 +1319,22 @@
status = "okay"; status = "okay";
}; };
&vvcam_sensor7 {
sensor_name = "IMX334";
sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB";
sensor_regulator_timing_us = <70 50 20>;
sensor_rst = <&gpio1_porta 16 0>;
sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>;
DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>;
AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>;
i2c_reg_width = /bits/ 8 <2>;
i2c_data_width = /bits/ 8 <1>;
i2c_addr = /bits/ 8 <0x1a>;
i2c_bus = /bits/ 8 <3>;
status = "okay";
};
&video0{ &video0{
vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2] vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2]
channel0 { channel0 {
@@ -1279,13 +1541,20 @@
mode_idx = <0>; mode_idx = <0>;
path_type = "SENSOR_1600x1200_RAW10_LINER"; path_type = "SENSOR_1600x1200_RAW10_LINER";
}; };
sensor2 {
subdev_name = "vivcam";
idx = <7>; //imx334
csi_idx = <0>; //<0>=CSI2
mode_idx = <0>;
path_type = "SENSOR_3840x2180_RAW12_LINER";
};
isp { isp {
subdev_name = "isp"; subdev_name = "isp";
idx = <1>; idx = <1>;
path_type = "ISP_MI_PATH_MP"; path_type = "ISP_MI_PATH_MP";
output { output {
max_width = <1920>; max_width = <3840>;
max_height = <1088>; max_height = <2180>;
bit_per_pixel = <16>; bit_per_pixel = <16>;
frame_count = <3>; frame_count = <3>;
}; };
@@ -2138,6 +2407,44 @@
status = "okay"; status = "okay";
}; };
&i2s0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa9>,
<&pinctrl_audiopa10>,
<&pinctrl_audiopa11>,
<&pinctrl_audiopa12>,
<&pinctrl_audio_i2s0>;
};
&i2s_8ch_sd0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa4>,
<&pinctrl_audio_i2s_8ch_sd0>;
};
&i2s_8ch_sd1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa5>,
<&pinctrl_audio_i2s_8ch_sd1>;
};
&i2s_8ch_sd2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa0>,
<&pinctrl_audio_i2s_8ch_sd2>,
<&pinctrl_audiopa2>,
<&pinctrl_audiopa3>,
<&pinctrl_audiopa8>,
<&pinctrl_audio_i2s_8ch_bus>;
};
&i2s_8ch_sd3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa1>,
<&pinctrl_audio_i2s_8ch_sd3>;
};
&cpus { &cpus {
c910_0: cpu@0 { c910_0: cpu@0 {
operating-points = < operating-points = <

View File

@@ -15,7 +15,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
chosen { chosen {
@@ -194,9 +194,10 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -581,24 +582,31 @@
clock-frequency = <100000>; clock-frequency = <100000>;
status = "okay"; status = "okay";
es8156_audio_codec: es8156@8 { es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
}; sound-name-prefix = "ES8156";
AVDD-supply = <&soc_aud_3v3_en_reg>;
DVDD-supply = <&soc_aud_1v8_en_reg>;
PVDD-supply = <&soc_aud_1v8_en_reg>;
};
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
status = "disabled";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
status = "okay"; sound-name-prefix = "AW87519";
}; status = "okay";
};
}; };
&i2c1 { &i2c1 {
@@ -731,6 +739,7 @@
no-mmc; no-mmc;
non-removable; non-removable;
io_fixed_1v8; io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>; post-power-on-delay-ms = <50>;
wprtn_ignore; wprtn_ignore;
cap-sd-highspeed; cap-sd-highspeed;
@@ -773,7 +782,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238
@@ -2091,6 +2100,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -2105,7 +2119,7 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s3 0>; sound-dai = <&i2s_8ch_sd2 2>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec>;
@@ -2118,7 +2132,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };
@@ -2135,7 +2149,7 @@
status = "okay"; status = "okay";
}; };
&i2s3 { &i2s_8ch_sd2 {
status = "okay"; status = "okay";
}; };

View File

@@ -15,7 +15,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
chosen { chosen {
@@ -194,9 +194,10 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -238,7 +239,8 @@
gpio-keys { gpio-keys {
compatible = "gpio-keys"; compatible = "gpio-keys";
pinctrl-0 = <&pinctrl_volume>; pinctrl-0 = <&pinctrl_volume_up
&pinctrl_volume_down>;
pinctrl-names = "default"; pinctrl-names = "default";
key-volumedown { key-volumedown {
label = "Volume Down Key"; label = "Volume Down Key";
@@ -588,24 +590,31 @@
clock-frequency = <100000>; clock-frequency = <100000>;
status = "okay"; status = "okay";
es8156_audio_codec: es8156@8 { es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
}; sound-name-prefix = "ES8156";
AVDD-supply = <&soc_aud_3v3_en_reg>;
DVDD-supply = <&soc_aud_1v8_en_reg>;
PVDD-supply = <&soc_aud_1v8_en_reg>;
};
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
status = "disabled";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
status = "okay"; sound-name-prefix = "AW87519";
}; status = "okay";
};
}; };
&i2c1 { &i2c1 {
@@ -738,6 +747,7 @@
no-mmc; no-mmc;
non-removable; non-removable;
io_fixed_1v8; io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>; post-power-on-delay-ms = <50>;
wprtn_ignore; wprtn_ignore;
cap-sd-highspeed; cap-sd-highspeed;
@@ -780,7 +790,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238
@@ -797,6 +807,12 @@
FM_GPIO3_2 0x1 0x208 /* pwm0 */ FM_GPIO3_2 0x1 0x208 /* pwm0 */
>; >;
}; };
pinctrl_volume_up: volume_up_grp {
thead,pins = <
FM_GPIO2_25 0x0 0x238
>;
};
}; };
}; };
@@ -842,9 +858,9 @@
>; >;
}; };
pinctrl_volume: volume_grp { pinctrl_volume_down: volume_down_grp {
thead,pins = < thead,pins = <
FM_CLK_OUT_2 0x3 0x208 FM_CLK_OUT_2 0x3 0x238
>; >;
}; };
}; };
@@ -2265,6 +2281,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -2279,7 +2300,7 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s3 0>; sound-dai = <&i2s_8ch_sd2 2>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec>;
@@ -2292,7 +2313,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };
@@ -2309,7 +2330,7 @@
status = "okay"; status = "okay";
}; };
&i2s3 { &i2s_8ch_sd2 {
status = "okay"; status = "okay";
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x40000000>; reg = <0x0 0x200000 0x0 0x3fe00000>;
}; };
}; };

View File

@@ -5,7 +5,7 @@
/dts-v1/; /dts-v1/;
#include "light-b-product.dts" #include "light-b-audio-hdmi.dts"

View File

@@ -15,7 +15,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
chosen { chosen {
@@ -180,7 +180,8 @@
compatible = "thead,light-mbox-client"; compatible = "thead,light-mbox-client";
mbox-names = "906"; mbox-names = "906";
mboxes = <&mbox_910t 2 0>; mboxes = <&mbox_910t 2 0>;
status = "disabled"; audio-mbox-regmap = <&audio_mbox>;
status = "okay";
}; };
lightsound: lightsound@1 { lightsound: lightsound@1 {
@@ -193,10 +194,25 @@
status = "disabled"; status = "disabled";
}; };
light_rpmsg: light_rpmsg {
compatible = "light,rpmsg-bus", "simple-bus";
memory-region = <&rpmsgmem>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
rpmsg: rpmsg{
vdev-nums = <1>;
reg = <0x0 0x1E000000 0 0x10000>;
compatible = "light,light-rpmsg";
status = "okay";
};
};
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -270,6 +286,8 @@
regulator-name = "soc_aud_3v3_en"; regulator-name = "soc_aud_3v3_en";
regulator-min-microvolt = <3300000>; regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>; regulator-max-microvolt = <3300000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_3v3_en>;
gpio = <&ao_gpio_porta 7 1>; gpio = <&ao_gpio_porta 7 1>;
enable-active-high; enable-active-high;
regulator-always-on; regulator-always-on;
@@ -280,6 +298,8 @@
regulator-name = "soc_aud_1v8_en"; regulator-name = "soc_aud_1v8_en";
regulator-min-microvolt = <1800000>; regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>; regulator-max-microvolt = <1800000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_1v8_en>;
gpio = <&ao_gpio_porta 8 1>; gpio = <&ao_gpio_porta 8 1>;
enable-active-high; enable-active-high;
regulator-always-on; regulator-always-on;
@@ -569,7 +589,14 @@
reg = <0x0 0x17000000 0 0x02000000>; reg = <0x0 0x17000000 0 0x02000000>;
no-map; no-map;
}; };
audio_mem: memory@32000000 {
reg = <0x0 0x32000000 0x0 0x6400000>;
no-map;
};
rpmsgmem: memory@1E000000 {
reg = <0x0 0x1E000000 0x0 0x10000>;
no-map;
};
}; };
@@ -600,23 +627,43 @@
&audio_i2c0 { &audio_i2c0 {
clock-frequency = <100000>; clock-frequency = <100000>;
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa6>,
<&pinctrl_audiopa7>,
<&pinctrl_audio_i2c0>;
es8156_audio_codec: es8156@8 { es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
}; sound-name-prefix = "ES8156";
AVDD-supply = <&soc_aud_3v3_en_reg>;
DVDD-supply = <&soc_aud_1v8_en_reg>;
PVDD-supply = <&soc_aud_1v8_en_reg>;
mclk-sclk-ratio = <4>;
};
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
work-mode = "ES7210_NORMAL_I2S";
channels-max = <2>;
mclk-sclk-ratio = <4>;
sound-name-prefix = "ES7210_ADC0";
MVDD-supply = <&soc_aud_3v3_en_reg>;
AVDD-supply = <&soc_aud_3v3_en_reg>;
DVDD-supply = <&soc_aud_1v8_en_reg>;
PVDD-supply = <&soc_aud_1v8_en_reg>;
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
pingctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_pa_rst0>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay"; status = "okay";
}; };
}; };
@@ -750,6 +797,7 @@
no-mmc; no-mmc;
non-removable; non-removable;
io_fixed_1v8; io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>; post-power-on-delay-ms = <50>;
wprtn_ignore; wprtn_ignore;
cap-sd-highspeed; cap-sd-highspeed;
@@ -792,7 +840,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238
@@ -866,27 +914,103 @@
* Format: <pin_id mux_node config> * Format: <pin_id mux_node config>
*/ */
pinctrl_audiopa1: audiopa1_grp { pinctrl_audiopa0: audiopa0 {
thead,pins = < thead,pins = < FM_AUDIO_PA0 LIGHT_PIN_FUNC_0 0x000 >;
FM_AUDIO_PA1 0x3 0x72
>;
}; };
pinctrl_audiopa1: audiopa1 {
pinctrl_audiopa2: audiopa2_grp { thead,pins = < FM_AUDIO_PA1 LIGHT_PIN_FUNC_0 0x000 >;
thead,pins = < };
FM_AUDIO_PA2 0x0 0x72 pinctrl_audiopa2: audiopa2 {
>; thead,pins = < FM_AUDIO_PA2 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa3: audiopa3 {
thead,pins = < FM_AUDIO_PA3 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa6: audiopa6 {
thead,pins = < FM_AUDIO_PA6 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa7: audiopa7 {
thead,pins = < FM_AUDIO_PA7 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa8: audiopa8 {
thead,pins = < FM_AUDIO_PA8 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audio_pa_rst0: audio_pa_rst0 {
thead,pins = < FM_AUDIO_PA9 LIGHT_PIN_FUNC_3 0x000 >;
};
pinctrl_audiopa13: audiopa13 {
thead,pins = < FM_AUDIO_PA13 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa14: audiopa14 {
thead,pins = < FM_AUDIO_PA14 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa15: audiopa15 {
thead,pins = < FM_AUDIO_PA15 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa17: audiopa17 {
thead,pins = < FM_AUDIO_PA17 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audio_3v3_en: audio_3v3_en {
thead,pins = < FM_AOGPIO_7 LIGHT_PIN_FUNC_3 0x008 >;
};
pinctrl_audio_1v8_en: audio_1v8_en {
thead,pins = < FM_AOGPIO_8 LIGHT_PIN_FUNC_3 0x008 >;
}; };
pinctrl_volume: volume_grp { pinctrl_volume: volume_grp {
thead,pins = < thead,pins = <
FM_AOGPIO_11 0x0 0x208 FM_AOGPIO_11 0x0 0x238
FM_AOGPIO_10 0x3 0x208 FM_AOGPIO_10 0x3 0x238
>; >;
}; };
}; };
}; };
&padctrl_audiosys {
status = "okay";
light-audio-padctrl {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_audio_i2c0: audio_i2c0_grp {
thead,pins = <
FM_AUDIO_IO_PA6 LIGHT_PIN_FUNC_0 0x004
FM_AUDIO_IO_PA7 LIGHT_PIN_FUNC_0 0x004
>;
};
pinctrl_audio_i2s1: audio_i2s1_grp {
thead,pins = <
FM_AUDIO_IO_PA13 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA14 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA15 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA17 LIGHT_PIN_FUNC_0 0x008
>;
};
pinctrl_audio_i2s_8ch_bus: audio_i2s_8ch_bus_grp {
thead,pins = <
FM_AUDIO_IO_PA2 LIGHT_PIN_FUNC_3 0x008
FM_AUDIO_IO_PA3 LIGHT_PIN_FUNC_3 0x008
FM_AUDIO_IO_PA8 LIGHT_PIN_FUNC_3 0x008
>;
};
pinctrl_audio_i2s_8ch_sd2: audio_i2s_8ch_sd2_grp {
thead,pins = <
FM_AUDIO_IO_PA0 LIGHT_PIN_FUNC_3 0x008
>;
};
pinctrl_audio_i2s_8ch_sd3: audio_i2s_8ch_sd3_grp {
thead,pins = <
FM_AUDIO_IO_PA1 LIGHT_PIN_FUNC_3 0x008
>;
};
};
};
&i2c0 { &i2c0 {
clock-frequency = <400000>; clock-frequency = <400000>;
status = "okay"; status = "okay";
@@ -1000,30 +1124,21 @@
status = "okay"; status = "okay";
}; };
/* &vvcam_sensor1 {
&vvcam_sensor0 { sensor_name = "OV5693";
sensor_name = "IMX334"; sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB";
sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB"; sensor_regulator_voltage_uV = <1800000 1200000 2800000>;
sensor_regulator_timing_us = <70 50 20>; sensor_regulator_timing_us = <70 50 20>;
sensor_rst = <&gpio1_porta 16 0>; sensor_rst = <&gpio1_porta 16 0>;
sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>; DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>;
DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>; DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>;
AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>; AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>;
i2c_reg_width = /bits/ 8 <2>; i2c_reg_width = /bits/ 8 <2>;
i2c_data_width = /bits/ 8 <1>; i2c_data_width = /bits/ 8 <1>;
i2c_addr = /bits/ 8 <0x1a>; i2c_addr = /bits/ 8 <0x36>;
i2c_bus = /bits/ 8 <3>; i2c_bus = /bits/ 8 <3>;
status = "okay"; status = "okay";
};
*/
&vvcam_sensor1 {
sensor_name = "OV5693";
i2c_bus = /bits/ 8 <3>;
i2c_reg_width = /bits/ 8 <1>;
i2c_data_width = /bits/ 8 <1>;
status = "disabled";
}; };
&vvcam_sensor2 { &vvcam_sensor2 {
@@ -1108,6 +1223,22 @@
status = "okay"; status = "okay";
}; };
&vvcam_sensor7 {
sensor_name = "IMX334";
sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB";
sensor_regulator_timing_us = <70 50 20>;
sensor_rst = <&gpio1_porta 16 0>;
sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>;
DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>;
AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>;
i2c_reg_width = /bits/ 8 <2>;
i2c_data_width = /bits/ 8 <1>;
i2c_addr = /bits/ 8 <0x1a>;
i2c_bus = /bits/ 8 <3>;
status = "okay";
};
&video0{ &video0{
vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2] vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2]
channel0 { channel0 {
@@ -1314,13 +1445,20 @@
mode_idx = <0>; mode_idx = <0>;
path_type = "SENSOR_1600x1200_RAW10_LINER"; path_type = "SENSOR_1600x1200_RAW10_LINER";
}; };
sensor2 {
subdev_name = "vivcam";
idx = <7>; //imx334
csi_idx = <0>; //<0>=CSI2
mode_idx = <0>;
path_type = "SENSOR_3840x2180_RAW12_LINER";
};
isp { isp {
subdev_name = "isp"; subdev_name = "isp";
idx = <1>; idx = <1>;
path_type = "ISP_MI_PATH_MP"; path_type = "ISP_MI_PATH_MP";
output { output {
max_width = <1920>; max_width = <3840>;
max_height = <1088>; max_height = <2180>;
bit_per_pixel = <16>; bit_per_pixel = <16>;
frame_count = <3>; frame_count = <3>;
}; };
@@ -2313,6 +2451,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -2327,7 +2470,7 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s3 0>; sound-dai = <&i2s_8ch_sd2 2>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec>;
@@ -2340,7 +2483,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };
@@ -2355,10 +2498,29 @@
&i2s1 { &i2s1 {
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa13>,
<&pinctrl_audiopa14>,
<&pinctrl_audiopa15>,
<&pinctrl_audiopa17>,
<&pinctrl_audio_i2s1>;
}; };
&i2s3 { &i2s_8ch_sd2 {
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa0>,
<&pinctrl_audio_i2s_8ch_sd2>,
<&pinctrl_audiopa2>,
<&pinctrl_audiopa3>,
<&pinctrl_audiopa8>,
<&pinctrl_audio_i2s_8ch_bus>;
};
&i2s_8ch_sd3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa1>,
<&pinctrl_audio_i2s_8ch_sd3>;
}; };
&cpus { &cpus {

View File

@@ -15,7 +15,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
chosen { chosen {
@@ -194,9 +194,10 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -569,24 +570,34 @@
clock-frequency = <100000>; clock-frequency = <100000>;
status = "okay"; status = "okay";
es8156_audio_codec: es8156@8 { es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
}; sound-name-prefix = "ES8156";
AVDD-supply = <&soc_aud_3v3_en_reg>;
DVDD-supply = <&soc_aud_1v8_en_reg>;
PVDD-supply = <&soc_aud_1v8_en_reg>;
};
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
MVDD-supply = <&soc_aud_3v3_en_reg>;
AVDD-supply = <&soc_aud_3v3_en_reg>;
DVDD-supply = <&soc_aud_1v8_en_reg>;
PVDD-supply = <&soc_aud_1v8_en_reg>;
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
status = "okay"; sound-name-prefix = "AW87519";
}; status = "okay";
};
}; };
&i2c1 { &i2c1 {
@@ -719,6 +730,7 @@
no-mmc; no-mmc;
non-removable; non-removable;
io_fixed_1v8; io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>; post-power-on-delay-ms = <50>;
wprtn_ignore; wprtn_ignore;
cap-sd-highspeed; cap-sd-highspeed;
@@ -761,7 +773,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238
@@ -2249,6 +2261,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -2263,7 +2280,7 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s3 0>; sound-dai = <&i2s_8ch_sd2 2>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec>;
@@ -2276,7 +2293,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };
@@ -2293,7 +2310,7 @@
status = "okay"; status = "okay";
}; };
&i2s3 { &i2s_8ch_sd2 {
status = "okay"; status = "okay";
}; };

View File

@@ -191,8 +191,9 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
sound-name-prefix = "DUMMY";
status = "okay"; status = "okay";
}; };
@@ -341,18 +342,23 @@
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
status = "disabled";
}; };
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
status = "disabled";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay"; status = "okay";
}; };
}; };
@@ -488,6 +494,7 @@
no-mmc; no-mmc;
non-removable; non-removable;
io_fixed_1v8; io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>; post-power-on-delay-ms = <50>;
wprtn_ignore; wprtn_ignore;
cap-sd-highspeed; cap-sd-highspeed;
@@ -530,7 +537,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238
@@ -862,22 +869,6 @@
status = "disabled"; status = "disabled";
}; };
&light_i2s {
status = "okay";
};
&i2s0 {
status = "okay";
};
&i2s1 {
status = "okay";
};
&i2s3 {
status = "okay";
};
&khvhost { &khvhost {
status = "disabled"; status = "disabled";
}; };

View File

@@ -309,7 +309,7 @@
entry-cnt = <4>; entry-cnt = <4>;
control-reg = <0xff 0xff015004>; control-reg = <0xff 0xff015004>;
control-val = <0x1c>; control-val = <0x1c>;
csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>;
}; };
clint0: clint@ffdc000000 { clint0: clint@ffdc000000 {

View File

@@ -318,7 +318,7 @@
entry-cnt = <4>; entry-cnt = <4>;
control-reg = <0xff 0xff015004>; control-reg = <0xff 0xff015004>;
control-val = <0x1c>; control-val = <0x1c>;
csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>;
}; };
clint0: clint@ffdc000000 { clint0: clint@ffdc000000 {
@@ -1193,8 +1193,7 @@
emmc: sdhci@ffe7080000 { emmc: sdhci@ffe7080000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7080000 0x0 0x10000 reg = <0xff 0xe7080000 0x0 0x10000>;
0xff 0xef014060 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <62>; interrupts = <62>;
interrupt-names = "sdhciirq"; interrupt-names = "sdhciirq";
@@ -1204,8 +1203,7 @@
sdhci0: sd@ffe7090000 { sdhci0: sd@ffe7090000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7090000 0x0 0x10000 reg = <0xff 0xe7090000 0x0 0x10000>;
0xff 0xef014064 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <64>; interrupts = <64>;
interrupt-names = "sdhci0irq"; interrupt-names = "sdhci0irq";
@@ -1215,8 +1213,7 @@
sdhci1: sd@ffe70a0000 { sdhci1: sd@ffe70a0000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe70a0000 0x0 0x10000 reg = <0xff 0xe70a0000 0x0 0x10000>;
0xff 0xef014064 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <71>; interrupts = <71>;
interrupt-names = "sdhci1irq"; interrupt-names = "sdhci1irq";
@@ -1302,7 +1299,7 @@
compatible = "light,light-i2s"; compatible = "light,light-i2s";
reg = <0xff 0xe7034000 0x0 0x4000>; reg = <0xff 0xe7034000 0x0 0x4000>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_i2s0>; pinctrl-0 = <&pinctrl_light_i2s0>;
light,mode = "i2s-master"; light,mode = "i2s-master";
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <70>; interrupts = <70>;

View File

@@ -185,7 +185,7 @@
sound-dai = <&light_i2s 0>; sound-dai = <&light_i2s 0>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
@@ -196,7 +196,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };

View File

@@ -11,7 +11,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
}; };

View File

@@ -172,7 +172,8 @@
compatible = "thead,light-mbox-client"; compatible = "thead,light-mbox-client";
mbox-names = "906"; mbox-names = "906";
mboxes = <&mbox_910t 2 0>; mboxes = <&mbox_910t 2 0>;
status = "disabled"; audio-mbox-regmap = <&audio_mbox>;
status = "okay";
}; };
lightsound: lightsound@1 { lightsound: lightsound@1 {
@@ -185,10 +186,32 @@
status = "disabled"; status = "disabled";
}; };
light_rpmsg: light_rpmsg {
compatible = "light,rpmsg-bus", "simple-bus";
memory-region = <&rpmsgmem>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
rpmsg: rpmsg{
vdev-nums = <1>;
reg = <0x0 0x1E000000 0 0x10000>;
compatible = "light,light-rpmsg";
status = "okay";
};
};
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
};
fan: pwm-fan {
compatible = "pwm-fan";
#cooling-cells = <2>;
pwms = <&pwm 1 10000000 0>;
cooling-levels = <0 64 192 255>;
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -196,7 +219,7 @@
regulator-name = "vref-1v8"; regulator-name = "vref-1v8";
regulator-min-microvolt = <1800000>; regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>; regulator-max-microvolt = <1800000>;
status = "okay"; status = "okay";
}; };
reg_tp_pwr_en: regulator-pwr-en { reg_tp_pwr_en: regulator-pwr-en {
@@ -281,7 +304,6 @@
regulator-name = "soc_aud_3v3_en"; regulator-name = "soc_aud_3v3_en";
regulator-min-microvolt = <3300000>; regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>; regulator-max-microvolt = <3300000>;
gpio = <&pcal6408ahk_a 1 1>;
enable-active-high; enable-active-high;
regulator-always-on; regulator-always-on;
}; };
@@ -291,7 +313,6 @@
regulator-name = "soc_aud_1v8_en"; regulator-name = "soc_aud_1v8_en";
regulator-min-microvolt = <1800000>; regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>; regulator-max-microvolt = <1800000>;
gpio = <&pcal6408ahk_a 0 1>;
enable-active-high; enable-active-high;
regulator-always-on; regulator-always-on;
}; };
@@ -361,6 +382,7 @@
regulator-min-microvolt = <2800000>; regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>; regulator-max-microvolt = <2800000>;
gpio = <&pcal6408ahk_b 1 1>; gpio = <&pcal6408ahk_b 1 1>;
regulator-always-on;
enable-active-high; enable-active-high;
}; };
@@ -370,6 +392,7 @@
regulator-min-microvolt = <2800000>; regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>; regulator-max-microvolt = <2800000>;
gpio = <&pcal6408ahk_b 2 1>; gpio = <&pcal6408ahk_b 2 1>;
regulator-always-on;
enable-active-high; enable-active-high;
}; };
@@ -379,6 +402,7 @@
regulator-min-microvolt = <2800000>; regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>; regulator-max-microvolt = <2800000>;
gpio = <&pcal6408ahk_b 0 1>; gpio = <&pcal6408ahk_b 0 1>;
regulator-always-on;
enable-active-high; enable-active-high;
}; };
@@ -558,6 +582,48 @@
}; };
}; };
thermal-zones {
cpu-thermal-zone {
trips {
fan_config0: fan-trip0 {
temperature = <40000>;
hysteresis = <5000>;
type = "active";
};
fan_config1: fan-trip1 {
temperature = <50000>;
hysteresis = <5000>;
type = "active";
};
fan_config2: fan-trip2 {
temperature = <60000>;
hysteresis = <5000>;
type = "active";
};
};
cooling-maps {
fan-on {
trip = <&fan_config0>;
cooling-device =
<&fan 1 1>;
};
fan-faster {
trip = <&fan_config1>;
cooling-device =
<&fan 2 2>;
};
fan-full {
trip = <&fan_config2>;
cooling-device =
<&fan 3 3>;
};
};
};
};
}; };
&resmem { &resmem {
@@ -594,6 +660,14 @@
reg = <0x0 0x17000000 0 0x02000000>; reg = <0x0 0x17000000 0 0x02000000>;
no-map; no-map;
}; };
audio_mem: memory@32000000 {
reg = <0x0 0x32000000 0x0 0x6400000>;
no-map;
};
rpmsgmem: memory@1E000000 {
reg = <0x0 0x1E000000 0x0 0x10000>;
no-map;
};
}; };
@@ -606,44 +680,53 @@
&audio_i2c0 { &audio_i2c0 {
clock-frequency = <100000>; clock-frequency = <100000>;
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa29>,
<&pinctrl_audiopa30>,
<&pinctrl_audio_i2c0>;
es8156_audio_codec: es8156@8 { es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
AVDD-supply = <&soc_aud_3v3_en_reg>;
DVDD-supply = <&soc_aud_1v8_en_reg>;
PVDD-supply = <&soc_aud_1v8_en_reg>;
}; };
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
MVDD-supply = <&soc_aud_3v3_en_reg>;
AVDD-supply = <&soc_aud_3v3_en_reg>;
DVDD-supply = <&soc_aud_1v8_en_reg>;
PVDD-supply = <&soc_aud_1v8_en_reg>;
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&pcal6408ahk_a 2 0x1>; sound-name-prefix = "AW87519";
status = "okay"; status = "disabled";
}; };
audio_aw87519_pa1@5b { audio_aw87519_pa1@5b {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x5b>; reg = <0x5b>;
reset-gpio = <&pcal6408ahk_a 3 0x1>;
status = "disabled"; status = "disabled";
}; };
pcal6408ahk_a: gpio@20 {
compatible = "nxp,pcal9554b";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
};
}; };
&audio_i2c1 { &audio_i2c1 {
clock-frequency = <100000>; clock-frequency = <100000>;
status = "okay"; status = "okay";
pinctrl-0 = <&pinctrl_audiopa6>,
<&pinctrl_audiopa7>,
<&pinctrl_audio_i2c1>;
es8156_audio_codec_1: es8156@8 { es8156_audio_codec_1: es8156@8 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
@@ -662,14 +745,12 @@
audio_aw87519_pa2@58 { audio_aw87519_pa2@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&pcal6408ahk_a 4 0x1>;
status = "disabled"; status = "disabled";
}; };
audio_aw87519_pa3@5b { audio_aw87519_pa3@5b {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x5b>; reg = <0x5b>;
reset-gpio = <&pcal6408ahk_a 5 0x1>;
status = "disabled"; status = "disabled";
}; };
}; };
@@ -706,7 +787,7 @@
num-cs = <1>; num-cs = <1>;
cs-gpios = <&gpio2_porta 3 0>; cs-gpios = <&gpio2_porta 3 0>;
rx-sample-dly = <4>; rx-sample-dly = <4>;
status = "okay"; status = "disabled";
spi-flash@0 { spi-flash@0 {
#address-cells = <1>; #address-cells = <1>;
@@ -841,7 +922,7 @@
>; >;
}; };
pinctrl_audio_i2s0: i2s0grp { pinctrl_light_i2s0: i2s0grp {
thead,pins = < thead,pins = <
FM_QSPI0_SCLK 0x2 0x208 FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238 FM_QSPI0_CSN0 0x2 0x238
@@ -929,17 +1010,94 @@
FM_AUDIO_PA2 0x0 0x72 FM_AUDIO_PA2 0x0 0x72
>; >;
}; };
pinctrl_audiopa6: audiopa6 {
thead,pins = < FM_AUDIO_PA6 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa7: audiopa7 {
thead,pins = < FM_AUDIO_PA7 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa14: audiopa14 {
thead,pins = < FM_AUDIO_PA14 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa15: audiopa15 {
thead,pins = < FM_AUDIO_PA15 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa16: audiopa16 {
thead,pins = < FM_AUDIO_PA16 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa17: audiopa17 {
thead,pins = < FM_AUDIO_PA17 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa18: audiopa18 {
thead,pins = < FM_AOGPIO_7 LIGHT_PIN_FUNC_1 0x000 >;
};
pinctrl_audiopa19: audiopa19 {
thead,pins = < FM_AOGPIO_8 LIGHT_PIN_FUNC_1 0x000 >;
};
pinctrl_audiopa21: audiopa21 {
thead,pins = < FM_AOGPIO_10 LIGHT_PIN_FUNC_1 0x000 >;
};
pinctrl_audiopa22: audiopa22 {
thead,pins = < FM_AOGPIO_11 LIGHT_PIN_FUNC_1 0x000 >;
};
pinctrl_audiopa29: audiopa29 {
thead,pins = < FM_AUDIO_PA29 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa30: audiopa30 {
thead,pins = < FM_AUDIO_PA30 LIGHT_PIN_FUNC_0 0x000 >;
};
}; };
}; };
&padctrl_audiosys {
status = "okay";
light-audio-padctrl {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_audio_i2c0: audio_i2c0_grp {
thead,pins = <
FM_AUDIO_IO_PA29 LIGHT_PIN_FUNC_2 0x004
FM_AUDIO_IO_PA30 LIGHT_PIN_FUNC_2 0x004
>;
};
pinctrl_audio_i2c1: audio_i2c1_grp {
thead,pins = <
FM_AUDIO_IO_PA6 LIGHT_PIN_FUNC_2 0x004
FM_AUDIO_IO_PA7 LIGHT_PIN_FUNC_2 0x004
>;
};
pinctrl_audio_i2s1: audio_i2s1_grp {
thead,pins = <
FM_AUDIO_IO_PA14 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA15 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA16 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA17 LIGHT_PIN_FUNC_0 0x008
>;
};
pinctrl_audio_i2s2: audio_i2s2_grp {
thead,pins = <
FM_AUDIO_IO_PA18 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA19 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA21 LIGHT_PIN_FUNC_0 0x008
FM_AUDIO_IO_PA22 LIGHT_PIN_FUNC_0 0x008
>;
};
};
};
&i2c0 { &i2c0 {
clock-frequency = <400000>; clock-frequency = <400000>;
status = "okay"; status = "okay";
pcal6408ahk_b: gpio@20 { pcal6408ahk_b: gpio@20 {
compatible = "nxp,pcal9554b"; compatible = "nxp,pca9557";
reg = <0x20>; reg = <0x18>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
@@ -950,8 +1108,8 @@
status = "okay"; status = "okay";
pcal6408ahk_c: gpio@20 { pcal6408ahk_c: gpio@20 {
compatible = "nxp,pcal9554b"; compatible = "nxp,pca9557";
reg = <0x20>; reg = <0x18>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
@@ -967,8 +1125,8 @@
status = "okay"; status = "okay";
pcal6408ahk_d: gpio@20 { pcal6408ahk_d: gpio@20 {
compatible = "nxp,pcal9554b"; compatible = "nxp,pca9557";
reg = <0x20>; reg = <0x18>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
@@ -1093,6 +1251,24 @@
status = "okay"; status = "okay";
}; };
&vvcam_sensor3 {//cam3 csi0 modified
sensor_name = "OV5693";
sensor_regulators = "soc_dovdd18_rgb", "soc_dvdd12_rgb", "soc_avdd28_rgb";
sensor_regulator_voltage_uV = <1800000 1200000 2800000>;
sensor_regulator_timing_us = <70 50 20>;
sensor_pdn = <&gpio1_porta 28 0>; //powerdown pin / shutdown pin
sensor_rst = <&pcal6408ahk_c 1 0>;
sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready
DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>;
DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>;
AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>;
i2c_reg_width = /bits/ 8 <2>;
i2c_data_width = /bits/ 8 <1>;
i2c_addr = /bits/ 8 <0x36>;
i2c_bus = /bits/ 8 <0>;
status = "okay";
};
&video2 { &video2 {
vi_mem_pool_region = <0>; // vi_mem: framebuffer, region[0] vi_mem_pool_region = <0>; // vi_mem: framebuffer, region[0]
status = "okay"; status = "okay";
@@ -1101,11 +1277,18 @@
status = "okay"; status = "okay";
sensor0 { sensor0 {
subdev_name = "vivcam"; subdev_name = "vivcam";
idx = <0>; idx = <0>;
csi_idx = <0>; csi_idx = <0>;
mode_idx = <0>; mode_idx = <0>;
path_type = "SENSOR_VGA_RAW12_LINER"; path_type = "SENSOR_VGA_RAW12_LINER";
}; };
sensor1 {
subdev_name = "vivcam";
idx = <3>;
csi_idx = <0>;
mode_idx = <1>;
path_type = "SENSOR_2592x1944_LINER";
};
dma { dma {
subdev_name = "vipre"; subdev_name = "vipre";
idx = <0>; idx = <0>;
@@ -1116,8 +1299,8 @@
idx = <1>; idx = <1>;
path_type = "ISP_MI_PATH_MP"; path_type = "ISP_MI_PATH_MP";
output { output {
max_width = <1920>; max_width = <2600>;
max_height = <1088>; max_height = <2000>;
bit_per_pixel = <12>; bit_per_pixel = <12>;
frame_count = <3>; frame_count = <3>;
}; };
@@ -1138,6 +1321,13 @@
path_type = "SENSOR_VGA_RAW12_LINER"; path_type = "SENSOR_VGA_RAW12_LINER";
}; };
sensor1 {
subdev_name = "vivcam";
idx = <3>;
csi_idx = <0>;
mode_idx = <1>;
path_type = "SENSOR_2592x1944_LINER";
};
dma { dma {
subdev_name = "vipre"; subdev_name = "vipre";
idx = <0>; idx = <0>;
@@ -1275,15 +1465,22 @@
status = "okay"; status = "okay";
sensor0 { sensor0 {
subdev_name = "vivcam"; subdev_name = "vivcam";
idx = <2>; idx = <0>;
csi_idx = <1>; //csi_b csi_idx = <0>;
mode_idx = <0>; mode_idx = <0>;
path_type = "SENSOR_1080X1280_30FPS_RAW10_LINER"; path_type = "SENSOR_VGA_RAW12_LINER";
};
sensor1 {
subdev_name = "vivcam";
idx = <3>;
csi_idx = <0>;
mode_idx = <1>;
path_type = "SENSOR_2592x1944_LINER";
}; };
dma { dma {
subdev_name = "vipre"; subdev_name = "vipre";
idx = <0>; idx = <0>;
path_type = "VIPRE_CSI1_DDR"; path_type = "VIPRE_CSI0_DDR";
}; };
}; };
}; };
@@ -1425,12 +1622,22 @@
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
cpu { cpu {
sound-dai = <&i2s1 1>; sound-dai = <&i2s1 0>;
}; };
codec { codec {
sound-dai = <&es7210_audio_codec>; sound-dai = <&es7210_audio_codec>;
}; };
}; };
simple-audio-card,dai-link@2 { /* I2S - HDMI*/
reg = <2>;
format = "i2s";
cpu {
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
}; };
&light_i2s { &light_i2s {
@@ -1444,14 +1651,29 @@
&i2s1 { &i2s1 {
status = "okay"; status = "okay";
dmas = <&dmac2 11>, <&dmac2 10>; dmas = <&dmac2 11>, <&dmac2 10>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa14>,
<&pinctrl_audiopa15>,
<&pinctrl_audiopa16>,
<&pinctrl_audiopa17>,
<&pinctrl_audio_i2s1>;
}; };
&i2s2 { &i2s2 {
status = "okay"; status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa18>,
<&pinctrl_audiopa19>,
<&pinctrl_audiopa21>,
<&pinctrl_audiopa22>,
<&pinctrl_audio_i2s2>;
}; };
&i2s3 { &usb_1 {
status = "okay"; hubswitch-gpio = <&ao_gpio_porta 4 0>;
vbus-supply = <&soc_vbus_en_reg>;
hub1v2-supply = <&reg_usb_hub_vdd1v2>;
hub5v-supply = <&reg_usb_hub_vcc5v>;
}; };
&cpus { &cpus {
@@ -1461,12 +1683,14 @@
300000 650000 300000 650000
800000 700000 800000 700000
1500000 800000 1500000 800000
1848000 1000000
>; >;
light,dvddm-operating-points = < light,dvddm-operating-points = <
/* kHz uV */ /* kHz uV */
300000 800000 300000 800000
800000 800000 800000 800000
1500000 800000 1500000 800000
1848000 1000000
>; >;
}; };
c910_1: cpu@1 { c910_1: cpu@1 {
@@ -1475,12 +1699,14 @@
300000 650000 300000 650000
800000 700000 800000 700000
1500000 800000 1500000 800000
1848000 1000000
>; >;
light,dvddm-operating-points = < light,dvddm-operating-points = <
/* kHz uV */ /* kHz uV */
300000 800000 300000 800000
800000 800000 800000 800000
1500000 800000 1500000 800000
1848000 1000000
>; >;
}; };
c910_2: cpu@2 { c910_2: cpu@2 {
@@ -1490,12 +1716,14 @@
300000 650000 300000 650000
800000 700000 800000 700000
1500000 800000 1500000 800000
1848000 1000000
>; >;
light,dvddm-operating-points = < light,dvddm-operating-points = <
/* kHz uV */ /* kHz uV */
300000 800000 300000 800000
800000 800000 800000 800000
1500000 800000 1500000 800000
1848000 1000000
>; >;
}; };
c910_3: cpu@3 { c910_3: cpu@3 {
@@ -1505,12 +1733,14 @@
300000 650000 300000 650000
800000 700000 800000 700000
1500000 800000 1500000 800000
1848000 1000000
>; >;
light,dvddm-operating-points = < light,dvddm-operating-points = <
/* kHz uV */ /* kHz uV */
300000 800000 300000 800000
800000 800000 800000 800000
1500000 800000 1500000 800000
1848000 1000000
>; >;
}; };
}; };

View File

@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
/dts-v1/;
#include "light-lpi4a.dts"
&light_iopmp {
status = "disabled";
};
&qspi1 {
status = "disabled";
};

View File

@@ -6,22 +6,15 @@
#include "light-lpi4a-ref.dts" #include "light-lpi4a-ref.dts"
/ { / {
model = "T-HEAD Light Lichee Pi 4A configuration for 4GB DDR board"; model = "T-HEAD Light Lichee Pi 4A configuration for 8GB DDR board";
compatible = "thead,light-val", "thead,light-lpi4a", "thead,light"; compatible = "thead,light-val", "thead,light-lpi4a", "thead,light";
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x1 0x00000000>; reg = <0x0 0x200000 0x1 0xffe00000>;
}; };
}; };
&cmamem { &cmamem {
alloc-ranges = <0 0xe4000000 0 0x14000000>; // [0xE400_0000 ~ 0xF800_0000] alloc-ranges = <0 0xe4000000 0 0x14000000>; // [0x0E400_0000 ~ 0x0F800_0000]
};
&usb_1 {
hubswitch-gpio = <&ao_gpio_porta 4 0>;
vbus-supply = <&soc_vbus_en_reg>;
hub1v2-supply = <&reg_usb_hub_vdd1v2>;
hub5v-supply = <&reg_usb_hub_vcc5v>;
}; };

View File

@@ -199,6 +199,12 @@
csi_idx = <0xff>; csi_idx = <0xff>;
path_type = "SENSOR_VGA_RAW10_LINER"; path_type = "SENSOR_VGA_RAW10_LINER";
}; };
sensor2 {
subdev_name = "vivcam";
idx = <0xff>; // invalid
csi_idx = <0xff>;
path_type = "SENSOR_VGA_RAW10_LINER";
};
dma { dma {
subdev_name = "vipre"; subdev_name = "vipre";
idx = <0>; idx = <0>;

View File

@@ -6,11 +6,14 @@
#include <dt-bindings/pinctrl/light-fm-left-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-left-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-right-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-right-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-audio-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-pinctrl-def.h>
#include <dt-bindings/clock/light-fm-ap-clock.h> #include <dt-bindings/clock/light-fm-ap-clock.h>
#include <dt-bindings/clock/light-vpsys.h> #include <dt-bindings/clock/light-vpsys.h>
#include <dt-bindings/clock/light-vosys.h> #include <dt-bindings/clock/light-vosys.h>
#include <dt-bindings/clock/light-visys.h> #include <dt-bindings/clock/light-visys.h>
#include <dt-bindings/clock/light-dspsys.h> #include <dt-bindings/clock/light-dspsys.h>
#include <dt-bindings/clock/light-audiosys.h>
#include <dt-bindings/firmware/thead/rsrc.h> #include <dt-bindings/firmware/thead/rsrc.h>
#include <dt-bindings/soc/thead,light-iopmp.h> #include <dt-bindings/soc/thead,light-iopmp.h>
#include <dt-bindings/thermal/thermal.h> #include <dt-bindings/thermal/thermal.h>
@@ -34,7 +37,7 @@
i2c3 = &i2c3; i2c3 = &i2c3;
i2c4 = &i2c4; i2c4 = &i2c4;
audio_i2c0 = &audio_i2c0; audio_i2c0 = &audio_i2c0;
audio_i2c1 = &audio_i2c1; audio_i2c1 = &audio_i2c1;
mmc0 = &emmc; mmc0 = &emmc;
mmc1 = &sdhci0; mmc1 = &sdhci0;
serial0 = &uart0; serial0 = &uart0;
@@ -55,6 +58,7 @@
vivcam4 = &vvcam_sensor4; vivcam4 = &vvcam_sensor4;
vivcam5 = &vvcam_sensor5; vivcam5 = &vvcam_sensor5;
vivcam6 = &vvcam_sensor6; vivcam6 = &vvcam_sensor6;
vivcam7 = &vvcam_sensor7;
viv_video0 = &video0; viv_video0 = &video0;
viv_video1 = &video1; viv_video1 = &video1;
@@ -94,6 +98,11 @@
}; };
}; };
aon_iram: aon-iram@ffffef8000 {
compatible = "syscon";
reg = <0xff 0xffef8000 0x0 0x10000>;
};
thermal-zones { thermal-zones {
cpu-thermal-zone { cpu-thermal-zone {
polling-delay-passive = <250>; polling-delay-passive = <250>;
@@ -383,7 +392,7 @@
entry-cnt = <4>; entry-cnt = <4>;
control-reg = <0xff 0xff015004>; control-reg = <0xff 0xff015004>;
control-val = <0x1c>; control-val = <0x1c>;
csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>;
}; };
clint0: clint@ffdc000000 { clint0: clint@ffdc000000 {
@@ -634,6 +643,12 @@
status = "okay"; status = "okay";
}; };
audio_mbox: audio_mbox@0xffefc48000 {
compatible = "thead,light-audio-mbox-reg", "syscon";
reg = <0xff 0xefc48000 0x0 0x1000>;
status = "okay";
};
nvmem_controller: efuse@ffff210000 { nvmem_controller: efuse@ffff210000 {
compatible = "thead,light-fm-efuse", "syscon"; compatible = "thead,light-fm-efuse", "syscon";
reg = <0xff 0xff210000 0x0 0x10000>; reg = <0xff 0xff210000 0x0 0x10000>;
@@ -855,6 +870,12 @@
status = "okay"; status = "okay";
}; };
padctrl_audiosys: padctrl-audiosys@ffcb01d000 {
compatible = "thead,light-fm-audio-pinctrl";
reg = <0xff 0xcb01d000 0x0 0x1000>;
status = "disabled";
};
timer4: timer@ffffc33000 { timer4: timer@ffffc33000 {
compatible = "snps,dw-apb-timer"; compatible = "snps,dw-apb-timer";
reg = <0xff 0xffc33000 0x0 0x14>; reg = <0xff 0xffc33000 0x0 0x14>;
@@ -1248,6 +1269,13 @@
status = "okay"; status = "okay";
}; };
vpsys_rst: vpsys-reset-controller@ffecc30000 {
compatible = "thead,light-vpsys-reset-src","syscon";
reg = <0xff 0xecc30000 0x0 0x1000>;
#reset-cells = <1>;
status = "okay";
};
sys_reg: sys_reg@ffef010100 { sys_reg: sys_reg@ffef010100 {
compatible = "thead,light_sys_reg"; compatible = "thead,light_sys_reg";
reg = <0xff 0xef010100 0x0 0x100>; reg = <0xff 0xef010100 0x0 0x100>;
@@ -1301,7 +1329,7 @@
65536 65536 65536 65536 65536 65536 65536 65536
65536 65536 65536 65536 65536 65536 65536 65536
65536 65536 65536 65536>; 65536 65536 65536 65536>;
snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; snps,priority = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; // <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>;
snps,dma-masters = <1>; snps,dma-masters = <1>;
snps,data-width = <4>; snps,data-width = <4>;
snps,axi-max-burst-len = <16>; snps,axi-max-burst-len = <16>;
@@ -1354,8 +1382,7 @@
emmc: sdhci@ffe7080000 { emmc: sdhci@ffe7080000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7080000 0x0 0x10000 reg = <0xff 0xe7080000 0x0 0x10000>;
0xff 0xef014060 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <62>; interrupts = <62>;
interrupt-names = "sdhciirq"; interrupt-names = "sdhciirq";
@@ -1365,8 +1392,7 @@
sdhci0: sd@ffe7090000 { sdhci0: sd@ffe7090000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7090000 0x0 0x10000 reg = <0xff 0xe7090000 0x0 0x10000>;
0xff 0xef014064 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <64>; interrupts = <64>;
interrupt-names = "sdhci0irq"; interrupt-names = "sdhci0irq";
@@ -1376,8 +1402,7 @@
sdhci1: sd@ffe70a0000 { sdhci1: sd@ffe70a0000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe70a0000 0x0 0x10000 reg = <0xff 0xe70a0000 0x0 0x10000>;
0xff 0xef014064 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <71>; interrupts = <71>;
interrupt-names = "sdhci1irq"; interrupt-names = "sdhci1irq";
@@ -1403,7 +1428,8 @@
clock-names = "pclk", "aclk"; clock-names = "pclk", "aclk";
vha_clk_rate = <1000000000>; vha_clk_rate = <1000000000>;
ldo_vha-supply = <&npu>; ldo_vha-supply = <&npu>;
dma-mask = <0xf 0xffffffff>; dma-mask = <0xff 0xffffffff>;
resets = <&rst LIGHT_RESET_NPU>;
status = "disabled"; status = "disabled";
}; };
@@ -1432,6 +1458,7 @@
clocks = <&vpsys_clk_gate LIGHT_VPSYS_FCE_ACLK>, clocks = <&vpsys_clk_gate LIGHT_VPSYS_FCE_ACLK>,
<&vpsys_clk_gate LIGHT_VPSYS_FCE_PCLK>; <&vpsys_clk_gate LIGHT_VPSYS_FCE_PCLK>;
clock-names = "aclk", "pclk"; clock-names = "aclk", "pclk";
resets = <&vpsys_rst LIGHT_RESET_FCE>;
dma-mask = <0xf 0xffffffff>; dma-mask = <0xf 0xffffffff>;
status = "disabled"; status = "disabled";
}; };
@@ -1481,7 +1508,7 @@
compatible = "light,light-i2s"; compatible = "light,light-i2s";
reg = <0xff 0xe7034000 0x0 0x4000>; reg = <0xff 0xe7034000 0x0 0x4000>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_i2s0>; pinctrl-0 = <&pinctrl_light_i2s0>;
light,mode = "i2s-master"; light,mode = "i2s-master";
light,sel = "ap_i2s"; light,sel = "ap_i2s";
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
@@ -1506,7 +1533,7 @@
light,sel = "i2s0"; light,sel = "i2s0";
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <174>; interrupts = <174>;
dmas = <&dmac2 9>, <&dmac2 16>; dmas = <&dmac2 9>, <&dmac2 8>;
dma-names = "tx", "rx"; dma-names = "tx", "rx";
light,dma_maxburst = <4>; light,dma_maxburst = <4>;
#dma-cells = <1>; #dma-cells = <1>;
@@ -1555,16 +1582,17 @@
status = "disabled"; status = "disabled";
}; };
i2s3: audio_i2s3@0xffcb017000 { i2s_8ch_sd0: audio_i2s_8ch_sd0@0xffcb017000 {
#sound-dai-cells = <1>; #sound-dai-cells = <1>;
compatible = "light,light-i2s"; compatible = "light,light-i2s-8ch";
reg = <0xff 0xcb017000 0x0 0x1000>; reg = <0xff 0xcb017000 0x0 0x1000>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default"; pinctrl-names = "default";
light,mode = "i2s-master"; light,mode = "i2s-master";
light,sel = "i2s3"; light,sel = "i2s_8ch_sd0";
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <177>; interrupts = <177>;
dmas = <&dmac2 14>, <&dmac2 16>; dmas = <&dmac2 36>, <&dmac2 14>;
dma-names = "tx", "rx"; dma-names = "tx", "rx";
light,dma_maxburst = <4>; light,dma_maxburst = <4>;
#dma-cells = <1>; #dma-cells = <1>;
@@ -1573,6 +1601,267 @@
status = "disabled"; status = "disabled";
}; };
i2s_8ch_sd1: audio_i2s_8ch_sd1@0xffcb017000 {
#sound-dai-cells = <1>;
compatible = "light,light-i2s-8ch";
reg = <0xff 0xcb017000 0x0 0x1000>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,sel = "i2s_8ch_sd1";
interrupt-parent = <&intc>;
interrupts = <177>;
dmas = <&dmac2 37>, <&dmac2 15>;
dma-names = "tx", "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
i2s_8ch_sd2: audio_i2s_8ch_sd2@0xffcb017000 {
#sound-dai-cells = <1>;
compatible = "light,light-i2s-8ch";
reg = <0xff 0xcb017000 0x0 0x1000>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,sel = "i2s_8ch_sd2";
interrupt-parent = <&intc>;
interrupts = <177>;
dmas = <&dmac2 38>, <&dmac2 16>;
dma-names = "tx", "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
i2s_8ch_sd3: audio_i2s_8ch_sd3@0xffcb017000 {
#sound-dai-cells = <1>;
compatible = "light,light-i2s-8ch";
reg = <0xff 0xcb017000 0x0 0x1000>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,sel = "i2s_8ch_sd3";
interrupt-parent = <&intc>;
interrupts = <177>;
dmas = <&dmac2 39>, <&dmac2 17>;
dma-names = "tx", "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot1: audio_tdm_slot1@0xffcb012000 {
#sound-dai-cells = <0>;
compatible = "light,light-tdm";
reg = <0xff 0xcb012000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,tdm_slots = <8>;
light,tdm_slot_num = <1>;
interrupt-parent = <&intc>;
interrupts = <178>;
dmas = <&dmac2 28>;
dma-names = "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot2: audio_tdm_slot2@0xffcb012000 {
#sound-dai-cells = <0>;
compatible = "light,light-tdm";
reg = <0xff 0xcb012000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,tdm_slots = <8>;
light,tdm_slot_num = <2>;
interrupt-parent = <&intc>;
interrupts = <178>;
dmas = <&dmac2 29>;
dma-names = "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot3: audio_tdm_slot3@0xffcb012000 {
#sound-dai-cells = <0>;
compatible = "light,light-tdm";
reg = <0xff 0xcb012000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,tdm_slots = <8>;
light,tdm_slot_num = <3>;
interrupt-parent = <&intc>;
interrupts = <178>;
dmas = <&dmac2 30>;
dma-names = "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot4: audio_tdm_slot4@0xffcb012000 {
#sound-dai-cells = <0>;
compatible = "light,light-tdm";
reg = <0xff 0xcb012000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,tdm_slots = <8>;
light,tdm_slot_num = <4>;
interrupt-parent = <&intc>;
interrupts = <178>;
dmas = <&dmac2 31>;
dma-names = "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot5: audio_tdm_slot5@0xffcb012000 {
#sound-dai-cells = <0>;
compatible = "light,light-tdm";
reg = <0xff 0xcb012000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,tdm_slots = <8>;
light,tdm_slot_num = <5>;
interrupt-parent = <&intc>;
interrupts = <178>;
dmas = <&dmac2 32>;
dma-names = "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot6: audio_tdm_slot6@0xffcb012000 {
#sound-dai-cells = <0>;
compatible = "light,light-tdm";
reg = <0xff 0xcb012000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,tdm_slots = <8>;
light,tdm_slot_num = <6>;
interrupt-parent = <&intc>;
interrupts = <178>;
dmas = <&dmac2 33>;
dma-names = "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot7: audio_tdm_slot7@0xffcb012000 {
#sound-dai-cells = <0>;
compatible = "light,light-tdm";
reg = <0xff 0xcb012000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,tdm_slots = <8>;
light,tdm_slot_num = <7>;
interrupt-parent = <&intc>;
interrupts = <178>;
dmas = <&dmac2 34>;
dma-names = "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot8: audio_tdm_slot8@0xffcb012000 {
#sound-dai-cells = <0>;
compatible = "light,light-tdm";
reg = <0xff 0xcb012000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,tdm_slots = <8>;
light,tdm_slot_num = <8>;
interrupt-parent = <&intc>;
interrupts = <178>;
dmas = <&dmac2 35>;
dma-names = "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_TDM>;
clock-names = "pclk";
status = "disabled";
};
spdif0: audio_spdif0@0xffcb018000 {
#sound-dai-cells = <0>;
compatible = "light,light-spdif";
reg = <0xff 0xcb018000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
interrupt-parent = <&intc>;
interrupts = <179>;
dmas = <&dmac2 25>, <&dmac2 24>;
dma-names = "tx", "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_SPDIF0>;
clock-names = "pclk";
status = "disabled";
};
spdif1: audio_spdif1@0xffcb019000 {
#sound-dai-cells = <0>;
compatible = "light,light-spdif";
reg = <0xff 0xcb019000 0x0 0x1000>;
audio-pin-regmap = <&audio_ioctrl>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
interrupt-parent = <&intc>;
interrupts = <180>;
dmas = <&dmac2 27>, <&dmac2 26>;
dma-names = "tx", "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
clocks = <&audiosys_clk_gate LIGHT_CLKGEN_AUDIO_SPDIF1>;
clock-names = "pclk";
status = "disabled";
};
pvt: pvt@fffff4e000 { pvt: pvt@fffff4e000 {
compatible = "moortec,mr75203"; compatible = "moortec,mr75203";
reg = <0xff 0xfff4e000 0x0 0x80>, reg = <0xff 0xfff4e000 0x0 0x80>,
@@ -1592,6 +1881,10 @@
interrupts = <44>; interrupts = <44>;
clocks = <&dummy_clock_apb>; clocks = <&dummy_clock_apb>;
clock-frequency = <100000>; clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 12>, <&dmac0 13>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>; ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>; ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>; fs_hcnt = /bits/ 16 <0x37>;
@@ -1611,6 +1904,10 @@
interrupts = <45>; interrupts = <45>;
clocks = <&dummy_clock_apb>; clocks = <&dummy_clock_apb>;
clock-frequency = <100000>; clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 14>, <&dmac0 15>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>; ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>; ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>; fs_hcnt = /bits/ 16 <0x37>;
@@ -1630,6 +1927,10 @@
interrupts = <46>; interrupts = <46>;
clocks = <&dummy_clock_apb>; clocks = <&dummy_clock_apb>;
clock-frequency = <100000>; clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 16>, <&dmac0 17>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>; ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>; ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>; fs_hcnt = /bits/ 16 <0x37>;
@@ -1651,6 +1952,10 @@
interrupts = <47>; interrupts = <47>;
clocks = <&dummy_clock_apb>; clocks = <&dummy_clock_apb>;
clock-frequency = <100000>; clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 18>, <&dmac0 19>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>; ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>; ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>; fs_hcnt = /bits/ 16 <0x37>;
@@ -1672,6 +1977,10 @@
interrupts = <48>; interrupts = <48>;
clocks = <&dummy_clock_apb>; clocks = <&dummy_clock_apb>;
clock-frequency = <100000>; clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 20>, <&dmac0 21>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>; ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>; ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>; fs_hcnt = /bits/ 16 <0x37>;
@@ -1693,6 +2002,10 @@
interrupts = <182>; interrupts = <182>;
clocks = <&dummy_clock_apb>; clocks = <&dummy_clock_apb>;
clock-frequency = <100000>; clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac2 21>, <&dmac2 20>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x82>; ss_hcnt = /bits/ 16 <0x82>;
ss_lcnt = /bits/ 16 <0x78>; ss_lcnt = /bits/ 16 <0x78>;
fs_hcnt = /bits/ 16 <0x37>; fs_hcnt = /bits/ 16 <0x37>;
@@ -1705,26 +2018,30 @@
#size-cells = <0>; #size-cells = <0>;
}; };
audio_i2c1: i2c@0xffcb01b000 { audio_i2c1: i2c@0xffcb01b000 {
compatible = "snps,designware-i2c"; compatible = "snps,designware-i2c";
reg = <0xff 0xcb01b000 0x0 0x1000>; reg = <0xff 0xcb01b000 0x0 0x1000>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <183>; interrupts = <183>;
clocks = <&dummy_clock_apb>; clocks = <&dummy_clock_apb>;
clock-frequency = <100000>; clock-frequency = <100000>;
ss_hcnt = /bits/ 16 <0x82>; i2c_mode = "dma";
ss_lcnt = /bits/ 16 <0x78>; dmas = <&dmac2 23>, <&dmac2 22>;
fs_hcnt = /bits/ 16 <0x37>; dma-names = "tx", "rx";
fs_lcnt = /bits/ 16 <0x42>; #dma-cells = <1>;
fp_hcnt = /bits/ 16 <0x14>; ss_hcnt = /bits/ 16 <0x82>;
fp_lcnt = /bits/ 16 <0x1a>; ss_lcnt = /bits/ 16 <0x78>;
hs_hcnt = /bits/ 16 <0x5>; fs_hcnt = /bits/ 16 <0x37>;
hs_lcnt = /bits/ 16 <0x15>; fs_lcnt = /bits/ 16 <0x42>;
status = "disabled"; fp_hcnt = /bits/ 16 <0x14>;
fp_lcnt = /bits/ 16 <0x1a>;
hs_hcnt = /bits/ 16 <0x5>;
hs_lcnt = /bits/ 16 <0x15>;
status = "disabled";
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
}; };
isp0: isp@ffe4100000 { isp0: isp@ffe4100000 {
compatible = "thead,light-isp"; compatible = "thead,light-isp";
@@ -2005,6 +2322,11 @@
status = "disabled"; status = "disabled";
}; };
vvcam_sensor7: vvcam_sensor@7 {
compatible = "thead,light-vvcam-sensor";
status = "disabled";
};
xtensa_dsp: dsp@01{ xtensa_dsp: dsp@01{
compatible = "thead,dsp-hw-common"; compatible = "thead,dsp-hw-common";
reg = <0xff 0xef040000 0x0 0x001000 >; /*DSP_SYSREG(0x0000-0xFFF) */ reg = <0xff 0xef040000 0x0 0x001000 >; /*DSP_SYSREG(0x0000-0xFFF) */
@@ -2154,6 +2476,12 @@
interrupts = <215>; /* TEE INT SRC_7 */ interrupts = <215>; /* TEE INT SRC_7 */
}; };
light_event: light-event {
compatible = "thead,light-event";
aon-iram-regmap = <&aon_iram>;
status = "okay";
};
visys_clk_gate: visys-clk-gate { /* VI_SYSREG_R */ visys_clk_gate: visys-clk-gate { /* VI_SYSREG_R */
compatible = "thead,visys-gate-controller"; compatible = "thead,visys-gate-controller";
visys-regmap = <&visys_reg>; visys-regmap = <&visys_reg>;
@@ -2181,6 +2509,13 @@
#clock-cells = <1>; #clock-cells = <1>;
status = "okay"; status = "okay";
}; };
audiosys_clk_gate: audiosys-clk-gate {
compatible = "thead,audiosys-gate-controller";
audiosys-regmap = <&audio_cpr>;
#clock-cells = <1>;
status = "okay";
};
}; };
}; };

View File

@@ -251,6 +251,7 @@ CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_LIGHT=y CONFIG_HWSPINLOCK_LIGHT=y
CONFIG_HWSPINLOCK_LIGHT_TEST=m CONFIG_HWSPINLOCK_LIGHT_TEST=m
CONFIG_MAILBOX=y CONFIG_MAILBOX=y
CONFIG_EXTCON=y
CONFIG_IIO=y CONFIG_IIO=y
CONFIG_IIO_SW_DEVICE=y CONFIG_IIO_SW_DEVICE=y
CONFIG_PWM=y CONFIG_PWM=y

View File

@@ -252,6 +252,7 @@ CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_LIGHT=y CONFIG_HWSPINLOCK_LIGHT=y
CONFIG_HWSPINLOCK_LIGHT_TEST=m CONFIG_HWSPINLOCK_LIGHT_TEST=m
CONFIG_MAILBOX=y CONFIG_MAILBOX=y
CONFIG_EXTCON=y
CONFIG_IIO=y CONFIG_IIO=y
CONFIG_IIO_SW_DEVICE=y CONFIG_IIO_SW_DEVICE=y
CONFIG_PWM=y CONFIG_PWM=y

View File

@@ -3,6 +3,10 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y CONFIG_PREEMPT=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y CONFIG_CGROUPS=y
@@ -91,6 +95,7 @@ CONFIG_TUN=y
CONFIG_VIRTIO_NET=y CONFIG_VIRTIO_NET=y
CONFIG_MACB=y CONFIG_MACB=y
CONFIG_STMMAC_ETH=y CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_RX_ZERO_COPY=y
CONFIG_DWMAC_LIGHT=y CONFIG_DWMAC_LIGHT=y
CONFIG_MICROSEMI_PHY=y CONFIG_MICROSEMI_PHY=y
CONFIG_REALTEK_PHY=y CONFIG_REALTEK_PHY=y
@@ -265,6 +270,11 @@ CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_LIGHT=y CONFIG_HWSPINLOCK_LIGHT=y
CONFIG_HWSPINLOCK_LIGHT_TEST=m CONFIG_HWSPINLOCK_LIGHT_TEST=m
CONFIG_MAILBOX=y CONFIG_MAILBOX=y
CONFIG_RPMSG=y
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_RPMSG_THEAD_LIGHT=y
CONFIG_EXTCON=y
CONFIG_IIO=y CONFIG_IIO=y
CONFIG_IIO_SW_DEVICE=y CONFIG_IIO_SW_DEVICE=y
CONFIG_PWM=y CONFIG_PWM=y
@@ -298,13 +308,21 @@ CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_DH=y CONFIG_CRYPTO_DH=y
CONFIG_CRYPTO_CURVE25519=y CONFIG_CRYPTO_CURVE25519=y
CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CRYPTO_CHACHA20POLY1305=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_OFB=y CONFIG_CRYPTO_OFB=y
CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SHA3=y CONFIG_CRYPTO_SHA3=y
CONFIG_CRYPTO_SM3=y CONFIG_CRYPTO_SM3=y
CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_SM4=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_DMA_CMA=y CONFIG_DMA_CMA=y
CONFIG_DMA_PERNUMA_CMA=y CONFIG_DMA_PERNUMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32 CONFIG_CMA_SIZE_MBYTES=32
@@ -320,6 +338,7 @@ CONFIG_OVERLAY_FS=y
CONFIG_LOCKUP_DETECTOR=y CONFIG_LOCKUP_DETECTOR=y
CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_INFO=y
CONFIG_PM=y CONFIG_PM=y
# CONFIG_SUSPEND is not set # CONFIG_SUSPEND is not set
# CONFIG_PM_SLEEP is not set # CONFIG_PM_SLEEP is not set

View File

@@ -3,7 +3,8 @@ generic-y += early_ioremap.h
generic-y += extable.h generic-y += extable.h
generic-y += flat.h generic-y += flat.h
generic-y += kvm_para.h generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += qspinlock.h
generic-y += qrwlock.h generic-y += qrwlock.h
generic-y += qrwlock_types.h
generic-y += user.h generic-y += user.h
generic-y += vmlinux.lds.h generic-y += vmlinux.lds.h

View File

@@ -11,12 +11,36 @@
#include <asm/barrier.h> #include <asm/barrier.h>
#include <asm/fence.h> #include <asm/fence.h>
static inline ulong __xchg16_relaxed(ulong new, void *ptr)
{
ulong ret, tmp;
ulong shif = ((ulong)ptr & 2) ? 16 : 0;
ulong mask = 0xffff << shif;
ulong *__ptr = (ulong *)((ulong)ptr & ~2);
__asm__ __volatile__ (
"0: lr.w %0, %2\n"
" and %1, %0, %z3\n"
" or %1, %1, %z4\n"
" sc.w %1, %1, %2\n"
" bnez %1, 0b\n"
: "=&r" (ret), "=&r" (tmp), "+A" (*__ptr)
: "rJ" (~mask), "rJ" (new << shif)
: "memory");
return (ulong)((ret & mask) >> shif);
}
#define __xchg_relaxed(ptr, new, size) \ #define __xchg_relaxed(ptr, new, size) \
({ \ ({ \
__typeof__(ptr) __ptr = (ptr); \ __typeof__(ptr) __ptr = (ptr); \
__typeof__(new) __new = (new); \ __typeof__(new) __new = (new); \
__typeof__(*(ptr)) __ret; \ __typeof__(*(ptr)) __ret; \
switch (size) { \ switch (size) { \
case 2: { \
__ret = (__typeof__(*(ptr))) \
__xchg16_relaxed((ulong)__new, __ptr); \
break;} \
case 4: \ case 4: \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
" amoswap.w %0, %2, %1\n" \ " amoswap.w %0, %2, %1\n" \

View File

@@ -13,7 +13,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/pgtable.h> #include <linux/pgtable.h>
#include <asm/mmiowb.h>
#include <asm/early_ioremap.h> #include <asm/early_ioremap.h>
/* /*

View File

@@ -133,7 +133,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
#define __io_br() do {} while (0) #define __io_br() do {} while (0)
#define __io_ar(v) __asm__ __volatile__ ("fence i,r" : : : "memory") #define __io_ar(v) __asm__ __volatile__ ("fence i,r" : : : "memory")
#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory") #define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory")
#define __io_aw() mmiowb_set_pending() #define __io_aw() __asm__ __volatile__ ("fence o,w" : : : "memory")
#define readb(c) ({ u8 __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; }) #define readb(c) ({ u8 __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; })
#define readw(c) ({ u16 __v; __io_br(); __v = readw_cpu(c); __io_ar(__v); __v; }) #define readw(c) ({ u16 __v; __io_br(); __v = readw_cpu(c); __io_ar(__v); __v; })

View File

@@ -1,15 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_RISCV_MMIOWB_H
#define _ASM_RISCV_MMIOWB_H
/*
* "o,w" is sufficient to ensure that all writes to the device have completed
* before the write to the spinlock is allowed to commit.
*/
#define mmiowb() __asm__ __volatile__ ("fence o,w" : : : "memory");
#include <linux/smp.h>
#include <asm-generic/mmiowb.h>
#endif /* _ASM_RISCV_MMIOWB_H */

View File

@@ -1,92 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
/*
* 'Generic' ticket-lock implementation.
*
* It relies on atomic_fetch_add() having well defined forward progress
* guarantees under contention. If your architecture cannot provide this, stick
* to a test-and-set lock.
*
* It also relies on atomic_fetch_add() being safe vs smp_store_release() on a
* sub-word of the value. This is generally true for anything LL/SC although
* you'd be hard pressed to find anything useful in architecture specifications
* about this. If your architecture cannot do this you might be better off with
* a test-and-set.
*
* It further assumes atomic_*_release() + atomic_*_acquire() is RCpc and hence
* uses atomic_fetch_add() which is RCsc to create an RCsc hot path, along with
* a full fence after the spin to upgrade the otherwise-RCpc
* atomic_cond_read_acquire().
*
* The implementation uses smp_cond_load_acquire() to spin, so if the
* architecture has WFE like instructions to sleep instead of poll for word
* modifications be sure to implement that (see ARM64 for example).
*
*/
#ifndef __ASM_GENERIC_SPINLOCK_H #ifndef __ASM_GENERIC_SPINLOCK_H
#define __ASM_GENERIC_SPINLOCK_H #define __ASM_GENERIC_SPINLOCK_H
#include <linux/atomic.h> #include <asm-generic/qspinlock.h>
#include <asm/spinlock_types.h>
static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
{
u32 val = atomic_fetch_add(1<<16, lock);
u16 ticket = val >> 16;
if (ticket == (u16)val)
return;
/*
* atomic_cond_read_acquire() is RCpc, but rather than defining a
* custom cond_read_rcsc() here we just emit a full fence. We only
* need the prior reads before subsequent writes ordering from
* smb_mb(), but as atomic_cond_read_acquire() just emits reads and we
* have no outstanding writes due to the atomic_fetch_add() the extra
* orderings are free.
*/
atomic_cond_read_acquire(lock, ticket == (u16)VAL);
smp_mb();
}
static __always_inline bool arch_spin_trylock(arch_spinlock_t *lock)
{
u32 old = atomic_read(lock);
if ((old >> 16) != (old & 0xffff))
return false;
return atomic_try_cmpxchg(lock, &old, old + (1<<16)); /* SC, for RCsc */
}
static __always_inline void arch_spin_unlock(arch_spinlock_t *lock)
{
u16 *ptr = (u16 *)lock + IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
u32 val = atomic_read(lock);
smp_store_release(ptr, (u16)val + 1);
}
static __always_inline int arch_spin_is_locked(arch_spinlock_t *lock)
{
u32 val = atomic_read(lock);
return ((val >> 16) != (val & 0xffff));
}
static __always_inline int arch_spin_is_contended(arch_spinlock_t *lock)
{
u32 val = atomic_read(lock);
return (s16)((val >> 16) - (val & 0xffff)) > 1;
}
static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
{
return !arch_spin_is_locked(&lock);
}
#include <asm/qrwlock.h> #include <asm/qrwlock.h>
#endif /* __ASM_GENERIC_SPINLOCK_H */ #endif /* __ASM_GENERIC_SPINLOCK_H */

View File

@@ -3,15 +3,7 @@
#ifndef __ASM_GENERIC_SPINLOCK_TYPES_H #ifndef __ASM_GENERIC_SPINLOCK_TYPES_H
#define __ASM_GENERIC_SPINLOCK_TYPES_H #define __ASM_GENERIC_SPINLOCK_TYPES_H
#include <linux/types.h> #include <asm-generic/qspinlock_types.h>
typedef atomic_t arch_spinlock_t; #include <asm-generic/qrwlock_types.h>
/*
* qrwlock_types depends on arch_spinlock_t, so we must typedef that before the
* include.
*/
#include <asm/qrwlock_types.h>
#define __ARCH_SPIN_LOCK_UNLOCKED ATOMIC_INIT(0)
#endif /* __ASM_GENERIC_SPINLOCK_TYPES_H */ #endif /* __ASM_GENERIC_SPINLOCK_TYPES_H */

View File

@@ -38,11 +38,10 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
RISCV_INSN_REJECTED(c_ebreak, insn); RISCV_INSN_REJECTED(c_ebreak, insn);
#endif #endif
RISCV_INSN_REJECTED(auipc, insn);
RISCV_INSN_REJECTED(branch, insn);
RISCV_INSN_SET_SIMULATE(jal, insn); RISCV_INSN_SET_SIMULATE(jal, insn);
RISCV_INSN_SET_SIMULATE(jalr, insn); RISCV_INSN_SET_SIMULATE(jalr, insn);
RISCV_INSN_SET_SIMULATE(auipc, insn);
RISCV_INSN_SET_SIMULATE(branch, insn);
return INSN_GOOD; return INSN_GOOD;
} }

View File

@@ -83,3 +83,115 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
return ret; return ret;
} }
#define auipc_rd_idx(opcode) \
((opcode >> 7) & 0x1f)
#define auipc_imm(opcode) \
((((opcode) >> 12) & 0xfffff) << 12)
#if __riscv_xlen == 64
#define auipc_offset(opcode) sign_extend64(auipc_imm(opcode), 31)
#elif __riscv_xlen == 32
#define auipc_offset(opcode) auipc_imm(opcode)
#else
#error "Unexpected __riscv_xlen"
#endif
bool __kprobes simulate_auipc(u32 opcode, unsigned long addr, struct pt_regs *regs)
{
/*
* auipc instruction:
* 31 12 11 7 6 0
* | imm[31:12] | rd | opcode |
* 20 5 7
*/
u32 rd_idx = auipc_rd_idx(opcode);
unsigned long rd_val = addr + auipc_offset(opcode);
if (!rv_insn_reg_set_val(regs, rd_idx, rd_val))
return false;
instruction_pointer_set(regs, addr + 4);
return true;
}
#define branch_rs1_idx(opcode) \
(((opcode) >> 15) & 0x1f)
#define branch_rs2_idx(opcode) \
(((opcode) >> 20) & 0x1f)
#define branch_funct3(opcode) \
(((opcode) >> 12) & 0x7)
#define branch_imm(opcode) \
(((((opcode) >> 8) & 0xf ) << 1) | \
((((opcode) >> 25) & 0x3f) << 5) | \
((((opcode) >> 7) & 0x1 ) << 11) | \
((((opcode) >> 31) & 0x1 ) << 12))
#define branch_offset(opcode) \
sign_extend32((branch_imm(opcode)), 12)
#define BRANCH_BEQ 0x0
#define BRANCH_BNE 0x1
#define BRANCH_BLT 0x4
#define BRANCH_BGE 0x5
#define BRANCH_BLTU 0x6
#define BRANCH_BGEU 0x7
bool __kprobes simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs)
{
/*
* branch instructions:
* 31 30 25 24 20 19 15 14 12 11 8 7 6 0
* | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
* 1 6 5 5 3 4 1 7
* imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 BEQ
* imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 BNE
* imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 BLT
* imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 BGE
* imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 BLTU
* imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 BGEU
*/
s32 offset;
s32 offset_tmp;
unsigned long rs1_val;
unsigned long rs2_val;
if (!rv_insn_reg_get_val(regs, branch_rs1_idx(opcode), &rs1_val) ||
!rv_insn_reg_get_val(regs, branch_rs2_idx(opcode), &rs2_val))
return false;
offset_tmp = branch_offset(opcode);
switch (branch_funct3(opcode)) {
case BRANCH_BEQ:
offset = (rs1_val == rs2_val) ? offset_tmp : 4;
break;
case BRANCH_BNE:
offset = (rs1_val != rs2_val) ? offset_tmp : 4;
break;
case BRANCH_BLT:
offset = ((long)rs1_val < (long)rs2_val) ? offset_tmp : 4;
break;
case BRANCH_BGE:
offset = ((long)rs1_val >= (long)rs2_val) ? offset_tmp : 4;
break;
case BRANCH_BLTU:
offset = (rs1_val < rs2_val) ? offset_tmp : 4;
break;
case BRANCH_BGEU:
offset = (rs1_val >= rs2_val) ? offset_tmp : 4;
break;
default:
return false;
}
instruction_pointer_set(regs, addr + offset);
return true;
}

View File

@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CLK_LIGHT_FM) += thead-gate.o visys-gate.o vpsys-gate.o vosys-gate.o dspsys-gate.o obj-$(CONFIG_CLK_LIGHT_FM) += thead-gate.o visys-gate.o vpsys-gate.o vosys-gate.o dspsys-gate.o audiosys-gate.o

View File

@@ -0,0 +1,124 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 Alibaba Group Holding Limited.
*/
#include <dt-bindings/clock/light-fm-ap-clock.h>
#include <dt-bindings/clock/light-audiosys.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include "clk-gate.h"
#include "../clk.h"
static struct clk *gates[LIGHT_CLKGEN_AUDIO_CLK_END];
static struct clk_onecell_data clk_gate_data;
static int light_audiosys_clk_probe(struct platform_device *pdev)
{
struct regmap *audiosys_regmap;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
int ret;
audiosys_regmap = syscon_regmap_lookup_by_phandle(np, "audiosys-regmap");
if (IS_ERR(audiosys_regmap)) {
dev_err(&pdev->dev, "cannot find regmap for vi system register\n");
return PTR_ERR(audiosys_regmap);
}
printk("%s audiosys_regmap=0x%px\n", __func__, audiosys_regmap);
/* we assume that the gate clock is a root clock */
gates[LIGHT_CLKGEN_AUDIO_CPU] = thead_gate_clk_register("clkgen_audiosys_cpu_clk", NULL,
audiosys_regmap, 0x10, 0, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_SRAM0] = thead_gate_clk_register("clkgen_audiosys_sram0_clk", NULL,
audiosys_regmap, 0x10, 1, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_SRAM1] = thead_gate_clk_register("clkgen_audiosys_sram1_clk", NULL,
audiosys_regmap, 0x10, 2, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_DMA] = thead_gate_clk_register("clkgen_audiosys_dma_clk", NULL,
audiosys_regmap, 0x10, 3, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_BSM] = thead_gate_clk_register("clkgen_audiosys_bsm_clk", NULL,
audiosys_regmap, 0x10, 4, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_TIMER] = thead_gate_clk_register("clkgen_audiosys_timer_clk", NULL,
audiosys_regmap, 0x10, 8, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_TIMER_CNT1] = thead_gate_clk_register("clkgen_audiosys_timer_cnt1_clk", NULL,
audiosys_regmap, 0x10, 9, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_TIMER_CNT2] = thead_gate_clk_register("clkgen_audiosys_timer_cnt2_clk", NULL,
audiosys_regmap, 0x10, 10, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_TIMER_CNT3] = thead_gate_clk_register("clkgen_audiosys_timer_cnt3_clk", NULL,
audiosys_regmap, 0x10, 11, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_TIMER_CNT4] = thead_gate_clk_register("clkgen_audiosys_timer_cnt4_clk", NULL,
audiosys_regmap, 0x10, 12, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_WDR] = thead_gate_clk_register("clkgen_audiosys_wdr_clk", NULL,
audiosys_regmap, 0x10, 13, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_I2C0] = thead_gate_clk_register("clkgen_audiosys_i2c0_clk", NULL,
audiosys_regmap, 0x10, 14, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_I2C1] = thead_gate_clk_register("clkgen_audiosys_i2c1_clk", NULL,
audiosys_regmap, 0x10, 15, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_UART] = thead_gate_clk_register("clkgen_audiosys_uart_clk", NULL,
audiosys_regmap, 0x10, 16, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_I2S0] = thead_gate_clk_register("clkgen_audiosys_i2s0_clk", NULL,
audiosys_regmap, 0x10, 17, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_I2S1] = thead_gate_clk_register("clkgen_audiosys_i2s1_clk", NULL,
audiosys_regmap, 0x10, 18, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_I2S2] = thead_gate_clk_register("clkgen_audiosys_i2s2_clk", NULL,
audiosys_regmap, 0x10, 19, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_I2S8CH] = thead_gate_clk_register("clkgen_audiosys_i2s8ch_clk", NULL,
audiosys_regmap, 0x10, 20, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_TDM] = thead_gate_clk_register("clkgen_audiosys_tdm_clk", NULL,
audiosys_regmap, 0x10, 21, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_GPIO] = thead_gate_clk_register("clkgen_audiosys_gpio_clk", NULL,
audiosys_regmap, 0x10, 22, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_SPDIF0] = thead_gate_clk_register("clkgen_audiosys_spdif0_clk", NULL,
audiosys_regmap, 0x10, 23, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_SPDIF1] = thead_gate_clk_register("clkgen_audiosys_spdif1_clk", NULL,
audiosys_regmap, 0x10, 24, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_VAD] = thead_gate_clk_register("clkgen_audiosys_vad_clk", NULL,
audiosys_regmap, 0x10, 25, GATE_NOT_SHARED, NULL, dev);
gates[LIGHT_CLKGEN_AUDIO_IOMUX] = thead_gate_clk_register("clkgen_audiosys_iomux_clk", NULL,
audiosys_regmap, 0x10, 26, GATE_NOT_SHARED, NULL, dev);
clk_gate_data.clks = gates;
clk_gate_data.clk_num = ARRAY_SIZE(gates);
ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_gate_data);
if (ret < 0) {
dev_err(dev, "failed to register gate clks for light audiosys\n");
goto unregister_clks;
}
dev_info(dev, "succeed to register audiosys gate clock provider\n");
return 0;
unregister_clks:
thead_unregister_clocks(gates, ARRAY_SIZE(gates));
return ret;
}
static const struct of_device_id audiosys_clk_gate_of_match[] = {
{ .compatible = "thead,audiosys-gate-controller" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, audiosys_clk_gate_of_match);
static struct platform_driver light_audiosys_clk_driver = {
.probe = light_audiosys_clk_probe,
.driver = {
.name = "audiosys-clk-gate-provider",
.of_match_table = of_match_ptr(audiosys_clk_gate_of_match),
},
};
module_platform_driver(light_audiosys_clk_driver);
MODULE_AUTHOR("nanli.yd <nanli.yd@linux.alibaba.com>");
MODULE_DESCRIPTION("Thead Light Fullmask audiosys clock gate provider");
MODULE_LICENSE("GPL v2");

View File

@@ -335,7 +335,7 @@ _ConvertLogical2Physical(
OUT gctPHYS_ADDR_T * Physical OUT gctPHYS_ADDR_T * Physical
); );
gctBOOL gceSTATUS
_QuerySignal( _QuerySignal(
IN gckOS Os, IN gckOS Os,
IN gctSIGNAL Signal IN gctSIGNAL Signal

View File

@@ -6,6 +6,7 @@
* Copyright (C) 2011-2013 Freescale Semiconductor, Inc. * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
* Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
*/ */
#include <linux/extcon-provider.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
@@ -103,6 +104,11 @@ static const u16 csc_coeff_rgb_full_to_rgb_limited[3][4] = {
{ 0x0000, 0x0000, 0x1b7c, 0x0020 } { 0x0000, 0x0000, 0x1b7c, 0x0020 }
}; };
static const unsigned int hdmi_extcon_cable[] = {
EXTCON_DISP_HDMI,
EXTCON_NONE,
};
struct hdmi_vmode { struct hdmi_vmode {
bool mdataenablepolarity; bool mdataenablepolarity;
@@ -160,6 +166,7 @@ struct dw_hdmi {
struct clk *pix_clk; struct clk *pix_clk;
struct clk *i2s_clk; struct clk *i2s_clk;
struct dw_hdmi_i2c *i2c; struct dw_hdmi_i2c *i2c;
struct extcon_dev *edev;
struct hdmi_data_info hdmi_data; struct hdmi_data_info hdmi_data;
const struct dw_hdmi_plat_data *plat_data; const struct dw_hdmi_plat_data *plat_data;
@@ -3117,6 +3124,10 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
dev_dbg(hdmi->dev, "EVENT=%s\n", dev_dbg(hdmi->dev, "EVENT=%s\n",
status == connector_status_connected ? status == connector_status_connected ?
"plugin" : "plugout"); "plugin" : "plugout");
if (status == connector_status_connected)
extcon_set_state_sync(hdmi->edev, EXTCON_DISP_HDMI, true);
else
extcon_set_state_sync(hdmi->edev, EXTCON_DISP_HDMI, false);
if (hdmi->bridge.dev) { if (hdmi->bridge.dev) {
drm_helper_hpd_irq_event(hdmi->bridge.dev); drm_helper_hpd_irq_event(hdmi->bridge.dev);
@@ -3423,6 +3434,19 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
dw_hdmi_init_hw(hdmi); dw_hdmi_init_hw(hdmi);
hdmi->edev = devm_extcon_dev_allocate(dev, hdmi_extcon_cable);
if (IS_ERR(hdmi->edev)) {
dev_err(dev, "failed to allocate extcon device\n");
ret = -ENOMEM;
goto err_res;
}
ret = devm_extcon_dev_register(dev, hdmi->edev);
if (ret < 0) {
dev_err(dev, "failed to register extcon device\n");
goto err_res;
}
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
ret = irq; ret = irq;

View File

@@ -50,6 +50,7 @@ obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o
i2c-designware-core-y := i2c-designware-common.o i2c-designware-core-y := i2c-designware-common.o
i2c-designware-core-y += i2c-designware-master_dma.o
i2c-designware-core-y += i2c-designware-master.o i2c-designware-core-y += i2c-designware-master.o
i2c-designware-core-$(CONFIG_I2C_DESIGNWARE_SLAVE) += i2c-designware-slave.o i2c-designware-core-$(CONFIG_I2C_DESIGNWARE_SLAVE) += i2c-designware-slave.o
obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o

View File

@@ -17,6 +17,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/dmaengine.h>
#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \ #define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \
I2C_FUNC_SMBUS_BYTE | \ I2C_FUNC_SMBUS_BYTE | \
@@ -234,6 +235,18 @@ struct reset_control;
* values than the one computed based only on the input clock frequency. * values than the one computed based only on the input clock frequency.
* Leave them to be %0 if not used. * Leave them to be %0 if not used.
*/ */
struct i2c_dw_dma {
struct dma_chan *dma_chan;
struct dma_async_tx_descriptor *desc;
dma_cookie_t cookie;
dma_addr_t dma_addr; //phy addr
u32 *buf; //Store the virtual address of the data to be transferred by dma
u32 buf_size;
u32 transfer_len; //dma transfer data num
//volatile int dma_complete;
struct completion dma_complete;
};
struct dw_i2c_dev { struct dw_i2c_dev {
struct device *dev; struct device *dev;
struct regmap *map; struct regmap *map;
@@ -257,6 +270,7 @@ struct dw_i2c_dev {
u8 *rx_buf; u8 *rx_buf;
int msg_err; int msg_err;
unsigned int status; unsigned int status;
unsigned int tx_status;
u32 abort_source; u32 abort_source;
int irq; int irq;
u32 flags; u32 flags;
@@ -287,6 +301,10 @@ struct dw_i2c_dev {
int mode; int mode;
struct i2c_bus_recovery_info rinfo; struct i2c_bus_recovery_info rinfo;
bool suspended; bool suspended;
struct i2c_dw_dma dma;
u32 laststat;
u32 laststatus;
int dw_i2c_enable_dma;
}; };
#define ACCESS_INTR_MASK 0x00000001 #define ACCESS_INTR_MASK 0x00000001

View File

@@ -22,6 +22,7 @@
#include <linux/reset.h> #include <linux/reset.h>
#include "i2c-designware-core.h" #include "i2c-designware-core.h"
#include "i2c-designware-master_dma.h"
static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev) static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
{ {
@@ -257,7 +258,13 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
/* Clear and enable interrupts */ /* Clear and enable interrupts */
regmap_read(dev->map, DW_IC_CLR_INTR, &dummy); regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);
regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK);
if (dev->dw_i2c_enable_dma) {
i2c_dw_xfer_dma_init(dev);
regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK & (~DW_IC_INTR_TX_EMPTY));
} else {
regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK);
}
} }
/* /*
@@ -289,9 +296,9 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
* adapter when we are done with this transfer. * adapter when we are done with this transfer.
*/ */
if (msgs[dev->msg_write_idx].addr != addr) { if (msgs[dev->msg_write_idx].addr != addr) {
dev_err(dev->dev,
"%s: invalid target address\n", __func__);
dev->msg_err = -EINVAL; dev->msg_err = -EINVAL;
dev_err(dev->dev,
"%s: invalid target address\n", __func__);
break; break;
} }
@@ -476,6 +483,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
dev->msg_read_idx = 0; dev->msg_read_idx = 0;
dev->msg_err = 0; dev->msg_err = 0;
dev->status = STATUS_IDLE; dev->status = STATUS_IDLE;
dev->tx_status = STATUS_IDLE;
dev->abort_source = 0; dev->abort_source = 0;
dev->rx_outstanding = 0; dev->rx_outstanding = 0;
@@ -491,6 +499,16 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
i2c_dw_xfer_init(dev); i2c_dw_xfer_init(dev);
/* Wait for tx to complete */ /* Wait for tx to complete */
if (dev->dw_i2c_enable_dma) {
if(i2c_dw_dma_tx_transfer(dev, adap->timeout) != 0) {
dev_err(dev->dev, "i2c dw dma transfer error\n");
i2c_recover_bus(&dev->adapter);
i2c_dw_init_master(dev);
ret = -ETIMEDOUT;
goto done;
}
}
if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) { if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
/* i2c_dw_init implicitly disables the adapter */ /* i2c_dw_init implicitly disables the adapter */
@@ -527,15 +545,21 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
goto done; goto done;
} }
if (dev->status) if (dev->status || dev->tx_status) {
dev_err(dev->dev, dev_err(dev->dev, "transfer terminated early - interrupt latency too high? sta 0x%x\n", dev->status);
"transfer terminated early - interrupt latency too high?\n");
dev_err(dev->dev, "laststa 0x%x, laststatus 0x%x\n", dev->laststat, dev->laststatus);
dev_err(dev->dev, "dev->tx_status 0x%x\n", dev->tx_status);
dev_err(dev->dev, "dev->rx_outstanding %d\n", dev->rx_outstanding);
}
ret = -EIO; ret = -EIO;
done: done:
if (dev->dw_i2c_enable_dma) {
i2c_dw_xfer_dma_deinit(dev);
}
i2c_dw_release_lock(dev); i2c_dw_release_lock(dev);
done_nolock: done_nolock:
pm_runtime_mark_last_busy(dev->dev); pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev); pm_runtime_put_autosuspend(dev->dev);
@@ -631,8 +655,9 @@ static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)
if (stat & DW_IC_INTR_RX_FULL) if (stat & DW_IC_INTR_RX_FULL)
i2c_dw_read(dev); i2c_dw_read(dev);
if (stat & DW_IC_INTR_TX_EMPTY) if (stat & DW_IC_INTR_TX_EMPTY) {
i2c_dw_xfer_msg(dev); i2c_dw_xfer_msg(dev);
}
/* /*
* No need to modify or disable the interrupt mask here. * No need to modify or disable the interrupt mask here.
@@ -645,9 +670,11 @@ tx_aborted:
if ((stat & DW_IC_INTR_TX_ABRT) || dev->msg_err || if ((stat & DW_IC_INTR_TX_ABRT) || dev->msg_err ||
((status & DW_IC_STATUS_TFE) && ((status & DW_IC_STATUS_TFE) &&
(!(status & DW_IC_STATUS_RFNE)) && (!(status & DW_IC_STATUS_RFNE)) &&
(!(status & DW_IC_STATUS_MASTER_ACTIVITY)))) (!(status & DW_IC_STATUS_MASTER_ACTIVITY)))) {
complete(&dev->cmd_complete); complete(&dev->cmd_complete);
else if (unlikely(dev->flags & ACCESS_INTR_MASK)) { dev->laststat = stat;
dev->laststatus = status;
} else if (unlikely(dev->flags & ACCESS_INTR_MASK)) {
/* Workaround to trigger pending interrupt */ /* Workaround to trigger pending interrupt */
regmap_read(dev->map, DW_IC_INTR_MASK, &stat); regmap_read(dev->map, DW_IC_INTR_MASK, &stat);
i2c_dw_disable_int(dev); i2c_dw_disable_int(dev);
@@ -747,9 +774,25 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
{ {
struct i2c_adapter *adap = &dev->adapter; struct i2c_adapter *adap = &dev->adapter;
unsigned long irq_flags; unsigned long irq_flags;
struct device_node *np;
int ret; int ret;
const char *i2c_mode;
//default used interrupt mode
dev->dw_i2c_enable_dma = 0;
np = dev->dev->of_node;
ret = of_property_read_string(np, "i2c_mode", &i2c_mode);
if (ret == 0) {
if (strcmp(i2c_mode, "dma") == 0) {
dev->dw_i2c_enable_dma = 1;
}
}
init_completion(&dev->cmd_complete); init_completion(&dev->cmd_complete);
if (dev->dw_i2c_enable_dma) {
init_completion(&dev->dma.dma_complete);
}
dev->init = i2c_dw_init_master; dev->init = i2c_dw_init_master;
dev->disable = i2c_dw_disable; dev->disable = i2c_dw_disable;
@@ -787,10 +830,10 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
i2c_dw_disable_int(dev); i2c_dw_disable_int(dev);
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags, ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags,
dev_name(dev->dev), dev); dev_name(dev->dev), dev);
if (ret) { if (ret) {
dev_err(dev->dev, "failure requesting irq %i: %d\n", dev_err(dev->dev, "failure requesting irq %i: %d\n",
dev->irq, ret); dev->irq, ret);
return ret; return ret;
} }

View File

@@ -0,0 +1,318 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include "i2c-designware-core.h"
#define DEBUG
#define DW_IC_DMA_CR (0x88)
#define DW_IC_DMA_TDLR (0x8c)
#define DW_IC_DMA_RDLR (0x90)
#define DW_IC_DMA_CR_TXEN (0x2)
#define DW_IC_DMA_CR_DIS (0x0)
//Because the fifo register bit width is 32bits, each transfer data is 4byte
#define DW_IC_DMA_DATA_BLOCK_BYTES (0x4)
//#define __dev_vdgb dev_dbg
#define __dev_vdgb(fmt, ...)
static int i2c_dw_hwparams_to_dma_slave_config(struct dw_i2c_dev *dev)
{
int ret = 0;
struct dma_slave_config slave_config;
struct i2c_dw_dma *dma = &dev->dma;
struct platform_device *pdev;
struct resource *iores_mem;
phys_addr_t reg_addr;
__dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__);
memset(&slave_config, 0, sizeof(slave_config));
//get i2c fifo addr
pdev = to_platform_device(dev->dev);
iores_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
reg_addr = iores_mem->start + DW_IC_DATA_CMD;
slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
slave_config.dst_addr = reg_addr;
//for light only support "false"
slave_config.device_fc = false;
ret = dmaengine_slave_config(dma->dma_chan, &slave_config);
if (ret) {
dev_err(dev->dev, "dmaengine_slave_config failed\n");
return ret;
}
__dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__);
return 0;
}
static void i2c_dw_dma_callback(void *data)
{
struct dw_i2c_dev *dev = (struct dw_i2c_dev *)data;
struct i2c_dw_dma *dma = &dev->dma;
dev->tx_status &= ~STATUS_WRITE_IN_PROGRESS;
complete(&dma->dma_complete);
dmaengine_terminate_async(dma->dma_chan);
}
static int get_msg_size(struct dw_i2c_dev *dev)
{
struct i2c_msg *msgs = dev->msgs;
u32 addr = msgs[dev->msg_write_idx].addr;
int i = 0;
int len = 0;
__dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__);
for (i = dev->msg_write_idx; i < dev->msgs_num; i++) {
if (msgs[i].addr != addr) {
dev_err(dev->dev, "%s: invalid target address\n", __func__);
dev->msg_err = -EINVAL;
break;
}
len += msgs[i].len;
}
__dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__);
return len;
}
static int alloc_dma_buf(struct dw_i2c_dev *dev, int size)
{
struct i2c_dw_dma *dma = &dev->dma;
__dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__);
dma->buf = dma_alloc_coherent(dev->dev, size, &dma->dma_addr, GFP_KERNEL);
if (!dma->buf) {
dev_err(dev->dev, "i2c alloc dma buf failed\n");
return -1;
}
dma->buf_size = size;
dma->transfer_len = 0;
__dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__);
return 0;
}
static int i2c_dw_release_tx_packets(struct dw_i2c_dev *dev)
{
struct i2c_dw_dma *dma = &dev->dma;
__dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__);
if(dma->buf && dma->dma_addr && dma->buf_size) {
dma_free_coherent(dev->dev, dma->buf_size, dma->buf, dma->dma_addr);
}
dma->buf = 0;
dma->dma_addr = 0;
dma->buf_size = 0;
__dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__);
return 0;
}
static int i2c_dw_synthetic_tx_packets(struct dw_i2c_dev *dev)
{
int ret = 0;
struct i2c_dw_dma *dma = &dev->dma;
struct i2c_msg *msgs = dev->msgs;
bool need_restart = false;
uint32_t *tx_buf;
int dma_tx_buf_size;
u32 addr = msgs[dev->msg_write_idx].addr;
__dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__);
dma_tx_buf_size = get_msg_size(dev) * 4;
if (dma_tx_buf_size <= 0) {
dev_err(dev->dev, "i2c get_msg_size size is error %d\n", dma_tx_buf_size);
return -1;
}
ret = alloc_dma_buf(dev, dma_tx_buf_size);
if (ret) {
dev_err(dev->dev, "i2c alloc_dma_buf failed\n");
return -1;
}
tx_buf = dma->buf;
for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
unsigned char *buf;
int buf_len;
u32 flags = msgs[dev->msg_write_idx].flags;
if (msgs[dev->msg_write_idx].addr != addr) {
dev_err(dev->dev, "%s: invalid target address\n", __func__);
dev->msg_err = -EINVAL;
break;
}
/* new i2c_msg */
buf = msgs[dev->msg_write_idx].buf;
buf_len = msgs[dev->msg_write_idx].len;
if ((dev->master_cfg & DW_IC_CON_RESTART_EN) &&
(dev->msg_write_idx > 0))
need_restart = true;
//dev_err(dev->dev, " msg_buf_len %d\n", buf_len);
while (buf_len > 0) {
u32 cmd = 0;
if (dev->msg_write_idx == dev->msgs_num - 1 &&
buf_len == 1 && !(flags & I2C_M_RECV_LEN))
cmd |= BIT(9);
if (need_restart) {
cmd |= BIT(10);
need_restart = false;
}
if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
*tx_buf = cmd | 0x100;
dev->rx_outstanding++;
} else {
*tx_buf = cmd | *buf++;
}
tx_buf++;
dma->transfer_len++;
buf_len--;
}
}
dma_sync_single_for_device(dev->dev, dma->dma_addr, dma->buf_size, DMA_TO_DEVICE);
__dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__);
return 0;
}
int i2c_dw_xfer_dma_deinit(struct dw_i2c_dev *dev);
int i2c_dw_dma_tx_transfer(struct dw_i2c_dev *dev, unsigned int timeout)
{
int ret = 0;
struct i2c_dw_dma *dma = &dev->dma;
unsigned long start_jiffies = 0;
u32 stat;
__dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__);
if (dma->dma_chan == NULL) {
goto error;
}
ret = i2c_dw_hwparams_to_dma_slave_config(dev);
if (ret != 0) {
goto error;
}
regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
if (stat & DW_IC_INTR_TX_ABRT) {
dev->cmd_err |= DW_IC_ERR_TX_ABRT;
dev->tx_status = STATUS_IDLE;
goto error;
}
ret = i2c_dw_synthetic_tx_packets(dev);
if (ret != 0) {
dev_err(dev->dev, "%s: i2c_dw_synthetic_tx_packets failed\n", __func__);
goto error;
}
dev->tx_status |= STATUS_WRITE_IN_PROGRESS;
dma->desc = dmaengine_prep_slave_single(dma->dma_chan, dma->dma_addr,
dma->transfer_len * DW_IC_DMA_DATA_BLOCK_BYTES,
DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (dma->desc == NULL) {
dev_err(dev->dev, "%s: dmaengine_prep_slave_single failed\n", __func__);
goto error;
}
dma->desc->callback = i2c_dw_dma_callback;
dma->desc->callback_param = dev;
dma->cookie = dmaengine_submit(dma->desc);
dma_async_issue_pending(dma->dma_chan);
//wait dma transfer complete
if (!wait_for_completion_timeout(&dma->dma_complete, timeout)) {
dev_err(dev->dev, "i2c dma_ch%d write timed out\n", dma->dma_chan->chan_id);
ret = dmaengine_terminate_async(dma->dma_chan);
if (ret !=0) {
dev_err(dev->dev, "i2c dma dmaengine_terminate_async failed,\
dma_ch is %d\n", dma->dma_chan->chan_id);
}
dmaengine_synchronize(dma->dma_chan);
goto error;
}
dmaengine_synchronize(dma->dma_chan);
//Release the dma channel immediately after the dma transfer is completed,
//reducing the dma occupation time
//i2c_dw_xfer_dma_init(dev);
return 0;
error:
//i2c_dw_xfer_dma_init(dev);
__dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__);
return -1;
}
int i2c_dw_xfer_dma_init(struct dw_i2c_dev *dev)
{
struct i2c_dw_dma *dma = &dev->dma;
__dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__);
// i2c dma set tx data level
regmap_write(dev->map, DW_IC_DMA_TDLR, dev->tx_fifo_depth / 2);
// i2c dma tx enable
regmap_write(dev->map, DW_IC_DMA_CR, DW_IC_DMA_CR_TXEN);
if (dma->dma_chan == NULL) {
//Alloc i2c dma channel.
//The function is to configure the handshake number in i2c dts into the channel
dma->dma_chan = dma_request_slave_channel(dev->dev, "tx");
if (!dma->dma_chan) {
dev_err(dev->dev, "Failed to request dma channel");
return -EIO;
}
__dev_vdgb(dev->dev,"i2c request dma_ch %d\n", dma->dma_chan->chan_id);
}
__dev_vdgb(dev->dev,"i2c dma_ch %d\n", dma->dma_chan->chan_id);
reinit_completion(&dma->dma_complete);
__dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__);
return 0;
}
int i2c_dw_xfer_dma_deinit(struct dw_i2c_dev *dev)
{
struct i2c_dw_dma *dma = &dev->dma;
__dev_vdgb(dev->dev, "%s, %d, enter\n", __func__, __LINE__);
i2c_dw_release_tx_packets(dev);
if (dma->dma_chan != NULL) {
dma_release_channel(dma->dma_chan);
}
dma->dma_chan = NULL;
// i2c dma disable
regmap_write(dev->map, DW_IC_DMA_CR, DW_IC_DMA_CR_DIS);
__dev_vdgb(dev->dev, "%s, %d, exit\n", __func__, __LINE__);
return 0;
}

View File

@@ -0,0 +1,6 @@
//#include "i2c-designware-core.h"
int i2c_dw_dma_tx_transfer(struct dw_i2c_dev *dev, unsigned int timeout);
int i2c_dw_xfer_dma_init(struct dw_i2c_dev *dev);
int i2c_dw_xfer_dma_deinit(struct dw_i2c_dev *dev);

View File

@@ -56,7 +56,7 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o
obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
obj-$(CONFIG_THEAD_LIGHT_MBOX) += light-mailbox.o obj-$(CONFIG_THEAD_LIGHT_MBOX) += light-mailbox.o
obj-$(CONFIG_THEAD_LIGHT_MBOX) += light-mailbox-client.o #obj-$(CONFIG_THEAD_LIGHT_MBOX) += light-mailbox-client.o
obj-$(CONFIG_VIRTIO_MAILBOX) += virtio-mailbox.o obj-$(CONFIG_VIRTIO_MAILBOX) += virtio-mailbox.o
obj-$(CONFIG_VIRTIO_MAILBOX_TEST) += virtio-mailbox-test.o obj-$(CONFIG_VIRTIO_MAILBOX_TEST) += virtio-mailbox-test.o

View File

@@ -28,17 +28,20 @@
struct dwcmshc_priv { struct dwcmshc_priv {
struct clk *bus_clk; struct clk *bus_clk;
void __iomem *soc_base;
bool is_emmc_card; bool is_emmc_card;
bool pull_up_en; bool pull_up_en;
bool io_fixed_1v8; bool io_fixed_1v8;
bool wprtn_ignore; bool wprtn_ignore;
long reset_cnt; long reset_cnt;
uint32_t delay_line[MMC_TIMING_MMC_HS400+1];
uint32_t clk_delay_set;
bool rxclk_sw_tune_en;
uint32_t rxclk_delay_set;
}; };
#define HS400_DELAY_LINE 24 #define HS400_DELAY_LINE 24
static uint32_t delay_line = 50; //static uint32_t delay_line = 50;
static void sdhci_phy_1_8v_init_no_pull(struct sdhci_host *host) static void sdhci_phy_1_8v_init_no_pull(struct sdhci_host *host)
{ {
@@ -114,12 +117,13 @@ static void snps_phy_1_8v_init(struct sdhci_host *host)
//disable delay lane //disable delay lane
sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R); sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
//set delay lane //set delay lane
sdhci_writeb(host, delay_line, PHY_SDCLKDL_DC_R); sdhci_writeb(host, priv->clk_delay_set, PHY_SDCLKDL_DC_R);
sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R); sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
//enable delay lane //enable delay lane
val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R); val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
val &= ~(1 << UPDATE_DC); val &= ~(1 << UPDATE_DC);
sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R); sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
pr_debug("%s: snps_phy_1_8v_init clk delay %d\n",host->hw_name,priv->clk_delay_set);
val = (1 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N); val = (1 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
sdhci_writew(host, val, PHY_CMDPAD_CNFG_R); sdhci_writew(host, val, PHY_CMDPAD_CNFG_R);
@@ -156,12 +160,13 @@ static void snps_phy_3_3v_init(struct sdhci_host *host)
//disable delay lane //disable delay lane
sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R); sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
//set delay lane //set delay lane
sdhci_writeb(host, delay_line, PHY_SDCLKDL_DC_R); sdhci_writeb(host, priv->clk_delay_set, PHY_SDCLKDL_DC_R);
sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R); sdhci_writeb(host, 0xa, PHY_DLL_CNFG2_R);
//enable delay lane //enable delay lane
val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R); val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
val &= ~(1 << UPDATE_DC); val &= ~(1 << UPDATE_DC);
sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R); sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R);
pr_debug("%s: snps_phy_3_3v_init clk delay %d\n",host->hw_name,priv->clk_delay_set);
val = (2 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N); val = (2 << RXSEL) | (1 << WEAKPULL_EN) | (3 << TXSLEW_CTRL_P) | (3 << TXSLEW_CTRL_N);
sdhci_writew(host, val, PHY_CMDPAD_CNFG_R); sdhci_writew(host, val, PHY_CMDPAD_CNFG_R);
@@ -255,6 +260,61 @@ static int snps_execute_tuning(struct sdhci_host *host, u32 opcode)
return 0; return 0;
} }
static int snps_rxclk_sw_tuned_sample_delay_set(struct sdhci_host *host, u32 sample_delay,u32 timeout)
{
struct sdhci_pltfm_host *pltfm_host;
struct dwcmshc_priv *priv;
u32 reg_val;
u32 tune_clk_set;
u16 ctrl_2;
u32 i=0;
pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);
/*0x320SMPLDL_CNFG
0x540AT_CTRL
0x544AT_STAT */
reg_val = sdhci_readb(host, PHY_SMPLDL_CNFG_R);
if(sample_delay >= 0x80){
/*if larger than 128,DelayLine works with extended delay range setting*/
reg_val |= (1 << SMPLDL_CNFG_EXTDLY_EN);
}else{
reg_val &= ~(1 << SMPLDL_CNFG_EXTDLY_EN);
}
sdhci_writeb(host, reg_val, PHY_SMPLDL_CNFG_R);
reg_val = sdhci_readl(host, AT_CTRL_R);
reg_val |= (1 << TUNE_CLK_STOP_EN);
reg_val |= (1 << SW_TUNE_EN);
sdhci_writel(host, reg_val, AT_CTRL_R);
if(sample_delay >= 0x80){
tune_clk_set = (sample_delay - 0x80) & 0xff;
}
else {
tune_clk_set = sample_delay ;
}
reg_val = sdhci_readl(host, AT_STAT_R);
reg_val &= ~(0xff<<AT_STAT_CENTER_PH_CODE);
reg_val |= tune_clk_set;
sdhci_writel(host,reg_val, AT_STAT_R);
for(i = 0; i < timeout; i += 10){
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
if(ctrl_2 & SDHCI_CTRL_TUNED_CLK)
return 0;
udelay(10);
}
pr_warn("%s: _rxclk_sw_tuned_sample_delay_set timeout %d\n",host->hw_name,timeout);
return -1;
}
void snps_rxclk_sw_tuned_sample_delay_dump(struct sdhci_host *host)
{
pr_info("PHY_SMPLDL_CNFG_R = %x\n",sdhci_readb(host, PHY_SMPLDL_CNFG_R));
pr_info("AT_CTRL_R = %x\n", sdhci_readl(host, AT_CTRL_R));
pr_info("AT_STAT_R = %x\n", sdhci_readl(host, AT_STAT_R));
pr_info("SDHCI_HOST_CONTROL2 = %x\n",sdhci_readw(host, SDHCI_HOST_CONTROL2));
}
static void snps_sdhci_set_phy(struct sdhci_host *host) static void snps_sdhci_set_phy(struct sdhci_host *host)
{ {
@@ -289,12 +349,6 @@ static void snps_sdhci_reset(struct sdhci_host *host, u8 mask)
pltfm_host = sdhci_priv(host); pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host); priv = sdhci_pltfm_priv(pltfm_host);
/*soc reset, fix host reset error*/
//soc_reg = readl( priv->soc_base);
//soc_reg &= ~1;
//writel(soc_reg, priv->soc_base);
//soc_reg |= 1;
//writel(soc_reg, priv->soc_base);
/*host reset*/ /*host reset*/
sdhci_reset(host, mask); sdhci_reset(host, mask);
@@ -390,7 +444,7 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
ctrl_2 |= SDHCI_CTRL_VDD_180; ctrl_2 |= SDHCI_CTRL_VDD_180;
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
pr_debug("%s: %s timing %d\n",host->hw_name,__func__,timing);
if (timing == MMC_TIMING_MMC_HS400) { if (timing == MMC_TIMING_MMC_HS400) {
// //disable delay lane // //disable delay lane
// sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R); // sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
@@ -406,10 +460,18 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
reg &= ~1; reg &= ~1;
sdhci_writel(host, reg, AT_CTRL_R); sdhci_writel(host, reg, AT_CTRL_R);
delay_line = HS400_DELAY_LINE; priv->clk_delay_set = priv->delay_line[MMC_TIMING_MMC_HS400];
snps_sdhci_set_phy(host); /* update tx delay*/
} else if(timing == MMC_TIMING_UHS_SDR104){
priv->clk_delay_set = priv->delay_line[MMC_TIMING_UHS_SDR104];
snps_sdhci_set_phy(host); /* update tx delay*/ snps_sdhci_set_phy(host); /* update tx delay*/
} else {
sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R); sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
}else {
sdhci_writeb(host, 0, PHY_DLLDL_CNFG_R);
if(priv->rxclk_sw_tune_en && (timing == MMC_TIMING_SD_HS)){
snps_rxclk_sw_tuned_sample_delay_set(host,priv->rxclk_delay_set,10000);
//snps_rxclk_sw_tuned_sample_delay_dump(host);
}
} }
} }
@@ -471,7 +533,8 @@ static void dwcmshc_set_power_noreg(struct sdhci_host *host, unsigned char mode,
unsigned short vdd) unsigned short vdd)
{ {
u8 pwr = 0; u8 pwr = 0;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
if (mode != MMC_POWER_OFF) { if (mode != MMC_POWER_OFF) {
switch (1 << vdd) { switch (1 << vdd) {
case MMC_VDD_165_195: case MMC_VDD_165_195:
@@ -509,6 +572,8 @@ static void dwcmshc_set_power_noreg(struct sdhci_host *host, unsigned char mode,
return; return;
host->pwr = pwr; host->pwr = pwr;
pr_debug("%s: %s set pwr %d\n",host->hw_name,__func__,pwr);
priv->clk_delay_set = priv->delay_line[0];
snps_sdhci_set_phy(host); snps_sdhci_set_phy(host);
if (pwr == 0) { if (pwr == 0) {
@@ -579,6 +644,20 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
}; };
static int device_property_get_clk_delay(struct device *dev,
const char *propname, u32 *val)
{
int ret = device_property_read_u32(dev, propname, val);
if(ret < 0){
return ret;
}
if(*val > 0xff){
pr_info("Note: invalid clk delay property :%s, val: %u\n",propname,*val);
return -1;
}
return ret;
}
static int dwcmshc_probe(struct platform_device *pdev) static int dwcmshc_probe(struct platform_device *pdev)
{ {
struct sdhci_pltfm_host *pltfm_host; struct sdhci_pltfm_host *pltfm_host;
@@ -604,13 +683,31 @@ static int dwcmshc_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host); pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host); priv = sdhci_pltfm_priv(pltfm_host);
/*used fix sdhci reset error*/
priv->soc_base = devm_platform_ioremap_resource(pdev, 1);
if (device_property_present(&pdev->dev, "is_emmc")) { if (device_property_present(&pdev->dev, "is_emmc")) {
priv->is_emmc_card = 1; priv->is_emmc_card = 1;
if(device_property_get_clk_delay(&pdev->dev, "clk-delay-default", &(priv->delay_line[0]) ) < 0 )
priv->delay_line[0] = 50;
if(device_property_get_clk_delay(&pdev->dev, "clk-delay-mmc-hs400", &(priv->delay_line[MMC_TIMING_MMC_HS400]) ) < 0 )
priv->delay_line[MMC_TIMING_MMC_HS400] = HS400_DELAY_LINE;
} else { } else {
priv->is_emmc_card = 0; priv->is_emmc_card = 0;
if(device_property_get_clk_delay(&pdev->dev, "clk-delay-default", &(priv->delay_line[0]) ) < 0 )
priv->delay_line[0] = 0x7d;
if(device_property_get_clk_delay(&pdev->dev, "clk-delay-uhs-sdr104", &(priv->delay_line[MMC_TIMING_UHS_SDR104]) ) < 0 )
priv->delay_line[MMC_TIMING_UHS_SDR104] = 0x32;
if(device_property_get_clk_delay(&pdev->dev, "rxclk-sample-delay", &(priv->rxclk_delay_set) ) == 0 ){
priv->rxclk_sw_tune_en = 1;
dev_info(&pdev->dev,"rxclk-sample-delay get val = 0x%x\n",priv->rxclk_delay_set);
}
else {
priv->rxclk_sw_tune_en = 0;
priv->rxclk_delay_set = 0;
}
} }
if (device_property_present(&pdev->dev, "pull_up")) { if (device_property_present(&pdev->dev, "pull_up")) {

View File

@@ -36,6 +36,8 @@
#define PHY_SDCLKDL_DC_R (DWC_MSHC_PTR_PHY_R + 0x1e) #define PHY_SDCLKDL_DC_R (DWC_MSHC_PTR_PHY_R + 0x1e)
#define PHY_SMPLDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x20) #define PHY_SMPLDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x20)
#define SMPLDL_CNFG_EXTDLY_EN 0x0 //1bit
#define PHY_ATDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x21) #define PHY_ATDL_CNFG_R (DWC_MSHC_PTR_PHY_R + 0x21)
#define INPSEL_CNFG 2 //2bit #define INPSEL_CNFG 2 //2bit
@@ -72,4 +74,6 @@
#define POST_CHANGE_DLY 0x13 //2bit #define POST_CHANGE_DLY 0x13 //2bit
#define SWIN_TH_VAL 0x18 //9bit #define SWIN_TH_VAL 0x18 //9bit
#define AT_STAT_R (P_VENDOR_SPECIFIC_AREA + 0x44) // 32bit
#define AT_STAT_CENTER_PH_CODE 0x0 //0-7bit
#endif /* _SDHCI_OF_DWCMSHC_H_*/ #endif /* _SDHCI_OF_DWCMSHC_H_*/

View File

@@ -25,6 +25,16 @@ config STMMAC_SELFTESTS
feature if you are facing problems with your HW and submit the test feature if you are facing problems with your HW and submit the test
results to the netdev Mailing List. results to the netdev Mailing List.
config STMMAC_RX_ZERO_COPY
bool "Support for STMMAC Zero Copy in Recv"
default n
help
This adds support for STMMAC reduce memcpy packet ring_buffer data
to skb data in stmmac_rx. Enable this feature will alloc skb in filling
ring buffer, mapping skb->data to ring buffer DMA addr.
If unsure, say N.
config STMMAC_PLATFORM config STMMAC_PLATFORM
tristate "STMMAC Platform bus support" tristate "STMMAC Platform bus support"
depends on STMMAC_ETH depends on STMMAC_ETH

View File

@@ -67,12 +67,18 @@ struct stmmac_rx_buffer {
dma_addr_t addr; dma_addr_t addr;
dma_addr_t sec_addr; dma_addr_t sec_addr;
}; };
struct stmmac_rx_skbuffer {
struct sk_buff *rx_skbuff;
struct page *sec_page;
dma_addr_t addr;
dma_addr_t sec_addr;
};
struct stmmac_rx_queue { struct stmmac_rx_queue {
u32 rx_count_frames; u32 rx_count_frames;
u32 queue_index; u32 queue_index;
struct page_pool *page_pool; struct page_pool *page_pool;
struct stmmac_rx_buffer *buf_pool; struct stmmac_rx_buffer *buf_pool;
struct stmmac_rx_skbuffer *skbuf_pool;
struct stmmac_priv *priv_data; struct stmmac_priv *priv_data;
struct dma_extended_desc *dma_erx; struct dma_extended_desc *dma_erx;
struct dma_desc *dma_rx ____cacheline_aligned_in_smp; struct dma_desc *dma_rx ____cacheline_aligned_in_smp;
@@ -210,6 +216,7 @@ struct stmmac_priv {
unsigned int mode; unsigned int mode;
unsigned int chain_mode; unsigned int chain_mode;
int extend_desc; int extend_desc;
bool extend_stat_need;
struct hwtstamp_config tstamp_config; struct hwtstamp_config tstamp_config;
struct ptp_clock *ptp_clock; struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_ops; struct ptp_clock_info ptp_clock_ops;

View File

@@ -1324,7 +1324,7 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv)
for (queue = 0; queue < tx_queue_cnt; queue++) for (queue = 0; queue < tx_queue_cnt; queue++)
stmmac_clear_tx_descriptors(priv, queue); stmmac_clear_tx_descriptors(priv, queue);
} }
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
/** /**
* stmmac_init_rx_buffers - init the RX descriptor buffer. * stmmac_init_rx_buffers - init the RX descriptor buffer.
* @priv: driver private structure * @priv: driver private structure
@@ -1335,18 +1335,21 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv)
* Description: this function is called to allocate a receive buffer, perform * Description: this function is called to allocate a receive buffer, perform
* the DMA mapping and init the descriptor. * the DMA mapping and init the descriptor.
*/ */
static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, static int __stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
int i, gfp_t flags, u32 queue) int i, gfp_t flags, u32 queue)
{ {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
if (priv->dma_cap.addr64 <= 32)
gfp |= GFP_DMA32;
buf->page = page_pool_dev_alloc_pages(rx_q->page_pool); buf->page = page_pool_alloc_pages(rx_q->page_pool,gfp);
if (!buf->page) if (!buf->page)
return -ENOMEM; return -ENOMEM;
if (priv->sph) { if (priv->sph) {
buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); buf->sec_page = page_pool_alloc_pages(rx_q->page_pool,gfp);
if (!buf->sec_page) if (!buf->sec_page)
return -ENOMEM; return -ENOMEM;
@@ -1364,14 +1367,13 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
return 0; return 0;
} }
/** /**
* stmmac_free_rx_buffer - free RX dma buffers * stmmac_free_rx_buffer - free RX dma buffers
* @priv: private structure * @priv: private structure
* @queue: RX queue index * @queue: RX queue index
* @i: buffer index. * @i: buffer index.
*/ */
static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i) static void __stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i)
{ {
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
@@ -1385,6 +1387,122 @@ static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i)
buf->sec_page = NULL; buf->sec_page = NULL;
} }
#else
static inline unsigned int stmmac_get_rx_buf_frsize(struct stmmac_priv *priv)
{
return priv->dma_buf_sz;
}
#define STMMAC_RX_ALIGN 0x3f
static int
stmmac_get_skb_dma_addr(struct stmmac_priv *priv,struct sk_buff *skb,dma_addr_t *dma_addr)
{
int off;
off = ((unsigned long)skb->data) & STMMAC_RX_ALIGN;
if (off)
skb_reserve(skb, STMMAC_RX_ALIGN + 1 - off);
*dma_addr = dma_map_single(priv->device,skb->data,stmmac_get_rx_buf_frsize(priv) - off,DMA_FROM_DEVICE);
if (dma_mapping_error(priv->device, *dma_addr)) {
//if (net_ratelimit())
netdev_err(priv->dev, "Rx DMA memory map failed\n");
return -ENOMEM;
}
return 0;
}
/**
* stmmac_init_rx_skbuffers - init the RX descriptor buffer.
* @priv: driver private structure
* @p: descriptor pointer
* @i: descriptor index
* @flags: gfp flag
* @queue: RX queue index
* Description: this function is called to allocate a receive buffer, perform
* the DMA mapping and init the descriptor.
*/
static int __stmmac_init_rx_skbuffers(struct stmmac_priv *priv, struct dma_desc *p,
int i, gfp_t flags, u32 queue)
{
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
struct stmmac_rx_skbuffer *buf = &rx_q->skbuf_pool[i];
struct sk_buff *skb = NULL;
gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
if (priv->dma_cap.addr64 <= 32)
gfp |= GFP_DMA32;
skb = netdev_alloc_skb(priv->dev, stmmac_get_rx_buf_frsize(priv));
if (!skb)
return -ENOMEM;
if(stmmac_get_skb_dma_addr(priv,skb,&buf->addr) < 0)
return -ENOMEM;
if (priv->sph) {
buf->sec_page = page_pool_alloc_pages(rx_q->page_pool,gfp);
if (!buf->sec_page)
return -ENOMEM;
buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true);
} else {
buf->sec_page = NULL;
stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false);
}
stmmac_set_desc_addr(priv, p, buf->addr);
if (priv->dma_buf_sz == BUF_SIZE_16KiB)
stmmac_init_desc3(priv, p);
buf->rx_skbuff = skb;
return 0;
}
/**
* stmmac_free_rx_skbuffer - free RX dma buffers
* @priv: private structure
* @queue: RX queue index
* @i: buffer index.
*/
static void __stmmac_free_rx_skbuffer(struct stmmac_priv *priv, u32 queue, int i)
{
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
struct stmmac_rx_skbuffer *buf = &rx_q->skbuf_pool[i];
if (buf->rx_skbuff){
dma_unmap_single(priv->device,
buf->addr,
stmmac_get_rx_buf_frsize(priv) - STMMAC_RX_ALIGN,
DMA_FROM_DEVICE);
dev_kfree_skb(buf->rx_skbuff);
buf->rx_skbuff = NULL;
}
if (buf->sec_page)
page_pool_put_full_page(rx_q->page_pool, buf->sec_page, false);
buf->sec_page = NULL;
}
#endif
static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
int i, gfp_t flags, u32 queue)
{
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
return __stmmac_init_rx_buffers(priv,p,i,flags,queue);
#else
return __stmmac_init_rx_skbuffers(priv,p,i,flags,queue);
#endif
}
static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i)
{
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
__stmmac_free_rx_buffer(priv,queue,i);
#else
__stmmac_free_rx_skbuffer(priv,queue,i);
#endif
}
/** /**
* stmmac_free_tx_buffer - free RX dma buffers * stmmac_free_tx_buffer - free RX dma buffers
* @priv: private structure * @priv: private structure
@@ -1644,8 +1762,11 @@ static void free_dma_rx_desc_resources(struct stmmac_priv *priv)
dma_free_coherent(priv->device, priv->dma_rx_size * dma_free_coherent(priv->device, priv->dma_rx_size *
sizeof(struct dma_extended_desc), sizeof(struct dma_extended_desc),
rx_q->dma_erx, rx_q->dma_rx_phy); rx_q->dma_erx, rx_q->dma_rx_phy);
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
kfree(rx_q->buf_pool); kfree(rx_q->buf_pool);
#else
kfree(rx_q->skbuf_pool);
#endif
if (rx_q->page_pool) if (rx_q->page_pool)
page_pool_destroy(rx_q->page_pool); page_pool_destroy(rx_q->page_pool);
} }
@@ -1711,7 +1832,6 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
rx_q->queue_index = queue; rx_q->queue_index = queue;
rx_q->priv_data = priv; rx_q->priv_data = priv;
pp_params.flags = PP_FLAG_DMA_MAP; pp_params.flags = PP_FLAG_DMA_MAP;
pp_params.pool_size = priv->dma_rx_size; pp_params.pool_size = priv->dma_rx_size;
num_pages = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE); num_pages = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE);
@@ -1726,13 +1846,19 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
rx_q->page_pool = NULL; rx_q->page_pool = NULL;
goto err_dma; goto err_dma;
} }
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
rx_q->buf_pool = kcalloc(priv->dma_rx_size, rx_q->buf_pool = kcalloc(priv->dma_rx_size,
sizeof(*rx_q->buf_pool), sizeof(*rx_q->buf_pool),
GFP_KERNEL); GFP_KERNEL);
if (!rx_q->buf_pool) if (!rx_q->buf_pool)
goto err_dma; goto err_dma;
#else
rx_q->skbuf_pool = kcalloc(priv->dma_rx_size,
sizeof(*rx_q->skbuf_pool),
GFP_KERNEL);
if (!rx_q->skbuf_pool)
goto err_dma;
#endif
if (priv->extend_desc) { if (priv->extend_desc) {
rx_q->dma_erx = dma_alloc_coherent(priv->device, rx_q->dma_erx = dma_alloc_coherent(priv->device,
priv->dma_rx_size * priv->dma_rx_size *
@@ -3664,27 +3790,37 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
int len, dirty = stmmac_rx_dirty(priv, queue); int len, dirty = stmmac_rx_dirty(priv, queue);
unsigned int entry = rx_q->dirty_rx; unsigned int entry = rx_q->dirty_rx;
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
struct stmmac_rx_buffer *buf;
#else
struct stmmac_rx_skbuffer *buf ;
struct sk_buff *skb = NULL;
#endif
gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
if (priv->dma_cap.addr64 <= 32)
gfp |= GFP_DMA32;
len = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE) * PAGE_SIZE; len = DIV_ROUND_UP(priv->dma_buf_sz, PAGE_SIZE) * PAGE_SIZE;
while (dirty-- > 0) { while (dirty-- > 0) {
struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry];
struct dma_desc *p; struct dma_desc *p;
bool use_rx_wd; bool use_rx_wd;
if (priv->extend_desc) if (priv->extend_desc)
p = (struct dma_desc *)(rx_q->dma_erx + entry); p = (struct dma_desc *)(rx_q->dma_erx + entry);
else else
p = rx_q->dma_rx + entry; p = rx_q->dma_rx + entry;
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
buf = &rx_q->buf_pool[entry];
if (!buf->page) { if (!buf->page) {
buf->page = page_pool_dev_alloc_pages(rx_q->page_pool); buf->page = page_pool_alloc_pages(rx_q->page_pool,gfp);
if (!buf->page) if (!buf->page)
break; break;
} }
if (priv->sph && !buf->sec_page) { if (priv->sph && !buf->sec_page) {
buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); buf->sec_page = page_pool_alloc_pages(rx_q->page_pool,gfp);
if (!buf->sec_page) if (!buf->sec_page)
break; break;
@@ -3695,12 +3831,47 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
} }
buf->addr = page_pool_get_dma_addr(buf->page); buf->addr = page_pool_get_dma_addr(buf->page);
/* Sync whole allocation to device. This will invalidate old
* data.
*/
dma_sync_single_for_device(priv->device, buf->addr, len,
DMA_FROM_DEVICE);
#else
buf = &rx_q->skbuf_pool[entry];
if(likely(!buf->rx_skbuff)){
len = stmmac_get_rx_buf_frsize(priv);
skb = netdev_alloc_skb(priv->dev, len);
if (!skb){
//priv->dev->stats.rx_dropped += (1ul<<32);
netdev_err(priv->dev, "%s: dalloc_skb failed,dirty ring %d :\n", __func__,dirty);
break;
}
if(stmmac_get_skb_dma_addr(priv,skb,&buf->addr) < 0){
//priv->dev->stats.rx_dropped += (1ul<<32);
break;
}
buf->rx_skbuff = skb;
}
/* Sync whole allocation to device. This will invalidate old /* Sync whole allocation to device. This will invalidate old
* data. * data.
*/ */
dma_sync_single_for_device(priv->device, buf->addr, len, dma_sync_single_for_device(priv->device, buf->addr, len,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
if (priv->sph && !buf->sec_page) {
buf->sec_page = page_pool_alloc_pages(rx_q->page_pool,gfp);
if (!buf->sec_page)
break;
buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
dma_sync_single_for_device(priv->device, buf->sec_addr,
len, DMA_FROM_DEVICE);
}
#endif
stmmac_set_desc_addr(priv, p, buf->addr); stmmac_set_desc_addr(priv, p, buf->addr);
if (priv->sph) if (priv->sph)
@@ -3815,7 +3986,11 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
while (count < limit) { while (count < limit) {
unsigned int buf1_len = 0, buf2_len = 0; unsigned int buf1_len = 0, buf2_len = 0;
enum pkt_hash_types hash_type; enum pkt_hash_types hash_type;
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
struct stmmac_rx_buffer *buf; struct stmmac_rx_buffer *buf;
#else
struct stmmac_rx_skbuffer *skbuf;
#endif
struct dma_desc *np, *p; struct dma_desc *np, *p;
int entry; int entry;
u32 hash; u32 hash;
@@ -3838,8 +4013,11 @@ read_again:
buf1_len = 0; buf1_len = 0;
buf2_len = 0; buf2_len = 0;
entry = next_entry; entry = next_entry;
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
buf = &rx_q->buf_pool[entry]; buf = &rx_q->buf_pool[entry];
#else
skbuf = &rx_q->skbuf_pool[entry];
#endif
if (priv->extend_desc) if (priv->extend_desc)
p = (struct dma_desc *)(rx_q->dma_erx + entry); p = (struct dma_desc *)(rx_q->dma_erx + entry);
else else
@@ -3863,12 +4041,14 @@ read_again:
prefetch(np); prefetch(np);
if (priv->extend_desc) if (priv->extend_desc && priv->extend_stat_need)
stmmac_rx_extended_status(priv, &priv->dev->stats, stmmac_rx_extended_status(priv, &priv->dev->stats,
&priv->xstats, rx_q->dma_erx + entry); &priv->xstats, rx_q->dma_erx + entry);
if (unlikely(status == discard_frame)) { if (unlikely(status == discard_frame)) {
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
page_pool_recycle_direct(rx_q->page_pool, buf->page); page_pool_recycle_direct(rx_q->page_pool, buf->page);
buf->page = NULL; buf->page = NULL;
#endif
error = 1; error = 1;
if (!priv->hwts_rx_en) if (!priv->hwts_rx_en)
priv->dev->stats.rx_errors++; priv->dev->stats.rx_errors++;
@@ -3884,11 +4064,14 @@ read_again:
} }
/* Buffer is good. Go on. */ /* Buffer is good. Go on. */
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
prefetch(page_address(buf->page)); prefetch(page_address(buf->page));
if (buf->sec_page) if (buf->sec_page)
prefetch(page_address(buf->sec_page)); prefetch(page_address(buf->sec_page));
#else
skb = skbuf->rx_skbuff;
prefetch(skb->data);
#endif
buf1_len = stmmac_rx_buf1_len(priv, p, status, len); buf1_len = stmmac_rx_buf1_len(priv, p, status, len);
len += buf1_len; len += buf1_len;
buf2_len = stmmac_rx_buf2_len(priv, p, status, len); buf2_len = stmmac_rx_buf2_len(priv, p, status, len);
@@ -3911,7 +4094,30 @@ read_again:
len -= ETH_FCS_LEN; len -= ETH_FCS_LEN;
} }
#ifdef CONFIG_STMMAC_RX_ZERO_COPY
skb = skbuf->rx_skbuff;
if (!skb) {
priv->dev->stats.rx_dropped++;
count++;
goto drain_data;
}
dma_sync_single_for_cpu(priv->device, skbuf->addr,
buf1_len, DMA_FROM_DEVICE);
skb_put(skb, buf1_len);
skbuf->rx_skbuff = NULL;
if (buf2_len) {
dma_sync_single_for_cpu(priv->device, skbuf->sec_addr,
buf2_len, DMA_FROM_DEVICE);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
skbuf->sec_page, 0, buf2_len,
priv->dma_buf_sz);
/* Data payload appended into SKB */
page_pool_release_page(rx_q->page_pool, skbuf->sec_page);
skbuf->sec_page = NULL;
}
#else
if (!skb) { if (!skb) {
skb = napi_alloc_skb(&ch->rx_napi, buf1_len); skb = napi_alloc_skb(&ch->rx_napi, buf1_len);
if (!skb) { if (!skb) {
@@ -3952,7 +4158,7 @@ read_again:
page_pool_release_page(rx_q->page_pool, buf->sec_page); page_pool_release_page(rx_q->page_pool, buf->sec_page);
buf->sec_page = NULL; buf->sec_page = NULL;
} }
#endif
drain_data: drain_data:
if (likely(status & rx_not_ls)) if (likely(status & rx_not_ls))
goto read_again; goto read_again;
@@ -4104,8 +4310,12 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
new_mtu = STMMAC_ALIGN(new_mtu); new_mtu = STMMAC_ALIGN(new_mtu);
/* If condition true, FIFO is too small or MTU too large */ /* If condition true, FIFO is too small or MTU too large */
if ((txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB)) if ((txfifosz && txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB)){
netdev_err(priv->dev,"FIFO is too small or MTU too large\n");
printk("new_mtu %d -- %d,%d,%d \n",new_mtu,txfifosz,priv->plat->tx_fifo_size,priv->dma_cap.tx_fifo_size);
return -EINVAL; return -EINVAL;
}
dev->mtu = mtu; dev->mtu = mtu;
@@ -5083,6 +5293,11 @@ int stmmac_dvr_probe(struct device *device,
priv->dma_cap.addr64 = 32; priv->dma_cap.addr64 = 32;
} }
} }
if(priv->dma_cap.addr64 <= 32){
skb_set_alloc_dma32(GFP_DMA32);
}
dev_info(priv->device, "Using %d bits DMA width,skb alloc dma32 flag %x\n",
priv->dma_cap.addr64,skb_get_alloc_dma32());
ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog); ndev->watchdog_timeo = msecs_to_jiffies(watchdog);

View File

@@ -18,9 +18,18 @@
#include <dt-bindings/pinctrl/light-fm-right-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-right-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-left-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-left-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-audio-pinctrl.h>
#include "../core.h" #include "../core.h"
enum light_pinctrl_type {
LIGHT_MPW,
LIGHT_FM_RIGHT,
LIGHT_FM_LEFT,
LIGHT_FM_AON,
LIGHT_FM_AUDIO,
};
struct light_pin { struct light_pin {
unsigned int pin_id; unsigned int pin_id;
unsigned int mux_mode; unsigned int mux_mode;
@@ -50,6 +59,8 @@ struct light_pinctrl_soc_info {
unsigned int grp_index; unsigned int grp_index;
struct light_pmx_func *functions; struct light_pmx_func *functions;
unsigned int nfunctions; unsigned int nfunctions;
char *label;
enum light_pinctrl_type type;
unsigned int cfg_off; unsigned int cfg_off;
unsigned int mux_off; unsigned int mux_off;
@@ -66,6 +77,7 @@ struct light_pinctrl {
#define LIGHT_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin) #define LIGHT_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
#define LIGHT_PAD_CONFIG(idx) (priv->info->cfg_off + (idx >> 1) * 4) #define LIGHT_PAD_CONFIG(idx) (priv->info->cfg_off + (idx >> 1) * 4)
#define LIGHT_PAD_MUX(idx) (priv->info->mux_off + ((idx >> 3) * 4)) #define LIGHT_PAD_MUX(idx) (priv->info->mux_off + ((idx >> 3) * 4))
#define LIGHT_AUDIO_PAD_MUX(idx) (priv->info->mux_off + ((idx >> 4) * 4))
static const char *pin_get_name_from_info(struct light_pinctrl_soc_info *info, static const char *pin_get_name_from_info(struct light_pinctrl_soc_info *info,
const unsigned int pin_id) const unsigned int pin_id)
@@ -247,13 +259,31 @@ static int light_pmx_set(struct pinctrl_dev *pctldev, unsigned int selector,
continue; continue;
} }
mux = readl(priv->base + LIGHT_PAD_MUX(pin_id)); if (info->type == LIGHT_FM_AUDIO) {
shift = ((pin_id % 8) << 2); if (pin->mux_mode == AUDIO_IO_GPIO) {
mux &= ~(0xF << shift); /* 4 mux bits for one pad */ mux = ~(1 << pin_id) & readl(priv->base);
mux |= (pin->mux_mode << shift); writel(mux, priv->base); /* Controlled by GPIO under AUDIO_SUBSYS */
writel(mux, priv->base + LIGHT_PAD_MUX(pin_id)); continue;
dev_dbg(priv->dev, "write: offset 0x%x val 0x%x\n", }
LIGHT_PAD_MUX(pin_id), mux); mux = (1 << pin_id) | readl(priv->base);
writel(mux, priv->base);
mux = readl(priv->base + LIGHT_AUDIO_PAD_MUX(pin_id));
shift = ((pin_id % 16) << 1);
mux &= ~(0x3 << shift); /* 2 mux bits for one pad */
mux |= (pin->mux_mode << shift);
writel(mux, priv->base + LIGHT_AUDIO_PAD_MUX(pin_id));
dev_dbg(priv->dev, "write: offset 0x%x val 0x%x\n",
LIGHT_AUDIO_PAD_MUX(pin_id), mux);
} else {
mux = readl(priv->base + LIGHT_PAD_MUX(pin_id));
shift = ((pin_id % 8) << 2);
mux &= ~(0xF << shift); /* 4 mux bits for one pad */
mux |= (pin->mux_mode << shift);
writel(mux, priv->base + LIGHT_PAD_MUX(pin_id));
dev_dbg(priv->dev, "write: offset 0x%x val 0x%x\n",
LIGHT_PAD_MUX(pin_id), mux);
}
} }
return 0; return 0;
@@ -430,7 +460,15 @@ static int light_pinctrl_parse_groups(struct device_node *np,
struct light_pin *pin = &grp->pins[i]; struct light_pin *pin = &grp->pins[i];
pin->pin_id = be32_to_cpu(*list++); pin->pin_id = be32_to_cpu(*list++);
pin->mux_mode = be32_to_cpu(*list++) & 0xF; if (info->type == LIGHT_FM_AUDIO) {
pin->mux_mode = be32_to_cpu(*list++);
if (pin->mux_mode != AUDIO_IO_GPIO){
pin->mux_mode &= 0x3;
}
} else {
pin->mux_mode = be32_to_cpu(*list++) & 0xF;
}
pin->config = be32_to_cpu(*list++) & 0xFFFF; pin->config = be32_to_cpu(*list++) & 0xFFFF;
grp->pin_ids[i] = grp->pins[i].pin_id; grp->pin_ids[i] = grp->pins[i].pin_id;
@@ -841,6 +879,40 @@ static const struct pinctrl_pin_desc light_fm_aon_pinctrl_pads[] = {
LIGHT_PINCTRL_PIN(FM_AUDIO_PA30), LIGHT_PINCTRL_PIN(FM_AUDIO_PA30),
}; };
static const struct pinctrl_pin_desc light_fm_audio_pinctrl_pads[] = {
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA0),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA1),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA2),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA3),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA4),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA5),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA6),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA7),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA8),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA9),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA10),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA11),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA12),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA13),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA14),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA15),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA16),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA17),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA18),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA19),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA20),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA21),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA22),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA23),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA24),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA25),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA26),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA27),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA28),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA29),
LIGHT_PINCTRL_PIN(FM_AUDIO_IO_PA30),
};
static int light_pinctrl_mpw_convert_pin_off(const unsigned int pin_id) static int light_pinctrl_mpw_convert_pin_off(const unsigned int pin_id)
{ {
unsigned int cov_pin_id = pin_id; unsigned int cov_pin_id = pin_id;
@@ -865,6 +937,7 @@ static int light_pinctrl_fm_aon_covert_pin_off(const unsigned int pin_id)
static struct light_pinctrl_soc_info light_mpw_pinctrl_info = { static struct light_pinctrl_soc_info light_mpw_pinctrl_info = {
.pins = light_mpw_pinctrl_pads, .pins = light_mpw_pinctrl_pads,
.npins = ARRAY_SIZE(light_mpw_pinctrl_pads), .npins = ARRAY_SIZE(light_mpw_pinctrl_pads),
.type = LIGHT_MPW,
.cfg_off = 0x4c, .cfg_off = 0x4c,
.mux_off = 0x404, .mux_off = 0x404,
.covert_pin_off = light_pinctrl_mpw_convert_pin_off, .covert_pin_off = light_pinctrl_mpw_convert_pin_off,
@@ -873,6 +946,7 @@ static struct light_pinctrl_soc_info light_mpw_pinctrl_info = {
static struct light_pinctrl_soc_info light_fm_right_pinctrl_info = { static struct light_pinctrl_soc_info light_fm_right_pinctrl_info = {
.pins = light_fm_right_pinctrl_pads, .pins = light_fm_right_pinctrl_pads,
.npins = ARRAY_SIZE(light_fm_right_pinctrl_pads), .npins = ARRAY_SIZE(light_fm_right_pinctrl_pads),
.type = LIGHT_FM_RIGHT,
.cfg_off = 0x0, .cfg_off = 0x0,
.mux_off = 0x400, .mux_off = 0x400,
}; };
@@ -880,6 +954,7 @@ static struct light_pinctrl_soc_info light_fm_right_pinctrl_info = {
static struct light_pinctrl_soc_info light_fm_left_pinctrl_info = { static struct light_pinctrl_soc_info light_fm_left_pinctrl_info = {
.pins = light_fm_left_pinctrl_pads, .pins = light_fm_left_pinctrl_pads,
.npins = ARRAY_SIZE(light_fm_left_pinctrl_pads), .npins = ARRAY_SIZE(light_fm_left_pinctrl_pads),
.type = LIGHT_FM_LEFT,
.cfg_off = 0x0, .cfg_off = 0x0,
.mux_off = 0x400, .mux_off = 0x400,
}; };
@@ -887,16 +962,27 @@ static struct light_pinctrl_soc_info light_fm_left_pinctrl_info = {
static struct light_pinctrl_soc_info light_fm_aon_pinctrl_info = { static struct light_pinctrl_soc_info light_fm_aon_pinctrl_info = {
.pins = light_fm_aon_pinctrl_pads, .pins = light_fm_aon_pinctrl_pads,
.npins = ARRAY_SIZE(light_fm_aon_pinctrl_pads), .npins = ARRAY_SIZE(light_fm_aon_pinctrl_pads),
.type = LIGHT_FM_AON,
.cfg_off = 0x0, .cfg_off = 0x0,
.mux_off = 0x400, .mux_off = 0x400,
.covert_pin_off = light_pinctrl_fm_aon_covert_pin_off, .covert_pin_off = light_pinctrl_fm_aon_covert_pin_off,
}; };
static struct light_pinctrl_soc_info light_fm_audio_pinctrl_info = {
.pins = light_fm_audio_pinctrl_pads,
.npins = ARRAY_SIZE(light_fm_audio_pinctrl_pads),
.label = "LIGHT-AUDIO-IO",
.type = LIGHT_FM_AUDIO,
.cfg_off = 0x0C,
.mux_off = 0x4,
};
static const struct of_device_id light_pinctrl_of_match[] = { static const struct of_device_id light_pinctrl_of_match[] = {
{ .compatible = "thead,light-mpw-pinctrl", .data = &light_mpw_pinctrl_info}, { .compatible = "thead,light-mpw-pinctrl", .data = &light_mpw_pinctrl_info},
{ .compatible = "thead,light-fm-right-pinctrl", .data = &light_fm_right_pinctrl_info}, { .compatible = "thead,light-fm-right-pinctrl", .data = &light_fm_right_pinctrl_info},
{ .compatible = "thead,light-fm-left-pinctrl", .data = &light_fm_left_pinctrl_info}, { .compatible = "thead,light-fm-left-pinctrl", .data = &light_fm_left_pinctrl_info},
{ .compatible = "thead,light-fm-aon-pinctrl", .data = &light_fm_aon_pinctrl_info}, { .compatible = "thead,light-fm-aon-pinctrl", .data = &light_fm_aon_pinctrl_info},
{ .compatible = "thead,light-fm-audio-pinctrl", .data = &light_fm_audio_pinctrl_info},
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, light_pinctrl_of_match); MODULE_DEVICE_TABLE(of, light_pinctrl_of_match);

View File

@@ -34,6 +34,11 @@ struct light_src {
enum light_src_registers { enum light_src_registers {
SRC_WDT0 = 0x0034, SRC_WDT0 = 0x0034,
SRC_WDT1 = 0x0038, SRC_WDT1 = 0x0038,
SRC_NPU = 0x01b0,
};
enum light_vpsys_src_registers {
SRC_FCE = 0x0004,
}; };
static int light_reset_update(struct light_src *lightsrc, static int light_reset_update(struct light_src *lightsrc,
@@ -48,6 +53,11 @@ static int light_reset_update(struct light_src *lightsrc,
static const struct light_src_signal light_src_signals[] = { static const struct light_src_signal light_src_signals[] = {
[LIGHT_RESET_WDT0] = { SRC_WDT0, BIT(0) }, [LIGHT_RESET_WDT0] = { SRC_WDT0, BIT(0) },
[LIGHT_RESET_WDT1] = { SRC_WDT1, BIT(0) }, [LIGHT_RESET_WDT1] = { SRC_WDT1, BIT(0) },
[LIGHT_RESET_NPU] = { SRC_NPU, BIT(0) },
};
static const struct light_src_signal light_vpsys_src_signals[] = {
[LIGHT_RESET_FCE] = { SRC_FCE, BIT(0)|BIT(1)|BIT(4)|BIT(5) },
}; };
static struct light_src *to_light_src(struct reset_controller_dev *rcdev) static struct light_src *to_light_src(struct reset_controller_dev *rcdev)
@@ -94,6 +104,15 @@ static const struct light_src_variant variant_light = {
}, },
}; };
static const struct light_src_variant variant_light_vpsys = {
.signals = light_vpsys_src_signals,
.signals_num = ARRAY_SIZE(light_vpsys_src_signals),
.ops = {
.assert = light_reset_assert,
.deassert = light_reset_deassert,
},
};
static int light_reset_probe(struct platform_device *pdev) static int light_reset_probe(struct platform_device *pdev)
{ {
struct light_src *lightsrc; struct light_src *lightsrc;
@@ -123,6 +142,7 @@ static int light_reset_probe(struct platform_device *pdev)
static const struct of_device_id light_reset_dt_ids[] = { static const struct of_device_id light_reset_dt_ids[] = {
{ .compatible = "thead,light-reset-src", .data = &variant_light }, { .compatible = "thead,light-reset-src", .data = &variant_light },
{ .compatible = "thead,light-vpsys-reset-src", .data = &variant_light_vpsys },
}; };
MODULE_DEVICE_TABLE(of, light_reset_dt_ids); MODULE_DEVICE_TABLE(of, light_reset_dt_ids);

View File

@@ -58,6 +58,10 @@ config RPMSG_QCOM_SMD
providing communication channels to remote processors in Qualcomm providing communication channels to remote processors in Qualcomm
platforms. platforms.
config RPMSG_THEAD_LIGHT
tristate "THEAD Light RPM Driver"
depends on RPMSG
config RPMSG_VIRTIO config RPMSG_VIRTIO
tristate "Virtio RPMSG bus driver" tristate "Virtio RPMSG bus driver"
depends on HAS_DMA depends on HAS_DMA

View File

@@ -8,3 +8,4 @@ obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o
obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o
obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
obj-$(CONFIG_RPMSG_THEAD_LIGHT) += light_rpmsg.o

763
drivers/rpmsg/light_rpmsg.c Normal file
View File

@@ -0,0 +1,763 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited.
*
* derived from the omap-rpmsg implementation.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/rpmsg.h>
#include <linux/slab.h>
#include <linux/virtio.h>
#include <linux/virtio_config.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_ring.h>
#include <linux/light_rpmsg.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/debugfs.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/workqueue.h>
#include <linux/light_rpmsg.h>
#define MBOX_MAX_MSG_LEN 28
#define WJ_MBOX_SEND_MAX_MESSAGE_LENGTH 28
#define HEXDUMP_BYTES_PER_LINE 28
#define HEXDUMP_LINE_LEN ((HEXDUMP_BYTES_PER_LINE * 4) + 2)
#define HEXDUMP_MAX_LEN (HEXDUMP_LINE_LEN * \
(MBOX_MAX_MSG_LEN / HEXDUMP_BYTES_PER_LINE))
//extern struct light_rpmsg_vproc *pri_rpdev;
static struct dentry *root_debugfs_dir;
struct mbox_client_light_device {
struct device *dev;
void __iomem *tx_mmio;
void __iomem *rx_mmio;
struct mbox_chan *tx_channel;
struct mbox_chan *rx_channel;
char *rx_buffer;
struct regmap *audio_mbox_regmap;
char *message;
spinlock_t lock;
};
struct mbox_client_light_device *tdev_priv;
static volatile uint32_t *p_mbox_reg;
static volatile uint32_t *p_mbox_reg1;
static volatile uint32_t *p_mbox_reg2;
/*
* For now, allocate 256 buffers of 512 bytes for each side. each buffer
* will then have 16B for the msg header and 496B for the payload.
* This will require a total space of 256KB for the buffers themselves, and
* 3 pages for every vring (the size of the vring depends on the number of
* buffers it supports).
*/
#define RPMSG_NUM_BUFS (512)
//#define RPMSG_BUF_SIZE (512)
//#define RPMSG_BUFS_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE)
/*
* The alignment between the consumer and producer parts of the vring.
* Note: this is part of the "wire" protocol. If you change this, you need
* to update your BIOS image as well
*/
#define RPMSG_VRING_ALIGN (4096)
/* With 256 buffers, our vring will occupy 3 pages */
#define RPMSG_RING_SIZE ((DIV_ROUND_UP(vring_size(RPMSG_NUM_BUFS / 2, \
RPMSG_VRING_ALIGN), PAGE_SIZE)) * PAGE_SIZE)
#define to_light_virdev(vd) container_of(vd, struct light_virdev, vdev)
#define to_light_rpdev(vd, id) container_of(vd, struct light_rpmsg_vproc, ivdev[id])
struct light_rpmsg_vq_info {
__u16 num; /* number of entries in the virtio_ring */
__u16 vq_id; /* a globaly unique index of this virtqueue */
void *addr; /* address where we mapped the virtio ring */
struct light_rpmsg_vproc *rpdev;
};
static u64 light_rpmsg_get_features(struct virtio_device *vdev)
{
/* VIRTIO_RPMSG_F_NS has been made private */
return 1 << 0;
}
static int light_rpmsg_finalize_features(struct virtio_device *vdev)
{
/* Give virtio_ring a chance to accept features */
vring_transport_features(vdev);
return 0;
}
/* kick the remote processor, and let it know which virtqueue to poke at */
static bool light_rpmsg_notify(struct virtqueue *vq)
{
unsigned int mu_rpmsg = 0;
int ret;
struct light_rpmsg_vq_info *rpvq = vq->priv;
mu_rpmsg = rpvq->vq_id << 16;
mutex_lock(&rpvq->rpdev->lock);
//pr_info("light rpmsg: notify %d\n", rpvq->rpdev->first_notify);
if (unlikely(rpvq->rpdev->first_notify > 0)) {
rpvq->rpdev->first_notify--;
if (!tdev_priv->tx_channel) {
dev_err(tdev_priv->dev, "Channel cannot do Tx+++\n");
return -EINVAL;
}
ret = mbox_send_message(tdev_priv->tx_channel, "Hello, Queue!");
} else {
*p_mbox_reg1 |= 1 << 0;
*p_mbox_reg2 |= 1 << 0;
}
mutex_unlock(&rpvq->rpdev->lock);
return true;
}
static int light_mu_rpmsg_callback(struct notifier_block *this,
unsigned long index, void *data)
{
u32 mu_msg = (phys_addr_t) data;
struct light_virdev *virdev;
virdev = container_of(this, struct light_virdev, nb);
pr_debug("light rpmsg: %s notifier_call mu_msg: 0x%x\n", __func__, mu_msg);
/* ignore vq indices which are clearly not for us */
mu_msg = mu_msg >> 16;
if (mu_msg < virdev->base_vq_id || mu_msg > virdev->base_vq_id + 1) {
pr_debug("light rpmsg: mu_msg 0x%x is invalid\n", mu_msg);
//return NOTIFY_DONE;
}
mu_msg -= virdev->base_vq_id;
pr_debug("%smu_msg 0x%xbase_vq_id 0x%xvirdev num_of_vqs0x%x\n", __func__, mu_msg, virdev->base_vq_id, virdev->num_of_vqs);
/*
* Currently both PENDING_MSG and explicit-virtqueue-index
* messaging are supported.
* Whatever approach is taken, at this point 'mu_msg' contains
* the index of the vring which was just triggered.
*/
//if (mu_msg < virdev->num_of_vqs)
vring_interrupt(mu_msg, virdev->vq[mu_msg]);
return NOTIFY_DONE;
}
static int light_mu_rpmsg_register_nb(struct light_rpmsg_vproc *rpdev,
struct notifier_block *nb)
{
if ((rpdev == NULL) || (nb == NULL))
return -EINVAL;
blocking_notifier_chain_register(&(rpdev->notifier), nb);
return 0;
}
static int light_mu_rpmsg_unregister_nb(struct light_rpmsg_vproc *rpdev,
struct notifier_block *nb)
{
if ((rpdev == NULL) || (nb == NULL))
return -EINVAL;
blocking_notifier_chain_unregister(&(rpdev->notifier), nb);
return 0;
}
static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
unsigned int index,
void (*callback)(struct virtqueue *vq),
const char *name,
bool ctx)
{
struct light_virdev *virdev = to_light_virdev(vdev);
struct light_rpmsg_vproc *rpdev = to_light_rpdev(virdev,
virdev->base_vq_id / 2);
struct light_rpmsg_vq_info *rpvq;
struct virtqueue *vq;
int err;
//static void __iomem *brd_io;
rpvq = kmalloc(sizeof(*rpvq), GFP_KERNEL);
if (!rpvq)
return ERR_PTR(-ENOMEM);
/* ioremap'ing normal memory, so we cast away sparse's complaints */
//rpvq->addr = (__force void *) ioremap_nocache(virdev->vring[index],
// RPMSG_RING_SIZE);
rpvq->addr = (__force void *) ioremap(virdev->vring[index],
RPMSG_RING_SIZE);
if (!rpvq->addr) {
err = -ENOMEM;
goto free_rpvq;
}
p_mbox_reg = ioremap(0xffefc48000,25);
p_mbox_reg1 = p_mbox_reg + 4;
p_mbox_reg2 = p_mbox_reg + 5;
memset_io(rpvq->addr, 0, RPMSG_RING_SIZE);
pr_debug("vring%d: phys 0x%x, virt 0x%p\n", index, virdev->vring[index],
rpvq->addr);
vq = vring_new_virtqueue(index, RPMSG_NUM_BUFS / 2, RPMSG_VRING_ALIGN,
vdev, true, ctx,
rpvq->addr,
light_rpmsg_notify, callback,
name);
if (!vq) {
pr_err("light rpmsg: vring_new_virtqueue failed\n");
err = -ENOMEM;
goto unmap_vring;
}
virdev->vq[index] = vq;
vq->priv = rpvq;
/* system-wide unique id for this virtqueue */
rpvq->vq_id = virdev->base_vq_id + index;
rpvq->rpdev = rpdev;
mutex_init(&rpdev->lock);
return vq;
unmap_vring:
/* iounmap normal memory, so make sparse happy */
iounmap((__force void __iomem *) rpvq->addr);
free_rpvq:
kfree(rpvq);
return ERR_PTR(err);
}
static void light_rpmsg_del_vqs(struct virtio_device *vdev)
{
struct virtqueue *vq, *n;
struct light_virdev *virdev = to_light_virdev(vdev);
struct light_rpmsg_vproc *rpdev = to_light_rpdev(virdev,
virdev->base_vq_id / 2);
list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
struct light_rpmsg_vq_info *rpvq = vq->priv;
iounmap(rpvq->addr);
vring_del_virtqueue(vq);
kfree(rpvq);
}
if (&virdev->nb)
light_mu_rpmsg_unregister_nb(rpdev, &virdev->nb);
}
static int light_rpmsg_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
struct virtqueue *vqs[],
vq_callback_t *callbacks[],
const char * const names[],
const bool *ctx,
struct irq_affinity *desc)
{
struct light_virdev *virdev = to_light_virdev(vdev);
struct light_rpmsg_vproc *rpdev = to_light_rpdev(virdev,
virdev->base_vq_id / 2);
int i, err;
/* we maintain two virtqueues per remote processor (for RX and TX) */
if (nvqs != 2)
return -EINVAL;
for (i = 0; i < nvqs; ++i) {
vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i],
ctx ? ctx[i] : false);
if (IS_ERR(vqs[i])) {
err = PTR_ERR(vqs[i]);
goto error;
}
}
virdev->num_of_vqs = nvqs;
virdev->nb.notifier_call = light_mu_rpmsg_callback;
light_mu_rpmsg_register_nb(rpdev, &virdev->nb);
return 0;
error:
light_rpmsg_del_vqs(vdev);
return err;
}
static void light_rpmsg_reset(struct virtio_device *vdev)
{
dev_dbg(&vdev->dev, "reset!\n");
}
static u8 light_rpmsg_get_status(struct virtio_device *vdev)
{
return 0;
}
static void light_rpmsg_set_status(struct virtio_device *vdev, u8 status)
{
dev_dbg(&vdev->dev, "%s new status: %d\n", __func__, status);
}
static void light_rpmsg_vproc_release(struct device *dev)
{
/* this handler is provided so driver core doesn't yell at us */
}
static struct virtio_config_ops light_rpmsg_config_ops = {
.get_features = light_rpmsg_get_features,
.finalize_features = light_rpmsg_finalize_features,
.find_vqs = light_rpmsg_find_vqs,
.del_vqs = light_rpmsg_del_vqs,
.reset = light_rpmsg_reset,
.set_status = light_rpmsg_set_status,
.get_status = light_rpmsg_get_status,
};
static struct light_rpmsg_vproc light_rpmsg_vprocs[] = {
{
.rproc_name = "m4",
},
{
.rproc_name = "m4",
},
};
static const struct of_device_id light_rpmsg_dt_ids[] = {
{ .compatible = "light,light-rpmsg", .data = (void *)LIGHT_RPMSG, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, light_rpmsg_dt_ids);
static int set_vring_phy_buf(struct platform_device *pdev,
struct light_rpmsg_vproc *rpdev, int vdev_nums)
{
struct resource *res;
resource_size_t size;
unsigned int start, end;
int i, ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res) {
size = resource_size(res);
start = res->start;
end = res->start + size;
for (i = 0; i < vdev_nums; i++) {
rpdev->ivdev[i].vring[0] = start;
rpdev->ivdev[i].vring[1] = start +
0x8000;
start += 0x10000;
if (start > end) {
pr_err("Too small memory size %x!\n",
(u32)size);
ret = -EINVAL;
break;
}
}
} else {
return -ENOMEM;
}
return ret;
}
static void rpmsg_work_handler(struct work_struct *work)
{
u32 message = 0;
struct delayed_work *dwork = to_delayed_work(work);
struct light_rpmsg_vproc *rpdev = container_of(dwork,
struct light_rpmsg_vproc, rpmsg_work);
//spin_lock_irqsave(&rpdev->mu_lock, flags);
blocking_notifier_call_chain(&(rpdev->notifier), 4,
(void *)(phys_addr_t)message);
//spin_unlock_irqrestore(&rpdev->mu_lock, flags);
}
struct light_rpmsg_vproc *pri_rpdev;
EXPORT_SYMBOL_GPL(pri_rpdev);
static int light_rpmsg_probe(struct platform_device *pdev)
{
int core_id, j, ret = 0;
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct light_rpmsg_vproc *rpdev;
if (of_property_read_u32(np, "multi-core-id", &core_id))
core_id = 0;
rpdev = &light_rpmsg_vprocs[core_id];
rpdev->core_id = core_id;
rpdev->variant = (enum light_rpmsg_variants)of_device_get_match_data(dev);
spin_lock_init(&rpdev->mu_lock);
pri_rpdev = rpdev;
INIT_DELAYED_WORK(&(rpdev->rpmsg_work), rpmsg_work_handler);
BLOCKING_INIT_NOTIFIER_HEAD(&(rpdev->notifier));
pr_info("light rpmsg: Ready for cross core communication!\n");
ret = of_property_read_u32(np, "vdev-nums", &rpdev->vdev_nums);
if (ret) {
rpdev->vdev_nums = 1;
}
if (rpdev->vdev_nums > MAX_VDEV_NUMS) {
pr_err("light rpmsg: vdev-nums exceed the max %d\n", MAX_VDEV_NUMS);
return -EINVAL;
}
rpdev->first_notify = rpdev->vdev_nums;
pr_info("light rpmsg: rproc_name = %s",rpdev->rproc_name);
if (!strcmp(rpdev->rproc_name, "m4")) {
ret = set_vring_phy_buf(pdev, rpdev,
rpdev->vdev_nums);
if (ret) {
pr_err("light rpmsg: No vring buffer.\n");
return -ENOMEM;
}
} else {
pr_err("light rpmsg: No remote processor.\n");
return -ENODEV;
}
for (j = 0; j < rpdev->vdev_nums; j++) {
pr_debug("%s rpdev%d vdev%d: vring0 0x%x, vring1 0x%x\n",
__func__, rpdev->core_id, rpdev->vdev_nums,
rpdev->ivdev[j].vring[0],
rpdev->ivdev[j].vring[1]);
rpdev->ivdev[j].vdev.id.device = VIRTIO_ID_RPMSG;
rpdev->ivdev[j].vdev.config = &light_rpmsg_config_ops;
rpdev->ivdev[j].vdev.dev.parent = &pdev->dev;
rpdev->ivdev[j].vdev.dev.release = light_rpmsg_vproc_release;
rpdev->ivdev[j].base_vq_id = j * 2;
ret = register_virtio_device(&rpdev->ivdev[j].vdev);
if (ret) {
pr_err("light rpmsg: %s failed to register rpdev: %d\n", __func__, ret);
return ret;
}
}
platform_set_drvdata(pdev, rpdev);
return ret;
}
#ifdef CONFIG_PM_SLEEP
static int light_rpmsg_suspend(struct device *dev)
{
struct light_rpmsg_vproc *rpdev = dev_get_drvdata(dev);
clk_disable_unprepare(rpdev->mu_clk);
return 0;
}
static int light_rpmsg_resume(struct device *dev)
{
struct light_rpmsg_vproc *rpdev = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(rpdev->mu_clk);
if (ret) {
pr_err("unable to enable mu clock\n");
return ret;
}
return ret;
}
#endif
static SIMPLE_DEV_PM_OPS(light_rpmsg_pm_ops, light_rpmsg_suspend, light_rpmsg_resume);
static struct platform_driver light_rpmsg_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "light-rpmsg",
.of_match_table = light_rpmsg_dt_ids,
.pm = &light_rpmsg_pm_ops,
},
.probe = light_rpmsg_probe,
};
static int __init light_rpmsg_init(void)
{
int ret;
ret = platform_driver_register(&light_rpmsg_driver);
if (ret)
pr_err("light rpmsg: Unable to initialize\n");
else
pr_info("light rpmsg: driver is registered.\n");
return ret;
}
MODULE_AUTHOR(",Inc.");
MODULE_DESCRIPTION("remote processor messaging virtio device");
MODULE_LICENSE("GPL v2");
late_initcall(light_rpmsg_init);
static ssize_t mbox_client_light_message_write(struct file *filp,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct mbox_client_light_device *tdev = filp->private_data;
void *data;
int ret;
if (!tdev->tx_channel) {
dev_err(tdev->dev, "Channel cannot do Tx\n");
return -EINVAL;
}
if (count > WJ_MBOX_SEND_MAX_MESSAGE_LENGTH)
count = WJ_MBOX_SEND_MAX_MESSAGE_LENGTH;
tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
if (!tdev->message)
return -ENOMEM;
ret = copy_from_user(tdev->message, userbuf, count);
if (ret) {
ret = -EFAULT;
goto out;
}
data = tdev->message;
print_hex_dump(KERN_INFO, __func__, DUMP_PREFIX_NONE, 16, 1, tdev->message, MBOX_MAX_MSG_LEN, true);
ret = mbox_send_message(tdev->tx_channel, data);
if (ret < 0)
dev_err(tdev->dev, "Failed to send message via mailbox\n");
out:
kfree(tdev->message);
return ret < 0 ? ret : count;
}
static ssize_t mbox_client_light_message_read(struct file *filp,
char __user *userbuf,
size_t count, loff_t *ppos)
{
struct mbox_client_light_device *tdev = filp->private_data;
unsigned long flags;
print_hex_dump(KERN_INFO, __func__, DUMP_PREFIX_NONE, 16, 1, tdev->rx_buffer, MBOX_MAX_MSG_LEN, true);
spin_lock_irqsave(&tdev->lock, flags);
memset(tdev->rx_buffer, 0, MBOX_MAX_MSG_LEN);
spin_unlock_irqrestore(&tdev->lock, flags);
return MBOX_MAX_MSG_LEN;
}
static const struct file_operations mbox_client_light_message_ops = {
.write = mbox_client_light_message_write,
.read = mbox_client_light_message_read,
.open = simple_open,
.llseek = generic_file_llseek,
};
static int index_names = 0;
static bool debugfs_dir_created = false;
static const char* file_names[] = {"mbox-client0", "mbox-client1"};
static int mbox_client_light_add_debugfs(struct platform_device *pdev,
struct mbox_client_light_device *tdev)
{
if (!debugfs_initialized())
return 0;
if (index_names > 2) {
dev_err(&pdev->dev, "Max device index is 2\n");
return 0;
}
if (!debugfs_dir_created) {
root_debugfs_dir = debugfs_create_dir("mailbox",NULL);
if (!root_debugfs_dir) {
dev_err(&pdev->dev,
"Failed to create mailbox debugfs\n");
return -EINVAL;
}
debugfs_dir_created = true;
}
debugfs_create_file(file_names[index_names], 0600, root_debugfs_dir,
tdev, &mbox_client_light_message_ops);
index_names++;
return 0;
}
static void mbox_client_light_receive_message(struct mbox_client *client,
void *message)
{
struct mbox_client_light_device *tdev = dev_get_drvdata(client->dev);
char *data = message;
spin_lock(&tdev->lock);
memcpy(tdev->rx_buffer, data, MBOX_MAX_MSG_LEN);
spin_unlock(&tdev->lock);
//printk("mbox_client receive rpmsg_work\n");
schedule_delayed_work(&(pri_rpdev->rpmsg_work), 0);
//print_hex_dump(KERN_INFO, __func__, DUMP_PREFIX_NONE, 16, 1, tdev->rx_buffer, MBOX_MAX_MSG_LEN, true);
}
static struct mbox_chan *
mbox_client_light_request_channel(struct platform_device *pdev,
const char *name)
{
struct mbox_client *client;
struct mbox_chan *channel;
client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
if (!client)
return ERR_PTR(-ENOMEM);
client->dev = &pdev->dev;
client->tx_block = true;
client->knows_txdone = false;
client->tx_tout = 500;
client->rx_callback = mbox_client_light_receive_message;
channel = mbox_request_channel_byname(client, name);
if (IS_ERR(channel)) {
devm_kfree(&pdev->dev, client);
dev_warn(&pdev->dev, "Failed to request %s channel\n", name);
return NULL;
}
return channel;
}
static int mbox_client_light_probe(struct platform_device *pdev)
{
struct mbox_client_light_device *tdev;
struct device_node *np = pdev->dev.of_node;
int ret;
static int chan_idx = 1;
tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
if (!tdev)
return -ENOMEM;
tdev_priv = tdev;
if (!chan_idx)
tdev->tx_channel = mbox_client_light_request_channel(pdev, "902");
else
tdev->tx_channel = mbox_client_light_request_channel(pdev, "906");
if (!tdev->tx_channel) {
dev_err(&pdev->dev, "Request channel failed\n");
return -EPROBE_DEFER;
}
chan_idx++;
/* In fact, rx_channel is same with tx_channel in C-SKY's mailbox */
tdev->rx_channel = tdev->tx_channel;
tdev->dev = &pdev->dev;
platform_set_drvdata(pdev, tdev);
tdev->audio_mbox_regmap = syscon_regmap_lookup_by_phandle(np, "audio-mbox-regmap");
if (IS_ERR(tdev->audio_mbox_regmap)) {
dev_err(&pdev->dev, "cannot find regmap for audio mbox register\n");
} else {
dev_dbg(&pdev->dev, "audio_mbox_regmap ok\n");
}
spin_lock_init(&tdev->lock);
tdev->rx_buffer = devm_kzalloc(&pdev->dev,
MBOX_MAX_MSG_LEN, GFP_KERNEL);
if (!tdev->rx_buffer)
return -ENOMEM;
ret = mbox_client_light_add_debugfs(pdev, tdev);
if (ret)
return ret;
dev_err(&pdev->dev, "Successfully registered\n");
return 0;
}
static int mbox_client_light_remove(struct platform_device *pdev)
{
struct mbox_client_light_device *tdev = platform_get_drvdata(pdev);
debugfs_remove_recursive(root_debugfs_dir);
if (tdev->tx_channel)
mbox_free_channel(tdev->tx_channel);
if (tdev->rx_channel && tdev->rx_channel != tdev->tx_channel)
mbox_free_channel(tdev->rx_channel);
return 0;
}
static const struct of_device_id mbox_client_light_match[] = {
{ .compatible = "thead,light-mbox-client" },
{},
};
static struct platform_driver mbox_client_light_driver = {
.driver = {
.name = "thead,light-mbox-client",
.of_match_table = mbox_client_light_match,
},
.probe = mbox_client_light_probe,
.remove = mbox_client_light_remove,
};
module_platform_driver(mbox_client_light_driver);
MODULE_AUTHOR("Alibaba Group Holding Limited");
MODULE_DESCRIPTION("Thead Light mailbox IPC client driver");
MODULE_LICENSE("GPL v2");

View File

@@ -521,7 +521,16 @@ static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
put_device(&ctrldev->dev); put_device(&ctrldev->dev);
} }
static struct rpmsg_device_id rpmsg_driver_char_id_table[] = {
{ .name = "rpmsg-virtual-char-channel-1" },
{ },
};
MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_char_id_table);
static struct rpmsg_driver rpmsg_chrdev_driver = { static struct rpmsg_driver rpmsg_chrdev_driver = {
.id_table = rpmsg_driver_char_id_table,
.probe = rpmsg_chrdev_probe, .probe = rpmsg_chrdev_probe,
.remove = rpmsg_chrdev_remove, .remove = rpmsg_chrdev_remove,
.drv = { .drv = {

View File

@@ -158,7 +158,7 @@ struct virtio_rpmsg_channel {
* processor. * processor.
*/ */
#define MAX_RPMSG_NUM_BUFS (512) #define MAX_RPMSG_NUM_BUFS (512)
#define MAX_RPMSG_BUF_SIZE (512) #define MAX_RPMSG_BUF_SIZE (4096)
/* /*
* Local addresses are dynamically allocated on-demand. * Local addresses are dynamically allocated on-demand.

View File

@@ -16,6 +16,12 @@ config LIGHT_SUSPEND
help help
This driver supports system suspend low power feature in Light FM platform This driver supports system suspend low power feature in Light FM platform
config LIGHT_REBOOTMODE
bool "Thead light rebootmode support"
default y
help
This driver supports check rebootmode feature in Light FM platform
endmenu endmenu
endif endif

View File

@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_LIGHT_IOPMP) += light-iopmp.o obj-$(CONFIG_LIGHT_IOPMP) += light-iopmp.o
obj-$(CONFIG_LIGHT_SUSPEND) += pm-light.o obj-$(CONFIG_LIGHT_SUSPEND) += pm-light.o
obj-$(CONFIG_LIGHT_REBOOTMODE) += light_event.o

View File

@@ -0,0 +1,278 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/platform_device.h>
#include <linux/firmware/thead/ipc.h>
#include <linux/firmware/thead/light_event.h>
/*
* AON SRAM total size is 0x10000, reserve 0x100 for event.
* Notice: c902 *.ld also need resize.
* -------------- 0xff_ffef8000
* | |
* | |
* | |
* | c902 |
* | |
* | |
* | |
* -------------- 0xff_fff07f00
* | reserve |
* | |
* --------------
*/
#define LIGHT_AON_SRAM_LEN 0x10000
#define LIGHT_AON_SRAM_RESERV (LIGHT_AON_SRAM_LEN - 0x100)
#define LIGHT_EVENT_OFFSET (LIGHT_AON_SRAM_RESERV + 0x10)
#define LIGHT_EVENT_CHECK (LIGHT_EVENT_OFFSET + 0x4)
#define LIGHT_EVENT_MAGIC 0x5A5A5A5A
struct light_aon_msg_event_ctrl {
struct light_aon_rpc_msg_hdr hdr;
u32 reserve_offset;
u32 reserved[5];
} __packed __aligned(4);
struct light_event {
struct device *dev;
struct light_aon_ipc *ipc_handle;
struct light_aon_msg_event_ctrl msg;
struct regmap *aon_iram;
bool init;
};
struct light_event *light_event;
static void light_event_msg_hdr_fill(struct light_aon_rpc_msg_hdr *hdr, enum light_aon_misc_func func)
{
hdr->ver = LIGHT_AON_RPC_VERSION;
hdr->svc = (uint8_t)LIGHT_AON_RPC_SVC_MISC;
hdr->func = (uint8_t)func;
hdr->size = LIGHT_AON_RPC_MSG_NUM;
}
static int light_event_aon_reservemem(struct light_event *event)
{
struct light_aon_ipc *ipc = event->ipc_handle;
int ret = 0;
dev_dbg(light_event->dev, "aon reservemem...\n");
light_event_msg_hdr_fill(&event->msg.hdr, LIGHT_AON_MISC_FUNC_AON_RESERVE_MEM);
event->msg.reserve_offset = LIGHT_EVENT_OFFSET;
ret = light_aon_call_rpc(ipc, &event->msg, true);
if (ret)
dev_err(light_event->dev, "failed to set aon reservemem\n");
return ret;
}
int light_event_set_rebootmode(enum light_rebootmode_index mode)
{
int ret;
if (!light_event->init)
return -EINVAL;
ret = regmap_write(light_event->aon_iram, LIGHT_EVENT_OFFSET, mode);
if (ret) {
dev_err(light_event->dev, "set rebootmode failed,ret:%d\n", ret);
return ret;
}
dev_info(light_event->dev, "set rebootmode:0x%x\n", mode);
return 0;
}
EXPORT_SYMBOL_GPL(light_event_set_rebootmode);
int light_event_get_rebootmode(enum light_rebootmode_index *mode)
{
int ret;
if (!light_event->init)
return -EINVAL;
ret = regmap_read(light_event->aon_iram, LIGHT_EVENT_OFFSET, mode);
if (ret) {
dev_err(light_event->dev, "get rebootmode failed,ret:%d\n", ret);
return ret;
}
dev_dbg(light_event->dev, "%s get rebootmode:0x%x\n", __func__, *mode);
return 0;
}
EXPORT_SYMBOL_GPL(light_event_get_rebootmode);
static int light_event_check_powerup(void)
{
enum light_rebootmode_index mode;
unsigned int val;
int ret;
if (!light_event->init)
return -EINVAL;
ret = regmap_read(light_event->aon_iram, LIGHT_EVENT_CHECK, &val);
if (ret) {
dev_err(light_event->dev, "get magicnum failed,ret:%d\n", ret);
return ret;
}
ret = regmap_read(light_event->aon_iram, LIGHT_EVENT_OFFSET, &mode);
if (ret) {
dev_err(light_event->dev, "get rebootmode failed,ret:%d\n", ret);
return ret;
}
dev_info(light_event->dev, "magicnum:0x%x mode:0x%x\n", val, mode);
/* powerup means SRAM data is randam */
if (val != LIGHT_EVENT_MAGIC && mode != LIGHT_EVENT_PMIC_ONKEY)
light_event_set_rebootmode(LIGHT_EVENT_PMIC_POWERUP);
ret = regmap_write(light_event->aon_iram, LIGHT_EVENT_CHECK, LIGHT_EVENT_MAGIC);
if (ret) {
dev_err(light_event->dev, "set magicnum failed,ret:%d\n", ret);
return ret;
}
return 0;
}
static ssize_t rebootmode_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
enum light_rebootmode_index mode;
if (kstrtouint(buf, 0, &mode) < 0)
return -EINVAL;
light_event_set_rebootmode(mode);
return count;
}
static ssize_t
rebootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
{
enum light_rebootmode_index mode;
light_event_get_rebootmode(&mode);
return sprintf(buf, "0x%x\n", mode);
}
static DEVICE_ATTR_RW(rebootmode);
static struct attribute *event_attrs[] = {
&dev_attr_rebootmode.attr,
NULL
};
ATTRIBUTE_GROUPS(event);
static int light_event_open(struct inode *inode, struct file *f)
{
return 0;
}
static int light_event_release(struct inode *inode, struct file *f)
{
return 0;
}
static long light_event_ioctl(struct file *f, unsigned int ioctl,
unsigned long arg)
{
return 0;
}
static const struct file_operations light_event_fops = {
.owner = THIS_MODULE,
.release = light_event_release,
.open = light_event_open,
.unlocked_ioctl = light_event_ioctl,
};
static struct miscdevice light_event_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "light-event",
.fops = &light_event_fops,
};
static int light_event_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct light_event *thead;
int ret;
thead = devm_kzalloc(&pdev->dev, sizeof(*thead), GFP_KERNEL);
if (!thead)
return -ENOMEM;
light_event = thead;
ret = light_aon_get_handle(&(thead->ipc_handle));
if (ret == -EPROBE_DEFER)
return ret;
platform_set_drvdata(pdev, thead);
thead->dev = &pdev->dev;
thead->aon_iram = syscon_regmap_lookup_by_phandle(np, "aon-iram-regmap");
if (IS_ERR(thead->aon_iram))
return PTR_ERR(thead->aon_iram);
ret = misc_register(&light_event_misc);
if (ret < 0)
return ret;
ret = light_event_aon_reservemem(thead);
if (ret) {
dev_err(dev, "set aon reservemem failed!\n");
return -EPERM;
}
thead->init = true;
ret = light_event_check_powerup();
if (ret) {
dev_err(dev, "check powerup failed!\n");
return -EPERM;
}
dev_info(dev, "light-event driver init successfully\n");
return 0;
}
static int light_event_remove(struct platform_device *pdev)
{
misc_deregister(&light_event_misc);
return 0;
}
static const struct of_device_id light_event_of_match[] = {
{ .compatible = "thead,light-event" },
{ },
};
MODULE_DEVICE_TABLE(of, light_event_of_match);
static struct platform_driver light_event_driver = {
.probe = light_event_probe,
.remove = light_event_remove,
.driver = {
.name = "light-event",
.dev_groups = event_groups,
.of_match_table = light_event_of_match,
},
};
module_platform_driver(light_event_driver);
MODULE_DESCRIPTION("light-event driver");
MODULE_LICENSE("GPL v2");

View File

@@ -73,6 +73,14 @@
#define USB3_DRD_PRST BIT(0) #define USB3_DRD_PRST BIT(0)
#define USB3_DRD_MASK GENMASK(2, 0) #define USB3_DRD_MASK GENMASK(2, 0)
/* USB as host or device*/
#define USB_AS_HOST (true)
#define USB_AS_DEVICE (false)
static bool usb_role = USB_AS_HOST;
module_param(usb_role, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(usb_role, "USB role");
struct dwc3_thead { struct dwc3_thead {
struct device *dev; struct device *dev;
struct platform_device *dwc3; struct platform_device *dwc3;
@@ -255,9 +263,10 @@ static int dwc3_thead_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, thead); platform_set_drvdata(pdev, thead);
thead->dev = &pdev->dev; thead->dev = &pdev->dev;
thead->hubswitch = devm_gpiod_get(dev, "hubswitch", GPIOD_OUT_HIGH); thead->hubswitch = devm_gpiod_get(dev, "hubswitch", (usb_role == USB_AS_DEVICE) ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH);
if (IS_ERR(thead->hubswitch)) if (IS_ERR(thead->hubswitch))
dev_dbg(dev, "no need to get hubswitch GPIO\n"); dev_dbg(dev, "no need to get hubswitch GPIO\n");
dev_info(dev, "hubswitch usb_role = %d\n", usb_role);
thead->vbus = devm_regulator_get(dev, "vbus"); thead->vbus = devm_regulator_get(dev, "vbus");
if (IS_ERR(thead->vbus)) if (IS_ERR(thead->vbus))

View File

@@ -1226,6 +1226,12 @@ static int virtio_vdmabuf_create_dmabuf(struct virtio_vdmabuf *vdmabuf,
exp_info.flags = O_RDWR; exp_info.flags = O_RDWR;
exp_info.priv = exp_buf; exp_info.priv = exp_buf;
unsigned int gfp = GFP_KERNEL;
if(attr->flags & VIRTIO_VDAMBUF_DMA32)
{
gfp |= __GFP_DMA32;
}
switch (heap_type) { switch (heap_type) {
case VIRTIO_VDMABUF_HEAP_TYPE_USER: case VIRTIO_VDMABUF_HEAP_TYPE_USER:
return -EINVAL; /* Not support currently */ return -EINVAL; /* Not support currently */
@@ -1235,7 +1241,7 @@ static int virtio_vdmabuf_create_dmabuf(struct virtio_vdmabuf *vdmabuf,
exp_buf->bp_num = npages; exp_buf->bp_num = npages;
for (i = 0; i < npages; i++) { for (i = 0; i < npages; i++) {
page = alloc_page(GFP_KERNEL); page = alloc_page(gfp);
if (!page) { if (!page) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_alloc; goto err_alloc;
@@ -1253,7 +1259,7 @@ static int virtio_vdmabuf_create_dmabuf(struct virtio_vdmabuf *vdmabuf,
/* only need 1 bp to record Compound Page */ /* only need 1 bp to record Compound Page */
exp_buf->bp_num = 1; exp_buf->bp_num = 1;
page = alloc_pages(GFP_KERNEL, get_order(exp_buf->size)); page = alloc_pages(gfp, get_order(exp_buf->size));
if (!page) { if (!page) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_exp; goto err_exp;

View File

@@ -29,6 +29,7 @@
#include <linux/reset.h> #include <linux/reset.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/firmware/thead/light_event.h>
#define WDOG_CONTROL_REG_OFFSET 0x00 #define WDOG_CONTROL_REG_OFFSET 0x00
#define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01
@@ -376,6 +377,7 @@ static irqreturn_t dw_wdt_irq(int irq, void *devid)
pr_warn("watchdog irq enter. however status is 0\n"); pr_warn("watchdog irq enter. however status is 0\n");
return IRQ_NONE; return IRQ_NONE;
} }
light_event_set_rebootmode(LIGHT_EVENT_SW_WATCHDOG);
WARN(1, "watchdog app was stuck! watchdog pretimeout event\n"); WARN(1, "watchdog app was stuck! watchdog pretimeout event\n");
watchdog_notify_pretimeout(&dw_wdt->wdd); watchdog_notify_pretimeout(&dw_wdt->wdd);

View File

@@ -17,6 +17,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include <linux/firmware/thead/ipc.h> #include <linux/firmware/thead/ipc.h>
#include <linux/firmware/thead/light_event.h>
#define DRV_NAME "light-wdt" #define DRV_NAME "light-wdt"
@@ -189,6 +190,7 @@ static int light_wdt_restart(struct watchdog_device *wdd, unsigned long action,
pr_debug("[%s,%d]: Inform aon to restart the whole system....\n", __func__, __LINE__); pr_debug("[%s,%d]: Inform aon to restart the whole system....\n", __func__, __LINE__);
light_event_set_rebootmode(LIGHT_EVENT_SW_REBOOT);
ret = light_aon_call_rpc(ipc, &wdt_dev->msg, false); ret = light_aon_call_rpc(ipc, &wdt_dev->msg, false);
if (ret) if (ret)
return ret; return ret;

View File

@@ -53,6 +53,7 @@
#define __WRITE_ONCE(x, val) \ #define __WRITE_ONCE(x, val) \
do { \ do { \
*(volatile typeof(x) *)&(x) = (val); \ *(volatile typeof(x) *)&(x) = (val); \
smp_mb(); \
} while (0) } while (0)
#define WRITE_ONCE(x, val) \ #define WRITE_ONCE(x, val) \

View File

@@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 Alibaba Group Holding Limited.
*/
#ifndef _LIGHT_AUDIOSYS_H_
#define _LIGHT_AUDIOSYS_H_
#define LIGHT_CLKGEN_AUDIO_CPU 0
#define LIGHT_CLKGEN_AUDIO_SRAM0 1
#define LIGHT_CLKGEN_AUDIO_SRAM1 2
#define LIGHT_CLKGEN_AUDIO_DMA 3
#define LIGHT_CLKGEN_AUDIO_BSM 4
#define LIGHT_CLKGEN_AUDIO_TIMER 5
#define LIGHT_CLKGEN_AUDIO_TIMER_CNT1 6
#define LIGHT_CLKGEN_AUDIO_TIMER_CNT2 7
#define LIGHT_CLKGEN_AUDIO_TIMER_CNT3 8
#define LIGHT_CLKGEN_AUDIO_TIMER_CNT4 9
#define LIGHT_CLKGEN_AUDIO_WDR 10
#define LIGHT_CLKGEN_AUDIO_I2C0 11
#define LIGHT_CLKGEN_AUDIO_I2C1 12
#define LIGHT_CLKGEN_AUDIO_UART 13
#define LIGHT_CLKGEN_AUDIO_I2S0 14
#define LIGHT_CLKGEN_AUDIO_I2S1 15
#define LIGHT_CLKGEN_AUDIO_I2S2 16
#define LIGHT_CLKGEN_AUDIO_I2S8CH 17
#define LIGHT_CLKGEN_AUDIO_TDM 18
#define LIGHT_CLKGEN_AUDIO_GPIO 19
#define LIGHT_CLKGEN_AUDIO_SPDIF0 20
#define LIGHT_CLKGEN_AUDIO_SPDIF1 21
#define LIGHT_CLKGEN_AUDIO_VAD 22
#define LIGHT_CLKGEN_AUDIO_IOMUX 23
#define LIGHT_CLKGEN_AUDIO_CLK_END 24
#endif

View File

@@ -0,0 +1,38 @@
#ifndef _LIGHT_FM_AUDIO_IO_PINCTRL_H
#define _LIGHT_FM_AUDIO_IO_PINCTRL_H
#define FM_AUDIO_IO_PA0 0
#define FM_AUDIO_IO_PA1 1
#define FM_AUDIO_IO_PA2 2
#define FM_AUDIO_IO_PA3 3
#define FM_AUDIO_IO_PA4 4
#define FM_AUDIO_IO_PA5 5
#define FM_AUDIO_IO_PA6 6
#define FM_AUDIO_IO_PA7 7
#define FM_AUDIO_IO_PA8 8
#define FM_AUDIO_IO_PA9 9
#define FM_AUDIO_IO_PA10 10
#define FM_AUDIO_IO_PA11 11
#define FM_AUDIO_IO_PA12 12
#define FM_AUDIO_IO_PA13 13
#define FM_AUDIO_IO_PA14 14
#define FM_AUDIO_IO_PA15 15
#define FM_AUDIO_IO_PA16 16
#define FM_AUDIO_IO_PA17 17
#define FM_AUDIO_IO_PA18 18
#define FM_AUDIO_IO_PA19 19
#define FM_AUDIO_IO_PA20 20
#define FM_AUDIO_IO_PA21 21
#define FM_AUDIO_IO_PA22 22
#define FM_AUDIO_IO_PA23 23
#define FM_AUDIO_IO_PA24 24
#define FM_AUDIO_IO_PA25 25
#define FM_AUDIO_IO_PA26 26
#define FM_AUDIO_IO_PA27 27
#define FM_AUDIO_IO_PA28 28
#define FM_AUDIO_IO_PA29 29
#define FM_AUDIO_IO_PA30 30
#define AUDIO_IO_GPIO 0xF /* Flag set to gpio */
#endif /* _LIGHT_FM_AUDIO_IO_PINCTRL_H */

View File

@@ -0,0 +1,36 @@
#ifndef __DT_BINDINGS_LIGHT_FM_PINCTRL_DEF_H__
#define __DT_BINDINGS_LIGHT_FM_PINCTRL_DEF_H__
#define LIGHT_PIN_PULL_NONE 0
#define LIGHT_PIN_PULL_DOWN 1
#define LIGHT_PIN_PULL_UP 2
#define LIGHT_PIN_DRV_LV0 0
#define LIGHT_PIN_DRV_LV1 1
#define LIGHT_PIN_DRV_LV2 2
#define LIGHT_PIN_DRV_LV3 3
#define LIGHT_PIN_DRV_LV4 4
#define LIGHT_PIN_DRV_LV5 5
#define LIGHT_PIN_DRV_LV6 6
#define LIGHT_PIN_DRV_LV7 7
#define LIGHT_PIN_DRV_LV8 8
#define LIGHT_PIN_DRV_LV9 9
#define LIGHT_PIN_DRV_LV10 10
#define LIGHT_PIN_DRV_LV11 11
#define LIGHT_PIN_DRV_LV12 12
#define LIGHT_PIN_DRV_LV13 13
#define LIGHT_PIN_DRV_LV14 14
#define LIGHT_PIN_DRV_LV15 15
#define LIGHT_PIN_FUNC_0 0
#define LIGHT_PIN_FUNC_1 1
#define LIGHT_PIN_FUNC_2 2
#define LIGHT_PIN_FUNC_3 3
#define LIGHT_PIN_FUNC_4 4
#define LIGHT_PIN_FUNC_5 5
#define LIGHT_PIN_FUNC_6 6
#define LIGHT_PIN_FUNC_7 7
#endif // __DT_BINDINGS_LIGHT_FM_PINCTRL_DEF_H__

View File

@@ -10,5 +10,10 @@
#define LIGHT_RESET_WDT0 0 #define LIGHT_RESET_WDT0 0
#define LIGHT_RESET_WDT1 1 #define LIGHT_RESET_WDT1 1
#define LIGHT_RESET_NPU 2
// vpsys reset
#define LIGHT_RESET_FCE 100
#endif #endif

View File

@@ -1472,6 +1472,9 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
int bpf_prog_test_run_raw_tp(struct bpf_prog *prog, int bpf_prog_test_run_raw_tp(struct bpf_prog *prog,
const union bpf_attr *kattr, const union bpf_attr *kattr,
union bpf_attr __user *uattr); union bpf_attr __user *uattr);
int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog,
const union bpf_attr *kattr,
union bpf_attr __user *uattr);
bool btf_ctx_access(int off, int size, enum bpf_access_type type, bool btf_ctx_access(int off, int size, enum bpf_access_type type,
const struct bpf_prog *prog, const struct bpf_prog *prog,
struct bpf_insn_access_aux *info); struct bpf_insn_access_aux *info);
@@ -1686,6 +1689,13 @@ static inline int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
return -ENOTSUPP; return -ENOTSUPP;
} }
static inline int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog,
const union bpf_attr *kattr,
union bpf_attr __user *uattr)
{
return -ENOTSUPP;
}
static inline void bpf_map_put(struct bpf_map *map) static inline void bpf_map_put(struct bpf_map *map)
{ {
} }

View File

@@ -36,6 +36,7 @@ enum light_aon_misc_func {
LIGHT_AON_MISC_FUNC_WDG_POWER_OFF = 9, LIGHT_AON_MISC_FUNC_WDG_POWER_OFF = 9,
LIGHT_AON_MISC_FUNC_AON_WDT_ON = 10, LIGHT_AON_MISC_FUNC_AON_WDT_ON = 10,
LIGHT_AON_MISC_FUNC_AON_WDT_OFF = 11, LIGHT_AON_MISC_FUNC_AON_WDT_OFF = 11,
LIGHT_AON_MISC_FUNC_AON_RESERVE_MEM = 12,
}; };
enum light_aon_pm_func { enum light_aon_pm_func {

View File

@@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LIGHT_EVENT_H
#define _LIGHT_EVENT_H
enum light_rebootmode_index {
/* C902 event rebootmode */
LIGHT_EVENT_PMIC_RESET = 0x0,
LIGHT_EVENT_PMIC_ONKEY,
LIGHT_EVENT_PMIC_POWERUP,
/* C910 event rebootmode */
LIGHT_EVENT_SW_REBOOT = 0x20,
LIGHT_EVENT_SW_WATCHDOG,
LIGHT_EVENT_SW_PANIC,
LIGHT_EVENT_SW_HANG,
LIGHT_EVENT_MAX,
};
#if IS_ENABLED(CONFIG_LIGHT_REBOOTMODE)
extern int light_event_set_rebootmode(enum light_rebootmode_index mode);
extern int light_event_get_rebootmode(enum light_rebootmode_index *mode);
#else
static int light_event_set_rebootmode(enum light_rebootmode_index mode)
{
return 0;
}
static int light_event_get_rebootmode(enum light_rebootmode_index *mode)
{
*mode = LIGHT_EVENT_MAX;
return 0;
}
#endif
#endif

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2023 Alibaba Group Holding Limited.
*/
/*
* The code contained herein is licensed under the GNU Lesser General
* Public License. You may obtain a copy of the GNU Lesser General
* Public License Version 2.1 or later at the following locations:
*
* http://www.opensource.org/licenses/lgpl-license.html
* http://www.gnu.org/copyleft/lgpl.html
*/
/*
* @file linux/light_rpmsg.h
*
* @brief Global header file for imx RPMSG
*
* @ingroup RPMSG
*/
#ifndef __LINUX_LIGHT_RPMSG_H__
#define __LINUX_LIGHT_RPMSG_H__
#include <linux/rpmsg.h>
#include <linux/slab.h>
#include <linux/virtio.h>
#include <linux/virtio_config.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_ring.h>
/* Category define */
#define LIGHT_RMPSG_LIFECYCLE 1
#define LIGHT_RPMSG_PMIC 2
#define LIGHT_RPMSG_AUDIO 3
#define LIGHT_RPMSG_KEY 4
#define LIGHT_RPMSG_GPIO 5
#define LIGHT_RPMSG_RTC 6
#define LIGHT_RPMSG_SENSOR 7
/* rpmsg version */
#define LIGHT_RMPSG_MAJOR 1
#define LIGHT_RMPSG_MINOR 0
enum light_rpmsg_variants {
LIGHTA,
LIGHTB,
LIGHT_RPMSG,
};
struct light_virdev {
struct virtio_device vdev;
unsigned int vring[2];
struct virtqueue *vq[2];
int base_vq_id;
int num_of_vqs;
struct notifier_block nb;
};
struct light_rpmsg_vproc {
char *rproc_name;
struct mutex lock;
struct clk *mu_clk;
enum light_rpmsg_variants variant;
int vdev_nums;
int first_notify;
#define MAX_VDEV_NUMS 8
struct light_virdev ivdev[MAX_VDEV_NUMS];
void __iomem *mu_base;
struct delayed_work rpmsg_work;
struct blocking_notifier_head notifier;
#define MAX_NUM 10 /* enlarge it if overflow happen */
u32 m4_message[MAX_NUM];
u32 in_idx;
u32 out_idx;
u32 core_id;
spinlock_t mu_lock;
};
struct light_rpmsg_head {
u8 cate;
u8 major;
u8 minor;
u8 type;
u8 cmd;
u8 reserved[5];
} __attribute__ ((packed));
#endif /* __LINUX_LIGHT_RPMSG_H__*/

View File

@@ -1088,6 +1088,8 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size);
struct sk_buff *build_skb_around(struct sk_buff *skb, struct sk_buff *build_skb_around(struct sk_buff *skb,
void *data, unsigned int frag_size); void *data, unsigned int frag_size);
void skb_set_alloc_dma32(gfp_t gfp_dma32);
gfp_t skb_get_alloc_dma32(void);
/** /**
* alloc_skb - allocate a network buffer * alloc_skb - allocate a network buffer
* @size: size to allocate * @size: size to allocate

View File

@@ -5007,7 +5007,10 @@ struct bpf_pidns_info {
/* User accessible data for SK_LOOKUP programs. Add new fields at the end. */ /* User accessible data for SK_LOOKUP programs. Add new fields at the end. */
struct bpf_sk_lookup { struct bpf_sk_lookup {
__bpf_md_ptr(struct bpf_sock *, sk); /* Selected socket */ union {
__bpf_md_ptr(struct bpf_sock *, sk); /* Selected socket */
__u64 cookie; /* Non-zero if socket was selected in PROG_TEST_RUN */
};
__u32 family; /* Protocol family (AF_INET, AF_INET6) */ __u32 family; /* Protocol family (AF_INET, AF_INET6) */
__u32 protocol; /* IP protocol (IPPROTO_TCP, IPPROTO_UDP) */ __u32 protocol; /* IP protocol (IPPROTO_TCP, IPPROTO_UDP) */

View File

@@ -17,7 +17,8 @@ _IOC(_IOC_NONE, 'G', 2, sizeof(struct virtio_vdmabuf_alloc))
_IOC(_IOC_NONE, 'G', 3, sizeof(struct virtio_vdmabuf_import)) _IOC(_IOC_NONE, 'G', 3, sizeof(struct virtio_vdmabuf_import))
/* dmabuf flag */ /* dmabuf flag */
#define VIRTIO_VDAMBUF_NONCACHED 0x1 #define VIRTIO_VDAMBUF_NONCACHED 0x1
#define VIRTIO_VDAMBUF_DMA32 0x4
/* /*
* Max single alloc size is (768 * PAGE_SIZE) only for * Max single alloc size is (768 * PAGE_SIZE) only for

View File

@@ -94,7 +94,7 @@ struct qnode {
* progress. * progress.
*/ */
#ifndef _Q_PENDING_LOOPS #ifndef _Q_PENDING_LOOPS
#define _Q_PENDING_LOOPS 1 #define _Q_PENDING_LOOPS 9
#endif #endif
/* /*

View File

@@ -32,6 +32,7 @@
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <linux/firmware/thead/light_event.h>
#define PANIC_TIMER_STEP 100 #define PANIC_TIMER_STEP 100
#define PANIC_BLINK_SPD 18 #define PANIC_BLINK_SPD 18
@@ -182,7 +183,11 @@ void panic(const char *fmt, ...)
int state = 0; int state = 0;
int old_cpu, this_cpu; int old_cpu, this_cpu;
bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers; bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers;
enum light_rebootmode_index mode;
if (!light_event_get_rebootmode(&mode) &&
mode != LIGHT_EVENT_SW_WATCHDOG)
light_event_set_rebootmode(LIGHT_EVENT_SW_PANIC);
/* /*
* Disable local interrupts. This will prevent panic_smp_self_stop * Disable local interrupts. This will prevent panic_smp_self_stop
* from deadlocking the first cpu that invokes the panic, since * from deadlocking the first cpu that invokes the panic, since

View File

@@ -435,7 +435,7 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp)
* be quite short, for example, in the case of the call from * be quite short, for example, in the case of the call from
* rcu_read_unlock_special(). * rcu_read_unlock_special().
*/ */
static void static notrace void
rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags) rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags)
{ {
bool empty_exp; bool empty_exp;
@@ -556,7 +556,7 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags)
* is disabled. This function cannot be expected to understand these * is disabled. This function cannot be expected to understand these
* nuances, so the caller must handle them. * nuances, so the caller must handle them.
*/ */
static bool rcu_preempt_need_deferred_qs(struct task_struct *t) static notrace bool rcu_preempt_need_deferred_qs(struct task_struct *t)
{ {
return (__this_cpu_read(rcu_data.exp_deferred_qs) || return (__this_cpu_read(rcu_data.exp_deferred_qs) ||
READ_ONCE(t->rcu_read_unlock_special.s)) && READ_ONCE(t->rcu_read_unlock_special.s)) &&
@@ -570,7 +570,7 @@ static bool rcu_preempt_need_deferred_qs(struct task_struct *t)
* evaluate safety in terms of interrupt, softirq, and preemption * evaluate safety in terms of interrupt, softirq, and preemption
* disabling. * disabling.
*/ */
static void rcu_preempt_deferred_qs(struct task_struct *t) static notrace void rcu_preempt_deferred_qs(struct task_struct *t)
{ {
unsigned long flags; unsigned long flags;
@@ -897,11 +897,11 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp)
* Because there is no preemptible RCU, there can be no deferred quiescent * Because there is no preemptible RCU, there can be no deferred quiescent
* states. * states.
*/ */
static bool rcu_preempt_need_deferred_qs(struct task_struct *t) static notrace bool rcu_preempt_need_deferred_qs(struct task_struct *t)
{ {
return false; return false;
} }
static void rcu_preempt_deferred_qs(struct task_struct *t) { } static notrace void rcu_preempt_deferred_qs(struct task_struct *t) { }
/* /*
* Because there is no preemptible RCU, there can be no readers blocked, * Because there is no preemptible RCU, there can be no readers blocked,

View File

@@ -328,10 +328,9 @@ restart:
goto restart; goto restart;
} }
#ifdef CONFIG_RT_SOFTINT_OPTIMIZATION
if (pending | deferred) if (pending | deferred)
wakeup_softirqd(); wakeup_softirqd();
#endif
lockdep_softirq_end(in_hardirq); lockdep_softirq_end(in_hardirq);
account_irq_exit_time(current); account_irq_exit_time(current);
__local_bh_enable(SOFTIRQ_OFFSET); __local_bh_enable(SOFTIRQ_OFFSET);

View File

@@ -10,20 +10,86 @@
#include <net/bpf_sk_storage.h> #include <net/bpf_sk_storage.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/net_namespace.h>
#include <linux/error-injection.h> #include <linux/error-injection.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/sock_diag.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/bpf_test_run.h> #include <trace/events/bpf_test_run.h>
struct bpf_test_timer {
enum { NO_PREEMPT, NO_MIGRATE } mode;
u32 i;
u64 time_start, time_spent;
};
static void bpf_test_timer_enter(struct bpf_test_timer *t)
__acquires(rcu)
{
rcu_read_lock();
if (t->mode == NO_PREEMPT)
preempt_disable();
else
migrate_disable();
t->time_start = ktime_get_ns();
}
static void bpf_test_timer_leave(struct bpf_test_timer *t)
__releases(rcu)
{
t->time_start = 0;
if (t->mode == NO_PREEMPT)
preempt_enable();
else
migrate_enable();
rcu_read_unlock();
}
static bool bpf_test_timer_continue(struct bpf_test_timer *t, u32 repeat, int *err, u32 *duration)
__must_hold(rcu)
{
t->i++;
if (t->i >= repeat) {
/* We're done. */
t->time_spent += ktime_get_ns() - t->time_start;
do_div(t->time_spent, t->i);
*duration = t->time_spent > U32_MAX ? U32_MAX : (u32)t->time_spent;
*err = 0;
goto reset;
}
if (signal_pending(current)) {
/* During iteration: we've been cancelled, abort. */
*err = -EINTR;
goto reset;
}
if (need_resched()) {
/* During iteration: we need to reschedule between runs. */
t->time_spent += ktime_get_ns() - t->time_start;
bpf_test_timer_leave(t);
cond_resched();
bpf_test_timer_enter(t);
}
/* Do another round. */
return true;
reset:
t->i = 0;
return false;
}
static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
u32 *retval, u32 *time, bool xdp) u32 *retval, u32 *time, bool xdp)
{ {
struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = { NULL }; struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = { NULL };
struct bpf_test_timer t = { NO_MIGRATE };
enum bpf_cgroup_storage_type stype; enum bpf_cgroup_storage_type stype;
u64 time_start, time_spent = 0; int ret;
int ret = 0;
u32 i;
for_each_cgroup_storage_type(stype) { for_each_cgroup_storage_type(stype) {
storage[stype] = bpf_cgroup_storage_alloc(prog, stype); storage[stype] = bpf_cgroup_storage_alloc(prog, stype);
@@ -38,10 +104,8 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
if (!repeat) if (!repeat)
repeat = 1; repeat = 1;
rcu_read_lock(); bpf_test_timer_enter(&t);
migrate_disable(); do {
time_start = ktime_get_ns();
for (i = 0; i < repeat; i++) {
ret = bpf_cgroup_storage_set(storage); ret = bpf_cgroup_storage_set(storage);
if (ret) if (ret)
break; break;
@@ -53,29 +117,8 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
bpf_cgroup_storage_unset(); bpf_cgroup_storage_unset();
if (signal_pending(current)) { } while (bpf_test_timer_continue(&t, repeat, &ret, time));
ret = -EINTR; bpf_test_timer_leave(&t);
break;
}
if (need_resched()) {
time_spent += ktime_get_ns() - time_start;
migrate_enable();
rcu_read_unlock();
cond_resched();
rcu_read_lock();
migrate_disable();
time_start = ktime_get_ns();
}
}
time_spent += ktime_get_ns() - time_start;
migrate_enable();
rcu_read_unlock();
do_div(time_spent, repeat);
*time = time_spent > U32_MAX ? U32_MAX : (u32)time_spent;
for_each_cgroup_storage_type(stype) for_each_cgroup_storage_type(stype)
bpf_cgroup_storage_free(storage[stype]); bpf_cgroup_storage_free(storage[stype]);
@@ -688,18 +731,17 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
const union bpf_attr *kattr, const union bpf_attr *kattr,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
struct bpf_test_timer t = { NO_PREEMPT };
u32 size = kattr->test.data_size_in; u32 size = kattr->test.data_size_in;
struct bpf_flow_dissector ctx = {}; struct bpf_flow_dissector ctx = {};
u32 repeat = kattr->test.repeat; u32 repeat = kattr->test.repeat;
struct bpf_flow_keys *user_ctx; struct bpf_flow_keys *user_ctx;
struct bpf_flow_keys flow_keys; struct bpf_flow_keys flow_keys;
u64 time_start, time_spent = 0;
const struct ethhdr *eth; const struct ethhdr *eth;
unsigned int flags = 0; unsigned int flags = 0;
u32 retval, duration; u32 retval, duration;
void *data; void *data;
int ret; int ret;
u32 i;
if (prog->type != BPF_PROG_TYPE_FLOW_DISSECTOR) if (prog->type != BPF_PROG_TYPE_FLOW_DISSECTOR)
return -EINVAL; return -EINVAL;
@@ -735,39 +777,15 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
ctx.data = data; ctx.data = data;
ctx.data_end = (__u8 *)data + size; ctx.data_end = (__u8 *)data + size;
rcu_read_lock(); bpf_test_timer_enter(&t);
preempt_disable(); do {
time_start = ktime_get_ns(); retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN,
for (i = 0; i < repeat; i++) { size, flags);
retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN, } while (bpf_test_timer_continue(&t, repeat, &ret, &duration));
size, flags); bpf_test_timer_leave(&t);
if (signal_pending(current)) { if (ret < 0)
preempt_enable(); goto out;
rcu_read_unlock();
ret = -EINTR;
goto out;
}
if (need_resched()) {
time_spent += ktime_get_ns() - time_start;
preempt_enable();
rcu_read_unlock();
cond_resched();
rcu_read_lock();
preempt_disable();
time_start = ktime_get_ns();
}
}
time_spent += ktime_get_ns() - time_start;
preempt_enable();
rcu_read_unlock();
do_div(time_spent, repeat);
duration = time_spent > U32_MAX ? U32_MAX : (u32)time_spent;
ret = bpf_test_finish(kattr, uattr, &flow_keys, sizeof(flow_keys), ret = bpf_test_finish(kattr, uattr, &flow_keys, sizeof(flow_keys),
retval, duration); retval, duration);
@@ -780,3 +798,106 @@ out:
kfree(data); kfree(data);
return ret; return ret;
} }
int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, const union bpf_attr *kattr,
union bpf_attr __user *uattr)
{
struct bpf_test_timer t = { NO_PREEMPT };
struct bpf_prog_array *progs = NULL;
struct bpf_sk_lookup_kern ctx = {};
u32 repeat = kattr->test.repeat;
struct bpf_sk_lookup *user_ctx;
u32 retval, duration;
int ret = -EINVAL;
if (prog->type != BPF_PROG_TYPE_SK_LOOKUP)
return -EINVAL;
if (kattr->test.flags || kattr->test.cpu)
return -EINVAL;
if (kattr->test.data_in || kattr->test.data_size_in || kattr->test.data_out ||
kattr->test.data_size_out)
return -EINVAL;
if (!repeat)
repeat = 1;
user_ctx = bpf_ctx_init(kattr, sizeof(*user_ctx));
if (IS_ERR(user_ctx))
return PTR_ERR(user_ctx);
if (!user_ctx)
return -EINVAL;
if (user_ctx->sk)
goto out;
if (!range_is_zero(user_ctx, offsetofend(typeof(*user_ctx), local_port), sizeof(*user_ctx)))
goto out;
if (user_ctx->local_port > U16_MAX || user_ctx->remote_port > U16_MAX) {
ret = -ERANGE;
goto out;
}
ctx.family = (u16)user_ctx->family;
ctx.protocol = (u16)user_ctx->protocol;
ctx.dport = (u16)user_ctx->local_port;
ctx.sport = (__force __be16)user_ctx->remote_port;
switch (ctx.family) {
case AF_INET:
ctx.v4.daddr = (__force __be32)user_ctx->local_ip4;
ctx.v4.saddr = (__force __be32)user_ctx->remote_ip4;
break;
#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
ctx.v6.daddr = (struct in6_addr *)user_ctx->local_ip6;
ctx.v6.saddr = (struct in6_addr *)user_ctx->remote_ip6;
break;
#endif
default:
ret = -EAFNOSUPPORT;
goto out;
}
progs = bpf_prog_array_alloc(1, GFP_KERNEL);
if (!progs) {
ret = -ENOMEM;
goto out;
}
progs->items[0].prog = prog;
bpf_test_timer_enter(&t);
do {
ctx.selected_sk = NULL;
retval = BPF_PROG_SK_LOOKUP_RUN_ARRAY(progs, ctx, BPF_PROG_RUN);
} while (bpf_test_timer_continue(&t, repeat, &ret, &duration));
bpf_test_timer_leave(&t);
if (ret < 0)
goto out;
user_ctx->cookie = 0;
if (ctx.selected_sk) {
if (ctx.selected_sk->sk_reuseport && !ctx.no_reuseport) {
ret = -EOPNOTSUPP;
goto out;
}
user_ctx->cookie = sock_gen_cookie(ctx.selected_sk);
}
ret = bpf_test_finish(kattr, uattr, NULL, 0, retval, duration);
if (!ret)
ret = bpf_ctx_finish(kattr, uattr, user_ctx, sizeof(*user_ctx));
out:
bpf_prog_array_free(progs);
kfree(user_ctx);
return ret;
}

View File

@@ -10295,6 +10295,7 @@ static u32 sk_lookup_convert_ctx_access(enum bpf_access_type type,
} }
const struct bpf_prog_ops sk_lookup_prog_ops = { const struct bpf_prog_ops sk_lookup_prog_ops = {
.test_run = bpf_prog_test_run_sk_lookup,
}; };
const struct bpf_verifier_ops sk_lookup_verifier_ops = { const struct bpf_verifier_ops sk_lookup_verifier_ops = {

View File

@@ -87,6 +87,21 @@ static struct kmem_cache *skbuff_ext_cache __ro_after_init;
#endif #endif
int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS; int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS;
EXPORT_SYMBOL(sysctl_max_skb_frags); EXPORT_SYMBOL(sysctl_max_skb_frags);
gfp_t skb_gfp_dma32 = 0;
void skb_set_alloc_dma32(gfp_t gfp_dma32)
{
if(gfp_dma32 | GFP_DMA32)
skb_gfp_dma32 = __GFP_DMA32;
else
skb_gfp_dma32 = 0;
}
EXPORT_SYMBOL(skb_set_alloc_dma32);
gfp_t skb_get_alloc_dma32(void)
{
return skb_gfp_dma32;
}
EXPORT_SYMBOL(skb_get_alloc_dma32);
/** /**
* skb_panic - private function for out-of-line support * skb_panic - private function for out-of-line support
@@ -379,7 +394,7 @@ static void *__napi_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
{ {
struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
return page_frag_alloc(&nc->page, fragsz, gfp_mask); return page_frag_alloc(&nc->page, fragsz, gfp_mask | skb_gfp_dma32);
} }
void *napi_alloc_frag(unsigned int fragsz) void *napi_alloc_frag(unsigned int fragsz)
@@ -405,10 +420,10 @@ void *netdev_alloc_frag(unsigned int fragsz)
fragsz = SKB_DATA_ALIGN(fragsz); fragsz = SKB_DATA_ALIGN(fragsz);
if (in_irq() || irqs_disabled()) { if (in_irq() || irqs_disabled()) {
nc = this_cpu_ptr(&netdev_alloc_cache); nc = this_cpu_ptr(&netdev_alloc_cache);
data = page_frag_alloc(nc, fragsz, GFP_ATOMIC); data = page_frag_alloc(nc, fragsz, GFP_ATOMIC | skb_gfp_dma32);
} else { } else {
local_bh_disable(); local_bh_disable();
data = __napi_alloc_frag(fragsz, GFP_ATOMIC); data = __napi_alloc_frag(fragsz, GFP_ATOMIC | skb_gfp_dma32);
local_bh_enable(); local_bh_enable();
} }
return data; return data;
@@ -458,12 +473,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
if (in_irq() || irqs_disabled()) { if (in_irq() || irqs_disabled()) {
nc = this_cpu_ptr(&netdev_alloc_cache); nc = this_cpu_ptr(&netdev_alloc_cache);
data = page_frag_alloc(nc, len, gfp_mask); data = page_frag_alloc(nc, len, gfp_mask | skb_gfp_dma32);
pfmemalloc = nc->pfmemalloc; pfmemalloc = nc->pfmemalloc;
} else { } else {
local_bh_disable(); local_bh_disable();
nc = this_cpu_ptr(&napi_alloc_cache.page); nc = this_cpu_ptr(&napi_alloc_cache.page);
data = page_frag_alloc(nc, len, gfp_mask); data = page_frag_alloc(nc, len, gfp_mask | skb_gfp_dma32);
pfmemalloc = nc->pfmemalloc; pfmemalloc = nc->pfmemalloc;
local_bh_enable(); local_bh_enable();
} }
@@ -531,7 +546,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len,
if (sk_memalloc_socks()) if (sk_memalloc_socks())
gfp_mask |= __GFP_MEMALLOC; gfp_mask |= __GFP_MEMALLOC;
data = page_frag_alloc(&nc->page, len, gfp_mask); data = page_frag_alloc(&nc->page, len, gfp_mask | skb_gfp_dma32);
if (unlikely(!data)) if (unlikely(!data))
return NULL; return NULL;

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More