3 Commits

Author SHA1 Message Date
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
66 changed files with 3036 additions and 516 deletions

View File

@@ -13,7 +13,8 @@ dtb-$(CONFIG_SOC_THEAD) += light-a-val-npu-fce.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-iso7816.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-iso7816.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-nand.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-nand.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-dsi0.dtb light-a-val-dsi1.dtb light-a-val-hdmi.dtb light-a-val-dsi0-dsi1.dtb light-a-val-dsi0-hdmi.dtb light-a-val-dpi0.dtb light-a-val-dpi0-dpi1.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-audio-tdm.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-dsi0.dtb light-a-val-dsi1.dtb light-a-val-hdmi.dtb light-a-val-dsi0-dsi1.dtb light-a-val-dsi0-hdmi.dtb light-a-val-dsi0-hdmi-audio.dtb light-a-val-dpi0.dtb light-a-val-dpi0-dpi1.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-wcn.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-wcn.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-gpio-keys.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-gpio-keys.dtb
dtb-$(CONFIG_SOC_THEAD) += light-a-val-khv.dtb dtb-$(CONFIG_SOC_THEAD) += light-a-val-khv.dtb

View File

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

View File

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

View File

@@ -0,0 +1,125 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
#include "light-a-val.dts"
&tdm_slot1 {
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";
};
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";
status = "okay";
};
};
&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 { /* TDM - AUDIO SYS CODEC 7210*/
reg = <1>;
format = "dsp_b";
cpu@0 {
sound-dai = <&tdm_slot1 0>;
};
cpu@1 {
sound-dai = <&tdm_slot2 1>;
};
cpu@2 {
sound-dai = <&tdm_slot3 2>;
};
cpu@3 {
sound-dai = <&tdm_slot4 3>;
};
cpu@4 {
sound-dai = <&tdm_slot5 4>;
};
cpu@5 {
sound-dai = <&tdm_slot6 5>;
};
cpu@6 {
sound-dai = <&tdm_slot7 6>;
};
cpu@7 {
sound-dai = <&tdm_slot8 7>;
};
codec {
sound-dai = <&es7210_adc2>;
};
};
};
&light_i2s {
status = "okay";
};
&i2s0 {
status = "okay";
};
&i2s3 {
status = "okay";
};

View File

@@ -10,9 +10,25 @@
compatible = "thead,light-val-audio", "thead,light"; compatible = "thead,light-val-audio", "thead,light";
}; };
&lightsound { &audio_i2c0 {
status = "okay"; clock-frequency = <100000>;
status = "okay";
es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
reg = <0x40>;
sound-name-prefix = "ES7210";
};
};
&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*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";

View File

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

View File

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

View File

@@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
/dts-v1/;
#include "light-a-val-dsi0-hdmi.dts"
&audio_i2c0 {
status = "okay";
es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
reg = <0x40>;
sound-name-prefix = "ES7210";
};
};
&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 = <&i2s3 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 {
status = "okay";
};
&i2s0 {
status = "okay";
};
&i2s3 {
status = "okay";
};

View File

@@ -93,9 +93,25 @@
}; };
}; };
&lightsound { &audio_i2c0 {
clock-frequency = <100000>;
status = "okay"; status = "okay";
es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
reg = <0x40>;
sound-name-prefix = "ES7210";
};
};
&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*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -106,7 +122,7 @@
sound-dai = <&es8156_audio_codec>; sound-dai = <&es8156_audio_codec>;
}; };
}; };
simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/ simple-audio-card,dai-link@1 { /* I2S - AUDIO SYS CODEC 7210*/
reg = <1>; reg = <1>;
format = "i2s"; format = "i2s";
@@ -118,19 +134,19 @@
}; };
}; };
}; };
&light_i2s { &light_i2s {
status = "okay"; status = "okay";
}; };
&i2s0 { &i2s0 {
status = "okay"; status = "okay";
}; };
&i2s3 { &i2s3 {
status = "okay"; status = "okay";
}; };
&qspi0 { &qspi0 {
status = "okay"; status = "okay";
}; };

View File

@@ -38,6 +38,18 @@
}; };
}; };
&audio_i2c0 {
clock-frequency = <100000>;
status = "okay";
es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>;
compatible = "MicArray_0";
reg = <0x40>;
sound-name-prefix = "ES7210";
};
};
&lightsound { &lightsound {
status = "okay"; status = "okay";

View File

@@ -5,7 +5,7 @@
/dts-v1/; /dts-v1/;
#include "light-a-val-dsi0-hdmi.dts" #include "light-a-val-dsi0-hdmi-audio.dts"
&light_iopmp { &light_iopmp {

View File

@@ -193,8 +193,9 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
sound-name-prefix = "DUMMY";
status = "okay"; status = "okay";
}; };
@@ -561,12 +562,27 @@
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
}; };
es7210_audio_codec: es7210@40 { audio_aw87519_pa: amp@58 {
#sound-dai-cells = <0>; compatible = "awinic,aw87519_pa";
compatible = "MicArray_0"; reg = <0x58>;
reg = <0x40>; reset-gpio = <&pcal6408ahk_b 3 0x1>;
sound-name-prefix = "AW87519";
status = "okay";
};
};
&audio_i2c1 {
clock-frequency = <100000>;
status = "okay";
pcal6408ahk_b: gpio@20 {
compatible = "nxp,pcal9554b";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
}; };
}; };
@@ -848,8 +864,27 @@
pinctrl_volume: volume_grp { pinctrl_volume: volume_grp {
thead,pins = < thead,pins = <
FM_CPU_JTG_TDI 0x3 0x208 FM_CPU_JTG_TDI 0x3 0x238
FM_CPU_JTG_TDO 0x3 0x208 FM_CPU_JTG_TDO 0x3 0x238
>;
};
};
};
&padctrl_audiosys {
status = "okay";
light-audio-padctrl {
/*
* Pin Configuration Node:
* Format: <pin_id mux_node config>
*/
pinctrl_audio_i2c1: audio_i2c1_grp {
thead,pins = <
FM_AUDIO_IO_PA6 0x2 0x008
FM_AUDIO_IO_PA7 0x2 0x008
>; >;
}; };
}; };

View File

@@ -15,7 +15,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
chosen { chosen {
@@ -194,9 +194,10 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -585,18 +586,21 @@
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
}; };
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay"; status = "okay";
}; };
}; };
@@ -2091,6 +2095,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -2118,7 +2127,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };

View File

@@ -15,7 +15,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
chosen { chosen {
@@ -194,9 +194,10 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -238,7 +239,8 @@
gpio-keys { gpio-keys {
compatible = "gpio-keys"; compatible = "gpio-keys";
pinctrl-0 = <&pinctrl_volume>; pinctrl-0 = <&pinctrl_volume_up
&pinctrl_volume_down>;
pinctrl-names = "default"; pinctrl-names = "default";
key-volumedown { key-volumedown {
label = "Volume Down Key"; label = "Volume Down Key";
@@ -592,18 +594,21 @@
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
}; };
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay"; status = "okay";
}; };
}; };
@@ -797,6 +802,12 @@
FM_GPIO3_2 0x1 0x208 /* pwm0 */ FM_GPIO3_2 0x1 0x208 /* pwm0 */
>; >;
}; };
pinctrl_volume_up: volume_up_grp {
thead,pins = <
FM_GPIO2_25 0x0 0x238
>;
};
}; };
}; };
@@ -842,9 +853,9 @@
>; >;
}; };
pinctrl_volume: volume_grp { pinctrl_volume_down: volume_down_grp {
thead,pins = < thead,pins = <
FM_CLK_OUT_2 0x3 0x208 FM_CLK_OUT_2 0x3 0x238
>; >;
}; };
}; };
@@ -2265,6 +2276,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -2292,7 +2308,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };

View File

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

View File

@@ -15,7 +15,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
chosen { chosen {
@@ -194,9 +194,10 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -605,18 +606,21 @@
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
}; };
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay"; status = "okay";
}; };
}; };
@@ -880,8 +884,8 @@
pinctrl_volume: volume_grp { pinctrl_volume: volume_grp {
thead,pins = < thead,pins = <
FM_AOGPIO_11 0x0 0x208 FM_AOGPIO_11 0x0 0x238
FM_AOGPIO_10 0x3 0x208 FM_AOGPIO_10 0x3 0x238
>; >;
}; };
}; };
@@ -2313,6 +2317,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -2340,7 +2349,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };

View File

@@ -15,7 +15,7 @@
memory@0 { memory@0 {
device_type = "memory"; device_type = "memory";
reg = <0x0 0x00000000 0x0 0x80000000>; reg = <0x0 0x200000 0x0 0x7fe00000>;
}; };
chosen { chosen {
@@ -194,9 +194,10 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -573,18 +574,21 @@
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
}; };
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay"; status = "okay";
}; };
}; };
@@ -2249,6 +2253,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -2276,7 +2285,7 @@
sound-dai = <&light_i2s 1>; sound-dai = <&light_i2s 1>;
}; };
codec { codec {
sound-dai = <&dummy_codec 2>; sound-dai = <&dummy_codec>;
}; };
}; };
}; };

View File

@@ -191,8 +191,9 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
sound-name-prefix = "DUMMY";
status = "okay"; status = "okay";
}; };
@@ -341,18 +342,21 @@
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
}; };
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&ao_gpio4_porta 9 0x1>; reset-gpio = <&ao_gpio4_porta 9 0x1>;
sound-name-prefix = "AW87519";
status = "okay"; status = "okay";
}; };
}; };

