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_GIGANTIC_PAGE
select ARCH_HAS_KCOV
select ARCH_HAS_MMIOWB
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_SET_DIRECT_MAP
select ARCH_HAS_SET_MEMORY
@@ -35,6 +34,7 @@ config RISCV
select ARCH_KEEP_MEMBLOCK
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
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-iso7816.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-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.dtb light-a-val-audio-i2s-8ch.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-gpio-keys.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-miniapp-hdmi.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-miniapp-hdmi.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-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 = <
FM_QSPI0_SCLK 0x2 0x208
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>;
status = "disabled";
es8156_audio_codec: es8156@8 {
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
reg = <0x08>;
};
status = "disabled";
};
es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
reg = <0x40>;
status = "disabled";
};
};
@@ -488,7 +490,7 @@
>;
};
pinctrl_audio_i2s0: i2s0grp {
pinctrl_light_i2s0: i2s0grp {
thead,pins = <
FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238

View File

@@ -373,7 +373,7 @@
entry-cnt = <4>;
control-reg = <0xff 0xff015004>;
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 {
@@ -1335,8 +1335,7 @@
emmc: sdhci@ffe7080000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7080000 0x0 0x10000
0xff 0xef014060 0x0 0x4>;
reg = <0xff 0xe7080000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <62>;
interrupt-names = "sdhciirq";
@@ -1346,8 +1345,7 @@
sdhci0: sd@ffe7090000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7090000 0x0 0x10000
0xff 0xef014064 0x0 0x4>;
reg = <0xff 0xe7090000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <64>;
interrupt-names = "sdhci0irq";
@@ -1357,8 +1355,7 @@
sdhci1: sd@ffe70a0000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe70a0000 0x0 0x10000
0xff 0xef014064 0x0 0x4>;
reg = <0xff 0xe70a0000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <71>;
interrupt-names = "sdhci1irq";
@@ -1433,7 +1430,7 @@
compatible = "light,light-i2s";
reg = <0xff 0xe7034000 0x0 0x4000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_i2s0>;
pinctrl-0 = <&pinctrl_light_i2s0>;
light,mode = "i2s-master";
light,sel = "ap_i2s";
interrupt-parent = <&intc>;

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
/dts-v1/;
#include "light-a-val.dts"
#include "light-a-val-audio.dts"
/ {
display-subsystem {
@@ -40,28 +40,6 @@
&lightsound {
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 */
reg = <2>;
@@ -70,7 +48,7 @@
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec 2>;
sound-dai = <&dummy_codec>;
};
};
};
@@ -78,12 +56,3 @@
&light_i2s {
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 {
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*/
reg = <0>;
format = "i2s";
@@ -28,22 +32,24 @@
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s3 0>;
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
sound-dai = <&es7210_audio_codec>;
sound-dai = <&es7210_audio_codec_adc0>;
};
};
};
&light_i2s {
status = "okay";
};
&i2s0 {
status = "okay";
};
&i2s3 {
&i2s_8ch_sd2 {
status = "okay";
};
&es7210_audio_codec_adc0 {
status = "okay";
};

View File

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

View File

@@ -11,7 +11,7 @@
memory@0 {
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 {
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";
@@ -111,23 +115,27 @@
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s3 0>;
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
sound-dai = <&es7210_audio_codec>;
sound-dai = <&es7210_audio_codec_adc0>;
};
};
};
&light_i2s {
status = "okay";
status = "okay";
};
&i2s0 {
status = "okay";
};
&i2s3 {
&i2s_8ch_sd2 {
status = "okay";
};
&es7210_audio_codec_adc0 {
status = "okay";
};

View File

@@ -48,7 +48,7 @@
sound-dai = <&light_i2s 1>;
};
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 {
status = "okay";
@@ -92,15 +112,14 @@
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s3 0>;
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
sound-dai = <&es7210_audio_codec>;
sound-dai = <&es7210_audio_codec_adc0>;
};
};
};
&light_i2s {
status = "okay";
};
@@ -109,7 +128,11 @@
status = "okay";
};
&i2s3 {
&i2s_8ch_sd2 {
status = "okay";
};
&es7210_audio_codec_adc0 {
status = "okay";
};

View File

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

View File

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

View File

@@ -179,7 +179,8 @@
compatible = "thead,light-mbox-client";
mbox-names = "906";
mboxes = <&mbox_910t 2 0>;
status = "disabled";
audio-mbox-regmap = <&audio_mbox>;
status = "okay";
};
lightsound: lightsound@1 {
@@ -192,9 +193,24 @@
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 {
#sound-dai-cells = <1>;
compatible = "linux,bt-sco";
#sound-dai-cells = <0>;
compatible = "thead,light-dummy-pcm";
sound-name-prefix = "DUMMY";
status = "okay";
};
@@ -262,6 +278,24 @@
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 {
compatible = "wlan-platdata";
clock-names = "clk_wifi";
@@ -512,7 +546,14 @@
reg = <0x0 0x22000000 0x0 0x10000000>;
no-map;
};
audio_mem: memory@32000000 {
reg = <0x0 0x32000000 0x0 0x6400000>;
no-map;
};
rpmsgmem: memory@1E000000 {
reg = <0x0 0x1E000000 0x0 0x10000>;
no-map;
};
};
&adc {
@@ -556,17 +597,74 @@
&audio_i2c0 {
clock-frequency = <100000>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa6>,
<&pinctrl_audiopa7>,
<&pinctrl_audio_i2c0>;
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
reg = <0x08>;
};
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
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>;
compatible = "MicArray_0";
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;
non-removable;
io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>;
wprtn_ignore;
cap-sd-highspeed;
@@ -759,7 +858,7 @@
>;
};
pinctrl_audio_i2s0: i2s0grp {
pinctrl_light_i2s0: i2s0grp {
thead,pins = <
FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238
@@ -834,22 +933,151 @@
* Format: <pin_id mux_node config>
*/
pinctrl_audiopa1: audiopa1_grp {
thead,pins = <
FM_AUDIO_PA1 0x3 0x72
>;
pinctrl_audiopa0: audiopa0 {
thead,pins = < FM_AUDIO_PA0 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa2: audiopa2_grp {
thead,pins = <
FM_AUDIO_PA2 0x0 0x72
>;
pinctrl_audiopa1: audiopa1 {
thead,pins = < FM_AUDIO_PA1 LIGHT_PIN_FUNC_0 0x000 >;
};
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 {
thead,pins = <
FM_CPU_JTG_TDI 0x3 0x208
FM_CPU_JTG_TDO 0x3 0x208
FM_CPU_JTG_TDI 0x3 0x238
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";
};
&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 {
sensor_name = "GC5035";
sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN";
@@ -1073,6 +1319,22 @@
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{
vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2]
channel0 {
@@ -1279,13 +1541,20 @@
mode_idx = <0>;
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 {
subdev_name = "isp";
idx = <1>;
path_type = "ISP_MI_PATH_MP";
output {
max_width = <1920>;
max_height = <1088>;
max_width = <3840>;
max_height = <2180>;
bit_per_pixel = <16>;
frame_count = <3>;
};
@@ -2138,6 +2407,44 @@
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 {
c910_0: cpu@0 {
operating-points = <

View File

@@ -15,7 +15,7 @@
memory@0 {
device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>;
reg = <0x0 0x200000 0x0 0x7fe00000>;
};
chosen {
@@ -194,9 +194,10 @@
};
dummy_codec: dummy_codec {
#sound-dai-cells = <1>;
compatible = "linux,bt-sco";
#sound-dai-cells = <0>;
compatible = "thead,light-dummy-pcm";
status = "okay";
sound-name-prefix = "DUMMY";
};
reg_vref_1v8: regulator-adc-verf {
@@ -581,24 +582,31 @@
clock-frequency = <100000>;
status = "okay";
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
reg = <0x08>;
};
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
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 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
reg = <0x40>;
sound-name-prefix = "ES7210";
status = "disabled";
};
audio_aw87519_pa@58 {
compatible = "awinic,aw87519_pa";
reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>;
status = "okay";
};
audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa";
reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay";
};
};
&i2c1 {
@@ -731,6 +739,7 @@
no-mmc;
non-removable;
io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>;
wprtn_ignore;
cap-sd-highspeed;
@@ -773,7 +782,7 @@
>;
};
pinctrl_audio_i2s0: i2s0grp {
pinctrl_light_i2s0: i2s0grp {
thead,pins = <
FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238
@@ -2091,6 +2100,11 @@
&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";
@@ -2105,7 +2119,7 @@
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s3 0>;
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
sound-dai = <&es7210_audio_codec>;
@@ -2118,7 +2132,7 @@
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec 2>;
sound-dai = <&dummy_codec>;
};
};
};
@@ -2135,7 +2149,7 @@
status = "okay";
};
&i2s3 {
&i2s_8ch_sd2 {
status = "okay";
};

View File

@@ -15,7 +15,7 @@
memory@0 {
device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>;
reg = <0x0 0x200000 0x0 0x7fe00000>;
};
chosen {
@@ -194,9 +194,10 @@
};
dummy_codec: dummy_codec {
#sound-dai-cells = <1>;
compatible = "linux,bt-sco";
#sound-dai-cells = <0>;
compatible = "thead,light-dummy-pcm";
status = "okay";
sound-name-prefix = "DUMMY";
};
reg_vref_1v8: regulator-adc-verf {
@@ -238,7 +239,8 @@
gpio-keys {
compatible = "gpio-keys";
pinctrl-0 = <&pinctrl_volume>;
pinctrl-0 = <&pinctrl_volume_up
&pinctrl_volume_down>;
pinctrl-names = "default";
key-volumedown {
label = "Volume Down Key";
@@ -588,24 +590,31 @@
clock-frequency = <100000>;
status = "okay";
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
reg = <0x08>;
};
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
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 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
reg = <0x40>;
sound-name-prefix = "ES7210";
status = "disabled";
};
audio_aw87519_pa@58 {
compatible = "awinic,aw87519_pa";
reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>;
status = "okay";
};
audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa";
reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay";
};
};
&i2c1 {
@@ -738,6 +747,7 @@
no-mmc;
non-removable;
io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>;
wprtn_ignore;
cap-sd-highspeed;
@@ -780,7 +790,7 @@
>;
};
pinctrl_audio_i2s0: i2s0grp {
pinctrl_light_i2s0: i2s0grp {
thead,pins = <
FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238
@@ -797,6 +807,12 @@
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 = <
FM_CLK_OUT_2 0x3 0x208
FM_CLK_OUT_2 0x3 0x238
>;
};
};
@@ -2265,6 +2281,11 @@
&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";
@@ -2279,7 +2300,7 @@
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s3 0>;
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
sound-dai = <&es7210_audio_codec>;
@@ -2292,7 +2313,7 @@
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec 2>;
sound-dai = <&dummy_codec>;
};
};
};
@@ -2309,7 +2330,7 @@
status = "okay";
};
&i2s3 {
&i2s_8ch_sd2 {
status = "okay";
};

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -15,7 +15,7 @@
memory@0 {
device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>;
reg = <0x0 0x200000 0x0 0x7fe00000>;
};
chosen {
@@ -180,7 +180,8 @@
compatible = "thead,light-mbox-client";
mbox-names = "906";
mboxes = <&mbox_910t 2 0>;
status = "disabled";
audio-mbox-regmap = <&audio_mbox>;
status = "okay";
};
lightsound: lightsound@1 {
@@ -193,10 +194,25 @@
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 {
#sound-dai-cells = <1>;
compatible = "linux,bt-sco";
#sound-dai-cells = <0>;
compatible = "thead,light-dummy-pcm";
status = "okay";
sound-name-prefix = "DUMMY";
};
reg_vref_1v8: regulator-adc-verf {
@@ -270,6 +286,8 @@
regulator-name = "soc_aud_3v3_en";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_3v3_en>;
gpio = <&ao_gpio_porta 7 1>;
enable-active-high;
regulator-always-on;
@@ -280,6 +298,8 @@
regulator-name = "soc_aud_1v8_en";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_1v8_en>;
gpio = <&ao_gpio_porta 8 1>;
enable-active-high;
regulator-always-on;
@@ -569,7 +589,14 @@
reg = <0x0 0x17000000 0 0x02000000>;
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 {
clock-frequency = <100000>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa6>,
<&pinctrl_audiopa7>,
<&pinctrl_audio_i2c0>;
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
reg = <0x08>;
};
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
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 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
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";
reg = <0x58>;
pingctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_pa_rst0>;
reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay";
};
};
@@ -750,6 +797,7 @@
no-mmc;
non-removable;
io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>;
wprtn_ignore;
cap-sd-highspeed;
@@ -792,7 +840,7 @@
>;
};
pinctrl_audio_i2s0: i2s0grp {
pinctrl_light_i2s0: i2s0grp {
thead,pins = <
FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238
@@ -866,27 +914,103 @@
* Format: <pin_id mux_node config>
*/
pinctrl_audiopa1: audiopa1_grp {
thead,pins = <
FM_AUDIO_PA1 0x3 0x72
>;
pinctrl_audiopa0: audiopa0 {
thead,pins = < FM_AUDIO_PA0 LIGHT_PIN_FUNC_0 0x000 >;
};
pinctrl_audiopa2: audiopa2_grp {
thead,pins = <
FM_AUDIO_PA2 0x0 0x72
>;
pinctrl_audiopa1: audiopa1 {
thead,pins = < FM_AUDIO_PA1 LIGHT_PIN_FUNC_0 0x000 >;
};
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 {
thead,pins = <
FM_AOGPIO_11 0x0 0x208
FM_AOGPIO_10 0x3 0x208
FM_AOGPIO_11 0x0 0x238
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 {
clock-frequency = <400000>;
status = "okay";
@@ -1000,30 +1124,21 @@
status = "okay";
};
/*
&vvcam_sensor0 {
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>;
&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 <0x1a>;
i2c_bus = /bits/ 8 <3>;
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";
i2c_addr = /bits/ 8 <0x36>;
i2c_bus = /bits/ 8 <3>;
status = "okay";
};
&vvcam_sensor2 {
@@ -1108,6 +1223,22 @@
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{
vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2]
channel0 {
@@ -1314,13 +1445,20 @@
mode_idx = <0>;
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 {
subdev_name = "isp";
idx = <1>;
path_type = "ISP_MI_PATH_MP";
output {
max_width = <1920>;
max_height = <1088>;
max_width = <3840>;
max_height = <2180>;
bit_per_pixel = <16>;
frame_count = <3>;
};
@@ -2313,6 +2451,11 @@
&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";
@@ -2327,7 +2470,7 @@
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s3 0>;
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
sound-dai = <&es7210_audio_codec>;
@@ -2340,7 +2483,7 @@
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec 2>;
sound-dai = <&dummy_codec>;
};
};
};
@@ -2355,10 +2498,29 @@
&i2s1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa13>,
<&pinctrl_audiopa14>,
<&pinctrl_audiopa15>,
<&pinctrl_audiopa17>,
<&pinctrl_audio_i2s1>;
};
&i2s3 {
&i2s_8ch_sd2 {
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 {

View File

@@ -15,7 +15,7 @@
memory@0 {
device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>;
reg = <0x0 0x200000 0x0 0x7fe00000>;
};
chosen {
@@ -194,9 +194,10 @@
};
dummy_codec: dummy_codec {
#sound-dai-cells = <1>;
compatible = "linux,bt-sco";
#sound-dai-cells = <0>;
compatible = "thead,light-dummy-pcm";
status = "okay";
sound-name-prefix = "DUMMY";
};
reg_vref_1v8: regulator-adc-verf {
@@ -569,24 +570,34 @@
clock-frequency = <100000>;
status = "okay";
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
reg = <0x08>;
};
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
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 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
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 {
compatible = "awinic,aw87519_pa";
reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>;
status = "okay";
};
audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa";
reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay";
};
};
&i2c1 {
@@ -719,6 +730,7 @@
no-mmc;
non-removable;
io_fixed_1v8;
rxclk-sample-delay = <80>;
post-power-on-delay-ms = <50>;
wprtn_ignore;
cap-sd-highspeed;
@@ -761,7 +773,7 @@
>;
};
pinctrl_audio_i2s0: i2s0grp {
pinctrl_light_i2s0: i2s0grp {
thead,pins = <
FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238
@@ -2249,6 +2261,11 @@
&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";
@@ -2263,7 +2280,7 @@
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s3 0>;
sound-dai = <&i2s_8ch_sd2 2>;
};
codec {
sound-dai = <&es7210_audio_codec>;
@@ -2276,7 +2293,7 @@
sound-dai = <&light_i2s 1>;
};
codec {
sound-dai = <&dummy_codec 2>;
sound-dai = <&dummy_codec>;
};
};
};
@@ -2293,7 +2310,7 @@
status = "okay";
};
&i2s3 {
&i2s_8ch_sd2 {
status = "okay";
};

View File

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

View File

@@ -309,7 +309,7 @@
entry-cnt = <4>;
control-reg = <0xff 0xff015004>;
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 {

View File

@@ -318,7 +318,7 @@
entry-cnt = <4>;
control-reg = <0xff 0xff015004>;
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 {
@@ -1193,8 +1193,7 @@
emmc: sdhci@ffe7080000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7080000 0x0 0x10000
0xff 0xef014060 0x0 0x4>;
reg = <0xff 0xe7080000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <62>;
interrupt-names = "sdhciirq";
@@ -1204,8 +1203,7 @@
sdhci0: sd@ffe7090000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7090000 0x0 0x10000
0xff 0xef014064 0x0 0x4>;
reg = <0xff 0xe7090000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <64>;
interrupt-names = "sdhci0irq";
@@ -1215,8 +1213,7 @@
sdhci1: sd@ffe70a0000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe70a0000 0x0 0x10000
0xff 0xef014064 0x0 0x4>;
reg = <0xff 0xe70a0000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <71>;
interrupt-names = "sdhci1irq";
@@ -1302,7 +1299,7 @@
compatible = "light,light-i2s";
reg = <0xff 0xe7034000 0x0 0x4000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_i2s0>;
pinctrl-0 = <&pinctrl_light_i2s0>;
light,mode = "i2s-master";
interrupt-parent = <&intc>;
interrupts = <70>;

View File

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

View File

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

View File

@@ -172,7 +172,8 @@
compatible = "thead,light-mbox-client";
mbox-names = "906";
mboxes = <&mbox_910t 2 0>;
status = "disabled";
audio-mbox-regmap = <&audio_mbox>;
status = "okay";
};
lightsound: lightsound@1 {
@@ -185,10 +186,32 @@
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 {
#sound-dai-cells = <1>;
compatible = "linux,bt-sco";
#sound-dai-cells = <0>;
compatible = "thead,light-dummy-pcm";
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 {
@@ -196,7 +219,7 @@
regulator-name = "vref-1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
status = "okay";
status = "okay";
};
reg_tp_pwr_en: regulator-pwr-en {
@@ -281,7 +304,6 @@
regulator-name = "soc_aud_3v3_en";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&pcal6408ahk_a 1 1>;
enable-active-high;
regulator-always-on;
};
@@ -291,7 +313,6 @@
regulator-name = "soc_aud_1v8_en";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&pcal6408ahk_a 0 1>;
enable-active-high;
regulator-always-on;
};
@@ -361,6 +382,7 @@
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
gpio = <&pcal6408ahk_b 1 1>;
regulator-always-on;
enable-active-high;
};
@@ -370,6 +392,7 @@
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
gpio = <&pcal6408ahk_b 2 1>;
regulator-always-on;
enable-active-high;
};
@@ -379,6 +402,7 @@
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
gpio = <&pcal6408ahk_b 0 1>;
regulator-always-on;
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 {
@@ -594,6 +660,14 @@
reg = <0x0 0x17000000 0 0x02000000>;
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 {
clock-frequency = <100000>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa29>,
<&pinctrl_audiopa30>,
<&pinctrl_audio_i2c0>;
es8156_audio_codec: es8156@8 {
#sound-dai-cells = <0>;
compatible = "everest,es8156";
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 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
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";
reg = <0x58>;
reset-gpio = <&pcal6408ahk_a 2 0x1>;
status = "okay";
sound-name-prefix = "AW87519";
status = "disabled";
};
audio_aw87519_pa1@5b {
compatible = "awinic,aw87519_pa";
reg = <0x5b>;
reset-gpio = <&pcal6408ahk_a 3 0x1>;
status = "disabled";
};
pcal6408ahk_a: gpio@20 {
compatible = "nxp,pcal9554b";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
};
};
&audio_i2c1 {
clock-frequency = <100000>;
status = "okay";
pinctrl-0 = <&pinctrl_audiopa6>,
<&pinctrl_audiopa7>,
<&pinctrl_audio_i2c1>;
es8156_audio_codec_1: es8156@8 {
#sound-dai-cells = <0>;
@@ -662,14 +745,12 @@
audio_aw87519_pa2@58 {
compatible = "awinic,aw87519_pa";
reg = <0x58>;
reset-gpio = <&pcal6408ahk_a 4 0x1>;
status = "disabled";
};
audio_aw87519_pa3@5b {
compatible = "awinic,aw87519_pa";
reg = <0x5b>;
reset-gpio = <&pcal6408ahk_a 5 0x1>;
status = "disabled";
};
};
@@ -706,7 +787,7 @@
num-cs = <1>;
cs-gpios = <&gpio2_porta 3 0>;
rx-sample-dly = <4>;
status = "okay";
status = "disabled";
spi-flash@0 {
#address-cells = <1>;
@@ -841,7 +922,7 @@
>;
};
pinctrl_audio_i2s0: i2s0grp {
pinctrl_light_i2s0: i2s0grp {
thead,pins = <
FM_QSPI0_SCLK 0x2 0x208
FM_QSPI0_CSN0 0x2 0x238
@@ -929,17 +1010,94 @@
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 {
clock-frequency = <400000>;
status = "okay";
pcal6408ahk_b: gpio@20 {
compatible = "nxp,pcal9554b";
reg = <0x20>;
compatible = "nxp,pca9557";
reg = <0x18>;
gpio-controller;
#gpio-cells = <2>;
};
@@ -950,8 +1108,8 @@
status = "okay";
pcal6408ahk_c: gpio@20 {
compatible = "nxp,pcal9554b";
reg = <0x20>;
compatible = "nxp,pca9557";
reg = <0x18>;
gpio-controller;
#gpio-cells = <2>;
};
@@ -967,8 +1125,8 @@
status = "okay";
pcal6408ahk_d: gpio@20 {
compatible = "nxp,pcal9554b";
reg = <0x20>;
compatible = "nxp,pca9557";
reg = <0x18>;
gpio-controller;
#gpio-cells = <2>;
};
@@ -1093,6 +1251,24 @@
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 {
vi_mem_pool_region = <0>; // vi_mem: framebuffer, region[0]
status = "okay";
@@ -1101,11 +1277,18 @@
status = "okay";
sensor0 {
subdev_name = "vivcam";
idx = <0>;
idx = <0>;
csi_idx = <0>;
mode_idx = <0>;
path_type = "SENSOR_VGA_RAW12_LINER";
};
sensor1 {
subdev_name = "vivcam";
idx = <3>;
csi_idx = <0>;
mode_idx = <1>;
path_type = "SENSOR_2592x1944_LINER";
};
dma {
subdev_name = "vipre";
idx = <0>;
@@ -1116,8 +1299,8 @@
idx = <1>;
path_type = "ISP_MI_PATH_MP";
output {
max_width = <1920>;
max_height = <1088>;
max_width = <2600>;
max_height = <2000>;
bit_per_pixel = <12>;
frame_count = <3>;
};
@@ -1138,6 +1321,13 @@
path_type = "SENSOR_VGA_RAW12_LINER";
};
sensor1 {
subdev_name = "vivcam";
idx = <3>;
csi_idx = <0>;
mode_idx = <1>;
path_type = "SENSOR_2592x1944_LINER";
};
dma {
subdev_name = "vipre";
idx = <0>;
@@ -1275,15 +1465,22 @@
status = "okay";
sensor0 {
subdev_name = "vivcam";
idx = <2>;
csi_idx = <1>; //csi_b
idx = <0>;
csi_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 {
subdev_name = "vipre";
idx = <0>;
path_type = "VIPRE_CSI1_DDR";
path_type = "VIPRE_CSI0_DDR";
};
};
};
@@ -1425,12 +1622,22 @@
reg = <1>;
format = "i2s";
cpu {
sound-dai = <&i2s1 1>;
sound-dai = <&i2s1 0>;
};
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 {
@@ -1444,14 +1651,29 @@
&i2s1 {
status = "okay";
dmas = <&dmac2 11>, <&dmac2 10>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa14>,
<&pinctrl_audiopa15>,
<&pinctrl_audiopa16>,
<&pinctrl_audiopa17>,
<&pinctrl_audio_i2s1>;
};
&i2s2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audiopa18>,
<&pinctrl_audiopa19>,
<&pinctrl_audiopa21>,
<&pinctrl_audiopa22>,
<&pinctrl_audio_i2s2>;
};
&i2s3 {
status = "okay";
&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>;
};
&cpus {
@@ -1461,12 +1683,14 @@
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_1: cpu@1 {
@@ -1475,12 +1699,14 @@
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_2: cpu@2 {
@@ -1490,12 +1716,14 @@
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 800000
1500000 800000
1848000 1000000
>;
};
c910_3: cpu@3 {
@@ -1505,12 +1733,14 @@
300000 650000
800000 700000
1500000 800000
1848000 1000000
>;
light,dvddm-operating-points = <
/* kHz uV */
300000 800000
800000 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"
/ {
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";
memory@0 {
device_type = "memory";
reg = <0x0 0x00000000 0x1 0x00000000>;
reg = <0x0 0x200000 0x1 0xffe00000>;
};
};
&cmamem {
alloc-ranges = <0 0xe4000000 0 0x14000000>; // [0xE400_0000 ~ 0xF800_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>;
alloc-ranges = <0 0xe4000000 0 0x14000000>; // [0x0E400_0000 ~ 0x0F800_0000]
};

View File

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

View File

@@ -6,11 +6,14 @@
#include <dt-bindings/pinctrl/light-fm-left-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-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-vpsys.h>
#include <dt-bindings/clock/light-vosys.h>
#include <dt-bindings/clock/light-visys.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/soc/thead,light-iopmp.h>
#include <dt-bindings/thermal/thermal.h>
@@ -34,7 +37,7 @@
i2c3 = &i2c3;
i2c4 = &i2c4;
audio_i2c0 = &audio_i2c0;
audio_i2c1 = &audio_i2c1;
audio_i2c1 = &audio_i2c1;
mmc0 = &emmc;
mmc1 = &sdhci0;
serial0 = &uart0;
@@ -55,6 +58,7 @@
vivcam4 = &vvcam_sensor4;
vivcam5 = &vvcam_sensor5;
vivcam6 = &vvcam_sensor6;
vivcam7 = &vvcam_sensor7;
viv_video0 = &video0;
viv_video1 = &video1;
@@ -94,6 +98,11 @@
};
};
aon_iram: aon-iram@ffffef8000 {
compatible = "syscon";
reg = <0xff 0xffef8000 0x0 0x10000>;
};
thermal-zones {
cpu-thermal-zone {
polling-delay-passive = <250>;
@@ -383,7 +392,7 @@
entry-cnt = <4>;
control-reg = <0xff 0xff015004>;
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 {
@@ -634,6 +643,12 @@
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 {
compatible = "thead,light-fm-efuse", "syscon";
reg = <0xff 0xff210000 0x0 0x10000>;
@@ -855,6 +870,12 @@
status = "okay";
};
padctrl_audiosys: padctrl-audiosys@ffcb01d000 {
compatible = "thead,light-fm-audio-pinctrl";
reg = <0xff 0xcb01d000 0x0 0x1000>;
status = "disabled";
};
timer4: timer@ffffc33000 {
compatible = "snps,dw-apb-timer";
reg = <0xff 0xffc33000 0x0 0x14>;
@@ -1248,6 +1269,13 @@
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 {
compatible = "thead,light_sys_reg";
reg = <0xff 0xef010100 0x0 0x100>;
@@ -1301,7 +1329,7 @@
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,data-width = <4>;
snps,axi-max-burst-len = <16>;
@@ -1354,8 +1382,7 @@
emmc: sdhci@ffe7080000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7080000 0x0 0x10000
0xff 0xef014060 0x0 0x4>;
reg = <0xff 0xe7080000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <62>;
interrupt-names = "sdhciirq";
@@ -1365,8 +1392,7 @@
sdhci0: sd@ffe7090000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7090000 0x0 0x10000
0xff 0xef014064 0x0 0x4>;
reg = <0xff 0xe7090000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <64>;
interrupt-names = "sdhci0irq";
@@ -1376,8 +1402,7 @@
sdhci1: sd@ffe70a0000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe70a0000 0x0 0x10000
0xff 0xef014064 0x0 0x4>;
reg = <0xff 0xe70a0000 0x0 0x10000>;
interrupt-parent = <&intc>;
interrupts = <71>;
interrupt-names = "sdhci1irq";
@@ -1403,7 +1428,8 @@
clock-names = "pclk", "aclk";
vha_clk_rate = <1000000000>;
ldo_vha-supply = <&npu>;
dma-mask = <0xf 0xffffffff>;
dma-mask = <0xff 0xffffffff>;
resets = <&rst LIGHT_RESET_NPU>;
status = "disabled";
};
@@ -1432,6 +1458,7 @@
clocks = <&vpsys_clk_gate LIGHT_VPSYS_FCE_ACLK>,
<&vpsys_clk_gate LIGHT_VPSYS_FCE_PCLK>;
clock-names = "aclk", "pclk";
resets = <&vpsys_rst LIGHT_RESET_FCE>;
dma-mask = <0xf 0xffffffff>;
status = "disabled";
};
@@ -1481,7 +1508,7 @@
compatible = "light,light-i2s";
reg = <0xff 0xe7034000 0x0 0x4000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_audio_i2s0>;
pinctrl-0 = <&pinctrl_light_i2s0>;
light,mode = "i2s-master";
light,sel = "ap_i2s";
interrupt-parent = <&intc>;
@@ -1506,7 +1533,7 @@
light,sel = "i2s0";
interrupt-parent = <&intc>;
interrupts = <174>;
dmas = <&dmac2 9>, <&dmac2 16>;
dmas = <&dmac2 9>, <&dmac2 8>;
dma-names = "tx", "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
@@ -1555,16 +1582,17 @@
status = "disabled";
};
i2s3: audio_i2s3@0xffcb017000 {
i2s_8ch_sd0: audio_i2s_8ch_sd0@0xffcb017000 {
#sound-dai-cells = <1>;
compatible = "light,light-i2s";
compatible = "light,light-i2s-8ch";
reg = <0xff 0xcb017000 0x0 0x1000>;
audio-cpr-regmap = <&audio_cpr>;
pinctrl-names = "default";
light,mode = "i2s-master";
light,sel = "i2s3";
light,sel = "i2s_8ch_sd0";
interrupt-parent = <&intc>;
interrupts = <177>;
dmas = <&dmac2 14>, <&dmac2 16>;
dmas = <&dmac2 36>, <&dmac2 14>;
dma-names = "tx", "rx";
light,dma_maxburst = <4>;
#dma-cells = <1>;
@@ -1573,6 +1601,267 @@
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 {
compatible = "moortec,mr75203";
reg = <0xff 0xfff4e000 0x0 0x80>,
@@ -1592,6 +1881,10 @@
interrupts = <44>;
clocks = <&dummy_clock_apb>;
clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 12>, <&dmac0 13>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>;
@@ -1611,6 +1904,10 @@
interrupts = <45>;
clocks = <&dummy_clock_apb>;
clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 14>, <&dmac0 15>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>;
@@ -1630,6 +1927,10 @@
interrupts = <46>;
clocks = <&dummy_clock_apb>;
clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 16>, <&dmac0 17>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>;
@@ -1651,6 +1952,10 @@
interrupts = <47>;
clocks = <&dummy_clock_apb>;
clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 18>, <&dmac0 19>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>;
@@ -1672,6 +1977,10 @@
interrupts = <48>;
clocks = <&dummy_clock_apb>;
clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac0 20>, <&dmac0 21>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x104>;
ss_lcnt = /bits/ 16 <0xec>;
fs_hcnt = /bits/ 16 <0x37>;
@@ -1693,6 +2002,10 @@
interrupts = <182>;
clocks = <&dummy_clock_apb>;
clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac2 21>, <&dmac2 20>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x82>;
ss_lcnt = /bits/ 16 <0x78>;
fs_hcnt = /bits/ 16 <0x37>;
@@ -1705,26 +2018,30 @@
#size-cells = <0>;
};
audio_i2c1: i2c@0xffcb01b000 {
compatible = "snps,designware-i2c";
reg = <0xff 0xcb01b000 0x0 0x1000>;
interrupt-parent = <&intc>;
interrupts = <183>;
clocks = <&dummy_clock_apb>;
clock-frequency = <100000>;
ss_hcnt = /bits/ 16 <0x82>;
ss_lcnt = /bits/ 16 <0x78>;
fs_hcnt = /bits/ 16 <0x37>;
fs_lcnt = /bits/ 16 <0x42>;
fp_hcnt = /bits/ 16 <0x14>;
fp_lcnt = /bits/ 16 <0x1a>;
hs_hcnt = /bits/ 16 <0x5>;
hs_lcnt = /bits/ 16 <0x15>;
status = "disabled";
audio_i2c1: i2c@0xffcb01b000 {
compatible = "snps,designware-i2c";
reg = <0xff 0xcb01b000 0x0 0x1000>;
interrupt-parent = <&intc>;
interrupts = <183>;
clocks = <&dummy_clock_apb>;
clock-frequency = <100000>;
i2c_mode = "dma";
dmas = <&dmac2 23>, <&dmac2 22>;
dma-names = "tx", "rx";
#dma-cells = <1>;
ss_hcnt = /bits/ 16 <0x82>;
ss_lcnt = /bits/ 16 <0x78>;
fs_hcnt = /bits/ 16 <0x37>;
fs_lcnt = /bits/ 16 <0x42>;
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>;
#size-cells = <0>;
};
#address-cells = <1>;
#size-cells = <0>;
};
isp0: isp@ffe4100000 {
compatible = "thead,light-isp";
@@ -2005,6 +2322,11 @@
status = "disabled";
};
vvcam_sensor7: vvcam_sensor@7 {
compatible = "thead,light-vvcam-sensor";
status = "disabled";
};
xtensa_dsp: dsp@01{
compatible = "thead,dsp-hw-common";
reg = <0xff 0xef040000 0x0 0x001000 >; /*DSP_SYSREG(0x0000-0xFFF) */
@@ -2154,6 +2476,12 @@
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 */
compatible = "thead,visys-gate-controller";
visys-regmap = <&visys_reg>;
@@ -2181,6 +2509,13 @@
#clock-cells = <1>;
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_TEST=m
CONFIG_MAILBOX=y
CONFIG_EXTCON=y
CONFIG_IIO=y
CONFIG_IIO_SW_DEVICE=y
CONFIG_PWM=y

View File

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

View File

@@ -3,6 +3,10 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=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_PROC=y
CONFIG_CGROUPS=y
@@ -91,6 +95,7 @@ CONFIG_TUN=y
CONFIG_VIRTIO_NET=y
CONFIG_MACB=y
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_RX_ZERO_COPY=y
CONFIG_DWMAC_LIGHT=y
CONFIG_MICROSEMI_PHY=y
CONFIG_REALTEK_PHY=y
@@ -265,6 +270,11 @@ CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_LIGHT=y
CONFIG_HWSPINLOCK_LIGHT_TEST=m
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_SW_DEVICE=y
CONFIG_PWM=y
@@ -298,13 +308,21 @@ CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_DH=y
CONFIG_CRYPTO_CURVE25519=y
CONFIG_CRYPTO_CHACHA20POLY1305=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_OFB=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SHA3=y
CONFIG_CRYPTO_SM3=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_SM4=y
CONFIG_CRYPTO_USER=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_PERNUMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
@@ -320,6 +338,7 @@ CONFIG_OVERLAY_FS=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_INFO=y
CONFIG_PM=y
# CONFIG_SUSPEND 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 += flat.h
generic-y += kvm_para.h
generic-y += mcs_spinlock.h
generic-y += qspinlock.h
generic-y += qrwlock.h
generic-y += qrwlock_types.h
generic-y += user.h
generic-y += vmlinux.lds.h

View File

@@ -11,12 +11,36 @@
#include <asm/barrier.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) \
({ \
__typeof__(ptr) __ptr = (ptr); \
__typeof__(new) __new = (new); \
__typeof__(*(ptr)) __ret; \
switch (size) { \
case 2: { \
__ret = (__typeof__(*(ptr))) \
__xchg16_relaxed((ulong)__new, __ptr); \
break;} \
case 4: \
__asm__ __volatile__ ( \
" amoswap.w %0, %2, %1\n" \

View File

@@ -13,7 +13,6 @@
#include <linux/types.h>
#include <linux/pgtable.h>
#include <asm/mmiowb.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_ar(v) __asm__ __volatile__ ("fence i,r" : : : "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 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 */
/*
* '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
#define __ASM_GENERIC_SPINLOCK_H
#include <linux/atomic.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-generic/qspinlock.h>
#include <asm/qrwlock.h>
#endif /* __ASM_GENERIC_SPINLOCK_H */

View File

@@ -3,15 +3,7 @@
#ifndef __ASM_GENERIC_SPINLOCK_TYPES_H
#define __ASM_GENERIC_SPINLOCK_TYPES_H
#include <linux/types.h>
typedef atomic_t arch_spinlock_t;
/*
* 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)
#include <asm-generic/qspinlock_types.h>
#include <asm-generic/qrwlock_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);
#endif
RISCV_INSN_REJECTED(auipc, insn);
RISCV_INSN_REJECTED(branch, insn);
RISCV_INSN_SET_SIMULATE(jal, insn);
RISCV_INSN_SET_SIMULATE(jalr, insn);
RISCV_INSN_SET_SIMULATE(auipc, insn);
RISCV_INSN_SET_SIMULATE(branch, insn);
return INSN_GOOD;
}

View File

@@ -83,3 +83,115 @@ bool __kprobes simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *reg
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
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
);
gctBOOL
gceSTATUS
_QuerySignal(
IN gckOS Os,
IN gctSIGNAL Signal

View File

@@ -6,6 +6,7 @@
* Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
* Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
*/
#include <linux/extcon-provider.h>
#include <linux/clk.h>
#include <linux/delay.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 }
};
static const unsigned int hdmi_extcon_cable[] = {
EXTCON_DISP_HDMI,
EXTCON_NONE,
};
struct hdmi_vmode {
bool mdataenablepolarity;
@@ -160,6 +166,7 @@ struct dw_hdmi {
struct clk *pix_clk;
struct clk *i2s_clk;
struct dw_hdmi_i2c *i2c;
struct extcon_dev *edev;
struct hdmi_data_info hdmi_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",
status == connector_status_connected ?
"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) {
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);
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);
if (irq < 0) {
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_DESIGNWARE_CORE) += i2c-designware-core.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-$(CONFIG_I2C_DESIGNWARE_SLAVE) += i2c-designware-slave.o
obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o

View File

@@ -17,6 +17,7 @@
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/dmaengine.h>
#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \
I2C_FUNC_SMBUS_BYTE | \
@@ -234,6 +235,18 @@ struct reset_control;
* values than the one computed based only on the input clock frequency.
* 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 device *dev;
struct regmap *map;
@@ -257,6 +270,7 @@ struct dw_i2c_dev {
u8 *rx_buf;
int msg_err;
unsigned int status;
unsigned int tx_status;
u32 abort_source;
int irq;
u32 flags;
@@ -287,6 +301,10 @@ struct dw_i2c_dev {
int mode;
struct i2c_bus_recovery_info rinfo;
bool suspended;
struct i2c_dw_dma dma;
u32 laststat;
u32 laststatus;
int dw_i2c_enable_dma;
};
#define ACCESS_INTR_MASK 0x00000001

View File

@@ -22,6 +22,7 @@
#include <linux/reset.h>
#include "i2c-designware-core.h"
#include "i2c-designware-master_dma.h"
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 */
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.
*/
if (msgs[dev->msg_write_idx].addr != addr) {
dev_err(dev->dev,
"%s: invalid target address\n", __func__);
dev->msg_err = -EINVAL;
dev_err(dev->dev,
"%s: invalid target address\n", __func__);
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_err = 0;
dev->status = STATUS_IDLE;
dev->tx_status = STATUS_IDLE;
dev->abort_source = 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);
/* 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)) {
dev_err(dev->dev, "controller timed out\n");
/* 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;
}
if (dev->status)
dev_err(dev->dev,
"transfer terminated early - interrupt latency too high?\n");
if (dev->status || dev->tx_status) {
dev_err(dev->dev, "transfer terminated early - interrupt latency too high? sta 0x%x\n", dev->status);
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;
done:
if (dev->dw_i2c_enable_dma) {
i2c_dw_xfer_dma_deinit(dev);
}
i2c_dw_release_lock(dev);
done_nolock:
pm_runtime_mark_last_busy(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)
i2c_dw_read(dev);
if (stat & DW_IC_INTR_TX_EMPTY)
if (stat & DW_IC_INTR_TX_EMPTY) {
i2c_dw_xfer_msg(dev);
}
/*
* 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 ||
((status & DW_IC_STATUS_TFE) &&
(!(status & DW_IC_STATUS_RFNE)) &&
(!(status & DW_IC_STATUS_MASTER_ACTIVITY))))
(!(status & DW_IC_STATUS_MASTER_ACTIVITY)))) {
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 */
regmap_read(dev->map, DW_IC_INTR_MASK, &stat);
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;
unsigned long irq_flags;
struct device_node *np;
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);
if (dev->dw_i2c_enable_dma) {
init_completion(&dev->dma.dma_complete);
}
dev->init = i2c_dw_init_master;
dev->disable = i2c_dw_disable;
@@ -787,10 +830,10 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
i2c_dw_disable_int(dev);
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) {
dev_err(dev->dev, "failure requesting irq %i: %d\n",
dev->irq, ret);
dev->irq, 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_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_TEST) += virtio-mailbox-test.o

View File

@@ -28,17 +28,20 @@
struct dwcmshc_priv {
struct clk *bus_clk;
void __iomem *soc_base;
bool is_emmc_card;
bool pull_up_en;
bool io_fixed_1v8;
bool wprtn_ignore;
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
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)
{
@@ -114,12 +117,13 @@ static void snps_phy_1_8v_init(struct sdhci_host *host)
//disable delay lane
sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
//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);
//enable delay lane
val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
val &= ~(1 << UPDATE_DC);
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);
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
sdhci_writeb(host, 1 << UPDATE_DC, PHY_SDCLKDL_CNFG_R);
//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);
//enable delay lane
val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R);
val &= ~(1 << UPDATE_DC);
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);
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;
}
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)
{
@@ -289,12 +349,6 @@ static void snps_sdhci_reset(struct sdhci_host *host, u8 mask)
pltfm_host = sdhci_priv(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*/
sdhci_reset(host, mask);
@@ -390,7 +444,7 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
ctrl_2 |= SDHCI_CTRL_VDD_180;
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) {
// //disable delay lane
// 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;
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*/
} else {
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)
{
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) {
switch (1 << vdd) {
case MMC_VDD_165_195:
@@ -509,6 +572,8 @@ static void dwcmshc_set_power_noreg(struct sdhci_host *host, unsigned char mode,
return;
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);
if (pwr == 0) {
@@ -579,6 +644,20 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
.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)
{
struct sdhci_pltfm_host *pltfm_host;
@@ -604,13 +683,31 @@ static int dwcmshc_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(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")) {
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 {
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")) {

View File

@@ -36,6 +36,8 @@
#define PHY_SDCLKDL_DC_R (DWC_MSHC_PTR_PHY_R + 0x1e)
#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 INPSEL_CNFG 2 //2bit
@@ -72,4 +74,6 @@
#define POST_CHANGE_DLY 0x13 //2bit
#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_*/

View File

@@ -25,6 +25,16 @@ config STMMAC_SELFTESTS
feature if you are facing problems with your HW and submit the test
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
tristate "STMMAC Platform bus support"
depends on STMMAC_ETH

View File

@@ -67,12 +67,18 @@ struct stmmac_rx_buffer {
dma_addr_t 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 {
u32 rx_count_frames;
u32 queue_index;
struct page_pool *page_pool;
struct stmmac_rx_buffer *buf_pool;
struct stmmac_rx_skbuffer *skbuf_pool;
struct stmmac_priv *priv_data;
struct dma_extended_desc *dma_erx;
struct dma_desc *dma_rx ____cacheline_aligned_in_smp;
@@ -210,6 +216,7 @@ struct stmmac_priv {
unsigned int mode;
unsigned int chain_mode;
int extend_desc;
bool extend_stat_need;
struct hwtstamp_config tstamp_config;
struct ptp_clock *ptp_clock;
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++)
stmmac_clear_tx_descriptors(priv, queue);
}
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
/**
* stmmac_init_rx_buffers - init the RX descriptor buffer.
* @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
* 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)
{
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
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)
return -ENOMEM;
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)
return -ENOMEM;
@@ -1364,14 +1367,13 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
return 0;
}
/**
* stmmac_free_rx_buffer - free RX dma buffers
* @priv: private structure
* @queue: RX queue 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_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;
}
#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
* @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 *
sizeof(struct dma_extended_desc),
rx_q->dma_erx, rx_q->dma_rx_phy);
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
kfree(rx_q->buf_pool);
#else
kfree(rx_q->skbuf_pool);
#endif
if (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->priv_data = priv;
pp_params.flags = PP_FLAG_DMA_MAP;
pp_params.pool_size = priv->dma_rx_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;
goto err_dma;
}
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
rx_q->buf_pool = kcalloc(priv->dma_rx_size,
sizeof(*rx_q->buf_pool),
GFP_KERNEL);
if (!rx_q->buf_pool)
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) {
rx_q->dma_erx = dma_alloc_coherent(priv->device,
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];
int len, dirty = stmmac_rx_dirty(priv, queue);
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;
while (dirty-- > 0) {
struct stmmac_rx_buffer *buf = &rx_q->buf_pool[entry];
struct dma_desc *p;
bool use_rx_wd;
if (priv->extend_desc)
p = (struct dma_desc *)(rx_q->dma_erx + entry);
else
p = rx_q->dma_rx + entry;
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
buf = &rx_q->buf_pool[entry];
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)
break;
}
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)
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);
/* 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
* data.
*/
dma_sync_single_for_device(priv->device, buf->addr, len,
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);
if (priv->sph)
@@ -3815,7 +3986,11 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
while (count < limit) {
unsigned int buf1_len = 0, buf2_len = 0;
enum pkt_hash_types hash_type;
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
struct stmmac_rx_buffer *buf;
#else
struct stmmac_rx_skbuffer *skbuf;
#endif
struct dma_desc *np, *p;
int entry;
u32 hash;
@@ -3838,8 +4013,11 @@ read_again:
buf1_len = 0;
buf2_len = 0;
entry = next_entry;
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
buf = &rx_q->buf_pool[entry];
#else
skbuf = &rx_q->skbuf_pool[entry];
#endif
if (priv->extend_desc)
p = (struct dma_desc *)(rx_q->dma_erx + entry);
else
@@ -3863,12 +4041,14 @@ read_again:
prefetch(np);
if (priv->extend_desc)
if (priv->extend_desc && priv->extend_stat_need)
stmmac_rx_extended_status(priv, &priv->dev->stats,
&priv->xstats, rx_q->dma_erx + entry);
if (unlikely(status == discard_frame)) {
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
page_pool_recycle_direct(rx_q->page_pool, buf->page);
buf->page = NULL;
#endif
error = 1;
if (!priv->hwts_rx_en)
priv->dev->stats.rx_errors++;
@@ -3884,11 +4064,14 @@ read_again:
}
/* Buffer is good. Go on. */
#ifndef CONFIG_STMMAC_RX_ZERO_COPY
prefetch(page_address(buf->page));
if (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);
len += buf1_len;
buf2_len = stmmac_rx_buf2_len(priv, p, status, len);
@@ -3911,7 +4094,30 @@ read_again:
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) {
skb = napi_alloc_skb(&ch->rx_napi, buf1_len);
if (!skb) {
@@ -3952,7 +4158,7 @@ read_again:
page_pool_release_page(rx_q->page_pool, buf->sec_page);
buf->sec_page = NULL;
}
#endif
drain_data:
if (likely(status & rx_not_ls))
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);
/* 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;
}
dev->mtu = mtu;
@@ -5083,6 +5293,11 @@ int stmmac_dvr_probe(struct device *device,
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->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-left-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-audio-pinctrl.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 {
unsigned int pin_id;
unsigned int mux_mode;
@@ -50,6 +59,8 @@ struct light_pinctrl_soc_info {
unsigned int grp_index;
struct light_pmx_func *functions;
unsigned int nfunctions;
char *label;
enum light_pinctrl_type type;
unsigned int cfg_off;
unsigned int mux_off;
@@ -66,6 +77,7 @@ struct light_pinctrl {
#define LIGHT_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
#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_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,
const unsigned int pin_id)
@@ -247,13 +259,31 @@ static int light_pmx_set(struct pinctrl_dev *pctldev, unsigned int selector,
continue;
}
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);
if (info->type == LIGHT_FM_AUDIO) {
if (pin->mux_mode == AUDIO_IO_GPIO) {
mux = ~(1 << pin_id) & readl(priv->base);
writel(mux, priv->base); /* Controlled by GPIO under AUDIO_SUBSYS */
continue;
}
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;
@@ -430,7 +460,15 @@ static int light_pinctrl_parse_groups(struct device_node *np,
struct light_pin *pin = &grp->pins[i];
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;
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),
};
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)
{
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 = {
.pins = light_mpw_pinctrl_pads,
.npins = ARRAY_SIZE(light_mpw_pinctrl_pads),
.type = LIGHT_MPW,
.cfg_off = 0x4c,
.mux_off = 0x404,
.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 = {
.pins = light_fm_right_pinctrl_pads,
.npins = ARRAY_SIZE(light_fm_right_pinctrl_pads),
.type = LIGHT_FM_RIGHT,
.cfg_off = 0x0,
.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 = {
.pins = light_fm_left_pinctrl_pads,
.npins = ARRAY_SIZE(light_fm_left_pinctrl_pads),
.type = LIGHT_FM_LEFT,
.cfg_off = 0x0,
.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 = {
.pins = light_fm_aon_pinctrl_pads,
.npins = ARRAY_SIZE(light_fm_aon_pinctrl_pads),
.type = LIGHT_FM_AON,
.cfg_off = 0x0,
.mux_off = 0x400,
.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[] = {
{ .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-left-pinctrl", .data = &light_fm_left_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 */ }
};
MODULE_DEVICE_TABLE(of, light_pinctrl_of_match);

View File

@@ -34,6 +34,11 @@ struct light_src {
enum light_src_registers {
SRC_WDT0 = 0x0034,
SRC_WDT1 = 0x0038,
SRC_NPU = 0x01b0,
};
enum light_vpsys_src_registers {
SRC_FCE = 0x0004,
};
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[] = {
[LIGHT_RESET_WDT0] = { SRC_WDT0, 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)
@@ -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)
{
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[] = {
{ .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);

View File

@@ -58,6 +58,10 @@ config RPMSG_QCOM_SMD
providing communication channels to remote processors in Qualcomm
platforms.
config RPMSG_THEAD_LIGHT
tristate "THEAD Light RPM Driver"
depends on RPMSG
config RPMSG_VIRTIO
tristate "Virtio RPMSG bus driver"
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_SMD) += qcom_smd.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);
}
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 = {
.id_table = rpmsg_driver_char_id_table,
.probe = rpmsg_chrdev_probe,
.remove = rpmsg_chrdev_remove,
.drv = {

View File

@@ -158,7 +158,7 @@ struct virtio_rpmsg_channel {
* processor.
*/
#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.

View File

@@ -16,6 +16,12 @@ config LIGHT_SUSPEND
help
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
endif

View File

@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_LIGHT_IOPMP) += light-iopmp.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_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 device *dev;
struct platform_device *dwc3;
@@ -255,9 +263,10 @@ static int dwc3_thead_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, thead);
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))
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");
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.priv = exp_buf;
unsigned int gfp = GFP_KERNEL;
if(attr->flags & VIRTIO_VDAMBUF_DMA32)
{
gfp |= __GFP_DMA32;
}
switch (heap_type) {
case VIRTIO_VDMABUF_HEAP_TYPE_USER:
return -EINVAL; /* Not support currently */
@@ -1235,7 +1241,7 @@ static int virtio_vdmabuf_create_dmabuf(struct virtio_vdmabuf *vdmabuf,
exp_buf->bp_num = npages;
for (i = 0; i < npages; i++) {
page = alloc_page(GFP_KERNEL);
page = alloc_page(gfp);
if (!page) {
ret = -ENOMEM;
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 */
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) {
ret = -ENOMEM;
goto err_exp;

View File

@@ -29,6 +29,7 @@
#include <linux/reset.h>
#include <linux/watchdog.h>
#include <linux/debugfs.h>
#include <linux/firmware/thead/light_event.h>
#define WDOG_CONTROL_REG_OFFSET 0x00
#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");
return IRQ_NONE;
}
light_event_set_rebootmode(LIGHT_EVENT_SW_WATCHDOG);
WARN(1, "watchdog app was stuck! watchdog pretimeout event\n");
watchdog_notify_pretimeout(&dw_wdt->wdd);

View File

@@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/watchdog.h>
#include <linux/firmware/thead/ipc.h>
#include <linux/firmware/thead/light_event.h>
#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__);
light_event_set_rebootmode(LIGHT_EVENT_SW_REBOOT);
ret = light_aon_call_rpc(ipc, &wdt_dev->msg, false);
if (ret)
return ret;

View File

@@ -53,6 +53,7 @@
#define __WRITE_ONCE(x, val) \
do { \
*(volatile typeof(x) *)&(x) = (val); \
smp_mb(); \
} while (0)
#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_WDT1 1
#define LIGHT_RESET_NPU 2
// vpsys reset
#define LIGHT_RESET_FCE 100
#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,
const union bpf_attr *kattr,
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,
const struct bpf_prog *prog,
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;
}
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)
{
}

View File

@@ -36,6 +36,7 @@ enum light_aon_misc_func {
LIGHT_AON_MISC_FUNC_WDG_POWER_OFF = 9,
LIGHT_AON_MISC_FUNC_AON_WDT_ON = 10,
LIGHT_AON_MISC_FUNC_AON_WDT_OFF = 11,
LIGHT_AON_MISC_FUNC_AON_RESERVE_MEM = 12,
};
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,
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
* @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. */
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 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))
/* 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

View File

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

View File

@@ -32,6 +32,7 @@
#include <linux/ratelimit.h>
#include <linux/debugfs.h>
#include <asm/sections.h>
#include <linux/firmware/thead/light_event.h>
#define PANIC_TIMER_STEP 100
#define PANIC_BLINK_SPD 18
@@ -182,7 +183,11 @@ void panic(const char *fmt, ...)
int state = 0;
int old_cpu, this_cpu;
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
* 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
* rcu_read_unlock_special().
*/
static void
static notrace void
rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags)
{
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
* 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) ||
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
* 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;
@@ -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
* 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;
}
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,

View File

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

View File

@@ -10,20 +10,86 @@
#include <net/bpf_sk_storage.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <net/net_namespace.h>
#include <linux/error-injection.h>
#include <linux/smp.h>
#include <linux/sock_diag.h>
#define CREATE_TRACE_POINTS
#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,
u32 *retval, u32 *time, bool xdp)
{
struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = { NULL };
struct bpf_test_timer t = { NO_MIGRATE };
enum bpf_cgroup_storage_type stype;
u64 time_start, time_spent = 0;
int ret = 0;
u32 i;
int ret;
for_each_cgroup_storage_type(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)
repeat = 1;
rcu_read_lock();
migrate_disable();
time_start = ktime_get_ns();
for (i = 0; i < repeat; i++) {
bpf_test_timer_enter(&t);
do {
ret = bpf_cgroup_storage_set(storage);
if (ret)
break;
@@ -53,29 +117,8 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
bpf_cgroup_storage_unset();
if (signal_pending(current)) {
ret = -EINTR;
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;
} while (bpf_test_timer_continue(&t, repeat, &ret, time));
bpf_test_timer_leave(&t);
for_each_cgroup_storage_type(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,
union bpf_attr __user *uattr)
{
struct bpf_test_timer t = { NO_PREEMPT };
u32 size = kattr->test.data_size_in;
struct bpf_flow_dissector ctx = {};
u32 repeat = kattr->test.repeat;
struct bpf_flow_keys *user_ctx;
struct bpf_flow_keys flow_keys;
u64 time_start, time_spent = 0;
const struct ethhdr *eth;
unsigned int flags = 0;
u32 retval, duration;
void *data;
int ret;
u32 i;
if (prog->type != BPF_PROG_TYPE_FLOW_DISSECTOR)
return -EINVAL;
@@ -735,39 +777,15 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
ctx.data = data;
ctx.data_end = (__u8 *)data + size;
rcu_read_lock();
preempt_disable();
time_start = ktime_get_ns();
for (i = 0; i < repeat; i++) {
retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN,
size, flags);
bpf_test_timer_enter(&t);
do {
retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN,
size, flags);
} while (bpf_test_timer_continue(&t, repeat, &ret, &duration));
bpf_test_timer_leave(&t);
if (signal_pending(current)) {
preempt_enable();
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;
if (ret < 0)
goto out;
ret = bpf_test_finish(kattr, uattr, &flow_keys, sizeof(flow_keys),
retval, duration);
@@ -780,3 +798,106 @@ out:
kfree(data);
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 = {
.test_run = bpf_prog_test_run_sk_lookup,
};
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
int sysctl_max_skb_frags __read_mostly = 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
@@ -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);
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)
@@ -405,10 +420,10 @@ void *netdev_alloc_frag(unsigned int fragsz)
fragsz = SKB_DATA_ALIGN(fragsz);
if (in_irq() || irqs_disabled()) {
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 {
local_bh_disable();
data = __napi_alloc_frag(fragsz, GFP_ATOMIC);
data = __napi_alloc_frag(fragsz, GFP_ATOMIC | skb_gfp_dma32);
local_bh_enable();
}
return data;
@@ -458,12 +473,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
if (in_irq() || irqs_disabled()) {
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;
} else {
local_bh_disable();
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;
local_bh_enable();
}
@@ -531,7 +546,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len,
if (sk_memalloc_socks())
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))
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