View File

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

View File

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

View File

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

View File

@@ -186,9 +186,17 @@
}; };
dummy_codec: dummy_codec { dummy_codec: dummy_codec {
#sound-dai-cells = <1>; #sound-dai-cells = <0>;
compatible = "linux,bt-sco"; compatible = "thead,light-dummy-pcm";
status = "okay"; status = "okay";
sound-name-prefix = "DUMMY";
};
fan: pwm-fan {
compatible = "pwm-fan";
#cooling-cells = <2>;
pwms = <&pwm 1 10000000 0>;
cooling-levels = <0 64 192 255>;
}; };
reg_vref_1v8: regulator-adc-verf { reg_vref_1v8: regulator-adc-verf {
@@ -196,7 +204,7 @@
regulator-name = "vref-1v8"; regulator-name = "vref-1v8";
regulator-min-microvolt = <1800000>; regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>; regulator-max-microvolt = <1800000>;
status = "okay"; status = "okay";
}; };
reg_tp_pwr_en: regulator-pwr-en { reg_tp_pwr_en: regulator-pwr-en {
@@ -558,6 +566,48 @@
}; };
}; };
thermal-zones {
cpu-thermal-zone {
trips {
fan_config0: fan-trip0 {
temperature = <40000>;
hysteresis = <5000>;
type = "active";
};
fan_config1: fan-trip1 {
temperature = <50000>;
hysteresis = <5000>;
type = "active";
};
fan_config2: fan-trip2 {
temperature = <60000>;
hysteresis = <5000>;
type = "active";
};
};
cooling-maps {
fan-on {
trip = <&fan_config0>;
cooling-device =
<&fan 1 1>;
};
fan-faster {
trip = <&fan_config1>;
cooling-device =
<&fan 2 2>;
};
fan-full {
trip = <&fan_config2>;
cooling-device =
<&fan 3 3>;
};
};
};
};
}; };
&resmem { &resmem {
@@ -611,18 +661,21 @@
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "everest,es8156"; compatible = "everest,es8156";
reg = <0x08>; reg = <0x08>;
sound-name-prefix = "ES8156";
}; };
es7210_audio_codec: es7210@40 { es7210_audio_codec: es7210@40 {
#sound-dai-cells = <0>; #sound-dai-cells = <0>;
compatible = "MicArray_0"; compatible = "MicArray_0";
reg = <0x40>; reg = <0x40>;
sound-name-prefix = "ES7210";
}; };
audio_aw87519_pa@58 { audio_aw87519_pa: amp@58 {
compatible = "awinic,aw87519_pa"; compatible = "awinic,aw87519_pa";
reg = <0x58>; reg = <0x58>;
reset-gpio = <&pcal6408ahk_a 2 0x1>; reset-gpio = <&pcal6408ahk_a 2 0x1>;
sound-name-prefix = "AW87519";
status = "okay"; status = "okay";
}; };
@@ -634,8 +687,8 @@
}; };
pcal6408ahk_a: gpio@20 { pcal6408ahk_a: gpio@20 {
compatible = "nxp,pcal9554b"; compatible = "nxp,pca9557";
reg = <0x20>; reg = <0x18>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
@@ -938,8 +991,8 @@
status = "okay"; status = "okay";
pcal6408ahk_b: gpio@20 { pcal6408ahk_b: gpio@20 {
compatible = "nxp,pcal9554b"; compatible = "nxp,pca9557";
reg = <0x20>; reg = <0x18>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
@@ -950,8 +1003,8 @@
status = "okay"; status = "okay";
pcal6408ahk_c: gpio@20 { pcal6408ahk_c: gpio@20 {
compatible = "nxp,pcal9554b"; compatible = "nxp,pca9557";
reg = <0x20>; reg = <0x18>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
@@ -967,8 +1020,8 @@
status = "okay"; status = "okay";
pcal6408ahk_d: gpio@20 { pcal6408ahk_d: gpio@20 {
compatible = "nxp,pcal9554b"; compatible = "nxp,pca9557";
reg = <0x20>; reg = <0x18>;
gpio-controller; gpio-controller;
#gpio-cells = <2>; #gpio-cells = <2>;
}; };
@@ -1411,6 +1464,11 @@
&lightsound { &lightsound {
status = "okay"; status = "okay";
simple-audio-card,widgets = "Speaker", "Speaker";
simple-audio-card,routing =
"Speaker", "AW87519 VO",
"AW87519 IN", "ES8156 ROUT";
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/ simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
reg = <0>; reg = <0>;
format = "i2s"; format = "i2s";
@@ -1454,6 +1512,13 @@
status = "okay"; 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 { &cpus {
c910_0: cpu@0 { c910_0: cpu@0 {
operating-points = < operating-points = <
@@ -1461,12 +1526,14 @@
300000 650000 300000 650000
800000 700000 800000 700000
1500000 800000 1500000 800000
1848000 1000000
>; >;
light,dvddm-operating-points = < light,dvddm-operating-points = <
/* kHz uV */ /* kHz uV */
300000 800000 300000 800000
800000 800000 800000 800000
1500000 800000 1500000 800000
1848000 1000000
>; >;
}; };
c910_1: cpu@1 { c910_1: cpu@1 {
@@ -1475,12 +1542,14 @@
300000 650000 300000 650000
800000 700000 800000 700000
1500000 800000 1500000 800000
1848000 1000000
>; >;
light,dvddm-operating-points = < light,dvddm-operating-points = <
/* kHz uV */ /* kHz uV */
300000 800000 300000 800000
800000 800000 800000 800000
1500000 800000 1500000 800000
1848000 1000000
>; >;
}; };
c910_2: cpu@2 { c910_2: cpu@2 {
@@ -1490,12 +1559,14 @@
300000 650000 300000 650000
800000 700000 800000 700000
1500000 800000 1500000 800000
1848000 1000000
>; >;
light,dvddm-operating-points = < light,dvddm-operating-points = <
/* kHz uV */ /* kHz uV */
300000 800000 300000 800000
800000 800000 800000 800000
1500000 800000 1500000 800000
1848000 1000000
>; >;
}; };
c910_3: cpu@3 { c910_3: cpu@3 {
@@ -1505,12 +1576,14 @@
300000 650000 300000 650000
800000 700000 800000 700000
1500000 800000 1500000 800000
1848000 1000000
>; >;
light,dvddm-operating-points = < light,dvddm-operating-points = <
/* kHz uV */ /* kHz uV */
300000 800000 300000 800000
800000 800000 800000 800000
1500000 800000 1500000 800000
1848000 1000000
>; >;
}; };
}; };

View File

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

View File

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

View File

@@ -6,6 +6,7 @@
#include <dt-bindings/pinctrl/light-fm-left-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-left-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-right-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-right-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h> #include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h>
#include <dt-bindings/pinctrl/light-fm-audio-pinctrl.h>
#include <dt-bindings/clock/light-fm-ap-clock.h> #include <dt-bindings/clock/light-fm-ap-clock.h>
#include <dt-bindings/clock/light-vpsys.h> #include <dt-bindings/clock/light-vpsys.h>
#include <dt-bindings/clock/light-vosys.h> #include <dt-bindings/clock/light-vosys.h>
@@ -94,6 +95,12 @@
}; };
}; };
aon_iram: aon-iram@ffffef8000 {
compatible = "syscon";
reg = <0xff 0xffef8000 0x0 0x10000>;
};
thermal-zones { thermal-zones {
cpu-thermal-zone { cpu-thermal-zone {
polling-delay-passive = <250>; polling-delay-passive = <250>;
@@ -383,7 +390,7 @@
entry-cnt = <4>; entry-cnt = <4>;
control-reg = <0xff 0xff015004>; control-reg = <0xff 0xff015004>;
control-val = <0x1c>; control-val = <0x1c>;
csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc>; csr-copy = <0x7f3 0x7c0 0x7c1 0x7c2 0x7c3 0x7c5 0x7cc 0x7ce>;
}; };
clint0: clint@ffdc000000 { clint0: clint@ffdc000000 {
@@ -855,6 +862,12 @@
status = "okay"; status = "okay";
}; };
padctrl_audiosys: padctrl-audiosys@ffcb01d000 {
compatible = "thead,light-fm-audio-pinctrl";
reg = <0xff 0xcb01d000 0x0 0x1000>;
status = "disabled";
};
timer4: timer@ffffc33000 { timer4: timer@ffffc33000 {
compatible = "snps,dw-apb-timer"; compatible = "snps,dw-apb-timer";
reg = <0xff 0xffc33000 0x0 0x14>; reg = <0xff 0xffc33000 0x0 0x14>;
@@ -1301,7 +1314,7 @@
65536 65536 65536 65536 65536 65536 65536 65536
65536 65536 65536 65536 65536 65536 65536 65536
65536 65536 65536 65536>; 65536 65536 65536 65536>;
snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; snps,priority = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>; // <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>;
snps,dma-masters = <1>; snps,dma-masters = <1>;
snps,data-width = <4>; snps,data-width = <4>;
snps,axi-max-burst-len = <16>; snps,axi-max-burst-len = <16>;
@@ -1354,8 +1367,7 @@
emmc: sdhci@ffe7080000 { emmc: sdhci@ffe7080000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7080000 0x0 0x10000 reg = <0xff 0xe7080000 0x0 0x10000>;
0xff 0xef014060 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <62>; interrupts = <62>;
interrupt-names = "sdhciirq"; interrupt-names = "sdhciirq";
@@ -1365,8 +1377,7 @@
sdhci0: sd@ffe7090000 { sdhci0: sd@ffe7090000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7090000 0x0 0x10000 reg = <0xff 0xe7090000 0x0 0x10000>;
0xff 0xef014064 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <64>; interrupts = <64>;
interrupt-names = "sdhci0irq"; interrupt-names = "sdhci0irq";
@@ -1376,8 +1387,7 @@
sdhci1: sd@ffe70a0000 { sdhci1: sd@ffe70a0000 {
compatible = "snps,dwcmshc-sdhci"; compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe70a0000 0x0 0x10000 reg = <0xff 0xe70a0000 0x0 0x10000>;
0xff 0xef014064 0x0 0x4>;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
interrupts = <71>; interrupts = <71>;
interrupt-names = "sdhci1irq"; interrupt-names = "sdhci1irq";
@@ -1573,6 +1583,174 @@
status = "disabled"; status = "disabled";
}; };
tdm_slot1: audio_tdm_slot1@0xffcb012000 {
#sound-dai-cells = <1>;
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 = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot2: audio_tdm_slot2@0xffcb012000 {
#sound-dai-cells = <1>;
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 = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot3: audio_tdm_slot3@0xffcb012000 {
#sound-dai-cells = <1>;
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 = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot4: audio_tdm_slot4@0xffcb012000 {
#sound-dai-cells = <1>;
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 = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot5: audio_tdm_slot5@0xffcb012000 {
#sound-dai-cells = <1>;
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 = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot6: audio_tdm_slot6@0xffcb012000 {
#sound-dai-cells = <1>;
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 = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot7: audio_tdm_slot7@0xffcb012000 {
#sound-dai-cells = <1>;
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 = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
tdm_slot8: audio_tdm_slot8@0xffcb012000 {
#sound-dai-cells = <1>;
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 = <&dummy_clock_apb>;
clock-names = "pclk";
status = "disabled";
};
pvt: pvt@fffff4e000 { pvt: pvt@fffff4e000 {
compatible = "moortec,mr75203"; compatible = "moortec,mr75203";
reg = <0xff 0xfff4e000 0x0 0x80>, reg = <0xff 0xfff4e000 0x0 0x80>,
@@ -2154,6 +2332,12 @@
interrupts = <215>; /* TEE INT SRC_7 */ interrupts = <215>; /* TEE INT SRC_7 */
}; };
light_event: light-event {
compatible = "thead,light-event";
aon-iram-regmap = <&aon_iram>;
status = "okay";
};
visys_clk_gate: visys-clk-gate { /* VI_SYSREG_R */ visys_clk_gate: visys-clk-gate { /* VI_SYSREG_R */
compatible = "thead,visys-gate-controller"; compatible = "thead,visys-gate-controller";
visys-regmap = <&visys_reg>; visys-regmap = <&visys_reg>;

View File

@@ -3,6 +3,10 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y CONFIG_PREEMPT=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y CONFIG_CGROUPS=y
@@ -20,6 +24,7 @@ CONFIG_SOC_THEAD=y
CONFIG_SMP=y CONFIG_SMP=y
CONFIG_VECTOR=y CONFIG_VECTOR=y
CONFIG_VECTOR_0_7=y CONFIG_VECTOR_0_7=y
CONFIG_THEAD_ISA=y
CONFIG_KEXEC=y CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y CONFIG_CRASH_DUMP=y
CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE=y
@@ -91,6 +96,7 @@ CONFIG_TUN=y
CONFIG_VIRTIO_NET=y CONFIG_VIRTIO_NET=y
CONFIG_MACB=y CONFIG_MACB=y
CONFIG_STMMAC_ETH=y CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_RX_ZERO_COPY=y
CONFIG_DWMAC_LIGHT=y CONFIG_DWMAC_LIGHT=y
CONFIG_MICROSEMI_PHY=y CONFIG_MICROSEMI_PHY=y
CONFIG_REALTEK_PHY=y CONFIG_REALTEK_PHY=y
@@ -265,6 +271,7 @@ CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_LIGHT=y CONFIG_HWSPINLOCK_LIGHT=y
CONFIG_HWSPINLOCK_LIGHT_TEST=m CONFIG_HWSPINLOCK_LIGHT_TEST=m
CONFIG_MAILBOX=y CONFIG_MAILBOX=y
CONFIG_EXTCON=y
CONFIG_IIO=y CONFIG_IIO=y
CONFIG_IIO_SW_DEVICE=y CONFIG_IIO_SW_DEVICE=y
CONFIG_PWM=y CONFIG_PWM=y
@@ -298,13 +305,21 @@ CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_DH=y CONFIG_CRYPTO_DH=y
CONFIG_CRYPTO_CURVE25519=y CONFIG_CRYPTO_CURVE25519=y
CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CRYPTO_CHACHA20POLY1305=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_OFB=y CONFIG_CRYPTO_OFB=y
CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA512=y CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SHA3=y CONFIG_CRYPTO_SHA3=y
CONFIG_CRYPTO_SM3=y CONFIG_CRYPTO_SM3=y
CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_SM4=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_DMA_CMA=y CONFIG_DMA_CMA=y
CONFIG_DMA_PERNUMA_CMA=y CONFIG_DMA_PERNUMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32 CONFIG_CMA_SIZE_MBYTES=32
@@ -320,6 +335,7 @@ CONFIG_OVERLAY_FS=y
CONFIG_LOCKUP_DETECTOR=y CONFIG_LOCKUP_DETECTOR=y
CONFIG_SOFTLOCKUP_DETECTOR=y CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
CONFIG_SCHED_INFO=y
CONFIG_PM=y CONFIG_PM=y
# CONFIG_SUSPEND is not set # CONFIG_SUSPEND is not set
# CONFIG_PM_SLEEP is not set # CONFIG_PM_SLEEP is not set

View File

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

View File

@@ -28,7 +28,6 @@
struct dwcmshc_priv { struct dwcmshc_priv {
struct clk *bus_clk; struct clk *bus_clk;
void __iomem *soc_base;
bool is_emmc_card; bool is_emmc_card;
bool pull_up_en; bool pull_up_en;
bool io_fixed_1v8; bool io_fixed_1v8;
@@ -289,12 +288,6 @@ static void snps_sdhci_reset(struct sdhci_host *host, u8 mask)
pltfm_host = sdhci_priv(host); pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host); priv = sdhci_pltfm_priv(pltfm_host);
/*soc reset, fix host reset error*/
//soc_reg = readl( priv->soc_base);
//soc_reg &= ~1;
//writel(soc_reg, priv->soc_base);
//soc_reg |= 1;
//writel(soc_reg, priv->soc_base);
/*host reset*/ /*host reset*/
sdhci_reset(host, mask); sdhci_reset(host, mask);
@@ -604,9 +597,6 @@ static int dwcmshc_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host); pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host); priv = sdhci_pltfm_priv(pltfm_host);
/*used fix sdhci reset error*/
priv->soc_base = devm_platform_ioremap_resource(pdev, 1);
if (device_property_present(&pdev->dev, "is_emmc")) { if (device_property_present(&pdev->dev, "is_emmc")) {
priv->is_emmc_card = 1; priv->is_emmc_card = 1;
} else { } else {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -69,5 +69,19 @@
#define ES7210_MIC4_LP_REG4A 0x4A #define ES7210_MIC4_LP_REG4A 0x4A
#define ES7210_MIC12_PDN_REG4B 0x4B #define ES7210_MIC12_PDN_REG4B 0x4B
#define ES7210_MIC34_PDN_REG4C 0x4C #define ES7210_MIC34_PDN_REG4C 0x4C
/* codec private data */
struct es7210_priv {
struct regmap *regmap;
struct i2c_client *i2c_client;
unsigned int dmic_enable;
unsigned int sysclk;
struct clk *mclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
unsigned int tdm_mode;
struct delayed_work pcm_pop_work;
int mclk_lrck_ratio;
int pcm_format;
};
#endif /* _ES7210_H_ */ #endif /* _ES7210_H_ */

View File

@@ -36,6 +36,7 @@
#define GPIO_LOW 0 #define GPIO_LOW 0
#define GPIO_HIGH 1 #define GPIO_HIGH 1
#define es8156_DEF_VOL 0xBF #define es8156_DEF_VOL 0xBF
#define ES8156_VOL_MAX 0xBF
/* /*
* If your system doesn't have MCLK, define this to 0 or the * If your system doesn't have MCLK, define this to 0 or the
* driver will crash. * driver will crash.
@@ -115,7 +116,7 @@ static const struct snd_kcontrol_new es8156_snd_controls[] = {
4,0,15,0), 4,0,15,0),
/* DAC Digital controls */ /* DAC Digital controls */
SOC_SINGLE_TLV("DAC Playback Volume", ES8156_VOLUME_CONTROL_REG14, SOC_SINGLE_TLV("DAC Playback Volume", ES8156_VOLUME_CONTROL_REG14,
0, 0xff, 0, dac_vol_tlv), 0, ES8156_VOL_MAX, 0, dac_vol_tlv),
SOC_SINGLE("HP Switch",ES8156_ANALOG_SYS3_REG22,3,1,0), SOC_SINGLE("HP Switch",ES8156_ANALOG_SYS3_REG22,3,1,0),
@@ -123,7 +124,7 @@ static const struct snd_kcontrol_new es8156_snd_controls[] = {
static const struct snd_soc_dapm_widget es8156_dapm_widgets[] = { static const struct snd_soc_dapm_widget es8156_dapm_widgets[] = {
SND_SOC_DAPM_AIF_OUT("SDOUT", "I2S Capture", 0, SND_SOC_DAPM_AIF_OUT("AIFSDOUT", "I2S Capture", 0,
ES8156_P2S_CONTROL_REG0D, 2, 0), ES8156_P2S_CONTROL_REG0D, 2, 0),
SND_SOC_DAPM_AIF_IN("SDIN", "I2S Playback", 0, SND_SOC_DAPM_AIF_IN("SDIN", "I2S Playback", 0,
@@ -279,7 +280,7 @@ static int es8156_set_bias_level(struct snd_soc_component *codec,
snd_soc_component_write(codec, ES8156_ANALOG_SYS4_REG23,0x00); snd_soc_component_write(codec, ES8156_ANALOG_SYS4_REG23,0x00);
snd_soc_component_write(codec, ES8156_TIME_CONTROL1_REG0A,0x01); snd_soc_component_write(codec, ES8156_TIME_CONTROL1_REG0A,0x01);
snd_soc_component_write(codec, ES8156_TIME_CONTROL2_REG0B,0x01); snd_soc_component_write(codec, ES8156_TIME_CONTROL2_REG0B,0x01);
snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14,0xBF); //snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14,0xBF);
snd_soc_component_write(codec, ES8156_MAINCLOCK_CTL_REG01,0x21); snd_soc_component_write(codec, ES8156_MAINCLOCK_CTL_REG01,0x21);
snd_soc_component_write(codec, ES8156_P2S_CONTROL_REG0D,0x14); snd_soc_component_write(codec, ES8156_P2S_CONTROL_REG0D,0x14);
snd_soc_component_write(codec, ES8156_MISC_CONTROL3_REG18,0x00); snd_soc_component_write(codec, ES8156_MISC_CONTROL3_REG18,0x00);
@@ -299,7 +300,7 @@ static int es8156_set_bias_level(struct snd_soc_component *codec,
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14, 0x00); //snd_soc_component_write(codec, ES8156_VOLUME_CONTROL_REG14, 0x00);
snd_soc_component_write(codec, ES8156_EQ_CONTROL1_REG19, 0x02); snd_soc_component_write(codec, ES8156_EQ_CONTROL1_REG19, 0x02);
snd_soc_component_write(codec, ES8156_ANALOG_SYS2_REG21, 0x1F); snd_soc_component_write(codec, ES8156_ANALOG_SYS2_REG21, 0x1F);
snd_soc_component_write(codec, ES8156_ANALOG_SYS3_REG22, 0x02); snd_soc_component_write(codec, ES8156_ANALOG_SYS3_REG22, 0x02);
@@ -489,6 +490,7 @@ const struct regmap_config es8156_regmap_config = {
}; };
static struct snd_soc_component_driver soc_codec_dev_es8156 = { static struct snd_soc_component_driver soc_codec_dev_es8156 = {
.name = "es8156",
.probe = es8156_probe, .probe = es8156_probe,
.remove = es8156_remove, .remove = es8156_remove,
.suspend = es8156_suspend, .suspend = es8156_suspend,

View File

@@ -145,16 +145,19 @@ EXPORT_SYMBOL_GPL(asoc_simple_parse_card_name);
static int asoc_simple_clk_enable(struct asoc_simple_dai *dai) static int asoc_simple_clk_enable(struct asoc_simple_dai *dai)
{ {
if (dai) if (dai) {
return clk_prepare_enable(dai->clk); if (!IS_ERR_OR_NULL(dai->clk))
return clk_prepare_enable(dai->clk);
}
return 0; return 0;
} }
static void asoc_simple_clk_disable(struct asoc_simple_dai *dai) static void asoc_simple_clk_disable(struct asoc_simple_dai *dai)
{ {
if (dai) if (dai) {
clk_disable_unprepare(dai->clk); if (!IS_ERR_OR_NULL(dai->clk))
clk_disable_unprepare(dai->clk);
}
} }
int asoc_simple_parse_clk(struct device *dev, int asoc_simple_parse_clk(struct device *dev,
@@ -182,6 +185,7 @@ int asoc_simple_parse_clk(struct device *dev,
clk = devm_get_clk_from_child(dev, dlc->of_node, NULL); clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
if (!IS_ERR(clk)) if (!IS_ERR(clk))
simple_dai->sysclk = clk_get_rate(clk); simple_dai->sysclk = clk_get_rate(clk);
simple_dai->clk = NULL; // avoid invalid clk pointer like 0x00000000d
} }
if (of_property_read_bool(node, "system-clock-direction-out")) if (of_property_read_bool(node, "system-clock-direction-out"))
@@ -242,7 +246,11 @@ static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai,
if (clk_get_rate(simple_dai->clk) == rate) if (clk_get_rate(simple_dai->clk) == rate)
return 0; return 0;
return clk_set_rate(simple_dai->clk, rate); if (!IS_ERR_OR_NULL(simple_dai->clk)) {
return clk_set_rate(simple_dai->clk, rate);
} else {
return 0;
}
} }
int asoc_simple_hw_params(struct snd_pcm_substream *substream, int asoc_simple_hw_params(struct snd_pcm_substream *substream,

View File

@@ -1,5 +1,7 @@
# CPU DAI drivers # CPU DAI drivers
obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-i2s.o obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-i2s.o
obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-tdm.o
obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-pcm-dma.o obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-pcm-dma.o
obj-$(CONFIG_SND_SOC_THEAD_LIGHT) += light-dummy-pcm.o
obj-$(CONFIG_SND_SOC_AW87519) += aw87519_audio.o obj-$(CONFIG_SND_SOC_AW87519) += aw87519_audio.o

View File

@@ -35,6 +35,9 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/hrtimer.h> #include <linux/hrtimer.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include <linux/regmap.h>
#include "aw87519_audio.h" #include "aw87519_audio.h"
/******************************************************************************* /*******************************************************************************
@@ -140,7 +143,6 @@ unsigned char aw87519_audio_receiver(void)
unsigned int i; unsigned int i;
unsigned int length; unsigned int length;
pr_info("%s enter\n", __func__);
if (aw87519 == NULL) if (aw87519 == NULL)
return 2; return 2;
@@ -169,8 +171,6 @@ unsigned char aw87519_audio_speaker(void)
unsigned int i; unsigned int i;
unsigned int length; unsigned int length;
pr_info("%s enter\n", __func__);
if (aw87519 == NULL) if (aw87519 == NULL)
return 2; return 2;
@@ -577,6 +577,79 @@ retry:
return -EINVAL; return -EINVAL;
} }
static const DECLARE_TLV_DB_RANGE(aw87519_tlv,
8, 12, TLV_DB_SCALE_ITEM(1200,150, 0)
);
static const struct snd_kcontrol_new aw87519_controls[] = {
SOC_SINGLE_TLV("Speaker Playback Volume", REG_PAGR, 0, 12, 0, aw87519_tlv),
};
static int aw87519_component_probe(struct snd_soc_component* component)
{
struct aw87519 *pa = snd_soc_component_get_drvdata(component);
return 0; // snd_soc_add_component_controls(component, aw87519_controls, ARRAY_SIZE(aw87519_controls));
}
static int aw87519_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kctrl, int event)
{
struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
struct aw87519 *pa = snd_soc_component_get_drvdata(c);
if (SND_SOC_DAPM_EVENT_ON(event)) {
/* Before widget power up: turn chip on, sync registers */
aw87519_audio_speaker();
} else {
/* After widget power down: turn chip off */
aw87519_audio_off();
}
return 0;
}
static const struct snd_soc_dapm_widget aw87519_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("IN"),
SND_SOC_DAPM_OUTPUT("VO"),
SND_SOC_DAPM_PGA("PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Power", SND_SOC_NOPM, 0, 0,
aw87519_power_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_route aw87519_dapm_routes[] = {
{ "PGA", NULL, "IN"},
{ "VO", NULL, "PGA"},
{ "PGA", NULL, "Power"},
};
static const struct reg_default aw87519_reg_defaults[] = {
{0x69, 0x80}, {0x69, 0xB7}, {0x01, 0xF0}, {0x02, 0x09},
{0x03, 0xE8}, {0x04, 0x11}, {0x05, 0x10}, {0x06, 0x43},
{0x07, 0x4E}, {0x08, 0x03}, {0x09, 0x08}, {0x0A, 0x4A},
{0x60, 0x16}, {0x61, 0x20}, {0x62, 0x01}, {0x63, 0x0B},
{0x64, 0xC5}, {0x65, 0xA4}, {0x66, 0x78}, {0x67, 0xC4},
{0x68, 0XD0},
};
const struct regmap_config aw87519_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xff,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = aw87519_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(aw87519_reg_defaults),
};
static const struct snd_soc_component_driver aw87519_component_driver = {
.name = "aw87519",
.probe = aw87519_component_probe,
.dapm_widgets = aw87519_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(aw87519_dapm_widgets),
.dapm_routes = aw87519_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(aw87519_dapm_routes),
};
/******************************************************************************* /*******************************************************************************
* aw87519 i2c driver * aw87519 i2c driver
******************************************************************************/ ******************************************************************************/
@@ -599,6 +672,13 @@ static int aw87519_i2c_probe(struct i2c_client *client,
goto exit_devm_kzalloc_failed; goto exit_devm_kzalloc_failed;
} }
aw87519->regmap = devm_regmap_init_i2c(client, &aw87519_regmap_config);
if (IS_ERR(aw87519->regmap)) {
ret = PTR_ERR(aw87519->regmap);
dev_err(&client->dev, "Failed to init regmap: %d\n", ret);
return ret;
}
aw87519->i2c_client = client; aw87519->i2c_client = client;
i2c_set_clientdata(client, aw87519); i2c_set_clientdata(client, aw87519);
@@ -650,7 +730,7 @@ static int aw87519_i2c_probe(struct i2c_client *client,
/* aw87519 hardware off */ /* aw87519 hardware off */
aw87519_hw_off(aw87519); aw87519_hw_off(aw87519);
return 0; return devm_snd_soc_register_component(&client->dev, &aw87519_component_driver, NULL, 0);
exit_i2c_check_id_failed: exit_i2c_check_id_failed:
exit_gpio_request_failed: exit_gpio_request_failed:
@@ -711,7 +791,7 @@ static void __exit aw87519_pa_exit(void)
i2c_del_driver(&aw87519_i2c_driver); i2c_del_driver(&aw87519_i2c_driver);
} }
late_initcall(aw87519_pa_init); module_init(aw87519_pa_init);
module_exit(aw87519_pa_exit); module_exit(aw87519_pa_exit);
MODULE_DESCRIPTION("AWINIC AW87519 PA driver"); MODULE_DESCRIPTION("AWINIC AW87519 PA driver");

View File

@@ -72,6 +72,9 @@ unsigned char aw87519_rcv_cfg_default[] = {
#define REG_PAGC2PR 0x09 #define REG_PAGC2PR 0x09
#define REG_PAGC1PR 0x0A #define REG_PAGC1PR 0x0A
#define AW87519_EN_SW_SHIFT 7
#define AW87519_EN_PA_SHIFT 4
#define AW87519_CHIPID 0x59 #define AW87519_CHIPID 0x59
#define AW87519_REG_MAX 11 #define AW87519_REG_MAX 11
@@ -90,6 +93,7 @@ struct aw87519 {
struct mutex cfg_lock; struct mutex cfg_lock;
struct work_struct cfg_work; struct work_struct cfg_work;
struct delayed_work ram_work; struct delayed_work ram_work;
struct regmap *regmap;
}; };
/******************************************************************************* /*******************************************************************************

View File

@@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for ASoC dummy pcm dai
* Copyright 2023 Yan Dong <nanli.yd@alibaba-inc.com>
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/soc.h>
static const struct snd_soc_dapm_widget light_dummy_pcm_widgets[] = {
SND_SOC_DAPM_INPUT("RX"),
SND_SOC_DAPM_OUTPUT("TX"),
};
static const struct snd_soc_dapm_route light_dummy_pcm_routes[] = {
{ "Capture", NULL, "RX" },
{ "TX", NULL, "Playback" },
};
static struct snd_soc_dai_driver light_dummy_pcm_dai[] = {
{
.name = "dummy-pcm",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
},
};
static const struct snd_soc_component_driver soc_component_dev_light_dummy_pcm = {
.dapm_widgets = light_dummy_pcm_widgets,
.num_dapm_widgets = ARRAY_SIZE(light_dummy_pcm_widgets),
.dapm_routes = light_dummy_pcm_routes,
.num_dapm_routes = ARRAY_SIZE(light_dummy_pcm_routes),
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static int light_dummy_pcm_probe(struct platform_device *pdev)
{
return devm_snd_soc_register_component(&pdev->dev,
&soc_component_dev_light_dummy_pcm,
light_dummy_pcm_dai, ARRAY_SIZE(light_dummy_pcm_dai));
}
static int light_dummy_pcm_remove(struct platform_device *pdev)
{
return 0;
}
static const struct platform_device_id light_dummy_pcm_driver_ids[] = {
{
.name = "light-dummy-pcm",
},
{},
};
MODULE_DEVICE_TABLE(platform, light_dummy_pcm_driver_ids);
#if defined(CONFIG_OF)
static const struct of_device_id light_dummy_pcm_codec_of_match[] = {
{ .compatible = "thead,light-dummy-pcm", },
{},
};
MODULE_DEVICE_TABLE(of, light_dummy_pcm_codec_of_match);
#endif
static struct platform_driver light_dummy_pcm_driver = {
.driver = {
.name = "light-dummy-pcm",
.of_match_table = of_match_ptr(light_dummy_pcm_codec_of_match),
},
.probe = light_dummy_pcm_probe,
.remove = light_dummy_pcm_remove,
.id_table = light_dummy_pcm_driver_ids,
};
module_platform_driver(light_dummy_pcm_driver);
MODULE_AUTHOR("Yan Dong <nanli.yd@alibaba-inc.com>");
MODULE_DESCRIPTION("ASoC dummy pcm dai driver");
MODULE_LICENSE("GPL");

View File

@@ -122,27 +122,11 @@ static inline void light_snd_txctrl(struct light_i2s_priv *chip, bool on)
} else { } else {
dma_en &= ~DMACR_TDMAE_EN; dma_en &= ~DMACR_TDMAE_EN;
i2s_en &= ~IISEN_I2SEN; i2s_en &= ~IISEN_I2SEN;
i2s_status = readl(chip->regs + I2S_SR);
while ((i2s_status & SR_TXBUSY_STATUS) || !(i2s_status & SR_TFNF_TX_FIFO_NOT_FULL)) {
i2s_status = readl(chip->regs + I2S_SR);
}
i2s_imr = readl(chip->regs + I2S_IMR); i2s_imr = readl(chip->regs + I2S_IMR);
i2s_imr &= ~(IMR_TXUIRM_INTR_MSK); i2s_imr &= ~(IMR_TXUIRM_INTR_MSK);
i2s_imr &= ~(IMR_TXEIM_INTR_MSK); i2s_imr &= ~(IMR_TXEIM_INTR_MSK);
writel(i2s_imr, chip->regs + I2S_IMR); writel(i2s_imr, chip->regs + I2S_IMR);
i2s_imr = readl(chip->regs + I2S_IMR);
writel(dma_en, chip->regs + I2S_DMACR); writel(dma_en, chip->regs + I2S_DMACR);
i2s_status = readl(chip->regs + I2S_SR);
while ((i2s_status & SR_TXBUSY_STATUS) || !(i2s_status & SR_TFE_TX_FIFO_EMPTY)) {
i2s_status = readl(chip->regs + I2S_SR);
}
mdelay(10);
writel(i2s_en, chip->regs + I2S_IISEN); writel(i2s_en, chip->regs + I2S_IISEN);
} }
} }
@@ -205,14 +189,15 @@ static int light_i2s_dai_trigger(struct snd_pcm_substream *substream, int cmd,
light_snd_rxctrl(i2s_private, 1); light_snd_rxctrl(i2s_private, 1);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (tx) if (tx) {
dmaengine_terminate_async(snd_dmaengine_pcm_get_chan(substream)); // work around for DMAC stop issue
light_snd_txctrl(i2s_private, 0); light_snd_txctrl(i2s_private, 0);
break; }
break;
default: default:
return -EINVAL; return -EINVAL;
} }

629
sound/soc/thead/light-tdm.c Normal file
View File

@@ -0,0 +1,629 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2021 Alibaba Group Holding Limited.
*/
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/scatterlist.h>
#include <linux/sh_dma.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <sound/sh_fsi.h>
#include "light-pcm.h"
#include "light-tdm.h"
#include <linux/dmaengine.h>
#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/initval.h>
#include <sound/dmaengine_pcm.h>
#include <linux/mfd/syscon.h>
#include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h>
#define LIGHT_RATES SNDRV_PCM_RATE_8000_384000
#define LIGHT_FMTS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8)
static int light_tdm_dai_probe(struct snd_soc_dai *dai)
{
struct light_tdm_priv *tdm = snd_soc_dai_get_drvdata(dai);
if (tdm) {
snd_soc_dai_init_dma_data(dai, NULL, &tdm->dma_params_rx);
} else {
return -EIO;
}
return 0;
}
static int light_tdm_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
return 0;
}
static void light_tdm_snd_rxctrl(struct light_tdm_priv *priv, char on)
{
if (priv->slot_num != 1) {
return;
}
regmap_update_bits(priv->regmap, TDM_DMACTL,
DMACTL_DMAEN_MSK, DMACTL_DMAEN_SEL(on));
regmap_update_bits(priv->regmap, TDM_TDMEN,
TDMCTL_TDMEN_MSK, TDMCTL_TDMEN_SEL(on));
u32 dmactl;
u32 tdmen;
regmap_read(priv->regmap, TDM_DMACTL, &dmactl);
regmap_read(priv->regmap, TDM_TDMEN, &tdmen);
//printk("%s TDM_DMACTL=0x%x TDM_TDMEN=0x%x\n", __func__, dmactl, tdmen);
return;
}
static void light_tdm_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
light_tdm_snd_rxctrl(priv, 0);
clk_disable_unprepare(priv->clk);
}
static int light_tdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{
int ret = 0;
struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai);
switch(cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
light_tdm_snd_rxctrl(priv, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
light_tdm_snd_rxctrl(priv, 0);
break;
default:
return -EINVAL;
}
return ret;
}
static int light_tdm_set_fmt_dai(struct snd_soc_dai *dai, unsigned int fmt)
{
struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai);
u32 cnfin = 0;
if (priv->slot_num != 1) {
return 0;
}
printk("%s fmt=%d\n", __func__, fmt);
switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_DSP_B:
break;
default:
pr_err("Unknown fmt dai\n");
return -EIO;
}
regmap_update_bits(priv->regmap, TDM_TDMCTL,
TDMCTL_MODE_MSK,
TDMCTL_MODE_SEL(TDM_MODE_MASTER));
regmap_update_bits(priv->regmap, TDM_TDMCTL,
TDMCTL_SPEDGE_MSK,
TDMCTL_SPEDGE_SEL(1));
regmap_update_bits(priv->regmap, TDM_DMADL,
DMACTL_DMADL_MSK, DMACTL_DMADL_SEL(0));
u32 tdmctl;
u32 dmadl;
regmap_read(priv->regmap, TDM_TDMCTL, &tdmctl);
regmap_read(priv->regmap, TDM_DMADL, &dmadl);
printk("%s TDM_TDMCTL=0x%x TDM_DMADL=0x%x\n", __func__, tdmctl, dmadl);
printk("%s %d\n", __func__, __LINE__);
return 0;
}
static u32 light_special_sample_rates[] = { 11025, 22050, 44100, 88200 };
#define AUDIO_DIVCLK0 49152000
#define AUDIO_DIVCLK1 135475200
static void light_tdm_set_div(struct light_tdm_priv *priv, struct snd_pcm_hw_params *params)
{
bool is_divclk1 = false; //audio_divclk1 for 44.1k...etc. audio_divclk0 for 48k....etc
u32 src_clk;
u32 div0, i, width;
u32 sample_rate = params_rate(params);
switch(params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
width = 16;
break;
case SNDRV_PCM_FORMAT_S24_LE:
width = 24;
break;
case SNDRV_PCM_FORMAT_S32_LE:
width = 32;
break;
default:
pr_err("Unknown data format\n");
return;
}
for (i = 0; i < ARRAY_SIZE(light_special_sample_rates); i++) {
if (light_special_sample_rates[i] == sample_rate) {
is_divclk1 = true;
break;
}
}
if (is_divclk1 == false) { // audio_divclk0=49152000 for 48k
regmap_update_bits(priv->audio_cpr_regmap,
CPR_PERI_CLK_SEL_REG, CPR_TDM_SRC_SEL_MSK, CPR_TDM_SRC_SEL(0));
src_clk = AUDIO_DIVCLK0;
} else { // audio_divclk1=135475200 for 44.1k
regmap_update_bits(priv->audio_cpr_regmap,
CPR_PERI_CLK_SEL_REG, CPR_TDM_SRC_SEL_MSK, CPR_TDM_SRC_SEL(2));
src_clk = AUDIO_DIVCLK1;
}
div0 = src_clk / (sample_rate * (width * priv->slots));
regmap_update_bits(priv->regmap, TDM_DIV0_LEVEL,
TDMCTL_DIV0_MASK, div0);
//printk("src_clk=%d sample_rate=%d priv->slots=%d width=%d div0=%d\n", src_clk, sample_rate, priv->slots, width, div0);
}
static int light_tdm_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct light_tdm_priv *priv = snd_soc_dai_get_drvdata(dai);
u32 datawth, chn_num;
if ( params_channels(params) != 1) {
pr_err("Not support channel num\n");
return -EINVAL;
}
if (priv->slot_num != 1) {
return 0;
}
switch(params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
datawth = TDMCTL_DATAWTH_16BIT_PACKED; // TDMCTL_DATAWTH_16BIT
break;
case SNDRV_PCM_FORMAT_S24_LE:
datawth = TDMCTL_DATAWTH_24BIT;
break;
case SNDRV_PCM_FORMAT_S32_LE:
datawth = TDMCTL_DATAWTH_32BIT;
break;
default:
pr_err("Unknown data format\n");
return -EINVAL;
}
switch(priv->slots) {
case 2:
chn_num = TDMCTL_CHNUM_2;
break;
case 4:
chn_num = TDMCTL_CHNUM_4;
break;
case 6:
chn_num = TDMCTL_CHNUM_6;
break;
case 8:
chn_num = TDMCTL_CHNUM_8;
break;
default:
pr_err("Not support slot num\n");
return -EINVAL;
}
regmap_update_bits(priv->regmap, TDM_TDMCTL,
TDMCTL_DATAWTH_MSK, TDMCTL_DATAWTH_SEL(datawth));
regmap_update_bits(priv->regmap, TDM_TDMCTL,
TDMCTL_CHNUM_MSK, TDMCTL_CHNUM_SEL(chn_num));
u32 tdmctl;
regmap_read(priv->regmap, TDM_TDMCTL, &tdmctl);
//printk("%s TDM_TDMCTL=0x%x\n", __func__, tdmctl);
light_tdm_set_div(priv, params);
return 0;
}
static const struct snd_soc_dai_ops light_tdm_dai_ops = {
.startup = light_tdm_dai_startup,
.shutdown = light_tdm_dai_shutdown,
.trigger = light_tdm_dai_trigger,
.set_fmt = light_tdm_set_fmt_dai,
.hw_params = light_tdm_dai_hw_params,
};
static struct snd_soc_dai_driver light_tdm_soc_dai[] = {
{
.probe = light_tdm_dai_probe,
.name = "light-tdm-dai-slot1",
.capture = {
.rates = LIGHT_RATES,
.formats = LIGHT_FMTS,
.channels_min = 1,
.channels_max = 1,
},
.ops = &light_tdm_dai_ops,
},
{
.probe = light_tdm_dai_probe,
.name = "light-tdm-dai-slot2",
.capture = {
.rates = LIGHT_RATES,
.formats = LIGHT_FMTS,
.channels_min = 1,
.channels_max = 1,
},
.ops = &light_tdm_dai_ops,
},
{
.probe = light_tdm_dai_probe,
.name = "light-tdm-dai-slot3",
.capture = {
.rates = LIGHT_RATES,
.formats = LIGHT_FMTS,
.channels_min = 1,
.channels_max = 1,
},
.ops = &light_tdm_dai_ops,
},
{
.probe = light_tdm_dai_probe,
.name = "light-tdm-dai-slot4",
.capture = {
.rates = LIGHT_RATES,
.formats = LIGHT_FMTS,
.channels_min = 1,
.channels_max = 1,
},
.ops = &light_tdm_dai_ops,
},
{
.probe = light_tdm_dai_probe,
.name = "light-tdm-dai-slot5",
.capture = {
.rates = LIGHT_RATES,
.formats = LIGHT_FMTS,
.channels_min = 1,
.channels_max = 1,
},
.ops = &light_tdm_dai_ops,
},
{
.probe = light_tdm_dai_probe,
.name = "light-tdm-dai-slot6",
.capture = {
.rates = LIGHT_RATES,
.formats = LIGHT_FMTS,
.channels_min = 1,
.channels_max = 1,
},
.ops = &light_tdm_dai_ops,
},
{
.probe = light_tdm_dai_probe,
.name = "light-tdm-dai-slot7",
.capture = {
.rates = LIGHT_RATES,
.formats = LIGHT_FMTS,
.channels_min = 1,
.channels_max = 1,
},
.ops = &light_tdm_dai_ops,
},
{
.probe = light_tdm_dai_probe,
.name = "light-tdm-dai-slot8",
.capture = {
.rates = LIGHT_RATES,
.formats = LIGHT_FMTS,
.channels_min = 1,
.channels_max = 1,
},
.ops = &light_tdm_dai_ops,
},
};
static const struct snd_soc_component_driver light_tdm_soc_component = {
.name = "light_tdm",
};
static void light_tdm_pinctrl(struct light_tdm_priv *tdm_priv)
{
//GPIO_SEL
regmap_update_bits(tdm_priv->audio_pin_regmap,
0x0,0x38000000, 0x38000000);
//MUX
regmap_update_bits(tdm_priv->audio_pin_regmap,
0x8,0xFC00000, 0x5400000);
//strength
regmap_update_bits(tdm_priv->audio_pin_regmap,
0x44,0x0f, 0x07); // AUDIO_PA28
regmap_update_bits(tdm_priv->audio_pin_regmap,
0x40,0xF0000, 0x70000); // AUDIO_PA27
return;
}
static const struct regmap_config light_tdm_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = TDM_DIV0_LEVEL,
.cache_type = REGCACHE_FLAT,
};
static int light_tdm_runtime_suspend(struct device *dev)
{
struct light_tdm_priv *priv = dev_get_drvdata(dev);
if (priv->slot_num != 1) {
return 0;
}
regcache_cache_only(priv->regmap, true);
clk_disable_unprepare(priv->clk);
return 0;
}
static int light_tdm_runtime_resume(struct device *dev)
{
struct light_tdm_priv *priv = dev_get_drvdata(dev);
int ret;
if (priv->slot_num != 1) {
return 0;
}
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(priv->dev, "clock enable failed %d\n", ret);
return ret;
}
regcache_cache_only(priv->regmap, false);
return ret;
}
static const struct of_device_id light_tdm_of_match[] = {
{ .compatible = "light,light-tdm"},
{},
};
MODULE_DEVICE_TABLE(of, light_tdm_of_match);
irqreturn_t tdm_interrupt(int irq, void* dev_id)
{
struct light_tdm_priv* priv = (struct light_tdm_priv*)dev_id;
return IRQ_HANDLED;
}
static int light_tdm_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
const char *sprop;
const uint32_t *iprop;
struct light_tdm_priv *tdm_priv;
struct resource *res;
struct device *dev = &pdev->dev;
unsigned int irq;
int data_register, ret = 0;
tdm_priv = devm_kzalloc(&pdev->dev, sizeof(struct light_tdm_priv), GFP_KERNEL);
if (!tdm_priv) {
return -ENOMEM;
}
tdm_priv->dev = dev;
sprop = of_get_property(np, "light,mode", NULL);
if (sprop) {
if (!strcmp(sprop, "i2s-master")) {
tdm_priv->mode = TDM_MODE_MASTER;
} else if (!strcmp(sprop, "i2s-slave")) {
tdm_priv->mode = TDM_MODE_SLAVE;
} else {
dev_err(dev, "invalid light,mode\n");
return -EINVAL;
}
}
iprop = of_get_property(np, "light,dma_maxburst", NULL);
if (iprop)
tdm_priv->dma_maxburst = be32_to_cpup(iprop);
else
tdm_priv->dma_maxburst = 8;
iprop = of_get_property(np, "light,tdm_slots", NULL);
if (iprop) {
if (be32_to_cpup(iprop) == 2 || be32_to_cpup(iprop) == 4 || be32_to_cpup(iprop) == 6 || be32_to_cpup(iprop) == 8) {
tdm_priv->slots = be32_to_cpup(iprop);
} else {
dev_err(dev, "invalid light,tdm_slots\n");
return -EINVAL;
}
} else {
tdm_priv->slots = 8;
}
iprop = of_get_property(np, "light,tdm_slot_num", NULL);
if (iprop) {
if (be32_to_cpup(iprop) >=1 && be32_to_cpup(iprop) <=8 ) {
tdm_priv->slot_num = be32_to_cpup(iprop);
} else {
dev_err(dev, "invalid light,tdm_slot_num\n");
return -EINVAL;
}
} else {
dev_err(dev, "invalid light,tdm_slot_num\n");
return -EINVAL;
}
dev_set_drvdata(dev, tdm_priv);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tdm_priv->clk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(tdm_priv->clk))
return PTR_ERR(tdm_priv->clk);
if (tdm_priv->slot_num == 1) {
tdm_priv->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(tdm_priv->regs)) {
return PTR_ERR(tdm_priv->regs);
}
tdm_priv->regmap = devm_regmap_init_mmio(dev, tdm_priv->regs,
&light_tdm_regmap_config);
if (IS_ERR(tdm_priv->regmap)) {
dev_err(dev, "Failed to initialise managed register map\n");
return PTR_ERR(tdm_priv->regmap);
}
tdm_priv->audio_pin_regmap = syscon_regmap_lookup_by_phandle(np, "audio-pin-regmap");
if (IS_ERR(tdm_priv->audio_pin_regmap)) {
dev_err(dev, "cannot find regmap for audio system register\n");
return -EINVAL;
} else {
light_tdm_pinctrl(tdm_priv);
}
tdm_priv->audio_cpr_regmap = syscon_regmap_lookup_by_phandle(np, "audio-cpr-regmap");
if (IS_ERR(tdm_priv->audio_cpr_regmap)) {
dev_err(dev, "cannot find regmap for audio cpr register\n");
return -EINVAL;
}
//AUDIO_DIV1 set to 1/6. 812.8512MHz / 6 = 135.4752MHz
regmap_update_bits(tdm_priv->audio_cpr_regmap,
CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV1_SEL_MSK, CPR_AUDIO_DIV1_SEL(5));
//AUDIO_DIV0 set to 1/6. 294.912MHz / 6 = 49.152MHz
regmap_update_bits(tdm_priv->audio_cpr_regmap,
CPR_PERI_DIV_SEL_REG, CPR_AUDIO_DIV0_SEL_MSK, CPR_AUDIO_DIV0_SEL(5));
//enable clock gate
regmap_update_bits(tdm_priv->audio_cpr_regmap,
CPR_IP_CG_REG, CPR_TDM_CG_SEL_MSK, CPR_TDM_CG_SEL(1));
pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) {
ret = light_tdm_runtime_resume(&pdev->dev);
if (ret) {
pm_runtime_disable(&pdev->dev);
return -EIO;
}
}
ret = clk_prepare_enable(tdm_priv->clk);
if (ret < 0)
return ret;
tdm_priv->irq = platform_get_irq(pdev, 0);
if (tdm_priv->irq== 0) {
dev_err(dev, "could not map IRQ.\n");
return -ENXIO;
}
//ret = request_irq(tdm_priv->irq , tdm_interrupt,
// IRQF_SHARED|IRQF_TRIGGER_RISING, "AUDIO_TDM_IRQ", (char *)tdm_priv);
//if (ret) {
// dev_err(dev, "%s[%d]:request irq error!\n", __func__, __LINE__);
// return ret;
//}
}
switch(tdm_priv->slot_num) {
case 1:
data_register = TDM_LDR1;
break;
case 2:
data_register = TDM_RDR1;
break;
case 3:
data_register = TDM_LDR2;
break;
case 4:
data_register = TDM_RDR2;
break;
case 5:
data_register = TDM_LDR3;
break;
case 6:
data_register = TDM_RDR3;
break;
case 7:
data_register = TDM_LDR4;
break;
case 8:
data_register = TDM_RDR4;
break;
default:
dev_err(dev, "invalid slot_num\n");
return -EINVAL;
}
tdm_priv->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
tdm_priv->dma_params_rx.maxburst = tdm_priv->dma_maxburst;
tdm_priv->dma_params_rx.addr = res->start + data_register;
ret = light_pcm_dma_init(pdev, LIGHT_TDM_DMABUF_SIZE);
if (ret) {
dev_err(dev, "light_pcm_dma_init error\n");
return -EIO;
}
ret = devm_snd_soc_register_component(dev, &light_tdm_soc_component,
light_tdm_soc_dai, ARRAY_SIZE(light_tdm_soc_dai));
if (ret < 0) {
dev_err(&pdev->dev, "cannot snd component register\n");
}
return ret;
}
static int light_tdm_remove(struct platform_device *pdev)
{
struct light_tdm_priv *tdm_priv = dev_get_drvdata(&pdev->dev);
pm_runtime_disable(&pdev->dev);
if (!pm_runtime_status_suspended(&pdev->dev))
light_tdm_runtime_suspend(&pdev->dev);
clk_disable_unprepare(tdm_priv->clk);
return 0;
}
static const struct dev_pm_ops light_tdm_pm_ops = {
SET_RUNTIME_PM_OPS(light_tdm_runtime_suspend, light_tdm_runtime_resume, NULL)
};
static struct platform_driver light_tdm_driver = {
.driver = {
.name = "light-tdm-audio",
.pm = &light_tdm_pm_ops,
.of_match_table = light_tdm_of_match,
},
.probe = light_tdm_probe,
.remove = light_tdm_remove,
};
module_platform_driver(light_tdm_driver);
MODULE_AUTHOR("nanli.yd <nanli.yd@linux.alibaba.com>");
MODULE_DESCRIPTION("Thead Light audio driver");
MODULE_LICENSE("GPL v2");

125
sound/soc/thead/light-tdm.h Normal file
View File

@@ -0,0 +1,125 @@
#ifndef _LIGHT_TDM_H
#define _LIGHT_TDM_H
#include <linux/io.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/scatterlist.h>
#include <linux/sh_dma.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <sound/pcm.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/dmaengine_pcm.h>
#include "light-pcm.h"
#include <linux/spinlock.h>
#define TDM_TDMEN 0x00
#define TDM_TDMCTL 0x04
#define TDM_CHOFFSET1 0x08
#define TDM_CHOFFSET2 0x0c
#define TDM_CHOFFSET3 0x10
#define TDM_CHOFFSET4 0x14
#define TDM_FIFOTL1 0x18
#define TDM_FIFOTL2 0x1C
#define TDM_FIFOTL3 0x20
#define TDM_FIFOTL4 0x24
#define TDM_SR 0x28
#define TDM_IMR 0x2C
#define TDM_ISR 0x30
#define TDM_RISR 0x34
#define TDM_ICR 0x38
#define TDM_DMACTL 0x3C
#define TDM_DMADL 0x40
#define TDM_LDR1 0x44
#define TDM_RDR1 0x48
#define TDM_LDR2 0x4C
#define TDM_RDR2 0x50
#define TDM_LDR3 0x54
#define TDM_RDR3 0x58
#define TDM_LDR4 0x5C
#define TDM_RDR4 0x60
#define TDM_DIV0_LEVEL 0x64
#define CPR_PERI_DIV_SEL_REG 0x004 /*audio sys i2s clock div Register*/
#define CPR_PERI_CLK_SEL_REG 0x008 /*audio sys i2s clock selection Register*/
#define CPR_IP_CG_REG 0x010 /* ip clock gate register */
/* AUDIO SYS DIV SEL REG, offset: 0x4 */
#define CPR_AUDIO_DIV1_SEL_POS (12U)
#define CPR_AUDIO_DIV1_SEL_MSK (0x1FU << CPR_AUDIO_DIV1_SEL_POS)
#define CPR_AUDIO_DIV1_SEL(X) (X << CPR_AUDIO_DIV1_SEL_POS)
#define CPR_AUDIO_DIV0_SEL_POS (4U)
#define CPR_AUDIO_DIV0_SEL_MSK (0x1FU << CPR_AUDIO_DIV0_SEL_POS)
#define CPR_AUDIO_DIV0_SEL(X) (X << CPR_AUDIO_DIV0_SEL_POS)
#define CPR_TDM_CG_SEL_POS (21U)
#define CPR_TDM_CG_SEL_MSK (0x1U << CPR_TDM_CG_SEL_POS)
#define CPR_TDM_CG_SEL(X) (X << CPR_TDM_CG_SEL_POS)
#define CPR_TDM_SRC_SEL_POS (16U)
#define CPR_TDM_SRC_SEL_MSK (0x3U << CPR_TDM_SRC_SEL_POS)
#define CPR_TDM_SRC_SEL(X) (X << CPR_TDM_SRC_SEL_POS)
#define TDM_MODE_MASTER 0x1
#define TDM_MODE_SLAVE 0x0
#define TDMCTL_MODE_POS (0U)
#define TDMCTL_MODE_MSK (0x1U << TDMCTL_MODE_POS)
#define TDMCTL_MODE_SEL(X) (X << TDMCTL_MODE_POS)
#define TDMCTL_DATAWTH_POS (4U)
#define TDMCTL_DATAWTH_MSK (0x3U << TDMCTL_DATAWTH_POS)
#define TDMCTL_DATAWTH_SEL(X) (X << TDMCTL_DATAWTH_POS)
#define TDMCTL_CHNUM_POS (8U)
#define TDMCTL_CHNUM_MSK (0x3U << TDMCTL_CHNUM_POS)
#define TDMCTL_CHNUM_SEL(X) (X << TDMCTL_CHNUM_POS)
#define TDMCTL_CHNUM_2 0x0
#define TDMCTL_CHNUM_4 0x1
#define TDMCTL_CHNUM_6 0x2
#define TDMCTL_CHNUM_8 0x3
#define TDMCTL_SPEDGE_POS (13U)
#define TDMCTL_SPEDGE_MSK (0x1U << TDMCTL_SPEDGE_POS)
#define TDMCTL_SPEDGE_SEL(X) (X << TDMCTL_SPEDGE_POS)
#define TDMCTL_DATAWTH_16BIT_PACKED 0x0
#define TDMCTL_DATAWTH_16BIT 0x1
#define TDMCTL_DATAWTH_24BIT 0x2
#define TDMCTL_DATAWTH_32BIT 0x3
#define TDMCTL_DIV0_MASK 0xFFF
#define DMACTL_DMAEN_POS (0U)
#define DMACTL_DMAEN_MSK (0x1U << DMACTL_DMAEN_POS)
#define DMACTL_DMAEN_SEL(X) (X << DMACTL_DMAEN_POS)
#define DMACTL_DMADL_POS (0U)
#define DMACTL_DMADL_MSK (0x3U << DMACTL_DMADL_POS)
#define DMACTL_DMADL_SEL(X) (X << DMACTL_DMADL_POS)
#define TDMCTL_TDMEN_POS (0U)
#define TDMCTL_TDMEN_MSK (0x1U << TDMCTL_TDMEN_POS)
#define TDMCTL_TDMEN_SEL(X) (X << TDMCTL_TDMEN_POS)
#define LIGHT_TDM_DMABUF_SIZE (64 * 1024)
struct light_tdm_priv {
void __iomem *regs;
struct regmap *regmap;
struct regmap *audio_pin_regmap;
struct regmap *audio_cpr_regmap;
struct clk *clk;
struct snd_dmaengine_dai_dma_data dma_params_rx;
unsigned int dai_fmt;
u32 dma_maxburst;
unsigned int cfg_off;
struct device *dev;
char mode;
char slots;
char slot_num;
unsigned int irq;
};
#endif

View File

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

View File

@@ -24,6 +24,9 @@
#elif defined(__TARGET_ARCH_sparc) #elif defined(__TARGET_ARCH_sparc)
#define bpf_target_sparc #define bpf_target_sparc
#define bpf_target_defined #define bpf_target_defined
#elif defined(__TARGET_ARCH_riscv)
#define bpf_target_riscv
#define bpf_target_defined
#else #else
#undef bpf_target_defined #undef bpf_target_defined
#endif #endif
@@ -44,6 +47,8 @@
#define bpf_target_powerpc #define bpf_target_powerpc
#elif defined(__sparc__) #elif defined(__sparc__)
#define bpf_target_sparc #define bpf_target_sparc
#elif defined(__riscv) && __riscv_xlen == 64
#define bpf_target_riscv
#endif #endif
#endif #endif
@@ -279,6 +284,32 @@ struct pt_regs;
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc) #define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc)
#endif #endif
#elif defined(bpf_target_riscv)
struct pt_regs;
#define PT_REGS_RV const volatile struct user_regs_struct
#define PT_REGS_PARM1(x) (((PT_REGS_RV *)(x))->a0)
#define PT_REGS_PARM2(x) (((PT_REGS_RV *)(x))->a1)
#define PT_REGS_PARM3(x) (((PT_REGS_RV *)(x))->a2)
#define PT_REGS_PARM4(x) (((PT_REGS_RV *)(x))->a3)
#define PT_REGS_PARM5(x) (((PT_REGS_RV *)(x))->a4)
#define PT_REGS_RET(x) (((PT_REGS_RV *)(x))->ra)
#define PT_REGS_FP(x) (((PT_REGS_RV *)(x))->s0)
#define PT_REGS_RC(x) (((PT_REGS_RV *)(x))->a0)
#define PT_REGS_SP(x) (((PT_REGS_RV *)(x))->sp)
#define PT_REGS_IP(x) (((PT_REGS_RV *)(x))->pc)
#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a0)
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a1)
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a2)
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a3)
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a4)
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), ra)
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), s0)
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a0)
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), sp)
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), pc)
#endif #endif
#if defined(bpf_target_powerpc) #if defined(bpf_target_powerpc)

View File

@@ -224,7 +224,7 @@ $(RESOLVE_BTFIDS): $(BPFOBJ) | $(BUILD_DIR)/resolve_btfids \
define get_sys_includes define get_sys_includes
$(shell $(1) -v -E - </dev/null 2>&1 \ $(shell $(1) -v -E - </dev/null 2>&1 \
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \ | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \
$(shell $(1) -dM -E - </dev/null | grep '#define __riscv_xlen ' | sed 's/#define /-D/' | sed 's/ /=/') $(shell $(1) -dM -E - </dev/null | grep '__riscv_xlen ' | awk '{printf("-D__riscv_xlen=%d -D__BITS_PER_LONG=%d", $$3, $$3)}')
endef endef
# Determine target endianness. # Determine target endianness.

View File

@@ -231,7 +231,11 @@ int __on_event(struct bpf_raw_tracepoint_args *ctx)
#ifdef NO_UNROLL #ifdef NO_UNROLL
#pragma clang loop unroll(disable) #pragma clang loop unroll(disable)
#else #else
#ifdef UNROLL_COUNT
#pragma clang loop unroll_count(UNROLL_COUNT)
#else
#pragma clang loop unroll(full) #pragma clang loop unroll(full)
#endif
#endif #endif
/* Unwind python stack */ /* Unwind python stack */
for (int i = 0; i < STACK_MAX_LEN; ++i) { for (int i = 0; i < STACK_MAX_LEN; ++i) {

View File

@@ -1,9 +1,12 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Facebook // Copyright (c) 2019 Facebook
#define STACK_MAX_LEN 600 #define STACK_MAX_LEN 600
/* clang will not unroll the loop 600 times. /* Full unroll of 600 iterations will have total
* Instead it will unroll it to the amount it deemed * program size close to 298k insns and this may
* appropriate, but the loop will still execute 600 times. * cause BPF_JMP insn out of 16-bit integer range.
* Total program size is around 90k insns * So limit the unroll size to 150 so the
* total program size is around 80k insns but
* the loop will still execute 600 times.
*/ */
#define UNROLL_COUNT 150
#include "pyperf.h" #include "pyperf.h"

View File

@@ -100,7 +100,7 @@ struct bpf_test {
enum bpf_prog_type prog_type; enum bpf_prog_type prog_type;
uint8_t flags; uint8_t flags;
void (*fill_helper)(struct bpf_test *self); void (*fill_helper)(struct bpf_test *self);
uint8_t runs; int runs;
#define bpf_testdata_struct_t \ #define bpf_testdata_struct_t \
struct { \ struct { \
uint32_t retval, retval_unpriv; \ uint32_t retval, retval_unpriv; \
@@ -1054,7 +1054,7 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
run_errs = 0; run_errs = 0;
run_successes = 0; run_successes = 0;
if (!alignment_prevented_execution && fd_prog >= 0) { if (!alignment_prevented_execution && fd_prog >= 0 && test->runs >= 0) {
uint32_t expected_val; uint32_t expected_val;
int i; int i;

View File

@@ -239,6 +239,7 @@
.result = ACCEPT, .result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SK_LOOKUP, .prog_type = BPF_PROG_TYPE_SK_LOOKUP,
.expected_attach_type = BPF_SK_LOOKUP, .expected_attach_type = BPF_SK_LOOKUP,
.runs = -1,
}, },
/* invalid 8-byte reads from a 4-byte fields in bpf_sk_lookup */ /* invalid 8-byte reads from a 4-byte fields in bpf_sk_lookup */
{ {